From accdd0ef5ccfc93536d522f8fae344c3ccda8ee6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 28 Oct 2014 15:15:07 +0100 Subject: [PATCH 0001/1390] Fixed issue concerning XLabels crash (issue #176). --- MPChartLib/src/com/github/mikephil/charting/data/ChartData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 2748d9a836..a735abcbdb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -134,7 +134,7 @@ private void calcXValAverageLength() { return; } - float sum = 0f; + float sum = 1f; for (int i = 0; i < mXVals.size(); i++) { sum += mXVals.get(i).length(); From 04a3ed9c7249f8d9cd54d0846c8021626e7a567a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Oct 2014 12:30:18 +0100 Subject: [PATCH 0002/1390] Fixed issue concering LineChart filling (#179). Made changes to the logic of filling and added FillFormatter interface for implementing a custom fill logic. --- ...-2.jar => mpandroidchartlibrary-1-7-3.jar} | Bin 1271973 -> 1275538 bytes .../charting/charts/BarLineChartBase.java | 9 ++- .../mikephil/charting/charts/LineChart.java | 54 +++++++++++++++++- .../charting/utils/FillFormatter.java | 27 +++++++++ 4 files changed, 84 insertions(+), 6 deletions(-) rename MPChartExample/libs/{mpandroidchartlibrary-1-7-2.jar => mpandroidchartlibrary-1-7-3.jar} (83%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-2.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar similarity index 83% rename from MPChartExample/libs/mpandroidchartlibrary-1-7-2.jar rename to MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar index 1892692380dfc980b710638d2800ba8e940170b1..b4084d2187ced5c0e811bd0daed2d262fa773832 100644 GIT binary patch delta 196157 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
R?VdcWO6`e_ar)+D zTS4Auf#Zd`8myW)zM7t~+hcY+YV3izRB_K_7F)zYyDlrfzGJP8eEX7AP3SwavSnCE zIX?Wah0-0)FR9v_daMCdOhpj#IJ@!hkW*WHzgak0$OR-uc1;A9-~u$ zx5m6aR%%U|@o~BAGJU_J0Y+#AvrsN1VQ*Hz5ylg>O9ery zXC(B6SAN|F34o8sWy=V4y5oWlzy~m18;EP#nOM7J(!t_ekqxc!3fWc)qNx+@0PRM? z93#=ekPt#33}WHJFne&Y$0J09eFG~$L{(&`9FX#6d3#sk%#aU%0=&s^X3Yh{zFW6P zrwyojBj`j${gcy?yB$1vB=F^BNQPAm!yJh6hVGt78-(nJ`5Be>?|VeQ1Fs9cegAWM zSf#4i9mN~Ms)b&b;Ir7`@8*OAnI%{J-3%+%LxHXua z(c#P!Fk;9hKf2l-A%MvVas44kC2x$`Kk*yXVc~(lc;i2RRoW0KA1fZYum&vOAu^>I z!uld^KE0!jb3#oG6!d^#_QC&xjvM_3BtOZd-l0AjlUx(Y_;c>~Lw|)4{XsY+$u^-K zBn*h15(u|)QUM=|6GyyZ)mq$qYsEg#F&L#XKu_<|n?Fg677+~DfO3Ir3?dcWg zc+rmO+lukDV?}r%{3mMwTl10UYK&GJR?z@-K{3+FstfcS&X;ZA*a_ys{3?@t|M8y$vCM$9IRu^5gb} z@P^qpbt>y^7HPuL&Df4HQLp(+H(1THBQSX1?LN=^PStW`*fxD+0*O2)NN^@+^N1`XPU#L2yhE$$2JndVc8^^iNF$w6#6r`IxO9-s2v%sqW5Z$U#aKMo zL~y2_S3tn3$A34v#H_3)j$6(kZLnilffU;VhLG;ID%*nCb+Ok-XJm_y@rDizauWe5 zjT8W@_%b{nA`BY%a(H^k3r_f=P9Mt)Kz(K-bWym?y>g^08DXY$` z8N;cv?Kvu{E{PG)aC8*%>cW-8WA=QVI(q5s2;iwCW!00{^;%f8Vf8{1)I+Y11qWRY z)~BDWq}$9PwxEX;v{DS)Zy{}~s%;^E7c9uOvwA`uzO7r}BgE7**#rbgp2aCn2ndn? z;+ovaJLrn)V=Og%NvDtZiThpS>R|SXb$#Q%y}geA`yEvKLA4ecvx4lbbSoe!njCN% z1orEPx)C`DwG-t{5^f+%82^YgVHYfJI3UTvr~Rn6B#EL&*Qb|Ar4|gq~3UnyM zsvLphL|$q!B3q7Bw1;W!l8jy%&bF1ASX_@9QK@N2#;svXbzEYF2G6d8rXxmQjk-X4 z-+Fp7!qrr!uC_OVON!#w3M>GZ@Y4B9pVW4g5B5fzEd}3MmhQ|Ob&R5a{MxVmIRfW- z%fU`%7Sk<4`i$mJ5cuWGU7s1#$Nr^jPQZD7Jv06-&s_%%S)|?K3V@7Pe<4{%^gf`;O4z7@(^XG1W z!fwTyMU~!Xnbs#x9b7qo1Zx+e3+hRCjX0^-R~cF|BJZYGE1*yv8iTr(ZWwJ1_BCbU zTw(2dA%CL9JxU~Efc6zNLqCa~q^GELpe5-Bjo}#}d09>{LBzGN%lvzN3jdjTRpiR~=lq;km zo+_0H`ARt**=L>T0+BS+y)R}_e1W+JstVdJtOG@cDzU)D;K^v|4cD7KvGpWZ?_~ht zkj(s>{=|!$HzA>Uf{y)Al>I=o)gPs-03{a~bU4F4niH2I%E_L^T!cE65$$Y)h6IXugMx_QHTv6S#%pimZY{Xe8l z>(&JdWIQQ@%t!2FjAJd^fhdcr!v<{b-oigTwo|lG;k>nBIma-K3u2oIsI-(*Mj1h_ zKF^0nWeJ(H27`x2VWr5P21f9zD;9n`<6c37ZM;v5#q!Y^P3bU!g&~t5Id|R%zzr2z zpy)eBP72w7f2_hdNvURYuULgcP||MlPAUs}oEua*d=+$t4IS}%?Jk3TJ+ULA^u#H~ z6ql-AA}?K+{*ulzrMYQI9u5v>pH$8{T%qzbZaVxltoY)X1U{Vk2KXw^Fq2so*nqRBj=(q4)7eBHe219pWr^aPD%ZjsMht?)ss;8j&5uyB)X_&yppuNA&$iKs2_8 zJocnaBl=J3@tpB~8uG>B!aN3ob4vx^ofaM=gb#d#4?cvCAx1)H{kS08IKFac|3o>- z#2bBn3-!35n@Cx`jMyNv{d^zai~MMQ9yZ9GP%*Il^7?Y^tFr5h%iINs?+iKn@Gb>^ zWWr5blX-9&PX%5QqUbn&sT9xwYDke#JP;of0=Re)!+1Q~p_=i*8p$tlUi1L%1b7a} za5x?L4EM~81y&ui-RCKu{#I4DD07VH{G^b4cURF)cjVux8Q93QRLoeYNOfzzX7DiT-cN8z>lVced<>({rv z1AAJD?O2g*8l<)(+pbERE61gd4H}L=9=;$)=`w2WuTab9Unq7!!O8xDW}e{ zZW`u+;r7Py;k4PLQ%rQo_e3K|hA7)F=$7{N5)9)4_pEH#Pq=13G9SskXURSB@#L9# z_1tKHWr(o}E?g2YRWhz&@|FL+W77;|y215B+%gtmJec@U*QRc$UB2GlkI}g}m_MnY zeRj}Smx(_*sx*QZH{}g4i<^^w9)^1)?`c8`t8*#vhre?a;z>!SA{LADhXIz;19$=*K#+3gFX*=8VK&&2W{rM*o9?=BG;#^MW9minujy+{W}fZ_9V` zgYB}PWF)(&V-aru<}znWQk>aMPSs*nn%Co%1v1QhP-(28BZn5Cw|9`PWbibdeB#(76^KOfaR3(g|2z9;?(v9U7N}?DEq>;6+8Ud z9N6a%^JfTKRHjVTAse_pG_TpbxTAGYsB&e0-=-3}&4>4wn>d#t zkPAdlvA~FnrYT!Zx z*j9p#j7v>8(wNPJTQ0aamM#8P!)oap#3~n@WrpW2KZ z$nNC!cjKIE_}ox2>LCmym}%eV1^+$DaHejI#v^=(GwV%%sn@vb0pNzg)zDA@p_qpi z^vOr=UQ7k+++x5Z8}1@jZQQV8));`s+1f8TR>3slz&&lB4cvrpKIjnJ zwC_H)(OS~Bm}yS#2^i(2Jz+jQRHN=)Yz6QhO^!<=OT}jYaGn9L4%%l@%lgDjt*nYk z>aE_!V_WEdPdY&VSucq{Z^u)@--^do->0i>meSFO9qPrw?HYcLd3tn2O4&}Y8c!@& z9d;186^;8TPJq54U3%9H45$g(DFgj2%%9$h91tiS!klCD7RGQ@@~<;CpriHGiPd8| z#Fi{Q3PBd)QX^zi==Ku4sutJQp_6c%x_=cKRtp1v6(JqFrYdt23_Ow>A7veLK!kJM zhAhH+9cqZ}8J}aI8iHb*9wWy{Ngau3hX0lg{#jk= zI(q|5zJ|3fBvvmZB4E=`;MkbSDAq<|oXC4wib;!5x_%5cy3#lZ@9YISe&Nc_xKX9<4FQdR`5ARleWX)|Mxn4I(*WOR;Ag4A7HXUv z@7qTfnW<{Z9MXrAF^C#N zBx0_%)5q1sNqJh+#?^+!T}@dVm60|o{>yi-&#Oy_Fp8Wz#o~P2GfOqFWTHKKNkvY7 zrthms1Zl5I+dmr5^-y@;SlQoL#d+Sq8i~|Jh4vy8eEwHIxIVuoE+T+k&_=-aB-T)n zhX(HhD=ctQUceYTF`87k;V#Fx(N0Fu-m z%wp$Yff~-A*~ujVaUwP4MCNJW3~R1^%+ode!!I1&>zrsDJX}V*CDe9r(f89V4JdXS zDh{@ma2+hYwDVuK4r7>+EAP1xe}GtcwmJ_EzG{cNuu4Zu!%uVmMzE()l;h}szJX9k zR(wuV+Au{$83`r}##r;mM-t^tooGQtfd!xjISw5kXCGUywSF%O5K{vp_GC!$;%!zk zA~K|Q8u_jm^@0`QId4PB&iLX_x-lKI5&MD8_^}SJ0t;qsu`ax!{$xWMbUq@dUwWfq za1w^0&rJmEGk$M&0GOQ3xjvidyi*K|Ar- z0eKf9f`NT>_NC!tIZ2lXWgVNzjR9RUSMCOKVP?arPbxD>_#VAKs7#Z8_ct-A-VTus z!ZJzahIWv>VI5sAjnu?j^WY$rzMXS>K#*Cr6#*S49wH8!J;q{tc465si2*)#nHjz* z&!^Vo;*U@!G<;A|cGe{ebVoR^d=Gzhx)JWSDiy(Wb{?kdJ!Seg7T5?cjP_j}6d0g0 z7%<@+I}FQd3B)^447zE5kog^o3ibzGc#_ zlz!bM0Tq2%$x`3-G`SWPhg`&o{Ud1ahTNiKf*n}D$MkxFUA>-vSj938hMS)t(yW*` zbwr4Ol}{#vRMwcZfdIq8Ug04xNT@d885Emg-oRnuIa8Dw;WaFOZYroSPLF}!lsmA! zl#6%mqnk!wU{>S*1E=vjLFiS%vx%Bh!L-Z-9|U-^xi#io53MMj-aCE_HAQ@=_R@eU zHhgn_&_dliu>Z#RC`MD{9{euh}rG`a8&25I_HgV3}Q~vi^a?z#d=Lgw1Lna&f+aU)lNUo@c z%4wdO4}LQ;sP!QKT7rk_8(+$4e&aOXdE~Hp_|$?w#}M>?nj5TnYP0`GUZ!;}62eW0 zal^L--Tp&(!O>zX7GzrU0BA`ev8w-~6Q^dkCH}n8i=fp)Qx6qggF*}j=wEQRnjWSx z25zAa(ps(F?4jodHmHs?YkQX`v~5@S0n)3q>p&yb>lC`Ec85Ug=SW>LkEeZ~t5%ux zNvR~~^B#MDc<2w6u-|lO!y{7k5R+Z>g&#xIgMjYbOCk`*$V<O(3XV?l{xkKG+6kv^RV`P3-*vEn6_XCg_VW{ z%ZldDjJ9^Q9`rce?1k7)y@TmOvQGda=f-f{6*dU<%7k@28+LyKLgj!t!1^kg)yA|# z^6K1wfcf#4u55~@h(Sg+ZkuqAa`e9k<>$sJA`wRv&ScjqDZePqtR=&je+?QgrW zjnf3%S)$!+h}@>zwnW<3dBfa|A=VOB)DkDg;m(m@2jxENAA6i6!$vQfY5Tc)*`no4 z@e1)=;!NeI;HxF77FiL$ky4%c4B8SIho#?tz7Vbq$Z0$Nv+I;sRRPe4-jmOhT?xWi zfnIw?ut1|!E8@wOhru34!rt+DX(WBTg0%0qLsq>?!uZ#nFsDBQBei|rP$D6Q3jUVF zc(ABUIZyyY_EL7@Kx9v|?O|5T!_&^=AxL6;tkNfUD8A!xNXhr`)Hw-RE*}|wgyvX( zrgyNPTpjRg*&p%6l64QHvE9+|1pJ+N%ND(STD)Aj;^gXu6L!Sbxx~wYQ`-r zliJLsm;LL=tu>50?U+F9mQ4jhBcfo>q$DbehAyT8CZ^I&OSAhfa{nrF`shn3+x64A zV7OFz`@XyN*wc2)Bj0y_egu?ym`CvkjxNd^!pNs}NnjZjx898c^7C4SZr9F#6rX43 z45dRODn+h1F((#(Z-a!Eq8qSm-P(BV%3aZtS);S)?^lx3nxhI)X|-v|p4EWb;7)N( zwj@_A_JhbH8`Xw$*J^??LBva?dN*K4L>9^p2meIYq+OkhCOcz0H(axl1tM<>AhMq)f(Ft!q#)Z!JIZDOwULXMkBk6X#Q-!x9T z+#xZ~H2;>$+tN`xcvv|pNR)7O?JQ2lFP;@ZG=!mVSGJ}-1g9~>uI`>Yc%QBf14>Cn z*DpM3WFX6OqM^I|mrY^S3Xu|3yJlG-u{_4ch}}xJd(@E*G&gfZTkIKsEd+;-Js(0V zv{AFrW#d^wP9jj4IR_Zojz!Tb-xdOg+oupk6zv(Nj6^)!N6IGDfoRr#=I{l7m7xl$ z*m@Pmvdu|O8L8~R8C4n{4*;)ih&{VsYcVOPDyuypK3RAf!^e~85Jr@S8;%bz2?A3H zY)(^+lnsn?YsTq>(v|{$V{Vu-Y~#d|BWcE=>6%#^M|;}NXtm(Zi@B6d!R#D6_?H#8 zJilPpmo}l}4TR_5>C&Vbq5-0YVihMH&;uRf)DSz#MZ>c(J!>Mgp}j=&Jn#RAHY?E; z)kK~&X%e#5+Ad3Hr?4I_dwha$V8hmsF_CMjuv(gPB^lqfS9s@tT7MxTxBBPI6R-j7 zCXmg-wxw;Z#Dn^hsq>@@vx9;s_B4|*EP0lXE+1KU4TE`z4>1|l8*H;5UG!QEYPz2T za|;sXotm??zO{AedSTX8x93pQAsc)M1C3mnO}CtTCilmG5Xe&PyB~+0bm6+uG09w=`GO%T1Q1>w;noB|AT5j!Qns+o=*Wg- ztNG&6q5gApJ6I20TIK1Pk@R$@h&4bCCuOD0Gxhh!@T#LxR>?GtrW^Ctsj8Z(7h@Gq zQdycStAs)Fbpr`yiX7^ z_a{<1N+tXKl$}7K!+Hy z3Ke>*0boh1s)4kVOs0^>B2VLuzsF>M1=MCfmefIyjcl)UQy*y~;7CP&)1k3I=JiCq zZG5P0=c*yUfJ!D$>n(8ueFBQBsm~7FHTI_bRy+7w%Bn?-smNP(2g*Ap#WP?w|u4ph#Lzb`G{!xy4BaiMInx<1*Te&LJ zS_M>WYbLmDgof3p@K%DRY@e^a7vN5xbfQoDbsBHVL*I1m2Gch-MVER1KD|Ac)O1;Y zlz|S==|7#A@Md-+Za3 zMj;`ua-zZ(&nRt1Lz`?t7ob5Zgl|yQtX~mFJRFK%U5znZRWTk@wyb4u?MJ7@0lUDHu@-{ze zx~D937?;Po683wqJTjfiyI0PK%ac`#HM>t1$E#rUs2?_p z$?#}CY2ZJ^jHJP*1zG5nG=R%l_>dG-VZa({<(^9%UG($?zx0vDnfli)jiZ|5CuQux zR}tx{RA9lGJ|^aMuoq@kbkNA_`EuB9(asxptQTMPaK5&E{nQQ6!C^SdLqYR@Fd0NY zn4f7o67}##67lGkfCV2au-9xKMECsVr?Y=glf9!IM?`v-E^3; zfvj@#ilMP%R#@A9ADv1Bs*~$)fumO#>mN(^Czm->Ds{jX@qzf;kevrO3GwH+TWR-K zFNms7UF&yB7~tlto|o5r?lGgQtr#rt%}D zMm)uWwMRv6;?#)aSZa%F{|(ZvI5_*9p?#z3pitx$mLW9GFtdlWHQq~qMftUP_shiM(%EeLr42^#*zagqKtBgA{)ajv-s_uN0X0Rl539Axe>iSD=o(vm)vSzi^$w3QAejaKP()YmamH=~<5#xY0oZ1ZyVHVE+W&Kt54`Br9O z%sqH`eD>(>XI9nE8Iw1W^dQxn@g_RNM^r14x8TT)`I+oD{;`#RwvcFZ{+;9L^bwxI z`%;x?)8wo4>6}-nJUM5QB0_Mte|P07!h1&(T4OMm~ zvLGqg%auW5^zWV5w~7!XBy1;?S^eehEeG-&g*y&mM@)u%-Hrc6Gkm8xoDXeer+kdh zVz|fRbmf(IdrryIzsXqO!(*ri9kIddRhf3K7Wc@MKF<7qo=R^&-)}-vzla~CbA$WEJpv!N_mfvrE}XBg+rkID z%vsa2M~I5xt2b8f+5zAvO1W4{UxH2hoo!oPILL2R^#Sus_4gNdEYHhueI(%{&WYsz zI9vX20eDA$7$6{c^#7Z)75jg6w*T{xiJF=jx>!4_8CtuTirYEb7&<$fI{qJ%o1(O3 zyCjIjcT~*mDx29_T(Z3dA*mD`uvSQtOjXVbQe4<=w=LT^5}VLd`v(03P6mU5=nX^| zlI|i5Of4pq>gHxP%f*xS{d0850TegiY>1o-=5UOEm_lIcBcNn=yp;g+Z9s-nGdeUu z{H$$O)p8hHVUrww+wWN^|vLqV|wO${H>mGhb0-aJ87!=hKP`Sb67PL@QG1Xb%H>4ks& z@j$?TWud<*Vw46k+P|3G2%QImBM{QgzjXR0iux3FVgkv*DYkgw^^_>4R~1bbe@S_B z1co+(4m>RdH3 zh-h$TY>VIrdSRJM5%EkepPs(&a-apa2@p(w6{AP8rc}gm7cjd`c)v~;atYb;{=(M3 z9rc2yL}tJVctm|i-MROSuL5s@@1|w)lu>c?i=+O$H&7!Wo6~9V=9XS-~mlc z9Go7^Mno0>1TzYjKn@KiqJfg?50hkq0+A>)O-A=u7g=T7ehhjkN54863C#NT@-TG zKt;E{BcFM`x3H)+|Gy90>m-?1QD_@nTP3itWF;*Kyg)lA!hU*gS#ARdeFm=r{b2)# zy_bf>46+0(A)h})WM9!{69(^16>O^GL$apUIJf$DC$BnTpe;w%nBTIyc2fs`6}#l z9^0DJ-Zp*U#0d!iWNCB9;HnbYys81C82VlkS$P5FwG3+b&EPno^t}|QM#4@~S#~qd z`cr@P!-d4ff_-9a_=9!Bs#V2Cf?Z=k_;}_ICEr$25~FCnTYgGAdIe#BV+{q}h$@TI z|E_Xcy;$Z(4A~YIXmjnJqWG21$|bk4g4KuyPEgRAvd+D>Eq`uRo9vy!_>r1%22g5y z48wNyMG89Q_kf(thl+f+fNM#?p|i!)qzt^!^aTnw6H`;$H4ICReaK$-;_$SlSI)c? zz}2e0sY0IB#z;#v#UA>9W3yq)Ql($~GmzMUp;1HDR)G%@jR7GjOxPrAs!Hc&m8cS> zSPul0`tOB3Ba<+*AQ?EVLYyDFph$L4?i5aVnz>JTX*`aPI5#7ADL4Fy}VsgmIRrsl2%P@5k3e$I6KlO$E_F zD8Od+3#F;i@Ri+3PK^45Y;&e8O-(IrR$ooGvpo|gQK3VBLv_l0y1GAZ^2XSFE>DZa z<)=}sWQmGrYjBD2yYCQhZS{(OCAd8WRT=OuFM-S}MR^7AC(oYnsTanEuG6l!01- z+tkMEzB~kf?)b@|XAc%+6$>fQ6_H89+#fi?mNN=i;R6$bEFjD13}+rPk=nHv*oRnA zF2_hs(@qekSjjpF_jK^p$tZj=E)gb$%`1p~@5v#tsO$0}XNZh%zWd7wpB zVN4NM(0B~{ye(1OMSj1jTyyEhhsAY_<~5pkIoqHQ?#!6cUtke9{opPMjU z`*l^=tObd)&qMjjr)YzM&;=lu{s>^n<_n_M0RL_7V>f8z+8l#R7w^wAi1%Zy4Bg~6 z6~vx@&R@5KOSdHXtOhPiPu?^a1TXeve(45gL}E7SXDzglt+}$OeQr}l6*nmazx0-c z^|1l|qn**{BSz#rd@^dOl2}^_FrBOLG#){jSa0cbsY&1;d+BYGvLKNa*Pwi&`*j6g zs5SV@10!K0!BcC@%4Q+gEvNK=lbL4m+j5|P0YF>|6gv1VFLP|FYOAPf!)m|$hF875 z%={Wo7r?z^_yT8BFY5F047Sf8m3Ur{!`ux+bb0G1{$f^zdxPR1eGfr8`xF_7ZRKth z4IK{HIHkO3sU$j^{3srsl;hmwh-2T z?5eT$fmnUZQdyEtiKkrL#koI9*Uag?!Sqsq_===V%}{^KgT{ss6TBh()C|3rLmjov zC@!<_L%t!hGtkzR8!**FR;^WQ%j|rc^v~HNy@x=APLh)l^kxXdN+EJFiQ*N4!}S^s z8YIqBa4rSO4zMFSF}KY=#3_ge{q#1D;Wj=2O;k-5Bvo-K7z;k+seJ` zuLEFT@K?eLb_VoFu`;gMzocu=tCAb7V@{kmM3t<>81a7HC^PP+DJMkw#1!i@&jxbdw9H z#AAcavaLr^diS)->RVY8-waK`wuU$%&%dbw^z6oGr7RiAa1yhGw-2761*w+nfsX%p zie(O0y6W##ZuF{2D_gn9`s(8b^5vgo$Z}!T6)$~huTN7(n zH;J`p;(`0XtBLdqRIoT!ltS{1D@nMAI|>v#)V8HvSC+e5aV&QYDb@c8?9ZGyQtziss7hnYe@S_*Qc~Jvu0-nmpJ4a283Cyv6Y$_ z3xHirdM*@|II7@VDTGr-kSmd5FX3D%M3UrKmjqi9Ov{xOZyWWouJBwLKn5Ymf4Esc zq1iH*Pq=vq%^j-2WG^i&?%F&yJpLO{Yb1yT6FB2+nAXKznJ2q{>RMDg3f>)x9aP%r zP&FE|bR+#o|6Q>ZM^=hhsRo3^QAcriktnT$3+7ks?wy*c7aXuyuh)N_n^&jl&d!&@ zHCWB-M}*A^4}Nh6>CV{-jy6Nicqiv3>@d?)Sa2***_knQrUfatSER0aY*4ti%-WjU zJJ#8x<5|I0Uj8J1r|pd16dT$YG95wTR7Ab2E`XY*6h1V+C!qeMa--3x`v4IaV#Vhp zo<~@&mlAh!q%M#;2V+_j*R@3fP`aqa)PVleLu=Xy#u=27Me0Z5AU>H4g6ZrF%FETM z)+Pz(R?^%AyFtLZTx--c_0`(84^{Y3Q)6T9OWQQLO&hR(^1!ueTw@RSXN$3v@(@{j zX~|IKy0J+HmnTu8`up5DQ6xrDwIB}(BvO(VgJ+YM~wKH)ztc_ugC=3S@fqa!^FeAeg98&3fk&O6i zY?+mH^=azK^|P}D`_nj-k4MyED|Dp>?=Z6TomTE=8_(p9Ho2i&ksq0!a&}cH8bGXM$jwm zpl?8gZBT&6NPeXTrBAte%fgbT1o6x&?+o zPY?uu&+r02X3TIPYoSqFCij`-lZ7i6O9L_+p}7u@&Jn}$&R?ZSCmeevS8&4>v1|nU zwgJ9BZN~b4!MNqm(KAjVzA!SJbHiOluEKk^rxY2z<@8}a^n=Qfus=mdhD~5@-N;;d z+KhX6Q(nh9`j?7mWuh&SIFv7Fat#HM(NLp*WrED_tsS+swX;?eiU~$i>shq2NVa3Q z2xqv+V~g9S4+tCx^QUwKKMQLkGQGZAfr_v^)OsF8ql?a-`RP zsYR=`wvR2r78|ixG0hvws+gL?N76gxC8ltHj#BZ_X`m#|DD%q}rzrIJ6Y?zX3daxo zG%EBab4>1%mX#tqI1zN%-zOmQ1{bKMY~tV?Y?0I*L#VO4rBe#mqz*xv&l2*{!Yfe= zWtUhEZS2Md4gUGb!sn#rf9{YPD~#8F1XUUzI+f@&lw9?hOLrVfi`A)7SpD;Or|w?d zcM6AWMw+pJb!}E_`S|zsU;-3=WnS(vV-@F3a}q3z${?C=KX|}B74H?Hm|JLGLWMGB zYo#yb3Zg$Kzw)l6qUTVB^~LJT9hn5r+`D6le_uiWptfS}iKu%>vH{M6Rtn62CqoLx z&cNU0>Cd;p8r8A4AN6KbEM2uRkX{6O7{cS;zfWuF={}zw3Dsj!a!chfqdYpzdCU}t z4V}T`KEGe{1;=gk&_d7vKC2TNS>l(*k5PbCoFMCE<$hZFIq6I=K-ys zN0yaPO*Dq=8$QX7`}Nm1hRb_%&Q4*8$IAq7j7Ui)EA>Bx)St7fZ^gTRb`5bjp0Rb+ zh!3BXh3LyzP8A;694Y?NhWFJT#whhRbx$FgFg z|1R#oiZ2&gYAZ)%?S&QcyX?|2dQaYRyn%Yt{^7h9QZ!!bQeD+Y^tD99_530Ro!v)V z8l5RGInhgwzJ}Nn8d?Z{vUzqE3s%^)ywgQaF67WGH)$JqRgfa=8t!fpHtl17)B8z3 zkxrwI@erQ#^`2v3%W)>+d{=lfe3UyY=g%ly_Pnmi1pIPC*e-8Z-Y z2`%OL2cv3aii{oM7d)sBi`r3Vut2Sk?d_J6d&p9Qb*qhietV&RdQoJad+iD<6;AY&msilEN%d#(&`ZJx z+=t?FE~WAeEnm3ScrI}>syQJ;xrG$&PHkfNpb?;)7&ZXMV2G_ZK2x{3=h9ZtQBfqP zh+y&@nLODErGueOEV(y!ds?y3_U4^Z(fO}W&!ST=1?>>Od5IP8e`I{KZKwvO$VYYf zFe%Yk9PeZoi3z<07z8e*3%JCobq6=6i7?=e7+B9;=lq--CII$K%PMTJJ{v%b4Q@oQ zc;tD4$;~V*piG9t1T9xs`-$~MR3(SxBUZ_vgq8edw~fOhD!@&Dj%!^3*IL&fngGKo z>Pr#>*g*m{>b6;8e-uoPWfmtH7i`;&I&?cBnVFK?-b3J(VyKqL>*;oLNYVo{4{d@7rTl-oFv)%C%;N>6o@ z$Vab=@grQ8GZ0}L!6{N!%(5W|W1@$q)6>i}(7uRi=I(i=#?h>e=%6L;KJo9V6JF>~ zBR|3`nr^Yl0xKQH$okS~8ia?a2&c~=wpLAYbW^)6Yiud5GjF|W ztdz?+514WY?W(HbthW?@V&?XLaq>>Fx^O|5=GkZ4wr%U%wr$(CZQDNEwr$(CZEODS zf9XjkbJ0o9%}QmZE-HEJtyJAS(>$ljIMT152OWG!QjozN=wftY1Oc3x-PZYQrr}{k zJJE-*{=^ciz}y#1{vM>cba^s5*LIJriKV11&-SUZX~aW#LflloxK6sN2DZ6!5sQ}N z3c3FjZV@Y2{!Utm@y&06-P~zu#o~E!f7}ni-8T_V39WFZG^ao0vJN@La-%%_6r~j4 z2^d@P%j&=ply=EwWkwt^a^>cdxY!7~0+&pA&P3fVbhWeplX6wNB}Q?ev+%G~yp?KV zn@p3ZD}BTbxLAEp^yhTeCBomOp4@SW$~J}8vO!vaG}pdmE9=-2lWVRk97W4Nf3t#~ zV#PlngF~GI#bPF&w?y#hkH>-#NqYIm^U{K(u_IP*r)uqas-vrjgDfW{vZF|{0xq~@ zp`xQz7cql2L>~I4{I#s;&+9q3s4~CaQmqm0J9v6v*YP%BP&A~>IFxqf3?{UB7Rg`M z4dP{O300F1oZrIfS2=vQTtTi@f4OWT8i#w(#DE$Q(b)cL+pQDc+HG??_AkAhchu_)j z%!JtN_HBNdm08*~RihLAWUks{RfGjyE7wD_Ya6BE?QaS2MLlZ+XM1d|e*|9|ozO+X zr6KFdez9YOa{g*Od)=;Y5>f^;w?t3k^Htk@qzvYz|4D z`{*kN5j@XK;yfuUVQ4Iv7do@9@2E2l$nwRPe;e1hZB5$DV5OrH zHSNWnj(^7n^b^Q18se)n&K)jn1_vP893}~bQO6{Ub?GOSTFYypXjm0fi1+&QHPGct zfk@PW3!ECV^T*?Dig@iUgpzBuUDlo1reo*Ma?-do>8F7336y535LK6`US1{=I~$`S z)}ZViec_f&JJxPkf0fdK?k?xYFy{I?OUst z2@c0xx>L>@EHEJotx8~<{!~*YoFi|Ikgk7_b!g~}D3Mf8J9C`$kaPW}@k`o{M}I4q zffpPCw2P#S+xMr~j|@BTiYtrr;51;`hxRhHC1E0+0xCbpf3_Z2PzwLHYKJm=OIt}5 zs;Smh@-(QfTq4QrBl7IRSlik>h6$cnT8sA%73)k@XZQabwen|-Ih!cZHW>5Qj*#q` zp(1vxZ2dD~L&f32f0ZcHAd)uSb~IXPF!s;!_cAk(uvaaYP^iN?N_$oHh*C#N6$iI| z!nI`=A_d8_^`o->c1%ap!JU;7 zxaa2&s-rDVX|HlCw~z#!t$nMu>jC*)i}6}VI!$R(o&DX}v(VcQctsyfPbivM-j}J( zZ<*h=e;)L>#P1v5littIKc2N+ayzw?dM+NA@`%und;TbV} z-IbMn1dXwEF8Ez(t;CkEQ@PH{MVK#w0#mAgL|eBcz#$aAZ&D4G@ET8LSWohefHAL$V}yW7W@ZJ#GrJY{6;CsYEMb9}@^JCX^M%OfUkPsyL|WC?p| znWgr|vyUT9ZDpaNcZIPIOYdxDkfA^mI#oejcO0ep#RFs&1|4$D?Kf>38&(+30eg9j zAljAsDD+_O+4$Rqdzl9;&b)KSk;PT+f0&!ZQ@9pob#UgJ1gWYdOpwP2LcV1Dd8!Y! zpzg|Cx@8gFXA&^2F`h={*~&h_ z&>}k3JGvY$zsTSSzn49BieJ4Be;EEN${x_7CG78lgqb)JI@i#iQ)PJk|9%>CwJa}a z%W9t8)SGy$=ykCDCq5XS>%bey1XbJ1$U3GOD;pOcv^2Xwt+hrjZNfEouzNExsM6{cYjiwf5|fT-$Tg&Ny5prD#=72<*R^NzMt zSZyD@tQUY98{$BPQ#;`M6!n+Nr%S~z5LLEm0J*9TK~~uS5v9@|DZ6L{pz%C;J|z&M zRQ<$Kx$R7$U{D@nhB+m_e=l9xg=1QNhXUOTh3d#zptO&JYTBorZuV%yTT+R0ZYfP~ zUxaSxnLyl)vB(8Io|WZz zLI>bVyAE`6Jf;KCvmXcQ*yn%ri2K+n@21Je$UM1t*bdOOCHAnLmS{IZ*A$wvBUEKM z#^~5X`)sFnqTiIQ!)m$q^UR-h&!71$o%w!jNb14Qud>nX1PpVz_1A1AZ+Gq~{Ow>@ zi4^`V5ShX-v!45`NitwpukiT>-1op>XQ64+Tk(mmFtM_AuFVCjxA6NXy{WPel# zUK7}DkINmv`a0NsMe5F<3lcY`We`^~c$kUq3vAcV`$pUqf1LirJ`U3xvI|tUcDrw4 zJV5;cvh$_V|+2>8l~`O1h>)(igPKz%OaA9e@3_DiQ8Bh31 zScxaBdM&8>jivES(r}^i1~L9qZ>UluVVu8q4pQYOWX=Mqd^HIDTf6Ur4j@dF&=&}pd{dd7pjwr6zF-$rn<43iRj#vSp zphd6sJxm7`B9>qVd+f{TuVmmfzQr!%`WF}zfBG94*;LcnTd?mO)EQ=Kxao9L4(s*+ zm3|Y;DmTGpT|2Q8z*b($j1*{O(;F1%|GDE=fC}|Ph#5Oeu62! z2qt$3TLA@k)Fb-n$agGBcT|gexF>DWKx-1hMv8CjTB_)^9~>iBG#q>aexdag`T ze+G{XuPmt}SQ>t=U{YqMbug}!T%kIXOzUW=(|E?f>$Ys^JcFSWm~7JRjmB>&bR3e+ z1V@6&#wMT*$P$|S4$?{1_<61PNJ?GhRp#(nP3BxON7z&A*61)mx8YWd(BwByyS`fG~$QnfAe}`nllv`lH>W<^5y&001`yp2Tv|EGXjQ))k zxpMb9!JRdw)_P8%GpXG$8QlX=q3Wq4iJl6R;U(r(O03W3zbBVKH?}K?zKkwot5cg_ z!Q3^loec_x8+s-Cn|qHS$RDSJR1FAZcC#9Zo16oV>2~2WwhQRxs(r+`*wawHW5Wn1Mt1{*rb zOm<)}i=^2?)|nK)O`BrT{zTi3%%;G4sRN(;HkzxXgPQPE^Os4N|UbxN;_fLISH1gPm@Jq>(2h ze7^`JN{ql=(_!$36XgaogL$oOB+A+wU8E)&c&)9IUz?mRUzwsSM@BRtGc6uX$1`A+ zW1FJW4%{I@txBbmHMZb<7}IYmH>T<6CQa0AO|!+pHChc`jWBeYuy;0#f1li#v@Rc+ zj%{DTX{!{Hq>IX;Z^l-6foQZsGp*ZVOuzK0zfef)#|a>M{Vk~{Hz4zZGHon10Q!W@ z4m}5Z!OkBBc`}E9bUnOk_qqmj{Vj+iok0*J29W9`ubcF34Lb@8gb; z(m?7|TmPewsC!Ldfp*3xe?WFi4lf9`xb87^hbPDvd0tUs{93Q4(L^U8nMB$EYT-60 zQ%3+lDCVHKRm*DAwkZ2G2bV}Y0AVw0?7#kv{$=XD1L z?1WFq$(H_vuNA%v<7yY4qkSoQ<4T|Y%7FgXaF%embydE2`zl7qf0}PtIQ^SZ@qE!HuZf94#vc@;`$5#iJi(lU>wqywBSUEkhWl@lzOktc>5$C7|7yGy*$ zWga{+M)OAnPBo z5brQt@H+bg9z>aYLT-N8dT->GVL>T!=&?!LA~)s@x#note>!~B19KCLT>AGHidnMu zt$}*@iRc~OS=xz&(>7>Cdcbw>y5rgV*HMsH+dof_^kJ7smx0MO=GPq%nUg2okni!* zw$%%I@JdY{46$Vc`^o(88MtkOTw_=Fj`T9OfoK+;=A>sg0nN>?f!`&r0KQCI z333KWZ!D@arH$=f(X@jN2yzCek4kG~yjeQar*&EH-mc)aib(Eh3+`^3NN1+(4*}so zLB_7A_|c596=Y>kN&W&=neYNQq;%(v?+i4{@?5F+I5aN#`My;6vFVrQOZ0oA4+(ps zi@r>;e+GE66+HG>v%_fS;e&#?VZ@GwW?l^%6HEs6k>^!7&b(NYTh_=6Rxl`9C$Gj< z4os&Z5oQ4~r|LtCL$=v5+v-CzSIvL+7na}z9|Xh~HK>1P;rhq-M5ZlBU0&KTapvCL zvjc;EfJeXne8UT}sqE>ptxdf_UWZ>T^@PP+e=}`ht$Ra+ayUBIxF)3St&9B>cvmY4v&sQuuqQ7CXZ2QMc2JdkGq}&%})91 zkLR-5-wk*<{IY1xg)C~L^5F1#a1z~VaRx6HhTjahOQPPP(g)P2O!4hrtS^TwyfY13 zf52sr7Cj&hGyfQ&5`$FK09ixPH=_|dUFVr@nk+R;HB5H(`Gu0?%<2={4>5bR^Bibc zGIpRCkm!2~84snbC}&boKA`Y{Hm9JSG(ziGLa7}WpR+M;u?#{}63a|{piVZX+KC@K zSuN@$HyeQ-%myTUai{mu2V3^w4L=B~PtXTy_8_X>Mdbre&K_s!^Ym&fG%e#~ z$jrl{iBPf$(>~$7g%nixJy++U<@7UMe@N_x`S(OOi}$Polp z1$hm0g${gH-RZ&s+hGl%pGY|(V zlp?fEY@|(~k-G>=+UlkryeBf$f9lO@sOBoZ=!q_uM-1`&yVn!cgK2axH7cHMNf!VKStqYP30EO>0;0mSgIfJqKqb;btRdFBbg-@ z&&}b9H$#;a^nPHuH?2HGt30HsJWLf)ouzWDjU0OU21wo`Qw+-$pzs}^e{oITa7DHD zN9cUaG#{@g@DG@4~xzH%m7fa9c!AS4~7rB_F zP`o8b*tr%cnmJDq&l#M(f2LDBbs2ongq|b}Ht`eT!k$kRQIO_~8h%0^dQ#Fx=M$iQ zUcdm;$)Avd>brbp@(cVpC6Frfqzz`Lit-x}G<(3H8T}#$je;;ua%{t2%-Bv&Q z4zy!uMn~5GOl@XPFFa3L&Xu~hXswPgV&k6Z22q1jYuPq&%s`e;^b)Z{ z@Cc#?#vI}2Dc3lZe-7H#K*jx`)X@Dm%BS!MQF3Q_IuEV$8)tZ%?qW=XA9LMIMqm6X zHZAU4(`X4^cX0Rm$SM*2ShRCa564l(Lh{9Jl;RSvH@m8x+{$6F9Q~rsuu>}&J-a#< zV)(RqDXwEb>0a`wJi9ZX;VyFH?tukC3SV?sp2H;j<LnLGQ5mhM5>$($XZ+nxSu?% z*gABMAF``~+uwin&%_%rd_r)15bte0F{m)ID1S{MAfbbyWs&jJ31I+2B>fpgpllJ& zZGy&qrU{U%2dAxu1YLw+{pf}eI0%F3WTFg0(S{jBX|Sm8RpQa6Nq5Xj(FQ67{r9Nnf1pG6RT9~KE0Kb(?G%QqQ4&{dj2YVjdEi6iG&Ci3yHVv=I*c(sG$oC_kw~um zQ+t^d2N8y7a%he32nyq21^~gSeNaQZJc5ch>w15+D3LDFrMtx;#T^paV?qZ`J|&t{ z?BF=P(EXHxR6W{@cie&iJ_4+FR~WZQvY%x0f0Nm8v>rK-_sN2k-cW{L8o@7~`F{BD zk2wB6;2W$>GZA#koH)!nP)d!;Y3Azg}*zfi3s=kCT7TVmk9z#)@iEq`ZM837K zi1b#(!O?zprs1tkf0p+xE!tlaR(%WvJByq{pBtL@0j{ZU@>=w~ z3v7{Q&C>_98_fsM*J%fKn&kf#K;JAjq_$Cb;QvzbCi+?UR{B!&Ci}_%rNu?yJJ*BG zX9+$$OIHgxlN@1C!Et;}n_`uQQVU3~fy6+QjH?v()L}Lbv`S^sR$-cNmiIo^f22#& zacRKEw6rEYisv!GwB)Fv^d`WMaFyz*jQ@@CivZiOpv(Ei%~1fNZpwR8!$`6ZeWCpY zA7KF~eg2*1b+ll&uq#ANj||(NGqP<#vt=>z2I00G{sH}*PIrgiVKI7eOW?l# z5$AdPOUG}7v~A$Zp>00m4rI-2e*~B$s;A$#U?$^>J+g=sHnb0UA^R+3PCf3SyAQIV+N0t6AAn)z!S%1@O%GTOIlY@lJ9QxP{DgS#F6 zL*Z`d`iQna$?(f}PK2B-I@g8DPHx7Z*OAP4+;MEg9i=p2+aBxe?m&kCY>zYK8y`vk zxp!^j^KJp?DM<(3F=;F)If_3?%HERR;|p@CI3dm*fe%DAO|JlIWJp;`J(00E+}jo!#7teVw}sVvBBZWS+xaUJI7wd zHgsx-R&ZiMOaTXV=@JYJkc(*k(BY=%Xp;($*5kP|3O?B|=V(_V_?w`g2j8(F z4S+T;1n7f7dc*-h?Isx15uGNrv!C1#_H?4#KFb^CCRuLa`@zCp_y_DozfFx7cy`ik z-vmZ4X||sn;?nAzyX9x(VEvD~7Ogr==%A9MItL2Be>!BPf4hB-3-4agb3ycCf>Uzg zE&#xZ^2D-~mWUfH0n>aml&2p$V}=umw8#0qkDvMYb(0@%FPKvIq9Q0 z)dm^8-*m0F0!eSs@kIs*xnZ1}2g-4KSZ~4w&T1IAGD104VngXz(77l8mP>ucRyDOL zlUZHRf1$qTsxMCcgL*MIZ^v(MM%>21p3nTAoL;CO;Zd=ff>K>WyTqU(eJ?@{twUii z75UVC@RSMTQ>yOk(Q*0UeEq;v;2LMHuHuGj0+yXo$>7v#PU&bB*KR2sioH2inScUz zVx#0S$e3e>e}^)zjWvA)gUM4200%R8a3hvQE3A!7>oGbzOOIF?p zf7|iSBamZb-Ubo3SC}l}j%7aaH1AMsfn-Az{7e^!HD7aK6S`g?wA=}#Q?_gfyW)lT z5z&m{G}vl>Gyl{6=s6?@$HC111@i5XQ2B+ZrWHyjAiVn9Dg^` z#dC0_bMQAi2;Eo*1?>`D;eELNIL+|Ae>kIpoB0y2qc%{(z(IrjLf2YCVFD_uk|ILD zd7*-sj28OCYTZ7X4WWSnrwTSOVnd%|A+(PKrqp~eUl|*yvDwI=h7AeL%A-ztG7QY7 zNhpDBW5^C=RsB-5u#L@h+x)6PJORbYAu!_7o-;FejX$dlBbH}@pV+7g49zIqe>?$~K41~MkuLgAhZcd}#PX5fav5$f6IL6UJxZ(N&#LuaYl9~AoAMwBr05E%t(se6!JH1; z6W0OJr#4LkZMX2t%-a|*dejw`u;=%eUZmHdz-@F$4|qP`2JsUm5C3mUTQ3)-uo(?y?hPp=e_ov(mT1EC z7AX8M(I*no=O*4;3+qX&KFT_{P3<71F}zKTz{|5P(PunuBPkl7l?iBQu-@>q2DqRT zTe#Kdbz&D-SQQ=mesMRlG>>MyD&{?2N8YiMBV=P1{d%#XnQ}}Nds08_3YRc zHzab`qHe#V8|zjIYnyspe@eC=ST`x`*dLmz-c}CRCb7LoCbAz{2l`5LY0MU*f0Do6 z>gDRIel-o>*vr*V-MY#O(N#kje}n~9UPBn$%sGwr%W|LYd2$*8au2}YIF4tYzSyC` z76V3-t0TSVs3R~{ZF}$>4@7Bu54=CE?M*qDO`BU@GB^?W zO_!Rk$=GvE3EIyD{njq+`%iF;lL}{wDx54M4ri{esDX)d&-*@pa_uezJ;s_Ch3FcQ zf9+`a&4%6yI>=@*fBu(-`JV`$Ht=(LijL^;A9jaAek^DoRKYt-z)!o+5Z|v3`Hl88 zPjJCKA7%NyQ@nNm^x~?|m^SCOoFlkP&DaK&-3@N+QEjKD74}6KT??#u+_ljK^j5*f z>}`SxYoc(~4nsH8VNh!+IQlTYQQ<-kv>$eZQ1J-SFxHz9h|FRT00;#`w7WN06BLHO4{-!j^32SR>QUyQN;eO9XGoss76#>z!z z87BDPCHU-@e@WbzzEPcAsh`ynJ*|5B|H#Hk?#*6>0+`%fX()e|q!hcb^H4So6TTr5 zzTf`KPHPjrX<0k|n*6UHbKQHn0K5dQSG%uBTi^$SfVJyLpwdR&z|S$>Yjw*6CdBK; zIO>O^!UJYFMy>Y_Y?ho@*)F&WGR-|!`>5Wi+75ZvfBBm;d>$8)1J~qe+~?s~#n_HQ z-~+2hVz%`TNH>?2@5pnt@|J(TqkeheP?S7n$Rmm$o3a=Z=SExx3?W9G27f{hISDfc6rNb11`i8HWJwJQXM>=+p-#@1 z<*Vs~f3bWJvny8p<@EkOf0QH4$pw-5U}opjhq-p6t(?2qx7>t1K7*;(*7{35{n0L| z4V?Cj8Z7GGKzpei*2E|%b8dbkGyNQYSEq#R;v*tj;bVavZav6DTl58U@;a`PPD-`H zZGzb=-6=T!TWMXLnLQ8i(X6tE^i4(l9{<`De+4&tDzQKq?kQfYe_{>o8JS1mhigW-xd+V&^h;MIYme+I=SCZ&MgOAHw@QD6v~O#x4Iru1D9*=H_x zs#Bm4J?H|+qU7D3nlnyX<&(GQ44|B zd=d9c=KUyEEf!8{`pU~N9bF7oCMo{+Ppxm?eb27L>&^w1(FA3w-uC(6j##NSe<1r| z%*VUY8mHS(#CZ$uoxIG4C`=}$ka=(cIcg}5;*pOd{>+GYew6p|+6Xt>y>A&df)@?R zG(#}(XT$NxvPHV-rOc*3L`FOz&gdjiD~`TtTO9#)L(C*`TLNDy58{%Ww*en%Gs;QE zC3lby&8T<%^o~j6rTI+52$nGAe;>4Gs@Wr3OIARvt>U$A)&MG=rICgR-ZO(Dh#KnLg z-n)}UrT*+0nvP{wW0`DGn&D%;(X3q#Mp3Yb?K-sm9T~U716>$doG9?xnXv zc<7f0^*Zz?q$`ZKPFDDeYRFucsf|cGi4;(3BUkV(*(|DYGTTH>e<;@(8?Qmt*px#< z&wpvBK@Vp{A4_Z4a!6*ZnB<6rKUYbrlDtkpJxjrO8Jno9-X;Ka*iXaOW6B?t zzh;!`7pw8j;wPhy&TtpfxS51PO%91ZbeADRJqf9_hE>~Df2Lah#uHBhvw zle@qk*LnEu*tZ$PY7(sKMWZ_!1@93?y>{=8iKS zXp-c;kq7vvf7b7+wEB`#wEf`Q5=Zlz#BzCHDOHNDQ=n1S&G*pLm8DY9Mb4V)$5Qs8 zCZp^^g`wEDVKUb$DmrnNi9trlL^!D(k*S%S3mUT8l#a&luHw~JE4EBT+@L+X=<$o+j4(S=K85|_*5$v$6TL0NyxE8eY4oCXIgIO&*an*)JWq!) zUQhR2`~oCDrOqyYpguZ(fymq7`^Il-4MIP$jX&My&VKMzJN*3NUgPXjKh4(84D2() z22JCFe=m8kwhrd^+2YXg?l2Huo&v~u#_zgH>AP+u0$#bx??OuPy-y{K_ReRKc!1Xk z@_(x0ymfj4r1^k)673A9Kx6KL zy`ii(S3rQIe-MO7@BxJ6+cCbwzXnlx7kos%$O5ki zM>MG&+Wx=zff^@D`nC+zQNoI<@!Yy`OKlKNb{PZl1GgKiCaIb)iMd%B&00UCqT3!| zfs@Q*2AyXwFbl_@sn-RQ@P^jt+ltYJA$3aAZbe>lREho3wnQ?O!aWzaz{r ze@NVe`Eh2^MmuDi-DH!q$+wY=_mLNbu{yS-ZX*oiehir&J?&0{`j3b6L(ao{AR6R`+ zY}#L2LOxAjlmDI{Awql+kERI6hOD28fBIqv@We2GlhfOHaLbo~trqjRuak(;uF|8M z_+O|;oADYBKnR+_#cuinaRff&ehZQ}@p4qrk$|KKl_iW4Q(}Dj91$cgGTL3H*inED zMbEf+p!IZA%VB+dlmQ;xI|vN)`~vmznHb8cAZqBcISKvfTv)+wv;nlInwjAle*?@v z@q}ot0-wK6IptO(giURjp-;ylN>{Z|pO?usdIT&V5pp%886~kRVp3q7wNDe8FOe&5 zl3-qlgD5aMcPXiyq`*Ccb-T$hv@%kwOmi;Ya7Ls54gqKeCV^qwVA4V&v-BtBnrthp zO#vJFX{WzH|ATp9zh)PoCiv%%e`@akn|Xm{r2GGi4=8P6Yw~}SRD|U1ENq?sA9TvN zB(MO24^PB8j*RryE9pGOJR%}}WEwv|1QkX5Y_!aR0~0YbGP`yk-vdD)IA32JQYBfx z7o5&>Md!tGWr3e>Zx7Iw0S}~%{_YE>s8UFEjfwM8bC(6>Xq{FGK2_^Fe{g_;T1^!b zjp{7Vaj3))sH4r}3JXrs!c0|5lMs-DT&d`(0DotPnGgkHi?aL{D#HaZD_7A1@o~jn zx^XIaRrN9(_TT#oH_}CddQK*c8G_I*I9$*Gb&tk=dSuSfczu>);&mZrPDLJ;QsS6k z{?rV)PF$&vw31`-0PpQaf05Rf+aL>Gy}y~K zS3j68WDrV24-;BFh;X=zC8A+5{1CDd|&a>D>?^1tu@srwv;{cSwZpFanG|985J z{~zoAzX&>_7S`7PAAnA^vXmUM0?N-!Q%?T%pOi3>`v53$Eqw%q3K61ImIVJyeQ^RZ zPFi$M1{(=3(jP?ae=>*3nIRBDhkf`vzcwaIZSx_Pv-U->LZteLsP@Mkr`b=3-K%a- zSbYp5ER=y5X+kp^E!mcAHpi6;^-0Z^gz-#~(FuArf${W~2O>&?*CKVM$(E!BYc3Uv z6X{Vz5m;S8^I>gv*iGZ&&2!WQ2bQwn{9a9Zu2dZ+-+B@Gf1E0n3p^r>MVF9N{bfdK zJC4KP{T@yiVkZ#0hB}Hb0+x%pIRt<3Y0fVQL~b9&e;O0JRHq9C?yJ(9fpbhcW9cv1 z8cifRMxG{rgU3Gv0d)=8N|z1x9*TFe`NkZogmUio;(<{mMjb8Wm{U;X3SsUfKABalI23Ul)q@jHs0VsaK7K2Bp&UJqerEC62VLA#elh1fhGJnWYY ztotT8IQ7rqIWRqID3Xi%qqh z6ncMe=BB-MQIc9Ts33L2T7qB-qNY9G9s>jk+g-kxJpPG)PQfy<4kQo!^0T}kc{+p3 z(5EZf2g{|H@Y~G~sHdejYtE1O33A1%(#`>-q&kT(UWZ!{;cU5upo5b7#pL$QPRL3M zwB}mpf1WW`KU(LhN#6vwgEx@XGLXw7EVJeYcG^xX?YISm(m8tSsBFrtDX+Y4$OwY4 z#hAJLz~Q^axP17*eT2z<4)(vJ1wH~1KOz-2hFv~FQB)X2yxPQe9r7AwsCn7TNoB)< zYe`8JP#D=20(@cGLJ%>6`*}&R43A8*M?gh+e|dSn=CHNP6rPsk6Ftx|Ez%9~Ragc# z4Bn{ElsT#7lS`nuB@creplgx-x*aN3V|QOEb|@Cs<7)G^AxC}=Z$CoSbm;6;p8Ck~ zzyD9WH6>qXzyD`7U$Fn3-I)JR?e@R;tLl*6$|9M+ez(slMf`t-VF+;o5gdt#hWsHQ ze}xMKWCK7@IL~Dl>KAc4xgd0zIbm`sF8&D#cfkgsmpLn=WMI0iDBQd1=%BAUeRZ(C%^Z2(&xxt5wzV&sdZO;+%#Uq?eevQ_X%%Yh6+$rz_%u|fEmizxRBBYJbqQn z1n5inB(Wnw2V+%BG!=0oJgAK=!GaqseM)DW&p5@)b1{fhbm+oiQyJ}S17ldqVWrArNy{3xO9#d z>Y1Y@sG8xD{KntDPkz#vJfIhe+$P(OK^mwp*Wtn)1}I?UjA4yeHuRBEw(Uy{8Yg!! zhIF&CUSU+rgeb|6^rfgQF9+}Y1joC$R>WtO*i!+(xE1`ST1Lyd27@9Zey2bJt zQ69G0DUv#w1q0qR`lS&pD~uam6%`ftSCZ#Ap3hFe`RzNbfn_TXWsRt4h6#6V$_5$1 z)tx4(d>D^(N&hWu$La!Sf2&ONNairXUHuw6>1i^q?w6l$@)0eaIC&Q%?ZIF8VF-4J z{?6G!Dp0x%pB3}?l^O@Is==Frsswcun6Lq?zWB8*?;KR+shHX*k1KiXtDBbODL*~o zuYtieg+x+Gf`6ui`)O4O_5SVP>)@mUGx`KR&OQ*2r$8oOkq88Df0+}a;K61Kst<97 z4kIaW05h=vuo6AILm}32XKZ^NTRqd|r+5EAINJu*k8Ju@xj)YV28)P8p;1;K+y(;d zwP|sz(vU3ZmD|K!7v0@5PNbGRBL<37H>d0lBwM8KzO?t5v}G~$vEzt+Gibwu?TY)V zmEKH{v}3At^6iVOe~Md|%x?|UQjRN8YtHL&Ac`L!z(OwVc?{%f4q!#F0hLqmPSVrS z!d+GzW~a2ZO-RGAQ0xa}FPW(tS171EbCz~2?WWG)aXW^Swga@bThbT{qlh7TM$FWL z+0x2mXO0=#dLbH-q@Zga9NB(NbI&bNC`YU<58=m5T1L_{f9krF&4K5Wj0q36AzmcP zDpDd^Bm={x)QLArXMJpFy_?k-{qbG*%hNl{x}8K3GZnxJ4wu*NeKDUJ)s!u$ctb){ zLWK~Cq`c+upxsk%T^*)=-2~wVVFR*+=k?e4s8w-P++;V0;b3%6(4!6^vJ#OMCi!{C zQETPAq2wsJe?zv^FCxgU4~J{D$=9W*FMAm^fC#qf*O5$9b`}PQ0durVaMd#p@zU2_ zsxP?S)2@CpiO{@MrcrW!C4$=kKGYx6Sbg;^L0<$DuIv*Q_P2wx$nP957y zWP6VaApBN6GWE{#_n^+0Dk{SVP=tXgVMhIu*3Gh$j$zD^#-ik#cdgTK zt9XP4+D>}ooVq1u5xKzHPB7U6pplYP;EOgGe|YYNqkNGPkG&xV zIMX#lhE-%qZ@3aR7LdMzF1S6S$c9&N&Nhy2stFH=(h@>Fo?{qD7xfeGTIg+y>aMw< z2h&lu+jVVtR4i$_pQHv|w-+HcCmB^E;H=HhAGnx9*BsXSsL^inD4)E6LS>Q~AZ5k$|m z@Mh|s#e_&}QGMsku1BBI|iGjX@m^@HMN#B~Krc}Mh zd2?b`ie;z^XnazOR?JLxp?Jb7P;%xgyBo39;^-AT8x;?Z%bMfvqJ7Ab;#-Jl=Ttxd zfrZrq*Azk@d;W1vk^{-P>2bIcgJnw0z)0*Pvar(W-pOiQ)KbhyVpc=FneBG^f3%J- z`>96FAm`p$*cmm5Q^g{>{}o^nX*zQCO}iz705;Sq@8y8kUGCPJTd8d@Rg4 z)uy=CN}~S85ZYDI4iv1EI5!j;)XVviEPeGRyvA_pJfx-swWk$|ipbna(36J%NkF#0 zl$UrFYRr28a*i)Gpf!s)k;2~Hh_UmB`yi-ShFLwlX_#WlD6UXc{{R3ttr8F zZ)@JM#kUMA9cx}D(pMx4@X}pfy>!e|k@lCOONFsWVx(xC* zOL)7^?KBod92eT9_TUbaH|Bq^>-)tTwhD`<;wwP@aSD%92c5z7d@k^{sdtDqo$h$l z659XeQssiD!5x$f+wTx9Q-5c=sgBN=&HpkY6E2T_3FUz{93u??*{ zOx>HKnW`6={OES1Ez|pA=uL;>DDD7DjGXLhK;k`azevp95l6|ybbrV}bHSFQHia*6 zeZ|(J7jQC`9wC&m#zXJ{sCf5ge|_JOM^2B57#kuvxi(%|F;4!6qT~Q&S_tFh(So$t zWIS;&n>s~kSIBld-Qpp3eClk-xTu|2UyiH6UA`XWbfDgjn(N&RE#+#Nhj;+ooM~D& z=cMkTVx7*Mc*RSV-+!Y}78W=D#!3=nTo+20laSXt^nSx$>aypWg##bMfqV#{k6q~w zpQil+*2Zm9W>LTxwN%LPF}!}-dLE$p)!FK@sKn9IOvfIbb>ByyE{+AtE!Acdr*uM}t<{u2oKcrQ#5_=!XXZysy*oRpWis<^VUD%(uzxUWQ8FL7uXGXS5OkW& z37ffI>BFo7*2lBb2bx7|7=m6CKx-tMF>O_kG+e49RNZsV9yC)kguHmG#8bO>ho#;J zW4WjG#M@oWYCb8^s;FZ%)5qRe9|z>@J8nhNb}3HCw_1#94QQHqX!xu$(6=7Kod~jU zW6T8EF9;lUAb)a&*E|1-g5h;BOPkR7x&wlCPGh_2UOp+uJ!u3TJa~h>{H!Vf z;L$l5a~-%3IiO!Ib;ZTq94wF0`X!$$Ib7*X95!af2zs6Ctub(Ssb6fx_^{@5zof=AmWM^H?JXq2`Cl?yHuPKs1N2$ChdAMk~z8SydT(N#xU>w+P2ToTO z)Eb^rnx9<$FGlXEM;M?%({S6iZQHi}wr$(CZQHhO+qP}@ezUvDW=|$_Sbw1MU6LM^`j$Z7LoOh8Q~k_A}PUUTniH9jazuJt|M%pzA!H6a@! zx-%gkuJ-~W>sFX#`XU(>6)51QsAD!?UmIS^>4ulxtX$?ktGwLr0nwf~b-04zZ`JW> z+Yg~V2kJtc){EVtza8wjJ%hpzP&*VhI`clh9vBy6^WNmZ|7&_ZKt3w{-t|Do$GSUaHcI|J$PrFI z^ZPzHJuH5z?rjr02Iz#;%UX7juMvAU;~{d&>Nc{;K@*B!_-Q)Q9AAr~}V z!?QcHw?#4K9UhwAWl{ct6T|R!V1MbvAG65$EjzoLt#yNwYtSodrqp7r`{a@{18baB zm_nO9B%Thxq|tpPP?I3~#F53VXh)GL5ABY}BBMFpW!oyqMq49Cvwi8!k;>nhl1!!f{(UUr`$v3oVvV*1ot9)O-%BEDa41edk4vWTmQ$%uuKR)>Z z_p^Om@=Km;jMKl5+$*{Tn12cx%H#E5mxH2Mx#ly9(lxhkoL1Tt2_=)Gy_dGQ#QRrI z4a!Z%&1Eknm^!pc>4YY!*8guZgF__O1#Z%@nqFeEButl(ZD;*uodvDnUKB_(&W>*={=&C*`C;f z+R64Hj?&2!d=%w)v(gzw%F_5BSK>blC0lvfUfuPYw1aD^{Eg}~sa0vz$a5JP1IfAL zj}9Ep!YD~Jc}Sh=Mt_%s0j8TdFe|sjRsRUeRxlh%EcF#FV9`QATeS|!7B6xm;479G z&Vz4R*sKbg1)&<_R!Rc?fzzzE`SRQz)C|cU)DUpR;*ZP;xLmQVgwzvzu#+G!I_ed( zw2tYCTe#~}qRbOHl!3BNKJk_#Hr}>MJ?`4O-^R+l6798Z?SIeCYlTaLQB}K97)qip z3maHJU6$b|ke})O=I<%F&QSE)sHGT(P7UOShXyAne8C%s&Kas8>?D9Mj`mp_1(W)a!d{#;9)VZ7v%9G_6TcYf{z$`5BJ9 zS>b3+dtCHnT7Q($8)rWB918Swwr=UFhCI6dv1Ty8gNHgE-^r`I1x;^B^n@_FQbA`( z*nSo@khP?`43(DP9xzpoQU;Les zh~<%*pD3<`&IaHa=eA;v8)HY>#(SyHW&*WM*)L;b?|(2z)kT~M%J|+fg5Sjn+CKs` zr&aC&j$wAkCAp;QNbq$+Txa<~)`4~oiF?I3U*ZYK2J#KaqAZ8Lm9sbV?ple7yH-T~T=ZqelYqVd3p^9)B~8SC`Qba!-}7aUAKs);Qw>)GhJQebOy)F(+i>k8zMu z)09`GW~({-N8WF=s$sJ4fkDDw{hTz%%e9K>qJOG0SFT}>9bU^K4$$~4{*pFf|MWBF zo3C%@FTT4;{GFp7VjWcr_OjoyM7pb5kwxc*Z#s`+1KjIYhm>=1>{t3$!Bb&K6-St7 z>&2nKB{AX0c2i*SYxLZM56~eli?jNhOp52BkZ+Sy^#3fk9$nOPP}5^koUt7Px}MDE zYky{*fpdGdNO5Icxj2iHuNGyDG0ybf=3%s-DtB>yqW=ssrL*n9vjdv#geILM4!Vdq z!9!nebMe500wv80S<_?M*V?v%bKF^_yF(C9{)hqx$k0&>w(tTmi&dDe_;m1sZ3?_& ze@XdsqR(O-8Mh|b;Mj==JsJ7A@ljt>AAfk^*rNwbj6ab7^3uEC-MBdv0DwB`|L!Yx zrvIUrDp>q~T&fA_p1iWccb4Vjm=qt3V2FeUObQcFuM!Q2IIg6$AqcX3Ns>W=oS4DE zENEY)I&3Lwp+jL#sm@whUQQyYs9o8PVzaWURI{RKRkLZi@@x6;vG2@xPbQRsrhoN* zdi!VlE%#@4!U-I2Q&OQ+4k;ZaA=jtOVUjd(1 z3!^-4MaDqNsw(n*E(_7p5>_N5nt$0cooUN-S#+odw?UwLtB8CCsx6R#K20IHbdP#vUQfW1q$6!>2~F&95V#h73crVQ>P`|yKQUop27fe|u49R+l_!yfpWo4zw&dbi`nI6;Dt|#dL8qL^*9urob}>4qY2JhMQ7TYIPU9= z0rjjt-VGXLZ-%ha@ytAmPC0k$PDSYuyL?!>&IHOk1{{@Vr9A3SOju+#n}5#GKS15) zP{WmhzpVi8#k{sL(YvMRu9v|*`pd@$-J@dV}dI zzH$sKV|`NA?j042U8pyO;3xiZ6q`k;(x)Rv&YHy9LO~TiL|0-D!GAlC@2mN1>dktBU5s&UF$9^J=bk=4dNoV0pn>v z;`%89(#qAtj3&*rFk|0H8qJI23ZaKGn2s$ocB8Zgm@4s2C}vJ@;lqQ8VZ^NHdCIJv zQVb_lc+2t?&wL6Tc-0(vall!hqo%d1MSt@|jNL_3By{TQ=;%~*NLL7sQ9v~eDg=7V zIM&gSlLe7skWyMc98@<)sOVR&EEtapgmEh0w450|tn(O2u}C9DB|~V?ZPH%Rhe{UQ zM1vd`m}TuUp4l!3>NMM6^s~q$ZC(N#tdb9Hq>h!XArM;u;i%kiPsStUjvW_Z&VR9H zrh$iB?LrSIos@WmGxuaxa;iMCv8i<8Rw1o4mTzlA=63rRk!JTY5F+HL37^XetKC&A z%QXB-#V+rnlN_^D(qL3nTK_;Zi2!|+BcbSPB;j`AC!(q+Evph&anx!Bf}A#Ed-7~9 zKF7G+=|js*bIaWM=>2U&fC56z6MuC$q%5sur__tx9TH<{Q-(4O!Ip#qo@hXJ%>xnZ zS-oRL^<=O|7qAkY7bcgE@hA}Hl)iZlS}{UA8j^RNP`*gX$K{SeBCZ&jG-|_CE;PQT z%}DtB0rGmsMyq!swPL9EZ7Uk7bCh*wQk73nt*PT6qgu1*;8u73=Tm4H9@ zQc%U!OU1Xeg7g>46NT-Tism?);nyH;6}l4>V9g|q<9QrZ`;$l4hfMaBl@RJ$(E_UR zB)n`h)HyWxOCMRe_e9m1WZuU}QvWjk4U=HqF*mVFDqD(`#WOgcdXBI&IJ%_4i9TUv z^!{@+7fNz`!1|@^#a&m)fv14xFMGxdg)>-c9O&F7Jgup3d3v3DZM*sdZ!!N za@jqOi=-*O!W(&$N~UxF&p1GlJu2%IBIm^>AQiTxioK5yCq?=!`UPk9AuW^ zCs(`Iv<_J2uG2#pA<^l4&oGi|Jer{3pP8flMZIHgk>nPg*R=E)S~QC4anQq(%TS2n zd_DJ(aXQ*aE4D`hOTx#!AuT%DP@G--J5ba`8*b1_VB@x|O@F4NHdulz|2G9C29GHl zH;UVPF@JsPr0Tgeu%m%?a@@<4q^+kGXbxwJ|B04?AN_hKQ$1dPP9GzWXO5(|X_tFG zKG@%ZJ0Ov7P&z9;-BqPNnics+!zrnn^^wl7rH5`F(hhjGk@ZjCK~$`2-{$K;i2~czPTf}gZ{h9B%)h z_yfWc<&`1`rX_C}5pp7~?H!!L$-x9WIr zNXdA7h=0p6w4365(I`b%YN@2qS;thNlnz|oB$YMSCWTX#Gv3jKQzDJ;I$1pEAt!FN zWqn1!qtH$U9`|fZHe|}vTml{TZKJDvJ&m_9O6;Ri+$~`)O=nZosH97#m+akIhvkA# z_8mlaHR`SefFH--d)<-;b>6tSbemS$cSq!amqCdM|s!wyKNBSg+} z=^RA?HG7FRyDb6tFG3Dzwh%A#fghL`yb&Lc^Rs@!oeHSf5CAu(W(@G01b~*j5A2ee zU4IUMmlE)q1iE~gs$nuTV}&Cf@&mEiST(6G%+lX&mB|apg`SNXvb7whRQ`%Llux*6FtW~{;!=(JqAGx4c1kid9j2BW6amxZE z2O3fYfCZ`?mnBYh@xmD|)}4=a5%e>EGJn_#cbV>Pe^s$n=nO_#+LIzOhMO(%hfj~a zX7CKin{M<>$$NF*33S$L1w%$NEj9EG-)-q7a3(eQ<}2Tg(vsglqb8uWI)v^Ifm;Vu zP#d;ETbS5_H~0Zrzk^OPEvdx>c?ZOq-D)x$uAN`n{#TcxV7wYgf{najN9kWSUVo+7 z$!fo z28<1}TcFq0LF295VKn;yCOt1y{(t!VNyS?6#F}9Uw2|AF{p}cD5qX!z-OwzZXRV%> zUg5`}_0~kIMGgv{^0F*Fuh2P)}Yd{(_T2 z$rwS)j{Z7yrcRTLnEEvqFzR>sFDP3~iS)VAdcB~DGonvnjR#eZ?AubAfFfkum)*1z zz?8+aABM}K8QPO9R$fpj=YJLSG|~i~_$)BXf+#&Re!d{xCjH7{K6$7kG3K5UsZ+EV`Zn~ljU{21E7u4AmlL@ET*`^SU7YeHSJQ5Mw0|n}Gj6Ua2Q&b~K-!?%tpZ55wMOitKs$JE(cd zceJUzr9eu#JC&@PCYtPdKp_+;=3cF@rEeR1{~!oN`a&-IfIjZRaC^jrFXA95>w=!_ z1T^i0QtbxrdS#m~aDO#r?glG*#AlxQwD-X64ey3#dc>l9uWedUCOC_a~LCnp#40G~N z>Q+ksFKahH{Ov zOtY--ifc+bT&J3G4TI`bIc$=2a-0iFxNMytmmTGMnb%A<-9y;-tTsP71H3OoXTk^1 z_c=RW@p8K&$bT#xxEZ(!?H0lgdE&yiYF?BsAp_8_WeHJDV+3&qMRF#2XNw+jhD~}9 zRC!SBggX*{+52G#w;BBctN)?IT_MwDhf!*S^V&kX0e|4MwnIvOyIQgv07v3#?z@t} zU45{GF9V+WmAE3ywI{V~%C-wo4of%N%NLOG=|I1!>Fu8-F-pfz{+IgGHhep1E z_7+3b#0Z=@b!%gbVZp3AS35GnZ}93R6u+M zS7cq4Mi{0LX&*VcIl!?8GwfS2iUU)ON_~aSJb&9anm{EZ_upc=+g+ z0sV%$)4}oPq0kr8=*oN`>`LfLB`L^_CYU~Iu%yiuoLrZgCR4ZP7H+2xN2ia#fDW{o zi%u4D;eNqpyKvS?FboNPlMbd5@*irwdPT7LYUBIYS`+Jp7%uB}%BVAHU2<-3&JZ3< z4u2|b4eQ`&X)!Z}skJ0;iKpIbY$ck}?-<#sZ!N0dQtU8qaDtuDxowbjabFZKF7kHV zf_V)ML&dpH;=$}DoMB~LX>Tc|o%x4AE!gVzjBY^x+1b&!)i^lScA;c8w8e?mu_2*3)gr_Zhbf?lCQk%n$ z)*V!_%wf$OY4S`7Dp6$*#^h{%5cR5Oi2dm%k zT`c`Vsr5>0*Ke_HEKRgUK+n2F%fqL5iC0IBxj8SNcwo2Sr})Q0^azo()%yB)Y$lY# zrdha6v83=e67lZkTuGAHoM5UmTYnJ8?95mpYz*rXn*o6UZOC#jizfP_W@5=rO zZcKF*+{D?F@lOW5GvbZ)9antA(C?dhaQ;QA-ShF~<(qjh5 zXSbp##Dvs*9=OSyCCS1+2d%ip*yf>zN>cdGmft z?77TQt8x1R3qH;iLw61t))D&c7$BCn(#2?uK;HPWBoE0qZzmC)CXaA9?d331BUUxB zr1=AS-Wwm9j879x9*Z5=fG}cQBPUo+5Ia8m7=1&CXox4IaDUA61&6&w_YNO$co+#| zWlrD=AMh6xd{e@T`_TBMq7Y9Z5lmJaQzwN!C~ImomfzNF&%+Ji-#vIYCK%VZg$avw)0B=MXlmUhYg<{EJ#d=m8NCtA!0Xk); ztQ8Z6r*j%`DS!DQpPHq{KV$I6F#_h2^@E2WgF`%{zptS^HwLdC+_~YDH z0eFBKq7d|*=@kPoRq_X&m4Y<#vx-lC0&74KOvMf+@E0FTX!ymxD+773vc^mP1T+JT zM-~Bi(31YwK|~qo!^n~V`4hMUL4b}6Dt=8FC}SRf{Djhf{X-rl?aKJ4IU4ic%Fg*o zi}QQ!*MD}gohl+!YTlh(uxJ@bzxYMZ!)8&6cp&tSRFy6boj+Ol#P*wobMZDoiv5q4 z*I0E|8vf?c4?;t0FDuW1w<8*R+{jvjh<};Lj+c0n-sdmSk2hI#=*#LZHM#Loxva&# z^TnChoZUvtbntVS=C>}a?_AzS3#mmA(o*kX4S%gABLZDkn|jpwDPZYK`p-A}I$*gj zBfM&mAyk}it5D5kAt~D0py7jJH}BB){V6Poq7p>(<4GL%YX54EPlP?HYkVzlRe64< zr@{rfVX*i_O4iESPm?}yRa(5@gpCKShPqnM%)6H{gg3P9UXJJoC$;t^@HtLa^zic3 zIe$@WGQ?+%nYp$HsPn60-W`?kh84@8TdpXEJ;~Saf%Nqa6Y5!gZILx@CaR)l9@Hcr z|C2@mn}I}n>8qi4!QA^qlWxFB*Mjj|FEUx==c7xDybATIZK6D(r`hhL~2NlRS zEct;hzX#kLf1cxLh{XK}`F_+&AzC;?;D4xKn8W6qt5daAu;TVcABCx~dlv%&RTThhB&9|pX28<-z z`ej6rRhiIS*GsZwdf+%@vBBLmg)=NX>z}Hl$qF;5GiKr255p26C8k(fq<^_{Eo|1O zjho4bR4GxFN(vph#?1TD%7fEq|EY-JU3{Q=RH%EhMtUC`aFtAeo0H-D$#%id4^{;pCFxNTIx zp3y~{^f%BZNs5AxF{$Q}vVWl(twu4@8&fegfMGA^nu04&i6<_bL|GyzqBEj~)kx@> z3W=MbN7LV$QNgUM$VSqYiqY!~Hh(s&MsOl#*rj#r)0UJtXGrv9TZrxxd$t)gi7cZ+ z4X92QC%W=E--bTQI01i9HW5+^)}m`+w@!?rMru~5KMwDjo#n=oLx)I6t*jVi7?&!fs{CO1vmfN6x@C=kRKH zab@o5Y6&J{IV>?a-Vr}3ppfD|2+fV*%?TgbgOQd|)Naq&+J9vfOcz@>P6!p=f;euh_6?6kqa5F2PY=gcYex`v-VF4{M<>YI8V$0Dp<(1$6aip>CiDDHV_9_8v6#Ev^PCBNyZD0^uyS5L%shb z*@`s&4OEmqa*~Ixh@Oh8SR8rqx4tm#0u{s<<7G_-M&oC~;)S(4zTq=}n}_JxL{xkj zy=m3i)qigLkR&KLoJNj{i!2JYBWly4@e@^4FJ)zN`yY24$j}olUvVLq`;%wIepJF`g+^awhh~e zLQ57~dIqAXAE_&Cbk-4)s~zR1RYNCz?hf^nU(vapiSCG#@#J7v8m-2!-GzT-X-Aa-PwdNy;WjM=BMDG@E6y^?8` z0tz)9VkA<*`H%s98{{h`1C21;h>bzk%sK{>?b5p>to2eeRF@OV+#%FD4Bo64ceX_J zogI(X15SeS>3D-Ma9vz8!3Nh3Ccw}R*({#?B4PagY_FTXQtdzQUOEJZid+~{<$ukm z`;B#T3`_aGp6FNNPU8ol5p)UKoRd{0a+U-d?Xvb<^ufD}tm6w)5H2h(<6oi?KwdjI zQdR?n2g3}C2@>w=gJhGE7*>RSmH2>;c401Lf4nB7A*5y+(y3+xzc6~W?d$8*Kq&Z$ zYo-xeCav>v^@8?)aZ5;%xrAkpn14tW`y7`VvafLnb&A_`hS1_kUc)Q60opWRDG*vm^+`|W$w)y}e>9SJ+isN%J(><}+7M7P1I;}j!DZGavvhBiS1qMps0+{0 z|FW64uDR9`S&z_E64TGsylL%HrIL~)$a`qUh00r!+aB5I;j^#x*H9wsl7Bq4n#ChS z754Jq#WEhE&zF&3Tq!;gdjcOPf}l)DtkLbYQ;QxN+|7uRGS6MN-7=lJq+i8R;N{cY z(%I-vbWV#R-8$Pyr{Bn39>fitqTL3+0xcFK@lcrYejmZiI#No+UCco`kE`iSw_hfe zJmij9;yf@@yWfYrQS;r|?|%}^WkxvSQ? z#F&0s!Y`%zO>Y>Pb6WM2iF{&SAInAr$;G&D1(_QQdHx`ePr@=*zfa|!AB)_heIfYl zS0^|z(eq!?3(?RM2!Hni3e*Vp{4ZKTP&GC4nB&~VwW4rOoZ((e=EeFK0jHNA^=j zlyCMKkGJT+=UOl(G)3<*Xd&^+N`TL`J(Dw=1SVT1(*o}utu0motV2=Z{6RgKTPLT= zNyl!1%mwcuXn*~1Jn;%n*Di1@0;BqbsG%?7hX*r-u{2c=p_*$j>LwpPfYeSvmj!b? z`1JP2;Vh25@yOOXJ;@q$z`=%Vy|Sa#fr`{sG-)jhf+i|wwc9hRjF!5On+oQxu?q<=o){~`eT_I#EYIZ zI5YFc?UmDm(6sT%?wZ$rFHGTXovLhI8eWf1*ZKPPS&;KVs}-Tn}i8SUXRZ z?7RZ~%$0thIJ;2bGmuW8fqEhFftvXpK!bPoa1VLoz{L=_d+_=eMeIAn;B6`7P(K=( z9+;eyUw^c#p@3XP!7o5RJ}Qy?RFbx+FBKUjon2S^sDx1ZRqDHIAg`FbdrA}2ocx~D zV_Pra7xuJ^LC25d6U6gV#JeOzf3ccd&~~$b=FB{SE6pu4B;eZB2%D>eccodDrKnoG zQ~e#7mHZUWD9B2}#X7M#j{3SVOH-A1t`T0=vL=Fn+Y{T#2+VR>VEFY7Q z?+#knGZVhjfI1I;nn!DQ0;urjZM+a0euD$KL@*`Bh?!@&DTZ90*rE`GC$xuOlzoOO zxqp;9`rrwDyTkK@M!8#@d6svE{zmEw(5+UGN%Xnv+WJPJ&C&D>y5rWLv4<$ zD}M!VkHb5*d1lCZhM=DQC|3(N&Pmgnv<@Qm&a(?w*sE%6hb1JoW|MR55N;eSPZ027o)QZeRM9ZYu2T2DR~-Txq3 znJ0{f9~z`r#;)EIty^Gq4sKmg9NuOeUQ1qmcEs)~vVgTYb7~6#Ds|6;ITvKql|7cr+P{F zBAf4qWx3lI@M8y8>=#9`M+7w`fNBrFPj@3S&JbZcB^r>--BVr*Kg8H*+kY+>KO=SK zSrKb#sM=J%*h1Rghk>?scEHJ(~!; zJr5bOWohRGRNLXO9GPCNlAN@Dj(}?ld7WWk#=FUE*9!Vs(Zg%vqJqCkv zAXe&?+%m|CS#KH2zkm7^Tzg^XsHHEp*<=F~vW9lMEXvRRW-?R2;2e!kAv=#TFaQf=o_ zG4DIkCEU59wi9@03~A{|V^0np`XC1ypFKSs-4^DB>ym|Ym4B~CbNfZ63+e`i+sp)B zJqmoe7o(a5zH;cWJG7DmYQ3C?)OX7!UDs86Lp)p6jsh;Z%ThV!rpb}qHDq6te|WVH z-yn-iL~n~iiamj-$|0;~`|H#;tpC0M&4&3P4z}$hq&>cKSP;QwaoWkk&U!o7!qWxr_C;{}Vu

!&{InA% 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

ui3eaM3v_vogQzqy~ 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 EKVnIdjQ{`u diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 220c3af253..0877703d86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -492,13 +492,16 @@ protected void calcMinMax(boolean fixedValues) { // additional handling for space (default 15% space) // float space = Math.abs(mDeltaY / 100f * 15f); float space = Math - .abs(Math.max(Math.abs(mYChartMax), Math.abs(mYChartMin)) / 100f * 15f); - if (Math.abs(mYChartMax) - Math.abs(mYChartMin) < 0.00001f) { + .abs(Math.abs(Math.max(Math.abs(mYChartMax), Math.abs(mYChartMin))) / 100f * 20f); + + if (Math.abs(mYChartMax - mYChartMin) < 0.00001f) { if (Math.abs(mYChartMax) < 10f) space = 1f; else - space = Math.abs(mYChartMax / 100f * 15f); + space = Math.abs(mYChartMax / 100f * 20f); } + + Log.i(LOG_TAG, "Space: " + space); if (mStartAtZero) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index b8c55c40d6..703765fbd1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -7,9 +7,12 @@ import android.graphics.Path; import android.util.AttributeSet; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.utils.FillFormatter; import java.util.ArrayList; @@ -26,6 +29,8 @@ public class LineChart extends BarLineChartBase { /** paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; + private FillFormatter mFillFormatter; + public LineChart(Context context) { super(context); } @@ -42,6 +47,8 @@ public LineChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + mFillFormatter = new DefaultFillFormatter(); + mCirclePaintInner = new Paint(Paint.ANTI_ALIAS_FLAG); mCirclePaintInner.setStyle(Paint.Style.FILL); mCirclePaintInner.setColor(Color.WHITE); @@ -263,9 +270,9 @@ && isOffContentBottom(valuePoints[j + 1])) // mRenderPaint.setShader(dataSet.getShader()); - float fillMin = dataSet.getYMin() >= 0 ? mYChartMin : 0; - - Path filled = generateFilledPath(entries, fillMin); + Path filled = generateFilledPath(entries, + mFillFormatter.getFillLinePosition(dataSet, mOriginalData, mYChartMax, + mYChartMin)); transformPath(filled); @@ -469,4 +476,45 @@ public Paint getPaint(int which) { return null; } + + /** + * Default formatter that calculates the position of the filled line. + * + * @author Philipp Jahoda + */ + private class DefaultFillFormatter implements FillFormatter { + + @Override + public float getFillLinePosition(LineDataSet dataSet, LineData data, + float chartMaxY, float chartMinY) { + + float fillMin = 0f; + + if (dataSet.getYMax() > 0 && dataSet.getYMin() < 0) { + fillMin = 0f; + } else { + + if (!mStartAtZero) { + + float max, min; + + if (data.getYMax() > 0) + max = 0f; + else + max = chartMaxY; + if (data.getYMin() < 0) + min = 0f; + else + min = chartMinY; + + fillMin = dataSet.getYMin() >= 0 ? min : max; + } else { + fillMin = 0f; + } + + } + + return fillMin; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java new file mode 100644 index 0000000000..0fe37914b3 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java @@ -0,0 +1,27 @@ + +package com.github.mikephil.charting.utils; + +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; + +/** + * Interface for providing a custom logic to where the filling line of a DataSet + * should end. If setFillEnabled(...) is set to true. + * + * @author Philipp Jahoda + */ +public interface FillFormatter { + + /** + * Returns the vertical (y-axis) position where the filled-line of the + * DataSet should end. + * + * @param dataSet + * @param data + * @param chartMaxY + * @param chartMinY + * @return + */ + public float getFillLinePosition(LineDataSet dataSet, LineData data, float chartMaxY, + float chartMinY); +} From 192dbe0fb5297ba98f0942308b1cf463116d0363 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Oct 2014 12:35:55 +0100 Subject: [PATCH 0003/1390] Minor changes. --- .../mikephil/charting/charts/LineChart.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 703765fbd1..d5b14c2e95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -7,8 +7,6 @@ import android.graphics.Path; import android.util.AttributeSet; -import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -477,6 +475,20 @@ public Paint getPaint(int which) { return null; } + /** + * Sets a custom FillFormatter to the chart that handles the position of the + * filled-line for each DataSet. Set this to null to use the default logic. + * + * @param formatter + */ + public void setFillFormatter(FillFormatter formatter) { + + if (formatter == null) + formatter = new DefaultFillFormatter(); + + mFillFormatter = formatter; + } + /** * Default formatter that calculates the position of the filled line. * From 3a1abec3ac0220c5f38562223659ac2975c75f93 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Oct 2014 12:38:08 +0100 Subject: [PATCH 0004/1390] Replaced .jar file. --- .../libs/mpandroidchartlibrary-1-7-3.jar | Bin 1275538 -> 1275770 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar index b4084d2187ced5c0e811bd0daed2d262fa773832..e6c40e70e0c4ae351a4c52d41216a430acf10190 100644 GIT binary patch delta 126697 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

vdqnBaOK8 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�`{ggC+N57LPm;Jkl0!Ft2B<8&G1i}Y`H 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


1tTuG2L2<}*J-+~*nx)#bF?Pa>%zD0{ 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

9+L;F>>}b$}~ZQ9}-JF+K?y;DqZ#<5seXjWiq2V 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

Y0R6Q>K~PdNhGTKEjf+2iQY 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%0A5T_+!58yl7DX9LKq`n);v_FlE#72LpYI+^ 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

VsN3uLUkKOteqB{rnw&?FJCI+S+5c^8xq?n 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

*WK-Xujy}Mqj>mON#N)3Fi)Uuv!}V z@OoOdcYc0GQ*NjkqB^wK^=lROjmqVnE|h!_1D2oE29eB?;@24YG1#*O{e!fX#S%&^XVPmv5(^}-I)Eb&qGVQuBxvZ zKXzoF9;Q|@9Qt*rv-=9B4m5ITKM-*Ge7>Tl zp~b}puD;L-p3$>?$UK#tE72r$((JF{G_JS1iQp7PC1q_)7|<%9t1P* zUM-n-byMc8^(XVDGcSY8d)cO28&1Ys_cAP3sa)sb?=)#o)YEP+&P`jrqd0dM$h^O- zJjsbK7iQk3AoET-aei>m;jfJ|hN{e@FCRCk;eD?q@ddwF1Mc4jhPq{*JbTC&>zd(e)Gsl0-ZJP z#KBdvG@7a^jb?=bI#rPzs2ejJgpypgz!66>z>iK*Y(A`O5o0k~v~$!)z>m~U!lGo$ zm!CR07FS+auxB`vAITPU0uY1#V)cFFc0j;GWnp!>v4kYKc>F!T5EZ|bEc0eUQBuHFt6GP74SN^3B z9FqywZ-9Z^lP6;B!~m1!{Q5G$zV!k^Hy8tObGX=oA=pN0vz@>7WP>TNtDUrHw7wWT z{h}z0K#R#1&gdWpuKK0ltfPR42{_Fuo<(7}d0|mZP8gd%n#~Po^GO&ad#HWCrvOrv z6e`$P=8BRQatYDzHJtewtaiF83RQJJg}OxXLOHCF9BwO1OBNh-!9bm`j1X!pCoq^D z)fZJ}E8TAyCV*ZAy0E{$pB$MP{H@) zasoMF!DE?W>?S1eTQ2;V?aGOaVuumwJj58{uRG=dfG-a)4#Z%LSV4u+F)p0T;w_I!gBMl?~$J(JnRFfkaTY>Zj3-!XD z$>jzxS<{Iz?y?Fq@c|jj3@g;8+%1$$Y)Nd&;-s270F4bc&;6`2KY8(l?Ule!#IX5<;RHlH`-0iauV54B0q-^fgZTMrD#W(YQ9Mr;AGpyb zvtrL>hK2(X6?{g9t*%!pHwK7}pDY@OjyX?-4QlvUUU+o4FDERJ7fa?%Aqtg*op*Bp z7lVLDwa1_^s-W~D5InrD(Il8IoG2G&RP(3AssNqg^|L0OQb4v*>595<>q;twQ0802 zkC>QC(LrZ^0%BqTzeZzV8+?+`TEdI?!b=h$=%KcljgAVb#=v6MfFRHrgLTap39VMk zCtTr2g6ZXU#CW^dHWqk+ZCj^+O2?odRCqnuk-TU=3#$giD5jszAp}|YaQak4<6eMh6JXj%45I6% z67Bz(Fnca9vN?FC+N2d~=TxBQGnPd)^jjYZHIyX&JMCO*IuKB$Pe%)w*ZPYs25_@R z@tHBe;t*r$ox-;>OLm{k_3>ZJ7JLI4*M%R=NT1Ek@TbtwCsNfh`EabN?VN`6i`*)KCCHMnMG+OcwpnhqFi}Q0T=naU|{zm?Uvl`W16fFyLvw8Hl)qA6Y>rLB*%haZ zx4Z&dI8g>o0^X!b=p@HQv-$B}?6@d#9OYD&eqt@4`V*kq4ujV-U6L@Pbs2*dNp7vK z>6>)=0HCjw!bKfx#MXF3e-}eYWHAw;W z0b_PaBK;&GqG3>tJP<)=z&BS6^x(acnK9zTzGc`Siut&Wff*av=txbJu4ns2hQA`s z^E2~aJ&ORWUoPESZnM=(6|9=@}2AFPV0pjCrMkNzr2AlI77em-yE zn`-WIXf0Feg+#s(q7bL7ubslG)dC`-h&x00`bymFj?wxDdoBlrS;P);Ok%>$=K%CV zfN%l^SwchG93p9`VaJDmN=$R{%Z@HL0n$h*)Lp)M^Dm^87^~s>x1C-BE|JPG#LC|x z@{ftf^}YdAccjoncYqXKV&r0@<<7KVTqGGLTunzt z6k%}R#H)uE9rYRkG>#S^gKEGT1xh+Z)*;>#P@%#ewYtSSFr%2B?5HsTk!*ep+2(8s2^v}hKs!pI zZ2(bvl$%3vx(g-Ij??mF5*nsRe~Izj0Y@mSpfUd8Zj`u0g()IarCIcSyT>WgXd0c+ zD7=m#A(g}kd^#-i+5^CSr=f@NsePyr;1XMs;PDA-&p~*>ItJ*`Pz?N>zT(S-eFzgU zidrCMC)7B@(oU%i+E4bpzXXC#4E$_B#L?0|G+Ovnv_zjhKwL#7hCI&s`Re7c4^sop z;*PQ;v7yA0`!@R!yQIlM@PKW)_9r!lD$ruiy zeTH#}|3}``ivZOqK%O@Sx$Dd}#UaF}kW?9uX=wKxLqPuzT-=(GAYrUvNqkm3Bl*N_ zkfGA*rBPSVW0oXD5}uzy1h-E-o?s0SNYl~dpU`CSZ3PBA*+my^40zeOgy2KjfgC38 zqROlp#|MDr2-m)*VO7?;<{=lEfNP8v^Hd|VUU&?AB$E`0y`kDgBlmtC2ggJ zn34}4GQ6$=j=hsZWk++hIGDz=`9VB>C|Llezo_`Y9ze+LE~xFYUoQzE#LzcNIrlgZ zwm?%3-G*_SB@!uuZHC+M`p1g2m$1!P1{J9p1#K27g6tOJ8n|NdoU4GAZ@BK*t6STQ zi=ZtF@@?hV;ae;KU5U8tMQx`zxCG9MJOzW~luo_%<{3b72B(diceR-u63u7UZCMX% zXSPykVc_c?NpRtdI%Hu&CuBgVtY99wMb5crdnL;(-vd zJxG`Uqnq6|*i_g)L5#2S*a0RD&+Y6KgKB}DjVX9*lA#MGa^Q-4L%F)KFz9dq6Ey5MBh!(!9dO^C4|fp z2G_WdV9S@0d_#~V`)Z+g!m6kN!7!c3^1x_lcM-)|3F?Z)DNK-QSgBBVb^#ksf@&Ah}1~szKucK^b)P!b|UKV&kKz)IplM%cUq6 z1A1Il(3Z@nRg^dcc~cyz;Sk)nY&W59qymk$Km+ZT{c(#DHoP76Cx2+J07iv)M)86B z2`0JuYp?6B{|#`9E`ws*Q!j>0F-G!$3c&B1GD7m&g&;TE_|yTmP+QF7qweGp%on!_|=*3V%n-Ao3X{0-Nc zcIP7{5?|(Yc2G38wO+6}q}piRP{e)+Xz`Oq^MTTD63G)mj1J+y8T9Q+Er6Y?fJRqx zKgG7h#GtEdHur*~VvKPm_+e7gk}Tbq$DdBsTnQccq4D8E;7QXkMRYsjq$!a#qiHgh z@IUZJVwzMZ%{ej`&}1!*b`n?1Q=*}ClvJ*n-S_g9D1fb49um8@)IiLjAm1tH%Y{k#DDoib=c%??w^cZc!EPLjnD5M{vD zhS_%kf%#)u9(i=iQPxy)1Wi|(s7_6fj=R>k58&@j8MHuH94Kn#VL_bWXuhCHnhb@-@oI;Q zoYKQ*A#GRY znb;x0!b6V_qbh3w@GxBOoWgVpieP6(6g#x#MyRLo{}8_5>=+jg{u0=wIFdVPoBb+T zP!)`UW15J;>d&Pn5&#Wn^P}SbycYMz(As;F|CVeJ0hGqE*>VXsU^lB2&;Vm7kAi+C zKbRBN`qY?8Fx3~2nQ9663s3B@HNjfGSSlq%#xuV8!Sh{NG_y~L zBFE&yj&CKL454)X`Ot^Wj|4c$PvOt&xbD*dICXJ%ah+q^EU?t~)7U)r^l1R)X53ZG zns^c7BM3C8M{z(#Htrg&eFwl}N}+Y*%?aYF1#msB)q%SE>k#kO_k$`l+6!&eD!xsm zFy4?HFJ=H76hSbf32VEy||!9|Ra=PDg8s@0W@t z*IqriFDtjwcT;l*_AU>SHB*0S1i`4hN@Y=r@ z@QT40_^dQ?_=MMZT2)Q#*vv5EyFS9Uh35Z>nCO7W@6|h-F2-RkV(Kcfh;|MD>9jc4 z_U~_+I!zs5Db+v^6bjagtH{KVEl-u*$^tZ8kwsgUHL}HwV;Gp91Q#QkPY#Ky1(0=l zxhCdk0g|awXwAhSR~(@PMoHL=BuWDyjjZdzMT_Xd!35(m$h`9;_l^v*UkE4rK< zox~1>WNjf|1+%qu;;NMI3tn%p1`yzJF9$0ZV#CD9f9t-XCUQxCPb{wRRCs&mZ)Y>X zl0Y;`^TaHxV?mpj)lyAuC0-=)(Bu3e=KesU(>ej?hgm@Xt!-L>FqtRfi10V$o?dVs zxTaz*yw;%ztXC*zIXb)l^KGJDTDMcq5&OZ?et@kC!Ys|W=s)39vrQ$B<_{J-2HF5! zb@(;Lz7a;h%)~ZG>M1DcP+kXU0lL9Ko!Yobc#D5}0!a_9hf?z?X^kB_l zSpIIHqc{Inocag6qN?;-#hQrXwB7Zy+UTs?ityc{Hh^sC__4}7qxN5uO{_aq z%ADWTZQeFua;=n52jzY5KT~FMi_4MLNGJx(IxdZl{Y!cH*9uH_Y6KB~{;)#}K8KNo zn^Jc2ahnjgDglt%c^8>rc}oyYAMc1(i&UQd3u=kCeBDix=P)4hP^HlVFjx;Y{6~g? z^xhj>&&SN+W8p26gMbq}%zAdc|IdRGp#>#h+`W$5Z^J?1Og$Qnjai(@r~gbp$n7Zf zDOc5OraT13L|Fk1YLEQ*NBk0Ug{YbXE!r`ijR#JH1snjOkq>48dNi4TZP7?7N?v_b zO@_z_hxtlY=vz8rLQo#vl9t{D zEPe}Y!XymZ)jEI8X2Qsu)MO7_u6}D9*zxbOXeRkX@9#N4=-()%P_U*dn{n_qxwi_) z9WiSf-2Fc{S1mq{%vNo}>94u`LW@*ce z{sVhLU8HcHa?1sl=UG6?12K#FZ1Nw8R#WIiwsYGb&78On82bEf=yA~zv%l6mVwCPb zcFMtiS9@Fu{Oq8A;9rPCB2jT#q5eY_%=~SD(oe=LiZS><5EIIP*6`x|Vi?d?g1C{7 zS1a&Eu({J$VMh|CU$8PU%eQN`nu8BU@$BSjfoXpExBl^^oCg zvXukMdQ}@$*i|F{Gg+k+4&%uM!{I$!4=oyPDrQBd?*EOWq*_e`EZpK@u#_#N1o$6boDwm4+u;G5Yus(btO*tM=C^CJA>%6x25ca_mR`-s6U+T|4-3N zRJr@MLoQo-8Jp zJ&GL}70qWmu%p4oUmU|PBWJJ- zQ1^(Aw#P-Y+Cm-GRJeD~dMY1)d73(n=8wS@%BJ2)lCB-dN$R#8Vk6MW|5X%hSPG`2 zuNQ6SkS~O4>IQ`RJ@BDPFc1=sBI;#$)5)PC%`=cBv07)Km+^8?T+jnBw1X15d85P0 zF;bk(lQb0~@av{2# zi{$Bsl!Nn*T>xA7K?yw^H%k$*62alPTf7AGOGkVx>lg$ty5R2Y1*VHKY>*I<<9K8u zc&p)cCUaTzep~O=qNw3h1UT?Mma0bo`bS{#(YR*GS8J(NsHHDL#2~GgC-jQW0Ti!r z&5{-w;%tWC-_$qR{8y(q+yE48Rz|x!CTCG85Of^mZPS8hJ`GaCHUZubkVD%rm*FmJ-cQ+qmkKc(=5#L+IrovVm&4KoS2S=U=iJ9gs-Bve044p$C;2sMf<$t z*WRNE8&|Mt8~a?Fk^}J*16b=1(=y$C0f=HeuCP&hzD;JI@)!yd{IyPR!B%*>AdO~Y zzb{enk_|Utl*Z#P0QzCvsPCMc;s$~+?I3P;_vJIgNvGCkgnnzk7a;mbLk)5JTVkgqM1l_K zDj9J&;xGWEgu5u%{kCLQi@HTtEA2gJ6xeVEE>N_+BQF0Ku+am2(n@>C^mol3*cNiVA^X-)wrj!_{(QfvSBsehwH?550Dl3M4 z7JSExQ1+KzI~BbM!0oAmUQL=5(pK3gxj^vza#AJOhkMd! zIVPm!((GEqs=dHc(-OM-GT3e&q=C*+SryhM0*U#US}xxR@9dAnMXf&~MeKVk zS4H;H=#&lmmGGtQgSacT9bzbUpU69lsA97Bmv@~2EUg*tm8yraVrh%Bov0)mvg^lo z&;I?JUK7E_!kZE(Ob;4{69b?1Ztm|Wz%3PNwEWe7mMD+WD#s$L+8Fq{pGXC=O1bD*0fcR?Ew$NkYiGT{v~Jg!j0y+(2=l^hd!xq}!>y7ywOPg24g z;n>!?GwE%?LReI3eOyUy?4*_iu7yXVa*Aj~>#(Lx#*R3Q5z)f}E!GFCd%MR0ru3tu z3ch!}*nXa9ehgIbVrB1wB4DIuXrKe+r)IWAHwaZ7imKIl--&P*>~!4qpcy&jh$O6Z z6HC>ei3cywhheWQdbh1-o+QB;O!>qO&>(MLZ(aAG5a3;aYX$1DMG{BG@Z^LAb3y7G z#F8L*S`Gz9M?KWnU<6d_b%frq8B6w+E2VD5JS;>W+V?71To< zqD&kP!%NI(abf8AJz`nc=0h2AY^(~e=F?DkTa%6+uo>>9ke;^G6o|>a)Gp~09f;60 zT-fz+pIGFMwiky^lfuH)XqrE4UR6UIedpczuR;*A zvf2$t^>c8BevK5GG*7=zzLwT+>k-4vRULE#-Wu*Ijh^a!e$eJ3#%OzTGZ)kQd|4p8 zAR~`Dj~5Tc4w(g!fT*w;V%s^PCif<+@yny{T$VifXGT?YKEmcr*hB|X)Wr;Kd((a) zj+7D?Ql@?XvIq%^vJOrU9N4>IGIBC@OK(;2}E%^Mrh!_ zRfZZB(t=6FE5YL~)6J?w!LIG2qfYjo1~sBq8cqGO3#7-g^R3%TO)YQOx9|3~Cr5)1 z@|$8qF~fX;FmQK-%xXHk#dfO=>PU_m8*PgyC0$invk{)X?~z86Cv7dUd5Buc);uM5 z;bR~kn3-9h3`o(j$j2#z7T%sM%?Ks?&a& za5@*ZI-{dcj*_CvK%!!uw|m*bXK9zqpvHet_qJ$rQ$bMD2AKJIfzyb4$k!W);_#my za+3D7SDufuxd3dn0@}#>r6)OP2?|2f?+gleh3|aHq6p3yQ?QVzT1y;beLQ!y5FS=d zS4I!4B238B0CwiYa{yy++<34x z=2V<$-4P2+Ov~vG*+D%F9kw5ixDPMZ!MC`uDtOVNEvi9uCIcDEaeZl;&}3b(rQe^H ze`Q@r&t}f53_lOw_=C^oVlloPBsLp8qXWD-;_y=Nq~9loQUJhag=-!%vKGfe6F5}Z z4B9KNYYsfp-;R3{8qrI&K{+69Jh16c_#O9!HMI$=gZr{ZUBNnPWKegi?elNfA$SOYgd0yk ztbe5gc9(-2EL<|at*fvNiwDM^7Zyy6(q{OQ{Bl6_NnF>C^F(Tt-ccMbr3kgN(<&VT z!0M}`B@!-^9JC!LkTa6U2i6ZhAKXkAQ*enH5Ee@Ql$yrlLniRa@~OCcmz}5mlTEbc z2J`rws1TCl3)M~mX3>CPpAP6Hf$-^K5=;zul8)WyLja5(uA_HYR9guniHxsn^~&1; z05{N3d6*h4?xvA|?mj3lH4f-l3~qi`a7}iCPqp^wh_XLS;DKUym*%ezB0q{oB=rMQSB#BXw#)$S8PcnA`m=9@a z^xJi|q|Bu1r0HLF)@?4JWRg5urZP_!gBsHH+l}kiZ&=fN6xbe1)%jw;B?ijdZ!mE! ztODb5$()7aYK&bphl{zG_a}0Ib(+>7bukFmEhR({%x8v&0CDY06@&D|K)NOZQXroh z3m>Y&1tc!7#(zHw1W#24J)`cpOiYjtP2aT20{?tO5ruwVzp@-`!w2uDhqV2_Mz?(RW2#m%CNnQbl7P|64-?UckWjy!Ke%Hq690|7ac^ z(LC%y#*z#|oR~os@Io+$g;hRSqJCt&b}4*K87cxcYP})>RP5*{;fDmX}Jl@a7$ zjM?DT8bwtgE?hZuuFTk-|2bdqtr2AI8yg6G-A%Z(KxPy(0Ju|}*ESj%KMbDypU2HY zFyBKB$)V{R!t9T1vDz3Eruzs{g!4Jb+tY$+FCl%qP61Hq+GtsZMF|G}do-IHE*Pyh z9k85a`hT|J`e9=L7tZ6F>U$g)4?Z#61+N1?Zv{}`LvGksw)3aOgG-b~L5?g}-t|6L z1*}gO?MvnLj@wJ1F5%(C^#Vca2yVduUdJc*48{E@E3Ixu5G|}x%xF*r| zlH{B#rBrLxfrXol>zb&&Ejc+tT;$Yje3H2Bd()L|?9*C)b&?4yqd(d9&shHS z4ra3A$)}RkZ>;XmfY%>o(LGd!vmi&vS`d>@bNDQZH>4s4z%Vo zA#zSr(U?-&x?>=<|3VE(cu8W-C$%6?9>Hk8Wi7Fn5n!6m%+>}PA=nVhWhNZNe<9V33 zVKpw*!H4^T)%2vJd9fc&o@_N?kj0Fo{s#)Eck08zB5nLoYW@>>$Y! zNF+Bf(_E?w0E?DF9|4-yu?>`gT(Z3!4k(rc!&LD0rF9e1?6K(`I-gmTjc3t;nQ>4<2sifUYdsoqTznE{qo zT;+uQQu;>PmxqC!9E+=GfA20i@dSO=WY2+P!-ISSLS)SFa9nu6SZlQA5Riqj3TXS# z9daNe`OM%@b{NpvfYH3jD9Ywhh{QW0R2$ARYcGSoD)glnDH7WzmW&C92Widc``Awf zef0!QWpFckX&s1B1{)DCgP!d=nTW(n-mfO8=I7czR|Ev{an~$%o05WVDtu8X&*ve@ zS+Eo#i+kQ#qYo)u_+&g_K5Kf@u^I#YfV?N=$gygN0|qC4mjgO-a6Nt(`jO&v=S6XV zQnYGk6ihD^_Q#QwTF!6p2Ct@6;s)n6nv>#jTybN`Tod`ceO+3o6|WC$={!kx6}4-|`&$P9V5 zJ@Ct+p5PB-Ijj(3u1;U@XblZMMj?fENF5m@IZg(-MK#D+<~3IiB$6G`Te1e$5{L-{ z{}IG#8_qHBM_d8wylmXwAJ95=!dE^hj=hmXLF|FreIIm1b3N1D*aFS4T zNE#_S4R)`70-$e}MiYPxXOZUi&-)t`uiamv9emaq2!6ISdgOoKRU~|}2+8}g^a?ky z=%sXY>)pn*QO3j*ZsVMHob3QFx>}HuGg+`he zC;Xj%A?_z&nBTc`vuPM5R-yF##dN_G9R!e~ic@p;rl|q@*Bw20@R=ko??~F~?l|1g zZ<n1r7sP1a4%M3W3E0XH?a;`p zBIEDPHC1a*!iGaV2ZCMeh#TQCB=_&^8pT#ZMZ062I?AX6jaD-VZA5&rNdl57ut4%6 zb^K&*1A*M6jJDIn9TrC@iJ@L|Ox-saFwImJbvuQ}B-t)IPB83wByn(p7h?3XPUr&{ zup2i{-1VfGZh)Bm!TOH;>j2DRT=aXkR4fvjcG{N{6(Y0>BsHi)`*q3hzz+D~CPmTD zO6&|6@Q{$0Q^WG|PicWY`HqVZ{Vzxq9}Xa$^)CHoOw;>AF>_*@&!M(XFzP>jd!U%_Tz=k&B zJ@M*dws#HK`v;0>#kFsp1QfLrfTl_Su}pi-y6g;V_$9aye!xRgbav73y#Tm5#F@?6 zpUM-ofSx~7LK_1XJeDxC@#F$R{B ztOWQaEsuKCS+6Lz2-d9xWh9})}ZeE-)JZ5nN#6&hx~ctgG^K-L5TCw%sd zct-vD+Ybrsq`W2Pc50`jszvTu$uadF;g zEGcvXbtg$Z`GMocT6a}G16O%CW(m3s9fP@utXrF{HUlJ0CLq`!gB+YSY>PCPHPLszD z2bvl!QbX){z;|#+Z~gAgducx(n8GsLR6ze2QrL*$V2mMnmrL+El3r2A=Kxf?6k6f7 zi6aG$CM(3C(|;bUgSVHmWYNefIbIxLWwaJtSnwedURd5cq?%Z^0SGQv6&2oq1POMY zEIWWlrlTBeci#pqGLS)ow}4~`P>8G-C75|@xd5K!%c7SwHqR9)NBFZ8GMjj1thUEP zKn_<1HCsLl+F-We?w~h$Tcex3f?;_EzJ1UMRn5Xhf3KP%GM_o~)6&ggvppS+CZDe$ zMUJhIFoZu+)Zg}=FN}q=O)lY13}&uu14En7c?8FL>_EYdX=2QqJpyj+0(jozEKf|j z*b+k`CI{8~Jcqq4CAj0S*{eib9!d#x44V}B8@v>A7FF<}?Ey^aoN^8s(*i5ig8I2JpcxH1N-R!$>&Rapb*uW@(7&h3_9FIt@w zQdj#{URrqyT2m(()N@7@iQI=j#RD=4UcR=#8g}o%d$QOATwFFk9IZU9g3n?DIzSIZ^EiBbx>q5io z+ZY;=@6D~l$0OnR3Izo;v95X~i7t|uzfqmeK=-{4*GJ|0tSvzau7=O}Ga!bnIsq-g zg_EP?&jK3n$)Taqmlu-dea+?o#79w1VS#X!JU;Q%SSUCH(v3R9O6Vcn<@JGYL~0jV zak5}encgCh#=g-)la0K0V#z%ms}dIF!DbSQAoKtqN_M|}u12F>(?^ql<=@43@=dKS z#O#4+!h&XRf=vV+716ftS|!E5DM~U(iq^z6Ysl1oA=x&3Wg4x!E@}r=)Jd0uXDX#) zPu*>}8y5QaNuhqPzKaCpG92RoDpD-6`U4-s6A>Ej7)e)`6pL8LNFtnJTIz=@hF~`r z$e~rV%X*}UiHd;4;NNk1UZsF@op28|d-afjdw_X-CfQpzj9WwCD=Oy{P&+?^L5hO% zfP^uY&x<4R=~=U~hQJwFY~1TGw#Fj)1>`Lkh3?PX zGJFIOye>dl$6|2l50eZRd4nN&)G=|uNLx67e=BZMS=|VcqTierwbT$u1_>QZ@zg#H zH4N7kde^QkazZxwab9Kpj3Byj1{gMB`r#n1 zNi5%DZ=)>W@E;hXmM?pZBzo)1X7b^Y8nugBZD#E>u*pSX6W7AYq}VXw1#!3~m*A>V z2=-fE8g=3WnPR&>ieesAoQv&rw#@`N@(&XqWSVW(|3CAXm|}zsDQ#qPp(FAq9m>;@hg;k4Md45G5lGz zH-;7hxoL-c$7TUfTpcFqz}y(}CKqIn-?UJvTofr1vLGO$erHf{@A+iJw{~FlGjQ+w zE>99`hp>s3;5YH)CC%NI+UIM5Aof#5J(cR5Hn@4pkYcOjYTjNz)WTgQ5{1!mn1pqLa|njg57sYx6`()1Si%@L%Gj7Gem~AO02Imd}wvOLfs($emm3 zQXNTKJmbKcJFp>X<0NzvoLr&Er4xgUC>|7r*HO$oZv->R|E{Qs~%YLt?;PmlQJLn{+)C(7pKh zmNNRo^`sN;^{Tt}?<0U|%2PvYC~H58WD9ke0E5?e-8esb!eazFdR`IyUBck?Pfr`k znWu^Q@-VOg^E#t3&!-=fJ6Dp1Vy%z4o8jekIaCSD<&`9B{T<6;!B-+Ej@Q|jt|-7_ z035ZCRgxMdQe@~!&zP`g8552-4AugYl0UQu6C(75P<#L>c&*6)p)Drey__)LwAG#Y}w zv6KuxgR;pSs?DpBtGXltN!uWY9%IN@k>Zjt=c6v!KxydxylZGZ$iPmtNBzJ25OR5M zN_>bxeo&jE?gSXPN*=YsL+!<3B6Z|`bfMDVmjG5L+(q(-BPCJLCdWeVP+&N`aB-R@ zeDn1^?l$v~(WJ;)1=(b$Efx2#9Ni5p*}yKS4wgER!bNKeB>d@F@?IBSJ(59<{UtB4 zxKEz7!%(Pj{kC~efP1~Df*SkLzLH6;h{FHDpY3N42XyqrmA}?b5^1JLdd2?C2!OV# zHAEc@{DD*P@R?y@yeNVA^hJ%Hv`&?$CXkQIQfMN^qXuLf6~*@;if19zsvSQ+5JRnD zQbL7;lSrZ3t=3)xAC0P(LhBK>Eb6s3JwrkYSvhmuO$Zsz(!~ZxdjhH1$pryEHii`^P>i~+zp9MF_FQS2pE;<0ni zxWdk^i{Kwa3{aIB)IbAC7kXmuX+2Fs`xrix5~e+mOCbPzGcAIl02JcD-cFzv0I>VS z_n#oxj%t|)IuKfh0ZEi#foB&45u^*gmAlPelTZrsW>G>OA4+Z*VhefU#LQJnrZ!|8 z5QdO~Jxt4!CI%ZdN3>aJ1y)v0Ad&PGdX>5qt!^$1Z~g~RO9u#3O@tNo0SW-elM4V) zO9KQH00;mG0QqHJMF0Q*000000000003ZMW0BmVub1!abZe?$5WMOV(a&Kv5b1gD1 zG%heLGA?Ria-6yYlqOxXCR$xxwv8^^w(WY$W|#ez)n(hZZL7<+ZQH)z%$YOy{Bzfw zJ7@MSQ0=l;(``;TIBLh@4LVgMC-Iq`eBiE&vOI{I0789M5ziRlJq#s!w0Lq}Ta zsS#QkI$}L44Ph2x3eB2Z<}7>xZpOxX^m_ClivLsh|EAP`)E(@fX>4c1@V}Qp`yUdv7Ph8#)+UCw zCXRL%CQkneg5ZCHFtoL>F$7xJ+5RV3?Eekc8E9ese*tr`Fm?S;U?l$;?EkCozxi}6 zVPkjgpIzt=5D>oq-&+;>?<+e;(tlsbS~vksZA~5NjjauxoT6fcq<;z_iTR##8V`{U z@q|+P!`te##v2GiK|yS!umk~5RAin9`rB?m2&6BVuq8*xyH3=-d=_ioUO(R;>?4%? z50>ofZ!K0j-!w-D^JHkUz1aIcN@Ll=xh3nG(O zi1BuHqOq{f+4F^W#HQL4OPzh)aRNeXt`#Mq%`nFoI` z?A>7-R(8y85LkMVEs0*_ZV{GVv=F8_e%++lrqf2I<{jL+J$O7S`?Hb^LsDeCpi!OU zKuYw6e|MqTc(#S9gpPU-=`;lR9^k06%F}cii4!1WMw#M@(a>yx8?8EX>3^OYq^zdC zQ*3NTWB5=VV`iUvbsi$S{tygKT-J^K!)AdBsgz8@wPY;9DVV2fS~IcnFtgKk@}!z- z`)A&fE-SW&Wdt%3z1AIYnZ#PJB>=#8UBAZBeybBkvLwaKoao6=@LmkkQ zpNIN~0@s#Gn+DK?Wmtb2R}5NcI?HN!M|qYITo1C7*$vzNVzkUr>DEBJWz2CZBguS& zUIoknrr0@U@o1w&c%|eRBeJu^L+=_K#s+s9e2oTPgGOG(IB9u25#Vw^K6zQi-u`=@DA}uioRu{o9RheXP?&S(k_m=k_DN&}e4-Yj9q%k1*51Op(pZ zR2WXytjCMP3IuzC??}7Tc3%lMupn#N8gh9v5l)HR8RgUp$>NsmteU!uPbUL;w>^R| zn_%D;^J-UnZh5GyHKt=nY7ijab>DNAs|QVhfE`}G`513A1_< zpgMw*ROAtZSf&gA$Ee}X5F7rwAaBiz(3PU$2mi0D5c6IMlW9{UU)e?l;TJyDk8Gsw z;C6`7S`kj!swQxftt4mg_fGLXFGqgy)i_Jf5>U%#848Zsy$mI|9Qv%z4JkVXWXX;Yx7+uC*> z9SIfBb1^x8*Qdmhv@Q6giruSxA3;B5I#w#2{htOX9W&J)30NNkNde~49LZta!ZkT@ zr=KJ*K^QHJ!TPE<{j`hxPbQ%(xwA$BWV*Bx41D}Tnt@vox1<2nMvL4}rl1ViIed7S z9c`C+WsF?RxOE_Il%eeB5V*~k__NI_o%DfY=CpzhzhTcJ-Xv-U?w8)YJ!pd8u27MF z|IIWKyjW5&r~-?{EH|+L8tzC-~+0J_(ROK#qt&Kv@5esZ`4Lx3wYg-_uT(CbU=Lu=971U5s6f!kp!xG%Zx@Bv}~x zUacvuJP{I9AebbCiR1_|ozbnO`j)PtjYzMe}0 z!Rao$Mdm>CC3#)O0GD>gpHbhVb=@j3C_^8{`=c%nyRA;EtroAxO$L5ggCG;{l@Ltt z7ln@$MEzk7ua$`Jr~M4K(Sa6Ouk`^}ubUk)L_M{88h$U#8tM}^LfOvh;BTf|KEm!8 z!qP6gms|2Lb$9`l{uthuIz+o&itr}@qEGQrj^_<5YR^L+4uePAmw@xfcZS<~2u{&B z59cM>0}WfI(s%>;*5ghlV#G~5)lHs!-C|g2ALC%&?-G5TJ+%O-(LJSrWwabbnn$L+ z63V*PM3g34)p2G3C_n2tplBm87tv}lUy~Z`cQB5yrDj(Dw|hIKx64{f~A`pe96L1X1w7YjZJ`z#9p$zCs zOT+lo0{a^+521MOvku71^$RIpS_?2L%bq@Q6-FLxjL?qm-#Z1gq)eX59=S%HNQ>m= zOcVi%LmGolb6S=5qA2_}KFw44JCuTX^VxrD&Ymq@zF#QW6|g{>b;<3;i8@Z5t|Tin z9BedeZDq+>W`Q6yNV*oS($nn+K%$L}F7s?E0tAHb?QN1Pdnm(P^V>;GhY`_5An%`^ zuGP1hogZy(be0tDw@*TPdbry1uPn_j&XL&Hgi-9TI)h5sY!di2BuPV!aqo?49N+BZ zX|z*#PzuS`k}P7%U4#|yTV{!HH%RPZ_ti&tFBlldYb%F+nb!+sg+H6&6lf8pmoe37 zdEPPFV9V5CXoRUW`feO$Sn@c&ta@nag&8`m_x@ywGU21JSS;u7z_yqlO_- zMf$@;_v;R$-XTzVpsyl}S?YjHo~8Td4;qb3*_PJV)I%BGPlI5)5nE{?gYTyqM0BcI z9z@RWKt1Dkw=0^{De-sP6=eK50%p@6uz^&t&V29LR1q&JY=yaqa>!>gEKf%6H06o~ z20{;e^l5Vt6%76Qa}=pOO{{$+*Q#-Un|G~wXIJ7Ui}yo<8<;TS7Uxxz>h$D4q*N50 zg!Ie2F6^XA3Mdj2?$~58tM&wE(k=Dmh-=I`x4078RlqNMr9~5dMr~?}5o=#QB(d(n zYNS{by>+@2n?xT0c$l>mgf_oUVVwsPKB)zCl+x3b*gRqO*Zt(ip^|liNi@2d>u^Ji zN4qtaTjkIg9GgqIfS{W5nOO~em(Gtz1>`-&g*c&kUVLD8w zNkk*pHWpt|G#YPZf?h+itTjjbpg0IlpaNLZs8?Gm!`&JjXfWxrt}PUU$2CRYOiD*u zn2?asGEE3da0_mZI=aE&4`rzH8!0Vruw4@y6=tYzF=>G5Dvv;OIO-wOHmL}j-upv# zX}MCo!DzLi(Xom?1Zg~&+)3{)!t4yFC$BM#D*u{fb7zsQlux!k&MFjPhr*Ck@RV_p zq>zax)2#<+TBne86s^Y-oMMR5mnds+mR8zl-K`R|!zwjx(7bExFpxmgovK1Rh0)QS z`iW$yj;(4x!A`#NyZ4YmF5dhI({hx2(zK>~qYE1~lz})1C3E1i9EFdsHBp3@S~Zg% zizjNEjc;UBPtnsu9A7ry@NVWx)tI-O4;MC7#-8L+hrQ&Am)|t$kz53j(Y}X7U~EHc ztznNwTb)4!*)6&XF&*jM3MBz`bQx!h63Dz8r7T?jbSTc+t zx5v_dwBMC;Z{gspg-e9H!*plo-f<@TWbPPm=B0?Upn7+;KPhLus>r2!*bd`Q;*T~L_&Jak=Bwy^It)vsoA$hQz^=i!nDuto zIPjRTnb}cm8MA`_P*}Q(jLsLgX2CH*jRk7y+Hz&yaBEKN@b?P;E>Cr+#QZq$XGE<+Xe&?SA~;j2JR;%vV;U-A4n{RW|03m0PcZ}bLrXWQGUG*@jD=gXOhj8Z z;}Uc8ijjbYOOY^LiT8bdL2Yn8UHXJNe%6(8&s-hPC!YiTt;V!zoxTN;c9e2F%GFvv zT#;fvj_W6vMeex`nQP29n(_Yg3aAUFPw;Mg=|q_?k5LIz3JMw- zfvZoBc;v-#4W;_yXF0*V)tb>|grltW1RM^H))08Z&{KNszJ$b>9OKBGqtF}FJZBPy z69hrV65a=-nOSkiyHUIaJ^@y4l}>QKud#T$6#8)=qW%iJlhVo;P`cw3O-|J|7^0ba z_D=!kkF8yza*$lI@(Ccum_pV{-C;pJy5rg>cTE>BW}YpDp@%8Uyl>{Q4_T-1xJ~Hs z>ym@FMFZ^e`da2@ezID}Lv+RQjv;7Uv^U-Ca@fO8XGCysgm33>_<`D141KaM#Dul% zv3qHJ4oIJnto?xSLG20HKK$?;5Z~dBSS9z_9*~%hJ7aX{u!lx)9gzF@@$G$~OFats zMsh9B;T|=;qxH#Nc^ZcB7*r%E*RMYy9UF8&=^G}0y$M|Enmg(zJOtL4juIyLlpL|V zFyxYLo65M*7Mf^Aam@{Cn}`pGp}{WgM{ z$`kHB+0C?oEUlu%vU8Ch&$-Kfy=jyTfJsCERj2`U!Z2UrLDJ`&^u1be$(U3UP4QI zOsk>8raak+x^7w$W5=neEqQ4a8_aMA4Ue)}oI{Lp-#;SgRP0gn26(@%Eu->MQ$}msM^5)6& zhm^z41vbvHP*de(I$+?+@|y0|u#fPRrmOql6yMU9%SFb&p3b+{AK+7SFnPZuWy(x+ zxM5=+lNoD_mbP0$1|-yVxA=^rwx$bhuI^xo0UB6PT%z}IFq(qmZacHaaY3i=T&8ca z-*6`ewv7q&dWF4$9uEndQmX3*F)b%hY-GB3ANomNh{+}kdlC`xH>?aJzZ~UDi9Z5c zlAQ7LDzSM#Fp4&*tFjW#bl>BwGU4fQ?K!|?!P(r28F~eRf9qL3A}Azq?AYD~@jm|r zo{>Iq06IX$zXW3KTctuQ-Mi~Zl?L9THmBBm=&m8%QDxWLYx+?j!BA$`^D4Bh0SKt! zRRo|2OWY9)l=_zWG`KHj%;7e2BS`?Tq6bl`zqa z&}0#>8q^UgCr{KSO%we}W!(#+DhiwRwZwVAy5@PCNDkUa7SIzAw5DZiM>lQrcv{6p z_Mqkru3tlfc5&t$Ox-SCX93owGBI>|$WG>c@0n;TGv`l|1h+luNs?33M%o^-?u-O? zLvM0}AHVUg96+>(-x8(q3B7zl=4mEmIo#fJ`b2Fe7cjm3;361acZ0d!L7UpSPQBGP zwDpaG{)*?kX>YxOh}hMZJ=70V&)iE%Qznie`vtE|zbqYOofr$0PP&NKte5yb{-Z3p zbs{dqBzuEgeFUFbpPwG~z*dtIah%v)*z!=bECrL4m|;}e9gsY(T`%lIMFTHV%?vtc zqB2fxoX3hgZrW8R&5m_$QZP$iH6(Ar@-&LE9}C2mFinYz-yDKIWwK4?qh8g_w=#!^ z9KUL499|EUM=nRAm{${_eX3$tO@~>ClJ&&pu6!o=^|%E3kbA@=j#%0V1lRcc zS-5X7!-V@di?z2uS;KU%u}b+aE46$<;|DE+LFdmNC3JGNi`in;AoRHF5MSF@Y!zvx z&&Qo@7`oQ8{KcFq?goFJ_Ur*2+zV1S=iY){`eG-0GxZvp){2T{{Ef{;D~OH`55B(a z>a9OKZuk-`ts%H-eAVCj`dy?&?WnrKB=p9RZfv@D*KbL$h%WiLaY^L*!;?2(IRDyj zuq15ocK87T()kkvgy;Xb-|+8kZXpvx`~SD?pu8^qlL?8>!fLr%)v9Y7Nl021D1=6c zmWKvzsHAwyw+WB4N=}CR$&dp^_yHmyovB;lCggf+`rDEDc!JE`$K4CGHb@LpOqM&< zk@3l}2q|B4n5L|~( zZbvrpKfzKhTwsdjsWVF7qD)hhB);~-+$;<|592-!(=g0fta{E@HL3cGIQa3md|OxH z?il1$Y{m%VUD-_@Opl8rxre`Y@EXO%hNDQVXSJQ&uV@qIufGfdHd{A5dV?Tia6I2y z@Qd=SouL&p*NsjjpyvjD>{$vnhaI%1pMmAW;a)s@4zwrexUY>eu|R1^elQr`?w4y{G>D=ku~1$km=HtZd{snO!bA zxRe|g&|ZN)fxB2McfZ>Y5{rc~JVg0Ja=0;i7;X{+GkKqj{pY%Yo!2__^2cH* zB(jLBd&u>@7nx(17ZcRWdOfbV$ts#nhhckfERFV;tzPTjTfPifo*P}B38&qwyOBq+ zZY+RL?b*O@mTLO~uHZSzpDrmzBb6-XWT4}*vh z=>roW5KdB16qN3~aQN|&i!o$;LQ0MA`ED*6;VhEwr5w4`_Ecu2>%n=Kf3slyVT!{z zU2Mp2dFII7kd(|W}886m=B{!T%lRNhfw^l-t`3Pxb z6Sf;!t%fywYY#_;X-=e_2$qDQt;qqUn&GAJ6=ZqEW(Rns;r63;*>2%}a%0HS?zM$s z{@Q7SC?8@}&1t@%3rR09zwa7>#$tBf{u>Kb0Vs$bA$HZ9YgVb9@jf1)M)Pkcn{1az zW?m$CZe1DcS=(@+<)WiIUS@<_h77PAq8o>{V25SRx{r#~JQ8TAc3e;X^&OPD+6%(R zS@nQc_5euoQ;}Zc+bV;$q|iMnt~)2PB#>5(pTzewm59kT5fGUymzY72tlpung19v3 znHiFIh;mD)EK1RP5JIpQuwD3=j3YnIr>fB1+eJialtScFtxAWK+9bVT{n6@tbsh*r zK{0+pT7#UJE5;*Xs+f9w_8w?8d5@U|f_iJ6FCxr(MPi`TGca0SBrRX7KAld-1aR7h z86!=CN%>WmN>bx^B!UGek{_UX_=Pc0i$~hU+Y%64B3YOx_JGZsbu&PlPg_uzn6(~-TB76Qdh`N=sCA^#%6+C2)21s@h6(zsOeq!{z6W&u zL)FpX?79wSy!Vqg?&Y`9K^$hb7o#7BH)E$;R9Fip>UE!$QN9vtoahbD{N^RGYD?_o zRpx!px7YWx@AvEUMF)qTC%zyLxrj!1H)FD4296D49wE=)k5%j;Be>F2dbTwiqiN7U zMl5kS&m_~FI~*8efnYg2s63Py>T#hamyrSEvG>~g$W*tD0puSvi|1`rJSkIfJY0Uo z8oXKI9@WQ%3DD~@CUdsLxJ}-e9G7A;nH5>qoKxv~=smwpoDcuVnQ zIG;R7zRI2*^%kJOUMQni%q{!yDH%^NDZVEt7+0t4A><8Vcp=X*!wA;}yZJG{MzEf-! z69jKNaKsL>da%E4K7nb+^SPbhu3Sg*u*b-%hD9xo&7cv;E12xb_jt;5i`u9b(r!fH zz>eP*26-wP@0A9X%-Hq~l?HL5VBm?;;q^NNW1Mt~;L}zPa>G*WXkqnB!Acd%y1{VL z&2S4)(MHmQE6{{vmp)~R=)=-c8zG>AW?YvuQDwyBG;W&!b_ zCD~-c8y%Y>DI56P^prkj^3o=cmFf45O7D6w@^{{p*&#Q!c5_2&Ioj|1zU5t z&1gEQEBl6_479{$kP1oRZHVmA$(HKH*4hd)bSmUqvLDLwbxsdrYbo}lmdmf4da>H8 z1M)>T8eK)@eD{W>2FF47g(Ete z5~NOlB(t>&D4ERJfuIb18q0KrOMWn^OFsIp7}L9-m2rgmnm&P1cg7ccPB|X~CF_#J zRS$YG9#_`ns}RvDFd~C!!6%ENXOnm#MBl;{NWMn!baX+910@@%dv8F%J{rbBgGIW( zv!qgIWDuUZj?iKD?@yHSaQB=n%_@Qgo(GKItH?9lk)g=YnZxDDp}Q2C?#QagNORl| zuuxe{D%r@NWEXVh3%V*6v*@%}%$9ILCYJbpl8i>#!{In2D71@K(2p=E$K~nFUI(!# z^3OrIhTud3B7#2AmapKJhbbB~J;Ew_VkI9Cx_8>vaob7**A5zAe@N~m@D4ZP1Po=r zA~Qe0OAc!|X?*)(?_70u?oD4Iiw~UjZ;TUb85mmqj;ZQ#z#YWfNQ^vUMj`uSR&p^!6uM!=)#J-Dm>fh?i(yYWgGyA4w0 zd9ZEYO>*{(6J+6=4}FOph^6;=D-G|cjTgd7Hy6SO1pylVbqI)*Uv`OjzDlIzcLQ#- z9}I!y->Aa*%g@`=kG;W*C#%!Ol&i*{VDR@KLpQO=Z@B-;#EwJdcO+mSAR7NLF~@(2 ziG`gltWEx%eXEkc0XPy^Lpe!7^ZSty1x!9=QkKe`inU5s<+rd%sI>7ow26flp7ter z;jU8-jR^u}Jxwf8zb#AVx0&aA%I2Rof6~cKLb3PvUUj`+HB2A#xm^2v-yiG$@Pg`s zOkrXm35+qJ-Kma@siQQM3cMb@G1e4S8(1liWFsXjGy#jlFn%_z-1mENrv&(j{|ydQ zz)Jj7*>r##pImM4>&1fDuw@e>RF(_ywmjtV#XbR2FWQ*7Ek4i{t(dA}yB8;KUmc!>ODO2wzX&44@A ztX8c|n%G36)s)Ls+-eKa)@u+O@7z$1i_o8iAU&HYs-Z*5*f=iA;&ETC_WB#Za}(+2 zN<(9qP}t3~$ro&9V{9? zVWWdP1Y-Z@rYA!e6dbNdZ^HFe@v&9W36@-EhHF_LH@yiOq)%*;9xPoXH$wr6R=U(L zlW0zxZ?aX~hG^NuG(&BUkAFkYNq1z|*+0qEqed+u;j3I;Q-a>$FGzXq!rii`@Rapd zmI~hGqiZ= zQ|^^qvqkFZ#(I?LR3hcECTr_@>sUwj@yF(HE zK-v^*Ke2c?+>0SS=*Rl(hJ@bXf3S}>ycz~W{53{Kdt+PJ7U?jCO>EW3c&G>2xdp#b zxbnV$==T}K>V-m1wh?ciVFX9`YopOywwbF5TPr;-%e?>k_XV3RbcvE+GS0Bc7CYhN9Cw?B2CMDk9FcgHx}yUB28 z!DpyJVcN>0Da_4YirPOM>lCKYwpM_V!Z6&ic$*2zmq#*HkQgikxE8_-zaQrLpe43NcX8uzUga1tS6PTp={Rgw0mDcASjzs;VV(I&-iV$=jl$Ulv7vxr!o%42z>zGtt(+ z|EWo4auy+xy-pBsB&4RT!M#~cccvw94ODvt zuAT&-L#um%!|9!|#aJW2O5V9&iks`#z8@EOeI~}J=mt?Ie=t^{s&U>u3)w+OE=l0g>Bmjan3PZwpYcdIf&~j9On`?^l6EU`m)H$ ztw-jL*Cv5%$2;gcEB7eNXedF$pz|>%m_h@HDRnRwiqa;G?lUc&bR5Z<1yfw-kKKHH zZ<^uz<6nJlhlxpU{ZFnz|L2hK|E16W*O&fH0In+9_hyD%a-dwUV66&rg@%+rJh8Gi zrOh8Tz|Td&h-OROdRX1`3+9eImKP;`?)?OLcZZ?qXnexT{THsEWiB7-x03>+A!ltI zM4E&0BHnG!8&21+S=+DDPcb|#zCRcvWsrfp=2%&&NaIX(cri2a(8eeL!v_Oye^gGY zxl<_YF3MhDaJb3Z=Or4pH=NW#Nl*dRMit>1jAF-Byy)NeYDDx z>2g!4P^>!3EUY#oNcUX)hPZIEZS{JstOYeo%6n$XCAGl4t*iN2rxcZRil+5++j&5woA{^H41Xd0DP^zen3>scmbL&YqG_XR(kIxXdQ$QYq+= zH9Mvk`_Mn@tMd?HaoTVH1b4YfiZBo?ndWXnV z#dY9UNczxJ!&aqoUQR)8y*&!y2)X0;6#5T5^JvPbcpB}RxU}2f$MzEWhoT`HS~SCu zE_c$3DE@lRPsAR11|E9fGc!p22ev-SsIF34f*f$X!rzj*zn-D~M3m(UFwjGYT(ROd zhMaWA=rLcE0OB5CE_Fw>4MrC*+#Ky;{YOT2Mlgth@tZv*#+4_be#*2JjsII4_l@ZHUv~@anR6WT`cUF3A6?qr2SK zY+EG zlhg@)P?cBaTJ*VQzxIMZuEzyT`#M){5P1mUJ8TE43oBs|pF$K#Kd5_|ybf{i+!iHf zp1ylY+&pT&WIavs#qM9ZY{7==cX{RXc;V?Bk0~GXB>@|a;O~Gkks!KU1Y^8KmZ;Jg}z)*tEt#SPJ+d#25 zAJ}25_t*3mnRUjW@hbGpdC;Wuj$XxnOx9a9Tdh`~t~mP{diTG~P_lxSXi>g)JIJ`6 z{b(bjo|0RJ!s)KcCC;Vi<8_YsMc-b1$)FbHkwuhD2+6cfQV@s%WFi{|lbrILkPJAJI1$_E~j~-%~@cKvceI!SLt`a z*rz4el-&&sX3a*y@|aMxY>ifhFJUS$jB4WQEZ?#5TMZzq*@4I@D$6`0v-69K)()eu zoL;KG_T=yH6s5Xi7!moxKREg`#W%_bH3B!CRES;FB6rktIIT?WFz@uUfA`MJGg`Rn zdQ$z@@_i(FS)P=~CyM$*T%ph0x{iIn6u+DYm~kQgb_>C^mO?Cho1I+0kVj&p1+N6N zNCo$$*a=tKdeBIiji`nsh7v|y=7zXFeGmMhEmR^ImyiHbtUfXIx#UPpTw;!qq)#yN zE0_48dTOjbiGn1D2dOs*NlVa(H{RqWk&iJZ^zS*fg3h#U zzjkqH)}9~{o|*1mL9?RjTPOG5uyyZ}Q;iBkEAji@#S9{E4V6h~tS5T%u`JZ}UDsOxI*g!xS{wqB3 zZxqp_1?{D}nD*`a+)Xzs1LX(yQwpj+s53CI7RoRRT9Q$e6$)a5V3b8Pf!9k4tZL1& z3BY4xQ`PLRW2CQ79*DA@V`e!uHyA($#GJg6VZ?%vXrqAg2xn8wx za~<<+ck6h4Z4PIHD3TG%_p^SehPVPb^ZS+XzmlW9@b35BxIf;!IPfhvi)jMzz_>#Z zk`bC+XFdz;vVjO&zzG!n;1{x75v|}tnP3E=9+NXIwcyD4CWrV*9@0sM{dq-Ft~cgB z22^yZYW=%8CS6CVDA~JlDi20|b@FpD0MO1)ABF`fJ|CDyJ;*H!uosMxoeu&ye*=3a zB!|7y%62rlCzkS77|4F4B}5M@mtPa%j{zywNmscuDjHyVRL;hEi|WQ0?&lRLV1XK` z(KwogJM+MPqauSaghe0C^k@jpVul8wM&$wRvM$YBn=hFub;W~86hg^4UlUA)48_)B zyJ^(lsTsp6{j;C-^!Ud#MLt}B7*ZfYS#sapDMVyG{ z78mtEc(Tjc>Tpgu8FeJ>T)?Ov;g*mQAhrtL)s7+-ms=q)`psYIill=j5k@3-8cEbW z`*!+<9n7@0fePn5tg$_Go(GpCZpk(X+9X0#L3MhJX@kk%C#9U2L)<9qazVLJRcvDc zH9E~An58O0ak|qp3&mIuEhhKF+ja}>>LiM^PzG>Pc^;KUHfE#gsqQ%qoT-dP)irZoYdNJR}wmlN36ShWvaE#ftIm(;H~k zgpQ6!r3lLTJhB@d1`FA&$A!ZFHDnu$D5nMomy%$Q7cWaDnflDq2Q0yai!00XZ6sgP zBx^U*C(oiE<@OoqpsH(I-tu;s4vlHO-GhQCr=$u0=uWxOml(gwhjvD#S;8%IE$?S~ zW5Voe0xapCJp5uJ^B1(*vu0;{ykcz0FcDid!Jav*UgGSvg31GL28wnNS5XZgg@l!>$M()+iHS<5w!4@tH4L*R?otwQ!_!J+ zhRAbo9e7CpIuU2h(u9)8F_b#rm|}NQ9moPj6At>z=7fjR2Gmlm;aY`NS}b#u@*MW+6p@9FJ7^-Q=W~SG zW;qk#3>0y{|KcC0HvmJP!Id{42_+D70C$0?lQC1@{VAjqW#!+hW`?*Qmzx;msQA zvoQ_&+J(r;o|=n_xJTpfZan3S)}@0suuq*Dp^C~-0hH$%RY6OvwZ4~;L5e{p>JCQ) zFH&s=zfC`LeHB=wq$-Nb)giVK;w?Xsm*Y0!vzl+VmyoNhYDr)s-A#IUbgQSjy12Ze z+QOhhz|_x6E8_H!x>b$SXynA9v5gR0@l3;QhP-9ng4<)18g7vG<>}6SdZp^CPmrRL zn$?jWJ7m@&*RW>}^*`zF5<2ablQuI`Y**2prV3NaQ{bgbN!Xk<&Mq;RRBJgqHvI?> zcmOL>uZ9|v&rjCn)}g{Iztk_v5I{<-I84vgsc`jCEcGv=DE$LnOA$}}?cQ`*m%J5i zU)jn=mWR=Ba2EcACgGyQJ$R`*Sa!s)e44dfVcZj`u0ptNpzC4eM4B4cxkcJEWUc_X zj>acvDw)|?UEONPV)82d9bB<_sV*kVH1NbclP#FdQ3$7SI`XmJzZn&$%cpgh5n`u( z5MSz}KZ>(vhg7EhXE`R7@50{dT!3;KTbCn>j3A~cNnWAKWJsa|tc zKLPg+*`HXt&8{iAa`GFLUG9y<0vpY~{*ONUT84aOE&3`FAKT-Ah6&H4oHnz#g#{K1 zy7t|g!FjCo9P0Vvf!l0PuuaKOxqAChogj|Zz*|8|pBzyXME3Zi^oi@(%&VZc-Zeo zwtf6oq%8!{=l)DkRAOCejh72^KBF2lg+Si$h$v}NS->N*nViJ1r`MK|4ostHhsWQ` zH>QF4vD^sv)L<_V?ApfEfZPB(4DMIspcJ?5zU@P*bEdEMkgkSW7N;eb8G(+CXPQk4 z8oqmzIE{x>5ms_#J+7W5WmkG$MhkKHy^inMJf49DtHwg>mzUSQux$~_?qo-ee}_(QZI`LVief1uC# zXkbJX9t^!SOJlE5IkpXCzIU#Z2-ar+U;@KdZf{zJN(B23&Yl7FAfcOyIe$BIeWH6_bFZ;uR1c^%Yg)9 z)jRaG9AM)f-N(>4 zPM^%VPcTQxLD7v!m@OW{oFPXq2(ulh;1uxA9?-VHt-lEX#i1tc(M8d#NT(+DzC|sg z&L})Db|UW}uc<>P6y9N`Ag?!vcP80;<7cIpXrv(HbkC7Hd}#E`Lud9Jnb9|teuoq2 zX+Bm|38jp8rcFIPK@BUyI~fsh7&vq{`Xi^iBV1a`%M__9u8l2`ME%^QH*=}yx%ej| zh%1s1PYbbc!&bVZFVHg$wvtRbIs0Z-G5yn83c`R9B{URA$SYveBWlV4qf~e3T3Y_v z+QE$NmZUHJsV^FM^4X}NabEo{Z9>wj37M%bmvnb~q_ z$L^r%h+BQ=A?jC-DGkm(jnqhQpU^QhNA>u{HiQcF>g21VF+Q|{{=1Y{6^Zm?Za0xr z{t*zE<&-wHH2otjQzhe4FT!Gk+|=L~@sm6-ST2Y@CzFF7Cj9C9d`uKQ)=l$sJ(QfN zvZ1@g7kB#G9}|6;a@G;3*Mi)-dkqUU^`9#;o;=c3+;AJis!u-EXeeI0b7dI)t!oypW0sJMOx|hUexL`tlwNOkg8h4vDX~Abe*~^)YvU z%q!07UzF4(8bTV}#uPE6z9)$E5=<*!>69PXfA6|NSIH8YI>1DrpiRjua^ilEe(WfY zcpWO9aE|x84HTUT6VDm90h96eNkSMa+E{@g4TSL_D6ClLvA=lZ!&pcEf{n5R54b{5 zUAd9R+7i;F`cKsNN2R+@q<3<+5;VF0#BW+3EUF#ji5KxhD88Y6z~`yl%7#Z!ENJMx zQI63*Aby2s4C4=xdc);Qlahe1vxHW^hR4>Cdyw;%Z#1_0MiloFLG=PGu5dLP zjj)4e&9U;0rb)v~>bA~U7pw*_QRxeYu=np*A11y{aR)cAkRNnmLcHX7Bq%0VF(br1 zwo+Eq#B*$t$}x3$14NK=goSd5X+2I;Jp`@^9epATavTIulB7De;l^V14^JVqcRe!V z7&$LV#%;WH-?*cXaMd^#ooWz<@sw}@eV*@&?n+ZN4EQwZ!keUU6(Y0k;NsgDV-vTP zLsRmvORS?*6aI+VV<=`8)O5aRUWsi9#oTglxDb?GNm(5#r+y{j5%B&XuQgjYKEwya zZd(CHS_08jdWJq(3z0INbV+*v5|9fnRz5^zYyWOXMXTA^QA|G8i&sb$Jg0qKro0jo z<*-D-4@HiOqKlr}@V7Uy!-_QCl!yJwZiP7S2k9#iq2|{iHKP8hidx_37>6!N=7!|@ zi=_0xJsEK}qQ0?iwTiE|sIX%&s^fTQAa9giYe=bH%p~*9esy#Pw(=wj+m^BVv6KqG>&*Od%o7!IvmA6-hxk zE26w13NTz|F4n*aJ?i0SnDFWpKSWPmtjZ*oW4bz9ehE(zdg@ zjf>KO6XB+`yd@7r(;R&EQh0AHnU%%5__*rSHTmOW5Ff%)^!3gV|?4* zA>rE|dv29v^|>C_GM=*aVXWF#b3Sd<7KoW2Q`R+Dvd6>{0zT{TAnA3qb55gL*5g8KOUJId z1hFLX*aJR*=qL#u!}cbAhGVm_719bn{@I{tUMB{6vy-#kB;F&gir~NkBH!+pZnp8{ zEidl09kXWFAFey%@&mHUL_6awuNb!B@fE7=;gB|;gpbJ4Gv^I@fnmK@aDrHlo6-*$ zhLMby?hgoogqEA+&M1;Q?X+KZQr#bVM3b{nIk+KIWiCIu6msj)*($gTJ(4DhphKgY^^%340TbkXvu9k@#fqb;_L^7jX5 z>cKXMr-t;pvTEDIjUMabob*>rRoPP}f9-yxmHuMhU16nEP}3DExyGNxVyh`8=^Z-6 z(+1KJwVLYpN*0FRO5K}Kf9@)XJ<@0j-P;kj_BlpKtu3gqyr66jZJgupSsm~Q8Y*5V zxyvy^Sn{56F4?D4fg1Sl_u6m^+E-3YT=vqD?YCGW`f=da4FH^wH}=JLk?BWZ4vR63 zrFtiAca)=8{VxXNOa#hPPyHIWH$xWyu^Ss4Tto36FyP2r50y10`@FeHKFn5 z1*|dWdcg@f*@9!TG7{xPr7ayjKJK_4=HUo%d)bz>0TE*DrBj5r%W8GAU<(o^=nvh| zGfk#imLpN7T&q^|b7O1n=&6u~v9bcjczpZ1s^tu9%B9C8>G0{fH@>KRsmjo*FJ>~& z?)W>t>HSOmNW(`26yBX~31qw9{q2KkmtuM|!Bf*5&mDiyQtVenp%04)`PqIAQ=&32 zN_z;GnGZlV&)l)99#0pi-+iX-1-3Ba&ZmVG3Ml1*IEefPsXOq%Z8j{sdC9|FUvyHULGpizvOP%Vr&4Z3vD@1OZ zHI8jA5ziW1F@O0+I{&J?)?WTtR2RuI!C}TvNT-33;6q36KIr2a@X zUyZpXioP6indf14{n@GDX@&XLR&L0C;TOoeC?QdR&rbilBqV#wmhr(w8#@|Lp~#Df zmAS$xXsb$9`Fc@u88edg?Bw(ArwhtZ}mYQuJuQ2SkNbT?P(DZUa z{B3%X?=+weW?YTk$cmm=jYdHHZq-JtQ(*aTA>$A(GMKG zC~I4z9uU2-crEfGw{9-Zo6PnNy#D!+W(OKxthyxECb!=OI-zUVj@<@xBXu`W-8O26 z@UPs6U6PE~A&Dk*3EW+pP&XxvW4fd(uZ|ThYU7?>CDtu!6RcgLoHv>so3%+<5PciE zWNnVWcwRjYH-N3-D$}#EN@z~E-l2Z!BTa*g_TWy1rq=*B?wG!l8Te{P+^2V57u;!! z2GXk~R(fG;GPN^9c@IuYNazP{)9;#q)`X*M(xbbP9iuHi*6UZWrgU5HU`o*L#&B=x zoPx3i(K0Ut9?sW#>CrM{;uZ}pBTl!G4l^BuqMIu*S@Z`wC|TMbFihumVh2W(EVAuy z?4uFvx#Ws3aNS}reb;XED~7VGC5}zTSTA~bBgw?~y+O~{Sl@m~vgiKb2)^d#cj1r7 zUSfE@SazLZRY@|}0If0JpTl6UYnvOGM7~G9a(GmT?o$|b`#0ABzEUUI>oZ<^*fVvo zbbw!UzI=lQbLVis2E$o53%EbTKXW|Y$&AXFA5vx38-9ak;e>|ITw^oWzZ&(Bh~E~% zl*TB^_TO`+U(lK{tl!r3Wd$SZU(CW7gIDj}!E+zptqx|ed0QX50B3UHE6=`qn|uEj z8n~Pn7d8O`0H6c;kMj18W`-iJ2G%bBYv-F3B`G;%1q>eaQl_N~WoS>pJww!~qMEv7 z3>d^1{UlK&g6eRGO*r=A>39Qz@xlGkn9&$5-(cJ2cKX_Hh06>sr4cd1?QN&tJKwse znH)MjK3^bvSX5}vNHAK>^MR6g3lt!G@jR1kjWU;dWDw^BmFZpz}U=>QDKK&5XZ zB8x%O)QI(F2U)u(dnbdc{YHGc+5u`Z>pUTtHtjNji)2~_5@Spn5CU?Fq#xgcVI4-} zwyMPSSH%5K?s#ZKHUHk+h5Dk7lMuEMMjJywWBX$O{5RWSK~nB+Bsgx>tDHCFhuu+N{7j_YDbv z2M*z5LqR-Al#Hj*-oUWgbGMM4Op>O7d0i?Y%IoL-jfD&u3$mrSOo4`MQ4=G!m{u?| zr&y-w7Go7X9g~Q~g!JE!&nU5w0-XwU6WPlMjrE;0QH9M#aqFa3jbslCO0QqwW;Q-% zm1Pdmiz8+F03~vx;9aO%eIzx8nY_B#EA>Ix>ip8?KFQ~jO{3K?-AybDyk?cQH4zYjP z%X$Z(Y>&7#a&y8`a-siSvkp3LAHgSyoq>f^ zf^W!;qF`Af34;<&q=J$#SPqe=c+$s+Yb3#lc&uVyFGWfK2f@r2#c;K?u(US5lANij ziRo_UI{NqP`vbZkP#Tufm6_bVwjcnV(v>CoL2)D(N=PJ0p7#-mj+YcA<}^OP8y+`J z{>CfduLCb`$3g|h$F;^)SnGWl(c>|P6XgS$o#^@NjlCsUHqvJ-L^k8=R5x5uB6E0am8HSpk+05`O7cRYrN zeX!EszTJzpx!c2s*he2+rWjU;vxFPX-0aEEM=v*%&{$M+PR(_-h1CUtH2E&LlA=%* z!N06a+JO?-MAv(T#I(NDh)o0cSdY|IYo#*sCf#0)q}CX!zS#9cUNwPc(@}cHGdGRh zQ)Edj4YV!2LA?zM{}~dOCAnbvfs|H>bMb%ve%&M+YyU+G5h|%==Coc;c`$wk z9*F|Y9K~8UQYIGgPBJwKU(_7(9BmJnA@Pjz%hI;a__*}0THbAN;WNTxY#Qubv~2bh zy14&EDv83rvMWh|ZiT`#wnpV1E()#*9J5B<@J-a`9&s(q`v(43S!H>WuwjA&0I0(M zCz*r)Dk~`y4^u}2831PS69m|V^|lwz7+k8wyEN;*PFpWGwgpcKBF-sd0$ z+l z0Nzxjk3>eJo)XA;Rak{k(Z0&5MWRdH4Mka$P`erZETLPedSjQQnkBBIsnA`JuziiD zqXjYKRl31?Z8RG?q>?6T)x6?Z86L@OHbV*Hk}G2-#Z2i>+i`M~M^|!P>du$;ByC5N z>kLhr;!KTJDj@8e93=+$l!u_Jafe4YFV~53+=h~fWM|_^woZ0)RqZrSfdbdf;$e|n zecSYOuo8BulUX-K+g-0%FI0g=8D{5gue6`*Xl|R5NEdSsCnw9%@vwY&Cx?In#Bt;a zl8W2&%N~!x$s?O27cB8hrk3Cb8>CQRCOlbf$!3prT@)M?n*MWohmzMVHgGM)S2EJRlvO zy~G%U0GrZ!Y7ZkD+9r1lPqnFKnw4zJ676OylikFyM!cZq?yGDo1BT5)(XAZMt!^D_ zq6efb{p=(+?xT~jt^&K2>j)g)JSWP+Ir&wNJo2?F4zi=k1eZGLB%45e!dMSzy}=+f zyfI|bSq=6$Xf#?wGP&WwDR&Wrd)+{r1FQGW!6B+ieeT^kd&$(Y8iMUF+%BtYDonpux68-Tvb; z>BwoYE+?;izG1CrNoxkMm<%!l^C)=2;Wq>ZZiTpA^C3I#02YsXG8YJ<^wk$J@z!iX z?-(Va^7r9j^=Z6!Bm=Is*N1ar(I{?Yn01Ihi_1*)VV!6#Sf4^Tuu4cFcdQ1$q_3Il zWzzR85Wfq)O{c8gti1cL5JIlmaBbkekyF<`e1o~cd1p!SNha z&W~#f?V&H%UA6`}&JWn_b74X_w(rPq3WT$!-_y%pM2QaIaZ;>JT>-YhYzs~P=Uxx3 zZGMFo%ry8G4II5Gs!O7Zn*d{PWkC`aGOY~-^3=}Is?^6Dv0_0XT#X_Ro zqx3t!uW<*H1gt3Gpu^tz7P{}K&9QhXivlydC<~p=f)p4mA&TapCFu^w zjd>S(dWfjIF?8;f(?Wf{&~5H3{lm}8Y(T5`36L!JW z_)%gHz}z8j_sq5XnA#&CyJHO7{Y~${e3HDyuVU_SeglwSuw*J^vK4sU#drZVi|LBQ z;}t^VRb&U{W%BY#>8fN7nkNiJl_6cgFJ`@nKGSPyeTKTsmg(+OYx#XCz-JUE5@=JRSLS&9N?N-^ zYkv>#KWlflm=R4w9x^bF`r`aZ<>Cl8uek<3g+MewZJ)kYi{B|WJ8F4Hj5L}4VuDp{ z$wRsWP@5X{_aR5!A}fT9Pw&FJ+BYxX@)~g2A{eStlEOrMg>CDz*gkCB0 ztab@lR6)TANGNgrgpA<yj2X;qKK*`e<+>T9-T3znm|?I{HSasj%RGSuf4yCy}CKh*mMP{r1R& z9_Dm0UVn=)HG`G;(nRCpRShlxOF*>0)7g1V)+=2XS>tRxM@Y+)b3Ia-SwtV9a zp^60d{y3sn(6B#EgK7b?A-4kA9=J}c_Tx4-8t=t0+#dK=xB2~B9E?|QCKmS}3#SDC zpZpp8qpSamf!njwdO`j5uB-F0IV+XeY9E+)t)``RxXfH+Etbe!Oa*D=ybu)(a3=0) zuv^SxZ*9marq~%3rLf*1b;nq2CY0$`7Ef7k{u8Yty(2|cz+)@dZH)wfPgW1Oai*=u z%k@;qUVw1!<|ymIUtqzm#%n+) zhfd>R40q<}`oOLr=_*lBcH~T%lP7nYot-mhTCH80?#5VBoZ@s^)0i~(r%KFiZQ$7@ zS8+b>j0wbA;^F*!@GDsdr>(Rx*;?XcN%b{Z#o71{^5sz@?DchbKr<(Sp=(>L?X;T) z9>1Hc7HR;q3#(ClOy10LRkJx!gNiMQn}fxwY(zS~(_%pXJ{0Ba!kSm?MU0d4F16m# zyu{G3;MzDzEK0qbcpO70@=KpuUE|e=5WhA#NM4%`Zsc0-GS{ zw4pI27rOz9mdI(9e}X?yV-RBjolcr_XxNwuTExqN#|>^<>;2-iqZ0-O(wxQOB%#eU z26m-(fJddx#nGfoecY_ZG1uimezGY~+xfa=^ly2^f@_tR^}?iTf_f_$#?dgYUF(D9 z7N>0%+rfa7MHj&*%n{I=(MO2kCZ6MQXDch|m@bDMQK$&=-Y_k)*nNAzALO%o>qBn1 zM_TFbU}&hgU7viJF91GecXuN)8P;}uitCQ7W3)^7EO$(ClQr}p;^z|r(f@Zw}r=hk%fW1;26hmxr z*pQv8>{zLWxYH>k=n%nP^;V`9DU)E6!IrV`|C3ylhhgH<&fEgfc=4 zyd`43vtmbnfqZ|4D1pM-{2+{$*J{L`Z|?NHhzi|Ao>f5Vh?^ttT`-K$U0h6V zlB~=%kYIZLJ54+yQuwe=$mWF!=MN?EH<1VGaR9<B_` zXFR21uahWU16!}$gQVH8?SRuTz-7_R=<+(L1UFh8giJWd;u91eakkbJep^;w)U@dk zscaFusEWPK+qUJ#FU-C8@B{=$gN>Qn(PMQ3GGRSek8J`k-GGH@%asorTM662i+myS z5KGtUmxWU-Ob{OSrG$S}?d`)d+=`MZjfsMIp8m>J@KS#E!xcQh(MCCoiELJl6~e6e z*nOipHHN=_7WoqH*C8QC=|AdCKx`0;|k24@eW55;zAqt6u+7Y6zh|zwk zgOz9z4PkZcDH-s7ZfCX+3<4w5kE2){l(rpUXbn47%C_leso{=IXD`yB@PiCL27>?umBGK?;Z~I&Pcs>T22nn%>?js>FN;k z*|IMRz4#8gmPMy#AGQtoqnJini&V{a%DB4L^G7ny16J!NYGB5OYt5W!Shfh0eSoio zxmFRWP-in(6B)zGVF`j4jA7_`eog z-~HEFYhVBX9`OHU#_)esT9SWhoc#A0LuDsC`?-6H6;jxVSG{ zXl((;ehNCK5z0bn1wumy(sZLR$CZ~x-cs=T)USjMh>4|2IoHC*@v7`v)#U$0CWM+xt+LJlM<**O={ zcE@1YF7{qmcXk$J5Y;S;?n5dB1?r?L+e3dteFkR)mhQLGFQqHkgEuiGqf8s*+IH)- zOe+rniDJxN7juF}VIW=tL){+c1~R6i9LJlnH}dd?Hn{RO$~?uY>DH{_t}#^#Kp&4R z<@~YKq^DRY35!yK$xux9CslZ^W%-n{y9(`>ei|JuyAQt=l3gE+Ovk0+=5AybEMuD! zvDzo$5c=fqdn#><3ibnrZ{9dF7~WpO4Dy!*aHr+0D2#l2kTB)TLMUR$V0y!aF! z!(A6*jiNPNL@;Sf&|f+?V8YOMi#KUnmpTL2QeF=O_Sc3@BuT0w)N~QQFwpy?y$K;( zO0}(M1^tWgXMh7Kn`{8Ic%u+ya|Z}a5K}K)0g9N{N8wgL#9Q>(hkxTwb~Uv{vZ}w_ zkUc~ZulqLm80b5dAwKH?e(?PR0AJ`3?@x%{mi+-b7_`jr-vswC-8a>KGDb&4y>#MRIEkE98qAn~vU=8YFH>1unoN3?79? zoU(Cb#$NFzkjdzYfmxy-^nYdeG)&3UmM#8Js{?KGVBxJ2WU%CZ<7D{D376;5M@jHMpdl!NH?m72#U%-;=F4M z#HEgO$wDHu6rZ`>4NrnJ>e)@3;peDw;P!{NeFvPZG$r?rG8OG6ZD^9AvcFCwPkJMu zy0^9LD2o{s5NNtSI`UN8TCn;duUVr38uCn7a+O7R>?2eN^FduestiQ=*bIP}+sO8L zS=4wC?%~=1RzRx_0|+*&(jJvwl@$AkqZp;XJ)D4X55ZM$Q0v2~{$=CP;sS>0?AX{s zjTvz}r7lC8+~vwJONvo3XzOdTY-p5bSV@O_o4(DGFUQ>=%wgSbv+H)aD$21Pb;?(D z15TarUY)G2n4iPdZqD1T2)vGtwAleo7np{AFxomy(( z^PeH5vG_!zn4Mwro&kT1nk9`lcb6QXXA@$IV$u)qn*@T_5jZ#KJvSf@sRMjD@mOqZZ%c> zx8J@qR3D~*EnMQ_4q^r26t}i*^{hgF;Uf zX+&_?SYM%!R;9rHhM%AqtxVP|R_EdjC+CMwgNNk>(C0>>81-$W2!d#)Ds`hY7P?$Z zOX&DS>#%Iw3K$v1rC)!$a9kd@5(>rELz+b@e+GkB{Sm|u*uSET@5Ogd{SV4@VE@S; zc>fb+IYUbmqyK9?#^Bj1mBALINY2U+50qCd_9rULCsGukj0Il8^nteN=g)Lr^nX

o^Zwi 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 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index 4ab125693c..a8d309b24e 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-19 +android.library.reference.1=../MPChartLib diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 32102fab94..c43a434c27 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -127,7 +127,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -140,7 +140,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -153,7 +153,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index efef8ce87d..0fc081710d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -44,7 +44,7 @@ protected void onCreate(Bundle savedInstanceState) { private void addEntry() { - LineData data = mChart.getDataOriginal(); + LineData data = mChart.getData(); if(data != null) { @@ -68,7 +68,7 @@ private void addEntry() { private void removeLastEntry() { - LineData data = mChart.getDataOriginal(); + LineData data = mChart.getData(); if(data != null) { @@ -90,7 +90,7 @@ private void removeLastEntry() { private void addDataSet() { - LineData data = mChart.getDataOriginal(); + LineData data = mChart.getData(); if(data != null) { @@ -120,7 +120,7 @@ private void addDataSet() { private void removeDataSet() { - LineData data = mChart.getDataOriginal(); + LineData data = mChart.getData(); if(data != null) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 7ee24f6e0c..e7fa55a40b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -154,7 +154,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -167,7 +167,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java index 84a1f69929..9cf0ad6700 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java @@ -125,11 +125,11 @@ protected void onCreate(Bundle savedInstanceState) { mChart.animateX(2500); - // // restrain the maximum scale-out factor - // mChart.setScaleMinima(3f, 3f); - // - // // center the view to a specific position inside the chart - // mChart.centerViewPort(10, 50); +// // restrain the maximum scale-out factor +// mChart.setScaleMinima(3f, 3f); +// +// // center the view to a specific position inside the chart +// mChart.centerViewPort(10, 50); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); @@ -170,7 +170,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -183,7 +183,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -196,7 +196,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index cd33e80a53..2d32dd7818 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -114,7 +114,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { @@ -127,7 +127,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (LineDataSet set : sets) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index b5368a04e1..a8c01f651a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -117,7 +117,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getDataCurrent() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); for (RadarDataSet set : sets) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 6a3425d84e..7ca4934e5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -96,26 +96,26 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX++; // extend xDelta to make space for multiple datasets (if ther are one) - mDeltaX *= mOriginalData.getDataSetCount(); + mDeltaX *= mData.getDataSetCount(); int maxEntry = 0; - for (int i = 0; i < mOriginalData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { - DataSet set = mOriginalData.getDataSetByIndex(i); + DataSet set = mData.getDataSetByIndex(i); if (maxEntry < set.getEntryCount()) maxEntry = set.getEntryCount(); } - float groupSpace = mOriginalData.getGroupSpace(); + float groupSpace = mData.getGroupSpace(); mDeltaX += maxEntry * groupSpace; } @Override protected void drawHighlights() { - int setCount = mOriginalData.getDataSetCount(); + int setCount = mData.getDataSetCount(); for (int i = 0; i < mIndicesToHightlight.length; i++) { @@ -123,7 +123,7 @@ protected void drawHighlights() { int index = h.getXIndex(); int dataSetIndex = h.getDataSetIndex(); - BarDataSet set = (BarDataSet) mCurrentData.getDataSetByIndex(dataSetIndex); + BarDataSet set = (BarDataSet) mData.getDataSetByIndex(dataSetIndex); if (set == null) continue; @@ -132,8 +132,8 @@ protected void drawHighlights() { mHighlightPaint.setAlpha(set.getHighLightAlpha()); // check outofbounds - if (index < mCurrentData.getYValCount() && index >= 0 - && index < (mDeltaX * mPhaseX) / mOriginalData.getDataSetCount()) { + if (index < mData.getYValCount() && index >= 0 + && index < (mDeltaX * mPhaseX) / mData.getDataSetCount()) { Entry e = getEntryByDataSetIndex(index, dataSetIndex); @@ -141,8 +141,8 @@ protected void drawHighlights() { continue; // calculate the correct x-position - float x = index * setCount + dataSetIndex + mOriginalData.getGroupSpace() / 2f - + mOriginalData.getGroupSpace() * index; + float x = index * setCount + dataSetIndex + mData.getGroupSpace() / 2f + + mData.getGroupSpace() * index; float y = e.getVal(); prepareBar(x, y, set.getBarSpace()); @@ -161,7 +161,7 @@ protected void drawHighlights() { arrow.lineTo(x + 0.2f, y + offsetY); arrow.lineTo(x + 0.8f, y + offsetY); - transformPath(arrow); + mTrans.pathValueToPixel(arrow); mDrawCanvas.drawPath(arrow, mHighlightPaint); } } @@ -171,11 +171,11 @@ protected void drawHighlights() { @Override protected void drawData() { - ArrayList dataSets = mOriginalData.getDataSets(); - int setCount = mOriginalData.getDataSetCount(); + ArrayList dataSets = mData.getDataSets(); + int setCount = mData.getDataSetCount(); // the space between bar-groups - float space = mOriginalData.getGroupSpace(); + float space = mData.getGroupSpace(); // 2D drawing for (int i = 0; i < setCount; i++) { @@ -289,7 +289,7 @@ private void prepareBar(float x, float y, float barspace) { mBarRect.set(left, top, right, bottom); - transformRectWithPhase(mBarRect); + mTrans.rectValueToPixel(mBarRect, mPhaseY); // if a shadow is drawn, prepare it too if (mDrawBarShadow) { @@ -305,27 +305,27 @@ protected void drawXLabels(float yPos) { 0f, 0f }; - int step = mCurrentData.getDataSetCount(); + int step = mData.getDataSetCount(); - for (int i = 0; i < mCurrentData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { - position[0] = i * step + i * mOriginalData.getGroupSpace() - + mOriginalData.getGroupSpace() / 2f; + position[0] = i * step + i * mData.getGroupSpace() + + mData.getGroupSpace() / 2f; // center the text if (mXLabels.isCenterXLabelsEnabled()) position[0] += (step / 2f); - transformPointArray(position); + mTrans.pointValuesToPixel(position); if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { - String label = mCurrentData.getXVals().get(i); + String label = mData.getXVals().get(i); if (mXLabels.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mCurrentData.getXValCount() - 1) { + if (i == mData.getXValCount() - 1) { float width = Utils.calcTextWidth(mXLabelPaint, label); if (width > getOffsetRight() * 2 && position[0] + width > getWidth()) @@ -349,7 +349,7 @@ protected void drawXLabels(float yPos) { @Override protected void drawVerticalGrid() { - if (!mDrawVerticalGrid || mCurrentData == null) + if (!mDrawVerticalGrid || mData == null) return; float[] position = new float[] { @@ -357,13 +357,13 @@ protected void drawVerticalGrid() { }; // take into consideration that multiple DataSets increase mDeltaX - int step = mCurrentData.getDataSetCount(); + int step = mData.getDataSetCount(); - for (int i = 0; i < mCurrentData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { - position[0] = i * step + i * mOriginalData.getGroupSpace(); + position[0] = i * step + i * mData.getGroupSpace(); - transformPointArray(position); + mTrans.pointValuesToPixel(position); if (position[0] >= mOffsetLeft && position[0] <= getWidth()) { @@ -377,9 +377,9 @@ protected void drawVerticalGrid() { protected void drawValues() { // if values are drawn - if (mDrawYValues && mCurrentData.getYValCount() < mMaxVisibleCount * mScaleX) { + if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - ArrayList dataSets = ((BarData) mCurrentData).getDataSets(); + ArrayList dataSets = ((BarData) mData).getDataSets(); float posOffset = 0f; float negOffset = 0f; @@ -393,12 +393,12 @@ protected void drawValues() { negOffset = -Utils.convertDpToPixel(5); } - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { BarDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); - float[] valuePoints = generateTransformedValuesBarChart(entries, i); + float[] valuePoints = mTrans.generateTransformedValuesBarChart(entries, i, mData, mPhaseY); // if only single values are drawn (sum) if (!mDrawValuesForWholeStack) { @@ -455,7 +455,7 @@ protected void drawValues() { cnt++; } - transformPointArray(transformed); + mTrans.pointValuesToPixel(transformed); for (int k = 0; k < transformed.length; k += 2) { @@ -502,7 +502,7 @@ private void drawValue(float val, float xPos, float yPos) { @Override public Highlight getHighlightByTouchPoint(float x, float y) { - if (mDataNotSet || mCurrentData == null) { + if (mDataNotSet || mData == null) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } @@ -512,17 +512,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { pts[0] = x; pts[1] = y; - Matrix tmp = new Matrix(); - - // invert all matrixes to convert back to the original value - mMatrixOffset.invert(tmp); - tmp.mapPoints(pts); - - mMatrixTouch.invert(tmp); - tmp.mapPoints(pts); - - mMatrixValueToPx.invert(tmp); - tmp.mapPoints(pts); + mTrans.pixelsToValue(pts); // for barchart, we only need x-val double xTouchVal = pts[0]; @@ -536,13 +526,13 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (base >= mDeltaX) base = mDeltaX - 1; - int setCount = mOriginalData.getDataSetCount(); - int valCount = setCount * mOriginalData.getXValCount(); + int setCount = mData.getDataSetCount(); + int valCount = setCount * mData.getXValCount(); // calculate the amount of bar-space between index 0 and touch position float space = (float) (((float) valCount / (float) setCount) / (mDeltaX / base)); - float reduction = (float) space * mOriginalData.getGroupSpace(); + float reduction = (float) space * mData.getGroupSpace(); int xIndex = (int) ((base - reduction) / setCount); @@ -564,7 +554,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { */ public RectF getBarBounds(BarEntry e) { - BarDataSet set = mOriginalData.getDataSetForEntry(e); + BarDataSet set = mData.getDataSetForEntry(e); if (set == null) return null; @@ -581,7 +571,7 @@ public RectF getBarBounds(BarEntry e) { RectF bounds = new RectF(left, top, right, bottom); - transformRect(bounds); + mTrans.rectValueToPixel(bounds); return bounds; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 0877703d86..ee7c6ff0de 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -45,36 +45,12 @@ public abstract class BarLineChartBase>> extends Chart { - /** if set to true, the y-axis is inverted and low values start at the top */ - private boolean mInvertYAxis = false; - /** the maximum number of entried to which values will be drawn */ protected int mMaxVisibleCount = 100; - /** minimum scale value on the y-axis */ - private float mMinScaleY = 1f; - - /** minimum scale value on the x-axis */ - private float mMinScaleX = 1f; - - /** contains the current scale factor of the x-axis */ - protected float mScaleX = 1f; - - /** contains the current scale factor of the y-axis */ - protected float mScaleY = 1f; - - /** holds the maximum scale factor of the y-axis, default 12f */ - protected float mMaxScaleY = 12f; - /** the width of the grid lines */ protected float mGridWidth = 1f; - /** offset that allows the chart to be dragged over its bounds on the x-axis */ - private float mTransOffsetX = 0f; - - /** offset that allows the chart to be dragged over its bounds on the x-axis */ - private float mTransOffsetY = 0f; - /** * flag that indicates if pinch-zoom is enabled. if true, both x and y axis * can be scaled with 2 fingers, if false, x and y axis can be scaled @@ -164,7 +140,7 @@ public BarLineChartBase(Context context) { protected void init() { super.init(); - mListener = new BarLineChartTouchListener(this, mMatrixTouch); + mListener = new BarLineChartTouchListener(this, mTrans.getTouchMatrix()); mGridPaint = new Paint(); mGridPaint.setColor(Color.GRAY); @@ -195,13 +171,13 @@ protected void onDraw(Canvas canvas) { // if data filtering is enabled if (mFilterData) { - mCurrentData = getFilteredData(); + mData = getFilteredData(); Log.i(LOG_TAG, "FilterTime: " + (System.currentTimeMillis() - starttime) + " ms"); starttime = System.currentTimeMillis(); } else { - mCurrentData = getDataOriginal(); + mData = getData(); // Log.i(LOG_TAG, "Filtering disabled."); } @@ -282,58 +258,20 @@ public void prepare() { */ private void prepareMatrix() { - prepareMatrixValuePx(); + mTrans.prepareMatrixValuePx(this); - prepareMatrixOffset(); + mTrans.prepareMatrixOffset(this); if (mLogEnabled) Log.i(LOG_TAG, "Matrices prepared."); } - /** - * Prepares the matrix that transforms values to pixels. - */ - private void prepareMatrixValuePx() { - - float scaleX = (float) ((getWidth() - mOffsetRight - mOffsetLeft) / mDeltaX); - float scaleY = (float) ((getHeight() - mOffsetTop - mOffsetBottom) / mDeltaY); - - // setup all matrices - mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -mYChartMin); - mMatrixValueToPx.postScale(scaleX, -scaleY); - } - - /** - * Prepares the matrix that contains all offsets. - */ - private void prepareMatrixOffset() { - - mMatrixOffset.reset(); - - // offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); - - if (!mInvertYAxis) - mMatrixOffset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); - else { - mMatrixOffset.setTranslate(mOffsetLeft, -mOffsetTop); - mMatrixOffset.postScale(1.0f, -1.0f); - } - - // mMatrixOffset.set(offset); - - // mMatrixOffset.reset(); - // - // mMatrixOffset.postTranslate(mOffsetLeft, getHeight() - - // mOffsetBottom); - } - @Override public void notifyDataSetChanged() { if (!mFixedYValues) { prepare(); // prepareContentRect(); - prepareMatrixValuePx(); + mTrans.prepareMatrixValuePx(this); } else { calcMinMax(mFixedYValues); } @@ -433,10 +371,10 @@ protected void calculateOffsets() { mOffsetLeft = Math.max(min, yleft); mOffsetRight = Math.max(min, yright + legendRight); - - if(mLegend != null) { - - // those offsets are equal for legend and other chart, just apply them + if (mLegend != null) { + + // those offsets are equal for legend and other chart, just apply + // them mLegend.setOffsetTop(mOffsetTop + min / 3f); mLegend.setOffsetLeft(mOffsetLeft); } @@ -476,10 +414,10 @@ public void calculateLegendOffsets() { protected void calcModulus() { float[] values = new float[9]; - mMatrixTouch.getValues(values); + mTrans.getTouchMatrix().getValues(values); mXLabels.mXAxisLabelModulus = (int) Math - .ceil((mCurrentData.getXValCount() * mXLabels.mLabelWidth) + .ceil((mData.getXValCount() * mXLabels.mLabelWidth) / (mContentRect.width() * values[Matrix.MSCALE_X])); } @@ -493,15 +431,13 @@ protected void calcMinMax(boolean fixedValues) { // float space = Math.abs(mDeltaY / 100f * 15f); float space = Math .abs(Math.abs(Math.max(Math.abs(mYChartMax), Math.abs(mYChartMin))) / 100f * 20f); - + if (Math.abs(mYChartMax - mYChartMin) < 0.00001f) { if (Math.abs(mYChartMax) < 10f) space = 1f; else space = Math.abs(mYChartMax / 100f * 20f); } - - Log.i(LOG_TAG, "Space: " + space); if (mStartAtZero) { @@ -531,7 +467,7 @@ protected void prepareXLabels() { StringBuffer a = new StringBuffer(); - int max = (int) Math.round(mCurrentData.getXValAverageLength() + int max = (int) Math.round(mData.getXValAverageLength() + mXLabels.getSpaceBetweenLabels()); for (int i = 0; i < max; i++) { @@ -556,12 +492,12 @@ private void prepareYLabels() { // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) - if (mContentRect.width() > 10 && !isFullyZoomedOutY()) { + if (mContentRect.width() > 10 && !mTrans.isFullyZoomedOutY()) { PointD p1 = getValuesByTouchPoint(mContentRect.left, mContentRect.top); PointD p2 = getValuesByTouchPoint(mContentRect.left, mContentRect.bottom); - if (!mInvertYAxis) { + if (!mTrans.isInvertYAxisEnabled()) { yMin = (float) p2.y; yMax = (float) p1.y; } else { @@ -575,7 +511,7 @@ private void prepareYLabels() { } else { - if (!mInvertYAxis) { + if (!mTrans.isInvertYAxisEnabled()) { yMin = mYChartMin; yMax = mYChartMax; } else { @@ -695,7 +631,7 @@ protected void drawXLabels(float yPos) { 0f, 0f }; - for (int i = 0; i < mCurrentData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { position[0] = i; @@ -703,16 +639,16 @@ protected void drawXLabels(float yPos) { if (mXLabels.isCenterXLabelsEnabled()) position[0] += 0.5f; - transformPointArray(position); + mTrans.pointValuesToPixel(position); if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { - String label = mCurrentData.getXVals().get(i); + String label = mData.getXVals().get(i); if (mXLabels.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mCurrentData.getXValCount() - 1) { + if (i == mData.getXValCount() - 1) { float width = Utils.calcTextWidth(mXLabelPaint, label); if (width > getOffsetRight() * 2 && position[0] + width > getWidth()) @@ -750,7 +686,7 @@ private void drawYLabels() { positions[i + 1] = mYLabels.mEntries[i / 2]; } - transformPointArray(positions); + mTrans.pointValuesToPixel(positions); mYLabelPaint.setTypeface(mYLabels.getTypeface()); mYLabelPaint.setTextSize(mYLabels.getTextSize()); @@ -893,7 +829,7 @@ protected void drawHorizontalGrid() { for (int i = 0; i < mYLabels.mEntryCount; i++) { position[1] = mYLabels.mEntries[i]; - transformPointArray(position); + mTrans.pointValuesToPixel(position); mDrawCanvas.drawLine(mOffsetLeft, position[1], getWidth() - mOffsetRight, position[1], mGridPaint); @@ -905,18 +841,18 @@ protected void drawHorizontalGrid() { */ protected void drawVerticalGrid() { - if (!mDrawVerticalGrid || mCurrentData == null) + if (!mDrawVerticalGrid || mData == null) return; float[] position = new float[] { 0f, 0f }; - for (int i = 0; i < mCurrentData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { position[0] = i; - transformPointArray(position); + mTrans.pointValuesToPixel(position); if (position[0] >= mOffsetLeft && position[0] <= getWidth()) { @@ -931,7 +867,7 @@ protected void drawVerticalGrid() { */ private void drawLimitLines() { - ArrayList limitLines = mOriginalData.getLimitLines(); + ArrayList limitLines = mData.getLimitLines(); if (limitLines == null) return; @@ -945,7 +881,7 @@ private void drawLimitLines() { pts[1] = l.getLimit(); pts[3] = l.getLimit(); - transformPointArray(pts); + mTrans.pointValuesToPixel(pts); pts[0] = 0; pts[2] = getWidth(); @@ -1069,34 +1005,19 @@ public boolean onTouchEvent(MotionEvent event) { /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ /** - * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom - * center. - * - * @param x - * @param y + * Zooms in by 1.4f, into the charts center. center. */ - public void zoomIn(float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(1.4f, 1.4f, x, y); - - refreshTouch(save); + public void zoomIn() { + Matrix save = mTrans.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); + mTrans.refresh(save, this); } /** - * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom - * center. + * Zooms out by 0.7f, from the charts center. center. */ - public void zoomOut(float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(0.7f, 0.7f, x, y); - - refreshTouch(save); + public void zoomOut() { + Matrix save = mTrans.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); + mTrans.refresh(save, this); } /** @@ -1109,15 +1030,8 @@ public void zoomOut(float x, float y) { * @param y */ public void zoom(float scaleX, float scaleY, float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - // Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y); - - save.postScale(scaleX, scaleY, x, -y); - - refreshTouch(save); + Matrix save = mTrans.zoom(scaleX, scaleY, x, -y); + mTrans.refresh(save, this); } /** @@ -1125,23 +1039,8 @@ public void zoom(float scaleX, float scaleY, float x, float y) { * bounds. */ public void fitScreen() { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - float[] vals = new float[9]; - - save.getValues(vals); - - // reset all translations and scaling - vals[Matrix.MTRANS_X] = 0f; - vals[Matrix.MTRANS_Y] = 0f; - vals[Matrix.MSCALE_X] = 1f; - vals[Matrix.MSCALE_Y] = 1f; - - save.setValues(vals); - - refreshTouch(save); + Matrix save = mTrans.fitScreen(); + mTrans.refresh(save, this); } /** @@ -1151,7 +1050,7 @@ public void fitScreen() { * @param enabled */ public void setInvertYAxisEnabled(boolean enabled) { - mInvertYAxis = enabled; + mTrans.setInvertYAxisEnabled(enabled); } /** @@ -1160,7 +1059,7 @@ public void setInvertYAxisEnabled(boolean enabled) { * @return */ public boolean isInvertYAxisEnabled() { - return mInvertYAxis; + return mTrans.isInvertYAxisEnabled(); } /** @@ -1175,112 +1074,17 @@ public boolean isInvertYAxisEnabled() { */ public synchronized void centerViewPort(final int xIndex, final float yVal) { - // the post makes it possible that this call waits until the view has - // finisted setting up - post(new Runnable() { - - @Override - public void run() { - - float indicesInView = mDeltaX / mScaleX; - float valsInView = mDeltaY / mScaleY; - - // Log.i(LOG_TAG, "indices: " + indicesInView + ", vals: " + - // valsInView); - - float[] pts = new float[] { - xIndex - indicesInView / 2f, yVal + valsInView / 2f - }; - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - transformPointArray(pts); - - final float x = -pts[0] + getOffsetLeft(); - final float y = -pts[1] - getOffsetTop(); - - save.postTranslate(x, y); - - refreshTouch(save); - - // Log.i(LOG_TAG, "ViewPort centered, xIndex: " + xIndex + - // ", yVal: " + yVal - // + ", transX: " + x + ", transY: " + y); - } - }); - } - - /** - * call this method to refresh the graph with a given touch matrix - * - * @param newTouchMatrix - * @return - */ - public Matrix refreshTouch(Matrix newTouchMatrix) { - - mMatrixTouch.set(newTouchMatrix); - - // make sure scale and translation are within their bounds - limitTransAndScale(mMatrixTouch); - - // redraw - invalidate(); - - newTouchMatrix.set(mMatrixTouch); - return newTouchMatrix; - } - - /** - * limits the maximum scale and X translation of the given matrix - * - * @param matrix - */ - protected void limitTransAndScale(Matrix matrix) { - - float[] vals = new float[9]; - matrix.getValues(vals); - - float curTransX = vals[Matrix.MTRANS_X]; - float curScaleX = vals[Matrix.MSCALE_X]; - - float curTransY = vals[Matrix.MTRANS_Y]; - float curScaleY = vals[Matrix.MSCALE_Y]; - - // Log.i(LOG_TAG, "curTransX: " + curTransX + ", curScaleX: " + - // curScaleX); - // Log.i(LOG_TAG, "curTransY: " + curTransY + ", curScaleY: " + - // curScaleY); - - // min scale-x is 1f - mScaleX = Math.max(mMinScaleX, Math.min(getMaxScaleX(), curScaleX)); + float indicesInView = mDeltaX / mTrans.getScaleX(); + float valsInView = mDeltaY / mTrans.getScaleY(); - // min scale-y is 1f - mScaleY = Math.max(mMinScaleY, Math.min(getMaxScaleY(), curScaleY)); + Log.i(LOG_TAG, "indices: " + indicesInView + ", vals: " + + valsInView); - if (mContentRect == null) - return; - - float maxTransX = -(float) mContentRect.width() * (mScaleX - 1f); - float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); - - float maxTransY = (float) mContentRect.height() * (mScaleY - 1f); - float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); - - // Log.i(LOG_TAG, "scale-X: " + mScaleX + ", maxTransX: " + maxTransX + - // ", newTransX: " - // + newTransX); - // Log.i(LOG_TAG, "scale-Y: " + mScaleY + ", maxTransY: " + maxTransY + - // ", newTransY: " - // + newTransY); - - vals[Matrix.MTRANS_X] = newTransX; - vals[Matrix.MSCALE_X] = mScaleX; - - vals[Matrix.MTRANS_Y] = newTransY; - vals[Matrix.MSCALE_Y] = mScaleY; + float[] pts = new float[] { + xIndex - indicesInView / 2f, yVal + valsInView / 2f + }; - matrix.setValues(vals); + mTrans.centerViewPort(pts, this); } /** @@ -1307,44 +1111,6 @@ public void setOnDrawListener(OnDrawListener drawListener) { this.mDrawListener = drawListener; } - // /** - // * set if the user should be allowed to draw onto the chart - // * - // * @param drawingEnabled - // */ - // public void setDrawingEnabled(boolean drawingEnabled) { - // if (mListener instanceof BarLineChartTouchListener) { - // ((BarLineChartTouchListener) - // mListener).setDrawingEnabled(drawingEnabled); - // } - // } - // - // /** - // * boolean to indicate if user drawing on chart should automatically be - // * finished - // */ - // protected boolean mAutoFinishDrawing; - // - // /** - // * Set to true to auto finish user drawing. THis means that the value that - // * has been drawn into the chart is filled up to the maximum x-index - // * automatically. - // * - // * @param enabled - // */ - // public void setAutoFinish(boolean enabled) { - // this.mAutoFinishDrawing = enabled; - // } - // - // /** - // * True if auto finish user drawing is enabled - // * - // * @return - // */ - // public boolean isAutoFinishEnabled() { - // return mAutoFinishDrawing; - // } - /** * Gets the OnDrawListener. May be null. * @@ -1363,16 +1129,7 @@ public OnDrawListener getDrawListener() { * @param scaleYmin */ public void setScaleMinima(float scaleXmin, float scaleYmin) { - - if (scaleXmin < 1f) - scaleXmin = 1f; - if (scaleYmin < 1f) - scaleYmin = 1f; - - mMinScaleX = scaleXmin; - mMinScaleY = scaleYmin; - - zoom(mMinScaleX, mMinScaleY, 0f, 0f); + mTrans.setScaleMinima(scaleXmin, scaleYmin, this); } /** @@ -1453,12 +1210,12 @@ public PointF getPosition(Entry e) { if (this instanceof BarChart) { - BarDataSet set = (BarDataSet) mOriginalData.getDataSetForEntry(e); + BarDataSet set = (BarDataSet) mData.getDataSetForEntry(e); if (set != null) vals[0] += set.getBarSpace() / 2f; } - transformPointArray(vals); + mTrans.pointValuesToPixel(vals); return new PointF(vals[0], vals[1]); } @@ -1706,7 +1463,7 @@ public BorderPosition[] getBorderPositions() { */ public Highlight getHighlightByTouchPoint(float x, float y) { - if (mDataNotSet || mCurrentData == null) { + if (mDataNotSet || mData == null) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } @@ -1716,17 +1473,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { pts[0] = x; pts[1] = y; - Matrix tmp = new Matrix(); - - // invert all matrixes to convert back to the original value - mMatrixOffset.invert(tmp); - tmp.mapPoints(pts); - - mMatrixTouch.invert(tmp); - tmp.mapPoints(pts); - - mMatrixValueToPx.invert(tmp); - tmp.mapPoints(pts); + mTrans.pixelsToValue(pts); double xTouchVal = pts[0]; double yTouchVal = pts[1]; @@ -1793,17 +1540,7 @@ public PointD getValuesByTouchPoint(float x, float y) { pts[0] = x; pts[1] = y; - Matrix tmp = new Matrix(); - - // invert all matrixes to convert back to the original value - mMatrixOffset.invert(tmp); - tmp.mapPoints(pts); - - mMatrixTouch.invert(tmp); - tmp.mapPoints(pts); - - mMatrixValueToPx.invert(tmp); - tmp.mapPoints(pts); + mTrans.pixelsToValue(pts); double xTouchVal = pts[0]; double yTouchVal = pts[1]; @@ -1825,7 +1562,7 @@ public PointD getPixelsForValues(float x, float y) { x, y }; - transformPointArray(pts); + mTrans.pointValuesToPixel(pts); return new PointD(pts[0], pts[1]); } @@ -1852,7 +1589,7 @@ public float getYValueByTouchPoint(float x, float y) { public Entry getEntryByTouchPoint(float x, float y) { Highlight h = getHighlightByTouchPoint(x, y); if (h != null) { - return mCurrentData.getEntryForHighlight(h); + return mData.getEntryForHighlight(h); } return null; } @@ -1861,14 +1598,14 @@ public Entry getEntryByTouchPoint(float x, float y) { * returns the current x-scale factor */ public float getScaleX() { - return mScaleX; + return mTrans.getScaleX(); } /** * returns the current y-scale factor */ public float getScaleY() { - return mScaleY; + return mTrans.getScaleY(); } /** @@ -1877,69 +1614,7 @@ public float getScaleY() { * @return */ public boolean isFullyZoomedOut() { - - if (isFullyZoomedOutX() && isFullyZoomedOutY()) - return true; - else - return false; - } - - /** - * Returns true if the chart is fully zoomed out on it's y-axis (vertical). - * - * @return - */ - public boolean isFullyZoomedOutY() { - if (mScaleY > mMinScaleY || mMinScaleY > 1f) - return false; - else - return true; - } - - /** - * Returns true if the chart is fully zoomed out on it's x-axis - * (horizontal). - * - * @return - */ - public boolean isFullyZoomedOutX() { - if (mScaleX > mMinScaleX || mMinScaleX > 1f) - return false; - else - return true; - } - - /** - * calcualtes the maximum x-scale value depending on the number of x-values, - * maximum scale is numberOfXvals / 2 - * - * @return - */ - public float getMaxScaleX() { - return mDeltaX / 2f; - } - - /** - * Returns the maximum y-scale factor. Default 10f - * - * @return - */ - public float getMaxScaleY() { - return mMaxScaleY; - } - - /** - * sets the maximum scale factor for the y-axis. Default 12f, min 1f, max - * unlimited - * - * @param factor - */ - public void setMaxScaleY(float factor) { - - if (factor < 1f) - factor = 1f; - - mMaxScaleY = factor; + return mTrans.isFullyZoomedOut(); } /** @@ -2017,7 +1692,7 @@ public boolean isPinchZoomEnabled() { * @param offset */ public void setDragOffsetX(float offset) { - mTransOffsetX = Utils.convertDpToPixel(offset); + mTrans.setDragOffsetX(offset); } /** @@ -2027,7 +1702,7 @@ public void setDragOffsetX(float offset) { * @param offset */ public void setDragOffsetY(float offset) { - mTransOffsetY = Utils.convertDpToPixel(offset); + mTrans.setDragOffsetY(offset); } /** @@ -2036,7 +1711,7 @@ public void setDragOffsetY(float offset) { * @return */ public boolean hasNoDragOffset() { - return mTransOffsetX <= 0 && mTransOffsetY <= 0 ? true : false; + return mTrans.hasNoDragOffset(); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 742b4417b8..e9e60e73eb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -41,13 +41,13 @@ protected void calcMinMax(boolean fixedValues) { @Override protected void drawData() { - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); // pre allocate float[] shadowPoints = new float[4]; float[] bodyPoints = new float[4]; - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { CandleDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); @@ -121,7 +121,7 @@ private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace) { bodyPoints[2] = e.getXIndex() + (1f - bodySpace); bodyPoints[3] = e.getOpen() * mPhaseY; - transformPointArray(bodyPoints); + mTrans.pointValuesToPixel(bodyPoints); } /** @@ -137,7 +137,7 @@ private void transformShadow(float[] shadowPoints, CandleEntry e) { shadowPoints[2] = e.getXIndex() + 0.5f; shadowPoints[3] = e.getLow() * mPhaseY; - transformPointArray(shadowPoints); + mTrans.pointValuesToPixel(shadowPoints); } @Override @@ -160,7 +160,7 @@ protected void drawHighlights() { int xIndex = mIndicesToHightlight[i].getXIndex(); // get the // x-position - CandleDataSet set = mOriginalData.getDataSetByIndex(mIndicesToHightlight[i].getDataSetIndex()); + CandleDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i].getDataSetIndex()); if (set == null) continue; @@ -183,8 +183,8 @@ protected void drawHighlights() { 0, low, mDeltaX, low, 0, high, mDeltaX, high }; - transformPointArray(vertPts); - transformPointArray(horPts); + mTrans.pointValuesToPixel(vertPts); + mTrans.pointValuesToPixel(horPts); // draw the vertical highlight lines mDrawCanvas.drawLines(vertPts, mHighlightPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 27051f1817..66e91a0305 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -7,11 +7,9 @@ import android.graphics.Bitmap.CompressFormat; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; -import android.graphics.Path; import android.graphics.PointF; import android.graphics.RectF; import android.graphics.Typeface; @@ -30,8 +28,10 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.renderer.Transformer; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Legend; import com.github.mikephil.charting.utils.Legend.LegendPosition; @@ -56,7 +56,7 @@ * @author Philipp Jahoda */ public abstract class Chart>> extends View - implements AnimatorUpdateListener { + implements AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; @@ -90,17 +90,11 @@ public abstract class Chart colors = new ArrayList(); // loop for building up the colors and labels used in the legend - for (int i = 0; i < mOriginalData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { - DataSet dataSet = mOriginalData.getDataSetByIndex(i); + DataSet dataSet = mData.getDataSetByIndex(i); ArrayList clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); @@ -552,7 +545,7 @@ public void prepareLegend() { } else if (dataSet instanceof PieDataSet) { - ArrayList xVals = mOriginalData.getXVals(); + ArrayList xVals = mData.getXVals(); PieDataSet pds = (PieDataSet) dataSet; for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { @@ -575,7 +568,7 @@ public void prepareLegend() { labels.add(null); } else { // add label to the last entry - String label = mOriginalData.getDataSetByIndex(i).getLabel(); + String label = mData.getDataSetByIndex(i).getLabel(); labels.add(label); } @@ -594,166 +587,6 @@ public void prepareLegend() { mLegend = l; } - /** - * Transforms an arraylist of Entry into a float array containing the x and - * y values transformed with all matrices for the LINECHART or SCATTERCHART. - * - * @param entries - * @return - */ - protected float[] generateTransformedValuesLineScatter(ArrayList entries) { - - float[] valuePoints = new float[entries.size() * 2]; - - for (int j = 0; j < valuePoints.length; j += 2) { - - Entry e = entries.get(j / 2); - - valuePoints[j] = e.getXIndex(); - valuePoints[j + 1] = e.getVal() * mPhaseY; - } - - transformPointArray(valuePoints); - - return valuePoints; - } - - /** - * Transforms an arraylist of Entry into a float array containing the x and - * y values transformed with all matrices for the BARCHART. - * - * @param entries - * @param dataSet the dataset index - * @return - */ - protected float[] generateTransformedValuesBarChart(ArrayList entries, - int dataSet) { - - float[] valuePoints = new float[entries.size() * 2]; - - int setCount = mOriginalData.getDataSetCount(); - BarData bd = (BarData) mOriginalData; - float space = bd.getGroupSpace(); - - for (int j = 0; j < valuePoints.length; j += 2) { - - Entry e = entries.get(j / 2); - - // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + 0.5f + space * (j / 2) - + space / 2f; - float y = e.getVal(); - - valuePoints[j] = x; - valuePoints[j + 1] = y * mPhaseY; - } - - transformPointArray(valuePoints); - - return valuePoints; - } - - /** - * transform a path with all the given matrices VERY IMPORTANT: keep order - * to value-touch-offset - * - * @param path - */ - protected void transformPath(Path path) { - - path.transform(mMatrixValueToPx); - path.transform(mMatrixTouch); - path.transform(mMatrixOffset); - } - - /** - * Transforms multiple paths will all matrices. - * - * @param paths - */ - protected void transformPaths(ArrayList paths) { - - for (int i = 0; i < paths.size(); i++) { - transformPath(paths.get(i)); - } - } - - /** - * Transform an array of points with all matrices. VERY IMPORTANT: Keep - * matrix order "value-touch-offset" when transforming. - * - * @param pts - */ - protected void transformPointArray(float[] pts) { - - mMatrixValueToPx.mapPoints(pts); - mMatrixTouch.mapPoints(pts); - mMatrixOffset.mapPoints(pts); - } - - /** - * Transform a rectangle with all matrices. - * - * @param r - */ - protected void transformRect(RectF r) { - - mMatrixValueToPx.mapRect(r); - mMatrixTouch.mapRect(r); - mMatrixOffset.mapRect(r); - } - - /** - * Transform a rectangle with all matrices with potential animation phases. - * - * @param r - */ - protected void transformRectWithPhase(RectF r) { - - // multiply the height of the rect with the phase - if (r.top > 0) - r.top *= mPhaseY; - else - r.bottom *= mPhaseY; - - mMatrixValueToPx.mapRect(r); - mMatrixTouch.mapRect(r); - mMatrixOffset.mapRect(r); - } - - /** - * transforms multiple rects with all matrices - * - * @param rects - */ - protected void transformRects(ArrayList rects) { - - for (int i = 0; i < rects.size(); i++) - transformRect(rects.get(i)); - } - - /** - * transforms the given rect objects with the touch matrix only - * - * @param paths - */ - protected void transformRectsTouch(ArrayList rects) { - for (int i = 0; i < rects.size(); i++) { - mMatrixTouch.mapRect(rects.get(i)); - } - } - - /** - * transforms the given path objects with the touch matrix only - * - * @param paths - */ - protected void transformPathsTouch(ArrayList paths) { - for (int i = 0; i < paths.size(); i++) { - paths.get(i).transform(mMatrixTouch); - } - } - /** * draws the legend */ @@ -1123,8 +956,8 @@ public void highlightValues(Highlight[] highs) { */ public void highlightValue(int xIndex, int dataSetIndex) { - if (xIndex < 0 || dataSetIndex < 0 || xIndex >= mOriginalData.getXValCount() - || dataSetIndex >= mOriginalData.getDataSetCount()) { + if (xIndex < 0 || dataSetIndex < 0 || xIndex >= mData.getXValCount() + || dataSetIndex >= mData.getDataSetCount()) { highlightValues(null); } else { @@ -1242,12 +1075,12 @@ private float[] getMarkerPosition(Entry e, int dataSetIndex) { else if (this instanceof BarChart) { - BarData bd = (BarData) mCurrentData; + BarData bd = (BarData) mData; float space = bd.getGroupSpace(); - float j = mCurrentData.getDataSetByIndex(dataSetIndex) + float j = mData.getDataSetByIndex(dataSetIndex) .getEntryPosition(e); - float x = (j * (mCurrentData.getDataSetCount() - 1)) + dataSetIndex + space * j + space + float x = (j * (mData.getDataSetCount() - 1)) + dataSetIndex + space * j + space / 2f + 0.5f; xPos += x; @@ -1271,7 +1104,7 @@ else if (this instanceof BarChart) { xPos, e.getVal() * mPhaseY }; - transformPointArray(pts); + mTrans.pointValuesToPixel(pts); return pts; } @@ -1498,7 +1331,7 @@ public boolean isHighlightEnabled() { * @return */ public float getYValueSum() { - return mCurrentData.getYValueSum(); + return mData.getYValueSum(); } /** @@ -1507,7 +1340,7 @@ public float getYValueSum() { * @return */ public float getYMax() { - return mCurrentData.getYMax(); + return mData.getYMax(); } /** @@ -1534,7 +1367,7 @@ public float getYChartMax() { * @return */ public float getYMin() { - return mCurrentData.getYMin(); + return mData.getYMin(); } /** @@ -1546,13 +1379,22 @@ public float getDeltaX() { return mDeltaX; } + /** + * Returns the total range of values (on y-axis) the chart displays. + * + * @return + */ + public float getDeltaY() { + return mDeltaY; + } + /** * returns the average value of all values the chart holds * * @return */ public float getAverage() { - return getYValueSum() / mCurrentData.getYValCount(); + return getYValueSum() / mData.getYValCount(); } /** @@ -1564,7 +1406,7 @@ public float getAverage() { */ public float getAverage(String dataSetLabel) { - DataSet ds = mCurrentData.getDataSetByLabel(dataSetLabel, true); + DataSet ds = mData.getDataSetByLabel(dataSetLabel, true); return ds.getYValueSum() / ds.getEntryCount(); @@ -1576,7 +1418,7 @@ public float getAverage(String dataSetLabel) { * @return */ public int getValueCount() { - return mCurrentData.getYValCount(); + return mData.getYValCount(); } /** @@ -1793,6 +1635,17 @@ public RectF getContentRect() { return mContentRect; } + /** + * Returns the Transformer class that contains all matrices and is + * responsible for transforming values into pixels on the screen and + * backwards. + * + * @return + */ + public Transformer getTransformer() { + return mTrans; + } + /** * disables intercept touchevents */ @@ -2013,10 +1866,10 @@ public boolean isDrawYValuesEnabled() { * @return */ public String getXValue(int index) { - if (mCurrentData == null || mCurrentData.getXValCount() <= index) + if (mData == null || mData.getXValCount() <= index) return null; else - return mCurrentData.getXVals().get(index); + return mData.getXVals().get(index); } /** @@ -2028,7 +1881,7 @@ public String getXValue(int index) { * @return */ public float getYValue(int index, String dataSetLabel) { - DataSet set = mCurrentData.getDataSetByLabel(dataSetLabel, true); + DataSet set = mData.getDataSetByLabel(dataSetLabel, true); return set.getYVals().get(index).getVal(); } @@ -2040,7 +1893,7 @@ public float getYValue(int index, String dataSetLabel) { * @return */ public float getYValue(int xIndex, int dataSetIndex) { - DataSet set = mCurrentData.getDataSetByIndex(dataSetIndex); + DataSet set = mData.getDataSetByIndex(dataSetIndex); return set.getYValForXIndex(xIndex); } @@ -2052,7 +1905,7 @@ public float getYValue(int xIndex, int dataSetIndex) { * @return */ public DataSet getDataSetByIndex(int index) { - return mCurrentData.getDataSetByIndex(index); + return mData.getDataSetByIndex(index); } /** @@ -2063,7 +1916,7 @@ public DataSet getDataSetByIndex(int index) { * @return */ public DataSet getDataSetByLabel(String dataSetLabel) { - return mCurrentData.getDataSetByLabel(dataSetLabel, true); + return mData.getDataSetByLabel(dataSetLabel, true); } /** @@ -2075,7 +1928,7 @@ public DataSet getDataSetByLabel(String dataSetLabel) { * @return */ public Entry getEntry(int index) { - return mCurrentData.getDataSetByIndex(0).getYVals().get(index); + return mData.getDataSetByIndex(0).getYVals().get(index); } /** @@ -2087,7 +1940,7 @@ public Entry getEntry(int index) { * @return */ public Entry getEntry(int index, String dataSetLabel) { - return mCurrentData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); + return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); } /** @@ -2100,7 +1953,7 @@ public Entry getEntry(int index, String dataSetLabel) { * @return */ public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { - return mCurrentData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); + return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); } /** @@ -2116,10 +1969,10 @@ public ArrayList getYValsAtIndex(int xIndex) { ArrayList vals = new ArrayList(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { // extract all y-values from all DataSets at the given x-index - float yVal = mCurrentData.getDataSetByIndex(i).getYValForXIndex(xIndex); + float yVal = mData.getDataSetByIndex(i).getYValForXIndex(xIndex); if (!Float.isNaN(yVal)) { vals.add(new SelInfo(yVal, i)); @@ -2141,9 +1994,9 @@ public ArrayList getEntriesAtIndex(int xIndex) { ArrayList vals = new ArrayList(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { - DataSet set = mCurrentData.getDataSetByIndex(i); + DataSet set = mData.getDataSetByIndex(i); Entry e = set.getEntryForXIndex(xIndex); @@ -2155,18 +2008,6 @@ public ArrayList getEntriesAtIndex(int xIndex) { return vals; } - /** - * Returns the ChartData object the chart CURRENTLY represents (not - * dependant on zoom level). It contains all values and information the - * chart displays. If filtering algorithms have been applied, this returns - * the filtered state of data. - * - * @return - */ - public T getDataCurrent() { - return mCurrentData; - } - /** * Returns the ChartData object that ORIGINALLY has been set for the chart. * It contains all data in an unaltered state, before any filtering @@ -2174,8 +2015,8 @@ public T getDataCurrent() { * * @return */ - public T getDataOriginal() { - return mOriginalData; + public T getData() { + return mData; } /** @@ -2185,7 +2026,7 @@ public T getDataOriginal() { * @return */ public float getPercentOfTotal(float val) { - return val / mCurrentData.getYValueSum() * 100f; + return val / mData.getYValueSum() * 100f; } /** @@ -2384,6 +2225,11 @@ public String getFormattedValue(float value) { return mFormat.format(value); } } + + @Override + public View getChartView() { + return this; + } // @Override // protected void onAttachedToWindow() { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index bc51eb3c1a..ce39c8e3c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -54,7 +54,7 @@ protected void init() { mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.STROKE); mHighlightPaint.setStrokeWidth(2f); - mHighlightPaint.setColor(Color.rgb(255, 187, 115)); + mHighlightPaint.setColor(Color.rgb(255, 187, 115)); } @Override @@ -67,7 +67,7 @@ protected void calcMinMax(boolean fixedValues) { // mDeltaX = 1; // } - if (mDeltaX == 0 && mOriginalData.getYValCount() > 0) + if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; } @@ -76,7 +76,7 @@ protected void drawHighlights() { for (int i = 0; i < mIndicesToHightlight.length; i++) { - LineDataSet set = mOriginalData.getDataSetByIndex(mIndicesToHightlight[i] + LineDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i] .getDataSetIndex()); if (set == null) @@ -97,7 +97,7 @@ protected void drawHighlights() { xIndex, mYChartMax, xIndex, mYChartMin, 0, y, mDeltaX, y }; - transformPointArray(pts); + mTrans.pointValuesToPixel(pts); // draw the highlight lines mDrawCanvas.drawLines(pts, mHighlightPaint); } @@ -131,9 +131,9 @@ public CPoint(float x, float y) { @Override protected void drawData() { - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { LineDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); @@ -199,7 +199,7 @@ else if (j == points.size() - 1) { if (dataSet.isDrawFilledEnabled()) { float fillMin = mFillFormatter - .getFillLinePosition(dataSet, mOriginalData, mYChartMax, mYChartMin); + .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); spline.lineTo(0, fillMin); @@ -210,7 +210,7 @@ else if (j == points.size() - 1) { mRenderPaint.setStyle(Paint.Style.STROKE); } - transformPath(spline); + mTrans.pathValueToPixel(spline); mDrawCanvas.drawPath(spline, mRenderPaint); @@ -222,7 +222,7 @@ else if (j == points.size() - 1) { // more than 1 color if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - float[] valuePoints = generateTransformedValuesLineScatter(entries); + float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { @@ -248,7 +248,7 @@ && isOffContentBottom(valuePoints[j + 1])) mRenderPaint.setColor(dataSet.getColor()); Path line = generateLinePath(entries); - transformPath(line); + mTrans.pathValueToPixel(line); mDrawCanvas.drawPath(line, mRenderPaint); } @@ -270,10 +270,10 @@ && isOffContentBottom(valuePoints[j + 1])) // mRenderPaint.setShader(dataSet.getShader()); Path filled = generateFilledPath(entries, - mFillFormatter.getFillLinePosition(dataSet, mOriginalData, mYChartMax, + mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin)); - transformPath(filled); + mTrans.pathValueToPixel(filled); mDrawCanvas.drawPath(filled, mRenderPaint); @@ -286,7 +286,7 @@ && isOffContentBottom(valuePoints[j + 1])) mRenderPaint.setPathEffect(null); } } - + /** * Generates the path that is used for filled drawing. * @@ -338,11 +338,11 @@ private Path generateLinePath(ArrayList entries) { protected void drawValues() { // if values are drawn - if (mDrawYValues && mCurrentData.getYValCount() < mMaxVisibleCount * mScaleX) { + if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { LineDataSet dataSet = dataSets.get(i); @@ -354,7 +354,7 @@ protected void drawValues() { ArrayList entries = dataSet.getYVals(); - float[] positions = generateTransformedValuesLineScatter(entries); + float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); for (int j = 0; j < positions.length * mPhaseX; j += 2) { @@ -392,9 +392,9 @@ protected void drawAdditional() { mRenderPaint.setStyle(Paint.Style.FILL); - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { LineDataSet dataSet = dataSets.get(i); @@ -403,7 +403,7 @@ protected void drawAdditional() { ArrayList entries = dataSet.getYVals(); - float[] positions = generateTransformedValuesLineScatter(entries); + float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); for (int j = 0; j < positions.length * mPhaseX; j += 2) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 5b41cf6aa1..b8d836a831 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -177,14 +177,14 @@ protected void calcMinMax(boolean fixedValues) { */ private void calcAngles() { - mDrawAngles = new float[mCurrentData.getYValCount()]; - mAbsoluteAngles = new float[mCurrentData.getYValCount()]; + mDrawAngles = new float[mData.getYValCount()]; + mAbsoluteAngles = new float[mData.getYValCount()]; - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); int cnt = 0; - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { PieDataSet set = dataSets.get(i); ArrayList entries = set.getYVals(); @@ -231,7 +231,7 @@ protected void drawHighlights() { float shiftangle = (float) Math.toRadians(angle + sliceDegrees / 2f); - PieDataSet set = mCurrentData + PieDataSet set = mData .getDataSetByIndex(mIndicesToHightlight[i] .getDataSetIndex()); @@ -261,11 +261,11 @@ protected void drawData() { float angle = mRotationAngle; - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); int cnt = 0; - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { PieDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); @@ -413,11 +413,11 @@ protected void drawValues() { r -= off; // offset to keep things inside the chart - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); int cnt = 0; - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { PieDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); @@ -457,13 +457,13 @@ protected void drawValues() { y -= lineHeight / 2; mDrawCanvas.drawText(val, x, y, mValuePaint); - if (j < mCurrentData.getXValCount()) - mDrawCanvas.drawText(mCurrentData.getXVals().get(j), x, y + lineHeight, + if (j < mData.getXValCount()) + mDrawCanvas.drawText(mData.getXVals().get(j), x, y + lineHeight, mValuePaint); } else if (mDrawXVals && !mDrawYValues) { - if (j < mCurrentData.getXValCount()) - mDrawCanvas.drawText(mCurrentData.getXVals().get(j), x, y, mValuePaint); + if (j < mData.getXValCount()) + mDrawCanvas.drawText(mData.getXVals().get(j), x, y, mValuePaint); } else if (!mDrawXVals && mDrawYValues) { mDrawCanvas.drawText(val, x, y, mValuePaint); @@ -486,7 +486,7 @@ protected void drawAdditional() { * @return */ private float calcAngle(float value) { - return value / mCurrentData.getYValueSum() * 360f; + return value / mData.getYValueSum() * 360f; } @Override @@ -511,7 +511,7 @@ public int getIndexForAngle(float angle) { */ public int getDataSetIndexForIndex(int xIndex) { - ArrayList> dataSets = mCurrentData.getDataSets(); + ArrayList> dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { if (dataSets.get(i).getEntryForXIndex(xIndex) != null) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 5c7b991375..7dedb9ce68 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -175,12 +175,12 @@ protected void applyCalculatedOffsets() { val.postTranslate(0, -mYChartMin); val.postScale(scaleX, -scaleY); - mMatrixValueToPx.set(val); + mTrans.getValueMatrix().set(val); Matrix offset = new Matrix(); offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); - mMatrixOffset.set(offset); + mTrans.getOffsetMatrix().set(offset); } /** the angle where the dragging started */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 19daac83a9..d933ba3bc0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -157,7 +157,7 @@ private void drawWeb() { mWebPaint.setColor(mWebColor); mWebPaint.setAlpha(mWebAlpha); - for (int i = 0; i < mCurrentData.getXValCount(); i++) { + for (int i = 0; i < mData.getXValCount(); i++) { PointF p = getPosition(c, mYChartMax * factor, sliceangle * i + mRotationAngle); @@ -173,7 +173,7 @@ private void drawWeb() { for (int j = 0; j < labelCount; j++) { - for (int i = 0; i < mCurrentData.getXValCount(); i++) { + for (int i = 0; i < mData.getXValCount(); i++) { float r = ((mYChartMax / labelCount) * (j + 1)) * factor; @@ -188,7 +188,7 @@ private void drawWeb() { @Override protected void drawData() { - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); float sliceangle = getSliceAngle(); @@ -198,7 +198,7 @@ protected void drawData() { PointF c = getCenterOffsets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { RadarDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); @@ -243,7 +243,7 @@ protected void drawData() { */ private void drawLimitLines() { - ArrayList limitLines = mOriginalData.getLimitLines(); + ArrayList limitLines = mData.getLimitLines(); if (limitLines == null) return; @@ -268,7 +268,7 @@ private void drawLimitLines() { Path limitPath = new Path(); - for (int j = 0; j < mCurrentData.getXValCount(); j++) { + for (int j = 0; j < mData.getXValCount(); j++) { PointF p = getPosition(c, r, sliceangle * j + mRotationAngle); @@ -291,7 +291,7 @@ private void drawLimitLines() { private void prepareYLabels() { int labelCount = mYLabels.getLabelCount(); - double range = mCurrentData.getYMax() - mYChartMin; + double range = mData.getYMax() - mYChartMin; double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -304,7 +304,7 @@ private void prepareYLabels() { } double first = Math.ceil(mYChartMin / interval) * interval; - double last = Utils.nextUp(Math.floor(mCurrentData.getYMax() / interval) * interval); + double last = Utils.nextUp(Math.floor(mData.getYMax() / interval) * interval); double f; int n = 0; @@ -366,7 +366,7 @@ private void prepareXLabels() { StringBuffer a = new StringBuffer(); - int max = (int) Math.round(mCurrentData.getXValAverageLength()); + int max = (int) Math.round(mData.getXValAverageLength()); for (int i = 0; i < max; i++) { a.append("h"); @@ -396,9 +396,9 @@ private void drawXLabels() { PointF c = getCenterOffsets(); - for (int i = 0; i < mCurrentData.getXValCount(); i++) { + for (int i = 0; i < mData.getXValCount(); i++) { - String text = mCurrentData.getXVals().get(i); + String text = mData.getXVals().get(i); float angle = (sliceangle * i + mRotationAngle) % 360f; @@ -424,9 +424,9 @@ protected void drawValues() { float yoffset = Utils.convertDpToPixel(5f); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { - RadarDataSet dataSet = mCurrentData.getDataSetByIndex(i); + RadarDataSet dataSet = mData.getDataSetByIndex(i); ArrayList entries = dataSet.getYVals(); for (int j = 0; j < entries.size(); j++) { @@ -459,7 +459,7 @@ protected void drawHighlights() { for (int i = 0; i < mIndicesToHightlight.length; i++) { - RadarDataSet set = mCurrentData + RadarDataSet set = mData .getDataSetByIndex(mIndicesToHightlight[i] .getDataSetIndex()); @@ -502,7 +502,7 @@ public float getFactor() { * @return */ public float getSliceAngle() { - return 360f / (float) mCurrentData.getXValCount(); + return 360f / (float) mData.getXValCount(); } @Override @@ -513,7 +513,7 @@ public int getIndexForAngle(float angle) { float sliceangle = getSliceAngle(); - for (int i = 0; i < mCurrentData.getXValCount(); i++) { + for (int i = 0; i < mData.getXValCount(); i++) { if (sliceangle * (i + 1) - sliceangle / 2f > a) return i; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 78bba6263f..31c7acbfb8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -42,7 +42,7 @@ protected void prepareContentRect() { super.prepareContentRect(); } else { - float offset = mOriginalData.getGreatestShapeSize() / 2f; + float offset = mData.getGreatestShapeSize() / 2f; mContentRect.set(mOffsetLeft - offset, mOffsetTop, @@ -55,23 +55,23 @@ protected void prepareContentRect() { protected void calcMinMax(boolean fixedValues) { super.calcMinMax(fixedValues); - if (mDeltaX == 0 && mOriginalData.getYValCount() > 0) + if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; } @Override protected void drawData() { - ArrayList dataSets = mCurrentData.getDataSets(); + ArrayList dataSets = mData.getDataSets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { ScatterDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); float shapeHalf = dataSet.getScatterShapeSize() / 2f; - float[] valuePoints = generateTransformedValuesLineScatter(entries); + float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); ScatterShape shape = dataSet.getScatterShape(); @@ -130,7 +130,7 @@ && isOffContentBottom(valuePoints[j + 1])) return; // transform the provided custom path - transformPath(customShape); + mTrans.pathValueToPixel(customShape); mDrawCanvas.drawPath(customShape, mRenderPaint); } } @@ -140,17 +140,17 @@ && isOffContentBottom(valuePoints[j + 1])) @Override protected void drawValues() { // if values are drawn - if (mDrawYValues && mCurrentData.getYValCount() < mMaxVisibleCount * mScaleX) { + if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - ArrayList dataSets = mCurrentData + ArrayList dataSets = mData .getDataSets(); - for (int i = 0; i < mCurrentData.getDataSetCount(); i++) { + for (int i = 0; i < mData.getDataSetCount(); i++) { ScatterDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); - float[] positions = generateTransformedValuesLineScatter(entries); + float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); float shapeSize = dataSet.getScatterShapeSize(); @@ -186,7 +186,7 @@ protected void drawHighlights() { for (int i = 0; i < mIndicesToHightlight.length; i++) { - ScatterDataSet set = mCurrentData.getDataSetByIndex(mIndicesToHightlight[i] + ScatterDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i] .getDataSetIndex()); if (set == null) @@ -207,7 +207,7 @@ protected void drawHighlights() { xIndex, mYChartMax, xIndex, mYChartMin, 0, y, mDeltaX, y }; - transformPointArray(pts); + mTrans.pointValuesToPixel(pts); // draw the highlight lines mDrawCanvas.drawLines(pts, mHighlightPaint); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java new file mode 100644 index 0000000000..b19b89b34b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -0,0 +1,38 @@ + +package com.github.mikephil.charting.interfaces; + +import android.graphics.RectF; +import android.view.View; + +/** + * Interface that provides everything there is to know about the dimensions, + * bounds, and range of the chart. + * + * @author Philipp Jahoda + */ +public interface ChartInterface { + + public float getOffsetBottom(); + + public float getOffsetTop(); + + public float getOffsetLeft(); + + public float getOffsetRight(); + + public float getDeltaX(); + + public float getDeltaY(); + + public float getYChartMin(); + + public float getYChartMax(); + + public int getWidth(); + + public int getHeight(); + + public RectF getContentRect(); + + public View getChartView(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 7db2f321ca..8f86b2cbb9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -163,7 +163,7 @@ public boolean onTouch(View v, MotionEvent event) { } // Perform the transformation, update the chart - mMatrix = mChart.refreshTouch(mMatrix); + mMatrix = mChart.getTransformer().refresh(mMatrix, mChart); return true; // indicate event was handled } @@ -385,7 +385,7 @@ public boolean onDoubleTap(MotionEvent e) { PointF trans = getTrans(e.getX(), e.getY()); - mChart.zoomIn(trans.x, trans.y); + mChart.zoom(1.4f, 1.4f, trans.x, trans.y); Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java new file mode 100644 index 0000000000..8b69cb6a51 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java @@ -0,0 +1,267 @@ +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; + +import java.util.ArrayList; + +public class LineRenderer extends RenderBase { + + /** + * Class needed for saving the points when drawing cubic-lines. + * + * @author Philipp Jahoda + */ + private class CPoint { + + public float x = 0f; + public float y = 0f; + + /** x-axis distance */ + public float dx = 0f; + + /** y-axis distance */ + public float dy = 0f; + + public CPoint(float x, float y) { + this.x = x; + this.y = y; + } + } + + /** + * draws the given y values to the screen + */ + @Override + protected void renderData(Canvas canvas, LineData data, Transformer trans) { + + ArrayList dataSets = data.getDataSets(); + + for (int i = 0; i < data.getDataSetCount(); i++) { + + LineDataSet dataSet = dataSets.get(i); + ArrayList entries = dataSet.getYVals(); + + if (entries.size() < 1) + continue; + + mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); + mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); + + // if drawing cubic lines is enabled + if (dataSet.isDrawCubicEnabled()) { + + // get the color that is specified for this position from the + // DataSet + mRenderPaint.setColor(dataSet.getColor()); + + float intensity = dataSet.getCubicIntensity(); + + // the path for the cubic-spline + Path spline = new Path(); + + ArrayList points = new ArrayList(); + for (Entry e : entries) + points.add(new CPoint(e.getXIndex(), e.getVal())); + + if (points.size() > 1) { + for (int j = 0; j < points.size() * 1f; j++) { + + CPoint point = points.get(j); + + if (j == 0) { + CPoint next = points.get(j + 1); + point.dx = ((next.x - point.x) * intensity); + point.dy = ((next.y - point.y) * intensity); + } + else if (j == points.size() - 1) { + CPoint prev = points.get(j - 1); + point.dx = ((point.x - prev.x) * intensity); + point.dy = ((point.y - prev.y) * intensity); + } + else { + CPoint next = points.get(j + 1); + CPoint prev = points.get(j - 1); + point.dx = ((next.x - prev.x) * intensity); + point.dy = ((next.y - prev.y) * intensity); + } + + // create the cubic-spline path + if (j == 0) { + spline.moveTo(point.x, point.y * 1f); + } + else { + CPoint prev = points.get(j - 1); + spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * 1f, point.x + - point.dx, + (point.y - point.dy) * 1f, point.x, point.y * 1f); + } + } + } + + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + +// float fillMin = mFillFormatter +// .getFillLinePosition(dataSet, mOriginalData, mYChartMax, mYChartMin); + + spline.lineTo((entries.size() - 1) * 1f, 0f); + spline.lineTo(0, 0f); + spline.close(); + + mRenderPaint.setStyle(Paint.Style.FILL); + } else { + mRenderPaint.setStyle(Paint.Style.STROKE); + } + + trans.pathValueToPixel(spline); + + canvas.drawPath(spline, mRenderPaint); + + // draw normal (straight) lines + } else { + + mRenderPaint.setStyle(Paint.Style.STROKE); + + // more than 1 color + if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { + + /** + * + * + * + * + * PHASE + * + * + */ + float[] valuePoints = trans.generateTransformedValuesLineScatter(entries, 1f); + + for (int j = 0; j < (valuePoints.length - 2) * 1f; j += 2) { + +// if (isOffContentRight(valuePoints[j])) +// break; +// +// // make sure the lines don't do shitty things outside +// // bounds +// if (j != 0 && isOffContentLeft(valuePoints[j - 1]) +// && isOffContentTop(valuePoints[j + 1]) +// && isOffContentBottom(valuePoints[j + 1])) +// continue; + + // get the color that is set for this line-segment + mRenderPaint.setColor(dataSet.getColor(j / 2)); + + canvas.drawLine(valuePoints[j], valuePoints[j + 1], + valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); + } + + } else { // only one color per dataset + + mRenderPaint.setColor(dataSet.getColor()); + + Path line = generateLinePath(entries); + trans.pathValueToPixel(line); + + canvas.drawPath(line, mRenderPaint); + } + + mRenderPaint.setPathEffect(null); + + // if drawing filled is enabled + if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { + // canvas.drawVertices(VertexMode.TRIANGLE_STRIP, + // valuePoints.length, valuePoints, 0, + // null, 0, null, 0, null, 0, 0, paint); + + mRenderPaint.setStyle(Paint.Style.FILL); + + mRenderPaint.setColor(dataSet.getFillColor()); + // filled is drawn with less alpha + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + + // mRenderPaint.setShader(dataSet.getShader()); + + Path filled = generateFilledPath(entries, 0); + + trans.pathValueToPixel(filled); + + canvas.drawPath(filled, mRenderPaint); + + // restore alpha + mRenderPaint.setAlpha(255); + // mRenderPaint.setShader(null); + } + } + + mRenderPaint.setPathEffect(null); + } + } + + /** + * Generates the path that is used for filled drawing. + * + * @param entries + * @return + */ + private Path generateFilledPath(ArrayList entries, float fillMin) { + + Path filled = new Path(); + filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * 1f); + + // create a new path + for (int x = 1; x < entries.size() * 1f; x++) { + + Entry e = entries.get(x); + filled.lineTo(e.getXIndex(), e.getVal() * 1f); + } + + // close up + filled.lineTo(entries.get((int) ((entries.size() - 1) * 1f)).getXIndex(), fillMin); + filled.lineTo(entries.get(0).getXIndex(), fillMin); + filled.close(); + + return filled; + } + + /** + * Generates the path that is used for drawing a single line. + * + * @param entries + * @return + */ + private Path generateLinePath(ArrayList entries) { + + Path line = new Path(); + line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * 1f); + + // create a new path + for (int x = 1; x < entries.size() * 1f; x++) { + + Entry e = entries.get(x); + line.lineTo(e.getXIndex(), e.getVal() * 1f); + } + + return line; + } + + @Override + protected void renderValues(Canvas canvas, LineData data, Transformer trans) { + // TODO Auto-generated method stub + + } + + @Override + protected void renderHighlights(Canvas canvas, LineData data, Transformer trans) { + // TODO Auto-generated method stub + + } + + + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java new file mode 100644 index 0000000000..4e64a6abaf --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java @@ -0,0 +1,74 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; + +import com.github.mikephil.charting.data.ChartData; + +public abstract class RenderBase { + + /** this is the paint object used for drawing the data onto the chart */ + protected Paint mRenderPaint; + + /** the phase that is animated and influences the drawn values on the y-axis */ + protected float mPhaseY = 1f; + + /** the phase that is animated and influences the drawn values on the x-axis */ + protected float mPhaseX = 1f; + + public RenderBase() { + mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mRenderPaint.setStyle(Style.FILL); + } + + public void render(Canvas canvas, T data, Transformer trans) { + + renderData(canvas, data, trans); + renderValues(canvas, data, trans); + renderHighlights(canvas, data, trans); + } + + protected abstract void renderData(Canvas canvas, T data, Transformer trans); + + protected abstract void renderValues(Canvas canvas, T data, Transformer trans); + + protected abstract void renderHighlights(Canvas canvas, T data, Transformer trans); + + /** + * This gets the y-phase that is used to animate the values. + * + * @return + */ + public float getPhaseY() { + return mPhaseY; + } + + /** + * This modifys the y-phase that is used to animate the values. + * + * @param phase + */ + public void setPhaseY(float phase) { + mPhaseY = phase; + } + + /** + * This gets the x-phase that is used to animate the values. + * + * @return + */ + public float getPhaseX() { + return mPhaseX; + } + + /** + * This modifys the x-phase that is used to animate the values. + * + * @param phase + */ + public void setPhaseX(float phase) { + mPhaseX = phase; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java new file mode 100644 index 0000000000..e23156c77c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -0,0 +1,603 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Matrix; +import android.graphics.Path; +import android.graphics.RectF; +import android.view.View; + +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; + +/** + * Transformer class that contains all matrices and is responsible for + * transforming values into pixels on the screen and backwards. + * + * @author Philipp Jahoda + */ +public class Transformer { + + /** matrix to map the values to the screen pixels */ + private Matrix mMatrixValueToPx = new Matrix(); + + /** matrix for handling the different offsets of the chart */ + private Matrix mMatrixOffset = new Matrix(); + + /** matrix used for touch events */ + private final Matrix mMatrixTouch = new Matrix(); + + /** if set to true, the y-axis is inverted and low values start at the top */ + private boolean mInvertYAxis = false; + + /** minimum scale value on the y-axis */ + private float mMinScaleY = 1f; + + /** minimum scale value on the x-axis */ + private float mMinScaleX = 1f; + + /** contains the current scale factor of the x-axis */ + private float mScaleX = 1f; + + /** contains the current scale factor of the y-axis */ + private float mScaleY = 1f; + + /** offset that allows the chart to be dragged over its bounds on the x-axis */ + private float mTransOffsetX = 0f; + + /** offset that allows the chart to be dragged over its bounds on the x-axis */ + private float mTransOffsetY = 0f; + + public Transformer() { + + } + + /** + * Prepares the matrix that transforms values to pixels. + * + * @param chart + */ + public void prepareMatrixValuePx(ChartInterface chart) { + + float scaleX = (float) ((chart.getWidth() - chart.getOffsetRight() - chart + .getOffsetLeft()) / chart.getDeltaX()); + float scaleY = (float) ((chart.getHeight() - chart.getOffsetTop() - chart + .getOffsetBottom()) / chart.getDeltaY()); + + // setup all matrices + mMatrixValueToPx.reset(); + mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + mMatrixValueToPx.postScale(scaleX, -scaleY); + } + + /** + * Prepares the matrix that contains all offsets. + * + * @param chart + */ + public void prepareMatrixOffset(ChartInterface chart) { + + mMatrixOffset.reset(); + + // offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); + + if (!mInvertYAxis) + mMatrixOffset.postTranslate(chart.getOffsetLeft(), + chart.getHeight() - chart.getOffsetBottom()); + else { + mMatrixOffset.setTranslate(chart.getOffsetLeft(), -chart.getOffsetTop()); + mMatrixOffset.postScale(1.0f, -1.0f); + } + + // mMatrixOffset.set(offset); + + // mMatrixOffset.reset(); + // + // mMatrixOffset.postTranslate(mOffsetLeft, getHeight() - + // mOffsetBottom); + } + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the LINECHART or SCATTERCHART. + * + * @param entries + * @return + */ + public float[] generateTransformedValuesLineScatter(ArrayList entries, + float phaseY) { + + float[] valuePoints = new float[entries.size() * 2]; + + for (int j = 0; j < valuePoints.length; j += 2) { + + Entry e = entries.get(j / 2); + + valuePoints[j] = e.getXIndex(); + valuePoints[j + 1] = e.getVal() * phaseY; + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the BARCHART. + * + * @param entries + * @param dataSet the dataset index + * @return + */ + public float[] generateTransformedValuesBarChart(ArrayList entries, + int dataSet, BarData bd, float phaseY) { + + float[] valuePoints = new float[entries.size() * 2]; + + int setCount = bd.getDataSetCount(); + float space = bd.getGroupSpace(); + + for (int j = 0; j < valuePoints.length; j += 2) { + + Entry e = entries.get(j / 2); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + 0.5f + space * (j / 2) + + space / 2f; + float y = e.getVal(); + + valuePoints[j] = x; + valuePoints[j + 1] = y * phaseY; + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } + + /** + * transform a path with all the given matrices VERY IMPORTANT: keep order + * to value-touch-offset + * + * @param path + */ + public void pathValueToPixel(Path path) { + + path.transform(mMatrixValueToPx); + path.transform(mMatrixTouch); + path.transform(mMatrixOffset); + } + + /** + * Transforms multiple paths will all matrices. + * + * @param paths + */ + public void pathValuesToPixel(ArrayList paths) { + + for (int i = 0; i < paths.size(); i++) { + pathValueToPixel(paths.get(i)); + } + } + + /** + * Transform an array of points with all matrices. VERY IMPORTANT: Keep + * matrix order "value-touch-offset" when transforming. + * + * @param pts + */ + public void pointValuesToPixel(float[] pts) { + + mMatrixValueToPx.mapPoints(pts); + mMatrixTouch.mapPoints(pts); + mMatrixOffset.mapPoints(pts); + } + + /** + * Transform a rectangle with all matrices. + * + * @param r + */ + public void rectValueToPixel(RectF r) { + + mMatrixValueToPx.mapRect(r); + mMatrixTouch.mapRect(r); + mMatrixOffset.mapRect(r); + } + + /** + * Transform a rectangle with all matrices with potential animation phases. + * + * @param r + * @param phaseY + */ + public void rectValueToPixel(RectF r, float phaseY) { + + // multiply the height of the rect with the phase + if (r.top > 0) + r.top *= phaseY; + else + r.bottom *= phaseY; + + mMatrixValueToPx.mapRect(r); + mMatrixTouch.mapRect(r); + mMatrixOffset.mapRect(r); + } + + /** + * transforms multiple rects with all matrices + * + * @param rects + */ + public void rectValuesToPixel(ArrayList rects) { + + for (int i = 0; i < rects.size(); i++) + rectValueToPixel(rects.get(i)); + } + + /** + * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) + * into values on the chart. + * + * @param pixels + */ + public void pixelsToValue(float[] pixels) { + + Matrix tmp = new Matrix(); + + // invert all matrixes to convert back to the original value + mMatrixOffset.invert(tmp); + tmp.mapPoints(pixels); + + mMatrixTouch.invert(tmp); + tmp.mapPoints(pixels); + + mMatrixValueToPx.invert(tmp); + tmp.mapPoints(pixels); + } + + /** + * ################ ################ ################ ################ + */ + /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ + + /** + * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom + * center. + * + * @param x + * @param y + */ + public Matrix zoomIn(float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.postScale(1.4f, 1.4f, x, y); + + return save; + } + + /** + * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom + * center. + */ + public Matrix zoomOut(float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.postScale(0.7f, 0.7f, x, y); + + return save; + } + + /** + * Zooms in or out by the given scale factor. x and y are the coordinates + * (in pixels) of the zoom center. + * + * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in + * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in + * @param x + * @param y + */ + public Matrix zoom(float scaleX, float scaleY, float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + // Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y); + + save.postScale(scaleX, scaleY, x, y); + + return save; + } + + /** + * Resets all zooming and dragging and makes the chart fit exactly it's + * bounds. + */ + public Matrix fitScreen() { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + float[] vals = new float[9]; + + save.getValues(vals); + + // reset all translations and scaling + vals[Matrix.MTRANS_X] = 0f; + vals[Matrix.MTRANS_Y] = 0f; + vals[Matrix.MSCALE_X] = 1f; + vals[Matrix.MSCALE_Y] = 1f; + + save.setValues(vals); + + return save; + } + + /** + * If this is set to true, the y-axis is inverted which means that low + * values are on top of the chart, high values on bottom. + * + * @param enabled + */ + public void setInvertYAxisEnabled(boolean enabled) { + mInvertYAxis = enabled; + } + + /** + * If this returns true, the y-axis is inverted. + * + * @return + */ + public boolean isInvertYAxisEnabled() { + return mInvertYAxis; + } + + /** + * Centers the viewport around the specified position (x-index and y-value) + * in the chart. Centering the viewport outside the bounds of the chart is + * not possible. Makes most sense in combination with the + * setScaleMinima(...) method. + * + * @param pts the position to center view viewport to + * @param chart + * @return save + */ + public synchronized void centerViewPort(final float[] pts, final ChartInterface chart) { + + final View v = chart.getChartView(); + + v.post(new Runnable() { + + @Override + public void run() { + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + pointValuesToPixel(pts); + + final float x = pts[0] - chart.getOffsetLeft(); + final float y = pts[1] - chart.getOffsetTop(); + + save.postTranslate(-x, -y); + + refresh(save, chart); + } + }); + } + + /** + * call this method to refresh the graph with a given matrix + * + * @param newMatrix + * @return + */ + public Matrix refresh(Matrix newMatrix, ChartInterface chart) { + + mMatrixTouch.set(newMatrix); + + // make sure scale and translation are within their bounds + limitTransAndScale(mMatrixTouch, chart.getContentRect()); + + chart.getChartView().invalidate(); + + newMatrix.set(mMatrixTouch); + return newMatrix; + } + + /** + * limits the maximum scale and X translation of the given matrix + * + * @param matrix + */ + private void limitTransAndScale(Matrix matrix, RectF content) { + + float[] vals = new float[9]; + matrix.getValues(vals); + + float curTransX = vals[Matrix.MTRANS_X]; + float curScaleX = vals[Matrix.MSCALE_X]; + + float curTransY = vals[Matrix.MTRANS_Y]; + float curScaleY = vals[Matrix.MSCALE_Y]; + + // min scale-x is 1f + mScaleX = Math.max(mMinScaleX, curScaleX); + + // min scale-y is 1f + mScaleY = Math.max(mMinScaleY, curScaleY); + + float width = 0f; + float height = 0f; + + if (content != null) { + width = content.width(); + height = content.height(); + } + + float maxTransX = -width * (mScaleX - 1f); + float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); + + // if(curScaleX < mMinScaleX) { + // newTransX = (-width * (mScaleX - 1f)) / 2f; + // } + + float maxTransY = height * (mScaleY - 1f); + float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); + + // if(curScaleY < mMinScaleY) { + // newTransY = (height * (mScaleY - 1f)) / 2f; + // } + + vals[Matrix.MTRANS_X] = newTransX; + vals[Matrix.MSCALE_X] = mScaleX; + + vals[Matrix.MTRANS_Y] = newTransY; + vals[Matrix.MSCALE_Y] = mScaleY; + + matrix.setValues(vals); + } + + /** + * Sets the minimum scale values for both axes. This limits the extent to + * which the user can zoom-out. + * + * @param scaleXmin + * @param scaleYmin + */ + public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { + + if (scaleXmin < 1f) + scaleXmin = 1f; + if (scaleYmin < 1f) + scaleYmin = 1f; + + mMinScaleX = scaleXmin; + mMinScaleY = scaleYmin; + + Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); + refresh(save, chart); + } + + // /** + // * transforms the given rect objects with the touch matrix only + // * + // * @param paths + // */ + // public void transformRectsTouch(ArrayList rects) { + // for (int i = 0; i < rects.size(); i++) { + // mMatrixTouch.mapRect(rects.get(i)); + // } + // } + // + // /** + // * transforms the given path objects with the touch matrix only + // * + // * @param paths + // */ + // public void transformPathsTouch(ArrayList paths) { + // for (int i = 0; i < paths.size(); i++) { + // paths.get(i).transform(mMatrixTouch); + // } + // } + + public Matrix getTouchMatrix() { + return mMatrixTouch; + } + + public Matrix getValueMatrix() { + return mMatrixValueToPx; + } + + public Matrix getOffsetMatrix() { + return mMatrixOffset; + } + + /** + * returns the current x-scale factor + */ + public float getScaleX() { + return mScaleX; + } + + /** + * returns the current y-scale factor + */ + public float getScaleY() { + return mScaleY; + } + + /** + * if the chart is fully zoomed out, return true + * + * @return + */ + public boolean isFullyZoomedOut() { + + if (isFullyZoomedOutX() && isFullyZoomedOutY()) + return true; + else + return false; + } + + /** + * Returns true if the chart is fully zoomed out on it's y-axis (vertical). + * + * @return + */ + public boolean isFullyZoomedOutY() { + if (mScaleY > mMinScaleY || mMinScaleY > 1f) + return false; + else + return true; + } + + /** + * Returns true if the chart is fully zoomed out on it's x-axis + * (horizontal). + * + * @return + */ + public boolean isFullyZoomedOutX() { + if (mScaleX > mMinScaleX || mMinScaleX > 1f) + return false; + else + return true; + } + + /** + * Set an offset in dp that allows the user to drag the chart over it's + * bounds on the x-axis. + * + * @param offset + */ + public void setDragOffsetX(float offset) { + mTransOffsetX = Utils.convertDpToPixel(offset); + } + + /** + * Set an offset in dp that allows the user to drag the chart over it's + * bounds on the y-axis. + * + * @param offset + */ + public void setDragOffsetY(float offset) { + mTransOffsetY = Utils.convertDpToPixel(offset); + } + + /** + * Returns true if both drag offsets (x and y) are zero or smaller. + * + * @return + */ + public boolean hasNoDragOffset() { + return mTransOffsetX <= 0 && mTransOffsetY <= 0 ? true : false; + } +} From 86f77709f2c7f53cc38ab94ba82e4839d1d7fcfc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 18 Nov 2014 15:44:49 +0100 Subject: [PATCH 0008/1390] Removed renderers, merged with experimental. --- .../charting/renderer/LineRenderer.java | 267 ------------------ .../charting/renderer/RenderBase.java | 74 ----- 2 files changed, 341 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java deleted file mode 100644 index 8b69cb6a51..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java +++ /dev/null @@ -1,267 +0,0 @@ -package com.github.mikephil.charting.renderer; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; - -import java.util.ArrayList; - -public class LineRenderer extends RenderBase { - - /** - * Class needed for saving the points when drawing cubic-lines. - * - * @author Philipp Jahoda - */ - private class CPoint { - - public float x = 0f; - public float y = 0f; - - /** x-axis distance */ - public float dx = 0f; - - /** y-axis distance */ - public float dy = 0f; - - public CPoint(float x, float y) { - this.x = x; - this.y = y; - } - } - - /** - * draws the given y values to the screen - */ - @Override - protected void renderData(Canvas canvas, LineData data, Transformer trans) { - - ArrayList dataSets = data.getDataSets(); - - for (int i = 0; i < data.getDataSetCount(); i++) { - - LineDataSet dataSet = dataSets.get(i); - ArrayList entries = dataSet.getYVals(); - - if (entries.size() < 1) - continue; - - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); - mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); - - // if drawing cubic lines is enabled - if (dataSet.isDrawCubicEnabled()) { - - // get the color that is specified for this position from the - // DataSet - mRenderPaint.setColor(dataSet.getColor()); - - float intensity = dataSet.getCubicIntensity(); - - // the path for the cubic-spline - Path spline = new Path(); - - ArrayList points = new ArrayList(); - for (Entry e : entries) - points.add(new CPoint(e.getXIndex(), e.getVal())); - - if (points.size() > 1) { - for (int j = 0; j < points.size() * 1f; j++) { - - CPoint point = points.get(j); - - if (j == 0) { - CPoint next = points.get(j + 1); - point.dx = ((next.x - point.x) * intensity); - point.dy = ((next.y - point.y) * intensity); - } - else if (j == points.size() - 1) { - CPoint prev = points.get(j - 1); - point.dx = ((point.x - prev.x) * intensity); - point.dy = ((point.y - prev.y) * intensity); - } - else { - CPoint next = points.get(j + 1); - CPoint prev = points.get(j - 1); - point.dx = ((next.x - prev.x) * intensity); - point.dy = ((next.y - prev.y) * intensity); - } - - // create the cubic-spline path - if (j == 0) { - spline.moveTo(point.x, point.y * 1f); - } - else { - CPoint prev = points.get(j - 1); - spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * 1f, point.x - - point.dx, - (point.y - point.dy) * 1f, point.x, point.y * 1f); - } - } - } - - // if filled is enabled, close the path - if (dataSet.isDrawFilledEnabled()) { - -// float fillMin = mFillFormatter -// .getFillLinePosition(dataSet, mOriginalData, mYChartMax, mYChartMin); - - spline.lineTo((entries.size() - 1) * 1f, 0f); - spline.lineTo(0, 0f); - spline.close(); - - mRenderPaint.setStyle(Paint.Style.FILL); - } else { - mRenderPaint.setStyle(Paint.Style.STROKE); - } - - trans.pathValueToPixel(spline); - - canvas.drawPath(spline, mRenderPaint); - - // draw normal (straight) lines - } else { - - mRenderPaint.setStyle(Paint.Style.STROKE); - - // more than 1 color - if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - - /** - * - * - * - * - * PHASE - * - * - */ - float[] valuePoints = trans.generateTransformedValuesLineScatter(entries, 1f); - - for (int j = 0; j < (valuePoints.length - 2) * 1f; j += 2) { - -// if (isOffContentRight(valuePoints[j])) -// break; -// -// // make sure the lines don't do shitty things outside -// // bounds -// if (j != 0 && isOffContentLeft(valuePoints[j - 1]) -// && isOffContentTop(valuePoints[j + 1]) -// && isOffContentBottom(valuePoints[j + 1])) -// continue; - - // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 2)); - - canvas.drawLine(valuePoints[j], valuePoints[j + 1], - valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); - } - - } else { // only one color per dataset - - mRenderPaint.setColor(dataSet.getColor()); - - Path line = generateLinePath(entries); - trans.pathValueToPixel(line); - - canvas.drawPath(line, mRenderPaint); - } - - mRenderPaint.setPathEffect(null); - - // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { - // canvas.drawVertices(VertexMode.TRIANGLE_STRIP, - // valuePoints.length, valuePoints, 0, - // null, 0, null, 0, null, 0, 0, paint); - - mRenderPaint.setStyle(Paint.Style.FILL); - - mRenderPaint.setColor(dataSet.getFillColor()); - // filled is drawn with less alpha - mRenderPaint.setAlpha(dataSet.getFillAlpha()); - - // mRenderPaint.setShader(dataSet.getShader()); - - Path filled = generateFilledPath(entries, 0); - - trans.pathValueToPixel(filled); - - canvas.drawPath(filled, mRenderPaint); - - // restore alpha - mRenderPaint.setAlpha(255); - // mRenderPaint.setShader(null); - } - } - - mRenderPaint.setPathEffect(null); - } - } - - /** - * Generates the path that is used for filled drawing. - * - * @param entries - * @return - */ - private Path generateFilledPath(ArrayList entries, float fillMin) { - - Path filled = new Path(); - filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * 1f); - - // create a new path - for (int x = 1; x < entries.size() * 1f; x++) { - - Entry e = entries.get(x); - filled.lineTo(e.getXIndex(), e.getVal() * 1f); - } - - // close up - filled.lineTo(entries.get((int) ((entries.size() - 1) * 1f)).getXIndex(), fillMin); - filled.lineTo(entries.get(0).getXIndex(), fillMin); - filled.close(); - - return filled; - } - - /** - * Generates the path that is used for drawing a single line. - * - * @param entries - * @return - */ - private Path generateLinePath(ArrayList entries) { - - Path line = new Path(); - line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * 1f); - - // create a new path - for (int x = 1; x < entries.size() * 1f; x++) { - - Entry e = entries.get(x); - line.lineTo(e.getXIndex(), e.getVal() * 1f); - } - - return line; - } - - @Override - protected void renderValues(Canvas canvas, LineData data, Transformer trans) { - // TODO Auto-generated method stub - - } - - @Override - protected void renderHighlights(Canvas canvas, LineData data, Transformer trans) { - // TODO Auto-generated method stub - - } - - - -} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java deleted file mode 100644 index 4e64a6abaf..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java +++ /dev/null @@ -1,74 +0,0 @@ - -package com.github.mikephil.charting.renderer; - -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Paint.Style; - -import com.github.mikephil.charting.data.ChartData; - -public abstract class RenderBase { - - /** this is the paint object used for drawing the data onto the chart */ - protected Paint mRenderPaint; - - /** the phase that is animated and influences the drawn values on the y-axis */ - protected float mPhaseY = 1f; - - /** the phase that is animated and influences the drawn values on the x-axis */ - protected float mPhaseX = 1f; - - public RenderBase() { - mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mRenderPaint.setStyle(Style.FILL); - } - - public void render(Canvas canvas, T data, Transformer trans) { - - renderData(canvas, data, trans); - renderValues(canvas, data, trans); - renderHighlights(canvas, data, trans); - } - - protected abstract void renderData(Canvas canvas, T data, Transformer trans); - - protected abstract void renderValues(Canvas canvas, T data, Transformer trans); - - protected abstract void renderHighlights(Canvas canvas, T data, Transformer trans); - - /** - * This gets the y-phase that is used to animate the values. - * - * @return - */ - public float getPhaseY() { - return mPhaseY; - } - - /** - * This modifys the y-phase that is used to animate the values. - * - * @param phase - */ - public void setPhaseY(float phase) { - mPhaseY = phase; - } - - /** - * This gets the x-phase that is used to animate the values. - * - * @return - */ - public float getPhaseX() { - return mPhaseX; - } - - /** - * This modifys the x-phase that is used to animate the values. - * - * @param phase - */ - public void setPhaseX(float phase) { - mPhaseX = phase; - } -} From 7ad2cc5643adcdda0748100f487074d1a3c46178 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 18 Nov 2014 20:52:22 +0100 Subject: [PATCH 0009/1390] Minor improvements and changes to the arcitecture. --- MPChartExample/AndroidManifest.xml | 7 +- MPChartExample/build.gradle | 4 +- .../libs/mpandroidchartlibrary-1-7-4.jar | Bin 0 -> 1283092 bytes MPChartExample/project.properties | 1 - ...tActivity.java => LineChartActivity1.java} | 2 +- .../mpchartexample/LineChartActivity2.java | 328 ++++++++++++++++++ .../notimportant/MainActivity.java | 45 +-- .../charting/charts/BarLineChartBase.java | 21 ++ .../mikephil/charting/charts/RadarChart.java | 17 +- .../github/mikephil/charting/utils/Utils.java | 2 +- 10 files changed, 395 insertions(+), 32 deletions(-) create mode 100644 MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/{LineChartActivity.java => LineChartActivity1.java} (99%) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index ef5edb5338..cd08251e3f 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="29" + android:versionName="1.7.4" > - + + diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8a33f7e0cf..31e0a5f1a3 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,8 +7,8 @@ android { applicationId 'com.xxmassdeveloper.mpchartexample' minSdkVersion 16 targetSdkVersion 19 - versionCode 28 - versionName '1.7.1' + versionCode 29 + versionName '1.7.4' sourceSets { main { diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar new file mode 100644 index 0000000000000000000000000000000000000000..749ac4603232191f02a07c4565fc6d8b6fd276b2 GIT binary patch literal 1283092 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

{?YkMaY-AN<9_BpNWi1lhdUPx1jOQBMtlCf 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�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±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
1tTuG2L2<}*J-+~*nx)#bF?Pa>%zD0{ z09lvHuX>-nT}hbTOXX8#Xzs2%@(@e!SINGTi{%@S-f}%EeWi!w&=ij+DF50WX0_UV zW$4;nXQ=)jEUf(jEo|Q~BrNe;V`y7O7igQ6$C&0vN~rt2HEf^ZgZ64)PQ%vh5geJj zQAp&jr3d^i^f13?A(YJVX0`mqs)4WhE}15rb!0X@N_?sdRZ-GBW`@hGT@i#t=2xe! ziL$jc6DRxMGbf2Yn#U?+!bz@Nd^%Rop&)!R&7fE^^;rz@3O$#C-&Hc%<dc~FN1I@kj8nX ztT~m;rtX#8i;q%?Q-C;YUB_H++IMg(^u`k+!D9p)Jwa#V%5~?Cb&mZBA za?zy`#DZLW;W{wL(dUTCvByV_k4%_5-ZT@dT?hok^FH%!1Oo}65B?ao3)B%~e(zLA z=S{4ZHQiga;y&k^bSX*cin#z6v}a%0izMTiaYy08f^w%|#LM?@5jaL3g@!*$%#zGX zZ;|O77M{7)Q6uHCMn-aMOR{{U1d1zg#u5zPq!8l7)pIh3i!xnZ8(mK7$ zY56vpk_yJr)l$+FdMsBAz+9t)jh0uEZkgWHITn>?07rti>xeAJ#T=;%JO%SqaW znyMjaG9BjfvM$-_NuMy@O_q)3!KowmQQU>Nj0%B2)Dd@!WobrVX_!9`G*nj*s!Vay ztpP5BPCE`c?HY8}*?$)eo_ZWS%_j1ZLo@`ZXG9&y`Cwqb*bQmAEWE(DkdFc7LVm^_ z^|X7q8H@g;jGd3<9(=tnQJ9eCr5QfI_> zbMSM$jBrx`vnz;dL9W`Yt0I0=#?_j}WQOnS&nrQWPZSZ>fE~BT$P;;bhJQQd0aSN@ z;Ood6^2!+6cfjx+LrfH2CQ2F`*}*}EwukA+my2HIsPl9HYPd&gcxdW~tcU1+pxOXm z7Xj>{i!+3MK-x_yw?}(VC>QR3U^^1!o=mZ$YPQd7inpVFaUZZ4zDq6pR@8{)uS7SH zmr`|?z!V;rg7Qtod@uXpz}-TVg(aVkKtIOtt}51^X29%-D8!Gg9ZpToW9mdJWAU&R z0OU?IhX|J@oK(12CBDf(wo z0ql&d!%3cWS=;nDmI~XUsd`IQioRDM8-8W7`YT03u%WJon@ zsQ=PrF|hNTc!hY0vzChO{s99mHcUXGHM~!e{fm2ckpGBv1Q#_VkaY-jVr$0EJA)9= z5xJnwa_vo#sdjOFT&+-#O?JPt*X|{ok>-HtAW5`%K_C5b?9*672OVbC4Kd*;(NTrf zC8FP7QA$iW@H-z0lsN>vWiU!~Fsx*dKB3m_3N@Y$EuIZ&5iX)RA>K`b9{V1(4Uuh< z{82F?Pi%jeaC5*m1kE>Uv(TDjrd*o+P9nyOGH$tQqYt3%@=@M$O-MK*J+Oi(*peu^ zX=EAly0i3GW9W~jL^A8=t59L}{tpI{DeTVzK{9FbuXi+dVJYAXL>&hR=Z)(0d2=+x zugqYlwSQOH>E$J+HH88Ia7O+o7nb>dd58KBnqEq@EYu(aLdfo$dJSlo)AeAE1wwZK z1w^EfJVKTNF<}B(jRz|_UcYbzVp?tXSofH5=5IWFPXe8x$s!N;NINiM@XaAqt}W56v-5P}x;bv&(0;OpS%ei$F^buZxG zCvwI_PTKI-_kIKX*Ar3yAF&hG{|(+KZRsNYpO90ElB_f^BZ9A`b(`*``q#IbLOC7` z>Ojyz2~l_zDoszBZFxc_P1nYY{kiBskjIO7L{kfDMIhF=43quNba(t(TbVh4XmuyX zV04fsI^;BGx_f|_;<&$;>6aU!CXpjvMazLmVmJU3pJUI zwBO1FDOzA~spX!U>M|;QH{h5~Wtlz|q=O1deP4m@#J>aEg6$rhuEkcb2UbsEY)QGh zrOb@;;aq3_d^sA4?nW}StCK-pJcx`up!wnWk(VCFhYm5U*>jb%g(1=~-}&>w4883s zz^P%Z`lF83Yrbt_%lJqSVktebAEe~VPWHzaAd}CH!`t!)ZoBW>uoJ?~4v}VkNc1!0 z2%JHXc^z%zaW;Jg4g)8;1AmUtf5JSZUmYmxa>qD6&>0pbv!~AX{tHIz{@rTf1_%H! z`j1svSpFGC^l-4TcQO_7RIzt8w)i(U@IPPyEodK=m5d+%BuO)-tzZ(80G?lv1aL{g zcZo_MB#;r9umNO*P~{vMI*HUt86355I+S@g8HC@+sRbRc%w_6z#Ls%ew&Nm&WxsSd-x1PPudnIwbKPbOSp5nn3Kh-kZ zcrgaK=|0QA<+_vRh<`|DZi_wDGhdxv9+1v^=x4y`KHISSUh@I)CqI5X@(=yD--5vX zhkrWmewg0KEx)e@#qp+x|1z;iJR(PT3UHhy6DeeI?@7{F?8pT^=bk()F)Zh(63P@a zE|!rzDl(*anSv#Y)W&csbUhgluBlH{rHZ7gl6AjDo3>fTf=J)u9T#*kpS;RLPdqL7 zXyZx8B%9`i$CBjB>6{XFgOKlIVb+}DE=m=7X;VuFM5TEwic6ThGgzidD3in*^a*>A zi!0ogq&)p%S0q*Kv`Fdm+?TA_b0~D{SfGnFiD$GdS0N*kire%u#T3Pos_j$Ff}&f- zlhrKc(CTd$p(UInS<0lA=%&~@%Z15o64PcDeFQCBCWGlbuV(>Yh`>Qw$I&hv7cA+x zwneo)f8~P`A@Z)`z>OYyWh-nndQ;%UoXdK577Y~y#9HL_a-!if{&~W{W|?1DTE|C8VeK#7Ngi9z`yFq3S#6fDjcAUI|?H*|EG z-5RoK7WZnuBN%hT+BCio4aV&9RK;7($HRgGOPVFR+Ja;5>~akmcEihdX-L@1X5eVj z?7}ptW?|kz=k}7(C}Q70BOUCINjEK5;n--*X$>Qhm=SKl7CYc?QC<*pW@iJ{7Hq^G zV~=|EI9G7Z0HZ>Sa7a+&&~ELZ+2LOUcnv0zLX1vpvli3KS=1;oBv0EmF;H32Sdk=H znKSY{eVLY~m;~B2<}ws>BK6;yhRo+|;^1L{gWH@4G0gpme8jWBG@%x4ron_rW^sl+ zjF}9Dh|l-KqMPf$VvV-(Rauu*_aOoP$vIZm4ELt>Jth(D=C{@Yd&Xo|BX}yEap7iQ!#h$GmQAfTp=)23w&kE9B(W zva6qO;IPkMz4?v1jg&^BbDm}5kA^pkhTuo}uR9D=Ne9 zt`SE*DsMC)WXOw=bta8SUIf!-BO?K1YnvjYQp-mP$Yd6-lGAIOp}`Gm+vatIY;!GTl^;*m** z250pnXkUyPvH1$_T-eNs0=3BlJjlB{!D4W;%A0s-pP{M57K?761k1LJnd91oa!u6S z$_4Fu56LicrEWAVG>TOxbP6)SSZxhztBDm#sV+(g>p9`3FbC`TP%j2-eEtl_?k?^v zA@p`n8|#`V^^R}rwoovJ2xa9?7H_nsU3LiALtzN;ovnDG!((2QG3Fq7-XdM2p{qf> z=+UArG;gmA>$>1k_enH{E?+N(t~iRLq$FjB6Gsvw$Sbt5D>G={!JeU+`UV##mb`nQ zm#;3lYR6(4`$>znx=lVV%qUdrfR$*cV4_Jdf38iUh<@R(my~YPb&3>8pEIHB)-IsB zl!S`km4}i$&WoxyFu1gc09Qb$zpc%;*gQtCQNr?%Vq^Jc^d1z}S-Ip$xbSZGoA$TM zlq{@?wCJ0oRTG)rGk@y13>>)op+SzBlPULOpOXnKVN7=8d(BX-Zeky|NBLt(u^;Z- zt09b`XUEKJ2gu@bV`XJ&cXk5F2D}KouHx2YWwyC|xh@9R^Ew!PcMK z8U7Uc9+cDXo5t9stZkl=#n_c`vvewZxi4&EZ4dEw|02fn8`li(mFzwcoglZDdc@LO zx#MDgvRx3pZ-3A)@;>Lrx<-fIC6B&21*;p61b2vw!dpHAxF)5^)p~mvWz{^Gl|sRG znNWe;mRa#p$~H>fOV&HV_U9zfP6|V3EsKp+#SFQ68#ZXb?&Aqxbnve+Sq%s{f2V?o;E8r~~< zd;cSHq(#<=%o%C4G}N*20$XOE6>Z5=N(aIn7}U8=LoAR99@s#q=u1*e4Mf*!*9O&w zv|HHF!ivA#DDJ_>{kf-L6z7>XZ!>xo`b0)d9wVB>XyP@QA=I_bDC<(9*>wFeGWeG6 zc^OMoot&ve<_Lb6v&t)QwKNuAa&GM4=&)!`G7vD%#aN}qNiVm@e-T-B&y0Q@ycBmH zqr2*uZ?-rtA$$Dwg&cI)gqyh)>RLkhS{+5!dqIK8KN-u95ba(r;3&3Cyy<+MGiJNK zc5X)}RqgD__~DyWnFExd!j$tVVRxM$Q*jyb>A?j$7k!DG-9-BNn4wFRfIjlvzz#5S ze~)0sfZkz{Aeu#V;@X=%*hZ~BxsRIoz8n+o+O?4+OVLui*jq9#kP38|H?K*~IRja| z6fL3u#1o>AXrvm+H7E=`Fi|_^*+(Uzi=|<$G#JwKT|l_oOK3=1W-kr7#GIIFBG1e& z_2Rfn5J?EIq!3^j{mTKbk8@A31V_1Dp9oy!xx3#>&w}^8xIEVfOIe=pyrRX2;jgDi zi_CJ?WQi2B6`gv9G0}-Veov!i28mShhNNWgUD;E;=K-YmNLO~p<-qNvQuIi78#M~#_ zvT5*`QQDy+Q%@Bc;X{$QWuUSbwVMT86 zP@JxzyWav$bLP+H1W#XO@kEtAd9 z6f(DcVm1KYt!G^i4Eba$9NsjIYJ+Yw$U};QpH1~}zq``$qpL$g0ZomUV!1&l-M=p9 zFWjlb@S3qQ?}1V0fH&5|I>8}*7p53=-(bZz4C0?Oj$=$F@xf57S4+3CVVFV{Q0m!4 zU6xw?!EH|heAl?rc0lJw*tgp<7St_>hJVo(M|xbkIZ-s?8+*!A&t`E>9f>%q>@S=j zZZ@qQ(^tJRvw@bwmOe&3Y8qMU-EX+}qUi?V3)OtWTIPT%@=p7M+y8&evmD3#qz zNgiYwGt)fU>JVdU7^btjUT~@KSf-9UdXGI)aRE1^&K?RXD^7=6@GFv8L#9nrMm^Y5 z-taMe2qFr&Rfk@)cUyOchU+3nlBUuh<(tInOZ8cD`M&Pkk%kN|Qt5`hoTkmhdSX$L z#=CRJ<>!DTmAs+wn?X+Fy4qpVKoyDla*5*$>47E9(QCf|3uOsty7+LP9A8a=H?thj zwizU+nT8ml(-yPSmep0;YV!DqaPcTV=IfLYj*2{vFFGhyXEPC?Lw*0>gQh|paDt*Ea7Wu43jfAn1^W`N$b>LH_7ZcM5{DM zv%u+)Bsx(Zol%xfv{NSx^qCV}eANcsTD@l72&D@y+rsl%0k#9%b~s=sBx5J4_c@!6 zY}+ANC-lde-InC*9^W4{yh8g!#!h(og)fg>y#A>t-EKknLt3tI{Uu_LJiL*-Ge)OH zLeodrQdcFt3Em~@oFj!)HwTO814_K90qt&io*7ez>%I|2@!cNzm`Js-LtaV)FnbV~PuRfEPoVsI!nX zCF_`C*BImcK=6AK0!HkO?>99*+0go8j!C<13_Ujo8=GE0J*-rtf0N4Si|uwb+-RPC zFx1^(p5bP%y32LF%Xw%>ep#vY$ZY)FXSs?iS-+ji8TD7cOrsOiiX)@*=Ia|_eMP!g z>^hzJXDMIZDhS^;%G?&@?u=>u`IU5d+YrDvJn;mcE#*Hf_J_H3Nt|P8zy7#(Or~~) zUUjE_X|-SOlQ$3WZG1{~o8Q5cWakb_uSFWmnVzEgAxu@x>?6ZiOKg(9nG*ds*)Vv9G&yG3V(#EiZidbQbjkHZt^4ZT4G!nZ{ zDd6A)CZn?Ow1P8R%S=F?=mFzXNlOXrtEKyeJ@VAw0WL+sbx(({GqRcaJ>%CQ{ofD~ zf^Bxs03rZ@Jk>v8fB&4k{C5`kzwkeGOFI*L_x~3G%u&*{MixZjWtVN5$;|Y#sA*Y6 z@sXf*K|~2Dr$-d*!WclvBkvOCGUaZXo+b02>Q%WD^m!4Nye+OVP(tafcQ&8n^*-4e z`uy|t1^%mS9kwBS2H;g#r5<%p@RzO7b;{yo4xeJLdO4Xn*lV^s%A{T2?E$2iC zx5|w|JDeeNgA&L4YNX=slT!t+u9YS5ReeosrTV`pJIr}YG&dP^F&wQ>$y-i zI`Q?P&lN#jH+yui)LZwT-WvN@OitMF3)L%g{{n#ZBU8V#0RaG5{*i7d`~QVjBqb!P z^q&=qRAm3I=;Dh#=4ibIrlln{B`ygq`vL|y7<7H zkWc^z!TcLZ$?!^qkfMMHNP1^u!}rnb<=Uc8*XJ8(4@Kxmxliz4QstCBEmX0!cn<@Nip?wj=INqs z)H>cF=DdymppL0Vf?pnT;Mm}~#2hc8E#@1HoMS4<3Sv9`NXK?@L8e6lbO(~(bUi;Z zcF>Mgq@hNx(6m7=81D*_IFq7-D^c%5=xav^=QMV^{XSqMm=uh>nWC)$md-sLrCm%H znp=Z;zKtP1YUtsQ3nq;C&#cQhaiYmr^(7-$9TOmjclcVb)eo`7MBaY zH#5pC!|9}5&{Q$)su<+&$S~ZE$SapH4rpZ#aa9gM_9K)&gc4V1)}tzvvZtv$r{qj9 ziRYR=4r1307nB}gPA}Xq`E$p02h>!Xc5JRksopMRtq(f*@g3cETv+dB!G z7&^H8Cvu&m>Ft8Dg88#OW9HrjzxBV{Oh~J4-d{D@aKap zJ>Jt$+|cI(Eq(9xm=Dh|J$%!&yT=;R<8av6mqz%l=Y25#bNf^nxhLP` zkTMU?%-P(XLv)zA=Nq3j|JcwYPxSq74)`(O_Wn5ZJC;Ma>7gi&0eSwrgD^jqebQ9F zj4*u9`$+UUulr1N{+EMd0FdPH+N$#x6PhGNW*}8>#` zPZVhx%QM*ww24xgR-PUzGEMrNJhb}F0f9%_iFE z%~kkyt*hN%4j$73bmK-`prpyos=J+u zi>I)}%lM#}-?ffntgCL>YPJ%0EC_!n$@*F=h^T{$B)a5 z$fn%Mj)`3iv6anMsjK6+nX1NYBAg#hG=7~oGBCQ~h9HflsYV6Kwm5pXC^W1R28sqo z9OJ2ajn%Fd^Jw=_5*J!nrd>*JD}}wGB5jPQN!1_TA6Te=qKIZ`y`hn-LPNWx$e-kEh4Ek`{9D47LCjTp zs;a7JRr$wKJ0thNL^^@;C77qv8! zwUWBHkyluy*=LbC1+5s;;t5O?bLS0wbH4w>**gYVwr$(OY1_7K+qP}n&dRK`ZM)KT zrES}0rLAx8I_JCZp8MXd^X`jSu_9*7SnEfhZOqX}@2$5cGt5%)-7M&cH;(u^r1K|R z@HfforFiO{3uiMWDwE5#2^cgruw$cd)a?fLj2}|M_ATurTx&>9+X=1R>mw!mRGP+Q z*+SvRPC_Umj-i2mIzRG2tx+rcNulVDO4W3v)Lxr{&}*olDYq1^F&hyNv$rV6CG4p* zV%-8FkFAW>M1!i{WqQF}C_JF~)vux7l>~7hLA(2EP~X8adeRe%V@MLu3}_^M%*t`W z_pHVWezN-bfG`P*v86*`c-sE05gT+Qm5gMq;&j%l|9adN>{xMthh-PHx{?)Qe0F+s)Y5dNiC*QkW8_Q)ELzU4 zp)rJUIA7mT+eqt^!m_QLt9u4zgEUcEx_}z265RN{FGxN_g15;u4}F+Kcsqpu)HDcQST&=e2Y6fb9Yww z`=QJNz4@LuC$i;ux`q1G0FM(HS3w(Krerlp?x8-=$pG4QZq@y?a5rs7(EwWlLi2#z z!mKmOX3@MbwPO81H&N1zW0*qgC@QfkyCvd*w#03P#y4$Jr;$15IBT2(EbR2$ z>O7wmi2-Wc0cx88oha!Df=y|pC&j3zW5P)^Vt!px=BpB5pO)-N9Hql3$Cu(?!eu@E zo)XD$O2yw*P6<@k7-grapKlFBDVOq+K7m40TWg$=dlKf(wS|8%CgB9os|Y#IOOEF! zKyT)kFt!RqpITc|@PNVd;t6>wH@O4xp-T+0hSZZ5FDLT_F$QLXeu%-ku+8TlbkBbT`Z;89%!M?k8yF{Fo0mX+KfdfZSHe=t(r z?w1WCYlM&^4k%_tmRc0@$l89w1bam(z0*AIau!|l)N{zez5q21g5V86rjOiJ?PQDK zxgmM3NFEq=n2bw!!xt~eZX09Nt{0`7rO=bwZw}*#^E%zALKbKMv4!n)#8z!sQqvP1 z&IvDUn0zNXwgg%P5|@rabJ@UV>6RqyPB!<9H`W}~TffDdGdc!NITTGf1m&U4=>bA_ zlky)d8eXg~-6DItn)&6AE`5_TP}X$8K?!A`!1TQbfd$*PJGyyHNZT?Wlx!9*KSKXR ze-*?^$D=&zlWV4_9tt1fK2$@7Jx9zZh~YB_yn8G_|FB12Ho0jh^Ma*)Bk{Bz>N>WQ zr7eqvl+nhzOJ0!KEeqEl;7;DaP~Y{^ap5P==^L=d*f_buwmS~&V&qVr#|_66#xPQf zwHGe5Fv*2sudx~3Rsbv-S!p;k9bxm7;QCAw zk7d>1zI_gBXh%cMd5|eI&nS|XXo~>x%J2F*fl`i^TLJ2a0_u_i?J9`&zIsB?pEm~c zwV_3tpGOSluZ&3%#_v60pzp1farmk8Ky`K8K1iu61-n92u-qzGQ0p$TD!2(Ud@-ov z6aq(fWIlQvrIt+D*rU#2a?b;35jD`LM%ZX!ml|{htpfK3RVx8%vypUli5ZVhB%=6_ zk((R@)dNj?R2u}3J7kP;sfn4{SsPLGBUvg6do?Z2x1t*c*qI(fI(=hvz=JV5lQ zgc=$a#IdAfxZ{Uz&7fUD*tXuAY?6zLOjz;-S*6z?LUcHpW19(EH^- z01Lb0t&%`K!F{y=Y~vqb3yGY!ZGlri$@qZPqXVE3=tNpG5q{;HY^91TJ-|tB3c079 zipv-qzQ>~Q8rconHak_|Hic#u)$K?ThC!U*0{m`DbkMj0MYdw>Usu=(Ba!W1_qJPW7{;2jDjN%B$!elX1b~jB7g-a{yr`Q?GNj9muN@gMZ`fc`3A@WUn=Q|#Ds{J2emeQi zcUH9@$fwdqn#nG@x<+LFC{tUki?*7zwXs`^QQyF#x5Hj^-K53~Ze74~Odu@eY(F~% z_X`OQ6j`(xpQo+i7=MUir^M9`>C#o9Ev)tmu|*v}aAUJoey}ljYQ2@&REjLIszN_r z&N1t-uqWbC6zeaTl&(I)JKK!q+pEXmtwyS%pDXX4wEc ztZ4_V$OogD{{b^Wy4lFu@4ZF#V_>FKaTpsMHm7D$C%e68<47*3IclXyN8XjkKafb< zAoVm9zcww5WU11Jfxu77H57W!wOY1XLQVxc#)49~(F|*etKXpGnSivuICH$KfGfV; z@J3O0Q}a=r`ZH|dWtrebL(yCM7#2N)iRlarcQ5_BuidQPq(Bg9Vg>?t%7G0vM?h>?D2v;E>k~zKHbTreG4) zBFx74fF8pu;16Yx24cP%mY4w9>LsmfChT0tqC^vW?F61Xbd$JYnEMVV0SW^yfee_C z@JbqVQwAv?$4=ap}!O zRP^#D?~%@MP|_UU`q;=@BBWyZ#HJ?l%-OHAGADVlq25bPZF=l%HIJ)>k0A2N9|#|e z$4`h|wIJK#C_eHSsqGhUQJ;-W{du75Z)=>GmUS-e~bwv7xD zYPw3wdZfN~LA910FXo+B?CAO7qqDe6sOk>CrLU=E?Us>SZf04vi1LXYw;uo3lb=$d znD)rOkPKTF?DDS&&pP_!IDKWctjIBjdjVzZXU|c*_#HlP*3x zv@|ep``k@#Z2Xpl)EN9gs&7^9aRQ_U)qr_%mG?Ts6mHg8H62+5QfH81<)LhD2bV?c zI+o4lVUF(E{iK8E^}XVDF258-@g60vJ8d2~+RAZA@}0TCB(tFu)wuISf$Zb4cQ_3R zIMz~ZnTHfIeZbQQ#UrIWr)WaMacR|(x~pQ8k#h7nFwvlcr^ptdB1~4DKNfFNv%I*& zYw@AeURpom>!s}88Bh!fMn;B2g>2gQEjc#nC3bYUCxax6*m^Kyly0 zczbS5WXKqmn}Nkue7fhFBtth8RnO|dxCO0b;`yjSHA<6X>$!f$r$}@uO^i9)PBcWs zd_}fwzt@hL7v`O-5=apxpU*jSueCQZQ7CfX;>g9g7J(6fOms;=l6gqPpG}|Tys##6 z-ZYsSob@YdE^!<}$?9F@3zdycNv7&Dq$qcE5a@M)Yao+*3-VO{w#%d0-VLfFAvNwR zdA%eThjz!LGf>PoEWD3Tbosy-(Z~`q-a1#hlE+-p&>)Fv4>N3pBRe{?qr@F>Gqh~R#n?+QDll^o%_#5qd zT58w6KmY)8f7F%zv+v(O3Up$YHZG=4B>(wB*v8V-?w>7$Xa!k$AV!p|P-^I~+g({+ zEMRo(LiB!FBxGbHqZAMN4*GE-%er-;cWbpY?gx@wpL3khmmt9ux|!)&^r;V z;@!xOhHZv|mR|di$B(>NO~crB{gC52UUaaj(cF#FN&SfGY+E{s207#%e>CbBZIWPNf^=JQERdyk#zkmAAf~q{Pd_Mz%FC8gmJ^@#4 zUmpN8T3~dv6sklrmB~QQ5lQKSs*!l}{9N}?5B!cep$(S`3`98guhXrc?)dn*_E!Ma z4rxa8gK>r?_r~IGA0jn+E}n%v{WmWzgsBP3O6ocu6)vvcH@C{%IiX~XCVei=dEw>4 zjzkh`MxT`ytZcH>A3tXs>0}c1hXN?!FoG6}S<4Tqt+kDL^|!8*si<$?)t^>vIy}m= z$YtG#+Ztxa99~O}p7V&+rH@A#acuds4xy>~)|bCpX#g?2!e-BzFY@3)Hli_}54cNL z;L|`!`vEkWo`0(>%KQ3Mo&FWgP{99pwblRIZpl9x^wGUiz=8-O6~-IU)*$q+pm->~ zg4ZdT&_V=x7$ZL?S*$}H%~rEFcWOMZf!`?{3kbmEPla8TbqC*`eZ0XPq6={faYBQT zA9%T&aEg7@%<+rob|4R5qJG*2YR$X3;$~R9VmGL1OS0UlDCqOnreb!7(8>Ar{~TMR zNsysK3o^oMH=}ev3vzg^ackPkagKs);qICGZHQ4s}!lqFb3Ur(n)z{t_KQ^V};Z* zq3TsdPyu7CO}ZLRXmt`+f<`X8dVdcv9c?f|%iUm>CL&j}4Oz-QEYQ;{Y|7Bg%B17b zP+_D+PuXd?gl|(tLG4mPR9q$;M3^`?{l3l`Sx<>`nQfO*(e&Ut zU!V9eY9dUZ9Gtx|#WBo2k%7Be#lR{G;jhK+k|}i+g9}n5mV)7fSsp}~H4p39{pcd9 z0Sak$GLkN;r@5Cxw_H7EUURxo8U7^^+FOVXlO1}{JL4|lm2gsoK@?WIQTOmZ7=JWZ z>!OV^VN2?Xr{=Wuqm87Tg~PO|Z(K!|K)15h_I3!zV5>6zsgq9HZd-e1#aQncORhj) zn462mMQSz}4wV^;DJ{9VEaWcCGOeGd>1-uCB4(VR5Q~T--zdQFeT7hE!w_R*Rc%?6 zxJ`tJtG~kNihJgmINcv6a`K&{ZXUO^S0Fra#uR5 z@WD)yL&(;p+AGcTiG2UJPOeSwROhQ?-Xivn)EwRuVtF!iai?!Afi8IM@B_%&298(i z9!1wuyOHE<`Ef^y4G$=ze9wS~q$r1&LSxQB$>=9adinaE(eox(TW}$QQZQ5VnlOk` zM1^!ttD<5gbKUT5k!K-7W$bSX_D=>xvN9mY3>O9`Gi_<&*K_a?!^j`n3dlF~*EU48 z&=!eihq&)!-i?&_Sv}v^wKD?xF&uAG<8KVF#z~Rf%h&n{`P2NH&u(r(Z!_VQ^@1X^D|L)|HrC+0+|FsXC{!s~< z_y2x9{Z}8}f37MGO9vcv#7{BqJF_M%?FwVs^@Q)pqcL#f^~j^*Hq?mqhtesiqwx+5 zJF~wuGCZ0JFJcZNNf3Gfg}#B{>=E}8f;p!38`Q|c5Q1~;AP~F<@T&+4I=+7kq>2f| z7kJ8CU5)OP`%#H+zdc*?c3$)5Dt~(BpX(3UBlXS`D278roQ}PNZ-{aK$sw z|K{Q04+6gr%;OUm3V-9k5-5IcnBz+l7`vyKGrDWs=@Vs+f4oZW;!}^p$TO9avvVnb zb8U$i^TQnpD#a_I$ye zqiu{^=IB8f=5|fbN`{o?>93;nQ4LH`1qHS()`Zn8wo;p?I3UxCz-x|e%%(Z04DU%5 zqRW-==81!WphUOzlC^cXm2kyz+i}WmBU19pdoEDtp*LFVuO1UB(-;z3(8Zrm>B?r> zb28D*hi;NGt;TL8hQWbDEediG@EWIjcX7<8x7iPFV{Y82G?@>@RkFfR3wGp!5@X(% zNsH{9d`89Yo-0(|*{$g~O!I6tAF|2ulp5U9$gs?(qx-x#rk~ z#<=fDEo^EAikk7zK#R59WntEEKyVrc!jP>I>w~I4f8z?g z-NOmIJrPFL@*kiLt{<=MIk$ogQFu9>B2lj<~_ub|60%lxGsmR>1 z3)^i7`GHFH#)hmd^MrKh=~(nf8`r4hG8C81VA%zQyqR(KLOxALlcP6=MfI4Lx$*dFWL=dM{%R zq9ZHBZgbWVZdPM5Ymks3x|A~Pxctfv){ORSrP-t5=?~2dQ`b)+*;u4-kE=g|z-?CC zhJosj73-*^N52Y*yRB5e=;tjIXnC{o2Jqg$?-P9iZymK)l% zAe|KUd!bKoSuY}>JYeFsz;Axu4}?g3XeVO+rC^UqLS_24eW=r|l#p@8vHVbUL72nA z3iC??ugf6UOBrtzPI<_8L++)g<#vpxY#$c%p&<+rQB?;j^0creyvssW#VNc{6H=Y? zwd$Z9T%=G(%2HQQzYJGHbl*zrXQExuNlSCvA&^uCJ<);>=9yiF1v){-Ih_DMd2&^J zxr%@{WbvBmKx1m1f;XtOr9WPFBGg8J>up0j+Bu{UWctcCxorjVDov@{d89Px~MV1=SZK;N!5fmP*~$J@xxr+Sq~B;1yr%N zl-jd?p!pwI$!qqt8gH~2jobOUZ@gSh{CVNfIh<>i{Xuq0E@BnjMmch zzQ8=mw+u@=sxJ8JzsI3}=3k5^b{QnoYoN^=YZ+l_$>*5DWnb-?4Fa1d?6sJ zc!@x`3JrP@)=Hk#ihy7$hV=Kv+5IA1Z34*wmPa~p%Y~t6Lju`_kl}|AXAlaYk8j|Z z6heu5Gi53ZGwPNBgGGx!JXMa%OGYmM>|PUf4lcxEH?8w9yF^e-ii`+E5CO(fl&U&J z5?}CNA$`w23;l-A#u>%D<=xfBoC;O%QmJHo=GYl+tITrr)T|)n5TwJW)9BvMVoH%6 z{4x>SUoZfcfOX_e<0ZY>5H_@cyh4I*UQ4K-V|S+;u*n`&FBUCxFZSHlOnE7a5IvEKJ#iU>&~ zrCtstzk^nN#|ddOG=sYKJdP9)N2;6sq8`Ws|AfZ7`CnzK_$u;+Jm_IvmKdCSZ(21T zFilcQp8Ok9JanV;O>x3BYzhY4ilo1Y+S_M|*a~#-B`7WrY?5T^BC~jK0n1_tJh|Qv ze)I$B%k_d3*MYlKT~!XPGR|+?f__>BSWVhSwG2(_9MPS;I$ocF^ozlwj|y z3wD=ZnQh9jyQ44cS#KV!ZgyG8J_aeUL`llLl&_PZx`;v6WO+AOT^jYO2ZR7CxkAE? z-5{{quvN@HE%e`?Hz9sT&c5oEtH^qQO#diu4a>cK{rWrOEF1uc0EYqq*hBeK#wq_l zCy-Ec{+kwbo!2I9vgVS7rkR+*4Af8#mh6G9%Th z1;Sgeph(d?9Ot1>uTltFS!Y`Cd+15<2gTi#KRKj*>;^PvJW<@P#C-_*7;_artZZXO z1YqdWjZ<}7-r%5h?>4VyY|6swGRqAFH}x0-6@CHD&4RV%gajl|AiT4>*lIOKMzEEA$TuG#LhzuM5+J?G~Sv~q?V!%X}&LQ_)h@; zq*g>PN$5QsvydmVt%J2`lL878L63I0OU5E)+UKqbSgqWcXSKqAN73}s^#G$R7-woV* z-!8n@zrwlx$70K$$ur$aH!(#7{3qZ?;Xs?T48F(#+@qV@QKr3_ zxf`AT$1`MJa5NRp#-qYed8l^l{$6#YcaYSYYV#I}O{matxT2#0_(zxIoIxvgl!_1C z{EkD>>unW}bkSwV-cQV;>6N>-IVxX43tqaTc260HM_C%kyZpJ^$(=nFGV#5};f%o< zkpg!bq~vUJDRSuqfWR*)>-3AKpr!=YNul`jj;u%5LVYV&LM7AtfEY+@^;7s{9MHX3 z*0jCbqzYwV!;ddIkgFM(1PM14x8UUN`BgvikU(pPyuzG1sod@q%jE$&yyvo>2gb-y zzNMS6Oy!G=AUDF$=31u=&oUdTwvnJ>|C3x4LU%>-ut51D4Q*{te;!29xwY5%BRIoS zgPtj~Qj275js1A4I~T>O6xOI>OudG(Tj2+dHDSu-=jf`MydgB-{)uB8*5NOx!f)`` z%p!Detsz=Np`bK!9BWZi9GyexGaK$na@81}8@KWMzGIpx!y}N=WSc#*N0f$?Pntte zS8%cX4Aa)hv~WZE=}k|V4Qza$V1I+f#+#XB{4bzz{E>Rg@o!h>-vxyK>Miw8z^Lfj zW2++Yc5KD2Y_cTPT4r$+Cn4DkS7)+t%#cxruOocNMn$SbQ!T*0O3-P16gzh%dZzS& z8~~>G{UH(!f>a~%PBGBd(fobw2v8GidLrA~>?q6n>tp)LA4p?h6NUz5o+C6EMv6k( znf5zWwY0rr2C1dp$VUDB7Na6-T|tk{73XdMI^_skRtz>+UsV=FYPyuLOJT{ioE;^D zny9$QIh4~2a|M(vs1~gQFDNqX?2Vh(r7!)4^P{hso-GLNusv6P+zr7G(a?el15c3E zOI%z~LlsUvKRn+;bkL3}hU*X8Y5rRwPGuI1cOP~>iN}?9seqiCRUkEpef?aY0flIdNGVuKFptX`}W#!=Gq2256xxG??q`cAH_gh8u%nPi>`?6OZ6pFXz70 zg#~Xer0LP*5A}r_P%ic`?IX!yT9C5a17nYq5>>hcT$y=lB=^{e!u9DpRYsucNhs;; zhxX*$ek2@|&)EhGa!d0~A( zb_#h1%z`Vt08XKz`+Zl^@c?_E6iz-g@Qipwa?ueBQAms`NpR`}!w&mNxpbqtPgDY) z=YO3;`2`)(EwoAb6kl%DT=EHVY00@5>ZUw>=Fd2C=6k}~VwGe&$@a=1r;Waf;1OAM zyt-%Gca*L#km8S?sxWlkIyFIbsl>D7Hs`>yL_}@Q5p!>L`a^_ju&^YIJr>6q%esUS zojy%GBaNBCh%$Va9eMTF%NP=ly@=T z#6z2XUTMw@ZiN-;XpG%?^JA;k#OJq)X2vJvC8_3;wgf6>>&JLA)gyDyQ*@p54>(Tk zFT7PHE0sL|Oq@B3(n7ZVI<>YftW%xi+ZM`qvf=9ZZ`?RekqdT-Q(Wk;ajUTo=uc^@ zg1}EVjQsG|ka))EZ_g-rczXb`dyDw-wWvgTq`qVoOpNhLAdCgVFefv+Lkks^uUQ3C zaS4=0Q^Q0DD~eU?G-0sc zph6`(7ff-71J3%oRvD!}R`S0v{S>{}>>A!gVY0bJ>pq zjv2qSSH%r;2VY9hxeIX1G0Eo=+!4J3k!fjg$4aD2*j#VoS?;~HOjDa2;7xOlBp;S4 zri(@L4F$=`;>Qd!zlFDGNmB`>=@UqUP|tM3hYdNbM5jyfci+n3gd^5-XM--sNy+If zGtXZV;#q`@xs{AAnDF3-!~6;55ho{=#(Rs&d4j>-$6x;ihsfO-NKl#n&OFy z)pg#1UNDn_ax`kK9>MFBE>41?q*5>$-?zSi4hH_X%qh6GEO{|s@*zi$%9K^>bz)28 zTf~?rlAXQ3tj;dr;0;QA_$#tqK=#RU~pQY{pwclg;7n)4}Pi~~e z39|NU0tg}7fZ*UlKra?^KK@ihybI+ESr+ras7Odq;6%Tmw@9!tu~(tX_$x}Kc<;gQ zb5+jrLvftSxvX(i6sd?rQ_PpHrg*rSx30Ro{eZ8*$T^GZtc|ya0-}Y5jrt1Ni4Ma+p}{ zl7@N$5`;?!OLSOe4>mZaAc7Vt6@!9D1hAHu;}<~6ky7w(qVe!gkd{hsVEu43Zvsa| zs-vmrg~rFKuI;02lC8*mwo>~&zEA&fbezn?cQa8<2c-Mjd_L!9MDUy-G~Q2B@EdA{ z5CwMTp&PVpyfO*x;PEGNKx$&4%;JMJ!6h1Oi3aagw~yg{Db= zU;FD=B%ribu#%~Q{d-Sf#2|*s!As$fJwF)6&isO&Zd%l0 z47Y+xqi}z2omL%{*55=#D)b7S&e1__ozBTYZmKQSo1BOz)O%U2Q=w5r6KHZ zI-Ay18|D@Yl#@aumbbJ=m1X=)33xCx3AiBzYB zI_rtX0g+-3`U^|rE&=^LY-?7Z$L52%m?*nFE&B0cuxqxQ2H7#6RTQI^3+ zl038XO{m9EFRBx_AZ`4RAL3QPNQC6TAiyjUrh82rkcAXt9DIzW;qLMT3wWiBYW=xr z#>kGKwo^=105?F$zmENtq<%QH?f0#Qn2~*U&1_?)(+lS$=Xg-|J!lFBWG(duq3o-2 zjbcyHro^fYm4gch@4oSeJL1sMhW57OWi0Yq+dZCmvdu_Me!Hg8;Q7O*?@PFxphgvS z(7f%vj+tHu{WC!(c|OPy2?bHvfyjcP1?hCz>=#iQ}4oMZOZ-*wqvcwj$r0Zq-urTJ4Zi-|4h(uhj)*d@enf0Q&5_0i2+ z-kw0h%<1@In~_`>N1UfrQlpgu+$s!eS=XF`XkF-MuFKX5gttgY=Fg)4@K(-~A)hFT zd>@WJvt>R$5XNdO~p5RL&<0DWG$(}#W#%3rSzOof2;QRE{XR{z4kNTM36J+)}==s_xSn& zjWZ;D9~%@H+wmE0n{FE&*V3nApQ&r!5q0|#so{g_d7POJxQy)a@^zw#e1Am($zx>-2+vWucZx)Py1_-1? z>8Wiit@#q^mn?j`3rF0>4wf_tduQ3JP{(0YLXz0MSI$0ul9?j}(4h>TzlE9B6tGX9DaKmu(Mc=p$3kY+#(c| zR=FbhA;q5ty5GBC#x=N*i zM!9e!8aqPl_~&4SGS)y&nW{Y^`nTx9>y2O?`Da~_6&JLDqv;~8bG|TSe`F7*h=gN3 zK70O(`>0gmRB5rPG=W)Wq)ImSfTT}s67$;6xfQjq&QPh|W$eDz1@daLEYK3x=nq0! zI-%=8Bw1GP*X!QkO<)!}C<%)>v?D^sY01&|bsPsBvgJZ4U5-s8XJ-aEP6=g34r!Q< zRfZU7!;NUzj#VaWDMrZR#+$Oim;&UF!46{%RTpx2edkbh(uVDAlkN!o>>9M5J9b@j zgF(s9N)_-Yi6AfYOE}A(}xK66v=qzYKf)ohcBsds_s80szDy{wY(C`k%6F zey0n+Nj87qH2v3behq#~%@-SNcW<3zg-Zh=%ZZBFl4|oRiu4&chYf09V@d;AXNfE7%hn zI%uwWj%thWK;5qiA~@qpsxPgu@qM1#cKlkQk+)ig!%y6U7LkfsJ~H@OLo{f$gbS9( zlc4cFBgd(@ut38K6N&0A!+8=}kwjC|J;+U1zs+p{8i+sY@-xJ@WTQIDc3-94nj(hd z$@^xy+ps0={Ct_q(CiR&L;ZHb&T*wYGbAD)9+8Y0Bq)C58CzUDJ_=HWJgQ_ztViDo za*?JUkRRGQ2Orb0?ewWHrjojWanXIUGCQoREH5k}ShR2JYX!WoHGeH>@FCN#< z=$QF{=14@%@c~(dhIqIoss>!Y4anRsqi~Qpli88(vkOG`njn-grntx>(l91D0KhcL ziOi>0!)oi0-QLPR+CALSvNjEC(gH_6(e)Q(;st?>Ay=?1Srp8QFHi*>+IH`=#aFb) zGeUg7OhN9UTCab~{xP@Mit^5TA(#>~*gAD;KExV*&AhT+d?rCm7VU<&gzZ zKGmR-xqyhmp7PLWL06kq0B?p=p+yl9P!u)S0GAdv&D^1Hz@JI3_|iOLZx%(UZ+gY? z-yuIS_Bn0yNi9a$*iKuHv(lYkrY5E?rnk4dfFXz#qrpIYEJP~c%@Is2j4jML#%Fr- zUJ-=SiXo)4VHDM->s)e*=|b#6@Is(re(LGm?EVWz3-|nf!>&grsGy(&Rb^EewrR0RSa3!8Y>==e~im z;Mis*#hkK`2_0+Fm+yuqi;USn($cUgYjBp3A|bK<_!LA0MMQ`0-R#Qry=x5HxEG|q)kA`xwejj$;OnmyF68Ce1 zxz%ZwwYgAJZnVAWVuJs;wQjy6?Ld!+xtcW5WlT2xbORET+EOI!*v86m2~D?|RP9%} z$i`cKy4{ReI|H1+kBa^N47w%Vd;Xw)6J8;uB$wvrKwJGhkZz;p(v7UbAXOG{j~L@1 zBJwu}9P%FZ8Obavk>}uujTNnHW|V0zDl-j@&|`4C+N5QwWkpqt>m&S*TrFEg*f6`ax?)!+ zF`n?i_}4J_(jL{Q9%?Q%E6YI@F1(L{}e1c?oqzN};dos?^D2rfP)f zUa)Tb)_G|x4TYll>s<-=M=9Vx6T|+ir`-R+PcB++Tnd;Gg|}r%Qd|2?fM4LG&kiPV zr(irn0Ryvlk8di-af}60((Kiq?j3+%N+#Hik?u@4%lp^)#@)lm4df0QatLz>;4V|@ zXK#d0F*32L4hMa5BaCn#gCezV@zonyezyuCz0_`&OVHc72d!1FbiPwgXO-#Maf3$L z#2L}PD`Cq!Yfoc7Gx@!qi>dO9MpA;qO{J`9PEk3UmvK<{YB*C=-}j#>6;ZQGcds$_ zku(}d(V3_DdUi6B7%XRs^A!DQ4z3H-hL85}K{xn6AqX04p{@B7|8;f z9AoCou-&{*#It{=DpZA^R5yP`uJn(6mH!(O{6AGHNMt=l3|$PBOe4af%#sTc{G z?;9^tEkG9tBYROksV)ZFU2BdrkNMCtzJJ#jKwh{hHd^)JYLe}N18*$oM(wIfW1Hn} zO0cL9+bZnd7*zfeT7FGIkNv=RKYk@i%nM(T-|2^{YWE4PTHdEa~Kk{BtI$+y?3 z2>*bX62p*MJPYSY(Wy^qjvPZluNW0Kv{nz|o+CFYZ=X)5*nkKvKz}BR?+T^@3^G3* zEcsQ+nGtzoC7MZ={|PS<_!AR$q1gu`%FN^9a$DBj^aKgae`@t7u3y{g4gPCER4f=!AM<~EpcUslKQLMob zub8nPxO!*O}bMT>fZW=DFVg&eyo>YU0T_ zV;YpYli^6)Tt%$n<_tV9aWUCnJ*s1NR&+_K@C1o2*388;s564-jYu5rOZR9c*BGAt z3Hoo?)%3fCLjARzSw^2e%-io<{Ce8}8#_e< zis8mWxFmE@7ic!zggUwWb@N?}S`U({o~$qNEaG~O2&|Vr7Vjo*btEcxC3n`IENm~+ zM@Pj?_1oLlc7@Lsv`;z(WE;NxP`c}EeC3~Nmr+|1D*n$yn4bn&Xt@;Kp&p!?k zND$d zA|wj$IV7q+L^%lAUSDa&mve_%gxpx zumq%pTZ;V~j%=o!@S%N@OL##c37eH#fB|Dg=x{rP%m`2$13+jtn`gwZtF5*+SupMx zka(x5HutHQuB)84IQ;jIOJ5=`S+$gqlSLZcLQXrq{UcYqqc+W*BQAD(hlY{K%ncgH zhKWg7yRE$=Te~gE*-4b2sYKruZ?i7fdQl1kZcm5`pBvR%FfOy3bkDUqG#lQ}#U^_v zW-86GrV4h~eQ3z{duclcElhgvd57!XEo<7WKo*b6od@02X}XWJ#j@koTy=e1qSVHP zUMDJdmwczI&#NBK%8$Wc*Mhq2menf-wqsmu#CIgcyk$TFn$m|Xx+;5Qr(tQ>XG+_) zA;=a(S=Y6eVVCW&0xsLUP;)<2rx}5!b8)hN+E!w=8@E!w>RdLPf*DAr6M_`(=A390 z{{#)2z0tj499ye`YR+>V7b=Z7^uLSUGDx!ffePoUoF;ZvvfkCb09^3OV2as6-7h+R zBg5S~Us%>xW>9c*ISDq+ibV^pJJJNy58uamUnFgd>i^C`DoUnOcXkBuUiS*dzQemx zsD@H{ZmZuIrC6|QuLl?Z}}{; zi%el@S>-GR`@YXJOZI`8P+`M84!bgzZc!?0Mu{|*YHRwgr>dS~@)%`c-q@G(H0EWb zTh#19a|E5YZiOVlIr+%Bfi-T<$WK4F+5BpW3e ze;#nHR+>P+3r5aOcEVt49B)s<@DMl38@vP)JDN<~laDG+jOpU)h)StGR!5!9U}ei||hncI{b zfoW+<&Lmzu@A^3 z{wL0Qj}6iVSrcbN%-KjdOT||GybEJjy%u}z@Cy}drd|xb;%U7w(=)U(=@FOerG+)KEZnvQDS!yEx6u4e^ zLaZY9Qvxm3Z#AUz|FBE}esWW;{Ck)A<4o(nu}t~jcbb2`4Am{Ym4{LN#1mYL&m(PN zfX34ZQsYJvq9yV|Mk?J1)b@AKu-OGt^v0K)!(56j7~^~ixg|4-WfL1^r7W`>ErDp8 zfr~&g7A)sKgx{cF@5vjt*K(M(;$1zVqH~9toz16ib4;f&eLt@njsZ8mb(fv=e7AeP zL4b$9yAG4;FZ8*_@aLQAS45TH8TE46{o%zEZT|mJ_KvZ=Kwp<|ZQHhO+qP}ny|r!I z?ycSaYTLfGZOs3fcP5$4hbQkOJ2{`v&dxb&tt~w-jX_sAFS)@-zW%~}aqvC0h1d+W zo>)z_o@mGW({_EYnXuct2Y2+C`|xPadwuk{xBTGS8ZTJK$1y}Tx*=zc7l03#Q!sGu z{v2V`DB)lw0jd+oe8!5w6$Y_2x+qSUs>|K4CNsSZ2Ug%uJ6eTb2d-l0#@KPFd- zM-95!kyu>Z_Y}z@z~L=dJSpjMQi^!bh#ha^v6^nwfwX_fP8LhE+GcJj5za;Y94z) zQJP{0&8KC_o~2n46#rR6;orboOCWOf2%X!FZLi&SQ)zZFi4E<*G%CCFr~#*IBgFP`F*LAjQKe@x+&TagZT z^QX(uyHEZ(-dWe9mAsHh;ZErxdRh8KGgpDHb3-AeRz=BRr2$_uY4O@BCJR1dEY{Mn zc(Vu``%U|oB|Bn&Z`jNB63nAcEJq8KK=uSJv#6x)Aza8e{^=LArj@;eN7?rh4fs-D zPm`m3y82JVkdAPRd9>)nQ0&Q{-{V17Gwx%jC+TzpA>0~5#H}Ug&z@~nzifQtt9|!i z+rmT`Qk*r%j(F2bx7X$+(ar*0UTkD{#uhi|SvzQ*8|!9B)-AJ1JYF6q4fymw&(uJv z@0I2gu-wdGTP*J@FezAPz7k<#2gVH%v2wUdDL$juZ-q};H#7LYv<%V|r;v4@g~04^ zYRR_N{$41tWW?iio9ON8+IV@=v)VxYv&3;2_K7nfxn#2&lE-NtzaRX>>1t9Ig}OxZ zD?A`muzuqXDB5oc$DW4yb7+*bgaa3wVo_sTcHrPAYNU=GKt{kx@$`nY;$Gs$E-l;| z)Z3|*I|)jft9n-y&dOD@pBtWVCkuai&y0N=WA3+1?AMiGa`-R%a7y7q+fa?uza(5S zeJR%QDKg6J=jTrz&d>Nzxe&t}>JQz#yLd+MWFh-E0V!#T!AR31Y^MiEPJLSotec@c?Frwm z7klgj1f9V=X;n!qrjF-r(m0mkg_PushRziq>HARsO|yMK(aSgbYw?BJfIiJL2mypr z$${zwC2aO2Wk?BR92Gl0rlw1P@)GGlp!EHr{Gna#W-%pB)72`f*{DjOytx8@8q1sa z!f}K0A%-3L4Iy(^^F%XoYt6sI=udg&oP9l~vM0CE$UECo3S9PXiidtW^pRK!Kr{k7 z_0CKAd7UcdF;s08ba!+Q9KD^`Jg`5S-B78b^$x^u?q?Z#$ksUg zz(CNi8aUWDIbucg+p|vmv)o+2k^`Un6a(<<31wVDzMcaSyyW{oJp(BFFaM{37#YAL z;RAZ%yB~!{y4{KwHbw@lsf;1xULJSc**b?5exPVy95Tj^t9awvLkvd#>F~mOu3x*) z{nPeszi^*6ty(*9_w>$l^MI%Z-Km!J2faU3=!HM z55Rz5TA%HX8`+WAwa=E=$HTbgjX3dl)jD*aGdZW@`>VCulN*77V{wotdO0SkZ}K7N znSsv@f*2<`KL2^9`TMOE47oodsudT}gprU4OHiif8>@2Z>@uG6hLb;}?}ekx7XpnZ ziZb_4xaSWg)w#i-ESGE#=3O@2kpEF_Hx*UL8_k9Er1Ie|Xxb4004bc>%bqK!w-hj< zKo5RNQiPK}*hK}fNU3Rv@5d=H-HT_D@4t!kk(CzG$&1MteszN7Mdcr zM}@wGT0ulB$(C!LZ*&@=#T?USZPo4VKSQUHmyD!$RFwvfK4nG{AmaPj@=5)6-;|n< zUdtd9%*M08OryH4s&YlVCs9U+I6D5wp|eC=3sh9lm$i$1l^fQuncJT{+Asay$EO~~ zEsEwytQi7cl@hsf*LdAagZSH99)Wn64^Chp+}?+?C>V8Wh(Qpq`ljs+VgXNdtzLvN zn=OyH<9yISNkH@~*AjWr>6)(%e9rNh zgdH)i;*oYQ7)R?pi3c>pUv_KqpVr`(y&Rrh_dVR|I+NG3g!>`kk`p*sQkp+9k)x0s zYKy$mh&&j5tVa`eKohuec6*Hd8S2&oqmQh2S2l}J16>!5I&j}#j}7=}3Nf>H^WO#E z4x=F{V#SkQpZO0!9|cJS?V+yjG$mrk1YubUgs(OT}_Noy0!j7r^Q}z5D@c93T=w zBc>RxsBysIgVrqy;sEX+#MXU&Ez&|-A6tI z-o#zhn&~`Ul#BSrsZ(Pk%_$OEk%(e#jO|^WY@*gst*6=)^10D`89f1k8qjh7#I8)) zld2A#bjy8nHmmtpP&LkDwPj~k8H%d^B1f*UdFF)?o$gAfsvrDY4{tY! zDyl4s_BP0hT=ss7{il|V15(>rbnwpyp0iP+<2BF#>KU2|S;I}7p+w74!@^^8D1Cik z@@cYMC3;J{z}Zn`e2m3}a6(GyRP*F9q=d;WfSV?04uaCF))~X~=H9Q`{}HtE8+&(3 zG!;QPU`!m5(pzsIV_tK5fiv_e&y^_^4=P5><%lbe)pQ6xe7yBeJs!PLmRr~khK z>BO|LZ4Vd-$m74wIWqpg=;;4j+tqhO`A_VK28CU>l@-{0mlk7G>)R@q7@5Lk+pVXM zqM*b@X&Z@DXnSye3I`@A_SyJbwM6|_YNJOtNXJIya4NUc^Opa0yOZ_vaqX25X!TAk zJXQ`xdK-I;?1sV_aSElG#bjJ+d?HaqFUhIExQ*m1`rvk5Vc*V~cAh7GqR=XRWGC6$ zi{KTjoD)8w06OXJkFg0AZMFUN8Qh#3z^1d!s>)!WtL?I8r^km#$Nr`!BsO`+8BWkO zyl4Q45k~e67tVBQgNHf&3d1sUF>ItgL?NV`y~H@#QldR4T$@u5d6VCAc@MSJ!~E$( z%{hPDe9da@sv1DA?TzTjzI+!oul;*UpPXnZWypmJoq)~o3b0e$ zfeYQ3TsG|8SgGD(3tifA=zI{~s$byc8k3ofpiV5$pj?tA`*5OY!4)OLL-sxy*P%2E zZQ4d&$J`WSQmm1KvLlIR!LX|Mf*v9-23B4)^9A#chU=e*h&<{urVE|}O@Eun@C;-g z?}*0@h2F-K^4c@i;t^|U%*_6dTxK?LOhEdL9;cMU6D1)P9zmHAUjaw3lgtAwBh>_<{u^{3;dsZApiKS z%V>cB0RjG7rI_yjcP{RK6Cxw-*vwBab8Ywn2jSCBc?P$hw~#f3lR}#hR(o; zPbb2Wu{v7}9R^pTwRSA)Wb6m4u&S-J3>_4nMB z6A^j5J-r>v>(2Lm@xAF}{5gxc6#xce9VTb+3gNAE;%RbHo{Q*MHA&6M$RqRd44wPO^S02>1QcHG( z2c$C}Vz%_e$0lEV=5LiZ0{W>+QxF7)%8X*Gyqc~1-JcLheLq%5Qs-7xWS4t-KU#Er z6K0q{6do{WkX&AwILJDC;;oNRRaEHA*@P83oakFtlODW#2m8F%hwlghK_P}``UoOEe;OLqv_v$n+$kCdeZ!2Fo*)H_V z*S2IcmsU@g3<3PV5J9~`(Qym`r2SDgoJ(i$YEMc{1rQFzO6@Aw9QWkOl>1YR{ba2@ zc^?Q!mAp`2c`aMQIxq4xH^o8St<^C}>{{Is(FU0P8G-+y(5Hv5kC2sKiFcnI=zB#$ z5tSa1(GgYeQ0M2yBG*vp{>z@J>G&m^CCjh+Gz6q%{gQk>xe)nIca->F)R2MM5dDfH ztPFU5>CvZGUtHe;iX({D2MJa~u*+`UZwc>;Rv`r_$c!r2*wx0-Ap7%KttJ-=~Aa0E?{?bl!Ja1S+`qWD3RtE)zI z7@KGpP$Qliki5b6KVFGJ%9sd{CF=M;T69>Z`}j6Gy@8gcynT~|&z^@Z)9gk2FBg^l zb(4DwO%r=vX+bp`{q$H?@&DX-10#ezTr2<9kVdAoL6$rhY4JsVuD^G~EkeG0#|L#& z%wy=`JUasPufJa5@Sc-a>)?}sKt4f1^@q%fbZ9bI?v@?z9Um1h?;^I!*~dzXoVNTR ztksj8=xz|l*4}u#LP8Z~&1Gl8yDmO(AZir~MSySYUo<$?8T579U8tW~YT7%?%gPL% zT{g>`Y(~PvM=!GBYcy4Q%d>?QnwPFNmDKmv3R+Suyr zb=rzL`<&5HdYU`y%N*cEhRa$vi+6@eLE9blcAATt%gU;x4}{oI zVB})lJ>A8N@2$5ie{+wSgnY-=dvSp!sSy zme696_g>h+w6;=WR!D0}_ZIN#Z9@Ks^C@r|QwCw@ouHK6%+7W-c4mj$h%RXHEr_wD z1|ji)(JZ7BNt>(`VS&WkHNcLAEUX%7_E38ncp}9y{LwL*WW|BgdG#HZ?>`r>%ojws4v{c zzkN;EVp*w=D~R<9pdr*>-E5=9wjtphVUyJT#IyfcMQ&EB#K=;+(}t@RX~ME?_!b#6#wUQ2cZe`XZGDt4^CTodyOQO5$>X49?8l=ZW?5 zBf*W8s&Dd$9t6-Rz<1W?P++ySwxe zz>i)iH7z+UsTCBZWdiCfSf_@lt4XEM7GDd6?CzyZH4}RbnY^hECsb89$K8eo(G$B>aGR`nv0+U>cKY5Hc<~V3AufluM9zMBgVPS2!1(b$K$jPx zDWwM;;T3f^b{2~Cgfu)gfqG2^C9`65n7~}0GP%P%-I%%jJCYUPJ)IQSPNbGmLbvvC z5ba^B>)`*I*Gv3v1ocV5cNQNxs+pP*p2Be!U{ksiF{P?WwH7ByZKGA|Yo8Dq zNvT7{dhQFkN=BL$uwuRG1mDIl#E#D7D1TJOq$AA3)wJ6;?hY!~i}#*$_PVIjEe8Dz z9d1{yz8GDus>)%ZZFEgwEpr_$>NFob%@jHP8CSU5)@AWl5?$0ij|GfVgf=HWS4(j+ zFDzk8OVyGm6HQ{DLy=wZT!`T*isHW1MHjkk4h>#64}tPJi4G0u^>d&(w$BqvUkGAR zV7t6dqV=Z*DcEU~;qVA`KtIk_|4NXCQNlqAizM#6b(DvPK* ziw&Js9vjJ$F(1W-;s*a{d7`0{sGcwCkTiADu18apb)|!s4NVG&7UvE#6ppuIm}m1> z*|LytEi1sdb>rQxow8L(uN|rUYc@t;ig#g;8+E3)_#>GEOQvn(pFxgmRLJ zozWV=RNfYNUzeC;&Rz)hV{pt07t|K?Vw17(w!hXW>aD0 zyTqC`tBkfoosG?QPDih9mEh?v|oTE`$S zj%em+feyF2m#?H!KoL)?x>|zdHf0{&I!Txz1eKtmtJdk&)nWRN&u(j?b`hI z@(AVmwm+gf@~-8wXjTkUB~V4y01wgqk4sefq?;l-w+U<$>@qg(Y}2$#A$UQNhwY&- z6dVUlL7?^GSL=PMQ3&Q2Hjyt>RLZM|h6aF$2%;d;qP7}0c7(SPN0wEV(r}8j+$WvS z<3j7+w8972w~iRZK{Fk~>s;oK_`86^N&X3=iTupFBBS#Bho)XlE18hGnYy70)yQ1i z+?SZ(BstOG)JsJd`~%)rig8Z_>F!S48BZT|g2b10)FyD-!isd`pq(W2kas0#56?#_13+|C+-ICr* zMvH=jO;opns*wXhWm@Q7*lCM1q38Jt$@!+*TXx-?{T(-2G_o92X(_D_vh?u)QTtt% z_$FHA82>o98R}9Y%~743Nw(Arbdw2>LU^!{o~XJ31q=sqH4G>2`(fmHfPOUV9=9rg z;02dCB#_8e#BJfJ*@RinMeomEjK4I-B7Xi0B9+c*c7(rSYtZwV*UMoYw#%h0s+YJa zx4%r-9GB{ta07QYUc#+{q7$4bfI5ayYM;qWZV|AIWNzugiZ(uR0v$8MfXj%F46Wh^ zO6WmD$M4939n@8>+aXlK=rx+}u=2_lW@dt6ibR-NEo-T!LUXu2LjWuLntv`WHxqe? zCg&ZU%M{3~^n)(`s?w&UiG|Pc|fk9Vn z^u3dkfoOBbZ?Tp%Z>j4>t?Rac#OHY!pT@@eW;mA^OiH^Pt}_93mMtN{Z!PCSqaB4c zZR*b)6nl)M-i<%-ZtAb0#W{}-Ppm&gkbZ(dx5Xt9H6tkyPuKT?V-D^OEB_JHLx$%_ zpt>=NgTS4mz_KI3Akp=LXHI?^P&9+A!jhJo5Z-`Z#7TZ~4gH#4wXn-B~oJ_h8;dLS1(V z(H8;fh}E~jM1@x#(!eocK^J&|u(6;K9?9Ej^13fKa<0Ixfs{Kb6T4BhT~*g;U2Z6_ ziBw5#rXr;ykkmy}jjXOxlM{tUUaH~sT)92P~}mnX|jA{}*z zMWiY?liAE@ZFCr0tCE-P!>5bVC@bi&=0tOw)Dxd1{kbK3pWz$^X__~(u2e1-DNLrL zAg@A`y(*qWT4^bj@VYKuMUs_f^GvZySN6n5pBjM)@sHWDjPzM-grL!gmJqEiUSO@X z5_v1mvY}V2r2t!V-Q4`-QpKG6&5m4O_CrlCm6$tJtw;qZ=BUG@t(BaHJ_xFMs; zQwxQELGWEeLS8V(v>H`LW);(O!!^P6okZG-g6_9;TpvLYy+S+1z2binXaev4o!qr# z`uB@xjCBa|5;gcU`r{A@E1khuY=Y@s9Jnw*hG+C^QGk7DvKlGi?1fv3=l#t+Wc1^t zjCXXNFnIo}nw~aj4bam}$)?Za&|`EUm!1lj&Be}*!xqFN2huO^O^w4!~9QwXAUg!!gaDt|!(j8_?>l0UML z1N`kv@PI#Vz2+I_mw1!sOnAe)z-AioUsQL!E_du78rO&@B}RjtRch0z7{oEvP|KzG zjZUU<#w&eS!ym=9xG2w4^mZ~Z3YY;FoI)jN$Yl)H%n)y!7?|wJ&?FC7^_M0 z^aI$oMf42TqyaxpenMJ;ZXW2bGb3T5J=gVEb_+&o6AQvYnP<`3?M*W@vpO z0e@ITDDShHR|dTTH8Z04q0Xk*lT=wa;j(MqF^ZeSYWXzQEbOA}%#;n?@1lV^1 zhaw#({&D%8%+0JRn~QRCKb+dPWL9+tKd(G#p^b$U`Lb|n$f`z*B;SVeizqqOZpENm zG_U7TE$d~{voPJ&cZH(=teeVTnIlMha>YJOj=5}y(gAS^8ypmMg^5+d+5vjoDTytiLYv@rUDH~IxPUc+8=Lx!3vhsb3 zblBy>3E#JW<@DQ{zZLAr#%Hie$Q9lVVqfLJ)w(2bj8FQ_X?mdH_e@Y#GU`zd=#xTk zNcNU(J3^dTFk>Y+R#x-na^7cR*?hMl)38S{VOuHkWj3e(%`ZzWNM{=Z1l}t}!03}? zLY}c!lERo#gNFa(jQKfFL_g5NJW9mla#e)T&>9L!HR>JT5W%)IxzE%pU$yxjE#J~^ zQYI?|KF`XuNFIk4g^w1UzfA^Z5=kD`2sHo})+Euf;X>&Kx2(OiE%qt000}lJ#-yn6 z(4p3PtI(dc#sZSnOuGg($XsG`WBYwL^2M_!ZxPCm36Jyr=~VjO97GIcDfVpEs|FGU z8BPU!7EAw!XK4m3hh*P49(a_388kQ)B1*yBrh4Y2^_G)7ubi{m;s)kK=^gziY!T7Q zl90Z2;V6cRid}hU!K%mg&K0*P0apyVNst*9|i7{eYDQ2Dze~k3ih2I(`pF%vSY@sR!@NsUj(^&elEPr~&dOPNnoyIQ{+<{6*|Y*Rk-em@G8&EJ8xQ8(K@_$`l;=&ZpK9OQG?`nywS$P8f_pqIq0z?!i{Wy=LM(Y^J&c<$ckZQK+HPTJFm{Q zW^KS&W7C6Y?g#!H#rR&-Lpuys&ag~lZfu=6(VxN%|FSD8tB519g0H^ZE<>v?l5&c>2}yX6tbb5DtA{T?Cx@wQ2-I>ntvq4*}YSB=IZMQ5JlJ-O;CC_$|{Ben>E>Qe>-0 z9b)tur{ryjGMiYO0G7SNbOvfnlSXY0Y78psW0f!}@(@;m2i)kP#6PIp`!SnZmCKL4=yOuLd@1LT_ysAL9^wKr7ZmP!r7IgzB*xhTXXCAkws(3i#2jO)Or(w zGh@610j5GX!g)d17ns2laD#N@?SaTJe$8tTVS~e?TcIB zFf9o6M#oyBxP@PRD9`L%x&TANqFXFE9td)D@izT7-hsO`f}n}<0K+8H4AEBEs=QKn zy29`MSp^PI7H3077@mYYgppc2ipCA8N4=y=SFq=kRaqRi3z`0$~6OtP1t8r~Gy~@08lYFkrJB-x* zhjO|?q89&IEpU}?mI)UFY*!3@`aE`xnJn5g4EU17b~X>vQY)0BJ`7zB_|#~%QXg2& z=1_xzwp(_?z$)aDA2*~gUv@*BRCAd9gN zV<~!3E&g(*@;vA}+Yt%xx%gPH29x5HC@ELnegHIqKGHaT)Cj9u@4V(RB&+qIa|=PX zKn-S(MMZuEp``4bD1e7wdIDu!45>S5A)~mEAtcET5v{O+$|3{cZmG+nQxexs)&KEB?%7^@B|5iZ(%P3|!Njt%mr(`5PEI(`pMe*IJzc=G?d;g7dt8t zaj-7|<`uYlB7#~4%aoW&0$H(@g3ni4-GyG=+JYYHby=m-n`$s>GeYU<8~Gg$`5lqu z0bJ%lc3hm4=Frbe#i(Y&n+V0$Dznb~GBvG1LXE1UbCd5VJ>B+%xUEI+)n*ge$;bT~ z!O7;h&0zf5rt4~q%`4b#61^=kq>G4=(j!%YeY*3?`!~f`q<`n;QG3pWse{H>SYcS^ zMd^e;Vm(tv5rH#_AS#NuoE}9wZ-i1HAy}3$B!eKZ02xP{R25H+CY-uS9eWm{&VPpc zxevEw*!9pNho+*Mto%4X2U-A!a1#P&0JG5p2lIxOIiMJ#B7j2Qh$)K7nJ}y!X+ocmShx6_HbjPzXhyP$!JD1t&utWDhJmjx95XGM=D$*!+(~$n zYE7B6v7I1S+^8lYE2av|VA#tcy>4w}%8N~w(Aq#$pv4byU0i9v# zkStni7nS&PX_*f!Dd^Qa5FE}+kWCJ<-Ub8iM=hAhh^uQR&K8{~D=!M`%?aBtyZ3Ll zkDEO{h1&)fv?G;wwFFLH*Jq8rFJ6SX^sSeI3N&f-RDw#63wQ zp;2e$L3`nB_(CbOL*dp zfs!SJ+bZ%%tP3<>i_0U#I`i1dw}~h73@X-~6XPDe^GaFk`7{abCdf`+Ss>ZX1`c18 z-E9%4pD(;`0Q1O&&8+*-1R+kH2d&DiB)r{fmOA-Uwq8pg`#lC;Dh!ObLA}i?aTk#> zR|ckAWZ-U7M-)G^xob*lTsoG05?F$za$FdmVv)99ugROR~zy<`pMgN2`SG3_ZBL% zkVRlMb0upZ#2=@GMF@R=#-D0KoI-PUr}U5ch?g(-Le6jJkCa@~S|LJ6 zXeqQ|+FIXHyZtjq`n;3FnW--nz!+YjZAwR2V@Y6h#M}lgm;lVjWpqg|_T-f|KtGOd zYNoCAW?ZM7)ctilTuGkZnsG4Il#NInaTuzh;BLe7z&GHU(6_T>z1x(Izb4V3!4C$t z|Ht#AN8EqqaB9)UC9-L=TyB5Xhsg@kX8fljr(oc`BdB0mRA0W zyYCXm%}D)St{V%7t_$0r5)MZlp}3RMsUKXQ8;3!Wa1$noLs>_+GUAhM3 zdEQBWgM?5wB)RqDd;_W%A0#J}75&7l%EM%rgzaHdkQXu}q}^D8o~|Qq*ZK0u-CBY5?y(>WwNrr6j|z=S?uoxw^q+AEeXl`!36b>iAdn>3 ze_{f1$ly%+vBBQOSk=Q=>ogQXYI31@Ly#F!Djf!?gTl<{2vOE|9bE7RXn*%ZsUqe^ z^iI$pwd=KpC89>`nkp^SO|WZF-D{=U8vl;Sv}v<7+nb+&PZg(qtALd%e`@l)oXOz1EF-qCNY|JbYAvWQGA3L9L6b;1OQC}M4A%>&g5pN}wWL;5- zbcO93>p8Wv$x}|7u1PJq9cX{)TW6>8@fl~GKzr24t*KsfpcCX9wb!g)gYg>WuV{6P zW|!xDtBn$KY+rg?Cwj1r@Yb0&1V0$K3MHO9Q>rw+v9saN~T3k>Z=*~5wx+a3}))Ac*%EPkj6$B#BNNS zqIVKW8RR?Jj+zWo>FhJ(Zcs4RuY&&Q8MjGfn_wx+_ zA=|5;W)=SmuiUPjOA_m8pEtwSgt1-*;cflP z%uVBm;*RT8c+?$5iu9!!OvsJ3Bk0>tPxP}oF;R+rt&srE09&(@n?zIoZjX#5d9FN= z$Zsg`hONtW*+y#?o;+Qj1NK^Z0ff3f7St`)svXGo^zJDrTfp?{wnqNR3yyEEwJ$*G z>AF(Y^{kI)!*;(G6sxF%)8sf_pd-bHAJTQP{pvErQ3Z6vN0ZUb7#$qi4k` zs-{qO2Z}_rzY6PlAIagoyUI6;FQIL4#+dE{dS^txKMbFy_w*+yuT3P*f;m(KM&^gY9$jx7 zHRy;%4Stzn!=zYxcox3H$R4d{rfV@JR~pW-JM;wR{)fyjruSUD#Q8>!F%?oJ+7xI& z2KpP{i{00NP0(fz%-JLzhr%L>vZ_vF6g>*~X>dk>-Amz>FYM%cds)I4Q1lT%2qy=M zcHPq|HBA_P*MQ288y}-l)TIT(Q4vvA(2u>P(t8acb8ZOlL0j)7HruURCuQkx10J@2 zs}u03?~#e0^q=G0y0iAV2ob}`)KR*>o-}uDomt|wL+%B}SIuWC=}fqv_S=crXMW7A z@d+xNd(ZS~8|JA3XwsZceIpck0&L(Xh2fN?hA3a&8L0~Mv2v1z&ls4WF{wj-h9;H5 zr31_1HMb?~ytP0w;ahYZgAp#NHm;ftAeCk@-sS=n%RiB?g1vZMIKg}F+Ht%CJ8_4U z;5$xq=E=Du2YU;+uNnMG(6dAS*$VsRSYTAR%qubVzQxO7loSNndpKT?AMl56Pr79_ z#C<(ppVzs`D9V$kU8BnO`V$T5YfK|Ata*1$fF-Gz?0<*v<1}1ga5wM!Pjq6#%NIxb zwUmx;0^vGijs-D)x|o6tb6EDQ*-*ms8+IJCKa~5>y%NcBpZkG=4zoX4{gD0)tv`t2 zUiS>+cHsR`zeDN^x*jPo+;+rwp7aNzJ*FSPIU=}ka3AF!SN})+%KAN63*L3(HS0a| zGk4_Ube;7|+pHHsvFViT(sh69imT*GSzvoEU_j~+E=?Xf2y-$NWPmdI7m@ZyF!q-~ zyHXv^Vlbooh86tICz>ew-Z1XMR~SYlC3xPSI~y%jAy~@zX{IWr#U%$Vt_`s)q_}AN z#aZig>aQ#@`-xKXmu}7}my28NcDr}{($iGLlsqj7ec2>Dn7 z5pkh%+lf@I>9J`p$oPowg|wFYz#wzbAn~RV-ckQ#Q-RB{?s_O^DWU9NC)VbM;yR19 zTY(nOW7HxxV~^?i^wwEs2iqFvhU}znt*WwYTf;sTUK!*hB#h4hF*eV>y*vO*nievH z19!2Nn@J=m<1j_#F-b55n6gB0Q>lAer4t4BxQP(wE}({9q9cvEsQ5WRHW0pKds1fJ zoW;KXtYCjLUCK#0Kz8@lj%6h*Y1)R2jDOApEB?Adt317HZkUT&kuxOJ@BLjQ|E6`! z`b>zBuglk%@kqtfIbR{dyIF89Jlb8(V!Cg0uLMoyYU4Idw{OU5WuO&jc}-`zyDYJW zKBQ^WC9|&XkN2ib<+8>g%r)G4Y3qQ8J-%M(Bg4{caD$B{zlJhCgRZK`3>o<<`b#+F&!Su-YC3YPQN&^Cnj1J4kCDLkQP?wA2E) z0Ox0+perdR9{`jZuKe_$L+<~YrKNd%Rh%NzwEs!R-J5e&ePD-=4jZ}Na z&Od3tg0lqziI1~K)IEtHAY ziX=3O6>oqn3>?-CMl@Ul^Mz&~KW z;Ltxv&_7n0V6GoA6Tcr2Wd;Zp`$6*|l(V2GxN0yU5AZUdl=1#>;V+C&8wCSa*Q!_{ z*V3D(8d|xq3eRj_7o1day%W353PLl}zk(35tF8fP`Eq?`<4}f{A$=%c+20bvR;qjS zGj#qq=}$r!z%=5)@k6S;RvU_drHR>!grQg8L3&-ugRCIkjc}#q_6;qA!xqLkQ93xhh0U!EC1MqZW`hHa-+BA)F3f=AT0~T`)hRn=!giM z@3cw~PTk|uMW)cxv4{Z%&ai%Hr`(@cD420|8RtnAG|Sj`FX;kfBcUXTenql9#z5A) zZxu!`eMS&bLU00qw%C;zW4<>3kB-z=*@Wi+?%BmW7FkaU?c0pNmf{KlzTb0+#>{$( zPvalvx52}O5_^YsE{M5?RBHmbDEEe&6@=n~SCje0$jl$7YXbZxKg1fr;;Z)%&}LH~ z==JA`{Z;?{m8n9Z0ua=vDkl8EspoSh#RA}%r!4A?CcUVJ`1=dG7s?(eRkw4~z)>#M zefGU&pTm6<+Lc!VU&Dp@>ORzQ+QvQLEUF4jp8;(TxPV&zeOfAB7(wiP$fu3*QSQX5 zIdP3y#d}cibc&-U#N|^8?<>YD(et+-8+)(L50k=F4m{at;Q~doM5xb~smSXJRXX(~ zsvfR=RT}(%D!nLrA1GK=n!r`?;160q|xw+<(wjIeK65a ztVXfBV5raRO!9`Xu21e5UE*gg7ie9s^lqok&sT&GHrz4aDgJZ|-2FIkUF*P zf&=s0=+};w_+$$|^7W)=3O`C!Hi{h2q;I@$R3sywH!9p4gR$urJ@ju_%KXu+Y`~a; zaSVAH(j_kNa^{Uq+`~^JA)hs6D#FA&f#fL*Q;i>Dg!D@*zWoE|PdRx>f>n1bkw5*E*kkz8~w#?wbA3&6BkT^a@W;y>+ICB;BF)H&KB> z0OBg>w>k6S0HI!&!MW!MZFauzRELqTfl~nFa2`m{5ps6I-o+uJ{f;wwu@!)OM>`(s z{Pt;E=xDb0XRna_c>i{5d?e%UwY}q(_wBR(By{iK_SRnE4fN;7xfu2*v_Eik@AdBW zJBs0j)=RZM5NG#D5Qy@ZmvH8{i2EI*PfZTw^!I-j$B&pecLNxJfSio}yW)7J|Gv5X z|C%WKzdGA9bTv^m(Z+r$L**Dii=jwN?9*rpQS6#Hn`n^9*@JPSquUWuKx5@COe{c( zUO%5ju9T+br+R4(Jv; zulmooe-*U*RPKNQ7KoY~cA6?%76S(@ei&z0Bh>YI_bv(j1ob`s0e$ zWa9jq5M#^1M(h{R*D-LYCTrJO z6R!2se-{9HwDUJPOA%V9PI_nGykw8P^Udo`y;iSq{9n)t_vC4}AVmy(0E;zi`?IT06qX3c`<-m5az$A$h? z-!L3Dt^rU%G|nE&5nmKXOl$rg$HM8Jgsj|+k^Q7^ zE_4)&wC4wiyMj59yn3)3EIcw}bwHSy7==%22uWZmqQin^Q79)V>tMFL(-T6G^^Yd* zl`gI3*Kb_UZ=uF!>8EJSbxsbe!W{%L>#VW_-k4@zktkdShpbW|IlSw z=OTSd30KryB4DGG8x<|^RD<=W{!kmPhAZ+^4R0tinsmr7GC>UwFh(;PiY=)#Ld#Wl z2sc|jZXz?nHe1s{wsS z1tYq(NuHV8JL`_avuTxQ#P!2vLk38KcvLid)v@16tumxNKFt@nt@JDn)EUHdtI~MZ z@^ERfJ96z^GCgfRpMdUav+cdQS6y2~Rc&d1zIodEAGEz=m}Tp-CYqIYrES}`ZQHhO z+g7EWS!vt0ZQGT+wbovH-+NB?Ugvc8?O*emV?N`@91-!3c;kzBqbAgc4KT`QSUyJa zCpNysLnl*RY!0jSO8oaAUOSI$Zq+NR>_i| z@MDnqI!EFSHMh#Pl;442?^1*mAc?SZ&sW{{~d0S>E8QE#nDHBL1xJn^y`wf`i(ma!3k5~B_ zvXjoz%Z~s}wJt)v2m5t{0_YM41B&5-e0{9L^*uYkxlX%&(Ev+W+)KPh6Mf*|of;_5 zNyQaL>xlclNVFl5nJ22w{UAF12_T+Ykx&gRZt*Pfx~@96*aOwJN=UvCQzbZVhdtH7);HQU00w`8TbWGFI&si7LY}9ML@$Y)u`Xy*m zBfT^j8x&xgSNWMZO|$(~7;Tw5J>6k*(AZI*@QmflR8jgUc@Pc`^jTM6rEBCwd0?D< z^y zcG8_0mKy*LB>g!XpCrm||7Qo|y*tkmb($>_HKJ}_1LpF0< zM@9#gXaxP})FIN&fFIt^sfN`D%6-up4nHf!6&%_pEUv1~U1Df|WszoNiZifvC-u3a zpHW;>7TiIx8?0D$`Y~!X)RH~Xv9W#3v&FbM#-q}rhtO9AM?4ZE5!8D>ioG`S3&$Jx06?^ z6aAA{t)y#a-0s7NDV{VTa%S^mF&t9g5+6(AIJt$`veb(%m1gQ2I!kHygNfFUkJ^&1 zW!cLKh*eb$1&`2rNjueK4bL8y=`2c5qrkzMn5pJ>zQ9y@QtGg|}^6+OtRHEVd`6%L-}30+7qKrIRp`^iSb|#9-slPjj!Y z*^q)4HsScSghritXln8Jt2Sd9JDJk_pP|qt77phhAvd<$?aL@gj6$CnsXW%xDXqFt zKSDPFokVk*EOj~li?`+H)Dc^oA_Nex$Zq?~rSN!^nj7gBT6)%&s zaY-r#H)c>z-reXi$^a;Vw&;1G$I7=085K;DYv_Emkz7dWi*qHnGRs?wy3#H;7*a@j z6^O>6u)iYgn$(WkV@EZ;N!pUOOk6D9*+Y`ybXymOr-a?Im+xz*+3HUVWawWcy(|jU zgljkBa4O0-=FJ)l=)5d z=vZZ9ws{ajxKVQvk(^5esw}Et-S7C6@p!IeX2_kJevO`6`lP!gp8njfA!Y}?4punI zAnHQ>4n=F%~JgD%~9(@c%fe0#@!DgP> zc+C(kw1GEHZ5LhTsE*gbT)TLA>2SALd)lt7=sWVAVMFnKFt?iMUU!i6OVUSjZ|qaw z+Y1xTE=Yj6*%O)ByV%Jx{6nVyj27^u=!^s~_EzW-R5zguKn{P_&bG+SbzE(?uaI5~ zEu9n~Vmu!{!b_S1Ii}*Tz6l(w0=cwb$l=;-6~ELeJ0tNunA#%`x^~=&#BM^(0C^1t zJ|PgFrd!Ou41(^tjda~08Pk~O)B3Qu@}p)pJ;FaPHPHGfKRB7J@61eYc@=Th(ibkb zf-4TFe4GBPv%ij^uatl}qT2n|!D15Y`;qnVbAgtbC z?|+{T+~wAN2J=I*52F(j3Y%(UZrw<2B$}vOQnPLfV3o;m9^{lsyHe7z)GXg4+fv zq_f=b`s%Yw-qYjimp5J8J@PdZnlSsPV#0IG7;^RRKYI7KiV2*5|0ry2oQ!Rpq-^#7 z#6bsJQwL*5M*)2YB8I<4h?Um=SOCPmUTANLm4PDG8lq`N6U-qUVMcz#2dq$m1Xl$( zwmzg&q{)76af$S(`T|8n1OMF%;Ez3ygdjL>^eJ39*_+(Q6H}GGpRb=lJscYMY5mTa z_bvMS7!pGp4fasY(XPX3?I>d?SL$l|BZHv~6s%}CE-iP?WZtY8*tnq_F0w2e-{)|{ zR;)uQP$;f~Hc~BaL_&e6^H129*MV<@DA0KgS1OAIN}bW`E@x1op|HyaDrReFAHH3K zA*r7Q;e2n?l4Q&Qt`}hdLd(J~3bFy?iU1bIDT0@?Q9wZFRxqj%iR#3SX&}{+=vRI{ z?rJ3T=@Y+)It0-da`YtNf%b+%20Pwi8!=qvM`i|duGDC`-ubqK)ndk`R7{fXM$rfj z(tiP}1+%gILAX2UBr`v=9|%twvE-W2#F0L(o+2Z^zXCUZmrHBKfcHVr-=7r0?{Xa&&gm zxeOxzZ&p6|^Sf{C9Lr?(dxT-9 zV8C?y&5LY5{ZgS^Dd8?}KE3|<{qvZiz1zq43j#0P3mm%zB_QD3D{m9Y26&WZGM4q1 zy+~gboYBV7QBn{m!WBahq=qyt3fAN-dQz78nM+fpGKEL*H|TtM^|d)^(5E2&v1+P` zYMLssw0$tmWvp=%v?)uI*`}y`3*`ml$*qO)H4*h#4_NXLyr+xdP zwnpRC7>!JY=4blP*Veajd5-HWSl)}}m|$ zECuKX4<@Ub8N5UKc>&5rLMSj>A2;#2;iwwYigqZdFLSi|I=z4>$WD2h{79)t8^b^t zE2Brq(him7xnSN14$$+Y`(kb*bPjNuj1Sh%(J3ccDzllot%|;wL|g`F98WO%Xtou@ z(3_%e53dN7X^hy-=SsyFTSUunVXdqrvmp|RA_YnzT`A6bL0!C%-i=-l1$nb;)9uo_ znKhQte7U|E)asySsrZ=B$ot{mFI_D>$7V406*o8mH{SxCV3#}Tg6{p=F-fS~(%$Rb zDv@K6kEndPYD0T4#r$2tUtICA>STLmFJcEigLrlw5qURuLha!T28`dA+}}%(MB~E- z5Ch-f5O1-;!2mtuK9N`a$u0<}E?NNzA7?`NfK#=XeTdK`Rx2e)01y+-FwLJ3 z#a)1opA1q>h4DwlV{0=^as+yUfByMii@6^Hzxf?mm7sq|eEz=1^+$C}$U)!qKZya! z|3im8cu}|xGGZI&)^9*fyu-Z14;Wz~FvN4UO0BM`u)U|7;nrxc7k4L?K?ZffjWP2| zYJ0--e$B_Ls}sm@g{YHL=9M;n@HV zv2KphXK%5AFm^+WqQfVM@)XmCjti;r-I6qIyU3XM{ zJVIY|$k6;d<}tK!Upq&#io2r1}iU#x;USs1awICty4Vj)JkuaiF%SWz{&jY)p}G&V%H_{t7Y zJUBrF!kN@L9pQ*O!B6*T9+l50++R1FMO zY2?W8?cMn$T5@t$2^8zhSas?CB`|JmT$!kWgNa@eARU3zRM#3a%>XL*0{Dj+g+7?} z%zu*-g})VX|NC9b!ftj}whqPu?n<`KhGu^m^FLmcu{ARO{jzp3|Ca=GRr0nhB0t=4 zw`Uc#_4l%!?>@rv6-~k|C~kt%0Q6c!1HgTOw!@o%metLZTiX6#qhQiZaJXK}FMGU3 zS)DjS;@)ii<5L$dM~wB1^~=}YU0xtFLk8#|3la@n6a`_!#$5c`w9y0^!V?Tg`GW9E z8qihJq&G=OImkns)k^V;nsqTju04d7A1&vSgQ~JFMi)3XcHQHP48M2~{lj$VsFvzE zSY6QXEa{Q?HH0@1eE3i$cOA=?LPdPrT3xc*vLfx~;`VY2Ss0BLY>qxn((WE%R zTQu&o=?;wEI1E)9ed|w~6sz}S22{0DL-SS;yTW7|!m%$TLsXsH>B+QYZwSYK%@1RU zsU>DtBg&`k=E%uQEt86_8|txS%R9U&IIC=kjri$z*sP=W8ktoM`5)gO4r!i+C$1%7 zIm5ZS!O7zffuf<_CVhkEa=flnY0P$7XR|pinyiV#?vdL{sde~8nP;kR5V!iyS#q34 zR$yQNPFyvKOmEvKFkaYP)1#-m%0*ZCWm-QC@ewlLKCS^BqNR=M#FI&wT=PS{YBOKv zfuZ>$;^>Vl5+r+24^&2zMZ-;&KNdZ*z= zuUo`g@xdJtC4_~?74-6!Zor3>-elJ*NM%A_1512JxgLVzh_dsN>pTGMX=;`Uv#D$^ z=(ba_t$i=e4i51+f;H%K;yRBQ7w#VDsQet{!?HXvyEMXL-u53}K7Mm;X#U&7%|QQd z#hdc~QbGP-E8d7?Z3L}s9sjlX=N~@{IQ((jU-^L?eFPvsT;-FK>NC;=2w@K| zE*@kbXdg&wbbEA6CFA%+=?gOu?oPph2{R86=ZQ^u+evL&`&o(p|GV^=`9G>wDaKJdnUl-k zYAR9TR$T;?(le73&jtmRn`1_KJLr|r!DJJ+Lk(>21P=Kc?1A0>`6k%HvDhFc47v;K(A_ z+MB%JI#>J7-+k@j&s?cac zat>F;LBUv$hw!K$JcYdnm|rP!?m+h}G?`0JPAvJt(*>v-OsSw%1fl5BR<8(G?S)}AkpQ!Ry9cZ?fthq4c&-J&8-kXAG4ci_epI9D z0hx+Ju`c?v{@~s}s5O-}elE%HsDA$s$-TmVit7JDL;8PQCi~Zlf&_Wnc{;e^FPr+1 zpq?Sn%^^r=v^W&{z$Vg=I62}%iC}K4@_~X(jm(mzaD-;#ZAcwHK#1FkP=T!ZS>Xa< zjlvhJ?ak{c-?!y!TV8+;zW!lktG1Twf*>#&oL9RV<4{o=oOZW9xDHP4ID+UHPKg-v z)j5sg$*vKGbb2Kn@~R2T5C^quI=0CcQgoDciSg%te%0d8{PmLTLl>-YAJM|G>S-2i z$I7tYb%EzOwMRD=sRTA=uZHpAa#tc4UfRtluyDF6vUS6j;=`7e1s679p;{IN%&mr} zg4GIHZbHaImK*>ZCVR%p>B&Ndbfzl*4cVv&X681GDZj>x){n}W$+3xqE{Zs{$fO3R zZ0N~da{&XlGp{S$fqte0+hk>P>k!a&QUfADE#aPR%~7QR>qD@Pc&H7HA<0d7Z@DJ%z!komLzW%Hlz{k!X0{}+Q>aV> z*pjWG++*qJ<-GHN5Fl^Ci ziHJxr+4WjdH$f#+E{oR(UrMAp%=UWSo=ubEA#K+X%G zSOYHkLJQ38swUmsg(D?P6DB1!tv-ce481L_9au5AhB+XXwk`4_S_!e<8lweR9|{~* zsZEThWprqL4&R`>o3?x};C*MXD8-bl$;`+2bLG=o_n|ubZ@U2fm7YTWX@~#JGSL6$ zcCj`#GS{d5_vGZ?XqEosHYEpr8^=E`N&oTH$@X6brevjYg+CNIx!t80VBzwCk%bmY z@q?i8cxtI62g=Rl%7sv_NW`Il60a5}h>$cZv|8-<$7t>LhbX*~pm=*?>pHl@Z}}S% zq@15G=e?)7z298Ayua>{djM^SeiIHn|9jA>U4ewQNKl6~d2OBH%9wx{0zs}7m-h=U z!91(T4ASh3Lsm?fQxFx)(enEYLru&aYA=wgGIP96Jbc6 zG;+=WUaKX_jrAHz8vN6`%C)QFOLmK`Zv_%~Kxh*Qa2uNT*4xKHNMK=^+C-z`t`-jG{nVL(+OvWeq7FtpLz%$Gh{hOX#*4i!7EHqc})8E0OI+IOVxsd`iL z1eeJ~y)lV+Qutuk9j;e!BmW?gJhxEQDCu8C&nlvq@XhU!w=nN>YVZ}G=#3!t{S&Wz zJ-V3uf5(I?$p06wl>ZZ6{hPC-f8*d1##UDD2FCg}(h3a!@e2re5*Y|Vl_I_%49 z%*^0@l@`(31pR4=Y>v|XjfoZ3BqChGgtmJd!$|fVimEzOKuyd0gpF$`q$X)8KuPPO z(@Qg2g7rlCKCwn?P=-^=(R-@I zK>R_#U(BRebTbwD0PSy_vUt;?>5Y7Q2(k9hQDbDY>?AtX!DWnRwAlheXU>Lr;f@pvR844%XOc$Gmx5-PmNHuMJke)Y5FzzKl zQvE<$$&$_O**j2kH|>#ESCvVQ$lRC~?sEQ~uV6p8&oX^~V?Xo=_)}x#c3f<~7d32% z^?;`~wO_r-hIFQfU|p~6sWym03pZQTdZ=c!J~A2O2YwfUZ^QNv2Hu1D<*z+5YzHm2 z@B+K6f>A8YuiX(t_t!&Vt-aQsZc4it(d1f?cXzJpK8xD-KTGk<6W<9Ie&gyP(BD;W z{(AuVM@jx4Z@zzKPSUcN^l%}%iPC`h)-Pm44~RD80_yno1!w+vL~=re#AA7^r0G`D zsGN13V((NkVpuQVKID~$#~~LYBrb8@-Avx6R(?JWPq%vlyscE{1-UAB{M-xVJ4~D# z^F<+RSnDpNmipzE*~!4sydR}I*=l1#ZNAMa!<|GCbMiKGbH8q? z|DNCwE3NjVte0&px@slTB=kS?dgiEL(nDXS`@kX{qp=s)`M5)Qf5lv7*ni2u_F z8-5JX^J~AgM;VB^N*o3ak2y8~2Y zu-|t*2xdHkb2h}6{2j?^5EjU4B&|V>smFkyHSvy!lUdYPxGx-WrX8at-5(%-m>Vbm zs3P{ax!VE%4le#p8T`Ki7k`0;Dufr(A@Y~+s0rz+6do`*kw02opGiR>9~WChFc}JN+!v;Y=Dbofsnmn>frpm5^hhq5Hb$04iOil+Oa!H1~2uOE&?ju zY(@og#v(cFYZtXp#Kz$q?g*Oz~iL9NUd3q3Ef1#k%Do&uF7=^XssTH>6_E z2|+E_F%ox-y-x9d2^gXTmuC3LNAz7Nq&BXlg&jXEXISS}IGkq_^|f%LClq7pXj{g9 z6Q>cWYKZmOAmP)@Ck#Om(}|i_&gS*e(na17Yi%ZzNbIV8t1El4qb$`1Hxog97YG%G z$*Ainjrf5s<|gZ)XRCKrmdyQWBcMk(JQco=*f-kr}fW5>U1*R$Yz+6 zYE~`NOqG-CDPx+DrjpS%QDr1u_$4w@^~0z^A}a9&F{T2b>-RY?DP5f=YJGXa6G*Ee z$P|GF`$^vJKgHg4=WT_kNinz@qM;_V+)7o)SQ46q;?jFvvul+pyw`wHs82xNA=d!qq$Ow-@$L^H{CZc}oYre!nAxNRa{0^3=iz<;vD30L9V_}y_O z)ap24(WQy!#59s~((hCi(=h@4LRlO@AZN6+8A2_|RM!P=A_YySnjkNQHq-_#d*2?^6ZcWe1B65~^`@7mXZ-8u2O z_XF#8f1JZ*FPg(AmiNX{>x!~?-|AxKR5s@v?PBBp!yn&Z>o_bkldXUs>7 z&~UfW^>*De?z?I~CCBG*kRb09*#xHvbD@UBX}N&%*;q-rla^mv@q62xQM<o zLf9!qu7&f}lDS1hb@3jg_ToOpYI<=6sB+1^MqT--MM$;DU9m+Wv=*sn{eqP?vp7Kx zS1TID0;&pZ@O+FpPB)8iIscU;^E2A9C24?MNB%)j19oPSB|~&@-<^0f7$m9m8RldT z5!>p|@T3WK;;tW+PVW|0MUkaF=^`6c?;36}c|W27)&YVM1NUQxx9xQA#^@m$ywjEj zT9KpWLQAMcJD5p zLd(CIAw*&Oxu#l3>K!vSCow5a0Mb^nVi7m^)A=i9#_i}s~bBAZow3*^RJhFGyGpVgc}{TYe=K~8S!y+EXYh}mgSClWd82v$|MoA!f~ z7JD|t3x9Po7}5RBpqkf8O`kD@CClHrw8z7WkNd0k8CY!9ha(BQRB$zjBMGKZaP^%% zX)|AN)tfU(yFqXjM(}fGkt1m`M{pIHBS|_-aP@|RX}7XOpcbMt&JaOveOD0K6&E5} zAQ(qrkVb|=bZ5Uq;^-6JEK7B~!vy%-l%;WXY%Yz^5P4nK%ss<*MEmSD_F z(-D{z>Ej=QsacVdCo|7GlWczXc45_>p)uZR)s5t3l>1oF1|#;nge${4Dp3QxYOGa&Bj&wrfsoWHy8fezN}$unpe$CP88*Kq(#SfXE$DxJ&fYVM(B%A0)J(tV@TA>aganm z7OX+Y;C86H>sKy_Z?b*KEn~?ulMN{Y)yNRT*n?vd2S`wCtGpS<2qf*C}EYZpi42hpU+Ij7^#qHl`w=~ga zHL-W%>bG~lxz1?P4;RC}URa1$!Fo(N7`%O>MeD5g&Dazw|E}EHTbiI(Sj!Q*c~a_) zSzyOmU%VgA@=66wWPI} z&J>q;$51M8SRFKH$I%S|>Q)KofZ)4BH(2X(Ff@V!n_N&xGAN;ldID|O5o19qvxW8@Y1#F2h zz=D_PvO|IN4cQGn8<8r8=@1o*BG+OyNu&a zN=Go;8uK`dSfBh5@(Pii+m2+nWCPc@^-h#yyWcUrRr74YLfU<>BVK~Im)!^&lp9@|mco^mR! z;WaM{;j3@ow`A{wB{?ybIYVx-Mh8BW+qZPc@*fM;tyJ5u*cim(CqWa+))uq43jdUU z6x^74kxo2z?{{5XZ=<#oNz5RVuKo2*oAXTM%jJblXO{;#nRQT1=IgfeqABjsU6@P5N8=LaWp)4 zI->9K?^8z@{h$607gK$ze%RTo(pjTya}aqQt5*3 zxODI`%rJKVhy2M9VN%`=dPspj324MW6?zg|sMw|X-kEP0iUSMh`4x>;PsJ3?7+d8+q;sP+V@b_ow|=t zP>ozcM{b4l(%<&_w?i2|(>;QBt}d*&hHYZustzTEo_PA1viva1_b2K4bxobYhdX;M z{_0QgDTR8E+UC)X(6tRdc`bJvI*=id^g^_is{^sn3VViCExrJ6MC{}L+7`w8{QVES zxWCU(ngs#?xc%ShQTaEt_pj~+btpG1W#muNRU?*l@r)yJ%#1F9c4-9zLF@Pwi43qp z>C6mi#5n@zjBFx7SJ%A@8@y5^c-&I1V1n2PE=mQYxI%D++u*R=T)f&tZ``w9x=g%r_T4AGWLBPdejqRLW;oD0!){_s z-y@Gm1>Q>xMhWxXm6&)D9eGhVh6hgU>0g7NywGR+t{_1iRBBh%vC1EFk>N>M_DE@zs>S%el=^aPJ%<{NzUZ=o#> zi{Zn;lZRz`526F4(2hK)5zsgD%4(yvqnDOAAJ{hY(lt0>ZE2w|j)%VHpLP?3Wk zdebt*GMJ8uellAY>-jZiLl{>qBQ$ZHF|e8yAd2GY4>C0|;tRJVz*KopW>Z(KvoNimxKZtA3k}|E3&$qFP;EF?ARM^ z$-A1G3}Dt3PzJ52B46n2tg5eQ9^IOSNGxJ)%-Nt;GnGt3K5T7>xv7(CQ6H-BP%bOT z@U=sdrTQt(nc|1j3>(P>(WUn`S9OsQO=oCs5{fg=LR`SfRIj-SUmLJ_qDshJUIw+6 zp5)5FLFNC>>>(vvnLLBygj~_z49*zJRXKg|70Su`&Q z(pJ#T{8f>?i2cNVy~OrBESdckw(hQB{Fb&{z5oeedz`?eJxiE;fViNfH*$eB^DveL2L{7cnJ(2XJReY6WN23 z#+eqpR@)`r4HN-+*iipBGDhZeB*L>&984>my;C!Nh*o||J*D|debiZl3kN5b#U~Hc zY4)QQN_CE`sP9D)k%~b`ikNhbFEhZSPG=Ov?3E<@8In_Bq*1#_!lI2t(#(07^y4*; z9Y;6CaJj3;Y42`qVNB%PepV2}oA+!U1JzPQ$S%wbea6==toiklf`t0f_bp zj>8LzqLU8ao;5)*XXv?mML;k@jNWB>uW!LXDr!Y~Z}li96bFF>hj5X(LXX|Q>UepP zI&eux-1vJVUlOBIkvgJyDb4yg(0%1^Aa#^yqEOI%6>l(D#MRv0t|4njeaXy(GXvza z%65LZY4>8fDfV^?-P>No&(KZksowl1*uAYUg#pbsO?}T>>vcrr3b54*g<4wWVmue} zc6mu9JAhdwJB<14x=g6G@ppqK2J{JoCkXU+k;Qx?pmwbUlW+jbVfWS9uTv#Xab=jq z^F~VDo~wnf#R*p%5k%GFmExyAmvn1ORq4*fJJy%`ca>knWsNInWRPqiN=ztMLOs@{p9T-m<0~B(?bNW6SXs9ZJPm_j zp9dcq2Q6v!)zDQ0=vpQP2MlBAEe04QckaqIau*sKIv9q-jDJQs&$~(0UZB@LDJ@bk z8jyMwGL)zk&JUs zC(BGg8~D`z?5ll8Arq`EW!rNUM8d8xC9m~R`CehVTjOEkU14f{0OsEQ^3dxsN9B$+ zJtSha=T*Yoo&EqecS19l$JCbjkiyg!>ST-I&2ZYq)B$eSkeL&C!o;{$)r z0;4m~$rl5=c$2CfOSSJic1e7F;zII;x-T8mF-jP3bT|4tM48WL6PtJJ{4>YLsLb~9 zgJ!l*=KPPthxV*btl77x!>jtr@EYoX7Z%K7W86W2WnpphChD+Rhuc^@&|gj2=ezYw zZ1!$pC4(AA?2M0KQ0v8wZa9OmS>if)54$gB1jv7bxEA5ZAYD>9?sEC zS?P3a4!Ugj-u6wjLNuvj7uGnPxa-y*A8f{1*_Xs#NK)&)c-VP(x58T$FjSnojZGKX zVh&;o*R}fZs))hn`tld#iFOI0(J?KsrQs|h&cGQ0yT{hr>0EU|$AC~If;;D!o567n z(;yXHcCAophc%G#lyJDUH#5=UzUKjaFWCjr>Hy%8Ifm$vH5$xhg}8>_<9@AnW8W(} z*@0nmg96!NJG$o2amr-uLWSbMVutcOSIDX4!&x5=duHSQ1&r8}2z^vC=S1V=q;hxW z3;CnT>2CD2I1KAGet1$&d!ZLjOR2f`vuAB1xyxaD<6KTh_sWus#@0pWlFef3QQULe zhrDr^J>_7&VF&%{o;5Afv^MNRq3a{~v+-d1Q1*f;cCF%8{cL)7RcY5z3a~XTnDE9u z#!IDV)#YfHY}GzHsPBf!?jGtdD%3&`Wo)ZDV-@Uv=$ql_IVWrtE~pX55YI0*uIbCH3;Jq%d1_z z7mp+Z%TkavGawx!AY6mrDx0EVS6p4vtxsnWH5jnQzGI|sGYTu*A?jQBV>hz$ybo_S}V!$NY)7_+DZtEs(6SF(zGh9fgnS;@O634IiH9LnY|AhZVQ8>?!}1;*rRD1h_8aZ?DOlP%=>6aq%?Glt zXfNlVvk+mejWxg7^BTtg`I+Cpnj-!>Cr(bXR-EU98~zf7$}{%^R6vr0D}VY1j`z}& zC}57AOU8&d^+IC}iy@XMlaR72_^S`SlCkRs=p_&9`IRpn5LTKbwY_t5`||2?^GA2L z4^WyYhaZ3egV6v`7y-T^24g-erQl$e*^zKP-fmHlFoYzuw$7Fvp(FG>`s5t;`iye3 z64hEvNeb#B;4+Lfw-eJiay~cxgOzFUg$m60%@X>88D~f>A*k=%61$-8P|eG*0{(cm zAhl(J5uV{O)4kYlDq9Wp(Z>%;N4B0am|a-bN<%tog?TP=GS6cwsY%@zixuYwY$|-rft-? zvD$Tsk)yBKAj8xo*kCX|aGYQ5uDlkL`>6KbLEk89&sZ1#{URZ8-(1j$%!_biRk5m4 zK15Mvib(R@DAvC2#JV3PY)_l3HkCM z4W9@_MH*7;BZ>QvJyw7BGpNucg8&}-_6<{cUd;TAmdT~mKR(Xj#72PBW_w0VFwn*2 zL!ubd1aFgQBo)z($T#2HgCM)HwzqR*{ zPTc|9fkypaoAtTheZ64j?&w!R5AY^2Lv|aU8W~Y}NOhXbtH-S99NZ(yEI%#YFd}cy z9`EdJwg~n~NmHbgpE0yth0+@XD0~RpaKD=xY2jH=j?g>81wt3(yKV+tD@Ut{-y;Q? zmST0F&^5dW_#j}*#eEa$(5Z2Bs{^dn@Wp&EZURn5>ITjd|N-G zZwooiPKUIvApaO``0-7GU=$Dl01@>6Qga23;34t z0Tubf@QIYmbf z-^TA>0hQBw-OKI>5jjk-RoP>odOvU-Ag_`k4YMVfvBInh387rEvIH0XquXJx@{IL2 z`7tGx;??){N;Bs>(zqU70=(f(P*~7#a1mwHBKW|xZu7)4I7#=Oj58o4s08;L21)DP zN9mRs#GQwIo1ERTz_{K=X4nNGVyjBsGEJKe)Qa8m)v_u*_P(@1OVkq<&y(F?m4G zN@gwFF@+IGbC4tkEs>+JQuqaYw!;k)DU6UN$VTXE0U3v}vWyd`EsD2V75Q(R>+991 zCy$j~#1tsYk~pqjWg3a&J&!sN>sz!?SCv)M2P4DzhibiwAzF3nq-D|}W?NO@A=Lqg zVS7_5>Tbk3P2!1UEhNpXt)`>Sg6PTNjDGx@_E@`z)>m%y;mkv5fCBQ~i1gJPkJp-Rkhtb=up|f8Ogty)?r8PKbH*u2gl*}14AU&9xCM#G z%Vr#XWW#2a;X95NkTerk<6h{ch^Flf2yehYwayBws(=2-$*m@7lJVbd(mpx@%fCQw z@%4)En$-G0(oV+6t^;vS*2i=Iwn_|nyI+;vQ}-C4S%g_L9>-I%!I+^i>FC<8p-9;x zc%304ixoLc{9W84Z#I}s`|F&@*qoZ#!eft7?UhmkRv;7jV|@fvO^EfQQBK7ksB;eU zb!PkKCcd(ODOQ?P)D~8Nv=fcblW+h4iQLhF@_3^_c-jb3;rC2br$0dEv^0dAC z_4xTMH@X18ePNu9Y(Fl~sieW-8T!|d@{hb3`dXvX5Q*{ORUDSZ~iHP=&Ve*xyX4ayn?JORqBb}IKW|$c72*Wbt;m67YlNHX$a+`+ z@1Qx+_eNROxqT3)8TW4Y9K;`HX`bqQ79SB(Er~4DKR*A2w0Jq*BF5j4=KZ&QMgIqo z#_%885Z4Rstv6VLnzRJW$;k`(`}`o!KyDG_A(G(Ag!s?a*K~+ATiX}c#0N`mK)49) z>M)hc3H_XpV)eTo;Bv4#q_fnR^Z_$_+TF-48Hmq2DrX>*H)7aH09m0Z2(EIG_ezk-lF}otU{xay1+b#=+F*jK;a>h;MlObr124pVIZSC|six3V(OH?;f< zP0rDs5SJHeCsfufHR0P<%`jK)ruR#g=9({<>H=CTwWpA* z{ax-(jO3G+UOiPbJkE#aQpIwrjEEqPy9vtMB3Wj&LYvJ{KH~%XM<9_1BSHql9k+qN zaRwyf;gQAFz%@@A83$cB-_h|oTm`Q6p8u@$)ZZ#hJN>m;{D8l!phx{bZ>O!}e<`0= z{m&X}eytIJzD`Pf@!hWijD?UA4xUAW{7Ly`)*E9cj-;g|^qU)c{kqcs+vDJ+Lm` z7q2CZi8M(nSK+xUR*&c%(HIiJ76lC*S<-KFTM<4IV$=*kaZiED?mr+rYzi1aaUr-H zL}1)memx4Dy?lD5hpHd7)bq&{+N0B?g3iA#qf|-1g*nwSst_}{^u;aMGh#-x?u^}F zC5^dQsuu~6ak;3R2AbiTN1}f%&xhu>GI7Db58u6sX*6Z07{HX^!6Xo{V#xeC&ep%w zT-yFq4Hmr2SG?lRE|AdM#Rt;KoD$v3!+wlPR3^Iz7wytHybxrCFU_C@o9`RU*x|+* z?HwZ|9PbDi`$#rvN!2AibVi*&yX2>j)D-jDh}H^@Iat(B!6kwoFW4WX(# zsMM0JBkciheEH_wgVY--W1F!ow zpFw>>_x_kfE;S)si(N&Ts|GU|L%L)~8=eDQfwiKCzNNlx5Q>(4OWMp$^L$zNq}|%x zXGfE7^u2Wf<%${jbiK8r{^x-_y)M-yDu#%P_URdOpIFgX=(xzTxMj88q`Vcj6{MfA z+xJ4?Rb?CHcH1zI(e!yaZGeJhJ;sx&Hj}WJk8O92n_6|sddEidk4aqc3Z@JES(bZ@ zO|(wxlsVTCbw}xZRb(;l?PFU`+_mwTY9dLJB-(j5-_DDn_sKl2f>65-aDj+wN|C6F z6FucooG-tM-^O`xUVIFfqDL0p06FBEh4fOD2kWBjV)O^`yhZ5O1VyCM$2Qgk75KfQ zRuSs=)ZQ@OfkL7-$ur5--2il}xrK7|4*)1A3F>|cKAms0Wzwo9^|F{JCDUjORDsY1 z94 zWZujvVZ0{l&_Syc*+fTPGd+Xu8Kd~z=X@>jRVt@BRBOhAx%6=1j|<~2Hb?K#10X8~ z`|f$&63pg3@{K^NkGP0W+SW2Zwbv%H zwjmnFF3kxZpSwoprW;)(aH-Olu7Lw9;{|E<0U;P}o?56W#x6K{??V8Js9F!Zm+b>8 zrFlQ!R-eZws@}dl$nl;!(^mfiyms^Dg`hWjm$Criaz<@HJ>HdkRQqj)X8sgY*)?X0 z#SRE#BTqF)1lDmy2vsKI3Q<0*Ku0UTOb{7r*_>61hY{H^!Ab~SR{~Lr|;94+5B5Sk#S3+#_GOAo*)uKvr1ef^gxg51AdqJsbZ#jEdNXl$i#U}gN*kri|> z{==31v+ej7JyLXXHu#6?jiR>gJRLH(O?$9WP*m^G3%XTL{}2$uJnpx|J9t07uXuTj z1>78^%v=iX4w>RVRM(LZ#XbOhkoPz&-e1hMQ8`~ZWtGAM+x&d)t2`+&Z&&9Jzj4)WZ z)L}d+X#)~219}U1e8!_Pky{5yf#=(vpz#Nh1YmCf9m+_ZX1mLJNH(u4da!U{bY>1GqmWf z`7_(q+AvUVk>^FTST4O5J{_^-IBmBZjEe@XC&_P6RRrIC&!N8w-|>l~*{8|Tyn>t^ zrhlR|0uh$v%oOkl*6;}K7=oyd=wwAyBpYk3S~4w3UUMXmf(Et*a;jOp@&3tra)}P| zI{(mN0RA0X{+kN@{~j%W6QBRxizwO82k)(EIlok${Q)N6VUI8n5a$mJDZrQ8>Yh$4 zDZXjae^s=nd%pvB67%(n<;8C)0IGi~BaQXmWGQ2r6#$J5!VY;SRX@>^Uqz}>gC}+> z$S5@sLODpqxHoCnnn?n+fsm#&{a!7eJ}gh*#O#CGCx=?dhA6nVB2(1}iyHmKH@&db z@R{<~tDL!$E;HD5e^?voOU{Z)2?#X#(`}U=Y=c?H)t^I$GH>6(~Ps*Hqiq%?9Ar?kZC3B zK<^W;*Pq9+*gHP!`PcTf0sd}-dH;WoJ*Zt(2RSut$?J|=5MQz2`TO!H=wl_>j` zQbqJ#@OqiaO>nMqg-Qk|ispW_@p~Fc@JpAEnM1LqCG_-A;%e2hr14z1&3VyPB8J4O zJ=7QuozPd6gtD}%)1s%cbqg~WZ6i8j%jB^rAe(c8YaEfx7>>s8PV9S7;|m^TixwRl z>+srg)9GoLMGtGm1zEQU#W-si&Gg=YvsoC*Ee+c17LN(&D$`2dr3zIp12L@zcK34b zn{0DRAuj}*MyW8NCaG}91XP0TBh2`^^lrt9^=^vw0k!h|&I|>#BL;Fb{dVQ)OpVji z))~(yqjifL@A!5F`M$X+hRVUIq4r1#KpHwZ7zbtMb1H63nEtNokHz`^hqL*!WrIXj zk%Tg$__emq6jrKeM2%iQH^D+oq6Ee_|ixlUX`6db20O*54eU zo@)iGEEIw+3+82iNkas>X4I{vd$5V0Li15-nSB4y@Cz)(U^DGuI` zP&pjg-f{sgn z)jG^El#AyNb(GOJ9EE1o4MOqK$XK2|`t;oBiKJR*$(6w=HCU|Y%jpv5>R}VvO+uBj zSfuOKSgrS+tLK@71YPK;ma|Zsqg&|?pY`bXyqU!PUlI5~D^1peOEfl|VZNeOv&&fk zi=553#j~@I`EGS)<}x9@6D&oN>7a>`coZN+I;-1<(qq08GnCvF!~;3wuRboS8)4^f}9@t#2(Qo zFHfbvDRjnXRw_Ye@)C;aeReLxWD3FNN4u`8+dBNb_jVU9<0;!Cev2q?G5Ls;M{+?n zGSb66B)@Q~1I&FQ?Tkc%L8t-YI}%mKyWb4!8>C^}78J6dwooh?a8~R$BVSgV9nu}s zavl$d0vF1XQowsm!kj4~-ur=o=^S_jsQ*xpjQeVjMTwk3kf;nj_>;>xF|FH7eyQ=1?Wtn(unR?(ocr zap?kdkAo958Eww1B<=OgAK0IMZ+Wu=e@c$*=A#-k)QwJLrFkB2I8IMY#pLLA1FZ~2 zLxPk;X!RB9ac6sW8S>iQO=L%PR}{kt|EJuxW^2BC~$9 zKgN}GMlb#J`1Oq|)GcQ5?+xw3E8>nP_TThFnK5GT$4C|;W2t=y=K1_NJ#O14JFKE<7T$+AS zF~jX&44nk3V#ZOvhbyXqA09Q9Fr$Z^N5h9Zh&Ht2BlrZ6V9Ezy zwjhR07IlO$+Bw}eTVN7j8m5J=sZQ$2AZHq~QS!&E@fel5aHwiz?4H^H=+y85Rtiy3 znC>4K%*q&4{`y~ZNB#<_{JZ`Q*8drUhJOiI{zjI7?Dq@*kiPsoY+a~&>WZ|C^2x24 zJS5OmYc)X#WWcCFXG1QH)$xsfhK*j*00<OoVZ4B9sKeIvu$#9^QXmVBJaj zG`?xZATE%!K^oKJt#EtY_6ORU&*Z5$<1~?ad@bxFyU)3I_q*rwmh1J2ZI1U1!ngOE zWqg)BEk=*qFSa@dlad|oX{^=2w_m63XDvJ2y#e3s{9?Aick%*R1HgCV14{w6;%_eT zQTG&LUAp@-#yeX3GOq8AJUd=}0Bpf(k$J)QLSEtm@$N@u-R>13u5W&t@@oxFlYIC; zcPHLZZgo@cE_ZxJ1#U~U423L{e8}`&1GOOZH~|O;S9QLn5}1laYUwCi8A~-<39Cv4 z&y>jg2qo1_HUP0p&>yAgm!hm{kWqNrN-RtzYq2x5Ve0P@!AN%`38gly%ch56o;O9g zbMJ3>m$AB%Y&U&pi#DjLtnAA9Hndnlvks!Dzv3~?2ZY4=76L9k#-1s=3N6W9g8^K7 z7#g)+XHNOS5Q5>~x{C~f#i4t1jH^r)1hD3?_me20F8fgPvemmNPK8QxvHprM46dZj z0*>Bk_(%zzw`T{7o`HCarRZ!dTY#o870E#&Kj|hlF1Zn?uJo=|?O`>cY_P_}Ct$|< z%V`>?>*NqeR!(okBpj1rUvgw#>49~f06)=$aBZ#O9Ym{a{`=FVG>+ojo&d&bGW(A* z?Qo<%!uf%c{k+}^15cl@fj!q-DWtGFbj!#=iZRr5iDb_eDv)(KtB0-rs04F42%R~u zp14n-nMMpz7_&pMNQ{`2r%BN>e7s{+-0kR@TfAtj8w@8(BEz*T1K6m!JxHkz}N5W3-1n@ zJKubG1n+=p)XbxtoL#? z#EIB!kjazT0K-XG+gKf1;hTtX`T#%$(f1}*wygFi=|F+pXak?=ar;moLhN|E(EGqz zQ2I=~{Pc~*XG@AG)YbFNnv$}L=OngN+<~8@q`np*Dp!_Nq=jd)<0R!Xt`czE7bQWH z-Gbfi;O2Xz=sPE+>oaPO$R8w`OTex-#pj1*N3Dr8B+}a*v;0Oe7zmnUM zx;sX)V%j1XP;4B93d!8}1MooZviuZVyp#g>?aL8lgShLaEi(aq?HdO4LhRFh3Gz~! z1ABcDWbjxhKWliPaJlE8jSnGm46)E_$fJUdKhIYVnq`;WgOVsr0xm4k)G}|e*qRWz zZf1}`?{cb!h~rT_;^lZwncicUK;?!iQ|o{2C@M0(GO^71Bxc0h~9!ZR4SsL+mBxNT{8F}r0s|4TzM=2j$|U zHU=`ynhTzX3-c*IX%6#QIZc^ey+qG-0h`nzjs!jPL}cwnjG8ywkv8mOg~7vPz8%UD zLq$jpcFH2gs!dp1gv}?q$pxEKi%}Vv@ncKI_d9fhKEGjei4#hRh^F1=4-teD38U^8 zWP+8yzT%eR?nie?U@~>iY`Ag63Bxk`iCozsNxUsugFpgVxd5aNOl}=WVVSt#>~_Xc z1LhgjHn-KkwZ$_X8#8kv9|=_ttvEf(9A|QxUOabAb%di#^G=$3ma9&A+bVxv&==^49|gV(;Bw49tJaSR64?hns~7wjNapDRD3)eUC+cD z0DW%x(#XDH zM(_%&tL{d=;e)ih4k2PCDU=e&|7|(!1ccBd&IhC`j5#%L#G`zo)jq~*BUkNeqeYbd zN-op>YM<%tYnMtt7EIEXTf2-cmpoEcE#j3$mYst%n=Z*lW82PJoPb6TH~;dnXV!-} zXUzI>*9{@ZSHlBC3ts-%F>qf=&Uw%4f?|BtCx)+do$JOud;0}jA zll8&MYXWd5M_hIMIUpgzTlr@&~QQWU6lU7HQDO-64Gm$k^V>_uGOk9;C28`d zjEx&y9L(+&VKUx^+(5V`3grDk0@>`4loNe>rky3;wSsl3w#372rQY|?aDgvsLCcJNE+Y2PJ30xEWR9p}EeR|3ti2$;vXq9(Gnne5%5g(!Ter$oX0+O9&P&KO z_gGzmZFYn@@ys&>2N>asYnb7IiqW*e!3kX<|7FSNnrnuo@P2WEnUhdkct*Ui6n{c~ zv@f1v{=3E%2Gu)0PhUk=-LZ|T`SsECYFX`~wFgLCM(Kx4o)xmMi*A^*?IY=e7+=~9 z%P72nra5@B^S-%9=Y2OSqtGuC*&RNAfF3#X%NAwmH*z>v8o+#*FiLvj;DJD3 zCqI2%8W_}ElFp!k?zyC)AiNz>jCCj;d&7jMOqt`%w1loM?rwk*L*5`@7sVC9UeQ_6 zupUk%g;Y}h4uwl3VhxKCh&mjC*F!IkowsxtQq)mbr5;l6qM-Kbp1@WF0>Dc;_5}%O zbGDqxL>4D|0U#2Xl;EcP8HITa#!LK*Gmn7pT*l2E7)HyJtYXSiec9Zo2?mabcgs)mF^Y5%ju8CnQcmlhJX0u+N z3hM!idlsbt7t|OV&Z%po&@2zNE;<XtocQ2{J3VpMQzEOFfL?@Jo_nH z^eyVDuv(g|=RrP`)Ce)`+^NYF>2t?2#ul0=t>uf<8L7p>a_{N;4(ry#jw4x)XY%_g z9z(DdP@0QRPP3arws?2`;(h3Q(24;>Myb};2R{T3ThUCr>NLwBmzg2X#pnxs85K4C zj>g+X7xyxj-x0I-g96P9h^_P({i%a5KiRpJl57gMva{vA(OG_?#Lc`ZCjhlk+9V#B z*&O53N8V^uuA{rh&QF5jOH6r!R?l0fk0;vDYkiC_#1@6{f6)f@5E6J$^fhOei5FnZ zcPDp+c}fceKx7K$KKv5TB+&(Ur5A2O`nKqxf=~dL`WoKTZghj08{Xj*l#9fU(Is#o z^m74F%A+IVfzEh@SrVTej_VSrp(ltbK;1t^KG3m6atr#|u3LCyRAYx2co*?jImMX2 zVS@zo9zc~olG$JFSYi$u-FD zf@86e6}KsWqq(R!D~R_U4rQ_mqXcTUXM)}F=;NoUO^)t09zb-hAz_p>k|uee;4I&0 z4@>VHJDQd@JTc`W3x636XC(gmjz4oqcK-*e^BYIqRxHhBbLn*dt1Mk%wi}<_-1oeF z$*tOeT|Inn;}{uhRmj1>I$J`;l&x=NmJ};1N!f}-Bkm2uHWX+nReMBLL%^mRtR{Jm+Q13?Iv41?1J_rYDxa5S3zE7Pps3IWm#e{hmJWvKxm$p~I`Ws)at|3~_ zgH_|xu8HfBNPq``quy0Cj4!Y4!E-onQ9@X#sh{dmKZ$LH8}s`GUE)9V?a$J~oN7b%6(0nx-h zNRn0}RZwG~1B}+a27lMMqYsCHu*xA{7@~TQ8BXVU2XlFQr)`g4MS#-5YcxVmSj*Hb zjO?gNSn;-XRVcHU*HKViu@6L87qXaIaXy6*+S4FdrvZ6WLk^N8skdKyZ}ycuU}SLh z)*h5Lg%pVq=`m3V(*Wg9(BhH3ri8#BVGr7cdk)5w!BaRuu}LP^a@kWj`SeoUAi-x{^3X9U z4_^G#{R}G9Q5=0UTLb=6%S!cPpwLvk_|&CKRxDV{QZffqp2iD8J^DT%-f5+)mO3}7IDR8@!0ye`Ane%)7x9(O}33eAItA_3JU!uQ9aW|U}+ zvQimHk8HM+6amhMcCe0O$nL)@x+I@F{=bo-6X%BPf^$bzF zOqEuvZ%Az7y0qLJ-YCc5nMQD-xjs!G!&#uush3^dR{rpBfSQ;+_*wUSf=PUMiuitH zAD~mUxH+~!)VV+XsKNWPaCOH)3*F17**kZn(CyWuqbv z9+1M?_U?DV*$$ni%whCy$4|8gYzxTP>dPv$#4JTR;(IrTzrv%yc}ZaK5>4df!|2Kh zb`^Xy+r#QA-{KZbn9>XA9D^&W6A~w30!Oa8u?IcKsNQT5b#%-T?{>~i-g>Z`Tf4S< zXTywWJr%Mb5D#Qy4tU}bPPP2_=_GP-JfmoQ60rXLQ-Z>W=%gEI(^t;)lQ{iT0NZzc zCImvj6{Ib}r4uELPx(|;*76`ls_Ms*K-H=;46|Y?Xr$W-JTF|TPOSK8e16;%OXjpLkkJ4T+ zB7esL6g!Z>bv9;nyDau=+!u(hYY6$`cibmMz{{*FyxB2V(3d5@15ui$*K1m!n4Pu$ z$>_e`=-hzEybK&sJWf9X7sO+;YeJ~i*kW>fFqk`#y#;AHLg078q@CPeH@|O?54g}o z67dm01qhh6?eK*HG>BecmG^GJPetCO3?|sQn9!J<7#1HOoxCKThfZzpZ zx8@f|yW@ZbadG-D`k?qkSUpx3ar&bpAm8y1Lngc3ai8w&(8{CglIWK@GfbbEc62tD zzg6#)b8XP>pTmIb=R|_39rpsP-N4}D-tA}ja81nr;Nt4D*p9z71BltRXZZx4?xNo3 z1Qc3%e|~uefRnwuL57p9pJL1L4Gy`!zf&KwpNTnM*(Jc>z1e>SNG71%2f?5na}yW9 zujjBWmXd59CI)7`Qh6?$ZLlED4`?dH8bv|$N&}p4a73(fbiHrNj;>O4ES0uMZaN2h zEXZARmrSs8Y#bW1NT?EG&9{7PXfi-)S1ZM8>y+q=6l;9jyF}#bH1WS+wO)X!%){!1e>H6 z4|EzzWNT`*WvVi^-eel78kS?k4n17SQ1MX{FjS~-R)5o&H}DI5jf1>bl*dTNA(7_T zH`RpJ^>3c8sjQ{AhSe5Q&LARH&TSS?)v3d%XNFvDKwk~rpG|P4qQGD@g)?bv;mI2& zX-KZ8PtGzrNY==%DrI6*(vhn`4neXowu+#fS4=UTOvV%kKd3X`jK+YlP6Q8)E2|_G z=Q2C0Y&jyWFHC&OSZVNQW)r|t9<03J98x(u_C8dZ-O?pHr{M194-d zP-;1YRk2b=P*WLJD;+(OvR#~PcgQn}mI2sglHd4CkU!iF0oc7{_K)y7#a_2{C6|No z`n^k)8w8(9Js`O5-Ce^EmELRgm+M@|o^IZR$}@#|(rIr* zG!ol7!|gk&!LilD93<)xTMZQDMdUjr%NRNzQ@jk#x}o05&G7oY-D`sYv*7TzPBs}H26rfHNHLPCtW;9?Or9Ql-_Q@RYX{J{!G>1 zK!CePwcV}`jAvo9G)IotWOhaBmawV6cT%GB1PNDJ&qc&;?dgdEW+8uX{zl`luH7R& zoY~TZcEo;{$8^$T~c#eCHM<-mAKZ)g}J6r1|lE!@hnp zse0k6%wGIe<$^!$41}M{M?l3TKIJgop4zRRYV9{|OV?Ot)pOXn_#2W9^$LH$xk8S9 zeL~K*(sFhQ@sEKrn(2)%$(em*o?P0FS&4IANGSkhuZjb}3EKQ?b9eFV5vzg(w#&da zSGV-9ez@BR6W4K+<&n>%(>Go+Bj-xP8>TND)L4*P41R|V{gD>}Uq(x@>L8^DMlcKx zV3@*L=@m2k1?&MO2Q-}ow}vkFa4rzh;^0$ak+1pDuJ`$G0bxVo?8UqeYUuc8&j;6u z9C3?mru9qEkGS^r=%=IDzOfOM^h;fY938krJh8csORl_On|Kwl?=hti8%%LO$sKb< zIv-F3R_nJ{Xa5xSh2Ab)gpBXLxc@}^gR=x8sBejY0{{g7b`tXcz*+uEZWD{xIv5)N z@%ta+9%T(2jU8P6&U$AlYX1?g^7mxscmAO#87cm%r&fqLoIlO--5ww;9THi+B^cU>@`G22|x!=%C)a`EOdMShRluG3&`YWcDOAIkQ_^l|a z&Bs9n#UuDes%9Yi6Mg&IH^vn(+}Abk9d$`vrgN<*vrRPE+$QDNTet<7mk0vZl_X9! zL&?JM)A0I@Sin%@E9S$T&zyOoH(u;}@^NtP>2}25f+)98Jx*;hqNp7dHWDR@G@&gi zpM^2g^&dlXYp_E6bI&A6x=c)|bGz?Vgrqi`c=t5YpEc`Ze@e@0DG8TV{oRD|)>3>qWn#BwbxA;ZQ4xU>0en4oQcQC^4z?FEUz%B$&ar z2*g9;C`@OS+GkbUzXWlJazz{YB>Wn~QR$2boZfI1H^Bq(l1gk+>k2JP2cyO$czKQWe17?HJqY=2ikl%vftfXxHxg1g((K-2J^;zNf5Fb9? zuWj`raV9f86P=FFnT*FePnSOqQF>UGtcl~AYXkk+lc|xZE9eTIjPaeL2(A)oF%X>> zk)au3Fhb{b){%BWo;8$4nG>fqQ@9e3eyU5IV67UjnBRQI_`2%U-YFv*w03#j)&TJ-v3w&InY_XrjxXFVu5=Gq&wcVpb$HieNVzPP^A;)#U3WGnA-FK7@kX~ z@=cDRY=$$a)&ly}GIyHmS}qv+@YZK6N^|SDO6e-j3Sw{dxD4&BZv#ENo3+!J4WmF$ zU2Rei(h_4LccA9S^((y*5fC-5R=ep|jX4b+3Udtn1NbmID;RkP$%0 zCb3ae1#}VE<^|>&_e3Ju@V@8_b+`Q^e8Ktz0@OZ#j>(`ywU-Y2Wo@M2jyd=rtSxQ( z%O%1@BCKT!&tVZfF4fhfX0(kP30@VF4 z;)Wk|RFpI{^+xR^x4Pou17=KrwAx=oM*$Lxv}bH&Fh1K)Wo516@pgNG$@SF}Ga)OG z8)yy3Mu$*57z$vH_wa@L#~6u>@`=0+gVxQ-o~0Vh=&GDaF1|qu_C>obSTLk26KvSc z9#0lY+SLsWs-U}Rs?;|&qXot_@*1=Ig=!(F)B01hB128W^{MYqJ{yv8k1aeedURI3 zVU90)Ec)oE=MC0I1+94unxuMcDlZT4JZmZ}NOjFAQanU*e zF{-~;$7L@_T120}4pM9sfQml)<;#5ARa=L2L&7Uh_GKA=8{vWEyG;fG;{~Jj;_PPCY1|gi zY9~ID#15aUaPSyFaF7>zB8aZtfq0rej~1TbUDu{F(~lwo8UjW+`tD)4)-NFW3}cY1 z2J%D9!H=KYx&9%rVhbFV{B**TXn6S9;39D?YT!koKx5vrYZnQ*^g>sj0-vOmmr>lh6NmqR-W z#DVvjqC<(_Ly;$wbO2=tf%HEVM?fd1!KLzA7+rx+x$~UEYteY1RJ^EOI_G;klsNjp zJL?)=KyQ!H-y3~`25he=48Yz4+1?|$-u;cAP|7c`npRzPr=?;TXNXJ^*rd7a?@ll> zg^5X+a-f*1HPjZv-{^bBmRFR`nA_+z7(Pg0}m3eQ_mUP6wD5Y0EwRq&%f7j znlDo^PEMiTpt;`|`S-frfW72L+73ZVSA=-1q_J-M*lu}ld*1IKH(vuh)vEI0VhOXY zQ0?Geq18rHJ9_PWKhnz}$blu)wxs8}vcn+#3Yp=-gk45#osG)`M50JAZz2l9<&#E^ z3#wJDP2;XhEIazHPMrV1-k;0b{+<*vHy|hIf5siGr5WU}UyCGuYvSZU74Q1NMp|H1 zeR@mGa7>@d_{#XLmpfj8_%hX!8k{|qJ$H>qIgy==TBWF9sD=)o2~|6nc@{&ZQ+y4* ziNr|ODJPfVl2!1w5|hNw4JYkkxyYpMIXlN8ekTdqppa=}(0lh(yvTtr5R0+DHTMnjg^<4kfIU4uzynEnrq1m20J)oDdasl|8E`Eg%K;ZAO> zn?ygHI5RGA@Tx|Qg>14)M z$pse4Wl~;#aRFrD-!;PH{vKU+*1sv-{vQ(Tzt-{_I+?qeJGqP7nArZ;WNngMyG%bH ze5N!uG%4*DL;)oyzTVq2KCuyaqfugzSeCXGFfF5P^(S`39N{3L-andV>T~n+R#$N* zr!1cS6eU1l;bN*iGT1T5nt2?~*SBNz1}|#fFSq;x5*S^rtlz?bl%1Fd!NjM=ks^@} zCE)04D`4k^10_J4C=og4M0)4RBT2;w?mUnHF>TEJ86WMQ46@61@O7#&QeEC8Z3;#+ zvrdeXC{bU1jE0B^ZLS0OO#Yo?vW1<<&9!ZUh(0lC_DFZMH0a>$UQvAGUu=I5WG4qW-d4+`qK#DgJ-(^?&M%{LR<@7|)2D`K7LI53K~;tPg?L zK=2`$ULKJs_=JCdP*EL|T3xeFGxR4FZTdehgNRw7!yVG~Rhi?-^Nx%4_i@T^piACH zHGBDi%5cVTD8Uz9b7Q!41?O0*&}qr1;=!-cb9Yv5%Sp3^C&2^A9Hj8ONuf%0pTvw$ zDudANIJus2^4z#^U_eOfJZt-Yvnm$jnh;y-$*ox6o?rWKaw&ss6k=AwM{q$^q7s$k zy=2aGMR?0Hmb+!vVAFLw!d_?Po&{E=9Nc6O_j27uvXL0ZS)(zUGT7f8=8Y z`05AC0$aRAedRsK)3v7mq$aA$cquKhpQKv0CsJw0GD3Y_~;!5`Qn{XQE z{&ES(heT^ASA0ukNPp5di}aJq3$~yG5>x&bG??{Nq^m7uLvC*_k#U#^VcI15?*+(# z9@Oi1Z^*!im-~OHJwjg8IvqsSk&|hz$?7lNHwS06>~8P2JP^|WMQNtJ;GWJMV|LBll62*1RZ^DjjC{6WLb_B= znxUjwFV;^b9!G5L!oE?ro8!Xz1^IoMttBjJ{BKVkV_tbJp+tzC}o z*=O6fZQEztwr$(CZQHhO+qP}pud2KH>D#EwU+Z0eXEJ9pl8li~ttf|n30h>XxQf&b zm7$sE6jegTmcTO|B*Gk2=VEums|(d5@qGP@9`~YLGZqWiO*Dsj*0f?|r+UPTsCo5O z2W4WGHT}IDV=u0_^5YdBQzQ)t|FJCO>RKuKU8J)jOSLfawPfajPKCz9fn1Vl31MG$ zWAILUb#$V(t}r-8+#`xrT6!%**;) zuj5W=_M!3hxw<~ctmVE*@-BBzJ5wv1zFDgQU9z_%Do(O(#uED+do{4PbH*Z{4XD15LrDxGI=YDD*5Oi;}Fbb|X@s84qCR`iwXn6rVZf zjW(ao#Q&7cjovX735N+{$VJ{Y97CwvCY4GddAuM1)d+$x+K_UuGC*yn4 zy_@3ub44Rg{Av=ug^`8}P5`RN_`ze=n2m5D7ttm2ng3~T4^cQJwS0Os%#HlQZN%g4 z9_GxaAlzKu_=NWN6RFT$W=^U7V#l;NsR?yXhSSiyGF*+xpQ`X}f+MpBw;Op#RZ<+UvSR(VONk=i$3 zSdD2^w!B&=Qqm0XLyaI~p3|)dR`{4N8M~gf)H3P6v|iNNm$_8~hL8LH<&)@2ItT&W z2hqWJqIsO{!T$37`gVoX3uB#97kGp~wJ08_45ig%I~B_exk6pZc*zmKs<$8W?s;j8 zZi);dof$nMPC8w9^eRrmPa>@Y%s(-5$9aZ(`KZ=`l~zC_V7C&(k4^%MULSRg zFJK*$%{ckQPu}_XBzp?T6GEczu!iX=C? ztbPUxb>t`BM9YyUrpmT5rIjFlv_2oBh&6uDEhX?X zl{>m0J@uB1S!>gVDaIXDnP8*}m6p5ag4?L|#pg{NH1BZEk#sWNv0dBcw(_g6UK&%a z5ZWjy9X*0?khZV*gP{&gjsMR9353 z@4r*m*{|!24*p6N)cjJN_HQNq2a-->Db!Sr$~>Zkr;3Agh^93id@KdMvB7Q{D@@<#{=tPFfY%lALl4~1;U z*Gte7Z}M7rMlM;~?_RfLUQAc9y`d*k++fiv>f@eyM5BROKSB$jCqc6916JF***w2@Zf3rqOfV40#giLO!MU&!Z8Gr zK{p<)q{0-}rm;R=j*73e9Lr!AP@r@N(omdCc*l0?DkyM}!8yBk=VNqS7m>y5g_hc8 z5`-Z zjX=Myxnz2Svwu;M4FkOj=azw>^yvl@nuaC?ibS;nQkh&Md{6wCfq+Z;y zhHal8*cc=#V*tie#UAp=2|GIOF|XeEjbW=B2m%1=*?RJI493BC3#OYYO3Hxh#!&^) zJVOvd+Q4D-*>ES;{dsV~<&Wek&;bTxa>ouF0Rx`f|GhVj87LqC_X7l{AY!bV|3I+n zg`LSoA^iI2C>%1cSEn!^wyRe|!0QN?tgUBhM8f_C8E=Ds)h&Do8~GW2!8qoM7amWB z5<0v?AT8;idH^v!U-PS00J%~=)uwE0rYx=lX`fU4{zDrS@e|}^a3JY5Vdq2 zK`U8IT>8^q6Ay#bJ?@k^KV^jAaY0THeD3G(X#a-weRk`wHzN=1pS>IZjoizB7kX4| z>@AG!<(;gp|0W>tADYoxs;ZQW_j@M5NuWf*O<}a{Qi$_|gQ|;v0${nMS`e{Tr&$^r z1ievYh`3$>KQX^y53;1`$%%*W>DpXox?VONZZ1DRz1{%-U}NHomj>O+LDr(^a`!R@ z=l%p)Y|o%4!)%OvCW?@&h|HZ_*NI9_()G~BAh8Ca9O61_GVC=#mlc{ZB(mt>(7jew zil9eWl?|5U?;y7ibdcjOIVayf`dXOvh~(OIi=DULGB1$w-yn;#cYgAb=V_47IPl%I zPASQl)T15^>BgENW_5?fOQPpVHcCJ@t&hzp&hNdA4YQ$=YhvGcvb3Iedw8r5Fa755 zAfS~;WIgybgWfBH z$K;goofV6}IRlXu`Z8Z_^Ojz0HK8CJ$_b!N*V*-Ck4~{7#IX2X7QeT|G-0s%{^RJA zwH+bD$|(SvD)h%WnhW;9k&BZa--zFNbUibz3exrDFwxdURsSbaM-{K<5}`JfVy%eY z5WUp*^g8C0C;my;@zS_mDTOY-VH=RE@D+%DiDN3}*3~p;7iW#ajhIVl2)2&FF!f)w z_EuI4NvHmbIOP9RrTss$`~Mf<^xu5uUk4ig_Vc&D|LQYJ8VVcAaNmZQkmzZxK${xk z5`bZ`T|Ms=w}G*nNHHY}A~tpchz zJDpRiJQyCaq`DL2lIqA0x&tdsKJ*A<>6AV6xfsWx1+bDYKxHf$Rg-fsIYRou_-B%1 zw>NT;-`e(oqS+GhxZ`8%H2JF2*jS)4h1VQ|(A~4C{q2XKg=+VBP?-toa20G>TrXc2 zAQ6tugKN1~>c+iSE!(way`7^70bw*=bRZmNZgZA32kN<_HS7WrE5*qyPQWv_NQ04A z2!c_~qib;kML?TdOt6?Nd1@>$qPzwiT(hZ+Q*#6LKy>lI&6U75Dwv>lTE-l{u--~! zWKV&Hwk>HhNYQOF0d0ejRI_gQv70u_Tdh)MV7V!pg!oN)oyS^bY9|^39H&^IXV~%| zI$g|p?XZ6#nB}+(HD7?bXs;Th!M%WAF*z$bOn^a&=gT3@h-k{u2b!^Bu-HjjbS6LZ zkNIf zPpoyl(jobG_|G(61ZSJ=IJJrlf0)iVgoeZ3=7q=H)`d%`CfdG1k?vM8qiay$#%268b|Ls)( znL8ntV_Pd~7?Y6H57Z@=J4*8A$M47Kd(6O{atnTyNo0{jpwOv8i%nS6!>9g(n1;(> zL+1!}#_Tr#nz-F&ngRl>v&&eo7=8k!kXme4Y;pt<)nlt53w7cuNGO8p_~lZlK8hni zBH_Ih(j5q|88aJk_YIU)rFI&)Go~PVKUhLNM}8ctmU*MXFSWoncJ?R_IbbMCP1b|o zla%V<(-Un^rpP$Uh!aJhK@fcEmEdWSc!J`#T&jJcHA%8DNkWgSYm@7pYqMu9W)nx zxke^>K~XtRQ|WK92(=YY3I0mg-M<3vnkM`VZP%qOQV zf*3=N>J|FRMY^Tl(v8LL#EGwK1z+yZvkTD7BKOUriW5s?G(qZ3zY0l?>Xs7XzR+n2(!O&|%2xbj z01hncKu7=PSeDscr^VjkRDC7Jbr_v5a*zq;Ne4pX8utvJ#GiQ4bvbh;t$IU(niI0P zi}L;LPR796o&4&%sy3pn=Jn_JIpUp3X{L)_-8|*V0B>u?AhsT=OQ6g?mBNqiggx5Y zeq1h-|Ag{yMu*n&Zx8q@rm+806!U)wgc<)Wn8;v?Abo>yR;q2T1Mrs{KCb&-7`yG1XOC{Z@ue90;GsL|2Gi%H^k zIvi)(OutRDqW(PG;Q9ch_D}H~(peG2peHONCv>X;I-qyj>;q~t%QDjC^o5WxsM5`a z#6W2>)|%>${n5&0UAG&U6Z5m1P>$+#!Ca!VZu-P4-_9xH=ngLoFSqa(05PZc%*~YI z?9@1DcT;Jb^Y3-PBZ92reD>{`CZhM9d1RNYw?>cMF z$S&3gu2uVZul|tHVurRdN4%_8wF=KX3C#ZyDDW|_eM0szxx9lx8 zNnBL_H4G=^=$Bx*n(1qW`Iz%H3m~s@ls>RT;L&qy(27Iz#n_ov7CgPTrOqX8TNQ(C?iWE?lp;nF~V6ijW>YsJkmpfeXlK z1+0&Wq#eBR1DUyp)CHvAw<}_>R|JzcY-yC|1L#apgp1$Xg*W?gt3?B=orqJ=jeuR4dVH5xtvrmgQ^o|Iw@ zH%gjCl6KtDki^%8j}3ALz1T)4i#gK7A^wY~o)PWLtm9wzxefH+-)X-8Gev>_sWT;P zZ{ue356113^ly5kAelEzAvk1UIk|lZruEcTgaZ&KA;&yDonR30U~=-IUX3$hL{uJM zSR+f&d_Qn{X@)Kr>zNhCm*T$@Zl`6%38Fm_Hpo_uM*6A)xcvu{Z*x! z+4zcSJiS>jncLhArDhaa&gYG^1IYDyN`_LeLjeG)7<-BeP3QV*cT&U`N*vC`bsTgS z(xV8q61sR6TEwG`lJGW;-;E2~?$cBZtV47lg=EQpu$V+tD4%FN^c6+jDY>krZ8yhY z`1J6ZE)4qkb``WP8SCy+cZy-v!F#ZsqtEPk(L_bXV?AR9j_fOlMng1snZiu6WB$t`ISBq3vCso)aUx zlX_j|Py1brt~}&m+jp~ z<(V&s2iruVXQ$!PbYve`Z?m-eCan(gt<2XpmRn_bXA{s+r>~xHj7<64ur~)+hX_Yw zDhPKQt{%L}?KEB5U5m*?rWdVIXUTD{TW|(%+R2pN{_@z$Z>6G#k6oPINbCuYMrgaK zzhQx#j6F=Jc8GSs#tPQ;om z&&Fj*#1)2d&g8(|>>{bz-PR|Rr+C?t*==DxS7v^xdP)K7W^&mNFu-Xy&`%C*y-42R zIv%G=d{NPxySj8o`N`q8;`9m9vs4FwyL3nIsX0PgD>p)dZZ$j%+%|9T3IbHRy;-DFGHkLytCqf0s>?GkPk0~caP|y>>7MEy*J0{6ZmFKoi97YoW|OyEKB3KrTl44 z@{kH0#T|x|gg<^@1dXXd)WBzmnXjwb0F$RIuS87H5vv~t`ogAO+G2Fu6N7HCQ(~Z@ zsQKF~O~=wBor)gYgwHZZX`H+aHlS&$*E|EP{T)ODEhE8bfxAG@+?(%%H~A5Gd#R8^ zYwcO7Xj@36^|eagHNG3sHD!$Rx?sy`I8HKH^uokw!C!i-auy4 zE}^AbAf8X9K)DII{8zDUH+yEoVXc<5mNrN8i|sSmzF?kp^Y1GE% z1Y{x+`<2CV;aqm#B#|G1qE~G2!Wm~`Fbr%x{M$?n^_y$p92h_PaA878cHkG+G zA9M+3?~{`EfGZ{O0M$WfOf6?v5dl^4-&sss0u2?l2}~~d0r2f+tS*;IiZ+m^* zvR8Y4&i0G_^c9Yx?y&mjrdj=^j2^&Ru*S6c9w28J5zaxbsn>44P&kziq9#k?q&xyR z>HXW-`Z=V|{L=KWoEy9YXwZ{%qFr_9!DTI0!G7maGk9_h9-Q%(kc}FJS_v#M`ozO& zq9e69C<$k+`}K^q@<$A4_HlDKAoW5~&kRZGOQyI9lOhUV~r%U>t^Rc zj#y^_kSp0V1tchsV-O$0I09WmbH@e{2rdn1Jv!1Hvf9=x$C(Wk;6_O6&}8m%=4@7m z>N?IluIV)N@0Wv5NBCt7(Yv(mJBe>cAC9CT9&QNG{JQ$6|5^LaQg)E?pdy_|YMAi}-Y9~5ei8bMY7oY)5QatG zy$iybSrFZWI8C$S6RZe9p%QW<*bv3k^gkp3bLroUwH%T znc@6l4SoaE&gmH#=DkJx9_x6gb^3(v>nk70F<#m#&E$weBqKkOH1Kz?GC!mfuZzZS zcd^$_q&T&RoL_&F%fH9Zgi2}&mJ>H}P~r343=;Ll6D^~dK+<%b1#9XeU#$Ou2p@s$ zR`En}Ju9(I8Ap*qUf@dp{=0lRmrYzg8`!U3;z<7tLH;i$(EiKW$bZRAn$*BOGmX-I zdK?V9-|nTN%}S;c3$xY(G7GDiDHr5L=jVmv!K6&VNA?ZxnXywR4NXXz_}DcmYh9@- zDp9nYS||ncAgHazG4iOK%J!RZI&yz&Ur4q8t_I0xlX>A8NX%6y{6Y=Cw&>W z?F|X=cghKaz=}^8;EBvgjUn`R@A>l+QOQGF0gfnf3yh8v+W>lWSqcUFc3b03z)h85 zK++xRgIFFjdfp196TdgXz(p~j0_C|BQj=CXvIWvj^S}!A+2Ln1ey_pcxiRQ+iwp9- z&}+c|Zin7&vFp+Q{Q;6qcSn@XK&QV83bJjo+Xdonx+}u-xhhEMt-s%MtAPHkfppIZ ze|f^db#-z@Yxr6ern85R>s=+goh&v2vR`LuU4boQ0)kW-tvEj2NNTWFnWaQ_(3Z7o zWKw*cw|i~1RS9?5NzqKXoEcdJlHp;WCTMP(#h=TaHGZsLw%M#|Kd5|by}9U2@3&NB zy&m0KBv3Ul05rbV;Q+BWt!j>!APvPdazvJ7F|8Aq$j&sBu0QFJ8g+;;c1&G&IbFR< z$M?w{)~86t8joL+w+44%BA4@~F6F)jRk)aUm51sWib^K8 zjZ!bMjvn*|JbY&9@SPagDPZXS6sG;W{9SR`+S$vynAb%m-BIJV+gOsg+x#u4RM~Lj4Tx`@X`QY&}n$_#q3KVh(?< zRbkFXTCNu*!!sUri56c+VE^!1sF3D&;x;vuxc+(*Ipz!__!uAsU&g4lV&0RJ2Q~T4 z?4{`1DAJ&gGse6E2dI+XU71dP?XI9#42;a#XZ%l%uA=LL#W>kxRNSJaM>Q9=NB9tu zz)()wbjmr!@jjIUKR{+3dqyhZP@E0|be=g4-ypDbFHO9NkXjNc zSCt79GVjqtX)c9F3pVc9n$Ue=hq6VjM&FW5R!i5nq-gq=e$ey8H&)}MDwnlM!-Pte zy3k9x*Au!}_Q|@Gp@A1ynhd?Mj5`rx%b9QEPJX_tN!U5HCy)pAWp8d!mM((ollj`m zZDr8OEhgl^D<%5#ymtdcagfBU$)5dV-70Dr9;8ngCAH;%bMdE2)#4J0cf=0(!wEH% zuME$N({TIjdsh(eF0fjc>0Zn$E+p-q5#&#V3YBDif_|PypFGXlH(y)YvP=>XRVUyL zQMmm_qR4GmGKCzE1p2rQxk8fqczlB|MS~){cHFzRq;yaaX^7;8C;>Yj>ygHlB}ZF? z2t4?8Xc2`X@fN{8kbPhfef&1OUBBWE2sN{eo0oZa5x+TrL-@j@U_6sp;;oWaJXN5s zC0(+vP!!u3yZ)ZKrb$`Qsgf!}7@G|jBj(r;LuFT-YW$h8E)xPKT5Z{ch9WYcD+EzbESY0VOfR3SxX6lLRm%mA3Z#JII$uJm~Jrl?F(qZ zbhWHKg{9LzP(=2uh&MUE@ zT6SrYSN`)>TW?{jE%NolUv=%J@6(R%s+L&k08`Q9>?E7XE3s_haPgY*g%fOfnOVkD z_6qh|`^HYLPDANDGFBnO7&!RL84PG+>q71-h6gTb@0{H;;f?ES1_fBUF~w|6U4=Sp&Yaal|^@F zt8-Qxkxhscqnf2cz;|-7QSGRytN|a6ta#$*W2`{?iC2v7{^MmWQ>PG6{h2wD(8fhO zSUAR7%BJO6Q*O<4Z=TK9M6U$Gyy)AbMOlQw$BU4SqFH7*Wm*s>C~>)=l8z7+KI0Y4 zT@^Brb)#cr>0DxRLuo3~IpII2ojU0fHgzsCT{cUZSF&?6{NPo)m$dZqTj&$cbzi#t zqa1vrWM#4677Mes)=WM^FQY}w%t7nx6XB{wqv)IiuJh4xWAnUe^rt#!irxja&eyPo zZ5e;4f$6jxI5ze zzpYC7p}v4Q?6w=$cHQHcWYZZv$fmu&wSy|a(++8%Sq}$Xhxl6GIdFNvUhEX5dlyuA zVQ%0PH$hovFrv3MmTW8U$iP!{!3hLIbgP(6{E3Ym&1%qA%t`;UMzuqv)&R>Q_p4z#g;R9x@ z^D=;#y0fxs3zSzXB0cKfCs3QeUHigTF32$hPZjC@q_xT!U4Er!bHLWWu|-Xshfs}j zC7@wYYKUbb=oLr-{c%qeS!;*2_Zxhm4GJ?o82%Y7j+@xr(mwxe6>YM#=S+3g=keFh z?!bo~rBNqx%h_5Lvn>w=`}XKYhUr&^S!qw7{ic7zt#+nVZ|ek4Vic zp41(_vxLvg_a0#2d#K~4x`KutoHeuXX$22I?EsB?hM%)#-$olPeu&)VaZZS5d~0ya z{%;S+_AN@OB9<@hvk|hVCpSp8MQc1}&gFUwO(kcTM9LS8u=!|y=gP!Ql znNv63>!k*RA}cVvPo%u-UarlsAhd;8N;}jiFIE;fXGWe0$y@f}XYR)NuEhs{^9wv? zM_4QO)Mm_)5wH)LLCgW5>jBipB^nb;9Y5jAyy&mO`HYsGp~t8f(~qhmC|2{2Dr3BG zt? z>C#2Jpi<(}IJ3nje{<~qjN&?@4SUXG@WT{;r@o%p0eY_7J~HdnZnS6Mi{ZQD5&0HaK48h*`wnAjKDXYXB?Cft0KO|1> zNl;+xIIae^T8)-aOMOoaLH;MBiYS|S3AC=(jh5=Z4~KF_3!5*A<#j6Fs4TdAEd{6w zA*21Z>_w=oM{uQMIr2M3h^AK-U>PE_B=Yx$I97|_a;k4f!&lkE1|L}fN}8!1uYsK<|*eM|W}#L|j35ha+CoAa>1=2Wc18KgF}6OcXJ*m2CPP z%0YXSQg+>%Fnd&19vI(*J9D>VP?xM;3)Ul2QbV$3UmDoBdT9?tk|emN-^h>TX2@&Y z#gbaN#%HY4v9xc;13>v;m-nknTGRw;4|TAU$Y z%i3XQkl^bq-<=Dqa!*)##vLj@F>Q}*UJXG!As(MbptV7tiy7Z(l;u2~S4;wTMGjsp zQgaA=5MLJ)q)>Vz922tgx5Lz6j!xv+VVbd}vcf6U!FaOiq;sO3$WsE!Td>kospT&@ z)=?)QG^toCsH&H83Es~(_ z*RUksSk71{wv?~3gg?YS(qN%jpgabmUV*UGnw9L_V9#>CdC^B=|3${wnt?sqwhk+} z(Qya++FG5u!XaKscMI;xU=wG&Rq|^akyhG3cwd{of(1+;V6&PbIx2*MG9tBViV$hju>n^{!jHH@6X>MpDz0Sb`12dU$EH! z4D$Uq%XR;^I>rCG1yXiSe1Hy#+pZzY;oNf`7A}((qz|-+F4j*r6=E5;)mhKbA|c)o z*vIN`>o|#vv5f}&Q$sR0JshUT##Ub55qqJ7@nHn87@-{0!%5@M@tx`uuLJhHnTVMg z)u&y{lMu)6!logsKF`wZ;kBBM?V#ZY+z3-bB@3l9sxDobv}DD&2$@g980Du5oKIk{ z8pJ=8R7HlF>un5EpuPlaBq?x=NYJEN1JB0}t0@EENTFP!sp zBPM_3I+#O~5RBvFn)=@{H?U}LAaOJI?sL2WdTT?>o!X(W9RXrKz|5g4)@MAPynP8{ zyk>6m=)v51|8~}jTde)R0Dk?N1Ni?)ul=_#c_RlWOUHk7!f{;Sl2~z?m#nyQFn=ZCw{8JMr~SbnN*gHD3W=sVRPZZFd@DRn=5i zJ3Wr4+fFiFOlYdTKY?yxY9L4TSYRO?j#FFeOb>|hUFK2lQ2WItO0ALJwOFOyyXfYx z&&n@?#3hQhWb{;o%?WuFvh`{*>ZtR8^Xz9iP)hot134UBI7a3dK3RHBa4GTkD)%ULSiy143sSfCZjEzvtr%itE#JhwrKLF-%p;_Gv+OA!1#4*ucDP{ElX>n9 zjCaPb$JxM{`qq@ig){s@4aNe8!N!t<2bZIy+9fM8XiDB);v2T5(yKsQncgof>o-2; zo>y_1Iy9`&TAy$9GhDo;`n6L9vp-KWP7?&`ZKiwyL2Ixg`em>C?C7FbY6JR_G8b4C!RHVNH@7P=rs@1B8-d$w9-muc%$Jy(5 zT9bt0W*8v-z5DWaMi+1+7loP#0a8N zMa{wy=^jt+B{V!kIsj6TUzUcGZwWY>P@TEuB0Px&AccaTnR^J_kSxTFPVS48;D`O_ zFWsvin`bNP5~KK&6B->i-P#-bnQMX-LiS7~i7hCWvt6$11BT>@lGdezwR5 z)^-GVF_;DR9^ujD+dkWaOrVB{Zl_Q#el@q9gwah#N6ouDkf48K`i2qm(y?e)Hqjr% zmA_|mYLGgJ1N%#~_k5N`l@-Ve22O5jDCq6ziBUMJG%_qPJjM%|DL`s#&vnmxH=10c zMs+D!<%Sr4ToZ}9BrWA<9&9@cRj4MTgE)|`W_>aI1ZmQ2P1xe0CNy37{0 z#6LZv1tPBSS0HLV_B$fJ_!}0SkwJL@P}bI%z6t6>a5uKZ!`B9AuV-=W`0->Ca@a~b zY!meYYZCDyHu5iK8bRdr!NiK+5N;XZ?ncICR5;--1FZAl5MK~LT*~*p5c#|knjPm9 zrWwymG|m^cMN&RZSH~~zRx6wYZx2?rOM$38u5imU#SPDVGHOa}q?Srp{R_7?j=bZh z`uDG2%KvmLm(c%3b&}{Gw7!2Y$y20YWr4^C=gktz{>DU&4+m;MXFNOL=COJdVl2Lx)tLAWEg?+{;G6?4Cbv` zY8BOL?dN3D?Kh5qb1;Ea?654%zH1Ja8uZSi?o&T9zKZ97VkHyZn$nG6v$SiJfrH7R ztM7ciXJ7nAlNBI=N`3WxwGS&LHd?nPzBs`l7S{t`&f-UpzSxgpOM1yiiCJ?_W&-tQ zs=Z5Q*9ziOPm|fsC2JO|ktNO{0N9#q-$@1QyLQ{-8I{7dq=WA2y@NdKa*Lae=n`Ru zgsRM2m=(;;@(XXpW2Ft_0+KpL!jX<|_&kCS=M8!wGa-ek@8tRX$>rEVFKEP2vrvP0 zy?0n<;#yJ74~Nc$+Hhtw@j;HOnR+poSM33*LS!!8)o+<3w0!}VnF`W=TXcW)8+Asb zw#YkU1yvx;(MWSHSA*O2~Nr6F&Etv8^ay!&rjg1peDg}Jd> zB1o8mR){OLK^v>WI5D;U*fHygJLMwO;lHingXJ8jD;Qj`8Sd0uD(9{s$D76Sa9uO1|ukNPR zGWdk#=@r$h1+3{vTNVXzfQ>T|0R?9r&+70 zz`rrT{;srCu$*pXWc-}P4W!1WF&lx*hn}a)t@y}O4Jg&#P|peRRpCzIehT_nkk45W ztf<&X=WxC4F}*gSr?Zo-^XpQVI0*kxKDDp1?U;&6Rn-uUCszDiAlOy!D;;0%{=#1` zpCXCP#)BDN^G-d1Bdz@A{+JoI(Cvm9@m)BWse+6;k>*W1;v#&-JXr$DS%@4yF`Wwv z*bb&#a|uvqIjeTd{LRmqqa*r4gx^HA=Y7dC2mk6WnC(CwyG`A>u-kwPg@@{cNBEGk ze7cSFd8KEvW7&}P7={7;zDJdQG8LFcu+%O0gH!XawlB8*al?;Nx=75>-u9zPV|$M! zSWiv0nclB4ioB5e5dHZZ7c}Ti=Z+rMZ0z#o>Wa5LnLLFPqIS6USp-};HuqjsDB-zW*;|t$%-i z{?*WG;GRe)PCq?s2F5Cce;|KXA?Xeo;S*7pM55Y(VGFBLf{W<}((4yuOIXx6FE=#& zo}aKP+rp|!C=Q8Xk`BWrZZHGwwDU)7u~T5R65U_6J|HnmSR4||XlBoRnW}bH zng3ny^ZA%{<8kA4^Xg-hoZ|iVDfA0-^p<~sGXKp3wmaG<_AUmZdoKu4W$-ftqMP{L z#={P&#=Z5egh25iN9Z9vwVUQZ$MCbl|HhRb*T!`E&)YtCmT;^tsysP6}E3fAy* z7LwPSDE$X%(I))3r?WM@MexA@m^bcj2jY7qLR?esR-y06XK3x`VgKij5&z~y8>^4j z@Kc_uhZ@n4Ac%<8d<;J!!DWm%VIv}{b)Ps5iPmkjLN*Rnhg2y~zj!c-AYJ644Zb}a zH31kRTctFRI5viTfjM&b5%(zL?;?>+SA*I~3ihpT8Tg6bF^!hnml9^!%!IOI~ zPEhh@zH$#|Vv)-06o}6%V#KL|yqGw_J-%eY<*0c2`D-s4r@x>e9ygu(+wJtEi`<b{Na>{D6I26+;NP4&u3H38__7JQ{x&IxP>5vNIq)kKa2(X*=mmJ19Hzl>unGw zZsG7Y3{J_`5?q3}=E*}SRuMZ!aLp=4YEoG?2w!#<8H}%A1 zW0eY8FU5`tA9LkuB9KJOmr3mKM~mU6$t=0VPr3@@k{JDJ(R_r%;bz5c;T@?sC(-L* z@`<3)iRi?MNUce%dKfMj0m_S^56B7bmgbt7*sSRSVs#^Z^JevJY1|Y0#4n|zH-}J{ zr&w^GsmyhvFS%8?dT*9X0~kB!uFt<2I%-}7{ioX9o1s@w`q5!KO|q);G09XlMe#i`3Gg> zi#dYHoo^mnOm4FdPcrQ+NK6qfh;Up>w<%4B2@3KzJrqxPlmibZNoWB`Ui3q#Cux%*I1^3~f|_a6%BH|0c%vWT?EZuPFzih*5g zKH4bJUzXHH-%OjPgcKGZ(4~5CclWR?C}PYd+5vUi&ka9d%iC|c<75CQS&j89vS|AURq>2AMNfSFe6=y2{ zM@@d{gRXL)JyVW8+<*cncZ$L)&mEa#)gRJW-F#jCy&r1lE6$VwenI*%qE+$Cc)fg{ z8fjnlT1I$hf^wsjulS1MDmROw+doC{fkEfEosF8NL83@_y-FUDxnhyOieamK9>-k4 zjCMrRsAG)}s^Q!2}3J_uX*Pj1K9Hf&)W z7rOy7bc#is4B@fC;cwU-;2dxfHpA>Ob_@Xmiw6%BosuZn(Sw4!=p0+QT64W;;UA z)7+KTWk3zvwTc23NAx&Aos>8PUErDng;s|{w%4GII4b9}90iNKImXwlFoKmRV-Nn$|Xj^~!1Fj5BS7r9bkT?(ZUP#k>uio3v<0Mp;j(u2$yB%3l> zOJ;LO((5oVMma-5AuUaHHnX9!%!&T_Wk{AgPbZ|*u5lQh4(r)3^)ia2U>3M~f@H{) z_JrKW$15^p8)X+ofiF_Wq~jf;*Mw2#N<@2YY?mrW%m^dhhd}9hiV*{ddID)>y6>J# z2`Z@>q_Wj2iK5iHddT3}L&iZ_qc(ZuReJVP%p@l#tw0*EwLc)R7>xb=(Oz1vOMV({ zgai65yEZ{H8P|yU8{eoy5gB&2zr5=WYmg;JNB&h!U!t{1v~Xj$R!#G?2_8u(|JX7@ zOt8(MCu^*wXw--SF|woW%+mK37ORxv$))}S%)olrwFFL#7GKk(y1b7KYeP|{1O%1QsstQGbc<0k(q4^Y4us(H|qLfm7$&DccrhI}zXTQo!y zoi1r8+0qYsKF&(4Cw;rXbGQezz2()Fcxq1v7iB)#bwwLO-MxHhBiZd9guEwA0~Vs9 z+hTVm+54gjw=bs&nDm70mGUAh7Et96sf)Z8M8+O6p0_0aZN`UAJb3D2H?M37=?(kB zND7P7dt-vcIp{$8@=(4~R~x;a{vb=7nXQ+3Ky?>5)x{xY^$^JIo^u6H@6P+duOC3> zxn)oZych5q(1_)pJ~L%dZc;vzXS(HvBmvfDp&jT6^3czW${X^AujUBJA6~GnfO!Aj zg?bTz^<-YAuI>o2Eqm%n>RByWDC z))!}hfFlUv9Y}fhKvhac7t{;E!xSp(k^FI?1it8hu=b9@m9^U%Xwc~nJGSkPZQJNL zSxHuGJ007$ZQFLowrzBHyT85n!LED0b8gkGdTUj!HP`$x$2;CJpTUPbCcDT6|8iY! zYDa)GBIpPfuc*!?baJ`T1M-$5(0Lbr*>|A07m<5do#dT32OhsSh@)y@7vw!yth8Ed zA#ZAn_{m`PU}{V5$=@*QJ-&tgY&z>Ybrz4O-~1b|=jcNOHmb)BU?ZW%*Yg$<52#yV z1n(6Obh%<5d$;!p*X%WTav>9(r2o$Ln3I0k%VKd3;kfHE685L<@I?NFQ z^g3iu4ASyi1UA1_&UW%ohEl8H9YLT>C&^1DZ5N?0yXlHXclKVtAXybAS&p6Qg_Ldg z=~lnXe)=^>`9fAMvH+bEjvDI1hwED4ae(ZBjOZG*8xsER&RBBT@ne*CGZd=4otfCR zD<+9;gT~u>VN|Daj{Mgr0BqK%4bS*oCC#D=M02N={d#&~>(}oLsW%yHyIea{^W;pi zNYcbE@rS@jr6rg9zUT}C8%{gD_{oJboC5283A!oCKdT8S`5->*U=yFuq$chSEq9w4 zZDo|7w4d)hC#^5jQP&us;i)v)blVR{f+-T~i!>5P-bF+GXTfIG?4#T6!IXR*G)p0V z=%e{i-$2($KX~CDx=w2BOKT_FvDw5_zIXKSS#{i1dvR3`!W3nNe9}P2+wHd3;kV4H znw%=ZX=nB%o3yF6YVLRlU~mztTtR=Wlwv7Lv85~;WE^y!UbI9s_koktQyYfFL19lu9f^*(bUlRz?vdLlL+D3(D(`cBrPB!Sh_6 zk^551-%1CbPr4Lf8z>h-$Jdk8w9c;!{Hjyf>IRDavLK_U)a-_nwwSQhX=`y@jEb!L z#%_fcbDirV_B5kOZZk&Ob<6z}S6{WU?*V%#sa+Y>^;W31J43klz%{aHgSU#SN3eGt zd8d{WJ=CN`K(>1n%e1s_=yGBIl#nUG9LR0JezuyiOlvSA!_?IDl6u>yX=Fur+hEj) zF0-?6+~zd}M45jAb{XTi4{lghjtnd!(rg3ZxD|1+y?Ce!BGia2d)-W_oy426)u9P# zShD3-zG|<808G)POAsHW+O7#ppyb3STvW|^&+_ zvW+jXja1q&L3@8XbS1HOyamZTjOq0zxAobbCr*!X+?Wsl{fN9=mvojiZu4H2xLTy1 za9MpKPR_x&ZXv{LK(XeulHU&ZK$T+3_n97LBJ#`o29;H`o2LiXaKKOJv}9he`9cuxjg6??kB>8?2z74ak=|o&e-=cXG7?&3ir1Cs(bJD`EGtVjX33Dkt0l`waz^ z5jedUW692-o}MgTkDtB<$hAJXdh^g(j6#@*e z;?xoclm5k$UAcPD%Rd8Ff%;rbjeprqs}V+)!7b)ExL|I3?BRA7wJXZ#ZewZ=?C0Tk z8<(ImT$adCi8Tc#WLodfNq6>xbGmyS{I}POPPDY5-Uish`S0J)oppj;T7CpWETU|0 z?S6$C_&NlO7=?y#O_8O1)wJyE8Wo|ypD-q?_^s(VT}v@TMsv;C1pAl(8w*T2z#@?5`Dx9Xhc~-7Y9GJ`xlVl4$&5flVJg1DY!{{Az|{rOA&+r{{A zyvEPZ*Iwkl>FNA-;d#3)mh=r=EfSvCWUy!Eqou3swFpPbRy?r}fD@ue#Y^7rM|AfK z^23uboKBP;P8aDRDd0Bx^+l4yRTuSF)yVN8@zdu{%DujQmrt9}y9xk4vYXAseOvX+ z=>1}vAwyTi#3JE~-`9Ga`<^nBJvn`mT?%2RM&GqCGn3v7F?A^V!Vo?1=@Pbq%iaX9 z-+S3n2TcQNt)%czX6wG7)XNl_E?viGPGG4A#CAToqn5Tlo_@JMh_|{h-#A#3u-7dU z6j@`ei?redccU_n-wuKr`IMRJ~!pyrrMp8zr@o-^ZXEvHvY z57B2FJe(mi5!&qp0O+tB16fC#NFP&L7X4A;P6Jmv9!JNQVMHR)cY{Ae#+NN5q*WnqmI!hg12w<-R_QK0QfBmJf%U=yTF zJ}M(z7TzaHbcmq|YfsTF7-EX6Sd1rW#MByxad9ux%G#F87O-B%e$xD~upT^VtM;&4 zOwFztt{Q+z8JjkK@3zy;yE>Wzn?u&>Qac_mir&^zQmch(aH)(l6ZbW2|5x`x_DLWS zZQ4Y7^J8%O@_bQB`l7liyZj&8@=ybcq2S+*2BOlKuQs=~zOgdD1-JbfFjSvtuv#oa* zCLbc#HQn6XoSio|F)uGqfis8hEB3OCq|V43tBI!>7r{<1E`@xR?h^`yz2MWQTB{r* zR~@P+LoL*Dd6uprk?us-fRoroJq^ay&Y)5nrQ%fo1X=QoYe7_xtJp7a?qx9(1y7J- zcf!5HM(DJfjnaU{i4O8G@+gi;({l&4pm8f#n4@34QG|ojRWP;e?_`*f+!K&27cI1@ zy?{qEwOVbYa*=>&R_0$a4K&tglO}-(nJjtM98knN@4?kx=PcjRp!Zb??k|kUaQX$ zg)Q4?on{7bblzVu;Ls`a>UK^<9hE$t^iSsPKucRCe76abKV;bbbh4*A0%>GJ7x&>h z9!}Y+WJeaA;%u1`%U!y1kl9_IEKgkQFm;eg$$>09J0J}Pk1P>Y9Ug_uCzlN>HXTe} z11pE9JrojK6ylFeGsATEuFmT|Wx%Gh1^!4>_l|UX#b}WZeba?Kf8?w%d_=a_3uV`H z7&j9e_M*ic`(6B2`TNs+Zfj*C_R--#*am zX@!z6YUXB_yk>`}ba8?l6)Do|m4gN$L_WsBCRuD^OMN?CsKO1~(RB_Uji@ay1Z0wN z{V@4rG3DY`+BuWf-3QJ+hS9o~_#0D)H30GwLFe+bdh-{lC0+BXIE~@Q;H;IndMbuZ zG|ku{8mRVblvV1eWd_lHRy1kl$bhE`fAA|_pLfuT6V!8c|NZL*_POc=Rcx zG1I`fAzBfDGNiW-VdUy^b~nC4ARj{@A5&o0OkNiN@qIG&Ntd+U_lp~=Vnuw;x^hyMe; zcCnuzaiKs!f|36#^!om9&G5|sADZE%OdX{DV?1`Oj8q>#Lf~daO$~$Byhg?5yi|oA z3it9(!O1}Gmw~V%nbx_4EhtseZXC?w;!+$H#aek0a6*MkhqhuzzA+-^Kp z+I)rT>R?jK#0GVS8Z-R}LhS?}xnJ5FZ4T}D znk|fC(>2(EZA(I2s{G9}>13N)bMao&YYG>WlY9nUx$iDk7d9Yg&YBdi5xL;Rra*Y; zP++!2J_a@wydLg;DYR)OX-qF>r{$E4b3tS&ggb{JFaUIHX&Tic8H1_D$^c0OTis%5 zIB&T6wrhe>`h(fwVgou#@K)$EFq!gRu2KEj-K*Rn{vzHB)~&>u-tcHI+IUZFtV(an zLA-}3Ez<86gWQ}PYL9%_*kr4O_X(n;2(S4HCUa04)|g>60G@)Ypl)oH4&%7syFO=@ zp@XUCDB#<{EqEHe+Zf6hW`UQ8I<(HeQ1`vbJXH!P2#C$!CjI`GGR1$6$&$1B2kF-z zu2Kh}w5k2?i~qvl5pq4Uz5EECeoHI9!y#=UU)rk~uJvfP!5A1!dqHDmh3m3w` zlS7XRs;%pz6KrLypq*1vsZ+47VuA8xsC@d7*U2`f%XXNsn_KHY?H%x5XOzA;!?6$9 z*CmBm8PzKKN$|_ILXu73w_AH7T;cHt_3$uUvSveRL?gw!yuH7QKkwrn$WDICto3ix z=>Ll^^KbQK|Jmt>14RAsZZUFZw47yz`{~cB_rp>!t&vh}r9PHy)k&(-C@!(yEXAsD zq%kdpzHOB?)EAnHV#kLc@l%Y@r-VXgL?QyPTmoO{4VNuX-7VVZjq$UyGox9EQt`{ZVKhnMF~O zF4CfucrjPa;T%t3bi9PyVT_|!q?z0!t8x-gwf;pwBSKeEYXzuY$dF!1C@Ymm71auIt^Vr;KpX*Uazl1lv(G3t1$u>b+862=aohl_?br zEO?7MV7D4Od2adNBQ8&;cSh6%d&j`+o3IafC(a~JT3fjar%R$Ue@bgdSgPLpBpXRS zh4D+U=a9wr3z=Q6)R#2@@)bR4@@5R~qF0&RN3PyEaw4(hSoxN}ZIEX`<2eqDVB zGdVwjx;VKwG22A_dJYL4EKlfKs;1{9HU^Os*%^69X01gZcSitj#zAA$#F9!W~r5U3#jCO*hmBrP0;%XAMsVxE8Sd!@w z8v!wT9INI2M3~2m6R5zK6?X_UqjIN52g}?Hdh8PZZggiYvY%_R)`f_;Cc)%lqOeTU z)!r=Nq!cJW7Rr1cluvK>j3u)vDQs)nxq|ko^w-OUah;dO#G!_M6x|H0WWx4j zplchVg2AdX(`Y)5lL!`W&gsVZ)~RVGMriD_@j(u6h)&9gn*+&!mpz`x%*F+4gn&|* z@pFe=e=zx(tBG7uj7>#5{Z>nucH5&_jDLakZ$E8PT5FP*G!)#7yH8#Ji*_+eHoqys z{bc(db947`3y3{Hyf5FMQ{1W8=3K8IoAXSCQ$F*v1o6w424O1LDQFs=O8#^%J^wp6 zGsDenQxeCSi}3DAb?6R)YNmb2DEZJF=d@H@x%?@d)L4-n4^u1WUVm(GgJ2ELQqOHb-$`-8 z_4poSz*lng(H)1>GwDpIy?S39Zj5PBB!yBdq<6CI%X*ZnB?CvjF=hx#&hqY&si2FYT7LmbP+#n-uvyNGfQClYEwJ{_vB1LwEC}?x24fFqkrDSC_EJmYsfd;ab9Od~?PDqYJv`zR!M9grTIG5m zslHxk@>g=NQa!SFls_4Yw>E<*mf)zirHs$Hs4iXS;#I=$LVXvv?|&h(GH!dLob?7k z^9Gld)J*zup3VkHN;i^*@XV7E3j2^iqbl?tG(-EvQm9_(XjN=^y6}PP_Vp1$H0^#B ziHDRx=w7>>ar_Qfp`+##(H)7^fxchFE^K+!lH1FgD(Xob{U8y3Bbt`0I z&8R6t<_kBuTw0@fHgCUucTnD#qMc)D5Y92UWv@{DKBu1x$Kw3N0tN>5i(pR5%EIz1 zFH_p4ms)MYFMr{4$y~}(0c13=oLx*b*8Q#2g+N=o-j$yZi)6Ij=$P{4wNONKpDX26#%+ju&vkL^Xh|LzWrmHAio_KkRZ+Vkz`Vem_8}MJ3_;-< zNAC7NyK9deXcSrZhBRZ&EAP)L(mEAroQXRUrJPT=NChf~X_ufGi#tLc#L-wgwlD0o zzVQy5ULl!ZSHdP4ueL9Jrf7w=CO#}$(iQ#Ou?83Fs2crqbDL%%%3UptvOIv;9r2Ml z@~u(h%)Z)fLmx;@t2GNb#EcF+OS#Bglu6poa9Nb5r;`P@hp0?PJAiIq4RD1wwNEIM z;j2JbbHX2zFr|2D?GP5zedtDQvl&pTr*hg3t*h5>PI=|`ytR0x&(bstQb|K*;0;Z_ zv88Dx58L&C7u!UM#aoe%z>}m(lNIfAN;6$6Nuo{D zg>l;-E4_S+eAoWjxvhoNY5)P#zh2u7oT>x~MKd9L;~S_l$jsyH=*NzN_znXNlAH^- z+CG&k3+an;%ZV}&m<9H((u26Ce>kX8M-U{hAts>YOumljwh$*a3}dGeD=A5fAQwv_ z2gr26Lfyes4l(9IQfWg{k&}?0uN0n7fhrvjlG{;=^ugwKEI!g%Y;-!Y94;2hGNK^r zO!Ck}uCkq@tSNQ3GSf^(N?UQmHV_DzLR?DMP{>rn9dVo|2*(%lE-(4A^p7G zp6FaMU1qu^b7QqSopYJ&L=*!tc#G@>a_zqVognkGHULtYrTa1_Y!8|NqBslz)y8O;ECw`%`R>CRvqU zRDjw;K_xif*p5Tt3uYEAK9g@kln;fUbXtg`^O)Mf1N$L~Y>6!K3i?j5dxopfJ-9{M z#`SpC&Rxg!55_dK>t0bjQW$s(*sX2)%I%nd+JMjq8c7c22@ZpA#u3cMjjq^2HncQq zYV}vigsU5{1|^tACqb{lZ8Z-!&#*pDg9%yr)%zz~#hC*Oo|@gWKUp)zkC}c3O`?7Dq$z-E zROJ9KOf?)t=`-Q8{OnF1o?o;IPPj7XxbU0gCN>zVF}}jz)H()YlE8yn;_Md z!=Pp-&mRNWBN7R`=KC3`igN6D_N6}{$Hr%Nuimdn&8gbgSk&!857m6|jkE9Uqy3PB z=<)$RK+KY1o-Hr_0PWGCI1;lo30`QPZc%#7(6xw|q=3`8(aN;;u+-_Bcd2|Q>0O}3 zLVl63X7WM-UO9tw^rm<6zC*I0^1{t#XuiVnD!=D2OErIAV$nNpjta9#z7I~ehz$QQ zT&xbE5R!cHLw6}T#?sgw{S#`+RLBX&xs!gabSO0j`G^FZ4RRA8&;ZO?HiN~)B;sNY zD)7NbHhTTEhw7jeqtZ*D5T-4RTAQ6m>+NpUo%Omg)df$gLXHRf_}j(w8vz;e+l&7X z7wK6qYQP|c!0rA&$Q|GyM9{y3fq+>3H%hjDPuOAnzpJg2DbShje@^rL4}%x~x=Z!< z$3Kh9<(z+qJ<5qP6|AuQ7-R{sqiy(MUr2Q8JFdq3Eaq zAZBpA*Oe|xZoh3I@Qbl(*f?+|Ts9XX~4Mf@0>I^JW*=Im%#1O0Pty0?H`iy-?@bNDe{~&Om zm5<3+&hZo{_FXT;{dkAnezOUD=F9lBLHU`Vj4~kri%B(+H^KqgEknX-Oc$TJeGstE zVWJgxU>%x9LMlS)mL$C=@5 zOtacu8fHz@;$K+NA=R{Wnz&dQu;%Ut=L2`y3P2wfN)X+_^-`W^GBBQ~<-Bz3|MmQ-{BtXM8 zXaMx6gi7@^D~r^1l$gG_A@G60Zo3idn%fW$BhaXX;sj!T`!#~6Vtx{5RuDti#Ag1h zaK)sd>Gq!Xf}BBk0e0+afzk<3BVmbhmN{utXrbl?tX`bX2wY$=1r}O3v(%Mvd~PBS zBeY)3R?v2DDl8eOUbsvn4s3%dEqzwtid@)aX{}V8ZPU5%2PVwMISoRY5=z*2OBpCr5HOo&~4gU+HW1F1%X2%pNq7jPB&C?a0r?fb5$Nu>NI_k{qAiN zoX6z^-IQr2L>m%iLmBdTEr67@g@rDO)KnAOZ>*MZ#U8>q$%rEBnikbnzD8Mh^<~KB zJ|h=%rk!D6t{gX@knF4beS83^1yed7Y@;^NKrgxDmr;o-dX)mF;QfxOW(9Nc>*__b zG@laX^D^`Qe zBU(KD`;;7XX4K$6WfauZ$&m+e#iv6#B+2s==#Ys6j~r!2*T~Z@NrfL@f5>p3 zy;4Jmb4flyAQ55mcz9gs23U^-iD|ihrDRK+d=0$=&8CDrz{FwAVx>-kN0e=!4#+kgrsz)Y`dK4d&D3UN1pAyc!do0t3sagDE z9KzlB2>QW6K&rp|T^R<;|7xGDj7*Ik?Ens@)>i-3OjN{cTO$de1a5Ad1KKPRyBai1 z6hIRiYQ8J7P&SN+=2Q6hQ!~*JuNy5BzW7`py6i`=RiH<(UjJckG^Wh02~6xybDc`z zxlL!XH+p!9s@eo8-}Zq0*I`fE0{9707AwvF&GSO)kK_02dKjk`=2Gt8N<9kWmKFX`t&F4gn5pf{a1Hz z(~KBdOzqkxw5jig;uyRabKxo{G*I?CW{|z&f^%25c*c$!4D~KpEjjemXr)~~0+mBQ zqgq849=XVc8HrmZKe(isDSfV_Y^?ukj#JSdJWnWZu>G0q$q4aUzO8K+ox+{2QmJNLD;$U@3hb1C| z)9+^0%!=q~)0pTknq=!p=5KAx*i3)3tF-p|0IiN|~>^-m&;mvI61 zT0tkE=rEB)<;T7=^eHwtO(IyEh|!ljOU8TFvcm$0!f2iot zpE)<%ans_y=%2N&+@6p4@Wkw-dFB90K()VmmZ;bh#c%#3PI{Txh?csHCVUa0I#ib0 zhpDQ-xy}HzxebM&;WwIF2Kv*x2ljg43a!B9d4C#Fo zO&Qh^t_oE?KLlOy-xcq^wtF4ZmHA8=nL;2>7b-|hLQd=iD-9jPKEi zaA?}I%L&QiO&Qtl@DZhFK&1Ct$P$fG(ruwAJddqWljL=&xawV?2-#y4H(LJ%N5@S2 zng{-%n!g?UEbzY=E-^c6N1K15%YXa+UuJH^2uStOqYQnd*k{4=JGt)W&;akrq^3Rg=iBN(fF zTIG5L{z}16W}zT(gmb{abUEREiC<+6Qu#B=7AsE-!=wSBbi93O{h;%wStFa4C1l=+ zCx2NOTp9HBIM%|1g9ygEN`Z!?RXPEQl=h0&I1FZ>K%eCOq)pcTh20o6-fp_hV!Lwz z!-|`#_J5mv;M9*O)k|H$=nuILX-a_7NCtAGjRH2)$UL&UnzhIU)NCHIFi1{7 zs|KzhHZH-IL<9ie^B%((G_IS(Ax3yz?vF@`Zp9|oe+$eC^zRg1>wi)7-x9L{+Bvui zSeaS^9IWmB)vha~^gmzya{~S~=At2fQx^G;-K?w7)>PHd=>H(nXh1PU91ECEj{b}s zOEnlfxN6GfL%6zZJq4ey z%kzs3ewhS`%`9`1Vs%Vbx8<5dPmeY>1oka!=%*s;c8{Oa8go1n$(3iJl{P#%P3uX1 z%VPe*^?ALowGkq{YoaY0N_LkbTTMWO4xQOjQX)Qzmx{( zHYh7u!q5D7itD&5xeXv@jXoY~!|1pGMDf#?o(NRL%O80XbkC#5EIn{ug%+Iz#sDB= zAqmJu3-1$U*lkh|ihG>}kADEhI(+&?^ z?_yI#3rmj`Q{Og=`l9bSl%2XAUL$*o-99*#Ip&Bq_U@~?+osUuT@qaMU~4!vEU6Z5 z?|1i4I?u+c_>lxA!P$g6DCAHw}M9giP0)MoMa^h0eR#I%j*Hj${ZcdA?He-u1l zW76PHV1e>)=TZC*({le|GXQqRrdHAbS8GQHd4L_j(*D0;(8MV@WCetwt}2woLh_< z75$`nQr00)B!+5*UAfC(Q}Xb*M>tuW?}g1THvU}|i+1(`u|V?1_@UFnUo z9oL3EigS35nby3@3!0EfwROmie?)w*Jidw}kT*?7bzH<%omkFbPA#T^bXob=imlr@ zIh7;3mXk_+vz1B>%&LSYt0gF+q$17~J;K_+VTu%qku-4{<@Aagz5=&KU`|)K(A|hr zSjvo&a++f{>*tbmETUH;^O=_^CMv1=uX|Sok7qy3P@RxM$yUu|DVt7%9GvF_dpJr` zM?)*HI5{eiCf&}fi~kXS0}V4?-C$ZV-=bUi!h!?PSqx zu_}mUb3}y6Cqs_*cffp!o?DvzK@pK2;coWneZdZd`w{fTaZZc5tZ(0I1b>|ZF=&z` z@Y8i8^GBXbQFL|kR*iyj&4FMCn9uL-zMuLrHJp0kq*8}VHA;<5sba$WLrBilM@CwP zVt$EWrOr5*UC@8gzI$2a?;48tn*vk!sx@U6Z=611G!<=StcPlp4g7NcivWIv)g^}i zi@H7`q_It6eUw~0I7W_m=i%lL^7;U1c-}L`(i<-82gKK-o?qNKixFG2WbM=v+3HS^ z0Oh^Yif#W!T4mKO8|u@1wwvSw!D7E{ReZruH`mVFVC7Vwy$IjtAzY?GXRxW)^W@id zn__t+t(ugzrJodH>5o?8tC~x)^1WM_S@xJ&&Y{ zw;0|(PN}e|9q_OB`JXuUzk+#x)s1HlMQfXtc-7VPHi|EHQXUmTGID-y5AA@3z z%LCusl78*a#QeF2(e9flW2}Mh8dU)tn_^k;_MDVGPFC6XppVb#KJHQYu|c(QCLd^)QEl z1lBntHn&}>cIPDZkj4!WFi~_47OjjZarHxfnX#oS8jWj8lK!|^VlmkY&fiC0b}>mA z)62C7B?_NeyPs^}o1FB>(W2{`I3O(9Zt%M*Sxo zE{Ie3lVceASjFpT#LE>at_UrLM1dv`g)fwZMMcujgOBDl(XZ{W(z|wBJi}#q+6t5N zLdU<8*zv>fh6kp1;87GLkm=af+1D|3Wn`qh{5pMs2cdRJ4hUJMIiRl+kqCpJMU$aP zQ8N?wNJ=t#f`?^d1r=UW)@20`%Fo zC{GP+i;B4bw2S$lH&n~c8Pzm1$(85#1qg;6I|e%nZ-BF3zphy71~?hdUx;5%@7Op6v9))J#h0qA)zW*;k~q3-QTEutF58K@l4El#2kEiV#-frSn7xNRB1V7rJxIB z^NT&P&g6(JPnX#)7ty7u@FzADqX;~{O;(=Cc0bqZ!Y(XkQzoN2ZS>B@siC~j56`l? zto>RaEjrlm36m64NADv6B~a{#0wVpr1P8w;x_&ofNI>ss7UkUc#!mM8sS z65jX_XfjwRVqhTkV0+=3V+Lc`eu1y8f6PWWuSoHHo+Qas zbl6`S9YgXa$3A*$XX2z^V-<9TFJ1Wv#_YsixR0*IR~*e~l8G^y%J1`^?xyzHuMMoF_34C`G6gK?EzIs^J*0&# zS_R=AJaqeO&c^stHLv4Qd=H{+&c!As4y@r4FD9!foavmGKX*^aecJXtN_3pJ!C-E6;0&w2gIT4<{L>49Msb+49h9N%#g6$&;cRc$6vn?f7n zSMw8_T52I!aGlI|()E{7q&7j>#CvRzPbtr!BEBi`Y8sABtIjgkip-q$o`*r3>8kzw z%qkI+hf&rpR0Ors*09zGBtkV=qnvpAD_1*$EnSEGTN`oyRvZ6^QtAJ6zWy4HrUY;T z8Y(#e9Dx7I)@H>0)2UKQ)K;TLke9#44_!&@Z5&KCfr2t6h(#goVOFRrJkO{3)@JCW z8DBJmEzbN5!V4CH-Why7?xZAL!Eib-nZn_I@R-42f3P|wrwbad&3`mcFy)Rv8g6jR&w)SY~dw?%*bp~Tt(O3cIma|s?n!Kpe>>Lr5swGWb4^G zjsW^C8l4Hs-W!oP{MU_%Hsy8Z6@62Jcbw`vnErLHjUKxjeN?_`n0c+t(av$o3KBT1@ExF{G~tI$1FK>HNs`PUt5iKKTo4*dN+#qtZgei{Ya9*V0ex0 zUmSSWKy$O-x||R3cQ`@l{~Vhkk+b@*F`0iW0FUgE1Q&n}{FrMsU!)Su2|iT3+ab6k z!!uN%sK5J})?|xqIO<@ul%nm)3eWoko^(MKn+n$crf%8d_P()D@Q=eLrO@rJuhp6zm56pd8$ z8W$aVM9AF_b@ESwUt}Cw{lOi4hWi3*vMlUFcZXpk9w60cUj7=K_N!7HbM=p;{x&G{ zcRAI+Y=SaCU&+DF)aIWuQ-kq{n@8nK@{m}$qo$?IiK@RbBa{jFp)WF;XSpJn55Euy zE$tKS&zvkak@rJMPl$`HD9wT$z`IPA#+VUTD4jmK7HDsMhP7>OOP)C3p*qqwR)0@FAfV|$(=7L^|81^ zS6oKpGD+Htl*N2hF6C(PjyZ0V{zX$~^)mT2bA(Ac6L^CY$4Bp)IRaDunj4~%%ZGI= zM^>80$8?L1)@70ZU3yP%M8hp%L^q{<@YFNI-TG=H%ixAPjxFU?#u(D$R)}mV6Tya(?D**Jc$O>& z8L7?X8E_WOkg-C=wi5D`yfcGj|Ay$zphO8nd9sNkf+~zQA?=R~!w6D)PD0 z5QvmTf5lw7;H|VY228n!M==Aap>Cof{-0gAKOs`hegBlm#yLZhCRKBwvOIcS-}-iK z!gv4y{hZ8qanqxwr)9vYSpic7ik<+OYzwp5;56u33uBt2JJrDETB<$9;Sw2*~1 z`$rzb z#Xt>U)E4kC+dcS}vhyi6KY|hNr&Eg4kKmDUov%cpN1yX35(iKKtf5Hi(x_;8$z-$l z4hhnPsxV9;^vA}vaT4*YSRy4fqrxpTR3=%{ZA;0hJPITEp(7mJS0c}`G==t;AnOES zm=5A-OanA|$+Tf+oc_(cWz0$)(T^I$VH~-tXif~L<>Z;O6 zht*im(CbvQxNB{3BkT236xrULYKAE2!?~GBo}}PTIchXvVf;tPu;cRt`XMIK1Bwh% zXk#u-V*}86Ch;Q3OcU+j$>qADE|NrGu&okeX1SX%>wm)d;#$Ccj%A2)Lv;l0^oBDo zPCPee?V&_wb(3d#>r9vA=7^^JbS`;8Hx9j4E+4<&HvdU6Js}^T!vZJ_+)}iaphr0g zC!0e_#MeQ-g>M!^T|F1TH{w(qr?wjA7*!BrmrS+@bBnWWC|$BNRzKjdY1VKMNzciC zym`>W>HcLPI_)zNfdrjufDL1KPeD6i=+%rYrNq{s3_SgRXnO}B%eFOLG_x`*ZQHgh zZQHhO+qSJr+qP|^veLHws`lBp&)Mg7@95~;cg2bsF=NbFvE~>*zh5wzrCjY4#t;M? zA^w>$y}+!wjXjOgh^4EfV%m6!uWzipd^wq3<}R)XUZJTqphki*b5s3Bh>O^kz)k55 zV}yC#(ydlj6agU_Q}x7C)@!QCxXvU7^iIpdk>&ITV3e_t>0H}sbkX4m$~?D(NeiL+ zDysRE+sin(gus!0C~+M@j%qYnxxnU5+FrCW&5hfPv+L^Q0e~>NIsOIeukr9-^TX}T zYj2jS&Y8ofGAE_bxJB^|98F2QDLmIrQQ5&{MxRWtL0NNY*YW)lakF=4VwFjp#b$rnVE z79{ISgDe-sZ%3q1@z5~ggUjJVQ}F0I!203(Y(Zg6Y5A{i!FmH?e}u?N;CDn57T}1G zaRtS?qHJGbFl`Olbw>~$)Yq1mm`oicISU3HkX>sN7ABW zpRq0=m>5&1o>HYQqBT{v$@fZE3h7H|`$34V03y_)Lr+)^k&fOwEoF7%EP8J`PK{6` z!x5+|s6e|~nWThbmU<#``G&W@%cm;XjPJ2gg{D)0F;Y>BCH;*8X8hRrj)c6E_It5{ zdvh+S-WxAS3J&xO0%c|jHa}RNnt3zKe9-qzgV-+dpgX54mqT8~csm_`;xf4H%`&!? zT(**$W$1Z*Ra(|iff5ce;bS_nHu&qZmsZe>Hq;jEUjNJSYlXOL1wb%smA8$!)e)mL zK$Yt?TKV_HmC6I+b{Ofi6As&ZJWcGuMbZ71vaw&^fw?Snl~w9qB>{JdCB`Q=Fz@L8 z>Hd{DLPSe)Y%Lc+(?yw-gW}NYps-8lURTr|qDUUTx152|JHzPf{K#v9%ys9%r)67r z1A%2GcE=nXQpYeKFVlq6yh#IwxoLT{5_aKn;dNJ%;owa0&;C1TYO%+kJ*@6Bc%w8r z%5DHd(R1NI1doIa7RqLqBfj$ ziRF{QXY2|I_0G8{hCPydp*u9s8S(Y;?+VNCdj$7C(%v^u@#o3ko1@4)ZJtTE3dwQ6 z=vib1BQ(C)&1lAmoA0Wyce}_wE!>z~JT0G*zF)*_0M69WYznwdZ#7uPsR}|do6$#W zI07vPQ6m(}!eR$Cg?Bh0ZY|T?0HMUMeF2%h+#xu`tdN`@7rt@>gGK-Y&Ld5ri=~QG z#J?FKxiRx2%Voizcc)Kdi6Cg>N1B()7vwWZYO9B0e?3~i1GwgCuI?{1b~Ho^(MTLn z0gQa444V!P9~qUEfxJrH0XFN=d>dJW)9{V+6m`vVlOPJN(B}C<-w!qriP8z7rrl~t zuX;lTS6~{osjkH=iCeFdA;EeD(VW))92DzABGC%sezs3`eL*FDKhj1dK8iQyE6WB~ z2EebZPF7~xnkrqX4{{%_wue|x9_+A1eK6CgU**40coNMZ3OyIAOaKyhQzc)ufCo*; zbL2aO!yY`GCHSTjq=8gGaYe9Fjb{X8bQjqGhnz7x-hXyUQSKSKM6RL`(vk0dvLHNx zeBNg~^7+R^j%J(H*Cr?cfD`op!3^$ygGmH`_m2OEL&R}!v&;4hA803DSBQgJN0_lBc&fotnAK{$= z@tq-;!K+0bIb~t*jX)SgnQU@5EhR;LFEc?^GgEzH1P_2goQIU2R%?rgoRYaUFpe)S zH_Z|XDiTT(3a)3M2Z}@ujn$V4RTjh)9f$)H^p8vjq!3yD)L$<&4e)ob%>UmDiilbL zUeU956t=PFGcYi6a4^$1vov#b`#+(PS@GY^vkgv`iWCLY(2c`6RarhD{c9lq693icAkpklCmXep%<$%L?-)D7z zCV5}$n`+8x)A0zbI`igJ<1HjuI(xLzM%SmVW@_%zoe*$=Bzf0X^tbgALnCe-Z{9Dm` zVZ4M4COzEnCnAfQsDd_h;+zRwi0?v`Iv^L4T^N#CVF{mjQhNd#9mA>VdBM9nm(ocd zZZ2-w$qLmSa-u-v9Op;&^Lga{B~O<(&=m%U64g(;$YT2JL09P#ta8a##6Et9YMD@V zVh{%A)|5)fxUBK$I%#7D z(uKK5F9}Es;^k~dL6)&73}R;noQw_P`2fSRz2SoCA)uShcDqZkagw7>J?n;K!XLS5 zO$t1(J1eUDiKAeN_S;fxTpaatwJRhGpGY!`q^0MyB@6aPoJ{5*drOx*r)=BdZY}wi zUg9MW6GXUUO*g1@p6vtW67(!eo6 zHX$%&BS`Uma5FD9t_D-cA41iy%Lf z?x}qj4h&@?PO7B0DmCZ@6Wew1QJ0e@UHbOx@7>WU-yv`P_3p@j3v~S##Y+E4?AOR% z(arWhBEEml1UNn@QZ>X~5|Gg65z?jMb;8f z;I|DP&t!X?>O7oSejFzCwZLL4VP&;vLFsOjDu#Eys7fNAyB5`` zgm_Xe3hmjpxTb2BG#l4r=Apj(EZ^;RL%Z!X8lRot#!D0DJrQMLA&whW9Zb$M^2k2D zIn>#6ZE34ON-3PvT!<4S9MwSv^96Bjze>vL@~APp-*VC~H6SvetY`ldWi%?K#>eIw z9MvjK{wWc}GOs2uLaLJ7@`)ilbkUM_!U@CxL)|YS$r}|1cxox8y4Ki`wXVDFn`^!6 zL&9PGKu3SA7+KFCiUM*MO7Q|@9d)8QS#wQ**Hp^{#F>8e!N(s8M{VKylH%7Xfc!<0 zDg0Y%oyp&v#9uUvppm7KiJqg;KaNJ+$kNh{-$>7z=s$gk-`>p7#OOaB`ZFa=Uh8-0 zjH_S7!eWu&3xu#geca2>;K1e^et4-UzoB66)F-+#&9Ov1JeZM|{9+MR5c{@BcfS9vj?rmWZp zsP*!#7L+AXc%pde0BMYq0P+tP4LV8r>UUjN14ji3+Sd4P9O;t&8U}gOVKDO(p#GZl z^2J?nSfu4mU6*c=ZRSmj@1G{qb+cQ?L?nmn1wz_`(^!?XO9OK6-jP`@gn_6x$(9c; z>QgqW^V|4AB1ChQ?Ry~|7HSEie97BhI8Ih8yupK^XMVNAK!zE4DZ-4NBUx80CYm#$ zjk1a7YStMm!FOsD`X$g;UIap$cYaM1b}u>I@$x3nJ1+)4*#s!)Pq^Z!B5}3cqD$4t z!+CBg8Vfb@j>k=*dJ}cx3Kn%5;T$5-c`wx_P?#?0O+7tyejnsg^pg4zqIMWTP!X<) zddCOaL%UFvuJPOR8E=e=jG4W+iDqBw)ja)D$dhN6Q~UYz?l6B7%Sr5wO6o6SQ3U>9 zNZAnAm$Ik-=lwr}r&$SGe`Er5ub;x2MkvMN5|H7M$)1Jb`3vC)h7m8q(RbLaLsw{D zrng%_`-H)E9R+ZsAu`j~zW82#$PKNY7BUZ~F>24Ht*$D5DJQBa9V9bYjBQBk5e9KUjY^q`yF~D1=&_IZy{ zf*65}D<@%sZX}zZlkQ%`IidwSQ^uU_1CeW6YTSdkNZbea#!{yh)igt2u=ub87SLWNq{4#3&c>xZE*(

9+L;F>>}b$}~ZQ9}-JF+K?y;DqZ#<5seXjWiq2V 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�&r8B!mworj^Rg+aj36R;?E>w}C3WdSt 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

o^Zwi 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 literal 0 HcmV?d00001 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index a8d309b24e..4ab125693c 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,4 +12,3 @@ # Project target. target=android-19 -android.library.reference.1=../MPChartLib diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 9cf0ad6700..395f33e645 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -31,7 +31,7 @@ import java.util.ArrayList; -public class LineChartActivity extends DemoBase implements OnSeekBarChangeListener, +public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, OnChartGestureListener, OnChartValueSelectedListener { private LineChart mChart; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java new file mode 100644 index 0000000000..1c0b942373 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -0,0 +1,328 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Legend; +import com.github.mikephil.charting.utils.Legend.LegendForm; +import com.github.mikephil.charting.utils.XLabels; +import com.github.mikephil.charting.utils.YLabels; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private LineChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + + mSeekBarX.setProgress(45); + mSeekBarY.setProgress(100); + + mSeekBarY.setOnSeekBarChangeListener(this); + mSeekBarX.setOnSeekBarChangeListener(this); + + mChart = (LineChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + + mChart.setUnit(" $"); + mChart.setDrawUnitsInChart(true); + + // if enabled, the chart will always start at zero on the y-axis + mChart.setStartAtZero(false); + + // disable the drawing of values into the chart + mChart.setDrawYValues(false); + + mChart.setDrawBorder(true); + mChart.setBorderPositions(new BorderPosition[] { + BorderPosition.BOTTOM + }); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable value highlighting + mChart.setHighlightEnabled(true); + + // enable touch gestures + mChart.setTouchEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + mChart.setDrawGridBackground(false); + mChart.setDrawVerticalGrid(false); + mChart.setDrawHorizontalGrid(false); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(true); + + // set an alternative background color + mChart.setBackgroundColor(Color.GRAY); + + // add data + setData(45, 100); + + mChart.animateX(2500); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + // get the legend (only possible after setting data) + Legend l = mChart.getLegend(); + + // modify the legend ... + // l.setPosition(LegendPosition.LEFT_OF_CHART); + l.setForm(LegendForm.LINE); + l.setTypeface(tf); + l.setTextColor(Color.WHITE); + + XLabels xl = mChart.getXLabels(); + xl.setTypeface(tf); + xl.setTextColor(Color.WHITE); + + YLabels yl = mChart.getYLabels(); + yl.setTypeface(tf); + yl.setTextColor(Color.WHITE); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.line, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + if (mChart.isDrawYValuesEnabled()) + mChart.setDrawYValues(false); + else + mChart.setDrawYValues(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleFilled: { + + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawFilledEnabled()) + set.setDrawFilled(false); + else + set.setDrawFilled(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCircles: { + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawCirclesEnabled()) + set.setDrawCircles(false); + else + set.setDrawCircles(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawCubicEnabled()) + set.setDrawCubic(false); + else + set.setDrawCubic(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + if (mChart.isStartAtZeroEnabled()) + mChart.setStartAtZero(false); + else + mChart.setStartAtZero(true); + + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleAdjustXLegend: { + XLabels xLabels = mChart.getXLabels(); + + if (xLabels.isAdjustXLabelsEnabled()) + xLabels.setAdjustXLabels(false); + else + xLabels.setAdjustXLabels(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleFilter: { + + // the angle of filtering is 35° + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + + // mChart.saveToGallery("title"+System.currentTimeMillis()) + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + + // redraw + mChart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add((i) + ""); + } + + ArrayList yVals = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = (range + 1); + float val = (float) (Math.random() * mult) + 3;// + (float) + // ((mult * + // 0.1) / 10); + yVals.add(new Entry(val, i)); + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(ColorTemplate.getHoloBlue()); + set1.setLineWidth(2f); + set1.setCircleSize(4f); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); // add the datasets + + // create a data object with the datasets + LineData data = new LineData(xVals, dataSets); + + // set data + mChart.setData(data); + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex) { + Log.i("Entry selected", e.toString()); + } + + @Override + public void onNothingSelected() { + Log.i("Nothing selected", "Nothing selected."); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index dbe38c8936..6e91dac71e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -27,7 +27,8 @@ import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; -import com.xxmassdeveloper.mpchartexample.LineChartActivity; +import com.xxmassdeveloper.mpchartexample.LineChartActivity1; +import com.xxmassdeveloper.mpchartexample.LineChartActivity2; import com.xxmassdeveloper.mpchartexample.LineChartActivityColored; import com.xxmassdeveloper.mpchartexample.ListViewBarChartActivity; import com.xxmassdeveloper.mpchartexample.ListViewMultiChartActivity; @@ -56,7 +57,8 @@ protected void onCreate(Bundle savedInstanceState) { ArrayList objects = new ArrayList(); - objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); + objects.add(new ContentItem("Line Chart 1", "A simple demonstration of the linechart.")); + objects.add(new ContentItem("Line Chart 2", "Another simple demonstration of the linechart.")); objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); @@ -113,39 +115,42 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { switch (pos) { case 0: - i = new Intent(this, LineChartActivity.class); + i = new Intent(this, LineChartActivity1.class); startActivity(i); break; case 1: - i = new Intent(this, BarChartActivity.class); + i = new Intent(this, LineChartActivity2.class); startActivity(i); break; case 2: - i = new Intent(this, PieChartActivity.class); + i = new Intent(this, BarChartActivity.class); startActivity(i); break; case 3: - i = new Intent(this, ScatterChartActivity.class); + i = new Intent(this, PieChartActivity.class); startActivity(i); break; case 4: - i = new Intent(this, StackedBarActivity.class); + i = new Intent(this, ScatterChartActivity.class); startActivity(i); break; case 5: - i = new Intent(this, AnotherBarActivity.class); + i = new Intent(this, StackedBarActivity.class); startActivity(i); break; case 6: - i = new Intent(this, MultiLineChartActivity.class); + i = new Intent(this, AnotherBarActivity.class); startActivity(i); - break; case 7: - i = new Intent(this, BarChartActivityMultiDataset.class); + i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; case 8: + i = new Intent(this, BarChartActivityMultiDataset.class); + startActivity(i); + break; + case 9: // i = new Intent(this, DrawChartActivity.class); // startActivity(i); @@ -155,39 +160,39 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { b.setPositiveButton("OK", null); b.create().show(); break; - case 9: + case 10: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 10: + case 11: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 11: + case 12: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 12: + case 13: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 13: + case 14: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 14: + case 15: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 15: + case 16: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 16: + case 17: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 17: + case 18: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index ee7c6ff0de..5c8c6fae70 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -775,6 +775,9 @@ protected void drawBorder() { for (int i = 0; i < mBorderPositions.length; i++) { + if (mBorderPositions[i] == null) + continue; + switch (mBorderPositions[i]) { case LEFT: mDrawCanvas.drawLine(mOffsetLeft, mOffsetTop, mOffsetLeft, getHeight() @@ -1452,6 +1455,24 @@ public BorderPosition[] getBorderPositions() { return mBorderPositions; } + /** + * Sets the width of the border surrounding the chart in dp. + * + * @param width + */ + public void setBorderWidth(int width) { + mBorderPaint.setStrokeWidth(Utils.convertDpToPixel(width)); + } + + /** + * Sets the color of the border surrounding the chart. + * + * @param color + */ + public void setBorderColor(int color) { + mBorderPaint.setColor(color); + } + /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index d933ba3bc0..0d93fa88e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -92,7 +92,15 @@ protected void init() { protected void calcMinMax(boolean fixedValues) { super.calcMinMax(fixedValues); + // additional handling for space (default 15% space) + // float space = Math.abs(mDeltaY / 100f * 15f); + + if (mYChartMax <= 0) + mYChartMax = 1f; + mYChartMin = 0; + + mDeltaY = Math.abs(mYChartMax - mYChartMin); } @Override @@ -103,7 +111,6 @@ public void prepare() { prepareXLabels(); } - @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); @@ -291,7 +298,9 @@ private void drawLimitLines() { private void prepareYLabels() { int labelCount = mYLabels.getLabelCount(); - double range = mData.getYMax() - mYChartMin; + + double max = mData.getYMax() > 0 ? mData.getYMax() : 1.0; + double range = max - mYChartMin; double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -304,7 +313,7 @@ private void prepareYLabels() { } double first = Math.ceil(mYChartMin / interval) * interval; - double last = Utils.nextUp(Math.floor(mData.getYMax() / interval) * interval); + double last = Utils.nextUp(Math.floor(max / interval) * interval); double f; int n = 0; @@ -640,7 +649,7 @@ public boolean isDrawXLabelsEnabled() { protected float getRequiredBottomOffset() { return mLegendLabelPaint.getTextSize() * 6.5f; } - + @Override protected float getRequiredBaseOffset() { return mXLabels.mLabelWidth; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 204a305dab..991fc7734a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -336,7 +336,7 @@ public static String[] convertStrings(ArrayList strings) { /** * Replacement for the Math.nextUp(...) method that is only available in - * HONEYCOMB and higher. + * HONEYCOMB and higher. Dat's some seeeeek sheeet. * * @param d * @return From c1358af6fa22d390feba46ad7f1b112f73162b85 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 20 Nov 2014 13:42:34 -0600 Subject: [PATCH 0010/1390] Adjust gradle to be more compatible. Eliminate the dependency on nineoldandroids --- MPChartLib/build.gradle | 2 +- .../src/com/github/mikephil/charting/charts/Chart.java | 7 +++---- .../github/mikephil/charting/charts/PieRadarChartBase.java | 6 +++--- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index da161a1a83..ca011a6094 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -6,7 +6,7 @@ android { // resourcePrefix 'mpcht' defaultConfig { applicationId 'com.github.mikephil.charting' - minSdkVersion 8 + minSdkVersion 14 targetSdkVersion 19 versionCode 1 versionName '1.0' diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 66e91a0305..72c42f8cbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.charts; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.content.ContentValues; import android.content.Context; import android.graphics.Bitmap; @@ -39,9 +41,6 @@ import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; import java.io.File; import java.io.FileOutputStream; @@ -56,7 +55,7 @@ * @author Philipp Jahoda */ public abstract class Chart>> extends View - implements AnimatorUpdateListener, ChartInterface { + implements ValueAnimator.AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 7dedb9ce68..c93c0be60e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -1,10 +1,11 @@ package com.github.mikephil.charting.charts; +import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Matrix; -import android.graphics.PointF; import android.graphics.Paint.Align; +import android.graphics.PointF; import android.util.AttributeSet; import android.view.MotionEvent; @@ -12,9 +13,8 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; -import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.nineoldandroids.animation.ObjectAnimator; +import com.github.mikephil.charting.utils.Utils; /** * Baseclass of PieChart and RadarChart. diff --git a/build.gradle b/build.gradle index f0b9d9492f..51c21ca66e 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:0.12.+' + classpath 'com.android.tools.build:gradle:0.14.2' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1e61d1fd3a..50bf2b703b 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Thu Nov 20 13:33:11 CST 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip From 806fdfe989dd1c2ae47e2f24f3cc545ce90309b6 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 20 Nov 2014 14:13:47 -0600 Subject: [PATCH 0011/1390] refactor line chart to be more extendable --- .../mikephil/charting/charts/LineChart.java | 240 ++++++++++-------- 1 file changed, 129 insertions(+), 111 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index ce39c8e3c7..cb5cffed3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -146,147 +146,165 @@ protected void drawData() { // if drawing cubic lines is enabled if (dataSet.isDrawCubicEnabled()) { + drawCubic(dataSet, entries); - // get the color that is specified for this position from the - // DataSet - mRenderPaint.setColor(dataSet.getColor()); - - float intensity = dataSet.getCubicIntensity(); - - // the path for the cubic-spline - Path spline = new Path(); - - ArrayList points = new ArrayList(); - for (Entry e : entries) - points.add(new CPoint(e.getXIndex(), e.getVal())); - - if (points.size() > 1) { - for (int j = 0; j < points.size() * mPhaseX; j++) { - - CPoint point = points.get(j); - - if (j == 0) { - CPoint next = points.get(j + 1); - point.dx = ((next.x - point.x) * intensity); - point.dy = ((next.y - point.y) * intensity); - } - else if (j == points.size() - 1) { - CPoint prev = points.get(j - 1); - point.dx = ((point.x - prev.x) * intensity); - point.dy = ((point.y - prev.y) * intensity); - } - else { - CPoint next = points.get(j + 1); - CPoint prev = points.get(j - 1); - point.dx = ((next.x - prev.x) * intensity); - point.dy = ((next.y - prev.y) * intensity); - } - - // create the cubic-spline path - if (j == 0) { - spline.moveTo(point.x, point.y * mPhaseY); - } - else { - CPoint prev = points.get(j - 1); - spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * mPhaseY, point.x - - point.dx, - (point.y - point.dy) * mPhaseY, point.x, point.y * mPhaseY); - } - } - } + // draw normal (straight) lines + } else { + drawLinear(dataSet, entries); + } - // if filled is enabled, close the path - if (dataSet.isDrawFilledEnabled()) { + mRenderPaint.setPathEffect(null); + } + } - float fillMin = mFillFormatter - .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); + protected void drawCubic(LineDataSet dataSet, ArrayList entries) + { + // get the color that is specified for this position from the + // DataSet + mRenderPaint.setColor(dataSet.getColor()); + + float intensity = dataSet.getCubicIntensity(); + + // the path for the cubic-spline + Path spline = new Path(); + + ArrayList points = new ArrayList(); + for (Entry e : entries) + points.add(new CPoint(e.getXIndex(), e.getVal())); - spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); - spline.lineTo(0, fillMin); - spline.close(); + if (points.size() > 1) { + for (int j = 0; j < points.size() * mPhaseX; j++) { - mRenderPaint.setStyle(Paint.Style.FILL); - } else { - mRenderPaint.setStyle(Paint.Style.STROKE); - } + CPoint point = points.get(j); + + if (j == 0) { + CPoint next = points.get(j + 1); + point.dx = ((next.x - point.x) * intensity); + point.dy = ((next.y - point.y) * intensity); + } + else if (j == points.size() - 1) { + CPoint prev = points.get(j - 1); + point.dx = ((point.x - prev.x) * intensity); + point.dy = ((point.y - prev.y) * intensity); + } + else { + CPoint next = points.get(j + 1); + CPoint prev = points.get(j - 1); + point.dx = ((next.x - prev.x) * intensity); + point.dy = ((next.y - prev.y) * intensity); + } - mTrans.pathValueToPixel(spline); + // create the cubic-spline path + if (j == 0) { + spline.moveTo(point.x, point.y * mPhaseY); + } + else { + CPoint prev = points.get(j - 1); + spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * mPhaseY, point.x + - point.dx, + (point.y - point.dy) * mPhaseY, point.x, point.y * mPhaseY); + } + } + } - mDrawCanvas.drawPath(spline, mRenderPaint); + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + drawCubicFill(dataSet, entries, spline); + } else { + mRenderPaint.setStyle(Paint.Style.STROKE); + } - // draw normal (straight) lines - } else { + mTrans.pathValueToPixel(spline); - mRenderPaint.setStyle(Paint.Style.STROKE); + mDrawCanvas.drawPath(spline, mRenderPaint); - // more than 1 color - if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { + } - float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); + protected void drawCubicFill(LineDataSet dataSet, ArrayList entries, Path spline) + { + float fillMin = mFillFormatter + .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); - for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { + spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); + spline.lineTo(0, fillMin); + spline.close(); - if (isOffContentRight(valuePoints[j])) - break; + mRenderPaint.setStyle(Paint.Style.FILL); + } - // make sure the lines don't do shitty things outside - // bounds - if (j != 0 && isOffContentLeft(valuePoints[j - 1]) - && isOffContentTop(valuePoints[j + 1]) - && isOffContentBottom(valuePoints[j + 1])) - continue; + protected void drawLinear(LineDataSet dataSet, ArrayList entries) + { + mRenderPaint.setStyle(Paint.Style.STROKE); - // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 2)); + // more than 1 color + if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], - valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); - } + float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); - } else { // only one color per dataset + for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { - mRenderPaint.setColor(dataSet.getColor()); + if (isOffContentRight(valuePoints[j])) + break; - Path line = generateLinePath(entries); - mTrans.pathValueToPixel(line); + // make sure the lines don't do shitty things outside + // bounds + if (j != 0 && isOffContentLeft(valuePoints[j - 1]) + && isOffContentTop(valuePoints[j + 1]) + && isOffContentBottom(valuePoints[j + 1])) + continue; - mDrawCanvas.drawPath(line, mRenderPaint); - } + // get the color that is set for this line-segment + mRenderPaint.setColor(dataSet.getColor(j / 2)); - mRenderPaint.setPathEffect(null); + mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], + valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); + } - // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { - // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, - // valuePoints.length, valuePoints, 0, - // null, 0, null, 0, null, 0, 0, paint); + } else { // only one color per dataset - mRenderPaint.setStyle(Paint.Style.FILL); + mRenderPaint.setColor(dataSet.getColor()); - mRenderPaint.setColor(dataSet.getFillColor()); - // filled is drawn with less alpha - mRenderPaint.setAlpha(dataSet.getFillAlpha()); + Path line = generateLinePath(entries); + mTrans.pathValueToPixel(line); - // mRenderPaint.setShader(dataSet.getShader()); + mDrawCanvas.drawPath(line, mRenderPaint); + } - Path filled = generateFilledPath(entries, - mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, - mYChartMin)); + mRenderPaint.setPathEffect(null); - mTrans.pathValueToPixel(filled); + // if drawing filled is enabled + if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { + drawLinearFill(dataSet, entries); + } + } + + protected void drawLinearFill(LineDataSet dataSet, ArrayList entries) + { + // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, + // valuePoints.length, valuePoints, 0, + // null, 0, null, 0, null, 0, 0, paint); - mDrawCanvas.drawPath(filled, mRenderPaint); + mRenderPaint.setStyle(Paint.Style.FILL); - // restore alpha - mRenderPaint.setAlpha(255); - // mRenderPaint.setShader(null); - } - } + mRenderPaint.setColor(dataSet.getFillColor()); + // filled is drawn with less alpha + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + + // mRenderPaint.setShader(dataSet.getShader()); + + Path filled = generateFilledPath(entries, + mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, + mYChartMin)); + + mTrans.pathValueToPixel(filled); + + mDrawCanvas.drawPath(filled, mRenderPaint); + + // restore alpha + mRenderPaint.setAlpha(255); + // mRenderPaint.setShader(null); + } - mRenderPaint.setPathEffect(null); - } - } - /** * Generates the path that is used for filled drawing. * From d1cb68e707837b40c1dff89e77fe40e691e5749a Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 20 Nov 2014 14:14:11 -0600 Subject: [PATCH 0012/1390] refactor line chart for more extensibility --- .../mikephil/charting/charts/LineChart.java | 240 ++++++++++-------- 1 file changed, 129 insertions(+), 111 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index ce39c8e3c7..cb5cffed3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -146,147 +146,165 @@ protected void drawData() { // if drawing cubic lines is enabled if (dataSet.isDrawCubicEnabled()) { + drawCubic(dataSet, entries); - // get the color that is specified for this position from the - // DataSet - mRenderPaint.setColor(dataSet.getColor()); - - float intensity = dataSet.getCubicIntensity(); - - // the path for the cubic-spline - Path spline = new Path(); - - ArrayList points = new ArrayList(); - for (Entry e : entries) - points.add(new CPoint(e.getXIndex(), e.getVal())); - - if (points.size() > 1) { - for (int j = 0; j < points.size() * mPhaseX; j++) { - - CPoint point = points.get(j); - - if (j == 0) { - CPoint next = points.get(j + 1); - point.dx = ((next.x - point.x) * intensity); - point.dy = ((next.y - point.y) * intensity); - } - else if (j == points.size() - 1) { - CPoint prev = points.get(j - 1); - point.dx = ((point.x - prev.x) * intensity); - point.dy = ((point.y - prev.y) * intensity); - } - else { - CPoint next = points.get(j + 1); - CPoint prev = points.get(j - 1); - point.dx = ((next.x - prev.x) * intensity); - point.dy = ((next.y - prev.y) * intensity); - } - - // create the cubic-spline path - if (j == 0) { - spline.moveTo(point.x, point.y * mPhaseY); - } - else { - CPoint prev = points.get(j - 1); - spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * mPhaseY, point.x - - point.dx, - (point.y - point.dy) * mPhaseY, point.x, point.y * mPhaseY); - } - } - } + // draw normal (straight) lines + } else { + drawLinear(dataSet, entries); + } - // if filled is enabled, close the path - if (dataSet.isDrawFilledEnabled()) { + mRenderPaint.setPathEffect(null); + } + } - float fillMin = mFillFormatter - .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); + protected void drawCubic(LineDataSet dataSet, ArrayList entries) + { + // get the color that is specified for this position from the + // DataSet + mRenderPaint.setColor(dataSet.getColor()); + + float intensity = dataSet.getCubicIntensity(); + + // the path for the cubic-spline + Path spline = new Path(); + + ArrayList points = new ArrayList(); + for (Entry e : entries) + points.add(new CPoint(e.getXIndex(), e.getVal())); - spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); - spline.lineTo(0, fillMin); - spline.close(); + if (points.size() > 1) { + for (int j = 0; j < points.size() * mPhaseX; j++) { - mRenderPaint.setStyle(Paint.Style.FILL); - } else { - mRenderPaint.setStyle(Paint.Style.STROKE); - } + CPoint point = points.get(j); + + if (j == 0) { + CPoint next = points.get(j + 1); + point.dx = ((next.x - point.x) * intensity); + point.dy = ((next.y - point.y) * intensity); + } + else if (j == points.size() - 1) { + CPoint prev = points.get(j - 1); + point.dx = ((point.x - prev.x) * intensity); + point.dy = ((point.y - prev.y) * intensity); + } + else { + CPoint next = points.get(j + 1); + CPoint prev = points.get(j - 1); + point.dx = ((next.x - prev.x) * intensity); + point.dy = ((next.y - prev.y) * intensity); + } - mTrans.pathValueToPixel(spline); + // create the cubic-spline path + if (j == 0) { + spline.moveTo(point.x, point.y * mPhaseY); + } + else { + CPoint prev = points.get(j - 1); + spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * mPhaseY, point.x + - point.dx, + (point.y - point.dy) * mPhaseY, point.x, point.y * mPhaseY); + } + } + } - mDrawCanvas.drawPath(spline, mRenderPaint); + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + drawCubicFill(dataSet, entries, spline); + } else { + mRenderPaint.setStyle(Paint.Style.STROKE); + } - // draw normal (straight) lines - } else { + mTrans.pathValueToPixel(spline); - mRenderPaint.setStyle(Paint.Style.STROKE); + mDrawCanvas.drawPath(spline, mRenderPaint); - // more than 1 color - if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { + } - float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); + protected void drawCubicFill(LineDataSet dataSet, ArrayList entries, Path spline) + { + float fillMin = mFillFormatter + .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); - for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { + spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); + spline.lineTo(0, fillMin); + spline.close(); - if (isOffContentRight(valuePoints[j])) - break; + mRenderPaint.setStyle(Paint.Style.FILL); + } - // make sure the lines don't do shitty things outside - // bounds - if (j != 0 && isOffContentLeft(valuePoints[j - 1]) - && isOffContentTop(valuePoints[j + 1]) - && isOffContentBottom(valuePoints[j + 1])) - continue; + protected void drawLinear(LineDataSet dataSet, ArrayList entries) + { + mRenderPaint.setStyle(Paint.Style.STROKE); - // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 2)); + // more than 1 color + if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], - valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); - } + float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); - } else { // only one color per dataset + for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { - mRenderPaint.setColor(dataSet.getColor()); + if (isOffContentRight(valuePoints[j])) + break; - Path line = generateLinePath(entries); - mTrans.pathValueToPixel(line); + // make sure the lines don't do shitty things outside + // bounds + if (j != 0 && isOffContentLeft(valuePoints[j - 1]) + && isOffContentTop(valuePoints[j + 1]) + && isOffContentBottom(valuePoints[j + 1])) + continue; - mDrawCanvas.drawPath(line, mRenderPaint); - } + // get the color that is set for this line-segment + mRenderPaint.setColor(dataSet.getColor(j / 2)); - mRenderPaint.setPathEffect(null); + mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], + valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); + } - // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { - // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, - // valuePoints.length, valuePoints, 0, - // null, 0, null, 0, null, 0, 0, paint); + } else { // only one color per dataset - mRenderPaint.setStyle(Paint.Style.FILL); + mRenderPaint.setColor(dataSet.getColor()); - mRenderPaint.setColor(dataSet.getFillColor()); - // filled is drawn with less alpha - mRenderPaint.setAlpha(dataSet.getFillAlpha()); + Path line = generateLinePath(entries); + mTrans.pathValueToPixel(line); - // mRenderPaint.setShader(dataSet.getShader()); + mDrawCanvas.drawPath(line, mRenderPaint); + } - Path filled = generateFilledPath(entries, - mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, - mYChartMin)); + mRenderPaint.setPathEffect(null); - mTrans.pathValueToPixel(filled); + // if drawing filled is enabled + if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { + drawLinearFill(dataSet, entries); + } + } + + protected void drawLinearFill(LineDataSet dataSet, ArrayList entries) + { + // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, + // valuePoints.length, valuePoints, 0, + // null, 0, null, 0, null, 0, 0, paint); - mDrawCanvas.drawPath(filled, mRenderPaint); + mRenderPaint.setStyle(Paint.Style.FILL); - // restore alpha - mRenderPaint.setAlpha(255); - // mRenderPaint.setShader(null); - } - } + mRenderPaint.setColor(dataSet.getFillColor()); + // filled is drawn with less alpha + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + + // mRenderPaint.setShader(dataSet.getShader()); + + Path filled = generateFilledPath(entries, + mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, + mYChartMin)); + + mTrans.pathValueToPixel(filled); + + mDrawCanvas.drawPath(filled, mRenderPaint); + + // restore alpha + mRenderPaint.setAlpha(255); + // mRenderPaint.setShader(null); + } - mRenderPaint.setPathEffect(null); - } - } - /** * Generates the path that is used for filled drawing. * From 473134d39a36809bc4c980dbdcf675ec203ff6e0 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 20 Nov 2014 14:37:39 -0600 Subject: [PATCH 0013/1390] Convert chart from View to ViewGroup --- .../src/com/github/mikephil/charting/charts/Chart.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 72c42f8cbf..f06c318bf5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -22,6 +22,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; import com.github.mikephil.charting.data.BarData; @@ -54,7 +55,8 @@ * * @author Philipp Jahoda */ -public abstract class Chart>> extends View +public abstract class Chart>> + extends ViewGroup implements ValueAnimator.AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; @@ -2176,7 +2178,6 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); prepareContentRect(); From cd2b2ac39c9ff84807bb1dac9bb750947fc77469 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 20 Nov 2014 14:40:09 -0600 Subject: [PATCH 0014/1390] Refactor Chart from View to ViewGroup --- .../src/com/github/mikephil/charting/charts/Chart.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 66e91a0305..857f79e255 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -20,6 +20,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; import com.github.mikephil.charting.data.BarData; @@ -55,7 +56,8 @@ * * @author Philipp Jahoda */ -public abstract class Chart>> extends View +public abstract class Chart>> + extends ViewGroup implements AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; @@ -2177,7 +2179,6 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); prepareContentRect(); From 63d1a1547fce4847b180a12e1e98ca3e0aa4210a Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Fri, 21 Nov 2014 12:24:01 -0600 Subject: [PATCH 0015/1390] AB-400: Integrated MPAndroidChart as a submodule @nopush --- MPChartLib/build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index ca011a6094..571951d2bc 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,3 +1,15 @@ +buildscript { + repositories { + maven { url 'http://10.10.0.246:8081/nexus/content/groups/astdev' } + mavenLocal() + } + dependencies { + classpath 'com.android.tools.build:gradle:0.14.0' + classpath 'com.jakewharton.hugo:hugo-plugin:1.1.+' + classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.+' + } +} + apply plugin: 'android-library' android { From b257057a661a2abc215845c27234e72599e1cda8 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 24 Nov 2014 11:03:23 -0600 Subject: [PATCH 0016/1390] make CPoint accessible to subclasses --- .../src/com/github/mikephil/charting/charts/LineChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index cb5cffed3e..78a89b6549 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -108,7 +108,7 @@ protected void drawHighlights() { * * @author Philipp Jahoda */ - private class CPoint { + protected class CPoint { public float x = 0f; public float y = 0f; From 2cb955268e1862c730650bf3bb2470315cd63fde Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 24 Nov 2014 11:03:52 -0600 Subject: [PATCH 0017/1390] Make CPoint accessible to subclass --- .../src/com/github/mikephil/charting/charts/LineChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index cb5cffed3e..78a89b6549 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -108,7 +108,7 @@ protected void drawHighlights() { * * @author Philipp Jahoda */ - private class CPoint { + protected class CPoint { public float x = 0f; public float y = 0f; From d4a0a4cf857c52718f1ab1ce439da6547217ea1d Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 24 Nov 2014 12:45:11 -0600 Subject: [PATCH 0018/1390] Make Chart tell children to do layout --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f06c318bf5..a992fd92cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -2181,6 +2181,10 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto prepareContentRect(); + for (int i=0; i < getChildCount(); i++) + { + getChildAt(i).layout(left, top, right, bottom); + } // // prepareContentRect(); // Log.i(LOG_TAG, From 98eacbcdb0ead1a2b27060fca848c934bc81a27a Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 24 Nov 2014 12:46:42 -0600 Subject: [PATCH 0019/1390] Make Chart pass layout on to children --- .../src/com/github/mikephil/charting/charts/Chart.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 857f79e255..b18d0b307a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -2182,6 +2182,11 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto prepareContentRect(); + for (int i=0; i < getChildCount(); i++) + { + getChildAt(i).layout(left, top, right, bottom); + } + // // prepareContentRect(); // Log.i(LOG_TAG, From 20cde649b4a06a6b04d8b61cef26681dcc8f32f9 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Tue, 25 Nov 2014 12:33:56 -0600 Subject: [PATCH 0020/1390] Make BarChart more extendable --- .../src/com/github/mikephil/charting/charts/BarChart.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 7ca4934e5b..64d04edcc7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -3,7 +3,6 @@ import android.content.Context; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; @@ -279,7 +278,7 @@ protected void drawData() { * @param y the y-position * @param barspace the space between bars */ - private void prepareBar(float x, float y, float barspace) { + protected void prepareBar(float x, float y, float barspace) { float spaceHalf = barspace / 2f; float left = x + spaceHalf; From 6f55d8ea43a90b7d8068075715145f612e883d4e Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Tue, 25 Nov 2014 12:52:54 -0600 Subject: [PATCH 0021/1390] make members protected --- .../src/com/github/mikephil/charting/charts/BarChart.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 64d04edcc7..542a204e80 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -54,13 +54,13 @@ public class BarChart extends BarLineChartBase { * if set to true, a grey area is darawn behind each bar that indicates the * maximum value */ - private boolean mDrawBarShadow = true; + protected boolean mDrawBarShadow = true; /** the rect object that is used for drawing the bar shadow */ - private RectF mBarShadow = new RectF(); + protected RectF mBarShadow = new RectF(); /** the rect object that is used for drawing the bars */ - private RectF mBarRect = new RectF(); + protected RectF mBarRect = new RectF(); public BarChart(Context context) { super(context); From a0243154b2ad93a7f49a51cd826cd5346d3a7917 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Tue, 25 Nov 2014 12:53:28 -0600 Subject: [PATCH 0022/1390] Make member bar objects protected --- .../src/com/github/mikephil/charting/charts/BarChart.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 64d04edcc7..542a204e80 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -54,13 +54,13 @@ public class BarChart extends BarLineChartBase { * if set to true, a grey area is darawn behind each bar that indicates the * maximum value */ - private boolean mDrawBarShadow = true; + protected boolean mDrawBarShadow = true; /** the rect object that is used for drawing the bar shadow */ - private RectF mBarShadow = new RectF(); + protected RectF mBarShadow = new RectF(); /** the rect object that is used for drawing the bars */ - private RectF mBarRect = new RectF(); + protected RectF mBarRect = new RectF(); public BarChart(Context context) { super(context); From cb78c15a4334a5e16703fcd1887f83a15a9e7c1b Mon Sep 17 00:00:00 2001 From: Pieter Meiresone Date: Thu, 27 Nov 2014 00:09:49 +0100 Subject: [PATCH 0023/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index 602ccd3d85..ad905f78f2 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -14,3 +14,6 @@ https://play.google.com/store/apps/details?id=com.tutorialsface.phoneaddiction AS Sales Management https://play.google.com/store/apps/details?id=com.armsoft.mtrade + +Notification Analyser +https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser From c6349bdc823d1c9b8bc7cc02ffe92784217b2211 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 1 Dec 2014 11:08:45 -0600 Subject: [PATCH 0024/1390] set WillNotDraw to false - needed since now a ViewGroup --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index b18d0b307a..a8048a44e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -225,6 +225,7 @@ public Chart(Context context, AttributeSet attrs, int defStyle) { */ protected void init() { + setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_SOFTWARE, null); mTrans = new Transformer(); From 0d5db0e1526e1a0d249163ede6eff9ee9e0b4b52 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Mon, 1 Dec 2014 11:13:23 -0600 Subject: [PATCH 0025/1390] Fix willNotDraw in Chart.java --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 1 + gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index a992fd92cc..ea731fe693 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -224,6 +224,7 @@ public Chart(Context context, AttributeSet attrs, int defStyle) { */ protected void init() { + setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_SOFTWARE, null); mTrans = new Transformer(); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 50bf2b703b..9ffc7dee6c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Nov 20 13:33:11 CST 2014 +#Mon Dec 01 11:12:36 CST 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip From c5de8516e438d5f7d65d68b7cef26934ffefc4b8 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Wed, 3 Dec 2014 14:21:11 -0600 Subject: [PATCH 0026/1390] Add extensibility elements to BarCharts --- .../mikephil/charting/charts/BarChart.java | 19 ++++++++++++------- .../charting/charts/BarLineChartBase.java | 2 +- .../charting/renderer/Transformer.java | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 542a204e80..b3f499f9ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -384,13 +384,8 @@ protected void drawValues() { // calculate the correct offset depending on the draw position of // the value - if (mDrawValueAboveBar) { - posOffset = -Utils.convertDpToPixel(5); - negOffset = Utils.calcTextHeight(mValuePaint, "8") * 1.5f; - } else { - posOffset = Utils.calcTextHeight(mValuePaint, "8") * 1.5f; - negOffset = -Utils.convertDpToPixel(5); - } + posOffset = getPositiveYOffset(mDrawValueAboveBar); + negOffset = getNegativeYOffset(mDrawValueAboveBar); for (int i = 0; i < mData.getDataSetCount(); i++) { @@ -468,6 +463,16 @@ protected void drawValues() { } } + protected float getPositiveYOffset(boolean drawAboveValueBar) + { + return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, "8") * 1.5f); + } + + protected float getNegativeYOffset(boolean drawAboveValueBar) + { + return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils.convertDpToPixel(5)); + } + /** * Draws a value at the specified x and y position. * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 5c8c6fae70..40e5151ec5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -485,7 +485,7 @@ protected void prepareXLabels() { * * @return */ - private void prepareYLabels() { + protected void prepareYLabels() { float yMin = 0f; float yMax = 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java index e23156c77c..8a772bdcf4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -22,7 +22,7 @@ public class Transformer { /** matrix to map the values to the screen pixels */ - private Matrix mMatrixValueToPx = new Matrix(); + protected Matrix mMatrixValueToPx = new Matrix(); /** matrix for handling the different offsets of the chart */ private Matrix mMatrixOffset = new Matrix(); From e1b5fc1aa1bcc39207edb3d7c8eb1dfb752b6342 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 4 Dec 2014 10:48:52 -0600 Subject: [PATCH 0027/1390] Add HorizontalBarChart and ColumnToBarTransformer --- .../charting/charts/HorizontalBarChart.java | 169 ++++++++++++++++++ .../renderer/ColumnToBarTransformer.java | 66 +++++++ 2 files changed, 235 insertions(+) create mode 100644 MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java new file mode 100644 index 0000000000..0781c79198 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -0,0 +1,169 @@ +package com.github.mikephil.charting.charts; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; + +import com.github.mikephil.charting.renderer.ColumnToBarTransformer; +import com.github.mikephil.charting.utils.YLabels; + +public class HorizontalBarChart extends ColumnChart +{ + public HorizontalBarChart(Context context) + { + super(context); + } + + public HorizontalBarChart(Context context, AttributeSet attrs) + { + super(context, attrs); + } + + public HorizontalBarChart(Context context, AttributeSet attrs, + int defStyle) + { + super(context, attrs, defStyle); + } + + @Override + protected void init() + { + super.init(); + setDrawXLabels(false); + setDrawYLabels(true); + mTrans = new ColumnToBarTransformer(); + mValuePaint.setTextAlign(Paint.Align.LEFT); + } + + /** + * Prepares a bar for drawing on the specified x-index and y-position. Also + * prepares the shadow-bar if enabled. + * + * @param x the x-position + * @param y the y-position + * @param barspace the space between bars + */ + @Override + protected void prepareBar(float x, float y, float barspace) { + + super.prepareBar(x, y, barspace); + float spaceHalf = barspace / 2f; + + float top = x + spaceHalf; + float bottom = x + 1f - spaceHalf; + + mBarRect.set(0, top, y, bottom); + + mTrans.rectValueToPixel(mBarRect, mPhaseY); + + // if a shadow is drawn, prepare it too + if (mDrawBarShadow) { + mBarShadow.set(mBarRect.left, mOffsetTop, mBarRect.right, getHeight() - mOffsetBottom); + } + } + + @Override + protected void drawXLabels(float yPos) + { + if (!mDrawXLabels) return; + + mXLabelPaint.setTextAlign(Paint.Align.RIGHT); + // pre allocate to save performance (dont allocate in loop) + float[] position = new float[] { + 0f, 0f + }; + + int step = mData.getDataSetCount(); + + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + + position[1] = i * step + i * mData.getGroupSpace() + + mData.getGroupSpace() / 2f; + + // center the text + if (mXLabels.isCenterXLabelsEnabled()) + position[1] += (step / 2f); + + mTrans.pointValuesToPixel(position); + + if (position[1] >= mOffsetTop && position[1] <= getHeight() - mOffsetBottom) + { + String label = mData.getXVals().get(i); + + mDrawCanvas.drawText(label, mOffsetLeft-10, position[1], mXLabelPaint); + } + } + } + + private static String TALL_VALUE = "100%"; + @Override + protected float getPositiveYOffset(boolean drawAboveValueBar) + { + Rect bounds = new Rect(); + mValuePaint.getTextBounds(TALL_VALUE,0,TALL_VALUE.length(),bounds); + + return bounds.height()/2; + } + + @Override + protected float getNegativeYOffset(boolean drawAboveValueBar) + { + return getPositiveYOffset(drawAboveValueBar); + } + + /** + * Sets up the y-axis labels. Computes the desired number of labels between + * the two given extremes. Unlike the papareXLabels() method, this method + * needs to be called upon every refresh of the view. + * + * @return + */ + @Override + protected void prepareYLabels() + { + mYLabels = new XLabelsAsYLabels(); + } + + private class XLabelsAsYLabels extends YLabels + { + /** + * Returns the longest formatted label (in terms of characters) the y-labels + * contain. + * + * @return + */ + @Override + public String getLongestLabel() + { + String longest = ""; + + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) + { + String text = mData.getXVals().get(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } + + /** + * Returns the formatted y-label at the specified index. This will either + * use the auto-formatter or the custom formatter (if one is set). + * + * @param index + * @return + */ + @Override + public String getFormattedLabel(int index) + { + super.getFormattedLabel(index); + if (index < 0) + return ""; + + return mData.getXVals().get(index); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java new file mode 100644 index 0000000000..bd164b7632 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java @@ -0,0 +1,66 @@ +package com.github.mikephil.charting.renderer; + +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.renderer.Transformer; + +import java.util.ArrayList; + +public class ColumnToBarTransformer extends Transformer +{ + /** + * Prepares the matrix that transforms values to pixels. + * + * @param chart + */ + @Override + public void prepareMatrixValuePx(ChartInterface chart) + { + float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); + float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); + + // setup all matrices + mMatrixValueToPx.reset(); + mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + mMatrixValueToPx.postScale(scaleX, -scaleY); + } + + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the BARCHART. + * + * @param entries + * @param dataSet the dataset index + * @return + */ + public float[] generateTransformedValuesBarChart(ArrayList entries, + int dataSet, BarData bd, float phaseY) { + + float[] valuePoints = new float[entries.size() * 2]; + + int setCount = bd.getDataSetCount(); + float space = bd.getGroupSpace(); + + for (int j = 0; j < valuePoints.length; j += 2) { + + int index = j/2; + Entry e = entries.get(index); + + //TODO: Need to find a better value than 1, should be dependant on yMax, I think + float x = e.getVal() + 1; + // calculate the y-position, depending on datasetcount + float y = e.getXIndex() + (index * (setCount - 1)) + dataSet + 0.5f + space * index + + space / 2f; + + valuePoints[j] = x; + valuePoints[j + 1] = y; + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } + +} From 2b380fe188cf73b6c7fdc3dca66c06645cdf2dae Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 4 Dec 2014 11:24:29 -0600 Subject: [PATCH 0028/1390] Fix extend --- .../com/github/mikephil/charting/charts/HorizontalBarChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 0781c79198..e7a4fb5543 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -8,7 +8,7 @@ import com.github.mikephil.charting.renderer.ColumnToBarTransformer; import com.github.mikephil.charting.utils.YLabels; -public class HorizontalBarChart extends ColumnChart +public class HorizontalBarChart extends BarChart { public HorizontalBarChart(Context context) { From 140a1ea5cfa628453c28e8e09639678a13725553 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 4 Dec 2014 11:38:18 -0600 Subject: [PATCH 0029/1390] Fix bug in HorizontalBarChart --- .../com/github/mikephil/charting/charts/HorizontalBarChart.java | 2 +- .../mikephil/charting/renderer/ColumnToBarTransformer.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 0781c79198..e7a4fb5543 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -8,7 +8,7 @@ import com.github.mikephil.charting.renderer.ColumnToBarTransformer; import com.github.mikephil.charting.utils.YLabels; -public class HorizontalBarChart extends ColumnChart +public class HorizontalBarChart extends BarChart { public HorizontalBarChart(Context context) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java index bd164b7632..d4540b8ab5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.renderer.Transformer; import java.util.ArrayList; From 49456e835f58a10779d25692706b78169e4e893f Mon Sep 17 00:00:00 2001 From: Dale King Date: Tue, 9 Dec 2014 21:35:05 -0500 Subject: [PATCH 0030/1390] Update build.gradle for Android Studio 1.0 --- MPChartLib/build.gradle | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 571951d2bc..3ba0294b55 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -4,7 +4,7 @@ buildscript { mavenLocal() } dependencies { - classpath 'com.android.tools.build:gradle:0.14.0' + classpath 'com.android.tools.build:gradle:1.0.0' classpath 'com.jakewharton.hugo:hugo-plugin:1.1.+' classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.+' } @@ -17,7 +17,6 @@ android { buildToolsVersion '19.1.0' // resourcePrefix 'mpcht' defaultConfig { - applicationId 'com.github.mikephil.charting' minSdkVersion 14 targetSdkVersion 19 versionCode 1 @@ -34,7 +33,7 @@ android { } buildTypes { release { - runProguard false + shrinkResources false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } From d6c5fe0ae69201af5bb3547b253c636a47bbfcf2 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Wed, 10 Dec 2014 14:08:18 -0600 Subject: [PATCH 0031/1390] upgrade to AS1 --- MPChartExample/build.gradle | 1 - build.gradle | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 31e0a5f1a3..690b755ac5 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -23,7 +23,6 @@ android { buildTypes { release { - runProguard false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } diff --git a/build.gradle b/build.gradle index 51c21ca66e..7130c34e51 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:0.14.2' + classpath 'com.android.tools.build:gradle:1.0.0' } } From 9068563a2bb91d3873f953da201f931a7179ea39 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 10:53:52 +0100 Subject: [PATCH 0032/1390] Update build.gradle --- MPChartLib/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index da161a1a83..789647c281 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -5,7 +5,6 @@ android { buildToolsVersion '19.1.0' // resourcePrefix 'mpcht' defaultConfig { - applicationId 'com.github.mikephil.charting' minSdkVersion 8 targetSdkVersion 19 versionCode 1 @@ -22,7 +21,7 @@ android { } buildTypes { release { - runProguard false + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } From 249725fe964ca4ba121f9f8f6f6a6d9c02b9bd1d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 10:54:31 +0100 Subject: [PATCH 0033/1390] Update build.gradle --- MPChartExample/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 31e0a5f1a3..b1ee191035 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -4,7 +4,6 @@ android { compileSdkVersion 19 buildToolsVersion '19.1.0' defaultConfig { - applicationId 'com.xxmassdeveloper.mpchartexample' minSdkVersion 16 targetSdkVersion 19 versionCode 29 @@ -23,7 +22,7 @@ android { buildTypes { release { - runProguard false + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } From 61755d4d7726beede34333fde7a7089ec801c41c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 18:11:24 +0100 Subject: [PATCH 0034/1390] Update build.gradle From 42f6fb69325f9e12e461c7c47022c67cae850153 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 18:12:09 +0100 Subject: [PATCH 0035/1390] Update build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f0b9d9492f..7130c34e51 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:0.12.+' + classpath 'com.android.tools.build:gradle:1.0.0' } } From e893ca108a9ed26dc4d2c802899f2f6604ae037d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 18:13:02 +0100 Subject: [PATCH 0036/1390] Update build.gradle --- MPChartLib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 789647c281..c488aa2412 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'android-library' android { compileSdkVersion 19 - buildToolsVersion '19.1.0' + buildToolsVersion '21.1.1' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 8 From ea1944edfec05bad922b6913bfbaf31e418d2833 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Dec 2014 18:14:09 +0100 Subject: [PATCH 0037/1390] Update build.gradle --- MPChartLib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index c488aa2412..782707587c 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,4 +1,4 @@ -apply plugin: 'android-library' +apply plugin: 'com.android.library' android { compileSdkVersion 19 From 73724d17cfdd0be4876ac4038f494940edd05373 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 16 Dec 2014 11:30:57 +0100 Subject: [PATCH 0038/1390] Fixed issue #255 and #258. --- .../com/github/mikephil/charting/charts/Chart.java | 12 ++++++------ .../com/github/mikephil/charting/data/ChartData.java | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 66e91a0305..2138c8f762 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1441,18 +1441,18 @@ public PointF getCenterOffsets() { } /** - * sets the size of the description text in pixels, min 7f, max 14f + * sets the size of the description text in pixels, min 6f, max 16f * * @param size */ public void setDescriptionTextSize(float size) { - if (size > 14f) - size = 14f; - if (size < 7f) - size = 7f; + if (size > 16f) + size = 16f; + if (size < 6f) + size = 6f; - mInfoPaint.setTextSize(Utils.convertDpToPixel(size)); + mDescPaint.setTextSize(Utils.convertDpToPixel(size)); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index a735abcbdb..9c4f2e27e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -415,7 +415,7 @@ public T getDataSetByLabel(String label, boolean ignorecase) { int index = getDataSetIndexByLabel(mDataSets, label, ignorecase); - if (index <= 0 || index >= mDataSets.size()) + if (index < 0 || index >= mDataSets.size()) return null; else return mDataSets.get(index); From ade2a8f603572cd1de297d6ebb5aa2515571be95 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Wed, 17 Dec 2014 14:51:39 -0600 Subject: [PATCH 0039/1390] remove reliance on xLabelModulus. --- .../github/mikephil/charting/charts/HorizontalBarChart.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index e7a4fb5543..1bef4c165d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -76,7 +76,7 @@ protected void drawXLabels(float yPos) int step = mData.getDataSetCount(); - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i ++) { position[1] = i * step + i * mData.getGroupSpace() + mData.getGroupSpace() / 2f; @@ -138,7 +138,7 @@ public String getLongestLabel() { String longest = ""; - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) + for (int i = 0; i < mData.getXValCount(); i ++) { String text = mData.getXVals().get(i); From 95d7eaae4699d2351ac1710251a60b10dd14aad6 Mon Sep 17 00:00:00 2001 From: Pingan Yi Date: Thu, 18 Dec 2014 18:14:18 +0800 Subject: [PATCH 0040/1390] Fix wrong position of linear legend form --- MPChartLib/src/com/github/mikephil/charting/utils/Legend.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java b/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java index 392561b8cc..f8d22eb9c5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java @@ -344,7 +344,7 @@ public void drawForm(Canvas c, float x, float y, Paint p, int index) { c.drawRect(x, y, x + mFormSize, y + mFormSize, p); break; case LINE: - c.drawLine(x - half, y + half, x + half, y + half, p); + c.drawLine(x, y + half, x + mFormSize, y + half, p); break; } } From 85ed5e001d4a7abcbdc77d07b96f5194514584c0 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Thu, 18 Dec 2014 13:50:56 -0600 Subject: [PATCH 0041/1390] Add flexibility to offsets --- .../charting/charts/BarLineChartBase.java | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 40e5151ec5..4c3f55eee9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -365,11 +365,11 @@ protected void calculateOffsets() { // all required offsets are calculated, now find largest and apply float min = Utils.convertDpToPixel(11f); - mOffsetBottom = Math.max(min, xbottom + legendBottom); - mOffsetTop = Math.max(min, xtop); + mOffsetBottom = calcOffsetBottom(min, xbottom + legendBottom); + mOffsetTop = calcOffsetTop(min, xtop); - mOffsetLeft = Math.max(min, yleft); - mOffsetRight = Math.max(min, yright + legendRight); + mOffsetLeft = calcOffsetLeft(min, yleft); + mOffsetRight = calcOffsetRight(min, yright + legendRight); if (mLegend != null) { @@ -384,6 +384,50 @@ protected void calculateOffsets() { prepareMatrix(); } + /** + * returns the maximum of the two values. Allows subclasses to independently change this offset + * @param min + * @param left + * @return + */ + protected float calcOffsetLeft(float min, float left) + { + return Math.max(min, left); + } + + + /** + * returns the maximum of the two values. Allows subclasses to independently change this offset + * @param min + * @param top + * @return + */ protected float calcOffsetTop(float min, float top) + { + return Math.max(min, top); + } + + + /** + * returns the maximum of the two values. Allows subclasses to independently change this offset + * @param min + * @param right + * @return + */ protected float calcOffsetRight(float min, float right) + { + return Math.max(min, right); + } + + + /** + * returns the maximum of the two values. Allows subclasses to independently change this offset + * @param min + * @param bottom + * @return + */ protected float calcOffsetBottom(float min, float bottom) + { + return Math.max(min, bottom); + } + /** * Calculates the offsets that belong to the legend, this method is only * relevant when drawing into the chart. It can be used to refresh the From ae428c2ef749b8d6470b481ef87789fabe57cb26 Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Fri, 26 Dec 2014 11:00:35 -0600 Subject: [PATCH 0042/1390] Undo changes not meant for pull request --- MPChartExample/build.gradle | 2 +- MPChartLib/build.gradle | 20 ++++--------------- .../mikephil/charting/charts/Chart.java | 10 +++++----- .../charting/charts/PieRadarChartBase.java | 3 ++- Projects_using_MPAndroidChart.txt | 3 +++ gradle/wrapper/gradle-wrapper.properties | 4 ++-- 6 files changed, 17 insertions(+), 25 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 690b755ac5..b1ee191035 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -4,7 +4,6 @@ android { compileSdkVersion 19 buildToolsVersion '19.1.0' defaultConfig { - applicationId 'com.xxmassdeveloper.mpchartexample' minSdkVersion 16 targetSdkVersion 19 versionCode 29 @@ -23,6 +22,7 @@ android { buildTypes { release { + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 3ba0294b55..782707587c 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,23 +1,11 @@ -buildscript { - repositories { - maven { url 'http://10.10.0.246:8081/nexus/content/groups/astdev' } - mavenLocal() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' - classpath 'com.jakewharton.hugo:hugo-plugin:1.1.+' - classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.+' - } -} - -apply plugin: 'android-library' +apply plugin: 'com.android.library' android { compileSdkVersion 19 - buildToolsVersion '19.1.0' + buildToolsVersion '21.1.1' // resourcePrefix 'mpcht' defaultConfig { - minSdkVersion 14 + minSdkVersion 8 targetSdkVersion 19 versionCode 1 versionName '1.0' @@ -33,7 +21,7 @@ android { } buildTypes { release { - shrinkResources false + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 652201c527..af52c5d265 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1,8 +1,6 @@ package com.github.mikephil.charting.charts; -import android.animation.ObjectAnimator; -import android.animation.ValueAnimator; import android.content.ContentValues; import android.content.Context; import android.graphics.Bitmap; @@ -42,6 +40,9 @@ import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; +import com.nineoldandroids.animation.ObjectAnimator; +import com.nineoldandroids.animation.ValueAnimator; +import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; import java.io.File; import java.io.FileOutputStream; @@ -55,9 +56,8 @@ * * @author Philipp Jahoda */ -public abstract class Chart>> - extends ViewGroup - implements ValueAnimator.AnimatorUpdateListener, ChartInterface { +public abstract class Chart>> extends View + implements AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index c93c0be60e..177348f330 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.charts; -import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Matrix; import android.graphics.Paint.Align; @@ -15,6 +14,8 @@ import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.Legend.LegendPosition; +import com.nineoldandroids.animation.ObjectAnimator; /** * Baseclass of PieChart and RadarChart. diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index 602ccd3d85..ad905f78f2 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -14,3 +14,6 @@ https://play.google.com/store/apps/details?id=com.tutorialsface.phoneaddiction AS Sales Management https://play.google.com/store/apps/details?id=com.armsoft.mtrade + +Notification Analyser +https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9ffc7dee6c..1e61d1fd3a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Dec 01 11:12:36 CST 2014 +#Wed Apr 10 15:27:10 PDT 2013 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip +distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip From 30e301ffd8b05d216a13459fe8e073cd61b1838b Mon Sep 17 00:00:00 2001 From: Robert Schmid Date: Fri, 26 Dec 2014 19:37:58 -0600 Subject: [PATCH 0043/1390] Simple Horizontal bar chart example --- MPChartExample/AndroidManifest.xml | 1 + .../layout/activity_horizontalbarchart.xml | 60 +++++++++++++++++++ .../mpchartexample/BarChartActivity.java | 9 ++- .../HorizontalBarChartActivity.java | 22 +++++++ .../notimportant/MainActivity.java | 48 ++++++++------- 5 files changed, 117 insertions(+), 23 deletions(-) create mode 100644 MPChartExample/res/layout/activity_horizontalbarchart.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index cd08251e3f..60adb59fd4 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -27,6 +27,7 @@ + diff --git a/MPChartExample/res/layout/activity_horizontalbarchart.xml b/MPChartExample/res/layout/activity_horizontalbarchart.xml new file mode 100644 index 0000000000..c4f255598e --- /dev/null +++ b/MPChartExample/res/layout/activity_horizontalbarchart.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 7798663282..0baccf7cf2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -36,7 +36,7 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; + protected BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; @@ -45,7 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart); + setContentView(getLayout()); tvX = (TextView) findViewById(R.id.tvXMax); tvY = (TextView) findViewById(R.id.tvYMax); @@ -123,6 +123,11 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawLegend(false); } + protected int getLayout() + { + return R.layout.activity_barchart; + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java new file mode 100644 index 0000000000..e95f5001e7 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -0,0 +1,22 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.os.Bundle; + +public class HorizontalBarChartActivity extends BarChartActivity +{ + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + //FIXME: Bar Shadow is not yet supported + mChart.setDrawBarShadow(false); + } + + @Override + protected int getLayout() + { + return R.layout.activity_horizontalbarchart; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 6e91dac71e..66004618fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -26,6 +26,7 @@ import com.xxmassdeveloper.mpchartexample.CandleStickChartActivity; import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity; +import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; import com.xxmassdeveloper.mpchartexample.LineChartActivity2; @@ -59,7 +60,8 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Line Chart 1", "A simple demonstration of the linechart.")); objects.add(new ContentItem("Line Chart 2", "Another simple demonstration of the linechart.")); - objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); + objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); + objects.add(new ContentItem("Horizontal Bar Chart", "A simple demonstration of the horizontal bar chart.")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Stacked Bar Chart", @@ -122,35 +124,39 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, LineChartActivity2.class); startActivity(i); break; - case 2: - i = new Intent(this, BarChartActivity.class); - startActivity(i); - break; - case 3: + case 2: + i = new Intent(this, BarChartActivity.class); + startActivity(i); + break; + case 3: + i = new Intent(this, HorizontalBarChartActivity.class); + startActivity(i); + break; + case 4: i = new Intent(this, PieChartActivity.class); startActivity(i); break; - case 4: + case 5: i = new Intent(this, ScatterChartActivity.class); startActivity(i); break; - case 5: + case 6: i = new Intent(this, StackedBarActivity.class); startActivity(i); break; - case 6: + case 7: i = new Intent(this, AnotherBarActivity.class); startActivity(i); break; - case 7: + case 8: i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; - case 8: + case 9: i = new Intent(this, BarChartActivityMultiDataset.class); startActivity(i); break; - case 9: + case 10: // i = new Intent(this, DrawChartActivity.class); // startActivity(i); @@ -160,39 +166,39 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { b.setPositiveButton("OK", null); b.create().show(); break; - case 10: + case 11: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 11: + case 12: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 12: + case 13: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 13: + case 14: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 14: + case 15: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 15: + case 16: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 16: + case 17: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 17: + case 18: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 18: + case 19: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; From cd5e3a42b7e05620b3adef95e7a898b36d1a14f9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 28 Dec 2014 11:23:42 +0100 Subject: [PATCH 0044/1390] Removed resource folder. --- .../libs/mpandroidchartlibrary-1-7-4.jar | Bin 1283092 -> 0 bytes MPChartExample/project.properties | 1 + .../HorizontalBarChartActivity.java | 1 + MPChartLib/res/values/colors.xml | 54 ------------------ MPChartLib/res/values/dimens.xml | 3 - MPChartLib/res/values/strings.xml | 4 -- MPChartLib/res/values/styles.xml | 18 ------ .../mikephil/charting/charts/Chart.java | 16 +++--- .../charting/charts/HorizontalBarChart.java | 14 ++++- .../mikephil/charting/utils/XLabels.java | 7 +++ 10 files changed, 30 insertions(+), 88 deletions(-) delete mode 100644 MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar delete mode 100644 MPChartLib/res/values/colors.xml delete mode 100644 MPChartLib/res/values/dimens.xml delete mode 100644 MPChartLib/res/values/strings.xml delete mode 100644 MPChartLib/res/values/styles.xml diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-4.jar deleted file mode 100644 index 749ac4603232191f02a07c4565fc6d8b6fd276b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1283092 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

{?YkMaY-AN<9_BpNWi1lhdUPx1jOQBMtlCf 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�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±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
1tTuG2L2<}*J-+~*nx)#bF?Pa>%zD0{ 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

9+L;F>>}b$}~ZQ9}-JF+K?y;DqZ#<5seXjWiq2V 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�&r8B!mworj^Rg+aj36R;?E>w}C3WdSt z9=|_G=uE9sXCsQ>Z>AKjO$vl+rD6h)>-O7bksy$L0hzezN{p* zhXLcNcHqvXMFC`tFz~(aJ2+Vp^f;v;k&lACQ%phc46X~CPP%30E84Q8P>UX14zJ^m z6Q^h5svNY*3ntW<<)Lbt$w2rMKght?7>Vl1g~|#)4<}W6Tvbe5nkf-RI`?E2>)GU0 zQ0?7ow1-6&gAvT3jS$wa6=J1ehIjx}SGrO=l_cWzz?nQ~t1HzsnkVgp+}Jzt;iv5( zx`wr58UFrxeo%q56RZK(OSpCM781noN2=$bHo#q$T#a@@B2vHUV<+{7UO`ftP;9a6 zb;)R3;6+$#oenG^@y3=*5Tb&#YcqtfmV#20@h^d;FFaUTxMk$lDUoz9y=b=9|* zDs0i~r@xhw{E4TDw+CetZw1>R`Go3u-epJfjWj!JMfN~4(P*ZuvBSDH%8PdjTC1G5 zKA)(NC_tHEOPH%Um!vu&r(_-Le`e|l+Sz+SQob~7;Fkw`i)MMYs$@BIChar+4zpTQ z`IhL}qbh85d8j-p79}0so1= z#mPRYy>~H14W*-!8Vlmjnmfxqq%w)wSA!hl&z$>oV3zqDQX2?FCpo;!4@$XZGU*3B zlRZogQoFT-{OPN}LF+gr(|}V|EOyRpU6fHh(qeF-!$Nf%MXa3`o2I!RA}?Pm;#sc} zGaC}yC~~aHybrEX_uYa_74|wX$!3t5uMkn7BG(W?4oiBsfc5e)tFJ$CKO>^aJpKNC z^f~j8syTxxq49pDbh<%jk*dtF8Yo@(6vgSlv7#Zj8Q1B^Q+?~GOVem3Q> zO9D32g|yQ-Y-Jv9lGCz*4k_g=_EjwFw26e?CE3+_Fe?U~>#`zTq&8Ks7Cw`oBw>U; zbsafZmAHNclY@WsYE*urLq#1-Tf@lF>WK~}&Jq(Do|TryU^1(6#WZ%^iHUkd3SP0R zdlR(o;?fRjxz*$Z-Oc%OGWViLhv8a*U+$RGV~iiH=ACF|QO(3zs1zcFFxxa8+NgIAb(iPtTt0{ z?GTg5S0QL^WVbsOdTjkHCXSGbS?%9*#zkkakv+`7(cyJQcl?GpElBK7LghR7yktKN z*iVDT+ZcVmpHhRWHQ_;37@*;(wW4M`HG>Qjw+xe&9S#$pcHxNl7FFvbrY;G~6IQg@YnyICSL=yBy0L z$^MIKU>@tJLFuN@#$|m`?&$~%Qa5Lqq21;eN(I(u^ey7ozx}donq%J*im_CGol1I@J zc<$x|rugAKeL|Zb>IqZ-AfesS7X9qqq*Me>UH_aqiHNHSK(rAIY9lhaR?3O0 zOV{Z}FdRn2HX#bCcB>)>sF(BX%U3rixd}NbJSS7#xTsA3X-Txpr_lFUpH7^~OXrqM zClr7w9o^K*9vp3{^&`9t(j$BeY^Hga}>IPRx>H~gjDTX zwrO@DV?&rmXKXsH1%bqGT2c_qfCZ3*_~7BbWNQcx$W;dwc)Ae5VLA`}S>^$#iy*C2U zS-nRhEnce$x(|mYUbA6#R&Ia8*0^K7mS=u;!SE;U;e$LA!}6mw`X%n=uzWUTehP>9 z&D|;?UYQlWs(p5%^z>R`>7oOD%h>x-a{SPd_!jNK!rDPyYw3Q1e=7~tuzrdr_dGG( z_8cDe@V;gVe2WqEyf8KKo4acb{8+k+jef;JBEL2XW1)JCiP+MkDus*U0a;=td5%e$ zV4dlv3m;*rjB1xDBu(-~m$Rl<&Y_TrvSP`gp0Y$+nq*hc!9<%{vPc!IVNK1A&X&p+ zcyeY^5Aa0O?X}29haP*G1NEU^K_Hd}%H!x{oJt{;x1`s}6XC%%4JOcD%-6{eYK|d^ ztz^WB$6$6cp5=)O4lTE0)+1>U{J9Am!a!h5kce!VXfTdH^Y?crT5{Cah~#9LHPpLg zF*40bN=*?9;Y@N3{V+78%BqFPppO_Wulkt!Z7MYw_0(j2v1SLVM6JebAh$S7JV`6e zh7nU#sXk6P^-4__#R^w4e@gc7cgeO`TJ=g-(4%oHA_!g`lG^xpWWn<#wpUKBNQaUs zkx8)d1$Sj4CLq|zC#ZarEK+`q0kLX=D^XFPZNZjQDg4!dvj$)bORn*cN;Ghupdy%i zGe3RIGpm$0qZw zD)<|to7uy9P1d?HB9z?f%wg(MRKTlhSh9v(H^_6Bi@9b))?e@T*Vcn9k76>yIfKer zGO&%I6w~MAR^T{$?e>Svv$0_R*b|*lUJKWvCq-`QcJXY6fv%B;u zD)tXr!sZ(cc&zVS7$zPI14qT}PYgKZn<3m&s0?D#FvQSb*vjFB~nN z=OuAf<+BO;0K~*d44={v>8j5tsE@{l{#X&90-SJkP53u<8Dz)}RYy-{1`9-an)wXU zD#=Nk5M{`fL}{{_JZT0FMQC~%v!TGFYZJAIEhV~{0u)^}OgBX;Ts8@3dIU>Y8&ykO zT4P-FG1m6yENg>di4Sgx;hlL1Jb6jDI%Ps$_Gg@V0zz@O2EoB_wkk_pv#L?%k3#lP za6$*K9Pdo$I_b1IB{wmU_-fmnaoUOr>w2L8~ zUhBXI%Jh5mi}ynkLSVRg$FyAM>9SlG@UpgrHXxgEmrKf2{H2~LMyv|*+?6GHgcv%61K@m}H`(vL>DRY+YrD`R7 z=Vq^Q#CT8_jXABqI@(aJ6Ic@-Fv_tHucA>5&fBhQWUx>&G%^rO1NlQ{#5dy3JW!%3 zUZ_JD+iw&WUvq_B_-*FNIiq1}d_;Yz7s%ietxVU2qbh6etJg6W5Ez{!6mpLY+=CbH zF=VyFX(~h%ees&=V~)&->5S1c)_Df!x-Jc=xbqD1vj>;Dzs6lU*y{P-GV#SAP)ga2 zpw+9Tqx)wPhur#VCP$NHgNbPn)x^03)ER8kut~*3?{DMAqU}BUic1{?zuK0~iWX16 zI{Hhws{TgF$ARw~Bg?v$2c2EE$r+lhq{*A{pj^ZLqx&1pmz~i$HpDhqYBaV_b>Ud6 zs%H?B5el76RTO{HF2A6AMN+lucUaWU)8Q4Q_bY#)>~22?IZ|h3>UOrKNoa;-QMwr} zkmeepiJU*x9LwHAA^#2lL!sY}W%wwBGL>JGgeD84q9prmM9r!fHgq}z^D|i2#wFUZ z&y8$KL-|C2CuN$k_l9g?qe7frn{gmrZtR}{rK94%$g58lzq~Ho&qL$Mc0^q3&_8-v z>(g%u#ch~3Be5coE@!ox2i4r0(9h_aBu;V=72NRx?fVT`Hf}C9S)IEk_CPMqLWio- zAEZ$JK6MCirb+&KHqO)-SIK(Zw0+WqoL(iSshVi%owkRDnNYlwSku1HKtg9npCucz8v)*`9G?oLTsiDG~TKKzTFE4w%5_0Bz}6_JJBA ze_afQe^4)A@B@1*(C738SbhRGxx@PP$@6atg5o3UTDq|JG>cbV@4d7yp3}b#*?ywd zxFq+76k-_myy@coV7=TyN{Q0Kpl3RLCs1GtlgefPNqpBJy8^Lm{L?B|x`nR56_&<# zqeRi+iP3I1k1+lvREi;ZWTAXzpuO{uI-qptA^k8h*+cj3lJlntx?~qQ@u5|RWqSRta`;ov?C#R=~)Op~?GLT^sGSb7C#+IAbUkLk!iN zw2HbkA5FML^&&STrARen_e1^MAwr~>AS643P8<2~y-lQf>w|cxe#Rp%nnP4g z`jq{}uqi@F-}o$5blXy>R-Q7XXtAM?krY&77R!?{NFts|nOi=ucF7U*smd_P(6~S| zt90RZZV0Pr&}Gz76>8ltrD6s6!5GL?f0J@Z1U@&g664G%&=g?M6=kfZQ(oq?kf#W( ziiJAx;`Y%xLvM?)jh1~1aY*40bG}pP7Jb|)y<_N> zfZu|_)|=qxOTKeVaY*9Y?hTqQ?of_q6Dt*~GbLIKioG zE%^eeb=rREWEP;y16ek9#LQ?^ad>O)=Nme0s2384n#1}?#2|p}sS)!quA8Z>0M`2p-Ju1)f zhUu~e4Pz@s0F6++(F(hPTcnGmX?--_vG5~GkW;BkfSeI3Z{U-&YFEW@a-T;udc~c^ zXO$#S%pS9>;twjeUZ$1Q-#2UM*X9XxXlIq)mVq^gMQ3gZZd`c>xW)+}2gA!|rIPVn zfRVW7%T=>a9wz}%>j=OI((H#ol|y;^K)wvSe+g(u*KEW?KPS*W`geN9fp^vK`Ngb@ zOr5TEotsN6Clp(I0aBx*|sRyX$I zTFV?0GjBlF9S-&>&q>6|oQR%KkZ$kPBdm8&cR2W&RwlacpxP<7dt7%U{(_Wyr0y{H zBk%m#hq4TR?%E?1>q13inlA?tx%Jp_5bY~X2YuPnN$U%hV#Uav+x~oKJGh=cyBp{A zy9iI-aYCzv3oYGX8PIRid%v#|&RVLs$Rm?X3d*nl@-TVmthqgd`}J#{;6LGMo&Oza z%)b#){uQ$Pe+j7k_utMg|8f^>Qq{4;7D3@Xu)Z8zV<~O~;x2;Kk3c@Kh6xdzuUWL| z>l6N)p$rkkr6IRPdZA<06~0dX4dhoagBmN!)62~d%d#?0X0cUPs!9U!@P4~(8Ds-Ud>eX25QIpD-KMe3ui?Z`>n`M@8 zN>^{>n0prs+QK~GuL}Hzq<-}osHIg;M@2rj<4VbiGqZD14>7S^4RT455`sEL5k4v4 z#SQcl?5gy7!dDORbBY5i@~1wbS~ypaAE{Nr@|ys@@L(eMpmBc`n(HF^pgJ${QG94HP8eQDO251f;HOwTm42&2DI5^=Alu7qPwzUKTIRki23tnewq2?V^ z+l;IlM*9dlQI`(6%FPp@VUPLp61qRxm1z~>Z*R;2>$p0(I;*A47O&i}mJk2^*i#!0^TB#_He++jgG__Dw#C z{fnRF4oo_56Y?lFIS3lK+9Z~AuwVW__e0ZpNFA0dY7di9QW~!A{0ZBJf`iUG--m_P z3t!je_Y-5Qhwr?LN{?P;bv?P}LDMm$+CkI>H7034whii_?&oOf$yP>;GCv%#%Vm?w z`eNU-9}f!6eW2aL$)7{V_AYZ7qN0vywHwrGOYI^Kvy_P*qNYz2WVu$!J(dv`Mgim+ z$HwTaAFC7#bK3@@$p%@XVhAgf6~n7 zUCHkgd}O?@vMt_rpS=A49C!OTM|hEn>t4pi82<= zJHixC=1`059v5*3*(nB?1o7n-&sBzqHDWJhK$z;kUkM`4>L%|C%(qV@60QmLgi%q!gqh zr%RYBrlj9jj`>$)X{>x*+P+YC`*_$4#i3Cas%MEFIi|3x(*Fl*?->)g}#etkdITcfJRsH)#n%thvac9#L$ zKXq+8uIZ7)LCikD*XeJ$c>fmy&&K3eegP;D5E}IV5P|ofJFWj|e@GbcOW zl-ry8H8^|M@I~@^OXeCk)r=o~{ki)3vjwT#5O5af@!(R+M;ol`?JnWx{)^*s5OK$C zq||y)yZd1}oDX6E-oZ|@n_EO=Ycl`S&9%>u=O!FPJJ0n<$kq=z(ys7ew--;I_byoe z?H)v3w-mJX;cSAN@#u}`P}pcFH>KQ`G)(D|JrHL`PTrIW5{R{f*x1M3cNk!Gsx-C4 z2CC_wVg1ajD(ziDLJOtWc4YC&bsx~Ir8UR+?lLy=qbIqK*EJaz%5(&(v-UwEg(|*e zEF3AS4xFUq3gyyKWuZo%6zPdWhM~B`9zc~x83joXG=ifinqDA*;2u59r{3>#al`JwwcaiqF4PFf>?_`0Z# zi{`_cm5j;As0gDvi??Ma*}Ui!#opBUkP13FKa<3r@$apC%t;c|o%yA}d20ASEjnvu zbmVMe>!I;+;#no#S?~zRkjdm4@|a`gO3J~!lvf&q=1cmZnLa9%8E2RaN`jVC&TO-| zxGZMFm{QJ^X9IZiC0QAJ(Zer5n30X+RRcM81cZ@HG!+*6nM;8U#JHP>(Ja)^p`OXb z1C8x!x8y{(_A@)gyXg=SV8+9uP3rdr6z|73^+|tNLk%X}$8gD1iHIs)zrj`QX>!AuP{sAP781O&!8DmWP-k67Qf|E4SLgMR3|7O zR9MK&`tbKnj8j^ibVk1vw>=j-L1&a9csB8SSiFstQgEIU38y;vIink8A~$d+N>FkY z0pxD_nS_E`j0<(CYQNh*~YFr3hd8X2lc zJc%edW6!6cDxS1OCn!@%P0C zm0eVb7dfk^{$7m&SCDL}OR)$=-T@}@nw*Dx$GzkGj%bGnk^=q!@{hr6T{qF*@@H6- zJ9X%_TH#);7--+VEm9-*XT*2q-rv`@(D|70H5k!~Hw`T1*(s(uUr^)CsK=*Qp%=4- zpW#b7Zn}AG-$^ktxxduC&lrz$3C!S=;hM7TIYZ*%Pf2Aod`x z;`adlr zgh`r(g+=d4gPop-uB=#O_8{3+BX|8)vahImtDGz2^7=GqWOrfBW`BoW3}$MoBOJ6O zWoW*h@FAz|xjW`oH`p3{upUYjlh;yIld30w@otxA{T?oTrPX;xj%wlgDrWRb$|iBz zp|waUQlHD=CKNae8x?d9>&^;kOV^|>1_T%@!^~t$(|5tD7uIL zye&viSCA^pQjh9#3Y^tW*aVKy=OTb|mTwDAAHsQD+*JUpU$2kcDF^q<61rRL;-z5) z9}3@}*p5A84I#hxY_!iCDyuv5+KoEEUFCq#dO>V~B`tPH#+!vYI;|2?w)1YpJ;Z}U z1eB*2GCL)lS%i2J{jNrf#r$#pgv%bO30NzdHlJuHQMFk{2Oe?-qC-fkV`vB7&D8OV z;Sj8!5PLIJ%epDbbI^+R;jD25;u5R=Vg3nkspPMzQGu1ED2xHyFwZb?u zkZ}4=tY)B7(aUPUYJ)_$PS?xveQ_rwWS4IyQoJ96ht%WRzeRyN9Gq)xP}6Eiwgr>> z1P*ZRGy7YayHvMjJ|x-YA_0gT>y!eqX+pH;kOj#4ou`1_)+fb;x+JnD8C5vkQ#-nE z!y^IFur+^iMyS~FgqNeUZ)Ml<@Mf^Gfv0@o((zWPat~^9n(a1CFPx*j$P4K!Sk@}v zY%NNw78G`1;5t0Bf0~p-UMH+kXc11kkeWT8&YuH<)sXmJOiNzOV>)zWzZI{M1Eo(w z0gkTU;5?U;oQ^ru(7h||wNS=Ft_Ti*PbAp}d7^HX^UJ_2f3UkmPwwtLo*k;lAzE{q| z$K~WzmcLzwzkT?UP{>h9N@^}U^Zi5waEO}{&K40fBzNn|NLS3sH*dAWXTW)32p9U1 z=Lm%>Si=J}7zQH1bPv0qgN=zt1|f>LGu_%G_pClrOI9V4*fNS7ytx1|X%V;I;$%Mv z1BQ?ws3VT5tCwJ=Lxx7z5sDyh_ER16Cm}Jo8su`>AkXTp8U53F5mAc;N)`5AKW5*> zKstO&jlOmw(!QxprqNa0aBH{+~Q zMP?>`qmbinq`{x(LTLgI@d+tbq|M3&`=CL(!(DmeS$QJT8j#kY`%zT>0@K!CE;`b* z*3i6G(~M1hgMWJS;6`7?MzduyeK;qb)2{H$v$-ND2OlqYDtd z)G;LDE+it#e7I#YEP_j#i3qIS2AioW+dl%rl8Fro%X==yK7bVKfz;?ay=*frLVEaA zR|Ftq1Scar2(M9|1^2-To-<|DU>Eq1^_A@mt1${bA~NY@c5s z*fe=gPMoAl1yC?u-RoEkTvlU8!Y@szUIKhnVThu6Ih=I^mlX}nX)9OR)y%&*A>ecY ze1vh?KTZ>N{JMX@Bo@vhd0c5pW0(?68Otrp^99OfDpF3tT1MWz-;W11dYN~umWj9- zJ6T1kJ>O&x8@wVSm|8yhaQBC&kG@=P;tg=&}x{*1?)3Zik zx(R&Qh=QIQ%?J@F$)&OQcKQ=|VY=;}Esr4>m~~o^`FscCSoGqr$DlI*4X!T@0aDq#z4Dy(yce(D8KfJk30Sf7qE)lJEgHLPuR zvvu8mdeq1T=;g>Y4-1(;`>ZL&mE%_ln%$jQGr6_2o7hq#0hd$deh=^LM%9(!!8_lKem=^F9}m8&LwO>X3q;0&svTR&KhS(Hu^$ z7sk9^#x-2rDS+{oqpNF8If?dkA(qzaqMAxYlNmAxZlLsmLP`w1&C%Y%9-t}TaRJSb z8IgqrH?qWbrI2*k;^%~FjzR7;9AnPOJB8}Wq$8&9rF9nEF;(C2s0j!fSrER`LT6o{ zsmTh8f`?Csd-@vlH{;ibY@1LO_g&{hC5yCt)62m+Bu|$nZ|1|bl{jT-uITI$kw(ks z@$OipGlbgL zk4TWINB8iFUOL{(iw+)f$bX%G2XY*aC;8O(NqP6%RU(mYd}i;@TG-Vd3OPc_jx zv<&LUDBz3w&a8Nl40cQ9zkyYNpf6ncE2u;TI@yjhj4n4sw4bsnBipcjsb$ z3a!f<5f`7sS^#t*hf+(E@Np^Va^rY~9h@e5xbX@G$MxWHhGt!0`#HnOiLYn$2Yn%> zerTMNm)sszGvgf7hP@C+s)ta>{y9;wIb}*x#*Zo*DbpW2D66ndgro9-hE%)^V(Uj_ zOZUBgdC15k8=4Vi$Aoi4xSNKt(^?6veT*2!lTA8+3ipT?jQ^w%B9 zIKnM~$Mtm-H!iyqk%nTN!~A@v^z~N-rO4a>L_oX0bpbB}7zU!p9Ffe}WX?{z1prU3 zOXBK13S=()?c69sj;h?8JuogO8GWrGIFnW$$P&3NQlVF%PaRBAT4i)KO6K}!A?%Eu z8D7u8>5r*R!uyLOzHh58Jq)nIe#0*dWi%#u;uXk%Cyo&7%uFqc^ZiN4jdS7yTK4Wx z66Mp?hpV$J`?J@Nnjnd#B84;c`Pnt@1_eP!$H+?N}yfbBjfFVmt>{?*$W8| zLPZ$_9Bqkx6fk`RdYOA2%w-Z#H$93zo6B_q+k$zXAj388XzH;Io2PrmQ2=I**Os<7 zS|d3}P1h+Fv6&OO$u!}L|4vDeCs&Jt6`dCc@gj~SL`=5?yKzPehWiRAD#kJUj7W;c zFPB}sS}`7m<&Gf!vHk6fets#0Zm|u=;NR4G;$rTm$v}aC01*GfjfMZ5asNoT4*HJ& zIEZn7u>b(3a}CghA35NwLfU+zz#RQ${qTXPnnhu!%ZV2v7bB}2Yc+|TmX%9r?=*4} zxX-}v6#W$_VQBq+V^P`eTX<8Gm(kfGdL^ zS*$sYmqW+E??$b9RYb@snN4G$WrtMk`@)TsefPorP?Ez+oY8l;?)|u_gsZE%L2W(izat|NANPY&{_2%0H5*u`m5iVo`3GAk*0Nj z=1JHp79^(`z7T!L{Iu0fr_?+&g)7WA4#g-IgBzpChkzgV#X3O$VxWzX@3gz_#k{aSvx=Z;4(my5YI!52g=mvvvjR!84mg zJTV&TlVGar`GVgT*720AGDt$=@2+Oz{KR-<*fpYF%KxjnxUsTT>HDLyK>u685rO~S zOC%%Q z60*o6IXpiX2&Q8`I~O2iBwL`~Q&)<_5R)y#=xhw#9SYif=-o1knBwG?X|5xYr9aGI zzH;Z!I{HZ2`2F>x+H`S_GWbIN5J*aGP)%eOgI&FVF0V8@=P zCReb*e7lDUt%SzUA|xm-Ex@Me}lYl!ZRBOajT z0(vertRr2l+!U>T7u8Z@T}Df^TczOmv>xWQbj?P&R2z-GO55C*X%3fEP+**i8@{@$ z^kI2a?-SR~pIjERZG=nb?yb4;i$p)iOQAyI1bAXBWm4Dng}3{AK2xV$shMIxcqisD z3T#(YH;YV~XxocaG~=a>OeB-pK~}^Ki>{m5t?1OuT^fQ?XC-Of)8RPJO3*o+6`=1% z*&^x23+$nS!C?pwy_P{=Dh;x5?;trP4A>%S|QR*ye57to7nX@5a6mR zoBcUvbKH8u?T07ZTj$zWPaBR`2a#}6wO0V^qGo!mxeLG+wF{ObFF#FPj6!Ztb+0*n^^5bK*??d4 z5?QOIY@+}NCKtz#{6@u$2N`>)eea81*On<#yy(L%O>6X?fJ??f?*)D^C6%##uYH@X zBV1&Vr#0MY5LeN3kI#d-C>Km@us~@|x8Y1!iLgip^LPG6zc!X5Mrr#ouJo}o+07E~ zAQR`0@QC_hPOS)rC`P?*&yGqILjjR=jwo8C_E6KBNWt@*kf+io;0s&(@B9T1v>gG_ zEY;AusfiTz)Eu(hx$>ZHYDeDSQ;O(I#YeHm#!zut!7Yf&77F}BreH4& zxDzc=j)P*O`jC(jbDUy!qwnMVd*EH%fwt#xuwwU}E%f z-)VRYo;4!Qa!|P1$1k;f%Zqb@eFXTa+UmWbp@oDJ$8@$#&FudMQsh*2*OLpIPk>}W-Ul+koozmx8#BF3VGt@2q29}6TwD{^L1)P5J~gaIoc{I~ zvp2&xgInp36lDBQVsjrr|F8eue=bx6?aY}N{u!HDr~&PUGKBUyl+=;b(S;<4O9-6| z2SJ)3fDGD`LJVR^!N!)-U`$(i5VTNLr)7UHVV=%*;!SX}ai8NFpG0GBb|SlW-*xpS zbM=-(JK|X%M`LJY^!hTF?z=hedH2}K&TRWW{Q@}!)FL;IXo#0pwr#FIzkNc8JH(8+ z(Q}+ClQpoxjkPgwyb_VscibA0HMIY-?hTxe!Q_FIkHPE?9iPl}WgPKi@)%9#$H>0w zczgOxd1?n>#4@!bYUC`n!>_m_b|yV#y>EX)X0vy{Qf6~-A1uC^*&Q<8mB}3=-Zi)e z{YvqAlL2AJTjtW(K@ZcuBYOt2mm~D8_00YWH6Jp?D`tSe$U&#a(!}7K)extTE%`CLJzB;S0x%gNV)`*T*{*Fn5l{yh4PezH+u$|;MnO{dD z6FKI_6;}huL|XqTCMwkZGNo=#>r%~qmzRl%D?|fQJco6sixM*=>(I83AC}z^T-Ypp zA)4ch)uPM#^Nwmf?uMahUD{eEtJ)83bZ*iUNQv)Sj4lbpN!{n8gar+h!*G~%YpmsQ zwqV#{%m;Y`KYFnn!F#J>c?!63nf+Ro!4u*p<2DJ`kU=6zS!KWvWsp?-l4d&0AIb4_ zo5Mf|l^th2{O1$6cYAB*Tuod!T~=otTk%#Ek*S@*O_J<-rB13Yjo_pmN3aYuawxOs zJO^>t>X>;*6tbP+))?0fQT=s%`k%yx_c5;;WOf&khGrye-$Z9a_vfNAr)-v@?M-Ax zNtjfko{pHYCSolW)P`3GX%kQ79F|eNGLmj;yCZ8)~xumdDA)fj9a4m8C}cPuH4I{f9KoK*Pcy=v<|kc!5s z@uFZ2l|!P&z{D|?AmkY{RiD<}$xCe+-G;_1YgERf$}r=e@B=gz5A1(74$Y1^p`&jl& zo&S61it5wPx9k~1`aK;j!|rw;Qg*@IVZMop~^E;9jfxT||}`2dw^A(Njoy$afIan>k& z{@fl8+j8-ivaiTeXo(4QsLttjzJANgZ=qHadErHY(<*}Fwyu2T_k`>2&)9m7rr&KT zR7F{*o1M=2(JortuOl2{`T1}w?ww*DdmO5#?Tu5*A(u6zDfv}i*Cv3IoC7+JdL!p;u zlXuv`v)^S2w}YFbsyXY+@p?E5CP$0Vi3Q_D28^ZCFZ{9xjuTt0vx27pXt1B76-<(}?Ow(m#$xwg?>7`M+Qa|v^YI3b}K0++b5Kf6>gXe zkoprfiJw+#elsm4i}SI1!rmtwn3meJb_GD@@Dr#ErcRkr(i==A<)k&vps+XbOsQY* zTc^NcpqC1(j)34Dk6!d_2?JC=+R3u?$5nFtAZz=M{aC{wR74jRqZm#+fuAITO=M9p zBTO@UnoGQTsBhk|(N_nBwTu<%rs2b{wl1!x7f>mZt{~kIz|)YBMb!4lY6l59qh8za)U99<*Q zJlg>giZ3paczojqf=$XLP$EebDV9!(ox7k#A~kDPE<$;17H@`X-XP5)md{MW6oQdU z&lwVt4SSyjD|OZ|7jmV2xTE!|EB-sN_&Nn|zKSbc&IZ5x!Fz0~0%5)iLCin4n>VGE z2U*8mS(n^&@HCg(f483)aju`$lv2Ls!LDz5HeO@qWJe5<9X_(%tM>i=2U97c<8Y+q zu-{qfh6vr7+$HvRalG%4_7paRdyCUk{<4=k0wS{dc0o=1PmI@RQSye8TB$#Hg==`z!7MDA-)^CbM4AeV zfkcG-noEK7sMUrI(pPwN$8$lKfd9<%c{EejiVaMu00kKt*+%MIy=j+Ym+hp}>)q0) zE08%2IFf*rsMvthH+-W21$%h}W~$5b6jjEd92(5t8UiLa!y8rzy`BmOfL|Qpvy^51 zcxAFjt6Ww%X?@<(lG9ksmTvJ>6_#x8u)0+rDx8)glnvUcNBzhMBEU)#Lv@U$Y{aB| zhJlv5HBt67Qp{nXA(CB8G#M85&_uX7-#WpJYiOIkIl@DA07Uo;w#$6Ag94j2U7uZz z#`;*>qpm9a!6>&#yZqfcJRD}qnMv~bNJj;}_6I5(#$yk4eX5RCs72<{4+8b&T&IgR z^arwN{M*A_UPmG^zI-Ay15qMVoF*09eGW2`g3AiaN1yO`yZ>{gb*&AWido#0=(pk zhAmry*02E#<1r^6cFchYE@ztV0qP~cF(!%hoKg`&%@xVZstOHa^&czROY#JMtDBYv z68fAPQ)MxDJty;~pY22xIo=|t9E%D8MzUB8F|Ts*3y!;BrbTDPUDLAhEgW8pViOBe zC2b85&tb9fGx8N<<%}VZMiy6rF}uI-TZ_n^(KSJ-w8{% zUkbe)=kQup+szcP`YVzPVL1>iYx}sMx}g@@yDBGL zCMV~KdyqdZ#!(nW*7Ij)?Vl{B`Y%8%zW?50|0PfFKXfQ$m6-lr|HfJ#NBo;l61SBh zT@Sd>E*pJ8kR2O+vO*g2cXK=$e`N_0yVx>`%EhC|*5elL%q11IFBLr!^|CUb@!-#r zvU*F$o__NRpX<%b$?>~!9%k3iw`~4T5Ie*zBSr-B@b;GE0V+QAu~p2vXQ7Rasa@%c z@&mt~6vnJUG3<0WvBvuZeTOSn{)4Eg0DvQfA-!45$*c<|3n}70(vvn(04?C=^m6iZ z60y+YVLL{D-#Cb{@c=x_OGLtDC!}W`;mlv(U<$VXZc$RUU-idbP#%=-CBe0a}#9iDJ7E<3jgC>KHOP@fPK$7Sj@3#W{e7cAmW^joZ*OrEz zJQXUwM^LAlMLxCkE1RIGfrg}67$mbUt6ul!@4T5`aVB34oGg_go`0VM}M+TIwup_Vr+6lsY75xr9v37 z^B@(P=n-I?>th%F_|i57!ghSSC?JbBSw%bGKv^Vt@)urtERB!r;%rP(nd342U4hEC zexLqzA(&02l%LU|4eMe&oGU%lYu(<}O*0RPhS@VzV+VbIcrpi;X^v~gFU60IRVOny znMx{N|E8q|Ww8d3}XzZnTgH=At@weQBc~hn2$z^uZ5A$xD->Uo6QVP3qho?|rp1$Yf%-`oLspDoi&$jQjdE0U z=K(AlQr@&Vig~EJsdLxC{pIj2hBB>z$wsMzjtY16&%a>Gp2(5e)_)`(9mxOvV1xWi zC{*~rJlG`v<=1~kepjlj*~|%i<2}>Cl`#{BrKMF_SCW`5vk?snREjanmnzL85FU8~C!_=3rbaoYxcrs%J*CW2CvEEtV*bv2nxO|8%WxVc+%1@c^GixFNBz*ohS zcj8%4G^D_nP#3GlbZC6V68;=Mg9QvkISrhcEu#n~KjGHVIP-*aoASh*W?sUqEJ^r|%3ub$(|WdLw)C zW{xlNpmdMdUqM%N{SMge+;VxF-HpXyz?~=4^ihsBcABY>A9v~g@M{pNm+vSes86&B zY3Nr5>XTwa>a(E8leG6GJ!+ifBygPDsj}`m$%Li0FsUC`l5PK_$1$hhK+I}OhRa5x zmLX6S4bFsT$7|K#Yx_5n0XdvV`E57h7? z0wEr2j?C$zA16`@D6h_xijc>v6;(u5Pj^j=^|8KU80H5GemNljI@9=t9U`itbnU3c z8l<0H93vN@BiTWzbYWvaDc2IAO)1V!E4`L>2xS=c(f8~#4PVOZC!3Nhi z{YOSpT9YCc{KlJ^YGfc25%u&&n{z1)7}y{ejrsK*>@Ek)A8|I7rPg>B#e~c61LOnm zMo^<4@!I@@aOG6d@LCc#rL2lswODT9er{|_9Ee|Ww5KO*0F%b>6YGx0A5IOgf_wSr zFurKV29gwW!DKX+*w!BGiowr7RI1!CR`s^YfUKI3WC@r6mH}>PD8M_=e1~-ns<4S3 zRVkuG_oG~9PgNjok3xkMshme0 zIo~R3y&Jx%z5yeA%?OTVqva1Vd4PT2KDbU}r`Da+bHiOFJ+gkJPns}wBcrX#v^hR! zL|SFKXuiPBvVu;5n-@h^4u%PoP|@*ztm*z7|7DL&e1dshDpS^ZQIKcl(E9KXYukH04WbXdd$ zlm944Nf zSQ$*MfoMnD?F_giE-mmLpT>%E!Frb{_Sd&3N_11j@a*k4^yCy(Bl8%&)3qt!ZWi1! zsWZ@!W3mw`2#;H9p}514$9k<*>J{OvrV@Z4&b;A(nm9{Bt8mp@&#a7pizd|_>}=ngMCyt&|Tj;DPO)q?pf(BXjH2{jLi zToJmv;`a3Y9&J$Gf7LfUAp#%o@Ms>A&BqbMJ?LCsvb*U;#qzW5_Ymfga@#_W$@+j} zXs2eX4W4=N72TN2^>NQ$+d(JeOy+P_Duv2T+^8kHc`L2g|( zjj7FU(&=K|Ofdn=dR@;zeo^eU8l#g8O2ub+dR%gDy-adGJszzzUjZ#%Gr^)bO7V>B zkd11N@0B9MawafX<{22w^dkqb?*DlCzOSn{9HQUUV@wXW9>vRX`V_!W7mUMp^>mRL zJ4PlLQ&vhP$ajXv^p{>vb`GDM37HvK5*dLyoXGB{L1xbJ)8@4lDS{ zx^KE?3Jt_4^q7ltRJ7z;eRv}N0O7)~0kscbHaJ5c2Glp;MvA;D6{YB{qCF0Rg@pUC zIA+RAC%AVc(UnSqJ9)Tx->3#je-n;_A=FdISg3d)h(m^iS#05_#e#Afa!9S*901s~ z6iPmh?R5GO#|65CCpbJ;<=#S}a?R;2Wy7iZarQ`ozP}LwH#a+1qOH&gCbOSqKC&gC zoj3*m#k@hSjC@+|=evNU`8g^?rOe3@H@lPWm;X4pk0KJ&F#|Ss7$6Fq809F9ZwTi= zX_a@q*a{9YuA&h$C`BjN(uiKL2F#!I8{!;cg|E=D8|oYXpv=0`tKzPUPNY~Rzi(ZM z0cZTb$z23a?s}N~5#h|i|E`J2@_*gL{Kr$A`k5n+I@*`6d12$eHFB{c&cQ{0LEO8- zE_QK~GRj(|w&D=9y@Xw#rL}bi{H>H`_@=o1CWB}{VG7kKOtr! z<^%(862B{@AjH(|$0P}h`EbmI@Ybjr1swk(4$i=xgqR5#B5@W|IwD~uHqJ<{jvm_y z{m!;i?(h~L=OHz)q~fI;w-saYo3a#kHp~{BlZQ6gRK-hsz*WUdT>x)9wX{GV)(m=# z={z?fYXVyn_{(RGDbokomc&Cw085G--mj6k$T;G#h#c;%gfDh?^fmUrAd9PLt;ma> zhH8>Bp6M~-SZ!7=eZ-9|d8ELa+^31U%9QD5rok|ah1_{aMqBvgB;pdzXnc~_8^n*Y z4=W|%j4G=TP4tyBjjKYQ%iL3J02U-tJmRFmkfcIpQqf*<+cq|?ZUFlgd92w`VG5hp zy^t2%+q=;vIaQ&l)vA$%P%9bODR?Rl4kX~nUE;8YCughYK)ffV7Tj<1=_2VBE2Dy~|rPu?@i1tIXp4d4b7b-8RM&C@ylsf{r$|yJVl;S4`F?wf~=&Q3B9Y<#~ zGbSboRN=*ik#A@E^|!faII7uq(@FV4sp5)qAs+z$KP*mZgoe%NAr&=G{h!@)Lxogi3 z@|q7eEwIZ9WRlW-Z+OIQL3qcOqMbI8+&ut*#AbSf`V19(kv4F9y5HPTDeH|oUePHy zEFDDmVL!k7b78(SOdI5BLHi8^Qq9u}%BliQ#xIjR$-cPSIEtY3Shh(dPg-~FVyv=Jg?hit+RWmSl$8T#?MKqq5^@fKp8{7^jHzvO6lVgA_ugnl6D+5 zXqKI}7+-djmw;!p&E#~Vnbl1lZHt;PgbnOax|3ON=T^y2aD?L#BSy@RSgI&($#yqi zBWGv~o)Moq4Xh!{t>Uqe6{UkVKnnF_1|$({t2&6Ux)J9WW79T$#U z`?S5XzOv|pw@FRP>EpVUKuw%u&7wOEdRqhzG;O!fzuOT}`h z8#*eiR`s#3O6mIWQDs9^L9E(-KORaHJ(QoDc1k@p!R`K4-nODjp(90gALB?2!MI;$ zlCP-nK}g6h5z{=)At#ER&HY@_3TVt&oX9l~yn79>_7#GZZFg+wREMU%+u*Zp=HEwr zF|l{mfPUfjTv)8(3Wgt|e;zpS{m6Gl$OX4_ZR2uSj&O{agVVChI*XpmB9Gbjf|75g zh>EfOMg_R}HpF(`+xK4elOFWJylpm^ZqzL>A^XiWo?VcKNraeV*q!-zgc3H6s{=ln zR_GgZ!kPWdXDsr2hNpoqKwih3w65J|+Xhjrb3;nPJUe^fQ9~lNZ;=1{`k5snrM@1u zqUR7Dg~)?`d*D88z&%Z*XB3g101BPbM>xwVX_{v&)^!+cX||qg{tSEsA`X;!gxKiM zhw1aFww_Z;@bcns6=Z3ia6_eMj)m(9?|T^p&Kn;7-F(sXsK2}gTWAZM9$&Tky3UrFf-8q~RR|jCa#qEfL96Gw*eR}LEBa^x9?-cs zTx;>@h%EGx@p8tzHRR=aWTbhaYU7MzI%FDXZDL49Z7?7y%$vj26TTg&4@w>&dB=uy z1=3?6E31WzZ1lq{FOppEla`DcQ*64TCvL78AFQcRbOL!Eh5F~Xm3|)8c-wDuX)C@B zOvJNRT+cV{TBuUTsa7u6E{8ppYwY;#M3LV>Pj*I((Iq*+2Dxl|hEM~a6E-dp2#{wD zb$VS9k#6;Ih&lrw>ZH8y`2O_}t>mB>;{gc-uFl!&ImR z?WR3|^tqJOD1Yl%K@r;Ha!wK>9DBjB0~HfUQb)4}^3v_Fi(7aZUNKBmM`FYY*^p4= zhpz+f@hu9(no}z$5S`l(RVo+0lm2*OL5N=J>aCz&UVgT|0j6J$?{{V@JNMny`1vId zx!%WCel)1YK-h zR(5)?!0#ZzA;Ip3q~4)@oA&6R%l&^tk8Gj63rBqIKPRWW*@CNwVSOoHGYt6#9s9!k zAV-5Rz*N3Y=^aH?t6~WMrb6Ks##~-=!{leA!-G0$WzgWLBS@!Nm{J`kp6E8dTam^b z{M~fTp4Jh@0>RYrVqdPANuI}|e~;vbBlSm()=kM?MOOU_+@vh8;8u6c5cl@g1=j6T z!&?&r1HW)0I}(Ak<;}ebEgL?aZ{{aMiQpI8mO^`VUp*y*f?O`Ra3S3q^7$heh)_S~ zc^d^euX?t@Afn)UOI?hZcg*o(HYV$3_xou$#r3-eWU;O>}4aOA}eE3;Ij)-Xb%3MqY?ezG7h&F+;l1hD4I zHXcO}^-HN03Z2N^yAV-?lS82F6Vnmc^v*9gPo+Q)sNHRNXl@wwA_I~5Uk!4acg@vm2+Iyp4Rx>W`{UaM4>8BbV zfeazYhWUY6I{GS_BybHZbu-3el-z&K-lCZ)A2 zOXn2HM8y~Z0m7AW3hyZ%fi$^Tz>IXScj>i8$|B2B4A!gej+qe&?QLAWu`WiW_}m%R zsO}g$vqnd#{-}uacWlI`i0DhGVu%L3+L~pr&=~Z!io!g9_Q0fji3FitOgKwQ!kY_H z`o101zEGoLJGP+Q9#yU!5VEB@XXn>Plxk2wm=Rg(!$vr$qlxBW;auWre(6cAp++{th2{!!=ZYh zK_~~UQRkV+yL6n)LcSv7YQxUX`JjB31ZITQG{+6y0pqqJ6%RD^i3GYa(7}0`J z@x&wUc=;oD@42nRipy32l~k^G0$#QG2iktmEyT0C<% zv8Gf8>`RfvGOfk0b3-x{Iguiz_;ihFQcZEVJTfIALpoXbqDB=iOes=>+9r`SClUOn z2?oUap|Hw2>wN|yXNi;l#o9Xt>9Vca!e!gG-m-1mwq3Q#wr$(CwaT{bRa|APGVVU- zbl>t|}PGU5wShC=vHrALGFfrNo0#w~_cybTb?&}m2 z1(nS#8d$6n$>UJbO$vhQSg%YEY+IuoJsx;`CLzN~Ra??eLZaFuqkIR4FN>}<%`6VK zsCjTDu+{U<>}s2w*Kty7%`Q~k=ymFw;BAX1d23>O?PTz;9<94OrEZp}UcFrF)iTpt zqeWj;R|mMUS7rUbl?NK=Q(recNjy)hX#?7;Uzq%g4#j;E4%Ia?m%V#Ef4u&nC0D59 zJ`m3{awG`TaCt1jot{QOJbi*5y63RV()QeJ=Ktkf@kfr0{6vAAiRV4FWm@fHir|&D z8v`bEY!oBE&51mhVx;1ucmm6HjPkLOq`isV8TF`|!W}^|rNra7?|z+Ag$OSC9^X-d znu$8pB~RwJ|7#0>#_6$~=lLPDMYm)1%U2|Fk$H1_&*bLS$Z11IbxjLU-Qvo zd9k&01$NeM1&M4omjSv(RF$Q(6t#r$RYxCO2IYeSr>Dy_M;01>gxDhvnIz?-B}<2H z(~68~X0%4qNSx>w%^B|+E3-xwgiX?~dto=3G(bIRmus!*F{c(;Y!$%o-i&#qhd0u= zs~L+zBzjo9(pe8H^OV|gH{tHm^OqN>?kJg2U7KiWwEJ-jK8*B;>La;@{gQvR@EVl* zfvqiAFrD_j>YkKOdgL>ze_o_O{!2jQ4Mp$R@H5Ju#UXgp79|js()dm zf$)cp+z0bvc-e3fh@T*=sGp0BUfqx94 zT!&`27pJ=K%kIXyC)H)$N%lTpd?UC3c5{V>2tvTslRnM0EwkbTuk86DS~s-VBDJ3T z2fei84&q2F>>ar&nBI{&ry53;ZMedypNEJJp-$ksbaI^Ok~1iETR3ef92ZeJJwaOO zX1ho$3{;eK5|!Fl)vY4oIMZK!h!7$9m89+nzsIi36fpQ}hDjAqaAoLUS zrWmYtK*U3!ZZZ1Rq{KT_pL=Z|RQ&$B#PgUnjW9I&zNJSe!~^9zyRl^BynqafpVY<+ zZYJ5%6NH99$OfCDG3f|BZA)q8GKXeds-~#$DFbO4${M9S67B2+Co9)AXaZ_{^}MT= zg~E{{66cT919)m?%UJ;uEt2YJ&EZj3xe8b=^2VggL}k#l_$Wa>QCmU<(Wl)2IS-UYY54)-z+5PfhLFFXqadt%Vr@j`w;IDH`L z_s_-x{)FT=)Z63rqjn$K+cWh;#D08nx45@t-$>-QLmpv!A%qXX9-(_dd-pnb?tVNb z9|(Mzuq+326mb<7j-ccc1ATv7Qjz8I;YMfu(@^xqP41~?%Up6%Em7WOj!qd@=ksh( zJPY`UN3}N*HrCWXTh$_Ptso;DkyrY#(5rlzHY;vNEX%7fe<@daGO0(&WyQ}}ccJ&+ z6s>Q^Ccp5hUOpRRf0L;{C>Zhe#T&Z_c)ftGPYcAh-$OPg6AI@Dl+?FU1n+283tOCq zM;Jdo54}V*3NxHT)k-%~P0nr#x$kzqJp0@-^pEDVV%JQo`I6fY3hnIAbcF6g2WP{; z)lFg1a$tYZWBZha41ji|PVc1g0EZqGccOl}6;ozm{GodGRyOm~Wn=YyWkWyh)L zTyy?RcC&!^QEgNrj5UGV07L9Q!rD2Qkt1~PnB)uMjxEWK6@79|Q57VN7ln=v!$FsE ziZSiTK`u$u0r`wGIvrsRiv(Cf5rxYiE+>0!k$$LT?Jr|ZgZlP;1B^QKvF58=@u!+I zuPYDkr;5GypdcRIzgiU$q?{~KPn0*|=yJ(q&511fXu}q-sWayzCSJ0<)X?U~ig9`Y z@_otgUm4l(KnB2a*GFD$X+<9~toRXsNg^kCIR;{oKqDs|phyxd=un19II0GjE_{MZ zx=AJa$j6BSgqh_f-O>f`GXjqs0Vt(N6UWMA`RSyM=)|3Y3EP?=6Q~eL43dfKFp1mb zV)rF@QfA0WkkAu_D3W>12|h|uB~3^Z#mZy`Nu-UK#GY9RKAm7mCJ;&GrIMGSl6k2l zuT6LpizH+WC`swkM6XeSN7c$?GO&p~)MEE+K06tgg(_9D0t$H2pGGwdgZCEP3SY*9 z##2U(2e>a~*Y7$nZASL7yLdndj^{inQwTvi75?-LA%6@|X(bR=-JKfPaT?It#lj}b z`mLKY6#-nTFugVfUKHWK@j%sDck$Ce%(6{D)N(=p)PSjmqAmM?tSEvkKf@{Rr3Y70 zL0ea%EhCZ@bfBry1Zr!6EF;1z3M2&|k_+XM0;^H@rQ2p;7v?E`SX7U`LRO-+CDp!7 zRf6|~U;dWe_?n8C@o(akB5ZRuYOEcz-4bVA-@MPI!f{T(z01-63i8V9Pv_!Yj_g%* zsg*Mp86Y?QY&9kAkrcp4>JiNnSoz~0h81hSXgO-LPX1L+7JE~4@~(|jPr4htrWw2v zCa}=4T=nsaLg5wG!TI3qoLW^ZFV|y z=PtcIpC7a%_zw!)Hlxze49Rb?8Vn<*oZo2HarmP`1umw9 z_UpV*mo+aY^qn*=$%QG)lY$Utu9Up!o7s&nJ_|VjHM^>6^Iz^Qg-MAC3mMYKGrgzM z1S44`eO9j5e-K`X+kNTv-p}_1;fl@Qzpbq8+_SE|iOgZ*BO|n8ib{X?=PPMG z3VS10dcM*KoL5tuGOOYJ@Qa-IeY|BTbF(Ecbh-2Gmnpe!+*TKOqVU9K2F`y0@&In(`f#e(2Js3KlCN>7~ zey&b%Af{E6w~FrSHN{+RZ$dVZZXP)Vt)gfdrczx{E!E|K7X~E<2z|3*KxxVTsy@ok zyPw;)#c@YCrF;RuXE2U@qM$#xZwV-U9+!jVBmuthLva9~GR3Yt+~gdnbqvz|x(d;g zOpG7P=#=H&NOk!cXRIAcA7Njn$oQ`g_f$GADfa)vX5zo*KmLtV*)? zmQz3zLh>E)i-GG7@?kJ=0yDNH-(F1sik!%b%@XW5D|Ii^!yUbLEVCf}mR7(*`~vbr zD=Z7Q4eEmAIj{Szp;m9OGCgxuzXzmm%p;1Qi)5pT*nn)9JnvH)>lPleIeX1j=x1yq zmT_fMyo+G~LCupK9Fq9j8*A!B&!V?`Gtl*3<2>kRkj2@|jp3PC#_nwFLS&j1#gb`| z$BnH=fXN-H_9RX|u_7q7L|y}*$`h4CU{$X6rJt#pZ8XPehDW@Mts=f^a#+%`r`!H~ zP_L-Aauo~8jyV<@iMq0bZ&I2ES>F&wR3!-}G)|%< z3)&3?CN*_-J}0U0`+&tDyY&Zbs!bG!4e;|=o}mnRlRNy|!BG5*t(OD(l22O|SV)Eu z&&>0a@12A=uIsB#7}(XGKcJ^* z(;5yp)NlUTLo zhFE4NK%ie>^2NN{-gpBk%fa*ER zkKOp`8vy}-;PpXy3@hGgVU?nQB9sg16jocy3QI<;#qPzVFP1RVLXYW$&1Rh-qb_2) zyQ(!inCA!%9@9*#b&4B2XN@XvOW9Y-MH5Xw`?tk5eFyiwV?rq7_APv+8}8gqf?)l2 z+JkG?j#FqDzm0wMsaCV8Tdz2i?%stxrjB1&jbyK|71eOfb_ayH5p^CH%e85&ojCpoWdGgWvb$wX!PHw*|E6?v&kj%J-x*adyLBIWd;>e@QyVt? zo0Ob7o(A95#KY?xz!k=k+UvY>v8Okvz#N*$}auLsM@lM zt7*c@t>hS-x$Crv&=`J=^}2b5-pUE{k@(i2g9Fxp@D$=1f@sIQUXDB>si7l^=eW)+LyE#ylv-rNqnOn@y&BjHn?v%#!$-h-3- zbH4xg8*V?XAJ!-oMp8$Vgs~>tP!d+!NCM#~jC!cLWYUwSu+m^x2qj$bLsw-tEZm){ zSGEz+j}_Li#w2@dT>avz4V@nA`N`v?QYVw_t*(rA49IQFt|14zA*VljddGG4nV!`P zNA`^itZAJh7Dq)^)^5A|am5Q8!jai*TZ=YPzu2HO-O^R-a<_1KCTurQ59tyXq-g0l^A43hx(q3-vbnqNwQ?PcONr(4 zl2~y~Hd(B~C4!kV$Dj-*;V9n9-gB(Lmtl3l!I9Y_%?S#m^{BXwJaRc90ipavzP1r- zF1te2y7wi0yh5|BZk(`FV-aPc+h7-87%r&_?Pj1wDOt7f-J=!5ld6PIEe9E3&+q4Do z$VIe{%nyoZ4b$LHZQ{8)WMO-|eC)Y|q&qwS^d3u1Pb>#uXrwq{awR=Wn#1Aln`9|AYBPiHxjW@x*7H5| zK)Bd98D@K2r>y!)#UsOWKBpa{7K?GwnJmNUjB)_d93{{fbh7MeXi7b*PyC z_t`qC>DeBkORKO^PCn2_vNP-tP?X3*1IDxs&)_5S95fg1QzQduvQ6C?=FZ~{@4aj1K%K{GmTL~V9~23r-WeodVb6C$(G#FaOo3DS z`4I<&@$3YbVU|pT`S&7yf!UNyhkbed9?PJ=M0~afHOa7V#!X7;s+O>X-@yO^Rjl^O zXqGl(MN#dAwGxb3LSat=@YNLRO(lR{zwj2VZM#B=(;B=${%~*NRo_K|{pP&Rt>1~= zb9Z8MIM4;D0RaKv{tkE4{~zFvl!=*$lbMm7%3mLHw=%K(Hw;qKQCSj1`%2T1 zmJ(9zjC2=;ksdAz+K(l{p~D0Wf&P$bYN?(mqX68V#rR8FB<)j>W+|)-t=-PXnSVD=(xxKYtxO|b-Ku$jy zVPwh`aopzOK?|A+|A7*3*LSoLHy#%B?pe33caDZFs{=qb=OYjc`dD=;fd)O-R_auR z8C>7YZ1Siy#gF6g=|O9TtJN_(?}WH!!g}zc77j~YKrN~AoGH8DhlB^fZyAq&h$)7d z@>7M!X{K}q`G(6;>ObJy7eSWG$(oD~`%Y(N41uB|vhgiGVkyW@liC;qE6CAWdxf1+ z*wT3yo|8L4q{-5njPz3v{r;wB9~$fn%Q;0xH)=?9x*ujUmwed}95H4v$EtW9Um!u( zVMBK%IsPUHd0MDAsI-5u$BjE>a9L@P$1e+wNQ>*okV%z$2ss`bG982<2PpA{@vJgt}B*tS6G?dB33_j@$*7=F`;qvFX?6*Ag(D;vI# z>D(k8CEX$F3;xZDWWF5~&cf1sVcgOd{~hkBv4~%0yDan)-^KzL?D zqzc8}>jO0lY9<6jn5Hn+5D6v3O*m;@h!Gkfe2VGf%b9TFOK$Lk&73YjPp{;PB}u<- z-CzJHHrTR^)NDQ;?6aAfGv1Bc5W+q21^OS8Npe_HX5z0!90~I8Cez<2Apbqbp6uTr z{=bH@+{77aP$slc1?#J2?bfe@#n@BT8UPfi@<C( zF#f=Satm>`bC8jDrA@*`w9e=`mtN0Q@%@1XtqH3Ua~Y{cNR030sAMU{VLHj(V=eI% zg*@34tvkdzDJNYe`-(QUM6-TkkxO2R80T7K{Fe>3^u!F2(W;ZoyteNCo6#ugx5}9R ztqqV6_-lna^s3??@Bwb?P>2f5uD~#N)dsC;xt1PwpYpkoTfW0sfb#&KoznPnW;z`@UaL`}utI`r&ZE zO&c@EF!GLWSs{7C>#@>wsz!4OxwF#VWa@Yi*v(2pQHVtr)IBZmwgXm`NL z>0ujBZn`Q{9E~Hq~yHsPtz@ z^-fW`>Mv6)ZQ^5cC+TDDbq@E2L!2V5ba9asqFHi42NmGtcMq#BF5<(2(ohytJ;Q!< zbLzLit?0>YvcrQ*>N$hv<2Q88$Fb=W8gh9}>6C7hP+=v*4_kb(r@n%4-&xxUsI@w+ zdAy-bEg9A+#Cmx@bZtBd(j;tTULP9wGhH!0eiA!&A*3WQK=Fyg;V|{%#(z*vW)hYa z=@wj@ydBnlsx4u@pKvcJ?}!sgl--vK{}ZXi9$^AFd_R;l$;KQ(UKXQs@{o6L6fs{L zhpUa0VDD^MOh_o2o2Vcr!GD9C(3|VJBQjj)GpRsiTWoJLHJHbsObL7%D(scBf7?>D z&WgI3wdBfO2~wO8Sws4{Zu3U)Q`g10`S|B>8c&N7iY-IsX1s_5StC|mPR3YkNKb^P zF0C>0n$tRcQ7HA$&iP5^Zk~}>?Jmv1{E_PSvt9x6i-HDQIQ!7=$8z=!u2>VqAbvi< z*qP01)Ua$+cC#N#94-{EQAW_tR493r=Xmt{IG^SAOJ0$z&(PQh)4y*F`>@i%wP8d0 zO-Q)<&E7P4T?Wy0!JBBg03v?5j3yB^CPjM=*QX{$TE!pdtkB1)A89K29Pn2<9Y(iy z+pHe2?eM#WKBzvFt$RX%)IGW5?#hq60cLf$xiTUISXl)*sVp>CDE8T&Z%EG}Ijj4^@ToVi78UpO3NCsJ7j? zl+KOow5syJq4Ec#ac0(3LsOuKHEx63o9RtoxQJGLAtWG7JWC4jCi9@Wf$8o}1}5&D&Yz<`2#~1-XMZEfa_8s7y;Pn?)wM+OBVl>$$b{Z3d#`M?^Gy_NC0aYYnglgI3#^}mRHgCY%NAQE zk~@c@N=TCBwo7terLj}Jc<7%o*li}IPQdvrO+rIg$aU{3PWsvl;ND{!;#R^|zOoqJ zz67h#Wpu2x&B~E#TwDjt7__v--gL>rNQ|yijEofQpL1&ZRJ>SsDfn0Owfdy=DA6v7 zu7q$>bD5*&L6%K?8+DJ7BTeb1NlXBZ<_Md~$!taj-XL(Xx{1~KyhW2vl)KD{jK)Z4 zTXsN(s_NG8;vzs-)gWGVyhn$lC|Wu>yJmHY>p?=whm1a;WPFnNFe;9^No>$bV|iE@B~!rxfVcJlo45Lai-|Y>N99Xf80Kw7 z6z0g2437RN4UYcEKjNyxd?9~WdZ6y9De}=KviczIS&*4lZQ%F?v}45;GSW|EIF5=8 zAvy}e2`t{4e25My+_i<}ADrU&1sYhtqy}8$_f#LQ;rIpbRlVef?ZIC8_Y-Qxh>Tdj zpnlaHFuYVp^;x~}d=(z#zhGWi4HGdbrdwt6nQyzSSN9yW1~rE1*w_vw={TBn z0=oLfFre^p=+}0pjMO#0Tny_`PHk)-qX0sU!Cn$Pkpe`s#0yUkI(GLxS2NH1YQ;f( zU2Tg){XeiHm&3l3&y*!7p36|6m$dNW%h{VSN=KhkINuQ2*|C3Ot4AirIF?7uq(%0v z{=9OT7;0>zQi_h3Sdp4210Za>ngto0;HyyOIzlK!;Q5pB_SD9^U`*hG`j#CZV_U#` zr(W1C>le!t)i~T)!KQPyhd0L(tkFN`skksQiywSD)vYmd z4;kj@A;c!mxfuM|p06CAd)fq8cW~b{^CG=U58J$8%jQgPUj?q{4yw3RS73jo0h;yO zHE^;krm|Dwl`~+qP*ON7y0=_b5v^1`+gGD5w93Y2L#x|#4FMHh;~ym^*E*N}LVYQD;XkcOR;SSy)6F}A^v3LRZo?xcf7mI25oi}o5>k>DN(n-BM3Dfu zX`DqboG$0#zqb3~2lPcteepxAHe=NS*#}OIh7|Nx%S#$w|^eEya=Y;h*^G2^~^FrX#EW-R0?a>RPq-XqmV-K<2~);pfC)=H}m>*f!&C> z?r3IzX)2Z6$&G2)phz8cj_|pDpfGUt6<5vhCF}2+f;5#14F{^TLLUw=g=B^OHFRQa z*dDWhNui^+o2hq(0~A$|lCGTRFE8@=U=O}dZ^k;7Ove7s7B5(YK?_FkQxgdKf^SUb zOok#oOcp-+#4r47ZPnY->U|lFSxlyAWFf?3SIPRG?Hd{oG0>72^|k7RTbZBm55p!v zs3Ri749_*l2Ly!oi$~U6tE}OgAioR#%+Qh``3umGd5~y_(`dqJELK-91lcemt~Eu} zTO{r(9tqhD1g{1`)`BBy!xG@>-4^sI;&5AmsRaW$1E~y?Mgw;2M<&lgqV{W(VSX6< z?#hC?H!%MY;*@>%7%xcbTDK?{%P-VmF_rni@(GGNDZl36{>$EH@ zANglImHg^nd`^2wB?+B8VKx0xKh}Fs$(it`456$tT7Fs;u6dOECM*m4YDKr+d^_x# zarGdu?U@z6`G#nRohflQ!oiMw?9OaEj;YnQa63DO&mD>Wr={%hhDh(z!v$e<`7tnc zwInB$nnAR!_H-X-=Txrv*34NkZyAJYnEU*ZO^n;E8hgw_4oN!ZOTj6iU29J`6%BEy z{=&p8E3J@HnqkW{*iqWVTDd$@-`3uQ=R|y{$eo1tRgU~x8P!vE!k@m`ejE(9p+4{P zgQUZR_cuef;A;oGOwm*y_qol2@RcCVXRc?kmDBH?-b^>+0YLO9%FP*l1P0Pji?NFVVx#HW`FH%)(ZqrtBB0!~GI=|j-a8i9UEKW+0*;GCfj^?lx1wqD2c_JrP`pYo!g&6;UE zQDY0#1o{8k1aIbB-W0+B0lodL++FDZuD17YRQNxZ_&on{?D}uqSXD;>RSD^9_PkAJ zaejxY7t!;2Hn$KWvph_=AJ06yL4pK~ zdN`Dq$;EP-eKS41k>A(*3B(xH3RQ$vDZ(Otd@o6F;v}_Zf`>{?F_aM{IO2lEqHI2x zk?KSr^U6pd<0>>#6jc*d4);e*X&s&1L`@Yg%+gQd680x;O;YbQSDD%*qeJs}zY`p= zLJC$;+EwNacGvwNHFulVvRG?X{iIwo5${slnXKh%i|mg)BPK^|W_QmEubMzP2yz?D zNIjF?mY9{FlW7OG5w%ToYxEKKWe&1d`S#SiZRgCQJ{iIA2iMG&TvNF2{Z#rKpEVa&?Dot}JZ@1crzer>t4epselZ*a6?RDmH(ShW+tM?oLYpRUa zV6K%7D-8;#>rPgLW|Osrw5(9XI`>TZPFDoMF>IYJ({gjR`b8b&XThv4RzEg8Lt;5H z?j>7vZ=-NA>$;3HhY0D5ya);ay&5j_`;1UziEE&>7Qc9(DP|9=0itwSbS?i^TXi2Z zb(=+wYvit+u$x|=QT6%Bmkf`gW%nVn)HqV^Go<5LRe(P$Z{GOl6ra~RMMq%UI4j@#Qww!GRQEauVBl45zB+2vm@^71OYt}682|cgJju^dMWztHL~o0dMSRG*Z121 zpQITa;_(ViYEQ{bgvfE?J5JGC8eyRvmB?{M{xG+^CzbZKxZKjXLPA7nZlNw&CP6~@ zoAXiuWMJ&RTm0YImM>tgud1w0FVurYd$JhErS(3r> z`GN9T1j7;Cg29TQ zTZ9o7+n|u?&afRcS4pJ&M%wdTaefmyKD&dSyPKPr;QR7P`!zko9*fjsAnRHrrLZ)s@5B9tMjvK6-x**M|?w*@(py{qtwEhUdyvCZ%dBiO`u6v#{#p(3s zJx>jFeJQ1SnHkl!UDG%x_qf`v^Kgr+UHe(8s@9`#2kg zm8pj|4x1V0e&bi^0cyQw-the3nS{Qx1dHDu1MZx|;aBh+Z?%9mWKav$ADu(TRJT_1Os6}MbsQG(M#P&z)RZ`)3G+B{snYat*x zOzM$YqH4py18+S$Pte{Q9&E96*LL$Tjk={sy5SL04jy6vj9I^P5G!$a1>R;3I%h^y z@++5r2Kf#g9BzKM1QzF9fpq6fOIW70;`S*j90zrLl@d)8= z2Z(zN3#K81Ic0O3<+@q+i;N9H)IgsFh4>!#?6E2a))XH5^RTdyJ33NF*V@jWTkY7kGpH(lm7+8j zw)M-AewQR~6lR0S=umb28Qf5x3ALUD)ftWYT4C!WX_g>L&9V_`naS&)FRQg7GW7y} zJ^KFrkxe~~P~l0?+bZphsX^`eU8LI=!dR<< zRkTo&%T)oj&@&~AKCwX}h1Z+t^dnw(qw-5X}V^c%P*MkQo> zWQV5VmWdC*N;%CYI(-D=;_LywbCQUTWo}>z&cktwdc>Y$fTZjvCi)uN^N#PGA~0Y6 z0l11~Psn;gkz+vp>k3To;T9=GSa`*10?w8p8&Y0)Bt2}1$vsySotevmE2^pd5Q8Ha zB4WnX7tdBNMoHiGam1(x>%e}Mt%~UcF266sNn{ikAqqg|4A%fX)-g?ydrZEsyNQ?+ zd7O{E(Jy>2$1lR_-W_Bbb+5e+Eqfvel zqK|D@4isXM@Qelt%IIVVT+u>_q8R^TrL`Md)Wp_cQ5Gjnp2ryMb=iY%QQT~5k<$Ue zCMUNOI1$M&zk>Wy$nQO!9hW!dXcO3WzV1BDd(U${^8b2H_6OfwzgKDAG&>E=MAr6!w51|jC)vy{0q=F)8Vp@4<8&X>GrFUq( znWOEuSFEY|X}FZ3-r^lgfINPhZD#;)JZ6%|!mx}LoH2i7dT1}nRCQBN+Nk@jUgH;^ zRxiU8qU;A_tkU$9iU9MS3910ooeC&p!F`^^y9#=>e)|Q)Vx2jncAZ^8eS;yLc4yRa zs`FCdjmI$)sGj{U%?2ermM7@WwO`+Fj2e{{alwh=#9`|0Hq0ZLmTP&npZ!iRA-1U3 zF>37d7X*!B8PC51kI`S1CwF9|?mF~Ppiuofi7_H9R0i&){Z;_SRe!ckhiKGnjn|Ll zb)wxW|17!~f^UvD4P>WXui&<7uOK=_yC2tR)2(%h(3~tM`l7Og$7Q@^+WKt4RP_c1 z(&Y2nzKV4l&!}AvXa-`cEXi*)2ZharBk1aQ`_SRxysr~LUv~WB8Xy1--e4O*oMFyT zSwR7Q#K77KhIgNRvN$r6(rL9+GpE~2^re*r8^a%cSp9QQ_|?NuxtXMQp6~Z_=x(zK zm9Pm6FE^}zLCbON(Yy$YGg{uk+SaapEpep;J)5PW>}_!>#&6~xz?1;k_)~Nu6co*_n6zCS1Im?v)-j`dC$$lDkQTuqfx_LPdOHy%Gug7{P5_~Ds=T3M`kVp zJ6*w=EetFcn*R%vLSKV3m;a}8>R<{>1q<_KKCBuq4hY=zD$+p#hok*%Ftz7EW6g2!}w5{?-u0FJyv-`}hLxjag$^GZeOm(d%BP-86dip5K zyp4Z)|9W^gp2UWE&5i<`QmkDuyS|Kq9`W1~b&X@*BCQ3dw(W@bYK%A< z#fB*OKw0kiQF3v5)5=Y%j6d_(f68w4Dm>|&%geUYb+={%K!-Aju*9SUgb+|}p@{dy zI(~s^_mg_yHB;T$s10b;In3xe&6Lj8xLr}Pwb+a@X}ln zP5+VeG55gafJW9Gwh*zUY`=06)y6q3wu`_uZnG(g#5Li^9zzXtMka4@Rn-MYhvinS zD8~LPT-kGC0o&3zeZG!DJcL5$59-YllN!@iSM)r6t5tbpiZN#c#?{NikPYEi|3Uj$gg76LGItrKS#8xHn#slEbL##zlYe2*2YhKbGy;~UOZzKz zM;%WUPZfHEud?J-bbO6n0Xo!o2O3(1u5xhbON>WWUXKig0+?m2V zB%ZF2J2DNwZ!O*=7wg+;4b$ue9jyz z#S*35i{(bqx68Rm#|zd$-Zk%1NPcN!&iXfK6Z40F*k;Dy6!bCh>nO5f0L z1L6n@%7H&~!l$~^p&2JI*3SWX@HyFV&79@Etv;dKwcS&cw@FOLXi77t8G|la!NI2) zQjG}aOzB=f_Z_gGLY(Q=6=Qt8LqGbq(VwbHw!O-5on%Dpt@>M6K`^-Z9r@E#djDDd z!6d5b9smXc`uN*GFslFlSNRVXZU6RLXzV$os{O-+t82ndXAwghAf{ZAQPu(|4L}iH zQgpC_Y6K)kX}3?1>#bjo&Xnydd|bsa^uC$kjZyBQIh3LE6vuHh|MD-o`5iOMnb$3q zl~lHP?=<(*V(zuq`G)UV=KZ2?&ku5+X!qd|I48Lg5*k~6+ttcCbs;9=0(IOBnc&Q@HUrbBif^Jhm$O^7GJF^kA&sDn?5} zVdjS7VxubyZdp)KnwA6Wl9ZKrB8$sTE?%U3HNe#?tWb(CJAx@@gq6ia$BROh>f|Bq zDgiAKa!$E0iG*T^&*pMDVpn+V>c1WW&2FlXd5p14)1I11$jdH^NpgJIj80d z?wl+J^<$m+*A>NM84pqoHw}ZZ9iBzKW&Dc(<`y(jKR}|9%L6T(b#BtoZ{OAIVpA_F zS0wBs-A;S9p?*~-%X3x+v^NQHajZBni0k@VzOg0o&c@>swU(ui6ngH}c4`;RmW&{y z5VV;6f{>n|Vh^D}cH@Ac9jCTlYzC$Q@;9|5?oN?7~BDj;ayhh+_f_k0r z{yH)PCLX$jGBEn1G;rS4b0Vc2i7PP?xpa$K+^B1dyfu|fq#h!JIxxGy zdb{f<3^Gs`2Q%fJo8G1mp2B(OFW0$}Kb84*S}_r)>{HZnwT(6iG^AC~yBpy5YNMk!<<6h2 z;2egRO*3ky7lN3f3$MTt58EtsTneAUB>=aNCKNC+6WF(35s7G58vZ4dwEk0q=PiTxj$RPsRfZk1=_1H65%8s+-)ynCFpa8 z@I+VaYL0EkBD21Epd5|L0T6{T5U2WY5L* zyMql(=8Q9R$sWGg1Ek7Zq1c}7a530EG?pK6*04!eqaGKObwPY&fhoOm<4+iXvTYGB zt6OIOmhSTQl|TFk_Kxc7Z2drQzy5)(b1vV}_A$3k`hraKPD@88$d1Tm7D^3LPf zdaOc4gMt-mKJtK;d$Z#uxpz$0k^=sY1Y~Ett-ywT6QZ&`;>M?`_XNKvyP#XahR8Qs zPh|VSzn1#!2|Rdfa3G)vxW8+P;`s0JTiML+hl`n%y@RXEzfkN%tlALmD#n;en@c>yb}*GX}YSYD7S2TEIVS&VM;3<`V+o zAN(a{epGzNmYE3u;5yhI8g4XHbplVXXNvKFE!J^EBZZ9HFm18uCt3U>`pqRc6@Lg89& z1|G8oO-6+rQ;s|$3kSLwSv+t2wM2?Kar8L8K78i#`}So4fZ)e&u|+9%!!M>X{fTEC z>^sKkf#Q|6%~6Uj$FG}_pBM|U5;qH2^b%K&mkJwvn=Kg2QMt#{Pfly8DWuu3>`j;=4LCini$4z7|v!`|Fz|wW9I4u@K6{*J((Vd*yF)QAQ+bQhjVHaBPXi5S& zuI~rM6y(zj#cLoYgZ}s}wuCntoCno2J=0!U-_-@TV5?V zS>-Ifh;?S&qoPP>+fZ34%~3>KM9tHV)@)g1T$8a7xct zD^xvFnf(Hcxio!HvC61MnT#H+A$Y-NeOH5E&xFO|DCXxo`OsOJcq*HQGTfKcPeaoqPttMxGY{T#P) zz`{Um-=`xN>}NJF?_B}~-&5-*L2 z0?4;2A2CDX$vxt8RvW-$D}s$}J|0T_bJ#UArICl`Dp-fW;ljXu{W2hakp};Zvv&^i z>^lEbNy0K&nW7nr{@9CfOg( z$SWpDmrpyF44d{5jK#X3T3jj(eOgWN<11wjGu{shr7z+-WyLJ0>!fMWDstlQ1BSxK zIy{kY3bP=argq(0uF^c$fla)rWmoj`JuBL6;hbZ>ZCXPa6qB<#&~^2D>02tJ3*iy& z;}{gcwlZTe6!&)v0y4%aGpqguM>ea&Q-d07!{mzDG4gF(QaiS+c1rYR)+BWxS@zt4*q?%XNL z6+%yS3qNb06lV%;G42kPms;PrTMNd|IPc8Q&^1qeUSWWE{$gM|pATKBY5>jIHO={R zE_OBb`LdjktopX#=W^0x=fbw;(sAkcTU}QUmw#uCsUfboyg9r1xqxafw?#SB{IUhC zb)Wa!Z()#)0FTnc)%;;~Pyfh8xpre3n4L-l4Q z=RhH;_2NiN7X>uc9ugX6`-*Prp4%-!^A7aDg!Z}uR!;Gqo#Czn1|Av8yx1b?IS)2j zc!JHbM6r}&5T9|(-vwy%qT3N*sC7hhLGv5mIRzt9YVqgL&o+>|f}chq8#frgKUEJ@ zzylgQLr2g=5ZO1yKAh#(B|jLz@zb?s`AF!*cM~wBc1xt?a|GoP3!l)U*TuVX?BxR= z;VKQ@)+1^JBBt}{wK+F>>B4rS<%X*)R=C^%!FZn@$duw5TmrE$3Ui94_@Y@0*7;g= zVw$5j91Ux+;pzrg>VCkMwvjmrY==N@>5gczdJ_Di99l%90>`F89pin;#cI6zdgUud zyH}DcXjP3hlLE~_m-;b5TN$Puebm1$__@7?OJQPSnfyTQSEXcr0qZjkZc9Qz#oZ&w z*+;VONjo224gN|cQJXv&&cI)doWxTE9;+m@GJbDR)Cmy`$o4g{lhwY&u_jPd0BDkAWE$sB z))7g@Kkjn90P!TYP*Q>mbA;#xzaC| zl$e=lTEp}sOYqK2_u(fQ|LMS*BzuIJzulw#0$Ld9|Gc|IiW zgo3mo<_F~5L{&4zbS81=P!KZkFp)AOatZ}Sr+#yUm~hHe`I7x9^Yzy{a=^^ zk1IsT=8Hg()9Blr$C;cCCS4yN59mFJ4bT%iRel~VIWVwnIQA6|mUM}KIJywK^~shn zMWG6->WKS2w{H)<_n?hj$%1Kwli$pVHVEN4PJM8w2Cp+i0dx01pPhENye4#?JpTl1 zs|v*xEXe$MaW27H50A%_)3eOtsTYD%1DjKF(&M;Pl@GwKIWIK#1B;i)Yl@Mz=c<$OJ(|t4B*CLaH&z3uoo`&b(zr z$68Vtwf6BgZ9&N%gie`SNPx8Ap*K{MI3}Tns(IKmp&v~hqGgu0#hYD(i!FWStDdW3 z+BKkMe_QY?HtGrtVn{rAp32N?(#(l!7k2-iq!JKetN(<*_$B?D&XnqWM|EP>)EE-{ z7((40+5Qf)PaxeQ8*uXld&er>l}0@>dTI$VzE&TO**f8CPEn}Lta-_ZM5>II{*eXj zV_JJ@xvCbK@Ih@g)M&{+tzw%245_xr;bNO*tE^eEi(%CvrA9fu2Y+gnMA7{(QGJ~Q zdNJfrAfSEV|5R%K!PNTy&S}sWvvF`F`g;|(Hn#a6ER148Ho0s|_u>%L$q=~%bK$+adcHHig zbuvJE-G|iWyvcm4-q1_)EqcubMsXJ`cI$85>w}urH4w?<~V+jN;|yX!>uiGJluXCA%V?1zYe+jRMUA? zo>%4y*qJ|U#tu1vqpl?{ANG?Yn6APASeA(kS*<1Yw;!N8s&jL*nOf)2Q0LQm{x(%^ zN3-BINkabD;|!+!UQf9QuiuZWQnowtBny%;^g|xeYsO`y<;+`bGlQm}0{UfvzEm52 z&qFr^gNA*v`Q+5rDGW?Qs)SwS=^yz~!^|5%1lJ@ELI<09@qbT6!9-Ux%Q5=DA{&*r zu+RFrr5N&mm!q$ZTF!rRWyKk9d9#;dEOzj!?mzm8n>9gP*GWMwlahvZG;=;%m>tytvXFi$_MI|m@bP)|nN zLqKuFHGc61uwG2ruP63Bn54bLzx2MW;u>)^UrA#Jl2}c1drdiHJ6yGXzMikU04Z}x z8-QY>D7YHx&kOtzM${ycAZbEZn61S^azn7}L?%0nbUA}AIu(+2ydrX_3iAU>+ zHKQQz3myjh#h*QChJcbCJHq~lnQ+#|weCF{;9UBk)W!|ZPOFV0L|`dtr_uewl9ztwyRZ_z>>PvW| zH?b$Am|%QBj&zx1|8TM~_G^C)mflNTsw$sCn*qbyXD%#o|sV`l$U*og?qh$i|UrQI9*Kg?;lx4B1u&b4y{ zfCcMH-s2vVod2Yyo%wWfSKE22rVK$2V_^3oMKwSeueT*QvLHHYrp^b*s6;K*7At*0 zsl0^`45K*&WOE?6MrS-s3^WB%+0TR+{%8g-MBhTB5w>Z6fT;NRHF}xUaSIZBBtFEY zlDP{qxMWa;QA+TEp3-DZh1NDm%m4fMuN4>muj#+>^v@%4k zxS9VOLpS>h>(%(?m_dGMU+InYpMtc;<9%WKTadZ`5pIe9=WzRPewQbNr_$o%ckA<{ z$324^zM&Dsc#R3MuP+if+)pt&AtI`uc{1_%=pz#YX%G?b3RaC*oTl34EfK$e40wg9 zRH|5Ap3SLfHkw;4wykfoKX1C-A00{~@P2pa$X>Otvp;(zdt9;HeLTZ*{{~V_66SFY zC|8diXO`$lJV`W^-@Dg~muBw=^Vwt9;Tairc-6(7-hWk6-1&t|`*25~uP6m#iP;x| zFiJ;@dv!>x!_x;gsI~Yi_7*+&YMS*<&N&1o>{*c#bANX$#Nk&$qQEdZEa`@RI0nHV zl%jgp5pGIy-mwOT_=;qnS$1!xHUvTrdEnET3XI(S@LWCD9fQ5hr5tk19x1y==NW=Hv8Bf+ zEvy{`XueWNs3_J2$2TsxLlK{osmqRnN<%}EWSNN70W6kL=1 zoE4#3FGb5UWF*!kJI!69BZimA^rrFh$-B=v`{2sTslLyV9|Ym(mODm0{m{?) zlXoxalE(Ev+8w7)HK%<0r6dAzLf=*02O?$@ew%sTTdlC@oM zpW);UndA+)*L3p6G;%rraL(H1@7pN7Zx{RJ^7gW6c%u2rt>aDWrA*sB4c7jOL$M({ z`itlwfMdJ--s>P?Q>itF0#?pm?if~n5}$&r;$AfLJ739F>NsZp8N%E<-d{)V*TecOI?3v)uTevla?3v-vTN+3Quu-n`oId3v7__ah>y-5!{kwZw zz{8Rl$tU+9M(LUK?8YRko1fW6VNz4+zG>=v@6e|ZBGmqSa(w&t&IKK5S#&Rqj|l!Z zk-+T8-X(Rf%orWr8DX4mMHL}j4A{QT7c6L3QO}aDg(5*LI0F!br<1#rD#3#MCem*gXJ8A1+8&q-cCgWO0joH^Jj!4#6{uKC>;9vj zB|axnyg8N4#LyrDD+f#FpFk;{j*cM6 zk$Rz9n$7lhmt}(yB_n81Rh62`-9_GuZTnV_SnbS}9Oi?+>q|oQFC|vbdiTZ#rOQ(? zgp>SGlGo6Ys-gn>O6J5gFPnN`KtYmoH3fUE7A@%bD}s!_*QCRACkT3`^Z=*CwS1av zXyRhoY&8pI9z6nt|LZuI*|)4tCN8ht_&LxD_<< z%$m_>97#KYwtPz!_rmO&#mfdA#t+JP=psksuC64hf|`bRbWgX?~F|siZrU*cczv&g%D&+-EKDsh3lx#(=A&Akk5-tsv73Mx=T= z*>u5VgZCU%Ydi-HDBgjfd~a_uHCs*|J(!6VjX55DjGux=6R4A^yN2~IiKP`}YnUMw zkU)$(%sgtpXl6gP(6PF?1XEZ*u}Me;PQDc_1ehk&MXLY178gZp%v_a^Y+ZByz2 zRIt%OWcn5oM4;VE4=nl?aW)ii+}a#G+bL0|$P{>_l_laAest|r(~zmYIMQ$pN-Fzl z)`lv+38~{?6Q8J+q$C|qv&)@s3!frVafX?w$(&M|llzeZpRt2xx*&EHXU~ zbadM6AWCqAZ&qe_T{BK|-ge;Jn|CFj=R)l2pK~O;pDC?!9X$F$EV~Qf z(*1ZCCwzc#39FSD^DQh(aqx=?_!%QaeRJ4>^+|HS3R~<&M0rKy1yi%Mb&Q_<$%B%q zlpqypaW)asa`hZ zJ`TTx9y}}>L=7)aHlQkKqUA|%Tw)2*I4}miU*f0;*&B88f}0x47urdXWRZDqVCH1S zpnuO>BeWVARcy<~lC?;o8u7@&{7FqhA;q2cMS8JJK+@z)<+n_3w+4Q4STyBoDZaE?*6jVd(;4%Y4ls59* z49iZIAM~6r9Ufgh!i<*(hVujy{}55=^*!!y33KTiIw=Z@R&cVL7FADH9U2T znfz!mwwh!xDRHI(;8E^5GZuHi6-Q@7RWSD(Ar7P%_*_LhXd+`0+C9cMzou0HWEu!k zNvo>%?IpxA6J~Pv3JF90^16Kpl6Gfu$5A2&aX%-Ghva6HlC6$)AemD)3IN*qangXM zs#LVO-)V>*vc?)$a~zQT^#mpO@(~e_K&HTR$bMC9gIax9mjkBgQA|S3)Wgj9O@b$0 z@MFjkS9HoLMoDJ!J=!tEq61orfw@KAa{>=aA-yHeGS?L28G*Zf{tZ1rb36tfi2F3a zAQ2#Dtm(mdE6^a&%BG`9OWkA`affe0bQ?$)J&hSs3>!hPk8l}kvfvIaTqY+3Ooo_+ zRfHHRU501U*4L$fzktJoqbhy`dnj(52CkZ5DG#lntWqm zQy59OkWE2*rnp)qmX)2A1bm2z0PQ#_CSm<1IrdG4?4>F?_uI2Msb)uj>0`W{C|urfvTw$);-Iv zI7O?OW{cp4?WAp-5gwnakD#CYw;|(t70Y!MZ9{ zPbR|vsF2aPc=}qR(Q)Q0=;X>KTP7x}o9|{IK}O~+9O0LKqGdl(r~+)7u#J5|iJC1M z4yLR*oL}+MG?c;$NentBn(2kPStjHxGqbh*72_#RX15-4?!+=jt<>0ed!x%l(Xt0) zrey^gQY71qY9QrIJCH9ux_n_Gqh!fOHDQTTMvTy|s9)AMurIvy`s`I~9Up=LJ_Ec@ zcRuJJh+j4V-yuHcH`6c2Cpn*Nb-mx?-8Xl%&|k>kYr4NZ$9uN7qhJEkKC=Lfoy<_9 zwtBu|s-mVaFNpHpRx+;%qNd%w-Miq{Z(5u(uU z?s19$pXqOt9+#WW-l2X~9T2D>@(tbm(Sl7&_<&LLhLwdN??4S!8$+uAW9nKnL3ugM zuO+#1+-CVNl#2+2-K+Y_EJrj_oCIwaxk4kdf<1aP1FZa6%e{iU7)h%7gx@(J~zfD;K65z}wB0OWo!w1`i@Qabs1XZW;So%(>TAc(;a_)j-ST44w_ z=bV~?-;TNmW}CaHq7itLp*GMjpom9$WxXANq&djCQt%952uJK02hyOT)$s;3&M0>j z0Z>h8R`hDAbV2G1x&i9hy}!v{fsQlcB}a87?#M=m1CeLhIMhwqh6F7S70pi!t|?I1veUPE9I-v=T z!p$v!k6GzkfqF!BT9bJjMXI7(knJPEg5s@13Qn>`l6$`s{#rEkb~h=ZPrO~&w&?n^ z2-g~HH)+#_xESi)60KjyZz;XisB0Fx{Z*i6pFEAt{O}d)z3itP%=^gVKj_(gAC?!K9g9WT7Hj73 z3YO0`N?p!YXm`#SEQfvDN%ih+?b=e1myG{lo%8 z=*;6?%`mI`t$V#Y095ClSI+z?4S|*xc;eXwNv24rCp&YIBO&F!QXk9^a#h@x$Ydnwuta4kmnPAG7cso%R_Ic%PZC+e%A5Fn6BwLU%rJA1K>i8)q+l_o5`+X2<0SEBd1)iFnoZpyfxTv%Ya+@u7JB?1W?d~}?Q$;2(2=SKT*T?H zmXOx#e|0~W32SeR$Q{zovO`k*i}B9Q+W&mF;@P5LPTb|JUW*7VS86qGr)h!O^({m7 zERBjBhsL=RBqL!>sIY28j?^whCOE}dE{yF*zIXsUSGm$7Ve5TsCD(qO)(`dxQ#yg7o=Pq5xU%+}*>)^i3m-)5h^Umb<0}*%rE3Ljx)85BqrJyLer(x{Y&| zUIOVYr5Q^d%+sv-FAtjdZannlubzN=yvJPCdERgyTt5*`n_iF2 z;}jSq@~a%pd~zR8(OccpV%L^+%sD+|6!BY=xZ%LfV44S(c%y?6VlozvMzO$gMYwvCvdixs9ftLn z0yb)Ii82|1{Rvjq&-TQlBFpd12$=C(sJ8uB4NsVC0p9Qla|<qYGKtBJ+_99Hm>HM6_bgQtc<>l54?Jf97~vqqCucjo18p z(MEz;efu+RP^A2J9b3VmzW8~Cf}VBBI$&{iUvu(4@RND#l6Z&ix-Ac7Yd&l=UwPHO z7F52V#&g!kz6T#5spfrL5s$z?xO+fZE$;O54Gxb+(LO)=VT!Y1V`VX6hyhTT@ z#a^+AyYmm1XsIq)H1cQ1@ z?mk!eSHU_muYUz0$hMl`mL!@!N8n=17J2Uo%h=uY;EebW>%nz^gOGj8selry`zssZ z_8*KCfpZ(ymRhD`S;3I;aoi-U*8JMpG^kw+4a}k%iI}9hpkvWaT^={4`zao2oF2LI z3htYV>k9M`Zaw0TEo&BDoE3ggzSkPsi(@v-i|<0U#`p2j)78>B{%HcOW;gx zX}sKz;`~c%%sO~{g<2qil0U>Ubr8m+-nPRYZOA*2#)yZqB9**ia(0W9DnB+&AZOq7KKeRQaHAV}zdJqhJa0pEXkIX*B1;QVKv- zR65`dLg4{Hx;id5sN+YtV(~L=8*5&mDUlj^HqHJ~O|(pFC^``hb{NHcyf?0_8m!uc z)pe%pwEn|MGj=2{^8VyVhaoLWN*r6mZO}V)ufV&%h;GuquvWwwsp)w3u=_xfy0-*v zt%zf_!{8S{f+Z41ndsJmL7_4J>ux9Vldclbu?K`D!qI{9o8qoGUtn29EU9YnIxI~l>msry{Y+^^TUGGVQX(Ln#EfazreBaCQ16Hp3Tgc}XPWy>4 zb>J%~;R`Xf_Y1o5LUG~K#1`otD_ZYQ&+Ua|hJ;2T)oM+2rG9yk#8OKM@GZMiUs{C3 z-HL`JvGbmK^vtA_suzxdbX}uDj-b@%A(lV;`Q7nVNc!*?B^^|8COxhR;myyRJAsk? zLAi;Ll>tnBb59o9SAfF-iRzv+ zO8mf&1+qqE#M^o#`{M_gR;SU}2$DYQ%^K4fL5K5MB1~O`ZBxvuH4JOUb%K!cIDAsb zSDGOs_b^18jLB^E#i< zo`@9LyF4vYPI*@$sAtR0ONDDgSHE&?1e9CrR&A}Qf${7hP$6d`<5us4(AV)cfFA2a z0YJPq_>Dw1Dsl6s_bEZ9Eo{GlUy4UURbLJNHqt}iR_r$ z#?rIUwA=MAX=-~p{=Qr%^U&vXUFofl?F=PP(97ta;gmzrGJDV3^x0<;o)rl%2C94W zT4Bnhx5ZTvQ>PbD;#>i5ikqJ>eb-j<{_2bwwT!n=qL3r%C=t;1n-t`$HF*b>R>tqf8$4N~fJ#%ibQhoVPoNeNA?P@(wG zkwRNs8EGET-0U_G!J}1l;vZhU;B2G2p?)V4%3mGssA2#l*vDAD3@tuJFFe`5rnM>y z*()1|7Bx_7Ac=1eb+5>xMfQ$xW=`u(awTg`a2sNWQ1@`HTr_Vdus6Ua{lh?nGH(;3 zc9f%k39|nKyTNI_W3?jny}f`_6f37ddhl`d_?$)rGhZB zy>ec58*Q6E^4hp3b>aB(0;b>;bH5p#Zfo=^9_`xLfLH_|>I{42FzI8qqoe7LTgL*H zpMf|y*v`e1QNGrB?)@U+zN~MjEktN&hj|UQ5)j|aEr7irJE*wADNx&KTyEF^+c^Hd zTxIgJBs6Z1b@koAX^ImM^LMqv6+60j$_KX#rQs9EP2tMT!spi( zyR4$>hl7h3G9TN2T7{L3h8I#F+rRp^g@qRq5!X-rw^hexnFPbieQNv5r7m{=Zrg!5 zx*0O-Lc_7{T-X2Dz2sp7D8$XWPA@gP;kUcR94NwUc1%#qDjsxJe?Kz09)0iEPP#=~rXPFa_-WtJAN!#8FRVW=XJec|t#NJ|=y2_%b^`_&M>z)p)ckU`Dt%I+g zFEW)6-dbMH05y>4xzmFf$&hrjQ#w_-p)K3pK`qxwQ60#)-Nz#!%bGG=%#Oh=7B|-; zJ-S|%FDqqX)=ae|-28>M+oAB5iW4yvBE!K7>yvmPO(W#1(PrgCn-pT(Lb5DE z$uhDmO3C4(P#=QwXhdvp3Q0YA4%uX;3mLF39I|Akz6dQ@uwpcV_xrpkhFimd(YXDBUNm%bSbbQ{GY zJMhfEyHz-Mr5}Y}6AXM_4YZ;sW)qjhah%^;}AiYrz)oR|(IiR~XNNE`%Qmo|4_^Jybgb zy$W=Ocob=mbsi;n#5%)cIQ7}cFSKQ%<8wHgT>GObnv0iiJ*U0ePRtKPW1@sq_p1eHo9Ng zCeNO`zB1x6kE^wE3}WB5Sq(e(<1R{rdehyceOig;*wYc}L|yd4Jt%n=1iS%7Dm}0H zFPl=jMj2mc*q-Q0Ux}3qc{ygRr{^H)Wy}ld6K{MKF z_BixqW%Wx;l4Y>;?z&M2{mREzUaX)UbkIs;2PFmaV_Q z3b&XMdSO3Q}x8rve>%{ z?)2*2O8N10*I?!DA`xnKlAY@vF5np~;2AA{3P~p4Erj3YA9l7(HsC@w@LVJDYbBT7 zbO|X#u~|*#(?&A#y#NjK9mT-sk3N=dIDRV=QELG(+%#`GsLmv0026jNGj5{kDxC(S zZeH>)$%ft@EYVuHZ6~! zvuLM@awclanQdt&94%zUUZ$za@D{lZV9~o2!2PDg;WpSBS$LB902j`H(kc(8vic1* zThvEqg<XH-P@H&MjJbwIG>1tXw(|U zFfDX?zYx1uI13gPo9^=wnGP=#=>Ts4t)Cf!c1$<~LMNdKj@ZDFnnyiq%WAHFKqrhR zs90NFF?q#4cgHBDwMbGWfT#)saQ~TtIlW2J(2KB|kSAm3uNi#hN`zzvO{bt4J*Me5 z#)(m6PPt2G6*Z}7thQr3(#cp;O)X{zVHOWz2Ic2E1~M=&1GjfkSt$yKiKohma@Vl0 zTjI$#z$P;REHgoq znW`y&XJzW2K$Sx_AgE@)Sf^q%!A(SX=dz^4tr%SQYBvAyY6$KDsD^vWTesdy?9 zV22J^M3>9W3cK<^X}embljU4y89dfh{CM}?`JjL}F6`Rr$V8uV13&f*bokNN3b(5j zXiFo)meShyngepo-^#g`3VOWk$l8GTEH>tALuS@rXG_~rC)x43|MqZpbs+JWZcsQ^ zB~+t|zhW^{>YS&z+b~l#xax#Gu~ZeJaS6(%&*`JxRT?k3&n|v#5|WJ`emN zt&r1wDVbAUTq##t_~;V->E{ggvkURZcGOxYSfdB6`7_VL)vp>g4>*hlFP7MG>eve0 z{BItJJ6JEj4+G4lypVkbqZwtNtwvOta>G-OUPcxJ_vHk z^~J%SRJx98TIh5*5eYeusBEZW?zb7}XdE@RS4Jagpw0D-wJd{tt2Q|%@Kjk?Pe{@F z*{gP#u4Pr&a}sUUNy#-dMUi#=J$}&>AWMD7SgK7t(@6zk`-4nA>G=Dw$n~0pL@D`p z_a|MCXb?b312ktV;FUTd-q%Yg-QFw&3PGgFU4qgDuco2hg=z*XH4?Qsos3%a(URbj zH63a0n<7EMPD;hi2i~#`anP_?LAaPbun|-eIK+B}0u_3^}Y^*)t`x4O2 z7JaEnpXTUcX`V4Acqr~z-Rylsd8!M24!`yL;hI}s_wtPy{9*$h1$TDm9xVCQ0u-VF zg`@BHOWBHf?&KXlhtH=d74DzW>N=2biX}|T!3rsXzGx-Sij zpf}|Rs_RtSWGkr7E;`HizgWa}tz2NWKY)Nr|D&Ru_J5;F{s-4mVOtiFAMUG&n%g5& zBNhcj2~XNIVt3{Nny5FJM7oSe?5(R)b1lfAx^;c&p?eOP`SzdOt#CRICi>k$o{NhM zR>tj*l~<4VcUa%%6>5MlG^*r^uz2*5kK|Y%j=pX! z;urj*aNdOn42q>0FkDB~5`&p2fiyAUdjv^k=e~X?WMO|-{2$(lHhh4_^_PXySdER< zMT(+jAx-Zmf^0mWb0T%#UF`jif)vQJZBYQ3OcIWFqA^kkOcOVo>j5AT8@Akah)}yl zN?>*FEpA5e`|qQm!E)cSuAECEH$;eiTmEU_ukQIVRyrZX*%t6hH0xzc% zm4h}BEt8+Pxkt1IT_!v@lF|BZLBmv?QZBc^lr_AAUeoAX)94bDm@`MR2i@FwGwA$I z*)Q2W<`yM2+|wxM-Og!cp3|BN{U9zG!D@0f4@{7)(mw*NJi$Nwoq z6|=E6ax<{8(*L)sfXb^4qA1cAiQV1`x|pv3y_^JjNdIB7!rGoKQIW4=f*jUQKb`Z< z+WML;=5r?jcRBa%XYp&r&&H&($_0s}H$;W+lCtZ|wO)`_X0^3zuY2R8PF9<(iI;01 z?{CDO%@_LUNj8K*H7spcvS2FviD(8)lhmCfdSh5d&MB&C%lK7@U~=nhL+9{Sruum( z6EqyX&HM=*gD19rL@12&-xH3Y0sQnx=n@;8{S$_4~uRFN``awV)~ z$;m4Tvm^=gjoXR5Qj6@<74%}Q*$%?!$|I*@EwKdANxHxj8JdYD>~+Pal(CwQokCQO zs>YaoWa7|rhPR2SOleq_1AC)GJWNrt2-h(wF-3=9ham!OhooyFZVJvj=d(if>EgG?ceSa~tW|m)-`LtPBUB%7}*uij9+mANfS?j3(>)1lAHKj5!$=*+BGmhesub zN>Pve4BHK6;vU~hf5U1;M#_R(`6-TOv}SYMttvX1H{sV9>eWaa%e0U@LYp%8JKklN zH{2a~21WDZ9#d!5aJp?qPT8YnF+)}z#Whwj8t5SuW28%uGG<+xEhr3)-1g_=XVk(hU4=6jg<&OsR5?Oc;DA2%Xsnmxm z5i(DYnl2QSoii%Qm#bqb@j78^nOaFXqwMr7`j>BS_fu2m69zKrDMAPQ;%7)_9v5>sX>0%H;~dVqM8N&nSVT3nxg){ZCvng+*?&B? z@}1glOwq_d#XheI`$D^`j^J_U#;XZZ3opQ1tv_T9{o{XC8QAH^;Aa)cfaQC+!e19t zw1F&xG9Q|oDoVaCy$;`|DXS;)2bqut}URX;^6fZ3mFOH!Z^;cgN9!QdH+QYZINo+r5 zONhHr&(+|S?gR3MXa%S4Ghzhr#g7ZX0==X`>fD$m?Grvm&F8?|PiG*)(70}$$i3d4 zZvb9;KO5SB;4|u{&lKJh?Z4z+TGF-$z(7D}kpC4)75*EN^8W82>HmAA)?Yw%Kx9Sw zN@TO!BO~Gyq@NKW4`JU75a`tkBVQ;LCxh8NYrGws>T_SNScZ5gc$U5n*ka{2SxcL8 zF3LK^?U8+r;P8@l#zGw$GBSBMoln@BpPx@?Ncn!fw*hM2PXX6wLmM&$wqjd|g5Q|F zpsR=KM`Mkl!!&VDT%|W2PRr6|8=VA8H;bC9k-B2V% z1`*_(^-|3+^z@#yGTI$!Wjr5&6}SByus*P`-orYN9JMAmhUTS=_xFIA=rR^?TKC_{&@Fn&T zHBz4-iKDjaHXOKbb*v5~51Nnw56h2ua$=-xD)sPQhT6Kp(Jy;7&V6oGWo)$dC;awU zwhE4@fUbHyojeIU$DfhrL_V8IsQjKe5&*);$#|9Cl4S}E*6Qg4A1 z3XGfemSW)?|2|deV*1YrbFRbGF;$&jd#D_Ld>Og4Tshbz>UF~uqcOY0l!hn;@wlV0 z;5cn%Wk4Dsdh>t%F|kfh1On}CY|3r;K)I{*o|9IrYk-jrL&x9^%T}Cg%BqL! zpS@qfu;?^(7lfWvw-7u@FOj8x6Jkb!rd04TW;8|AG{JDfjJ;ef1Z{3 z%;-|`^AU@clIL{o^2y{mSi0yRq*=I2O%u_IylBY3OROuSp;>u6ojfq>9QT|Yl2jDO zijeRL)BN?;lQOjsB?~nem_2eSOvnUO;;os7pNG=3N|Gy7VNDM&oD**8H&NJ7+Ox;2 z3fVa&tXJtlj+Q|=4Ua-iicXE5scIr;qMem{XZo-VNs-n?x^(bmW2Rw7k#TjS9^l1+_81>TwCc0S zSl7HdQ27r4KWrE@P%hmtn~!20uZleu9#Cg_RI{CHIF!arT_&aICFK0B=+SsnKCF)V z-N^^H!bc_3nA>LXi3`_#dKDFzrGYj`BA|}$JIRE0(r5LsU!FAR7DyLk$mj#OWJ5RI zzTp)3!BKKnfB-WitnA_ouFO3f4HPd%o8g@rE~gAc2}Pk5zXwP;f+M>l)b<2H z;PQvHA-|7mmSJu3!?JiDkvf9z=@8I33rGvOgvPnq8c-?T4Ojk~B#18YzE9}BzC6I<$GBg@6w7CCj=tDY>5RK^wmc1KTR(*YK4 zcTg8Zi)BmB+E`=G*jzM*^)PLuKgR8~V0x2J26e5{`K#P3vhQ|j z53ssuolM(aYs*XuYnp91r^DYmj^F=^4U-8t;$sE@0?Pk?IIaNyuM2YjTWr`rnp`5r ze@9R&_Wl!&?v+tshYckyQR3Smhc`0-VJ8WRDo3m#ub1dABp26Wg_Y2@VlloYv{xUC z5X*M+;{(qBm;Ms40zZ6IVHW!I)Kr%nu7$(R`$yrNy28Xp? zC7+74pmsnhpqGyKz+3sI$4Jc*_ZGj|ljcoDbSV2|+hk_(%Od9)5!9IR;1H0aw2Yo^ zMdNOF@>pRAC#*+RxtlzgKe86##%mk2aqR!RxdKCwb9aF2+Ly2n#o4G1^94Oxg-dtf z+>e8=W9rf8#R1-C{o(KO*$_Ol`}HG+`;ph~2+0_f4y_5!y5szw$Zm8#{fC58LfOdB zFaEkBIwX!=Jm(E=S#9~ReIdzR65p7>{Sb)VEtf;RmH8PaTTJR-kYpHazxsRBGa2Os z27QB^pfN$Obmx0et`J7+cMQm6R^6Al?XkrJrL?EP1U`rcxV$v>sD9^TUv->{AwWqs z`aB51;&9Aiy5CU?e)$nvwmY_M+wM5$_wBp)!L7RAIrmhpda9m(=c>8Z7-OzE#|~CVB>SCm&Ad|; z85zb#Sq{3lFpAqJhWgpqDH|1pX|&i9VE|h*)zTuHmkG8uIi2#NXG6=GphSl)$FQNf zOH52Vi}>EZ z#aKr=p{VuE!aYgaj5cD-1`k9>WGMZEe?# zUWGthUQbMw?^7O|b_m*vz?pGKadj$N`n)EkFkWSo>}l({?g0rFtX%*T|nj>6D ztZhYE%(XZBfHOcmtXXneA>iUW+u$hah zljWge%~diR`oPRAuc6S+kjP`%ZcD0Las(0D5m@Wu0+j7PMdfB^c>bo=;`+3-5yh&c z1`Ow~lEvCI7!&42ZtMlA(uu&i#g(UQnn2^B>R;B77iE3HM6x5zv-L(4N06b`aNW)y z9uPT5cH|3cq>QYy3!>EOBu`=;FjJ`KpfGw1YTbr*U2Z;OLcAW%hllyeb;}8k2Wp1v zE};c|{39ZiiY|jF4PL5A)K!+|O(o|LuMeAVUP5VPk+bLD1N$0CMzobx7TwP2$^5;) zbgLx6jHL7b?m1&VIm(Q!+qhMAqX4{+JwWrCFIKQY$Q;HCu2T`wN>$Rt?VDvDh zcZ}u^PzS1*C72vvmmy@VQ0g=N8fHC zR3YXxtUYlLETNx`!jDq4&$x->2~L5a0+a0#Saj;hL?~9J8bxbCf{%NGQy$P@W<=N(~pvx3!L3{-RLjM?ffjYcKj;yp2EyU}t$j+F2;m z9wz(CkjP^+BMQ1fGZny|1~6lU^iGS{(_ zF~SBrt~CBHzDK|p^3GlFABol%kdq+=dMg53X@bFb^{4SQxhVISLfHo>(Znhg8`huR z9#CIbV82x8e{IU_93lS|K7O$de&jS$x$8U?zNf4AfH>)0mC;EixYa+!ym{6|N( zwP0>U!aoOKDD1yG1eyN#H!+!tk(-(6|1|bHbft5mVs+S*!%riCf>LL+UrYY*ZP+}O>Qp$m!rx}+TPLk$>S-C6i4eKUZZ zD@u-lAvDGm4$9v&c9AYCe6^6~8zvU`lqs4Oq_$%28$Tvf|Jl*l%kNXeQ!B6GsgfE7 zMgxJv5x!EF!d#avhO90MIt`tltY3~BH~FDw_ShnqjGype>~mGx+G6N(0~B&ayy?Hor^B{tC&pE(28qsX-lZ-a%P>y`fBd4M|}X(NtrT= zh`N{{Bw1CN<`5i=4b5_WenABD{oOGK#fcjHerkwZ*yPm4Xjq&eZ;FUg@lyjF?dh$_Q z?0-`ETs@dO*1_j`!6#>MZP>4-=qpS42O4I{v;OoG>U83CABaz{xdHhQyAI2Ww5K@$!EXM} z>$nE}4A-0d+(Ke0SF|~~=<0;bufrBHY-)pFF>EZV_n?5*vQ1@ zpM3d`&wo!EO)EpyC5$h7bI+tPFkw?7kRVdgF>!HvQE~tRaiXLo8w?TEIN1Yg?)34b z%nzNvRMr>DLl|PkGS-!@CXnp*c1tY`TQ*pB)q1veS0!7V?>U@FFffI~gzYDr-ZT7v z>2|pP%H@9Vm?(g9!G1sOn_kk1BGga~qUxRv!RnH4j+kAcg<1|Q_3IVxX(QD<6d?aj zzPd1L%SUdklWD^>Ym*AgGHVlC+^pE+;O@{#zQnwC+q1{IM%=qbwoh~H4A~&vB-pz~ zzn0&-M!ja(yT-h>XMEmQVe!!pn?c`i1W@;5zhsAbv-xbx^f6ktt;pb>F8aO{K>fAx z=#^1$_qxrS4L9{z4fYjQAt(yH{=1LDM?*=lz(lhwc-@C4{2M(-VeGa^_mv#Ghi*Wl ztLp?V`{_(N?6-9pjm41}_ybr^NIt)Zby2Rl~V zMMFkK!6Gf}#7vl*HdT?Ui64MKZfs74ECVSIL-7{lSjTCrY6{_DVARTujG!G1w!@Z?$UKbN49ytNaYONg$i%YX}p=v|Ih0I*Ayl%+G zWk|M8a_2YzwLNS0IE0!XR`Dcj>Ov=4Xwj6VR2WRmjLL6ZO-8ef1z(FqA)8@=l`{4R zF}I;5Gv;WY`b{|RQ3BmsFa`}aZkw#uM`4E2yKpxaQM@BY(smU3Zdfy0gfcvn+PdsC zW}^BIz@Me(>4nGUzV&Uw$nPahRIE`vgKe7 zJJB~=#~>o!z-aW0GgV(EM$L0xR%P5LzmdvBUr3pHCuSrs@OQ(uOA&&0Xo(OJ@wUxE z%z!Ie$$G!1m6t>EOkHJ{#pc(Ot8yJr5McQZbb9HIM1TGcK{xLpi{%qjerYaH9)D-p zUDN&GX$un(7p$)ip)~c%SDbIb*4%B7&Y$l5<_P1fNSAE=PvwDk!P)z2zDbTFd-I0R|tb{E6$^JYpteT2=eVD<;ORT8lFj*CIW75XWxDYGeFMPKbJfBaV z?Lh~#7krni_@U2e(|b(fK}|{oe}DDbs&9S1ui!YreFdJcm^4koXY$}wY(zG4)IR(x z^LbRpZF8m%seyaSOPZX#Bm57s5raEUeE*RRp07av^OrQo?^GZCi0`^B+42olyy633 zcDdtA^5EILha`{p496R^gTXdtjpA2NwVrDo*bE7(vkV{SC9;jFTv`&|u{sHr)uJ&fFXrhEK-OR~%Yis&s9Th40u$`O;h z)Vmy#jAIUburLqZHT5L{ZsaDHV<7@s*&8(f*p@OgZ&5~?%0rQ#N#V_Mm$$HK%*lFr z4KzE2g5I)?L&)HVAo?Rj^`$SF8l0{r8J#wJtf{s zcP7-CE7#kc`m32PxdTHNwOo6hJ!~DyJUh3^y`M+kzJO!@MMpA0cZFllYa9qtGnShsg;X%zIErNmw|N+RdbBzcs?W8z zXW{Dqia`31fan+0i-bB5}aM>xC6Y90g=5^TyNU74rwb8{KrDQyc1p6C4gx|BjNCv_Q0Y zR|wjRmJu`w4Al)+LJ3>nXqP*MvhRifXU zs$$G;^81;7p*UEdb^Q3Vr`Nn*^O!XqgDzGZb6gp7j0RJZH`p7JV}m$7huLvb&lwZa zs;3{h#cbjj+xn5^hqt&=W4*bc^$HIT{?oLx&{UGQ+5uIn?Ph$(Q4LEPT?!Jfsvhi{ z2=r!DF}XzCK9xP8-hCol>T*eaRZ(utOvW%X`N*%v_(iAGVW)V**Rbp;uhyAv+z0FD z{JxXv0JnDaW10o!bdI2YmNXL9y>V-tr#Ic3uaq9z0jLyOt_RYOflY8vY4!!WpE{8g>q))Tr`*<6>Zq~G2Zsr!v8 zw=nc_Msc(4)X6Y8zx%tiEno>U=p^%X%LGG3LK$TDnDQ~G=_<_VvaAV5_Y9GU5jg$` z3)e?XIq)=ch4cEEcf}cUreASA@Jm`6NIM#c85+o0?)+rhnaX*GIirL=!Gbix_gOKOZ8G(pCc$p)bX7^cSm`tN)HN>Kw zOQ)UVUqhu=1 zjG-rC>Pxk z(wnZl=Ca{|p5}uuW5V%z`k3#|=CI~tg+Lk_{9SVwamMq|QNexX zc{p#meTX{Pb($D88=SCu`#0x-)F|PhPOA?u6T6F6o3K1f(;-xvWkmzsDHPj0onGf7 zEc=Rj;q)Qrkk??*KvenhhOTmdhL6jsw8nUn8D+$N(*vBBDrYDOUz^F=C|b`y@sr+T zVSx`dr-E|hGl#4xs>4m9#v4)#+cQU2oB9d+?noa>R|1%q&ehtxuHgQ2KS(VF28{dr z-Q-kYj6}E9)@e93GY7NYgjqAg*Kmw!B|9al_;)bJ-yK30%d(_!D)yK4B2%@$i)nMv z$oCVGRn+5iK9R&<7u55GFz`<@o}XC%AiyCV%d2nbRQW#x+cOdLNciVlKPPzhZv+cn zJ@M^ss7b@v_<4cP)J+S&eIFLXSqWF_!H$&%wyyAc2VG01}FF{CLKFckxb=lB+*pHS7F*cC1Fq!YyHx}+MiP& zw3-qZ=4nny>h{I8{0@#$`=wOkN25Kgh+jZVDx)gV6jOzXzMx*4ilRYDLqb@rX4Z^Y zO?sCvl(+~{OZC(orm&Rc2tQ(F#uexT&V&atxLVT7f$!N^%(7gDM^^qc?u1{u8g3Wr z;A*7sX{K6Mm1N2sg?RCy0*;XB8q-s~D)vjl5d}@s2kKubiXT;GBm(y12MP4Qt86g; z@AVYLf7LaFOpP3Y|0N&iXxO-*sR8_2)+os7LNP-i%ODs5%F?2JGIKQ5K|{jPkDw5P zb`5e^zqaZ+sj+U{hu*gs{ZxmsbLOxkm~=W=uC^MrAUqB2$rIV=K{1w-F^KNmFfoylGROvd&rQn98`;c7dFTTw z#!U_56ta|Z;0%iOYc)WH{?_y<6r8?nl!x}v7&HyFt%{h#Yd0b6Ip5{DDuX^#p4gl3 z*0!|HU?3A@$VJe<~TTtB3jzyd?&q(hq&jM3A6%CIWztPYWXI`Wv z>8~#D?kr`)9anbLw=d|vk=DEFG)!llU+teBJs^PdYk$6J}r z)zNECzeI9%sA)OXk8~-S&cGg)>d{HJng&4Y%2@{I8;i7!vupGB%3ajue>NxU?I5aD zBCwouG{YaiI;GD!O`;~Y$Vv#zhISo6<>D4Q{he>I=OEV~(rY%*oMxx0?rE-*jj>7% z5M;%wcWq(BMD((^;+jvg4>0rx+eiY612hv5zybC<+0AiK2m{VYJq$D`y3@uNH?}@T>JZ-qa15wV+Z!3$4Kk*DCOehe{_I=)8R(QYvJ`?c~kh!NPHMR zi(Sty!(A?MG>^Gn8IQGIz%W8rkOrE^RPTkyKyUY|&8}RR*{+=~`z>OP^{IA=8GILQ z!A<1w-@Cv-q&t-0hSlF+QF^L-*3pkoZ&+7EoF<;#kOIS$!UASOm9;bQK5>j(s$U`l zjeWR|mG@esE&268I(pBY`Uc`*QF$$h4J{_1dudt@BizXK@UZXLc~buvt?cD92ZyGg zyvX;FQe&Qx!P{|^));W23XceG79Nz9v(U(6ZLg>6F0^K3lJ7H18i}Fu#s8&!Ruva& z8D*k8W}}DS4C`vQ0eDbk+L@za(sNW^S@0A>zrdQ?DqPEXw5dFXh=?A2Ew-+Nf-<%z%cg{eKV8bYOq^d*Z zzAXz$plpl3sq!onp6{HaU1O}~z=!cC(3K=HN+U75EzGXJtAmrl z;-BA{F*PIEqC>uC_T`fOdYWab^~|VmMG;@Z<%BrYF#wn^C_dNF?Qe>HR^T@sLEsqj zkp~L`97OgAJVQcMn(t%4i;X^HVp_vSe7I$PurpE;qj-*jk_Ohm&VZxfIJk5dA`^nq zPhaN?-A)|QU`l>}LpzKMisON;n$-z#zrc4`8%y=T@eph4ypDesiDCn8uL*c@J?im~ z*@%i*0p_L3(nlsoZ`1a`rv^#z!e;j39YaM|y&#$<_M~|&`-c}6$zS^USu^*s-*__n zp2j|b7*D8`&t?VQp`-dH9@~m-f5Vn-+TN}IW07n+ZSz&|Ev09-XR;L{o+bxu{S2p5 zYmy6@%IjYfsBgolVF|cF-tDCO`*-yh;o_2m1%m89d=+Uga&(i)^YA;WMURH_qVtcC z@E=J2=dFU&7t!)fOqLbZ79-^FCEu+3ipY0LW_0SE;uxj)=K&Hs0~$MV4_vDSM{o(! zF^Lx}o5c)+rM|M8Nu%eg61Ne}LeSuuG|9D3B}o$<{cpd-4u=a+jLP!pa@{*@@|j%8 zG3MN;x#^v{y~CNdVqX)CEDnvix!nDdO4#dGI=6>+2+#Dqc_t)EO>orAq$vOU|ELcn zZ;ISILH_tr@W0rgf&RblGv0p>IUVeUjhscDjoi(gRUIrWY|Y3-&1}sq{)g(R*e4Cf zjGVLDv9VmSL;&7hVJie5l*^|UT}K3~-L2prZYP}?LZA*5xJ(UO-H~M-sQ>2 z>Ok=N;r0C^0Pb|S4sC!S*j~twtAx5cUG<1Wq?SH-p~yX+rd9i}tIl$m#D%Z*C5%+c zr;e%y8;?I_Jes=Lnj#xo+kpCN4z3z6IH@?2Hg;~=MOWYQs}*Yp+AjcJjdn2HT0R4;)CpR)5&S!R&2rKV12@iq zKRz!(LJ_F%tzFf)TLt=>PUN)GON{){6nRCEU>rrVC#1!<7Amu09mrDo682&q!Hc<} zQZF=-B{SRcYKZzQr=g8sYd%^X#L@@HrTCP?zjot}(CUL6Q=9M2bGYR33O2)~Y}e|Aq4T+{%Bn_%3~3|DL64O==Z7&9$;HBn zAA?d;^_z+Oy3Wm-&)zu&^$+_t-3 zkEgtMx;!hx4Z1J50#wLU`+^k4UYh!!Sz&co8Ofk7+hqHmUaDedBEL?CZm|Y85LoLV zILEoD!jP!ThOvfLPnPD3!DTdcZQ5&GWwXWW|LbUF41OhvQ1^`V5 z5tcUzPNhM`0A;3_!hI)8$hbX*d@d4#9YsgZxDBWHAn!Xl;&uhT>$E%izz;hJx&AK- zKB5Dmz(HTWkeg8t%|4#Xv^zbB3$b^82;4e@^haNqD2eFsCrw3}o5Z}geJB2-NUO7^ z+~ah?#K`My%3;%wpF!+@pG9C?LHL&l5iWAUDMMJj1~+O)SW&IP<|3}omZ)M~t(~eR z6r|EGE@Xy%ROQdK4Sq&TFhqxWM=}g?3$iJHLN!Bf>mv z<>onL2`(N#I8fs>94Nui!jb1QIMh}0E*?`v%n&}hT>;%gc)(D}3?LNmvO~nk7kRf% z!ud9)pP>Bs+7MWId;;@UZmvkqrNj)we6R4Y ztMRmQpNE_EnE8!Eh;Wu!=0v+lGpA4C6+1{#wpA|E?K&CE@J`c*lH`*W1=n8O=)1z1 z3)idg+&Iu;+d(^i)WC{*?`uy&&i>YHf6A0`ob%V|Hiii%?8M-99Bw>YHb!bXk48k6;F+m@zA zMfFf84;1#**+mT(W=tL4lR;jQ`IT@=(^O@}*|pRqszcB3qG_gDhEO&cktoH?Ma3+O zgdH8Xne3l(Lbub~lM%tl;P{xG8Ln0g!;zt4Ca5D)v!Kn=G{vRO{@LvW2(O-5BWihsYa70xL!hOqJl#!vdZTPR4)iJ3tO zWkesN6IuO^m5;*cAeo<8-Kgw^+mBfGwKxjtKpVpfaQrDPhWW1AMM#)F4QgT*^}}0t zsP+yQ4(mcKSXrbLdOIJrjrViy3vyRaFcm7i_*}yV@}9I zi7Op>lfu?QG2C`JZUU{H1r99Um=t+aOlhklK}$nKSdi^aM>^Jp2u7tht!> z{Mr!@|8&%k_%A8q`a~+|1gDb&Qy3gWgYg&juMjj zmERyqwup5oYlpddN})%Verta$v|2`i()hDLS8r`r^UV)mWu59k4Q4{T`B%B9Algr9 z-F9q-EDD(c@j!cA-*Qx4Cfi?i&6A&c0fO8z_j?uCjA-r;+f|q{@zL>Pv`(HHB}w&E zYwaDXAJWUL(UjFOnh>T3ohI60B3D(l5(wPQWJ^0`qZJGl1|BLlD412Tl#U$|NOiYO zD^&`*Nf<2THfd{UA#{iltErNMKzjYKXP^y!%BEC@+aeAt3?1DF#X(l3b!}O!^Y4e+ zJGgesCrdizKS?{KliVM+0B<;3ZV4ZB)+cD?*eyQ0IgcX#k|)Q5xQ0bCt6|2Vqq^Q9 zg<~zv05{vvkjB-|f4cMj1b^0m`a-=|<-GL#)Lpd2 zaN5D8zp*`c#r49?S0NPRI-j19z#(rokIHO%YEr=sEzJ$<;fvjtNVDUsFf)m;ENg z%>AUeUlYZAbMq?ogmxM3JQ3RGQ#GvTcc|Y2#(Q+ar{Q8Y=CM2N40w{5*RV@4|NVhE zzu&=(RE<5%hr=JR-bJ{AHz1V)AiS4=exOQiaC0ysXP9(6HheH|yN`3ph(mMe&x2Jy zg6)b$#UZ;gG}v2Jn>H+oF0N91rAE^%`dSsgm1ipIw+W6wf z(JF72xH=cZbz;!EmCXwi@nyH9w$9W75``uMnq*s?5L<&8}rps1nxbS#i95mnArA8a$gK zPp~N)Z~(AgZ&0HUr{C~Jsr3)A%QaVq&pQ5SaQ(3yr89hYVYYrR-FKJe5Q3OI-3N6? zT%bLukre5NpuyfR7%_Z3{SLY3gX|(PYsymT2>^CBW)QT#XWbZxxbtR(%{r$O85h!W zxkAWutY@RZQ9~d8C-_l$0IGzAA}92DWAWU zP+fY-CZf(Cgm9TXjTk@2+$GhIA{qWb!G+N8jveXGko1AN8KBmdSpH7b?iQic9l0_* z74z@|;XPz8S;1NK@EE(y{02V4|DJwz)D3Nea|7Mh+?!(1{~EIkV&B0HZgcb4tHsWi zv+k*GtAE+1k+ttDj?axL`UCD;XzAi#h_;f3CDtDH$Bz)ezeBYDzj`&ugsm(TtxSNf z&Sok=Puu_G7{$pG_6v&0Vc$vXPA1t!$ubU`un@n{t-bOUl>-+gF;WU(sf*#K|D~A>w@uBC#5!L!AYJ_$yo_3jvoXM>IJX-U!V;!Cn#hOWyzRw zh+HHxI>#reOlVycGPJ-RATa@u-4^|cQ?q6OTIWBgkOjsXBKkY1@&o!P^9N6SBJ(;Z zOC(5@*O_Q9@FIFnV=3^L5F$QWFTw)mfKgLU>?UDFV#f|DANTIFlr6{LG#j9K8-S~; zWlSW0|FnprRW!IE63>ce4F4&-`S{&lv+PcMpg6=w!lF>C7An7~70Xt?cH<%toiTKv z82Uqacd0%5+~^2_js-v~r&QTSJYamxRpq9p?`ocmg#18BH2VXmhRiOsH?4+|Gep%_ zU#H2bRjfJ@LG^wq!B2^ z7zgq;H<>3eHo9;)I^4IIK8C2mrjVPs;&RisJud`*GMagq?;BR)+vgco?S{%=nA`;_ zD;l6S9#akrF)H^*@*V-^$~ziZpM#&cI7hB)AK4aEiSi&d$mYD@4H&(8 z9(@DRd-sGk2O2`w%z>j{dO1zddx5Shu#_fTZ@(dg9h>cq<3Tr_W%8%k%*;{y@i?Szf4%n?Egzv zj#cQh?pH+4UP@nF6h=|VjXo`o4-(7^Qnb7y@-Rpurzm0E>n>{ht)RBC88hN+cn zpy`&XZV4reWAdsJmLzJLg@^c(0r#`Xe+VZwo?*sO2(e%72K`sm%%*0c`~Hau-M@AC zqW|AV?Y}By|9NQez<8*rEuUnkaag@k*+~b^V)pBIC}IlHWfh~Br7BY^f?$YbrAlTl zl0lqv#PJ-&@Lb0Q(Vj=Z@#G;ZZsPa(t~l*Tj5y`U;Y%C|p7f-pvB?F#e)$>PbY84o zuU&V0o}auEfCogbJITMGIy4?!$rE*v!u9l4yLBzVV0&b-T{j#M=Ik_*35C=g4{Ml4;=9WAnlo|KvSx8C@o?xLZHIVv^nK605 zN7-L1VS*%|k1|_^f%0hK2R2m#HCQo#Oa)SAioTgx8C_b5%y&o`9^=PA_F?{>at!hh zQnPU?Y<&7505*WumwXzd$=d+}hx2$63Z~AjPM0RAUj> zhR_MusfOEIbMUn5tV2k{&iWZ2WtY^6j8mW_jYx+-<)kjvkXZlR(E8UW=mTovVsSxG z+SszLeJQQ!iG5P!pR`=sVz-nWj&-Y~oEq`bT&(97_m`kK@@+TpZU(?(s14}0L0`OxM{92?x@W%kK56k$go-7TaJSPxTwfLBeZ$k+0?V$uAinQ}J1 z6K2M_vyFUFWg{zkoO%s!)%?bq7WVJPS=`5#_kLIW9FXSJ*9fmqp+Ez#y5{B0Ghq$6 z)sxsa?TkMd^SYPOKv&6yxjA$MS2t<)aPRKGpRG%Khln73!lHo1`ZARe0IY*O!l7C=ALEGd`I8WjdQpxQ_{y9CLR(wB?nD8H&<0CP=51zJn8wnd5kA0 znyin>j#?hPXE(-2Hx^1Qxv%Fu&UK7qJ6qmCGghw)QG@;qp$ydbsxy)d^qx0#zndrM z3|7sMIjyRE@`F_3RcqmDS)XsO?X0kxxTT(3)SL4F1y#<)eFVCPu+Mo8Ub{JVztq{b z;43#*nZ-ZTgjeQ1?fHgX+zW;t)N8f?v>L%U&w@NgnCi0|^( z_hJQ*Skra=hHSP~$ok9SJxs)=FTvG42(|(FyLb*0>*D(ODAj;;<2800k6KehSt&-t zu9Aik(;*@C+1Bk-F@PtujphS(EDNl-!7tk?mySVA4Ao21Aq4`P$1oiqkTsmJ-6)Th zSM3A+2sK^9qf(I2pM97inIc<*O1@q^kSSQDopZR45Q8`w!@mZfYaZU0HKhMOI@zAL zjAqVyVJc)PV9Vi8EH39SAC_wM32-9%V!M-6(QyY{4Hnbp4!06#0u(tk@sG|bI}3U! z2x+wxOhK~~*MhbYF*CY{e)KZ*D6CfT>O+o}D0=*0`QMlZyo$BADx{ux5w@;8`A45`!g^iFh_XTXkHh`1fyio#sh#C zTl!*NEA+DKS;46}{IoxXjc6Q&g*a(&4Hem{@N25|wzu?6XqVqIA}H4@y-ago>sem0 zTQv-G$SJT^By7w`RIC$d^2@I!MK{N*QB>r9EUPUX!@6yzqTGVh@`=h<_N#g7H@(Y((su@7ec#4j- zk)i1}y^(E`rZT^2d4hEztoAlR#85>mw%q$i$q^rjnXX0OV3 z3zE3Jg<`xuIelo?g~H&jvi_>?%b2s(=3!z*#Bn8qJP8kyyR=v7swQ2;V6Uu_p_wpj zDZ(^f;iq8O#u>8M5hmEWj$ZcWF2gs~Pn0qu`IeH7BKzUy%Cug5mR)jw7fy5X3MSBU zn_BmW6$h5`4cAkmTaG)e zAOZ=8*q@@USPBL`HaDqJfEXZ4zH_7)%;ZLQ!~VrsBALCn%>2$RtWyq)-fbN@Y8uWd zxoT^6U!_1aJ$>1(kvqJD>qT7rNt@)jcM_5JmM6EkzC|)Ys@P3FO>njXJc*K*ijV&G zy&vylr7k+#Gw(_^)rM#6w#DjdZ~Cxm6eoue(N#*mvNa4fgVRBN3^rvh1Z}L9Au2na z7+at1+)j&?5hZl~c$U9PGN40iE-U6PnKi6!AlN+PShvK}P}G(_x6bjHP=P)A4Y=hR z6_9(;pC1Q~#ELXM5NPyH-zdA6NKZUPQ8A_Uhhh+ghB!4@_D_*R{$o0|XDe4?Ze_e| zu3Vpfg|6!iLtDUjd0xxX9AloVf_LD$$lnXipaY=S zkJlo_&u;;$)73a`p63C)7C1ER6qxF9*h@Dr#nSLoBm5QPpQRF~N;w2*+LXJZIbWjj z7for;YiCk9xnVa~k1_Hy^DaE{Lj&APwuxETy!^EbaE}G@jB^uiUSg#hXY9P6TBR#u ziw?6{Jl*7-pB&vLrS7g?3U1z_#x@tAAO@YBium?7sF`%NH4E=R+WrEX8R59`T*=bf zp`GQcGuXG+kF&_eLkIfS^X%a?Zx6U-$K2gJuNa^0#%)5q0TsS4^=3h1>?#++*>E0T zQNoKytVzW+vHew*Ar}kz-BpXfWebC{9NZ?+T2K~I488>mr3JkH#WTP+T=UaMZlBr( zEM*^<@A)&@vv(Y&QinR>(mxA=z&FazXfW9n3wsTV-ktuo5Hg`8t!txse!j9%&NB`u zxC8i*0vn&bka6rTQ0 zDW1|*%Ck(J$y3u7S-S}JG8-}N`ZyG!D`Z^`hNk@a#bORw>$L*K4DvliDjxZftXp%v zhtXX}Bcl*>XguGO-%SVOAs+Ql{) z4FP;zSz33zJsF_KEN4s(ugPD-H?M7p7iXReoGQJyL7T}N9U0Ct#a?_RRR9F_vo?@5 z-oIEXcbcB43oQDTO*UviyMkf+FX1jpJxPbZRj< zoA8W(An*>)ByqQ~l8<*DIuaZzwb!^>2w(!Mbaf=&?RyRh>9*dns1-S1HB6AZRQP{k3E(WN$U45kbEx?Kk4@q`~33gmWhf2qyo&k}X zOoyh9l9eI9jgFs$cd+0*yBT6p-tH;}eOZOIv}3O?oI3=0St)uo@S)SO$Wq9CW#zqF zNr5MtI3~G#Z>&lj9-d34eEO6^>7;bjtzl*#_qpsW+ z8`g*9T%!+3=#*?Sy&o$&!pLoX%7smm48PA2M3v=3OZX$F+Pnd__ZW@&+3NAHd0bbs zbllZ{CGnUo$+O<_1nhf{5>1-{N-9mfyEe^Kh79JEhpX?>K4yBx!EarVgkHPY*)pRb zYstB%W_;4)dLH6ZdO2Lw-m5F~TO^r0vxHLI0hJQEA$Q%3P*o$r+xyyyrda9$Wv}*B;{!lAI%p>vUFQoo7s(63z7URitHB}c!e)~oMX$& z#!i{ksEx~hRg3BonKg)0yRnj*lUE1tW_%vl)8A<>;53{=SncSq{-&8YGnLRBh%A2j z#g$%!mC^6<`;69GU>_3UiKs^R7vB;fVqxo#lzE; ztUrs8Ib>wirC%V?so;+R-tX7JB;38hs+L05b-QV!(;kGLRPk%`DU1|FMl$;Vt%0y~P^a9!G3~37o?{yMz?q$IijL;CiTlD#HOSbf1 zkG0g-0=i+2$-j@ka#9LZwE0E++(o<9kKc6Gz&&3<9ZX~IR5O=b$m6J~0`pLwGPy}c z;okBVMMnS$Y2|ENbQt=)D=Vn5xVa@nuI;Z?*;&${H{i8w2WEcp4&{TyCn7A8GI`5VAA-FpNXFNsWlP#>RMltc8V2M;A>#i*i-{Z7zojV;iXh4<8SYCWr!Hy>G0D#`5^H(4>a75AGDFjW!12`Jju_C#duFtf29d3D_z_pmB=ywR^d{o+#alB&hhkwjD@xe3Y(DJ%8KP1nJVA6V6Z* zzt`h~*J}pSsve90ZXrS-|#B&$VpYRn|5`z!3Wu&L8ScM3Mfvog!$xy5tpg4t+Mbrg@ zaHN+FyD&uA{1NL&>aj;*8JxAJQ3t^gwy}%43ainVBMse{uEZ$YOG2k!ux=S8Vl9#a zD`^K-`aS7QXMoeG+pu9YMt0~eu zbtn+?#ANBiAEJV=lDAr80MIZ^7&FmftOv_Ji^$Fnz^?x^2^|tejO(k9>7%HXqS#E! zu*LP)fEiV0$OeERsqpYYl0FNyEWY>`<>3#d%pnb=haP!*=J`OyY{8J5c^g?~*!(xv z-Z410b=wwBGGp7eZQHhOYsSf(aWZ4uwr%T;ZQD*}^sTk_KDYKh-#+`?bLv*Tzn-f1 zPpdZi==~YJwWbRzjRPtQ7Q^LPY70{kF4WfND;6*#1t9I^C%==z1Xbu`^gtKyyH|u~ z=m+(HD(<6U{H7m_?Gd&3@SPKQOA(OBoW{loBvU6_*FJ7+gO+Rp)}RKT;KZxWJWuJM zN*>t5f>lYm0a_pfGvVI%qBSI}#^s`d6$oW9)s91cWbP0WxmVR(H5^%m-X@}z2DD{? zNFd1WGupjJf(cB(GL}=P=Vu?63>VB9UZp8nQ7c)|J661=x?{vC7RQc;V6h^bzErdX zEaxt_H<{TP9;~fCh3&i24DBk{hEZ&-Xhu`hiUS|h$I6a?a~;Yf648gG#_k>xWvs}? zHlGzogy+Wbqd2AAuER(inXuBi6|YmrUINzqF48LPMjrkr5!bs48!Hx?_9tG+``zQu*$pySe8i^j8e5=YO(72c3^ z8K(hY;VR@~5-hD*N5@lR&?zULdqcN+Cw4$iDQM|8Ns z)q_53>H#iRuw&}|Q&w3*duH8?;(&&Q=w50kBi)Q>mX*d|mY7oqN;r{uAjPKa9UWM$ z1Tm)iEJpNxp^LoM7TsGzT$#MTvOm8iod&W^Y=hH3H8N8msLYI##QgPb>0aIuxrTtc445B2fe@GVuPbH5pll-Ix@iykxAM6rXDVx z-%z3~N&%8$_lyV*T9KfkFF6G5Jz>{4gwWqg*osB&C~)ItI0L$H+p0uM**Ox;yL7%+OJ-j(dHCD!mH2stM z-3&R0g_hq!lim#+e}EZ-Kf^IxN+(omT{0n8IB&C%Vq26z+0~tVg+tT_A0h)L7m^_W z$-@cxEDrszU$J}3*th1UCeuSJiWKJnbaNl}r@6SO@i=L=aqkVYupfFLJ-@g-$V57R z4b{e-t_-^BPU3jdMGl?M9obCOt`6#0m_vV%n$~b6G%s{*LSuPQTp#I4g$oNr)cJYP zTCm4c(zdK63=(Q&l;~1Mi(jzR4s8_QAS%kw%6M zExH`py(N$I*5o4Ps66s9)*jO5j5NyXMuIjCRXB!p1{by>Dkl%3bpqDx4!;B{A<$Omh-ji?y{S-rT!z3XXxybHq z3n^qr57)P*4MJH}!-NIwe@{maP*>jyjF#1kG9W!|9|*WoWQ5DZ zY|jp@s2k!X;T>kg<9*_E@nVNKR?gs@#LQH2ko>Iy)1;+KvkGH#h!SWJL5ly=rGgpS zwt1;64J=J#0MT7ss2ElT@HRQ%Xg|-D_SSOorJAq{vL2;Kg+lIBJ}?rp&5XWYNvB9y zS1YG3b?wQ-+4GtyyHWoY>{>_AQO~2PO0nWYudZW2M%Q3Iq;Gj9_ zI*7T&R(VVw^SoI~b}>;fV2|NOXX)3q=7gVN@( z7$tRWE#;|4`=z`4VYbJ*9`&ml!&nX(+zzqrP8Xej-e@zT#PbKd;--5E= zg7WM@PgM>c>KZ9Nc+YnXeSG^-vjO_Zyf00n{>)=)KKuiUFJQf$j4lm4|2T~XKXS3OBh z--!gCf}w!y8`1Y&S@%cuu=T5!u)W32EJRpK0J$)_TmWu5>^CcD)Ol6)>H#BMwLZ{v z_<2imK(Q8Miuu5-D=BS}HD~luuXZ|2i4t9=9Lx@fDgwr=uzD?cYczVF+ybQg3{$0M z)D0qApT0JT!o0GFe{x^NhF?Uo4#XDS1*cdYt4DeQi4r>wZ~y1WNe8?+wV4P%yMoF% zx!ar@xImWao*J>qSaoxQGm1JTH28Mh1ZeRsO212D#GubiD!wR_m1SI3@y z2#W52FADjb{$az(L1B_T~28`@a zcz84C?nIrONAz_Vx#s&xmBIp7j*V8m7XiMcZ3C8_?Ev}Xx-8v6UV}{0@7-dL;PPIu z-mMuLQp|}~0ZY^`sU9l9=jK#clLQM=K|J>1edzbRO5_ybI#CItYU06}(4PHv)?n)j zu=X{Mn?}w3jUwnpT1tI5%`D(`dbKn}lV-hhc{W<<8ALhuL3yqyk@*?BkiWkz%+bw= z>h#LA2#495JbUx#jN&=++Xc&<%C{z88Be^B*p}Gc@NP~fJ0kc9^DqXwX`>T8yBCk_ ztx*j-1=*DBSy9W44$gBCEvjB(c#yA8Ao-a7CYzoxgyDvnW`9zExx<}0u#99(hOoE_ z*nBht%ycoe#;n@VPw=sUd#6uSRwdHMxZW1NMFll!2OweoAQ{?w=@F(P>D@JJn=pMs z$J9>Nu~-04Je=aNo~qxt1%JWh?VV+I$0tZd(L<2du#2e17TJYtNWAyIpton&)Z6*< zF2me8siO|<3{hwJ=o_o-Pfw_&nN@3`dVDW*phvNZRS%i|J8$~N z?XvDfA(5@Y@t%XHD~s#Cr$_e+aFmiKWvwjqEyz3G#D#9Fz8(;x^s7d|O{?kZPojh}|g&O*y~ zgbFVHIuoJBRfJUh@J*IDzfxS1siy9rY53hTZk_5uW1|?=mAP5CXbz@%GWNLEymj`* zmfys?Z-fG3k@l_|jby_@p|Idz*B~+Tqk@#yEGg%uwGz#w>Rjv5WPVJSSO!K?8S07} zf|N?*HBw1s<_ zUV;2LxSD;8)5T9tM!O7%QK=?u)HZj+hh0Dyj8jiZRK(D6MbDu4UIwQo{?h|a--fsg zG*V=5(74?{SVumfpcUiFc>pm$&c7dIlDy(WL6lLEIRLZ5B0qA&6JGDUUh_v=hFDV+`dG&22mi)VtDW<%EA%Ry!Iy zaQrp3MM^KUDNW>*Zk5OoA z#{NiGn$`}3T#Cwt?KtKf2|G1*_0rbx+IxPS7ijK0Gor9~Hl)dA3 z*S{_L2{~FZGyZ*1M}1QRM-B07lQb4#X$~RQK}V-C0~C_DS@I`3h!u%Hb>C8eLB;_{ zgb~N)X5;UzuU-lR-`k|@eJLHjyVB#A1B1dTTj5;RbrBrSG#>BkjkIkC^XrR`x9x3s zARi!#06&2HjxVh!qWG^N;s`QyEA$qRM>oVYLjLd_=ylOpGrPDZw54QC9W%PgHM}MJ zx+kiL>6J-sP~XwIX8gfpp$#<4oLRWdG?bePB`?@QKtAdT;4DP9>f*4dsrpcc)rH>% zy>U)&a_+T_AIs6rRfjNcF*4umY$!;NDn)KWiZ@f%^3d5>?kX)BfO+^Uf%$nnoyA~@ zVmJYWXrxjO^fp*!~`Uo1Kisq?t_#l-;mnp^&A-V#s{J=@gl@%$TJ~Un2?( zT7hPKCR0~;-Lee<9&D9nWvDg>!nf0^!XX-UlrSGtv~x=aykWzt@j^YzajJM08g-%K z@BF>rCKXOrs-F~97=H?Z;jF0Mkaa8Huyrfl&{-121OyNl2GH5UJb0)o?c|S)-w2B_ zpcRQZo?}a_E9IJK^tn?~tpw)vil&+HDmua~qxpnMfz9XI71S&`f&MYwiAu3FqqyI7 z)C)$1GP6Dwvmv*xp7|HD8;(jmvNM*LYuoTk?*|(sAJoW1na5xrb3yv8BBr1T#q*3GMHFr+(I3I= zbp$bZyrI*fXkQzO7dsY_BO&C)-$+Dmy9Lqw(1FqIXxFqrb4V7VH%xk74tsuxKjF+W zBp4uW00G;TNM^B4Xo5ox;GRafHkp_vp!&vE7KFuJa-GFEMfOgIG5%sou}`OrM%j|r zE$KJ{6@zplsABOD#s^`oUcelL{}kjr&%rZ&nXl^$UwqlQ4%;B8%HO9##oj94gN4gd z%PiW}MLV`?RTR@e+iV-*C%&_ICylE>6(%EQk~YKD1FcKhp^NL56-Q>j7g>yT;nu5>V!Xi8Z#{c>N_E#<$0z`y zT!34eoS3YSjE=yId@0dKCaCDCMiXUP)7d3P)F+aOJZoDW+GDPbP_TeAFsGSf4oXkF zS;tAf(Z**cD%mQ>O$Vuc|Dy1^Qd1h{MCWc0H|wnY)vq~{f}x8FX3)mT93kAQqclzv zvNNX2p5$H*&-Jp*mK{+9xoZ-*Yn$Z}V&t26EZlPwYD%y2`{9rqN`i(Oem37}DPp$x z81X4A3uQ_A_yO-CN)iTm@h9R+V5sjycyJGS|KxDP;sS7cR0_GI-pKjKUuL~;uP7t% zz(7DHYycBKt^wL{{-t4=ASs zC<~9?lC7cZvfP5QIxyYL_gKOli|#*TdBe1tjj`=rocr+ z1mQ|3z~%gc*BXn~E||9WaBM^qz-3&77Zvi2`Ekh?t+Yo`{51uHWpm445OEy|3P3SF z(_zd_`YZ&`=8cY$A?-_;Mg5#I)vKUNUz;Gw;;bH(-#N;B?&JDS8?S|~r-Za_MgCC@ zu-gCi%oTx?uwBwQ^GR2iU1ZO|6+gl}Hy2sp?>-)x#x_wY3NHoY`e`_bati)XMwozn zpALwiP%j#6SMTVG`6_Ns`>k#B)^;8Cdr6L=V9wVy<{jF7YyPp=D2p`JUphXD;rU%ATfHyx;ucjKuZh!gS;X@(J5RdKC z?66cMQLN7H?ux3wu(Qq+%Jnmk~!@n+(=+uXGA9`k{8RZbjEmJa~*HSbZ-Cf`vg%OP{-He z9T!oNK_Y9aEHA1wk{f6T4Cvm^O1sMBKPUO4t`#AJnj*!qi9 z-po;*Vd$uOWRt||w|MA_n%}U!E8(0IJ}{0}+T*SJbNslir zAU7Mp46wm2ny_7fvFdSG%|Z5g6b zXX3@<9x6PxDP{U;)WEqWyKrW0sX|ZzyQmbWn#?g3Zt;t+%-oZR$zG37O#poS#Hdyf)?1@sfbol9`?n>TsRu9gj&XF7Qm$rxjcfrhR!NQ> zEY%`nyIw(t5Rb~zB7vlDi3l`z)#}U()Uws$8*pkbTq#unz4#7AV@YC-PxM0z@XawI z?>a(Q@0lwKOCI^8kmx-;R{gg&XEQr;muLXtVoI!a1p%tcp(D(Fo&ZLCasNDsJqcd+ zm0?_1T6&YDWezXaT9dQcEv`u*vw=w3qMsyf!4R`HZ9(wCX+V6NfF^7?sZ903p)qf- zGo%jGK0yE`RUm5~b!s6w-E4F}CtG!ZHTxIFpO3(Wcp|nh2oO-#zm*G+{Tuy^k(-*U zmF<6|#c95}<7l9LX482djCq7#a@S>;We%<++fk8)?5(VD%FmTIp_$Oo)600o4d0Q@ zMW$kvL77n{7U7s}ryw_@LM}-4$s5Ce_!BtGze2nqaAtnX91!T;?Vhy^=havC^SqwS z@b2;MdAss;FKqepex3%x@5{kv0y04$W;D}2B=r#vAR~d~0hIuFVi}>D@&?in>B8+M z5b@GH36PQeRDda(hWzeM_&7aoIpSjc=3@Nli8Z|sgWOGNB4EqpBW3$T3zlKj1BpS( zLyXW@Y`Eg3JTm2$&Hv%M(W3nz$Bi7+cKj@iPJfHpL-;EXa`(gx?s4#abatJ|s_s#^ z3am7Mk=2HKz)q(DOS@t_XRn!j*PB$eYeF$6)hja3?g*LT#xexw^d!LKRQ!(vt2I{J zP@E~^>4PT3?&%q34z?fU*{zIhSz&a;$TCFlKZy`CvNDXq0FESPX|4v7KOwCC%)IEH&sC+FIflnl!F&@~mcLktBELp}I`wa;dpuD8nWwlCmyP_9 zcn_%e7j=Hy$z#{AV)uFD?!8F0!(SOT>wS`A`N%^?GQ1&AZwP~8W-A?IhotD))^-1=r;vV;Hn&nJdW}%u?&NWIa&lQzYyAgSp?2EZYfvTZ;p{kz6D=e0s zR6qT>fTlmAT8$2)ct}PUC|te9MOVgfu1(#4)4KLUTcJ#2va{Xx7qteS%3)dJS!Jvr z6C)A>V_f=FVYCHXC_+i=0EOx}soI2PKy*0{$c%Es#!L#^dK#|c4T~-cu3z;I>l7pI z20KmA0Rt-S?!NJ(3{;P@BVNrs+Mar(hYS-jD_#S2y+obEd#d@N{9p~uKQQH!Ulv%L0s;)@yUhWZYM$) ziq0Cn@Yjxesv@9;SX3dqpOe8IZOL61Xk?;ohiq9-pTIfI^U4ikkD}Bt+^?l**Avlx z+Y`hGsY7gfv3~M&?Ne9X^YK2W8h2{ozkP)Le*F6Ne&otorRA4~tiVD2@qJ->jov%T z*hXF})vIOQdgFk8xN@3;_!E`;-3#e8qncT9@Zxm)Lh&+Ga5`E|BFAg7n@pYd9;+pz zbz4g(D5qPK8g@dkiy!{=@fZ4B)fE)%JWnwHQH1Wi<{rY#hjo*$vUWc>SV^Jfno`TJ zXu9k)gRra!6`1l$ba??!B6Nirro~?cp?>(mr_UOE?M|6~!AzYQ*=LR*dYENieh6J9 z@?thvQTcka83_-pQt97WuiL=T@jC=dkRQ3bBt{b{~D;qz)zL3k^8vZ9GP7!k^AN#dh;PR{~Di)Nq)8 zU#7!M1}dxb{z*bgVoVIv%VSwFU@h19d1Oo_Mui|l$SYqB8PpS70mrHk%rVoAimxj% zV#mwMN;BCx!2Ygr}V`I@Z}rEI-Xh?x9@0f zrk(z?e4`*I#&C*hK}zHrbvO(SI3uB9P>+n`&%_J9uIr)QmUZr$j7^6)XV{_K6B69*A5JeFDX3B!N8ilaHj zv)h9J0_s8jUz+~^!`MVB{N2j-|3sW5CH-mok2>kRrL`ind6nONhB4zFRl{$cA1|5jkp7YvY0)fWWs9?GWZ`B${hGz{#lrIT zHr;X!MDAoT?58WA51~P-n>4G0qnqH!=a0j@*Ge_qBFaLRzTR)H-5(ige?Ybo=a?eY zjN!pn`wsCACgSBMw>`rq<37HYf1M`($}O^yy&SP&jA{FlZm`%T_Q|>v-8V*VbgZE_ zzoQnCM{zmnb!j!>oP)+Y1ygM?&6U(^VMqfT@B7?#eR{CXQ^P|x%_ftsvuF-dVhT0= z0yod}p#%G2?Gn987BbbTvj@v}Upznn?iS}A^O!$0l&&k%lI%K-x^G!OZ@@;C%!-n# z9_|f0p1JSH;BdNFt~uzz7jCUs)|y>or#tf?EvB>6e16Y(s}jdzmh#}nDy!N?0Hv@{JCN^S*Nsu@*PurVN;X{!gCgmHxNU%&g6;1Cj+sbhBGoCAQ01(a|TtR4-uXz zbA@Uq)9kk1Ue5cl_Xyt1=H{0}JA78f8Wf=N9s^6nUHn5f&LXq7UNp=I3?f#2CW0UA z15=SP!W;DS3p(f-SH%AL*BrI`ov*6yKKNp#2-*mZym=!NCb)KT6s@{8F2L=r;c{5d z3aVtiI+UI#7se_NylW_k&`2RYh!2hULdyM&jFAYxNy74AeiEZVf6^}Ckh_O4d0lwq zj{Ky_<^rR=1<^oWCPVUlG|E@#PDPSi`cjD)n4DWl6d8O-w}A7U6Bwt!(J`_ceqm*F zhZM0pDuPJ68ZJXJMR3bmLasBE-3;L;|bi*%)e zy%u*8Y6WvR!!R_M{;OXf=a?I{8IO?J;Oc&=AgiRfnw=`jzb z$9AvWVjERv5i;}@>6Dl*9qv3hA^=a9H}f6QI5Ax)$cQrrCeDRu1FrW5y*&jgwosy2 zf)o>_SFZ5W%+J;kUIKtgA96`n-W?nI$^JmW7oFGh=VN*gAAlhB$7q`f@&8U6|M!5R ze-0+fimj6e5kd_4>bplrL~9~cR*~GdHqNU<&WD2X@2AkbLa#sA*u1#Z^I?a^?+qos z%7Y4yVjKeGr1^ZA9@#W#e`_5<6N%W3M4V7y_&z=Z|C{V~+)~)4u*r2m_Mi=bMGtAK zSW24|t+*8#ET5%BH4S4Eb>Hc;)343Xq(7-fOdXT=THF8Z2kYH)i3_xT^Fq5qSMmdbz1hot_m zaaFN2ayI)LpwhyBS5e3Qd1LoS;afdBv;J<+-BJJ%CpSpwk>OEGNGyhswAny!i>0U2 z;QCVcQ0Q^pRPw+1O%e$xZ$KBoU2iP4%I|y`ac=lSW0xOe3klqO7M2@76jLUF%%jO9R|HRmfNREy3t3)_M#!N$bjM(X;dd0?+>_U zrQ(`NiE#2q;6OPZ`MAUJt#2#7ar(tg%3*SZCSD=ldTROyxmP^cwTRMPxD=Gy;WzHd_K=80hR0@0!{T-L2uy+ zqS;sZBV5PDJX3oZ{M>&#-2di$*$k9^+XuuSw0^jb=e#>`cZ&o@P$h=PkKQ|S3kBv5 zKJ&AqaFpT@P;#(df`)sy-{9v%|MQQj7WxW47s()T&mjKXK;1D0_d1Cs^l;r5`s#V# zA4qtnTwBO z=&35L(T^}&>JnX3)5^CXc^=J2&rrWe&Hwl3t}VNXwr_e_37wt0GRDot$qMnzOqT}E zY`zp7AL?a`ED2wux}mxSc~(PXW0Q;wyh{bg()==AZMTjL1t2mm?C9<+pTs6#n;nOa zt-TT%`s}g9*eU|(c6+LDdCg>|Cwc$ymtc@Mqm#-q?YO(#H*;|ABoBX(Ycq3lGQ^X) zhGP7ZC{P4V8B(vd^b+~phK0G6qPA;EnqPQFN z^yuEk7`h#p>>6_x@_1n^Pb^)~X6M}GrBNEe)?x zM2VXReA(&zJd{2(*wAF2CX(1)B86S9VpW*|f8}wd&unEkZ5iAwzW0I}#AHZ@aC5=PbRP?7?#0?}aV}w=@QsTS5Dk6Nl$OWh%S&j}`J4lJNlYc2PMx zmWp@;G@QUf)ZRgQOxe|i(L}$i9 zC!`G-tBdBbXf)$Dke6%J-obm49C}o4i9^ud^@(2se+i7IWjIFkwqs#Y$r+&Ot&p;P zNc9=0zQd)!*mB1uSC`UlIud)CzK!=%PHHVZ-WBo*jfzFNzlEO|aUB8IG6#*z$idvJ zkiFWA!qCDc8PFC@0;E(Pd@n!`q~xXP{SVPtlMiz{C1m+hq@q!qSkSlu&V3r89YML| zXej}~{d#q+Ai^z%9122yHSF~XNr_-zr0b{Bzcjk66Ew`L?ar#(J6#g^eoVE-=ehN< z8jq}_B^hZU{!$CW!q)p;KGIK0by0VnaRorUPEmYyXuZQ)J*TDJYBPyRYZEq4v|BfE z-?%sXrWzvm1k)y0RtbyGPK1#p>e~m@M5#X94FV>d7eT|RWhB3Kq4N2XD=jc@>(U(# zsTP(NZxR=pI~!M}La>pjCtCCw)ICLAz4$*4{`l@t;9Ags?D>GfMmqC9LV|Pt9 zi{kL1cdUnfzNv(Y9ek+?O)wSEd%inl>}p7|%>%4zMAYMnb<-u}MxD8BJw5U=Sv-_o z6aN9J;q}^tg75e3e!v8A*GUyFy6+ySb9eMxY4wM@5zNq(eVFju{+yY3{f>;^8md z3U~tl9@Up-;$3Tr7h#-;Sh%FXyaZ-sE4vpz50ZjXEJy`P=oK0Fxg$L>`Nekm#XVzP zV-t_SiW}^!TSr|XGym)*3MGuZvoocIXyHpMUl6w4B_#khq>HaxT^*U?3$JYD^X$%t zsV!;*Bl#C`@S(@(AAM_u8*rr~km^2aCsK-Xg5gLhm*VgXokEGqgDAe(=4C1xS4cYq zlY}71y+m}bKC!mAp#K)TuwB;AH5~f}qvqsZT{&t0kykN|8`7hCAzmnjJSYW}Eta6) zwAw3<+2O~v$#|v^*)4gYP-a~2QmObEF99f7D^Z+88cq%YR|i=$SuFUuF7c0E!-fO7 zgBVx?y21&uykf^6!m~(=9pmRtSRt+5BT-;nCat?Y%k0h5Mi)%hiILyOEHQ^Vzc+W0 zyo0Sjfnpz;qG)LmT5y3M^yg{l^A6@284cu3aSh2=TO**6Vk*x>w?Aj2#Rpf}z) zCcZNY;ta~LvF*ZR#lf{J7ZnMXiOy?NJ>DbEDz8xa?h3tHl;98D4JN}zSGA*qukv|N zb1<&fy4Ke`Y%cFbEnerE-@QsE*qEnXNjrD!(zb^HE-^5lnN(MBe4E+tiZfCc2sbfY z`;NqQoY^;Ei9cjDQk!40$P#_jr#^kg6ojoUj&zmczc}s@vEiTFwdA#s5j)Xk2PZpt z^Ap9>4h2ZT1YNk1gmB3y`$RBeC9KI9r8#VJg{pZ6xeg7gZgR3O%Pp;Y5T0a{Ow(eu zJ3G3OG19&_iXDq%H+O%{eB9Hv94A9^dR)1jftFg{Poso@V?C67d+Q>I{Kq^eH-buY zx`_dl-fYdNfF)ro*68GP5BaN&VC;&Q&aZYa3ZH|-&zN+b@FVW*DPAu?aGnvWK) z+-Y~+^20o-nR@2V&8RziZ-gRvlgG?89wrN1iyM6d7Xo#>`1hQ#nC07jeV%5Dt7qIM z%}NcD&Zwt(WB$M`fA_Wh4$Tv@Dn-pMAKZ`5RbNYt|6M2iZ&CyP@j~X$FO~nWN{}GqFfWKW@|BT- zw>%SzPU)bcon8o1fxL$tBucGTZwhQJ&E@F4N7m}>Mkf&PqW%E7*9)-&L)Zt_4Qc!? zi7iCa-^bH%|1x<|`8-jhkOO>Ss3QW$p}L{!BopYr4t+(rqF6ho=zRdi;0I8&Z$iML z?wC7-ooJ?bnK$L#+4X0+8JlZ7oVi8Fnvr=9u0!s*B?e!_hVYvXAI;YhzHwZ3&ksvD z&c1}?NX)homqHw6WT!xorGNzZ@+UL3h{g`$%wNzCoP~|N@k+mQuE89xATwbw8ELaj zDVnphxPM<~35^8k6YB~LEp!q)T~_jP$L_a_m3`x)TX5*o&fUM#T2M)s3M~(%Xk$&B z47O&ZG}^)+7%wYX_{|Iz>N71>lz~<;mV)kWaU$ZJqBgGoCKK{1CL`6nB zt345EkT+j`49pn{E)@b}i9W{ni#~24y~zBPgqmUX4NGW(ce`}qIntRbhL*CdIbgB! zMeOdd69ZL+NGsuCfolRr5zf77Nn8s-*neGJVa-D3wls4Kq zrvh#8!Djm3hOiE@&O6*c24V4kNL7*>aI-=%6A@sFt8xYo%j{;vtEtvq(jlvCa2PL5!b$KQKOeHEg_R<}V)-_)2~h ze&v^3cWFT)#_pevjREww-nysnH=es)zCNE*1b{mIue(ZzOJPj(IT^3=M${O{5#5aD zB5YFkNapnchD*Wc_MQ8~nHWf-uP<;6M|C^Ha{ToteRQ;*PB`u_`_(uT_>FsdS8|WU zA)G%*Gb6cdbZ0QJiPQ1ek-c=AJ~7+GydtIQj;ll!pn+Q)Y?+Dod-q_x@N zr3af`Nw|6yd5p2Obl5ID*|JD1*k;4)PU{ZyEM4jQcQm0{R1wZX>>pNm@}s>k;{s#hhq6_Nl!V#vv3d^87DFaSS84xxNhzEoiD?VR>g9~514ezEt! zar!~m!SI9|t*sIkhYQO_(|tED5{}oH^HEs9XVIJ9hj5=H(|y+jD`!UqD`(dQ+-&5m zKN$>py{s7~C{o2kZ5ZQaF1W_jC(6OpXM$sIL&gp?@JCN#0riS#DtXw9qMJl=b0S$| zQB|RpO`_GLd>WK=b+PnTsV2pQJaP>7TFVUX`ZSMOwS8sUGnEK~DyN@}cPKS}S2HmU zl8b3abRzt7+@+dPx}0^;O4D!;UIUHlPykP~YhM5^2P)Q~Enk&vniO~3`JUqSD>)t~ zvYeLrr(|ep>Edy7Q_gbJ_v#-^Gws=gdPz6s=?gEo8V)^N{St#>?v1K;JOQC)w7eMH z@I%C+B?leMi00~8Q>Uk*Z|^I*q`W*L-1aTR1NkE|in zrudQ;X(L?<$+PTrJ}jC}$ms;WX*p9*ngi6olNdV`mQk(+@g_ICauo8lqQZBz`epO3 z5XW@r?%xodw@l3K;W%{{8@2p|oOvuwr#FIc+#y{POwxa_E>$4&UsHQ1Ntb1*Q976N zV&PwVMZJ(P`pwPvIs^wPoPVwc(R9#>6cu!GDMZnJ2e0|F|Mq7L_gBC>4Q_;4$fFtG$_Ui<_`nxy;j=yTupNAB!vt z$}Lgri+mDY9_|i#ekg3FGdHjj=-dP-@#?b1+POz340-w+B4iKw=)RVNT=kp^Af0ku zFs3|`OCPC2KS?#S)g^wJgaV9rX%3=|>{kdHrkhZXp(a zORdnc+UHrJJboZUIV~_a6$PRCMUv>o=chEow@NdTOa792Ir+S#xU+M8yCTsJOeJ~q z)J7^w!+GeSIx!&5wOiPGAWI*cPvLw({s>0?025jh+8P11qKLyMRk|;{o{LP_lFL$< z=@fGxp+82CmP1kb@w~4*{u=bW?zj(sW*LPr0U|}%qdo{SIUaP$>{(3`q!Dyt51Vw? zrst6tl;n3$&+SXsAdr_-z2R8Iv76NX>7|K=A?Du&7+QV}j%ivW%i*NHzb_HVPs}d1LsL21SiB5qM-&}Jj?lAx zh!iAZK0_ao9l2;dq8CqpM`of6Sv7tkt@Q(y@Uk8LbFNEiGL!|lifgp=i#w%kC zT74qfxsgu7C}peF12W-=%p+Wh3@6r&doHL8Iw$88NQ0b$Xte&1@K0cT`6mev*|$bj zC+!Z%_z%#G1qeH2th{5yH|+0f&5e8k8X$T@1f1mf6?(jix6=B1wD=I?HyeI z`jW!%U#k}=|NS3@TwR@&&Hlb>6|5*HGa!iQyS_HORQ|ZXC$xYMtq+^c2bPhqXeCvF zp|EaBsWZ13YYY8hgZ~cvN$I3M=mpuzNWgPF*=fYjzr6*#v9~Y~7ixk)0diSJb)OnS zP3A9eXos)l)R1UH<%piNR*u$HDm%4ZRSek$mWbIkmR*HVbDvE+NvAZoVWp{ ztL{Qv57>#MifWRTQNQ{U$x2ln!m+oMADN!@rF7KaWJ-7qphfXs^hk|gcW53PmGg$S zK-l*ev_TdH{?Q-ij?EuJQvFyc?_7Y~L)id0c)Cu_5rJ}Tq27OuH>Pn^qU!9@HxSGn zRuA=NyYP7fPsgokJ9FAF>lCvzLBLDt&X->q@plQG`rh-`PUknAc@-33AfRdBeiJMQf+45SIVnE#?J&XbnPWh2)MO5CP96o=Lg3U0O* zW1!Z!PyDToLsP}fjnRt56`dp9b#utDgCMJ0DXAlU1y()5MWki!IGng9UJOR#{*@;$ zSH4Hbv0#yKd_#oTN_!n<+DtexD9?poc<>a_Y~wsXEcC#M1<6|cQ9GSOc#svM&=+Qd zSC#-M9h{DMTr>R}(2efY34Z~tM%~$=uOXP*uO94;cH#SmeTM7sC(st1LY8|#bbkOX z%{dt7GBVZlH=yS$Kkol~plSabM%!E28M!+ABdgow|73MWY-$hB2P3lKjvlZ=qErg4!c3(x)0%-iqJ7f{C-7K9OedEQKD zSBhe4W$f}yP%nRV7%Mp>6;F;78Y)M8jkR*Ht}@jdA$+%WPO5Ip;|tf{A5q-N?GiljwxI6F6zzv?#a zBIURwlg-Ze7qq|~{Dau34%qymBvX$?Q_uy>J(bBaDl3;vI>vRb8FI6(@?~hPm3rMu zwG4zahBp0O;BJ0(!R&83Q(hPDZCgaHb)mi(-33ydy?KEo5M6)07=@FtlF|NvdimeN z{jcKU|FQDees?yqb@>Oh$Nv0q>kHQpNx$QKYp9DX)ycVg5k872#~2ITEWKF({TLjzrozXV z0$GX|mXtAQw_ZcJo3+Vs>`N8I8E!>L9rd@El2!w7QEDb`B@?zC+NH)6yrYX_3c3YN zHX^*=!;QDBZcyRc+(;&Q8?5n<#M0LQA9xL2NrK)qtm$-AP9PXXYwO?KKtZW()m}9E zrebRHrf!offJgL(ae~O7YOm)xRG}a^AF2=a-u{|uVKS7K{zQB6-=a z)ob;NKkM~-KmbOdg+gC3rK-Xfccqd@$|OV!DJqq% zvR2ljZH&RxFpRxW+E0=W)FAH>bPHz-bZLg)~&dFD3*4}>T~%02Ukj0j+n{4Fmy}uh0!^h zkBTRjd)=*g?5vb^X3N28wtcsaOy%X&x14`{umAA1?Vp7O=AF;-=pF8}wZwYL zm?neGO>8#ULC|2!AMKOqxZ%pF?8xtb4EE0&hqw-a%~vT|O>~;xiq)P`d`?&}A+L7| zcs)Yk8#@YoV;=C0QHXE6Y5%hO{nH7rN(Oyc&?vMbp6a9YQf#sm_8WLUQB?JIrf)d+ z#QCzlNkb=oPua@T9{vY55ArVLI4AyL_Hy0wF}CkwkAlOzV=2|s;Pw) z%bC@)D(%3`-(!0jdY{kG$+-H}GC>7w#gKsYm(QEOJJLnnga7^P%Vl@>uhmcLqAuf? zo>cR6jK+KS(x+3;9MIVsTs+R=k9WMZRpyBQhIdi6i#r}JTvb=MyO;i0*7nk4U1E|F zrQK2vP5fllU|!c_KQJO|k8g6f8c|+s|MbXk$m^*?Pi8@0SN%P&9oRulydHPaS=v@( zM`h`a!gwP+2ZwfwGtSrFs>*9OFLmCl9;4OFoo@GInjhr`NjD0NNY9uKX}Wa1{DO>a zF9K#9KR$ez)ZGU)_BZS=mA1>Z@-<|gK7T3ngyp!%$2#otq-P$XGWUod$ZlZH8H0-efPPKX>`2&@#Ndv!wn{eITUt$@TI0`QV+!) zzYU(3ja1j_VLEL8oPLZf-XI5)uKP4=Z^Rtu#F=Pray;E*o6PH&UP^gS-M^d7cs)?D z`a;UJ@hg5zSi^{TG4R;-UYgrpKG<+--om}vOLxYsZLOivK{4ZhkI;m+zjDo(U;_oC*t2QwBE_|f}oB+4>nf1F&gRDM&O{=51G`+D_o z8E|TZ(u{XrYZQ$q`0c%O_HFghuhKupl^M$~K5sbidFJzyK^xWz7=7hb{OojEfmEf; z3sz=9|4-3&bk(hOJ=w9!2Yl#S=7Ze(KKBlukukQq^UGCLHv{QAldI<~Hvcg8XM5)5 zvc|M!n{FLD8C^6ojU^jwx^;(l+K2m}hhJOi7FF_K!Hc-BJ-YQszF42K*!k(B@o}CN zqZH$3rC(a|gLnDrqlg;K!sSQyUR*JHZ^19m0r&k})=!xB$+Y7AjSKk=D~euc%VZqw zUiy4aK(BCbtJp&&2WO91%+vn0YR{pwO4~r-*CqUJ@bQs_o06qB9?x|JfgeZ{E(rpW z82f$f_JGBg{wD5&wO(cbm)(lj7oAH-bg-!c*^F-@cjBTIj;EHNI8)jA}R{VsKNcd7s^@VyVLv@v-%JWUkyA*=B zkJ zQ`*D>1xAUB?2{{vM$?lV6fX~mTed*=rHhT(vW#!+0~0e&|7v_1G@;~(TS1(8L4{IQ z^}u^v828=3GjE70_vcjQ(1X>wpK8J^?t!>(?xd&3^PFl*kI$8sKPGsx@!UM)JEG%0 z5&4WAkH>ArYMU`I=u!Eqrs6*Z4-Ddh@1A3R9XdiPt zQPw-9dZH?@9+M5O7cE>cX399jR}W7fwSSW_MUc+8m#MTDna+raubsl8*uiY#9DT)2 zU_#zWo5uBz`|QPCGT+&y%dxoI`S!Qc8Wse4KAZC4zWUoyi}&d*TR2I>D`knNBjGEbn-|#l%@mH^iH?8SsvRq@sj3?>7hIJUwAh0{LRxT213Axr|pl>z76M9?w{MrA+Vhq^}DG zKcFpC8?1KZ9^|$zGny?rz9wqj!vrGnTsC4wnngP)`S$qE!eEPxJ&PshN2yk61uV{6z$urLpK=(837mG2m-(Q(^eqx zTisjkNZI&a8}=G%9qtn6Ubtob!uRS5GY1;43Dmu$C)4Mmb$@F?vhMt1&f_7#HTrB1 zyrlZ+-CN6~Wipi)fosf6XVphr>v7(Hce`oa$mx6a5vN8oWZ993wZq3%4EeNilT>xs z=Jjl!OQ%alduA5D?tiDceMso$1y!;=-S6jlB}Sf3nLT3uPNm-_HI1JvuUpsgE$<(` z7&rII8NJVm-%?BfyX(5fSAP?k~=a-v3Z$6^0mAP8x-8cb?v;bnrM!^-k9AVx90hW{G>qRIQoE6C79XSs~p`EioiX z!1gHn54%r6KbaL8%9?(|XN;bMam}Vv`wDW5m5R)q-qv$6 zhh13nI&Ad7`M)w2!dSau$#``stlq7U>P5ns+N>&V^>;zS_-=ttM%BB>D3G1| z##RI#*S~mXvZY==h^a$;9_8E2-?#AHh#X7ByxGH3#BNK^<&%eorsr~!j zwpI4>HDRWF_|oR=r9hCqERz|WT<73**YuH}QkEmkUHWbtyRW$l@^NI!!(flgiH*ul zxy!X7$rq=&JFL;p>c6FE&4lx(f6gk@Oy3$~l+2o;t~eZrfqOy@#Xx{kA6BI(&@iKBMYdw6BYH=e@m;$UJvkHu%ChtKKhn+@JC? zuiKRsODfy5wd}M?vm)!B+LV?E%GO~K_4luwS~-_xmt-8(L$TQJ*l&lzxH1Qy@g3L8 zTX$M~&~*8MbsBpQ%;qU$QoD%*BGRnCL{ug|N=lrSK#w~)f1#&(uwJF?Z41vQ{Z+l4 zb(f{3F8RI%#Mc-1T=&`e%&p_JY>z2|JVuK?h*j{;bE_82W0DtN?8tFBziGrFKg~3@ z>`YV64z}O>yLH2_ZFTZ4c`)Y*_kEXPvUJ}Y9amOpfjq|llDu*8&pfx0yY9GX*o={* z@8k@B6{*n_@KvuKe15s}kGu-=^gAa)4+gh?_A1Eri3|0vb zNhf6Qv4=a#V>UK+%3Ut4JNQf2=+o^|x@K8D`yt@**g0ohH2{Av{!K;Ip2x+69v5Nt zdWRHK*704$yQv918I$jZe|DI<*s$}tIg^K~x-3-D4m#Ihst7_4^|zar*%&Ta=$5s) zTa|b1jpu@jYG{_6l~TCweTST32jerwPT{lB;{gzDT#N5+*nj#CTA~+2r4j5YFqK@r1w)IlaGx{9z_O9oZ4)a4? z+LwSVX2o9iQRDOZS3njc|8-owzb!P`mB$k;cye{+Pwxzw?VlC*Y^K%waMLSp??KeD zd4S@_?A|*cdsSV6jOI+#-VPY;e75%Fy1UNX`JPG>9o!#I=RAQDz0OqIS5?+;`qthD zyZ$iP@W_v?Gbmh3)~QFh&+ya>0q$#}*M3SUrC%rKSSZ#5cUYmg zsk~o(-Rc4RdiYwL*x|FiWY4V7q&50i?v*VoP`iCCz zn0aY+`Q1LbbNhUr*to=y+08~?UQJC{s@|Jv5e%b_!oMkfjN~%~9d9jSoazG47t4Pu zLvwLBuHP^<#$@i$nbS5eH(ZzIaV*a7!aP&sqnm5f-rgAcRqDssvI**^;Q=EnIO)T= z1ZXY}m#>F$hn~Ca5te61ZAX({$&Yc?oHYrom1qWU| zR-avFI(N{g#(upHO*t|-?d9k8`C~xnVWE@;czt?^?*iUT*{g zvO20|9_S#l@*%<}jt}J$*^7kx59?1E>5VQq3{Sh-yY)+zUB0-0`8>6IsmiSlJs(s9 zMklQ*8m0Me&*JottRvfw4*vPB@v~aa+$!2AsTAofh3n-5$7sIj?M7d|c1w!!(Fx}c zbg)_)`S5yLws(GhMpJI68KOG0*Y#@^_KnK(Y%(9Yn5P6CqOU!hwN4j?cx{oiftykbD(Ps7ZPjhq!%A0-Luc}=-tw>+t8ziSm9 z+k=>EcKZyBo>l(iu2W8NM{RelRaVJM?P_1YyG^I}JZS!-H}mNo-?5M5F5Q^@u+KwF zyRNFQ8b5YqpB|=GGUVf~Mp?+`Te;ipHATiABJ70&CzKsVeb!}vIeUrQxWdhwuP!YJ z9lXjcVo>X|t|A4Hrd)cJIjGwZLG1CZ<*aMkg`v4Cot<(lymoIkFbP`&1lm2%!#_XU zJ2%K!^-pg?|Cla<-h_LzhYxT%Z)tjo2f{eZb`yN|l&6(B=l49+@Y7(!I}tnKgpbJko=^k(*(Q3ElxR>G1J}p zKOO`#?_MpLcXdt%zN3UTN_TsTlX?7SE*d*;qNqQPt?{()*@?`Kwn1!qWP$(at$d z%wKnrBJ87U4L}9~&=~{3g&06|6o=clHS^#yYKGpFUm{PVomUZB?Ut`(3MgK{u(TR5 zg#w*5?!>`WvNW2iDvf4^0XkKY9H<*J9E6fww!jfbGQf{cQEWb}YY}5HS+sN1N5GHN zPQs#O%a@-zITlx5Sg>a}lOM?zbOI2A{$llg<90y6LuFxgx#eqX7jn?{96l?W%jA;) zhMTtHN%vh1K)TITg{e!+*G_$Mzyg4PAH<8DRI8?*4|L~@jIg-U^7W=CIZOw3Ky)z0 z9-i69wzL4;?biui=}RLD?((DUnXC{tG0a^GJ^_Q<(P*2x3j?y2FTMpiOixZ|IG0V$ z14iE>S_Rm!Xf>hMw|vPtiY;+IOl~wgvgH$ERP*+8Yk$hoXp;dUmKanvE@Go{42$B& zd$Oa5QE*)j=|xD>Xi)%79}J2O9u%t0<8dPyLT0#uCZr_%K!opBKiN!44$nw(0IqGA!Uyu695rJ|sw7ZWBY! z-dFym4;+&T)^C7;+><9_?Zg0+<^1|Gz`peYLN^!#aC5lWf+5&OYO|fc^<;x7u&bT4 zXtcfjp6hzU5&DV{}PxOrhwOimb^Kbp-AXY)xIBzvfR zzo!6FloTr1SLTY67IF#E?=_tH8LW1?DhgF~K83nO@j^MQksNL-OG_3UbiqKKu#6CD zEGICS9n}|AW-Hxq876>U1-h`mzvXKsB^=?kF=3AkL(uO}Y%KbHr9XKDpv?j}FpH+? zq)@^43Ej95X1(J?NZ z%j2`{;=Op$tPr7~5E(0o<6`j53%2n39WYkb7#vGd#pfFCssxJWgPq2$69A|_j(O(k zl+26ego9)yh|i7;X+kz8?9b1X%+uY}WA+bVERO)+=Z?Y1T1APG&E&H}d^qgbrin%9 z2hCRt;XPMk+=&(0DIS2SH)Mq)pkAlUW3vApQyJ#O*tcA3|04|~0LR*)LR6C@8C!w$ z1`GAVp2_6~Fj>=yG48SoGw}f#%M2^jrra%*Ol(PP%HpJ&IslCgHqZqFKkXDHd_m-7 zAI*>C@ofW{;lPVAgg<%lgzc5UPsFhKgy954Jo|##%dcP)=K=3F0)zPZX)46F(NR24 z79Y6LCbMGCWrl_W5fyw!hOMqwDmMm*jh`$UhmJWSYCK^xGyIxkQYnlO(6=E zgq?SD02hORN43YGFsh*RA`m>huF)izE}SSAW>oX1#Hs+D;q|j7ol-!yQR#}hZ|h1b zgiz*N#E+PmOVL4Rega}*0l!9LU>kgr&|1Qa_`*vPAn2jCn2nAKsm8!!)_@?;8H07r z7YVIa%O_mnM}q0)cEotQ*fth;fo)r-fJ(=pA5?ff*pa+wJ`1Y`#3-hp+O2*8Fw_bc zJvaQ8kf9bNmT};_!LTY6FC(n(w0w1;ONr}8?L#=+KwB1z9T~|9;BYxn@eXV*JD4;i zY3S%Wt0O>~gd=N(3>8uWvItDB$BAkOnTI=M*8#>=(os7hCr^n1vF}c-NQPT{%csQj z1g*0)tI_}=oT0FnsO3vVkqR4Xm58BR-P~}^1kmvUXq6)dx=j~JXu&xzaw9S7Wd0a` z5HZ(jphn`hE+xt)b4q3LY!7X!90$~9xjY)Vtuzo@;)MSh%j7dd2~r6t0s6DdSA7Ot z9j(IpYR96=s>cY27hF}onm`JiM%^?I?_;C7EMB`q7XcJ)C zNDQLurV{P{m@s=TFS0p!r`n_yYUfm-=QEZ?HS}8_2{n`?{yXhlYB~^5rB6o-nAiG? zEe3G2M)8?3z~T^N>7Byg=m7XOMjkB=gjrBw5!z;u{E?dGgIXR}w}bWX0MOmAIzNaC zGGS~WaCgXW$hGqXt?Yq3da$(e0>~ENgEoY5QER~9M0naX{eS#O@w2dMBo_? zoJiRI0DfZgJ)*E}SD8g=C3s-t!=hYyOaT}9ykKDWBJG%@RSV8Gqnzzv zk0O*%-{+LvCPc(&=oXgyoPeqx)Ifte{{@nXg9Jg{8tZmT#{*eNmqT-G?UcV#Uu=#| z!r2w4jJLc3TR2e$O#l)^er1KG4v zMm0aVKzyG)3TP*rAHZib1BuCEUKq{*a!2a}7;1|_b# z>)5GwV4qFU1Yyl-%AF^u@e>m;hSpia%e46>4ikT5TX#LtgoHIs?`D_qKG>~`1(rR?2gg;2YW6DgjvK6aZF;u z&gTI1LV$1r23bNw+Z-ZksA0#4e@aYq@ym`bHv!T}Db!uQdh;)&l^Cnx`nR240xmz7 zMUy0}cVfHCmO~+8B%99AmdFFETi*fgFj@4m%`rd8DO-&G7WgFUOIRDgp!)Vp^6Xt` zUBt@YA@Yxj$MwDeRClD%M0bD`U1H>7qvg)DU|b|DCU2orp(Uv43?Rmk+j+G8GQd$E zIb2OgMigOi-^8nj79I5(0W^*lAcJba83jr@MAk#80`FZm-A=-37GH6Zm60+PR;&gH z&cDP7zx9vI44DIzEu|eAFLG2RArcuVi>tZ(Iu!}4SUaWBw8=x05)Iy(2%DnBY!T2@ z&W;)aa2`@XWih&=gt9o07{mU8g-WJ?GBsQb)LvWc{c`28rn~V1N$i!$re7xS06-AH zBlaq{3l$19*cKzu-d!5AP^qbn3hU{9>QJG=9<{o~J20b|p6sYG0g-He4B6&v2?-in z13)`Up=|(BdX$?(aJma6(T>ydWD**tNPmg(+yO@@tDrId;ck?;M1?6LQ>9t-eY?jg z(r6l;&?vl)At9B-2z)v$^V$QzeW#&^@Tq;M5a1G9lHl+oF~3yk%+DSfSu{kl#Rumn_Ua11WsCPB`G1Nd?-_R3lQy)L-oTk zQbONG5x7E8aQHc(o&!X|16K;)7(;~#DTR}@y1jkFg2nw1IW$%cilc%~*iMK2&>i?T zz{wa6p?!vNi2q04)QbSsC_tV!2D$6ZHpL;tr;t<`k7;Q49790=4_w@uksx8LU`c#d zJR|wUZIGeT>ZMUv&|{V)L=v8#K?Ju?Jf2_;5J=O}`iu$f_Q9_D1t?0R`mwyyxVj^es%CoK{O7qm8HtznRs86S&QPXaq2uY(#F z*ClPGg_x2LA2PhI0*<|tLuE&EwK$l@viU(gekfT0roX88z#c%z?JlV8vR^L=A;i!( zN;&s954J#44&8=vn_u&-IJgAPiaZ5_MuhPpTUHQo8Zx`LUcFdV~T zIDB3hoW4(8ZH9~NPaEPi0kGUe4lVhr>=zpW9`snS_FRKUd9bMEA%oUmPaYzrA9ygf zVB&!gvOP$c0Hd4THP}?xK0%DIATe#j7Xbc<6lw$;iX}w&XJ-iQTicfzWu0l_ex$nwBwXyfC%DP!RUWt@(=U!nx+B=}Er zFyzK3asJ5zd)AZy;BREn!`F7qweGp%on!_|=*3V%n-Ao3X{0-Nc zcIP7{5?|(Yc2G38wO+6}q}piRP{e)+Xz`Oq^MTTD63G)mj1J+y8T9Q+Er6Y?fJRqx zKgG7h#GtEdHur*~VvKPm_+e7gk}Tbq$DdBsTnQccq4D8E;7QXkMRYsjq$!a#qiHgh z@IUZJVwzMZ%{ej`&}1!*b`n?1Q=*}ClvJ*n-S_g9D1fb49um8@)IiLjAm1tH%Y{k#DDoib=c%??w^cZc!EPLjnD5M{vD zhS_%kf%#)u9(i=iQPxy)1Wi|(s7_6fj=R>k58&@j8MHuH94Kn#VL_bWXuhCHnhb@-@oI;Q zoYKQ*A#GRY znb;x0!b6V_qbh3w@GxBOoWgVpieP6(6g#x#MyRLo{}8_5>=+jg{u0=wIFdVPoBb+T zP!)`UW15J;>d&Pn5&#Wn^P}SbycYMz(As;F|CVeJ0hGqE*>VXsU^lB2&;Vm7kAi+C zKbRBN`qY?8Fx3~2nQ9663s3B@HNjfGSSlq%#xuV8!Sh{NG_y~L zBFE&yj&CKL454)X`Ot^Wj|4c$PvOt&xbD*dICXJ%ah+q^EU?t~)7U)r^l1R)X53ZG zns^c7BM3C8M{z(#Htrg&eFwl}N}+Y*%?aYF1#msB)q%SE>k#kO_k$`l+6!&eD!xsm zFy4?HFJ=H76hSbf32VEy||!9|Ra=PDg8s@0W@t z*IqriFDtjwcT;l*_AU>SHB*0S1i`4hN@Y=r@ z@QT40_^dQ?_=MMZT2)Q#*vv5EyFS9Uh35Z>nCO7W@6|h-F2-RkV(Kcfh;|MD>9jc4 z_U~_+I!zs5Db+v^6bjagtH{KVEl-u*$^tZ8kwsgUHL}HwV;Gp91Q#QkPY#Ky1(0=l zxhCdk0g|awXwAhSR~(@PMoHL=BuWDyjjZdzMT_Xd!35(m$h`9;_l^v*UkE4rK< zox~1>WNjf|1+%qu;;NMI3tn%p1`yzJF9$0ZV#CD9f9t-XCUQxCPb{wRRCs&mZ)Y>X zl0Y;`^TaHxV?mpj)lyAuC0-=)(Bu3e=KesU(>ej?hgm@Xt!-L>FqtRfi10V$o?dVs zxTaz*yw;%ztXC*zIXb)l^KGJDTDMcq5&OZ?et@kC!Ys|W=s)39vrQ$B<_{J-2HF5! zb@(;Lz7a;h%)~ZG>M1DcP+kXU0lL9Ko!Yobc#D5}0!a_9hf?z?X^kB_l zSpIIHqc{Inocag6qN?;-#hQrXwB7Zy+UTs?ityc{Hh^sC__4}7qxN5uO{_aq z%ADWTZQeFua;=n52jzY5KT~FMi_4MLNGJx(IxdZl{Y!cH*9uH_Y6KB~{;)#}K8KNo zn^Jc2ahnjgDglt%c^8>rc}oyYAMc1(i&UQd3u=kCeBDix=P)4hP^HlVFjx;Y{6~g? z^xhj>&&SN+W8p26gMbq}%zAdc|IdRGp#>#h+`W$5Z^J?1Og$Qnjai(@r~gbp$n7Zf zDOc5OraT13L|Fk1YLEQ*NBk0Ug{YbXE!r`ijR#JH1snjOkq>48dNi4TZP7?7N?v_b zO@_z_hxtlY=vz8rLQo#vl9t{D zEPe}Y!XymZ)jEI8X2Qsu)MO7_u6}D9*zxbOXeRkX@9#N4=-()%P_U*dn{n_qxwi_) z9WiSf-2Fc{S1mq{%vNo}>94u`LW@*ce z{sVhLU8HcHa?1sl=UG6?12K#FZ1Nw8R#WIiwsYGb&78On82bEf=yA~zv%l6mVwCPb zcFMtiS9@Fu{Oq8A;9rPCB2jT#q5eY_%=~SD(oe=LiZS><5EIIP*6`x|Vi?d?g1C{7 zS1a&Eu({J$VMh|CU$8PU%eQN`nu8BU@$BSjfoXpExBl^^oCg zvXukMdQ}@$*i|F{Gg+k+4&%uM!{I$!4=oyPDrQBd?*EOWq*_e`EZpK@u#_#N1o$6boDwm4+u;G5Yus(btO*tM=C^CJA>%6x25ca_mR`-s6U+T|4-3N zRJr@MLoQo-8Jp zJ&GL}70qWmu%p4oUmU|PBWJJ- zQ1^(Aw#P-Y+Cm-GRJeD~dMY1)d73(n=8wS@%BJ2)lCB-dN$R#8Vk6MW|5X%hSPG`2 zuNQ6SkS~O4>IQ`RJ@BDPFc1=sBI;#$)5)PC%`=cBv07)Km+^8?T+jnBw1X15d85P0 zF;bk(lQb0~@av{2# zi{$Bsl!Nn*T>xA7K?yw^H%k$*62alPTf7AGOGkVx>lg$ty5R2Y1*VHKY>*I<<9K8u zc&p)cCUaTzep~O=qNw3h1UT?Mma0bo`bS{#(YR*GS8J(NsHHDL#2~GgC-jQW0Ti!r z&5{-w;%tWC-_$qR{8y(q+yE48Rz|x!CTCG85Of^mZPS8hJ`GaCHUZubkVD%rm*FmJ-cQ+qmkKc(=5#L+IrovVm&4KoS2S=U=iJ9gs-Bve044p$C;2sMf<$t z*WRNE8&|Mt8~a?Fk^}J*16b=1(=y$C0f=HeuCP&hzD;JI@)!yd{IyPR!B%*>AdO~Y zzb{enk_|Utl*Z#P0QzCvsPCMc;s$~+?I3P;_vJIgNvGCkgnnzk7a;mbLk)5JTVkgqM1l_K zDj9J&;xGWEgu5u%{kCLQi@HTtEA2gJ6xeVEE>N_+BQF0Ku+am2(n@>C^mol3*cNiVA^X-)wrj!_{(QfvSBsehwH?550Dl3M4 z7JSExQ1+KzI~BbM!0oAmUQL=5(pK3gxj^vza#AJOhkMd! zIVPm!((GEqs=dHc(-OM-GT3e&q=C*+SryhM0*U#US}xxR@9dAnMXf&~MeKVk zS4H;H=#&lmmGGtQgSacT9bzbUpU69lsA97Bmv@~2EUg*tm8yraVrh%Bov0)mvg^lo z&;I?JUK7E_!kZE(Ob;4{69b?1Ztm|Wz%3PNwEWe7mMD+WD#s$L+8Fq{pGXC=O1bD*0fcR?Ew$NkYiGT{v~Jg!j0y+(2=l^hd!xq}!>y7ywOPg24g z;n>!?GwE%?LReI3eOyUy?4*_iu7yXVa*Aj~>#(Lx#*R3Q5z)f}E!GFCd%MR0ru3tu z3ch!}*nXa9ehgIbVrB1wB4DIuXrKe+r)IWAHwaZ7imKIl--&P*>~!4qpcy&jh$O6Z z6HC>ei3cywhheWQdbh1-o+QB;O!>qO&>(MLZ(aAG5a3;aYX$1DMG{BG@Z^LAb3y7G z#F8L*S`Gz9M?KWnU<6d_b%frq8B6w+E2VD5JS;>W+V?71To< zqD&kP!%NI(abf8AJz`nc=0h2AY^(~e=F?DkTa%6+uo>>9ke;^G6o|>a)Gp~09f;60 zT-fz+pIGFMwiky^lfuH)XqrE4UR6UIedpczuR;*A zvf2$t^>c8BevK5GG*7=zzLwT+>k-4vRULE#-Wu*Ijh^a!e$eJ3#%OzTGZ)kQd|4p8 zAR~`Dj~5Tc4w(g!fT*w;V%s^PCif<+@yny{T$VifXGT?YKEmcr*hB|X)Wr;Kd((a) zj+7D?Ql@?XvIq%^vJOrU9N4>IGIBC@OK(;2}E%^Mrh!_ zRfZZB(t=6FE5YL~)6J?w!LIG2qfYjo1~sBq8cqGO3#7-g^R3%TO)YQOx9|3~Cr5)1 z@|$8qF~fX;FmQK-%xXHk#dfO=>PU_m8*PgyC0$invk{)X?~z86Cv7dUd5Buc);uM5 z;bR~kn3-9h3`o(j$j2#z7T%sM%?Ks?&a& za5@*ZI-{dcj*_CvK%!!uw|m*bXK9zqpvHet_qJ$rQ$bMD2AKJIfzyb4$k!W);_#my za+3D7SDufuxd3dn0@}#>r6)OP2?|2f?+gleh3|aHq6p3yQ?QVzT1y;beLQ!y5FS=d zS4I!4B238B0CwiYa{yy++<34x z=2V<$-4P2+Ov~vG*+D%F9kw5ixDPMZ!MC`uDtOVNEvi9uCIcDEaeZl;&}3b(rQe^H ze`Q@r&t}f53_lOw_=C^oVlloPBsLp8qXWD-;_y=Nq~9loQUJhag=-!%vKGfe6F5}Z z4B9KNYYsfp-;R3{8qrI&K{+69Jh16c_#O9!HMI$=gZr{ZUBNnPWKegi?elNfA$SOYgd0yk ztbe5gc9(-2EL<|at*fvNiwDM^7Zyy6(q{OQ{Bl6_NnF>C^F(Tt-ccMbr3kgN(<&VT z!0M}`B@!-^9JC!LkTa6U2i6ZhAKXkAQ*enH5Ee@Ql$yrlLniRa@~OCcmz}5mlTEbc z2J`rws1TCl3)M~mX3>CPpAP6Hf$-^K5=;zul8)WyLja5(uA_HYR9guniHxsn^~&1; z05{N3d6*h4?xvA|?mj3lH4f-l3~qi`a7}iCPqp^wh_XLS;DKUym*%ezB0q{oB=rMQSB#BXw#)$S8PcnA`m=9@a z^xJi|q|Bu1r0HLF)@?4JWRg5urZP_!gBsHH+l}kiZ&=fN6xbe1)%jw;B?ijdZ!mE! ztODb5$()7aYK&bphl{zG_a}0Ib(+>7bukFmEhR({%x8v&0CDY06@&D|K)NOZQXroh z3m>Y&1tc!7#(zHw1W#24J)`cpOiYjtP2aT20{?tO5ruwVzp@-`!w2uDhqV2_Mz?(RW2#m%CNnQbl7P|64-?UckWjy!Ke%Hq690|7ac^ z(LC%y#*z#|oR~os@Io+$g;hRSqJCt&b}4*K87cxcYP})>RP5*{;fDmX}Jl@a7$ zjM?DT8bwtgE?hZuuFTk-|2bdqtr2AI8yg6G-A%Z(KxPy(0Ju|}*ESj%KMbDypU2HY zFyBKB$)V{R!t9T1vDz3Eruzs{g!4Jb+tY$+FCl%qP61Hq+GtsZMF|G}do-IHE*Pyh z9k85a`hT|J`e9=L7tZ6F>U$g)4?Z#61+N1?Zv{}`LvGksw)3aOgG-b~L5?g}-t|6L z1*}gO?MvnLj@wJ1F5%(C^#Vca2yVduUdJc*48{E@E3Ixu5G|}x%xF*r| zlH{B#rBrLxfrXol>zb&&Ejc+tT;$Yje3H2Bd()L|?9*C)b&?4yqd(d9&shHS z4ra3A$)}RkZ>;XmfY%>o(LGd!vmi&vS`d>@bNDQZH>4s4z%Vo zA#zSr(U?-&x?>=<|3VE(cu8W-C$%6?9>Hk8Wi7Fn5n!6m%+>}PA=nVhWhNZNe<9V33 zVKpw*!H4^T)%2vJd9fc&o@_N?kj0Fo{s#)Eck08zB5nLoYW@>>$Y! zNF+Bf(_E?w0E?DF9|4-yu?>`gT(Z3!4k(rc!&LD0rF9e1?6K(`I-gmTjc3t;nQ>4<2sifUYdsoqTznE{qo zT;+uQQu;>PmxqC!9E+=GfA20i@dSO=WY2+P!-ISSLS)SFa9nu6SZlQA5Riqj3TXS# z9daNe`OM%@b{NpvfYH3jD9Ywhh{QW0R2$ARYcGSoD)glnDH7WzmW&C92Widc``Awf zef0!QWpFckX&s1B1{)DCgP!d=nTW(n-mfO8=I7czR|Ev{an~$%o05WVDtu8X&*ve@ zS+Eo#i+kQ#qYo)u_+&g_K5Kf@u^I#YfV?N=$gygN0|qC4mjgO-a6Nt(`jO&v=S6XV zQnYGk6ihD^_Q#QwTF!6p2Ct@6;s)n6nv>#jTybN`Tod`ceO+3o6|WC$={!kx6}4-|`&$P9V5 zJ@Ct+p5PB-Ijj(3u1;U@XblZMMj?fENF5m@IZg(-MK#D+<~3IiB$6G`Te1e$5{L-{ z{}IG#8_qHBM_d8wylmXwAJ95=!dE^hj=hmXLF|FreIIm1b3N1D*aFS4T zNE#_S4R)`70-$e}MiYPxXOZUi&-)t`uiamv9emaq2!6ISdgOoKRU~|}2+8}g^a?ky z=%sXY>)pn*QO3j*ZsVMHob3QFx>}HuGg+`he zC;Xj%A?_z&nBTc`vuPM5R-yF##dN_G9R!e~ic@p;rl|q@*Bw20@R=ko??~F~?l|1g zZ<n1r7sP1a4%M3W3E0XH?a;`p zBIEDPHC1a*!iGaV2ZCMeh#TQCB=_&^8pT#ZMZ062I?AX6jaD-VZA5&rNdl57ut4%6 zb^K&*1A*M6jJDIn9TrC@iJ@L|Ox-saFwImJbvuQ}B-t)IPB83wByn(p7h?3XPUr&{ zup2i{-1VfGZh)Bm!TOH;>j2DRT=aXkR4fvjcG{N{6(Y0>BsHi)`*q3hzz+D~CPmTD zO6&|6@Q{$0Q^WG|PicWY`HqVZ{Vzxq9}Xa$^)CHoOw;>AF>_*@&!M(XFzP>jd!U%_Tz=k&B zJ@M*dws#HK`v;0>#kFsp1QfLrfTl_Su}pi-y6g;V_$9aye!xRgbav73y#Tm5#F@?6 zpUM-ofSx~7LK_1XJeDxC@#F$R{B ztOWQaEsuKCS+6Lz2-d9xWh9})}ZeE-)JZ5nN#6&hx~ctgG^K-L5TCw%sd zct-vD+Ybrsq`W2Pc50`jszvTu$uadF;g zEGcvXbtg$Z`GMocT6a}G16O%CW(m3s9fP@utXrF{HUlJ0CLq`!gB+YSY>PCPHPLszD z2bvl!QbX){z;|#+Z~gAgducx(n8GsLR6ze2QrL*$V2mMnmrL+El3r2A=Kxf?6k6f7 zi6aG$CM(3C(|;bUgSVHmWYNefIbIxLWwaJtSnwedURd5cq?%Z^0SGQv6&2oq1POMY zEIWWlrlTBeci#pqGLS)ow}4~`P>8G-C75|@xd5K!%c7SwHqR9)NBFZ8GMjj1thUEP zKn_<1HCsLl+F-We?w~h$Tcex3f?;_EzJ1UMRn5Xhf3KP%GM_o~)6&ggvppS+CZDe$ zMUJhIFoZu+)Zg}=FN}q=O)lY13}&uu14En7c?8FL>_EYdX=2QqJpyj+0(jozEKf|j z*b+k`CI{8~Jcqq4CAj0S*{eib9!d#x44V}B8@v>A7FF<}?Ey^aoN^8s(*i5ig8I2JpcxH1N-R!$>&Rapb*uW@(7&h3_9FIt@w zQdj#{URrqyT2m(()N@7@iQI=j#RD=4UcR=#8g}o%d$QOATwFFk9IZU9g3n?DIzSIZ^EiBbx>q5io z+ZY;=@6D~l$0OnR3Izo;v95X~i7t|uzfqmeK=-{4*GJ|0tSvzau7=O}Ga!bnIsq-g zg_EP?&jK3n$)Taqmlu-dea+?o#79w1VS#X!JU;Q%SSUCH(v3R9O6Vcn<@JGYL~0jV zak5}encgCh#=g-)la0K0V#z%ms}dIF!DbSQAoKtqN_M|}u12F>(?^ql<=@43@=dKS z#O#4+!h&XRf=vV+716ftS|!E5DM~U(iq^z6Ysl1oA=x&3Wg4x!E@}r=)Jd0uXDX#) zPu*>}8y5QaNuhqPzKaCpG92RoDpD-6`U4-s6A>Ej7)e)`6pL8LNFtnJTIz=@hF~`r z$e~rV%X*}UiHd;4;NNk1UZsF@op28|d-afjdw_X-CfQpzj9WwCD=Oy{P&+?^L5hO% zfP^uY&x<4R=~=U~hQJwFY~1TGw#Fj)1>`Lkh3?PX zGJFIOye>dl$6|2l50eZRd4nN&)G=|uNLx67e=BZMS=|VcqTierwbT$u1_>QZ@zg#H zH4N7kde^QkazZxwab9Kpj3Byj1{gMB`r#n1 zNi5%DZ=)>W@E;hXmM?pZBzo)1X7b^Y8nugBZD#E>u*pSX6W7AYq}VXw1#!3~m*A>V z2=-fE8g=3WnPR&>ieesAoQv&rw#@`N@(&XqWSVW(|3CAXm|}zsDQ#qPp(FAq9m>;@hg;k4Md45G5lGz zH-;7hxoL-c$7TUfTpcFqz}y(}CKqIn-?UJvTofr1vLGO$erHf{@A+iJw{~FlGjQ+w zE>99`hp>s3;5YH)CC%NI+UIM5Aof#5J(cR5Hn@4pkYcOjYTjNz)d$g z$G;B`7Y+~A(%*6P6ntw3*RVP@MRJx=9X@29*HxVcOx+?CwDW0csyJ?l*w~$W&tt$* zjdwesrwT4>NTK4I7b&bAOr7_v=C{8BKu*HNKrge!Vp6N#q^56$b5zLYLGF#zE`ax4 z9^x*Sn&yZ@6@#J?AHuIzzoL`S)QydGrEBvgiK}&Vf zTgaVT>rx#_TRh{ynme!|Y2zex5}aJ2$fXm5j3^!|U(|G&89UzbP=)w$m^;+xR^z{g zsR`I+Vx;E!-E(2^cMo@(Tw5tVQUWFk1a_iZ_#?pi7s_aAaP^7=mWd+Og`)|XwL_u%l)fsJz)`T08S;2-H|A|v>@J(X~VM@rNRf(l~5tDt80TX z7cT^id7X0cZqrMm*t+AWhoX~TQFrx5mlwb30?7HLiRxhT6H@5dV?$!VU6&Lx;hS_l z6wtl+_?9yI!}X*S@Aay?_U|KrY06VWYba|!iew9Qm;i&$DhGMOcxtrnTbvaZC%jK0MYyBO|VZm1-D2~_J zm#!$lVgMYqk5!TyB~oPQNza(DW*HNXHxDGAZw`@~miDM0Z9t=Sb4E|U)l@_x{Ude6 zDP`@!#Y^D;hp)8BOt%=c`9e&G5Ac4 zj5Hd8zOj@HK7+E!9IDN$k*m5S0!iB-haO|dSdrqAFz2H#*+6ON{k&^vJ;=aLv`78F z{19?^Z%TZKL4Hu1qwWM4xJn+i!b9!FVIpbS_Ro;r!5utuN>VCEZM*=s1BAok-|l53MBmLS@K>NUOkdQ zjr}DrvA9p3wZl-TaQ(J&eFvOM|%RP*~tX~ zJ~xsS@Xs2DxDHL-5ZH5my&&o(^ZCqpQm|8pp3H(^t8kjVIG7SFd_X5Gm=x}sq5KAI zc&`%&_fv=%a2?n|#Bj4ZkBTE+Z_qSKxWe9j()GsJ?_;-bx|xqXOujaq60Qd`mK5l@ zdB%5$#mqXC66l}H6Xa^)UZ&EXP%R3>C?VVNcwADby3A-cvG8hyQ$mI3v%zd~t@s(I zxd;Njg=<4jiVz_UAZVoI#GS>jyFx*`Cxv?12ENEO^TT;uN_E!rf1VBRspRAM%#Naj z4$^k_Xf8oH6hhr>8lFdN)Q(4sG(Y6KcbgeREW*8FML;FD4~yLza*P4MIvmiHI8p2+ zRpPO8&bY$Pu8ZIwLkv)r8Pq@nNf&xz?rA+uLi-p#lM<#qk4qr{dowM9p#T)(z}`-v z767pO#P^>d*p6zM2Raa1h5<>GV1Z{B1QDbQzLmSpUXxG?@@7#&9v@0>7-9=~;l#{U zN~Shs91w<(f;~*jlO_fmHAl2rXa!bQP9Tx=6nd4q6s>M93~&AiP)i30Q%!^w^#KY1 z$CC>HP)h>@6aWYS2mmXlazy|D0000000000001BW003-hVskHUX>Mh2Y-C|>WO8q5 zWOFStE;KGMEix`@VRD?h1C%CRvnE8IkcsMr10=`~-sm`R}8CMG)ja4CsHRoS2Fbos_&dgW~@X zg97=iTM=ZcX}352XXpOUMEj3oazgS_;$i?5dO7iXxruRE89Mq|co{nCsfp8TM~89HGo$b&+)L=2is7A1j28QlwYT>1W=Gtw+h z(!G0{he&$i)#}phBjzl80dB^|dh~kqAd3G}_y4BUf7Bi9pJ{Ao!|=bCK>HsOwidRg zcGf0_wkD2t7A8*r34-8%gD|wUurUN$*xCLkSnU4|)){DF{eJ;-u`qT0Phcef8SMY7 z?!WnTEn#DK?Vnxf4-gQ(|KD2``tK_{N78>^$XYl7O>Ipb>5Z)oot&a#grt88A&L2( zavBej4)KIi`or7mw8k3B$h%I|y?hpH-d;c7 zAnYTQ{1QM#{*IgntbubZomcM8AXPJzB(w$K5%xJuBc#kytRg<;0S zOwzK^?1P+3uJ<48Db!U?b^1E;zwmOsHN`nalVSeOroX0(jUVuQeS2b&CYyW8Jlt;) z{;Sb&`j2^jfP;W^z=D9#{vR9d-)vN*Dg(e%Mf;+k?`Q14f!amBQ&f@-#{O&08U`JT z@(Uu9SBUX;b)vDb?lk-CRA_&VdReR8Ayb7HWNmCOduCJt@-d1|u~DkLV83P?FG&h^+r-$R zW|;?nFznr78&-DAZV*^{ku8Z{v&z$S8Hp1hV@8?ciqX()fg7zlbLoGc z8lvOhGV$jLOL z^qzVPRyzMLTdGol9%UuFk9h^z+6pQ3qJb(Oew&pl$hBl)NR5d zv{F6IqAR3wc7^xdcj?Me2#b+s9#+2lcpbJC_ak9Dt?U;?Dk7Umcf1Q1uS0rc5pmb` zV?!O#lb?tBhXU7@N}C4Igk@NN8dnTjXgbSkct?4b5L^$kli3a1{$jMuQR&t|yk*RB zDkI5!gI)#90jAhFW$|dEM0lm-7$dT?#6#~I9L5HB8hnigUV}zn#W-nsJQ3h>KjZ*- zYA;jH{$Y_kAb%m9kE$zmG5n|Z31?H*2;r3!#*yhp8s&cOh*G{@Puofi1+!1>!M3Os zlt*n*+)b!mnft1JZc>S{ZRrtO{jc8R#r@ljZhfrNL|K=J4CnSEztCuA{A+Mtv5zp* z!c39P%v2ao)~v^i!wLj@g6~MX({^78H?SaU+8T0sGZ9XS+!^K63d!P@?5vu)i%%y5 zdAB`+Fq>fD7V~OXdv1BCt2L%$M`{ot-gVz|ma7L%fPfudzWbSh%da}_v>Y{nYubABNfG)>Ca<|G|+ahc*Ynh11WV5|ufPUV3 zE${2so->=N=jZZ;lTX`}Xp*cXK!X}enPXGQe#36$7BYR!y!@Q_Ex#?XqtB1uOCsu~ zq6xEl5}-PQl2qgogIJ~u|Hr7|&JY{^x*%`OiqMs!;RpY(s}S>E36p74BVXA@1>qMy z)sJkX?%;Na(OMBs*{UXRlC30X@b^yfJ}*ap@zpp>&k|6}W*G{O*}Y)`eau$tX2;U(X!@%6S(Ut_}V_<|UM40eEdWtA0Ed>=tSWja=A^9tl_<14#kq(j3WQ z+`=_Eai^aoFF_bBjKTVq4Gd1Z`T%(!(RZj_y)Re*euh61-SaFsK5H#Vj|m02=N{OXSky!MbXIR|#6k>umm!MUgKAeryX~jh9PJ z7ysA)l7Bqq2|fvsKtPU&KtNdkkEvA3_P4bm@ZZx;mL{}U;;{2~k6nyijKZAdpfoL1 z>?Bzj`d+OmtvnGDR3Mlngo)$`F`dz^rTUhxq2$?GRRTd>2DgRou>5|33-vPBSp{=6 z%D$dU0>SAnyG7fmpt zTRy_>7{bynyO&$?FLihUmHrssmpVkdU5fB00HROvQI6*gENag~9u9*?+n0dz$9IO? zdI(O@I1lF~*#iw*rqXx=`PSo3CSt@*JJn5|eBEMLX&>WY-tQ89ojtVxsnI>9fMv8C zM4CsYy%Ng0)1Db8K zfB7P#1l{qQN%lhNAvyx`zABqnNK>URnzd#3?%z8Fw4_X)${x8! zok)x1=1dd;ibEQMPIFq7_M#~KHa^W$`8$+?dGpzSYR;Z5UA|u^*%h!rnsv$T#fdsj zovtJ+GaPI*Yi(u8S!RJCG)TG@tC}4MFZ~`@fXv^ znrEjzGh&_xgV7MDtrW!!JG{_nwgb_y7_NnL zKcj{rQAPU0MEC0squwD9P!vu);;Brsy=&X0C3p*(c^X)0RWHmg2$5CfE6ocJ%h%pu zFZEe;wJWu4#*6@#uOkgF>B?r(d^xVDi0So#TY#XN^O;!D{7NQBTh2mfINWhFT|pyXiA!^kxj^k@`JtlsE`Lveq2s zIIS06&W^Fcs3YS!hWt4^Dy!ZR2~}yjPC7dR3&SF6b1qxDPG*(TtUkbASdN>bve+9i z`C&Rtr%6O3*ESYkQ8XHFWrAKqvaB^n`=B@oPM`u<(x_KkD#P6x9B44}#ZZTAFH zn%?_Ec4@g%yuoO-q0zC5J_KnznA}P4F2d{#s3)&6j4J<{WOHYct&~r;KF%r>VTZzy zQ}C2=k))7`C)2G5Xj-R`brh|~6P#j*(w8V}aF$luXWgw5w8JVjZP2`H>@bi()19h9 zJB88Fo%)GnsE(~_KfzAE^1JttK`!3>2-9+ueA2Y0d!q{*HI#uk2qkmivK)nvuQgGG zms&NG9*ZYxn~iT|R8P^5*InkkP(} zL||+~Ypr3AMq8ah1lcXTcKsN~JJ%w523KELlG_wvF+7$XHHfet)z(ndU-vOg!?XnI zdWWe57duFV1RF`QkHa?|KZ`jZ=Q%!xf{qPKUGiEAV$bEs*+k(_uTvF1vVAh*ZTf3)9~b8q3`tA$I1yTf#6=iYH9`(*AIZ|0?lv!Hr+wLd9my{gEig>0>u zw1|ITSgU^)BSm%?7Od%m!;(>|VtDUJcDS)z}W>PvVa@7x+1l7UrwyeL4(Fq?`7-Eij2+|w`RdHL5&4!>DqE--f(M9?C|#r|1M8;sKop@ z@M&Dmvg0gWx9Re7OlT`l<03dysXQX#_+uI>Vh%<%LH{D^NNvxg-ekzU5WR7eL-z-K3)2RI)2uba?e~H&nKS){jJ8dX`Q|Wk#>}F zJj&HtK3tJvK91`rmqqTm4Vi1qH=6PO^9ra7rcdy0d+A2gGiK70@$HJ-aa-byb0e1> znj*gZdmv%7R`G|!KCxqjSY>m8VgAC}nuSf(dH_u=<~vBDVX~z<)Z||uygxhMXA;z% zIp+afACTm`1zaC_QZL>4&H~GI`HzOxkl{-btlECoTJbi z)I4Vrh7$xq#uDBKq?uW9$GcIy1wH{*Zk0}Ozpt@)yA=9yAEN#Wypz((7f`z66irUm zHW;FrdiGBN=8vsiqH>U2vhoQa#+X9ZO5I^WJ-XxCCwEO3FJ_)Cg`tNj%e-&qu@70N z@VHIr@#~UllW`43-$3t|*@s1&ATeLUb>~h${PG>}LZ-j5>Z}@@QRt$Zz zFT{kk?6G@kd=5yTkgWZH@Imbf*gpL591!2(j#wr4*&dLXjyq#?=&*-Ia2=5Q`0?$1 zp-Vjq_(pOq&*2_5y`%NXUU?dZ@EBAiDA%t)ARQZYKY6+1Cp-k!myQx9 z_>>&6yfEaFZJWxt&=#6#g@4*K$fR$|WD5o5j`q6;=eCRj1^y`GV&Cyb+6BuVf4VW5 zv|ojI9&EHoLPMu_8QRr4qNzUTii!g zFg8D|1fwrp1PpRhYMx0&a!lD80DhVT&!q>%3eMT2+|DIr({PzG`2wGdBVgdF_T3#A zyjc+Hg$+NcCy}5)m#mEY&0>zW5nu^UhsrC_{?8@72%n@@&Iq`krAOQuDuZiX(Z(fq z7JI{M&zUY|4)bCRyQ2{y_eUlvsZ32oZ^A+HY40B&eGM-*$`FU(gZ7>GOQyn)NNj9a~CH!P7mtY4sJx23JOn$SB=%6`-1 z%w9rEdrYgL!=^mhiMnoD5@W}ys4aPE6dRMFtv|vC(-iK}gK#reD#%(DcS` z;;!dwO)%^n2^F3JKCoQpT!&fKAP&>J=x3^|0Qij><4k z%kt*Q^M{nf&ILBku~1XxWIABr%JQ1-)v%B7l%}iu;1u7|m&--Qzn;#w)*s+gb1-?o zBxTA>bhu$-9+MesjFz@rLIxz%b+`D8qPC_BZLaQMi2)i|P+X$-a4?#J;%+;$#&JQX z?_8#DvEOhf2DXg}^m>K8f*ubEn^LOl2Qe)tP;6wncOUvmUWmyi3wsg~@i(jtBflKw zONl=MTaujd^D41=_zWG`KHj%;7e2BS`?Tq6bl`zqa z&}0#>8q^UgCr{KSO%we}W!(#+DhiwRwZwVAy5@PCNDkUa7SIzAw5DZiM>lQrcv{6p z_Mqkru3tlfc5&t$Ox-SCX93owGBI>|$WG>c@0n;TGv`l|1h+luNs?33M%o^-?u-O? zLvM0}AHVUg96+>(-x8(q3B7zl=4mEmIo#fJ`b2Fe7cjm3;361acZ0d!L7UpSPQBGP zwDpaG{)*?kX>YxOh}hMZJ=70V&)iE%Qznie`vtE|zbqYOofr$0PP&NKte5yb{-Z3p zbs{dqBzuEgeFUFbpPwG~z*dtIah%v)*z!=bECrL4m|;}e9gsY(T`%lIMFTHV%?vtc zqB2fxoX3hgZrW8R&5m_$QZP$iH6(Ar@-&LE9}C2mFinYz-yDKIWwK4?qh8g_w=#!^ z9KUL499|EUM=nRAm{${_eX3$tO@~>ClJ&&pu6!o=^|%E3kbA@=j#%0V1lRcc zS-5X7!-V@di?z2uS;KU%u}b+aE46$<;|DE+LFdmNC3JGNi`in;AoRHF5MSF@Y!zvx z&&Qo@7`oQ8{KcFq?goFJ_Ur*2+zV1S=iY){`eG-0GxZvp){2T{{Ef{;D~OH`55B(a z>a9OKZuk-`ts%H-eAVCj`dy?&?WnrKB=p9RZfv@D*KbL$h%WiLaY^L*!;?2(IRDyj zuq15ocK87T()kkvgy;Xb-|+8kZXpvx`~SD?pu8^qlL?8>!fLr%)v9Y7Nl021D1=6c zmWKvzsHAwyw+WB4N=}CR$&dp^_yHmyovB;lCggf+`rDEDc!JE`$K4CGHb@LpOqM&< zk@3l}2q|B4n5L|~( zZbvrpKfzKhTwsdjsWVF7qD)hhB);~-+$;<|592-!(=g0fta{E@HL3cGIQa3md|OxH z?il1$Y{m%VUD-_@Opl8rxre`Y@EXO%hNDQVXSJQ&uV@qIufGfdHd{A5dV?Tia6I2y z@Qd=SouL&p*NsjjpyvjD>{$vnhaI%1pMmAW;a)s@4zwrexUY>eu|R1^elQr`?w4y{G>D=ku~1$km=HtZd{snO!bA zxRe|g&|ZN)fxB2McfZ>Y5{rc~JVg0Ja=0;i7;X{+GkKqj{pY%Yo!2__^2cH* zB(jLBd&u>@7nx(17ZcRWdOfbV$ts#nhhckfERFV;tzPTjTfPifo*P}B38&qwyOBq+ zZY+RL?b*O@mTLO~uHZSzpDrmzBb6-XWT4}*vh z=>roW5KdB16qN3~aQN|&i!o$;LQ0MA`ED*6;VhEwr5w4`_Ecu2>%n=Kf3slyVT!{z zU2Mp2dFII7kd(|W}886m=B{!T%lRNhfw^l-t`3Pxb z6Sf;!t%fywYY#_;X-=e_2$qDQt;qqUn&GAJ6=ZqEW(Rns;r63;*>2%}a%0HS?zM$s z{@Q7SC?8@}&1t@%3rR09zwa7>#$tBf{u>Kb0Vs$bA$HZ9YgVb9@jf1)M)Pkcn{1az zW?m$CZe1DcS=(@+<)WiIUS@<_h77PAq8o>{V25SRx{r#~JQ8TAc3e;X^&OPD+6%(R zS@nQc_5euoQ;}Zc+bV;$q|iMnt~)2PB#>5(pTzewm59kT5fGUymzY72tlpung19v3 znHiFIh;mD)EK1RP5JIpQuwD3=j3YnIr>fB1+eJialtScFtxAWK+9bVT{n6@tbsh*r zK{0+pT7#UJE5;*Xs+f9w_8w?8d5@U|f_iJ6FCxr(MPi`TGca0SBrRX7KAld-1aR7h z86!=CN%>WmN>bx^B!UGek{_UX_=Pc0i$~hU+Y%64B3YOx_JGZsbu&PlPg_uzn6(~-TB76Qdh`N=sCA^#%6+C2)21s@h6(zsOeq!{z6W&u zL)FpX?79wSy!Vqg?&Y`9K^$hb7o#7BH)E$;R9Fip>UE!$QN9vtoahbD{N^RGYD?_o zRpx!px7YWx@AvEUMF)qTC%zyLxrj!1H)FD4296D49wE=)k5%j;Be>F2dbTwiqiN7U zMl5kS&m_~FI~*8efnYg2s63Py>T#hamyrSEvG>~g$W*tD0puSvi|1`rJSkIfJY0Uo z8oXKI9@WQ%3DD~@CUdsLxJ}-e9G7A;nH5>qoKxv~=smwpoDcuVnQ zIG;R7zRI2*^%kJOUMQni%q{!yDH%^NDZVEt7+0t4A><8Vcp=X*!wA;}yZJG{MzEf-! z69jKNaKsL>da%E4K7nb+^SPbhu3Sg*u*b-%hD9xo&7cv;E12xb_jt;5i`u9b(r!fH zz>eP*26-wP@0A9X%-Hq~l?HL5VBm?;;q^NNW1Mt~;L}zPa>G*WXkqnB!Acd%y1{VL z&2S4)(MHmQE6{{vmp)~R=)=-c8zG>AW?YvuQDwyBG;W&!b_ zCD~-c8y%Y>DI56P^prkj^3o=cmFf45O7D6w@^{{p*&#Q!c5_2&Ioj|1zU5t z&1gEQEBl6_479{$kP1oRZHVmA$(HKH*4hd)bSmUqvLDLwbxsdrYbo}lmdmf4da>H8 z1M)>T8eK)@eD{W>2FF47g(Ete z5~NOlB(t>&D4ERJfuIb18q0KrOMWn^OFsIp7}L9-m2rgmnm&P1cg7ccPB|X~CF_#J zRS$YG9#_`ns}RvDFd~C!!6%ENXOnm#MBl;{NWMn!baX+910@@%dv8F%J{rbBgGIW( zv!qgIWDuUZj?iKD?@yHSaQB=n%_@Qgo(GKItH?9lk)g=YnZxDDp}Q2C?#QagNORl| zuuxe{D%r@NWEXVh3%V*6v*@%}%$9ILCYJbpl8i>#!{In2D71@K(2p=E$K~nFUI(!# z^3OrIhTud3B7#2AmapKJhbbB~J;Ew_VkI9Cx_8>vaob7**A5zAe@N~m@D4ZP1Po=r zA~Qe0OAc!|X?*)(?_70u?oD4Iiw~UjZ;TUb85mmqj;ZQ#z#YWfNQ^vUMj`uSR&p^!6uM!=)#J-Dm>fh?i(yYWgGyA4w0 zd9ZEYO>*{(6J+6=4}FOph^6;=D-G|cjTgd7Hy6SO1pylVbqI)*Uv`OjzDlIzcLQ#- z9}I!y->Aa*%g@`=kG;W*C#%!Ol&i*{VDR@KLpQO=Z@B-;#EwJdcO+mSAR7NLF~@(2 ziG`gltWEx%eXEkc0XPy^Lpe!7^ZSty1x!9=QkKe`inU5s<+rd%sI>7ow26flp7ter z;jU8-jR^u}Jxwf8zb#AVx0&aA%I2Rof6~cKLb3PvUUj`+HB2A#xm^2v-yiG$@Pg`s zOkrXm35+qJ-Kma@siQQM3cMb@G1e4S8(1liWFsXjGy#jlFn%_z-1mENrv&(j{|ydQ zz)Jj7*>r##pImM4>&1fDuw@e>RF(_ywmjtV#XbR2FWQ*7Ek4i{t(dA}yB8;KUmc!>ODO2wzX&44@A ztX8c|n%G36)s)Ls+-eKa)@u+O@7z$1i_o8iAU&HYs-Z*5*f=iA;&ETC_WB#Za}(+2 zN<(9qP}t3~$ro&9V{9? zVWWdP1Y-Z@rYA!e6dbNdZ^HFe@v&9W36@-EhHF_LH@yiOq)%*;9xPoXH$wr6R=U(L zlW0zxZ?aX~hG^NuG(&BUkAFkYNq1z|*+0qEqed+u;j3I;Q-a>$FGzXq!rii`@Rapd zmI~hGqiZ= zQ|^^qvqkFZ#(I?LR3hcECTr_@>sUwj@yF(HE zK-v^*Ke2c?+>0SS=*Rl(hJ@bXf3S}>ycz~W{53{Kdt+PJ7U?jCO>EW3c&G>2xdp#b zxbnV$==T}K>V-m1wh?ciVFX9`YopOywwbF5TPr;-%e?>k_XV3RbcvE+GS0Bc7CYhN9Cw?B2CMDk9FcgHx}yUB28 z!DpyJVcN>0Da_4YirPOM>lCKYwpM_V!Z6&ic$*2zmq#*HkQgikxE8_-zaQrLpe43NcX8uzUga1tS6PTp={Rgw0mDcASjzs;VV(I&-iV$=jl$Ulv7vxr!o%42z>zGtt(+ z|EWo4auy+xy-pBsB&4RT!M#~cccvw94ODvt zuAT&-L#um%!|9!|#aJW2O5V9&iks`#z8@EOeI~}J=mt?Ie=t^{s&U>u3)w+OE=l0g>Bmjan3PZwpYcdIf&~j9On`?^l6EU`m)H$ ztw-jL*Cv5%$2;gcEB7eNXedF$pz|>%m_h@HDRnRwiqa;G?lUc&bR5Z<1yfw-kKKHH zZ<^uz<6nJlhlxpU{ZFnz|L2hK|E16W*O&fH0In+9_hyD%a-dwUV66&rg@%+rJh8Gi zrOh8Tz|Td&h-OROdRX1`3+9eImKP;`?)?OLcZZ?qXnexT{THsEWiB7-x03>+A!ltI zM4E&0BHnG!8&21+S=+DDPcb|#zCRcvWsrfp=2%&&NaIX(cri2a(8eeL!v_Oye^gGY zxl<_YF3MhDaJb3Z=Or4pH=NW#Nl*dRMit>1jAF-Byy)NeYDDx z>2g!4P^>!3EUY#oNcUX)hPZIEZS{JstOYeo%6n$XCAGl4t*iN2rxcZRil+5++j&5woA{^H41Xd0DP^zen3>scmbL&YqG_XR(kIxXdQ$QYq+= zH9Mvk`_Mn@tMd?HaoTVH1b4YfiZBo?ndWXnV z#dY9UNczxJ!&aqoUQR)8y*&!y2)X0;6#5T5^JvPbcpB}RxU}2f$MzEWhoT`HS~SCu zE_c$3DE@lRPsAR11|E9fGc!p22ev-SsIF34f*f$X!rzj*zn-D~M3m(UFwjGYT(ROd zhMaWA=rLcE0OB5CE_Fw>4MrC*+#Ky;{YOT2Mlgth@tZv*#+4_be#*2JjsII4_l@ZHUv~@anR6WT`cUF3A6?qr2SK zY+EG zlhg@)P?cBaTJ*VQzxIMZuEzyT`#M){5P1mUJ8TE43oBs|pF$K#Kd5_|ybf{i+!iHf zp1ylY+&pT&WIavs#qM9ZY{7==cX{RXc;V?Bk0~GXB>@|a;O~Gkks!KU1Y^8KmZ;Jg}z)*tEt#SPJ+d#25 zAJ}25_t*3mnRUjW@hbGpdC;Wuj$XxnOx9a9Tdh`~t~mP{diTG~P_lxSXi>g)JIJ`6 z{b(bjo|0RJ!s)KcCC;Vi<8_YsMc-b1$)FbHkwuhD2+6cfQV@s%WFi{|lbrILkPJAJI1$_E~j~-%~@cKvceI!SLt`a z*rz4el-&&sX3a*y@|aMxY>ifhFJUS$jB4WQEZ?#5TMZzq*@4I@D$6`0v-69K)()eu zoL;KG_T=yH6s5Xi7!moxKREg`#W%_bH3B!CRES;FB6rktIIT?WFz@uUfA`MJGg`Rn zdQ$z@@_i(FS)P=~CyM$*T%ph0x{iIn6u+DYm~kQgb_>C^mO?Cho1I+0kVj&p1+N6N zNCo$$*a=tKdeBIiji`nsh7v|y=7zXFeGmMhEmR^ImyiHbtUfXIx#UPpTw;!qq)#yN zE0_48dTOjbiGn1D2dOs*NlVa(H{RqWk&iJZ^zS*fg3h#U zzjkqH)}9~{o|*1mL9?RjTPOG5uyyZ}Q;iBkEAji@#S9{E4V6h~tS5T%u`JZ}UDsOxI*g!xS{wqB3 zZxqp_1?{D}nD*`a+)Xzs1LX(yQwpj+s53CI7RoRRT9Q$e6$)a5V3b8Pf!9k4tZL1& z3BY4xQ`PLRW2CQ79*DA@V`e!uHyA($#GJg6VZ?%vXrqAg2xn8wx za~<<+ck6h4Z4PIHD3TG%_p^SehPVPb^ZS+XzmlW9@b35BxIf;!IPfhvi)jMzz_>#Z zk`bC+XFdz;vVjO&zzG!n;1{x75v|}tnP3E=9+NXIwcyD4CWrV*9@0sM{dq-Ft~cgB z22^yZYW=%8CS6CVDA~JlDi20|b@FpD0MO1)ABF`fJ|CDyJ;*H!uosMxoeu&ye*=3a zB!|7y%62rlCzkS77|4F4B}5M@mtPa%j{zywNmscuDjHyVRL;hEi|WQ0?&lRLV1XK` z(KwogJM+MPqauSaghe0C^k@jpVul8wM&$wRvM$YBn=hFub;W~86hg^4UlUA)48_)B zyJ^(lsTsp6{j;C-^!Ud#MLt}B7*ZfYS#sapDMVyG{ z78mtEc(Tjc>Tpgu8FeJ>T)?Ov;g*mQAhrtL)s7+-ms=q)`psYIill=j5k@3-8cEbW z`*!+<9n7@0fePn5tg$_Go(GpCZpk(X+9X0#L3MhJX@kk%C#9U2L)<9qazVLJRcvDc zH9E~An58O0ak|qp3&mIuEhhKF+ja}>>LiM^PzG>Pc^;KUHfE#gsqQ%qoT-dP)irZoYdNJR}wmlN36ShWvaE#ftIm(;H~k zgpQ6!r3lLTJhB@d1`FA&$A!ZFHDnu$D5nMomy%$Q7cWaDnflDq2Q0yai!00XZ6sgP zBx^U*C(oiE<@OoqpsH(I-tu;s4vlHO-GhQCr=$u0=uWxOml(gwhjvD#S;8%IE$?S~ zW5Voe0xapCJp5uJ^B1(*vu0;{ykcz0FcDid!Jav*UgGSvg31GL28wnNS5XZgg@l!>$M()+iHS<5w!4@tH4L*R?otwQ!_!J+ zhRAbo9e7CpIuU2h(u9)8F_b#rm|}NQ9moPj6At>z=7fjR2Gmlm;aY`NS}b#u@*MW+6p@9FJ7^-Q=W~SG zW;qk#3>0y{|KcC0HvmJP!Id{42_+D70C$0?lQC1@{VAjqW#!+hW`?*Qmzx;msQA zvoQ_&+J(r;o|=n_xJTpfZan3S)}@0suuq*Dp^C~-0hH$%RY6OvwZ4~;L5e{p>JCQ) zFH&s=zfC`LeHB=wq$-Nb)giVK;w?Xsm*Y0!vzl+VmyoNhYDr)s-A#IUbgQSjy12Ze z+QOhhz|_x6E8_H!x>b$SXynA9v5gR0@l3;QhP-9ng4<)18g7vG<>}6SdZp^CPmrRL zn$?jWJ7m@&*RW>}^*`zF5<2ablQuI`Y**2prV3NaQ{bgbN!Xk<&Mq;RRBJgqHvI?> zcmOL>uZ9|v&rjCn)}g{Iztk_v5I{<-I84vgsc`jCEcGv=DE$LnOA$}}?cQ`*m%J5i zU)jn=mWR=Ba2EcACgGyQJ$R`*Sa!s)e44dfVcZj`u0ptNpzC4eM4B4cxkcJEWUc_X zj>acvDw)|?UEONPV)82d9bB<_sV*kVH1NbclP#FdQ3$7SI`XmJzZn&$%cpgh5n`u( z5MSz}KZ>(vhg7EhXE`R7@50{dT!3;KTbCn>j3A~cNnWAKWJsa|tc zKLPg+*`HXt&8{iAa`GFLUG9y<0vpY~{*ONUT84aOE&3`FAKT-Ah6&H4oHnz#g#{K1 zy7t|g!FjCo9P0Vvf!l0PuuaKOxqAChogj|Zz*|8|pBzyXME3Zi^oi@(%&VZc-Zeo zwtf6oq%8!{=l)DkRAOCejh72^KBF2lg+Si$h$v}NS->N*nViJ1r`MK|4ostHhsWQ` zH>QF4vD^sv)L<_V?ApfEfZPB(4DMIspcJ?5zU@P*bEdEMkgkSW7N;eb8G(+CXPQk4 z8oqmzIE{x>5ms_#J+7W5WmkG$MhkKHy^inMJf49DtHwg>mzUSQux$~_?qo-ee}_(QZI`LVief1uC# zXkbJX9t^!SOJlE5IkpXCzIU#Z2-ar+U;@KdZf{zJN(B23&Yl7FAfcOyIe$BIeWH6_bFZ;uR1c^%Yg)9 z)jRaG9AM)f-N(>4 zPM^%VPcTQxLD7v!m@OW{oFPXq2(ulh;1uxA9?-VHt-lEX#i1tc(M8d#NT(+DzC|sg z&L})Db|UW}uc<>P6y9N`Ag?!vcP80;<7cIpXrv(HbkC7Hd}#E`Lud9Jnb9|teuoq2 zX+Bm|38jp8rcFIPK@BUyI~fsh7&vq{`Xi^iBV1a`%M__9u8l2`ME%^QH*=}yx%ej| zh%1s1PYbbc!&bVZFVHg$wvtRbIs0Z-G5yn83c`R9B{URA$SYveBWlV4qf~e3T3Y_v z+QE$NmZUHJsV^FM^4X}NabEo{Z9>wj37M%bmvnb~q_ z$L^r%h+BQ=A?jC-DGkm(jnqhQpU^QhNA>u{HiQcF>g21VF+Q|{{=1Y{6^Zm?Za0xr z{t*zE<&-wHH2nZpK&ihYEmI}qQZK?{gxu8N7x9xkFjy{#J|~ld9wz+h`+Q6kJ=RV0 zb3K%tsIsBE#20t^+aD8sm~z$;sMmtrx_b=^HT9n>GM+rrRorkJ!>Ug{)oERO9xLs; zfedme)j)O6J3jsX#!al0Yj>D=;h&sMgsAB3-W>ig8S*QUUwt)*E$!cV%O8JkcS8y< zB_cHiihV!9tZo296***H);I-gDLRC(ZM=|*2|Mn(!iMMO75efX3rt`mTMmh@w;+6H zQ1vl)f6Ob+>R*)9B^p8++{P3!q`oJJ^b$-fU+I(|*njW3LRZNWnL5BkprB33D{|s~ zkACbZj(8m^o^X!$yA2eb2@}s5w*iy!_DMn*E819rAPt1^AtPo#Hpw-PkD|HN-vA1taJ@yLR5@ zJ?5W`k@D5=2ZB=lQHMcJBsLjUArCS_8)v0W1~{}&h$bZNfTjhoQw=_%{2ex>$32JH zU`TQkJ=*_6%Sy}}a;7~2Y>r{-FMdUDFYnA|l<1lTyZ9RDUPq~=#ku&g?~_ zEUs`h8jY}nX3eqkjiyP%OX{}HSQo4YFj46XhOqbVS05(6O>qY|uaF;fVM4s*cqAw$ zS1}{RJ+@L-)WmaalFBi4c>_d{a)gC)h-p1eQ#}N(2_1bR3vwI;P?DrNw&BKN^$$-W zw0Au+;utwENycrwb>Fz7k8ssE7M*GkhVhhe0eznDi|$HOH4OMP>B5_&a1|o6?cn0u z7-JK+l|xhVuS=|>R1^M)*<&bX7SwdUXkLkJ3B}xUZ@3VYT}fFTDyM!W;SuouAg?uB zH$KD%#BN&wMp^>VRC=E7WNZI!M@6gI*ilSA){9q26+EYX zU8cMe66LT&!4E}_ilU32+wiwHvBQcq-js*^%5H@??+58C5TWMRAvL1@sft?P=op7C zN#=&+`irFWz&#mpHln_@T?`Z4jbF$5>K2vR78eT zGM?aLLUle$(ov#Yk!GQ0TzP(VGIPbZ4%Y~k9K`i#C$=Mpmm^|*5u#~5rc5Cr&B2!_ zGZjfeIV+;PAqp^DW-ivi2|eoJXPEHn6hA~yU9Hhy1d6pdE1iOLwvAHxn+?;4zlK!u z1chAQK}QdY;Z(1v#VVl6!fJN?yZ64?G`TeuJk=09$rRknWp`jNRM@PZF$+uBPGJHJE^>U`txYM*IqUt>{j zRl6_ei=@3LW%7)*XvfBgTS0@Qzgvs&YU|dqBP@rbT{g2{q7r+rO;^DamSe#s_SSU* zF=Kq&-XY=J9(!(;Wc9fo)-s;5^5~`esaLsu&h2NQ&ew~euiVSu@%w^KmOUEXkI4mf%*B`Ds;_?Hs%0xTkEUy^0;qeu!?ctC%pM;Od(KF`_dVyiRS8#$@ zj+@dC7>1FIm+lV;frOTuWNevnTEz{L90TQ;Xb7r z$JnQui_r#MBX%33quPnNxF!V?oT;%xPspwKDGczldOyd?e9BrrxpdL;sU5gW2%{~w zjq>*gXzIZ>h^L11y0U89!;K#6;+*tXOjX%aCV%aIq?P_+-d$m(R8Z3uD!Im=#bT=| zCg~kI#M1`S5w)7?_evIq-b&q@P=D?!h&|G13f?lc9H2v zU=E8hjiq`gZFiKTSp6>s<4gq9MzrpziB7rQfn+xY)V#!iG!2LJc@sWSw51kjGXnN3 zST&*X<^`-V=X${jIoX0^vN96oM5QeqJwEQZ9_HZ)aC_O7v;h%f?WI$Mx65jEvtSDn zCg=~{(KAh^T9zYGrd+F5^K)Zs?&ztIhOx2&#&~@Dx~k<2Y|5p_CF$_#xi`M3e5uON zsxM|T&+hm;zUlo-{7Az`1Qgz#ZV6<&-~H`_X_sPpGr?2S9M2tp&rIE5 z4O5~rFG_m|mzfVhHqYF#svb`lr{8_1@1Q){i<7_V$b*?N{wfjDR(Oupl+ul-N6J`M z9W4k^H6rCLsfW^5n48rn=Z&iRWi3c+8ddicSI*w6l_NQ-xS!Q4?R%P0V%45F^{WRA zSJK^a&sK-N3O@hjj*Zj}=@HSU9?Vue+S$ zLi9$Fa#rB;6#&B(D)l^fLHaw~6zt+M?%wcKx`>2wD8a~GV!pUeRSfTnnBWZE-063$ zuB84*HD8UnC5pZrahc~~cKz9@;Aw^V)>dxFe&H9$yC@-1fX`0n~{6dr03_?X*M+6{vg?3hbCxO zse1SeD@jPv+O`xf>AjGrZ4D^9D%9gfHMN_gt&TaODsIGwSsJ!tZ17%l_(mmNiB6<% zbqid?_f&M z?#6I$>70VH1<^7u1Rl=Udg;+JW8xMKEhA31kq$E*grb`(FS*I3_vNV4bt;0V6v z=6B(b$X;T2zF2mhVO2>o*8r_C-k-x@uWOqdm_)uuzH)d}i0)Gub^ABh0KQTu+3Pc2 zd)PB|uylZ5biRCp26N|dzXrouHw(Bw#6NR9-N}r~m>*JQ)*F6R-&l7=u^u-NADo-mMO1uz6b_y8vf$;VaL+ zdYgOy78iiwp&D#Ej z(6cW1R<=yr_G4zQ=V!LS)Flm9LAq9@GBlpoR*=aU)p~`O3?%2x*gZJlx*io5Z@Zz0 z?*6*jV5=D~E?Kj!h(LSEerMz$RNGWj?5lrNcfC)SA+gez`$5Z6jscy>Rtmyy@ z$UvoUBO;4I)6|IdW(QfjCwnJ@s{KZMy4nG1GV44cm^SS)fs15X1rlRS8V~|1s~ohH^_D<;$Fv76%cUA=fO%@ldJ&-CNHJvW5^2vMP!*sl_bjW^txAg+a>3ilG?1m zI`<6;fCmoYV?#kaNtBGI(cZwY*>ks$olKIZfq7jjAHW|d_Q(TgKx`T!+zqu^brT74unhMBy&*emrx*y{Y!=03^il1-!4FyEFqV4NWb z)z}P@E0diyjQv?=Rlf+rMi?*dAxOrY99R3qX??!D9|7NBiFS6GRFk_fb|F)TK#}Y} zQx36z*~@wdplpx0HF9&pQgWgHU9%9n;DX@)XqNUL%`*OfH7jauXW;yQh*rjKi66ly ziJgIkRDy5FjiO*#A_;>MPNag8Fjx+er+CuGh-)Olh-z(`A5a>W(v_Lqy|y3#ozj&h`9X0c7fMJZNuKu+h>n*OCFV3f zzZ)JmP5#C!;I9KOZpT6e#>chBRaonN7}4V~hZE%knVsnQ>y5o7ST@pUEJQZ>b9M#= zkR7EV9gOr8yvWyq_PY~em_nTWm<&9OgSq;51Uq^uT_6)v$@K}(3{@?NY+*F9ffNvs z28az>6geKFy`n9g;3Al;YaSSxcyOB(OLjDAE$-W6uIa7_xwprkkt>r)sx|Q7lmIuh zaCbb0hkdZp-@e_8wYl5FhuB9ST&5USh_i$n&D`wC&qpselh9aHb56~5wT0CMfi(Fp zxRRn!6~Vu(OWJ`F*hJTRg~YVJ)QC+3_gIhARcoa(@+RG0jHK2Ws=nCuLtZt3X46r6 z#xpmK-BV;qEDf|Ry+OSV3jVW=+3aohaV5E6`GJ&HiF5IP{(jvg8*BeX3K1%)W#+VA zPI)kX1|Eq5%^byAH&P}R@J=!{318G4@*Hgsm?80u^2^e;&iJ_Wu3Fx0aN#q;V{97i zT(oTV6S}znMJkEHzOpMxfNq7tGqy(M9xe*52^_OV-SAD+=N@q_%=-rZS6O9wlCWWd z0|2PP|0kJ)|0*jf6Ax2I0~?e7xuDpiw&R4YhWe{xQIc}(a^2pbvM?M>X=B3?nYk>1 z!sU=f7hpAFakXrLyy;9+lkH+Gk?`lNCRPU&CU00+iC9B_j$vP51<}+FHWDBbkKaL z0V2zcIDOb5gBN|^iQV9^_*swTK@h~C+x#%OyoUtK6@;|ZI5~-wE{0g90CtI;hPVxu ziQT9WLjc}Xq>n^Kqn;ATc~w}2P|?21sYRko-3>)qlu)}F{Vbtdsd{6Vq?#qJqp8qc zkg$D?rlSQhFlt))`UFy!4 z_9Sgblj{skn&M22Rw^Lun;azu_>_mBt8s@%H!s(Ta@>ZJh-7EuNw!XQb5-p$Pk{p0 z&EjE^TYcN~bg&Y3sgqeZMcZAkST9t8MHy!2ZLhSS>u7G9l1LYG4kste(ebc+cqfN| z0>p9T36hH2^UEHO!O0_=Bo{34OQx3eO`Yluw1%7PYK@|gtMvp~)p52}1{lYmSi!kR zdfjqnp^taVcCR&z^aDgj^Sttn4koedNKxb0%yg!NW1ym9o<~6wdSz+uDn*ymv_|u_ z9y}l&p1s5vg8-Y-dTI|N8`>s!3{SPGWtx?2%M$HoE0f*CutvO~jy&?UDh{%v$pn`==_H##eZp7| zXuZK8G`uln(pe4mIA}ClLo&JH!6|nUgL~aTn**!&&cPw8Eh_^qU6plLw+h;4{MLI| z7^rV4G}eN(LG+Rh>KQhMNdT>PwA^}o%stizTFRYZIL2RJ=Qs%vpH)`vl z_V~?$`M%R8g?77?r~(8%p+ItLjYDU7+F$n$R)sp{$(76`J#NjA8Y|k2PH|W2g3Eh~ z^rysQG3Z3`smplXG+|2`xY2B{gpZ@UD>H!yxu~QapQ0*KeZv_KYE*q!ZwHujNkDDt zlANg@WUTlG2y2RR=?6C6A^xLO>0kvP4I__+9(LwO>|1PMti9k?Qkjd zwF7TdHQQsZxL?-D5b`X6fX_~=OY&vT0P{sP;z-eJs1)$ddEi*G!|40Ju+e(7f?yRu zl(YgN=mmrB$=^ur4RBe7<3=XGv=Yu$T-o1M?_&!r?ar25yD8UGpJ3?f@2#domXYqV&}l zG4a-HLGKtPq4M|PVD)LdcO(O@wbzGpV$mpWWSDh`Ka0yu^ zz@)F4>t)jSEfBv8zD=jB-K@O(uMk46*>G*(zL8VcK750@!Fgv%@#OCy5IJWP|ZwiF7rr*=cUPOrw;Biu{O|XL$#87$ z)p1x0_RI(@P)tf{^HhSfu#Dkgs*Cl$?{K?FOPq`!XtYH1kH2<;HHZwNtdJ3I52500 zEX6{i+@th6zprrzlLV|N;h@9b`4+nGsLio>DT@L#yC@5t&gBvjFhvFB8-f%VEFp^K zpe5-J$BlUxdU}YcyD@a`l+!|ez0hs$EB(XJ3@@DN2iW%hB?kmd?+9?jLDbO04$+4q z+!J=e)c8?i55U|ZZuiW!`+x<=Nz`_-NkqT zHH+zr#N!o0<5gq_}pIx0n%4Lmo0Pj{4&KNaf-PH?O${K7~LuKy9DCR*T;$Halv0M~pO? z{$hevY{^5q15le9_4grOZp(?qx}$QJP;s^(LA&dp1QFEA&03N(cQ0j)Rk+Y)W#lTJ zqAD$q1tEN!-6Q;kFd@yO*FyOGx2-k-uU;>q{&8^l|2R1M|8J?4u>F7ew=8xCE9uPE zVuW5P^Q?9WSX4p52uecXVsS(s=1Cu9yCKn8EDl*vzkKu`=?;`(K!;N?LQ`C1zy<^y zZYD1LyPN6iKA+z&(0)QV>U4Mg0e+FFFj80Q;|43kIpG!I7{a|oNl`JF4a=H2{cZ^E zf%?@H$?i-UFrw>+0J+>4Tl!<)yfDQ)n*rt6XxH{tHpN&0ATB3hR_)xVrCz&iRysHw2ve_1chtRxM@Y+)b3Ia-SwtV9a zp^60d{y3sn(6B#EgK7b?A-4kA9=J}c_Tx4-8t=t0+#dK=xB2~B9E?|QCKmS}3#SDC zpZpp8qpSamf!njwdO`j5uB-F0IV+XeY9E+)t)``RxXfH+Etbe!Oa*D=ybu)(a3=0) zuv^SxZ*9marq~%3rLf*1b;nq2CY0$`7Ef7k{u8Yty(2|cz+)@dZH)wfPgW1Oai*=u z%k@;qUVw1!<|ymIUtqzm#%n+) zhfd>R40q<}`oOLr=_*lBcH~T%lP7nYot-mhTCH80?#5VBoZ@s^)0i~(r%KFiZQ$7@ zS8+b>j0wbA;^F*!@GDsdr>(Rx*;?XcN%b{Z#o71{^5sz@?DchbKr<(Sp=(>L?X;T) z9>1Hc7HR;q3#(ClOy10LRkJx!gNiMQn}fxwY(zS~(_%pXJ{0Ba!kSm?MU0d4F16m# zyu{G3;MzDzEK0qbcpO70@=KpuUE|e=5WhA#NM4%`Zsc0-GS{ zw4pI27rOz9mdI(9e}X?yV-RBjolcr_XxNwuTExqN#|>^<>;2-iqZ0-O(wxQOB%#eU z26m-(fJddx#nGfoecY_ZG1uimezGY~+xfa=^ly2^f@_tR^}?iTf_f_$#?dgYUF(D9 z7N>0%+rfa7MHj&*%n{I=(MO2kCZ6MQXDch|m@bDMQK$&=-Y_k)*nNAzALO%o>qBn1 zM_TFbU}&hgU7viJF91GecXuN)8P;}uitCQ7W3)^7EO$(ClQr}p;^z|r(f@Zw}r=hk%fW1;26hmxr z*pQv8>{zLWxYH>k=n%nP^;V`9DU)E6!IrV`|C3ylhhgH<&fEgfc=4 zyd`43vtmbnfqZ|4D1pM-{2+{$*J{L`Z|?NHhzi|Ao>f5Vh?^ttT`-K$U0h6V zlB~=%kYIZLJ54+yQuwe=$mWF!=MN?EH<1VGaR9<B_` zXFR21uahWU16!}$gQVH8?SRuTz-7_R=<+(L1UFh8giJWd;u91eakkbJep^;w)U@dk zscaFusEWPK+qUJ#FU-C8@B{=$gN>Qn(PMQ3GGRSek8J`k-GGH@%asorTM662i+myS z5KGtUmxWU-Ob{OSrG$S}?d`)d+=`MZjfsMIp8m>J@KS#E!xcQh(MCCoiELJl6~e6e z*nOipHHN=_7WoqH*C8QC=|AdCKx`0;|k24@eW55;zAqt6u+7Y6zh|zwk zgOz9z4PkZcDH-s7ZfCX+3<4w5kE2){l(rpUXbn47%C_leso{=IXD`yB@PiCL27>?umBGK?;Z~I&Pcs>T22nn%>?js>FN;k z*|IMRz4#8gmPMy#AGQtoqnJini&V{a%DB4L^G7ny16J!NYGB5OYt5W!Shfh0eSoio zxmFRWP-in(6B)zGVF`j4jA7_`eog z-~HEFYhVBX9`OHU#_)esT9SWhoc#A0LuDsC`?-6H6;jxVSG{ zXl((;ehNCK5z0bn1wumy(sZLR$CZ~x-cs=T)USjMh>4|2IoHC*@v7`v)#U$0CWM+xt+LJlM<**O={ zcE@1YF7{qmcXk$J5Y;S;?n5dB1?r?L+e3dteFkR)mhQLGFQqHkgEuiGqf8s*+IH)- zOe+rniDJxN7juF}VIW=tL){+c1~R6i9LJlnH}dd?Hn{RO$~?uY>DH{_t}#^#Kp&4R z<@~YKq^DRY35!yK$xux9CslZ^W%-n{y9(`>ei|JuyAQt=l3gE+Ovk0+=5AybEMuD! zvDzo$5c=fqdn#><3ibnrZ{9dF7~WpO4Dy!*aHr+0D2#l2kTB)TLMUR$V0y!aF! z!(A6*jiNPNL@;Sf&|f+?V8YOMi#KUnmpTL2QeF=O_Sc3@BuT0w)N~QQFwpy?y$K;( zO0}(M1^tWgXMh7Kn`{8Ic%u+ya|Z}a5K}K)0g9N{N8wgL#9Q>(hkxTwb~Uv{vZ}w_ zkUc~ZulqLm80b5dAwKH?e(?PR0AJ`3?@x%{mi+-b7_`jr-vswC-8a>KGDb&4y>#MRIEkE98qAn~vU=8YFH>1unoN3?79? zoU(Cb#$NFzkjdzYfmxy-^nYdeG)&3UmM#8Js{?KGVBxJ2WU%CZ<7D{D376;5M@jHMpdl!NH?m72#U%-;=F4M z#HEgO$wDHu6rZ`>4NrnJ>e)@3;peDw;P!{NeFvPZG$r?rG8OG6ZD^9AvcFCwPkJMu zy0^9LD2o{s5NNtSI`UN8TCn;duUVr38uCn7a+O7R>?2eN^FduestiQ=*bIP}+sO8L zS=4wC?%~=1RzRx_0|+*&(jJvwl@$AkqZp;XJ)D4X55ZM$Q0v2~{$=CP;sS>0?AX{s zjTvz}r7lC8+~vwJONvo3XzOdTY-p5bSV@O_o4(DGFUQ>=%wgSbv+H)aD$21Pb;?(D z15TarUY)G2n4iPdZqD1T2)vGtwAleo7np{AFxomy(( z^PeH5vG_!zn4Mwro&kT1nk9`lcb6QXXA@$IV$u)qn*@T_5jZ#KJvSf@sRMjD@mOqZZ%c> zx8J@qR3D~*EnMQ_4q^r26t}i*^{hgF;Uf zX+&_?SYM%!R;9rHhM%AqtxVP|R_EdjC+CMwgNNk>(C0>>81-$W2!d#)Ds`hY7P?$Z zOX&DS>#%Iw3K$v1rC)!$a9kd@5(>rELz+b@e+GkB{Sm|u*uSET@5Ogd{SV4@VE@S; zc>fb+IYUbmqyK9?#^Bj1mBALINY2U+50qCd_9rULCsGukj0Il8^nteN=g)Lr^nX

o^Zwi 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 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index 4ab125693c..a8d309b24e 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-19 +android.library.reference.1=../MPChartLib diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index e95f5001e7..5732d3c7e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -12,6 +12,7 @@ protected void onCreate(Bundle savedInstanceState) //FIXME: Bar Shadow is not yet supported mChart.setDrawBarShadow(false); + mChart.setDrawXLabels(true); } @Override diff --git a/MPChartLib/res/values/colors.xml b/MPChartLib/res/values/colors.xml deleted file mode 100644 index f88b8b7867..0000000000 --- a/MPChartLib/res/values/colors.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/MPChartLib/res/values/dimens.xml b/MPChartLib/res/values/dimens.xml deleted file mode 100644 index f11f7450a8..0000000000 --- a/MPChartLib/res/values/dimens.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/MPChartLib/res/values/strings.xml b/MPChartLib/res/values/strings.xml deleted file mode 100644 index 4c6703375a..0000000000 --- a/MPChartLib/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/MPChartLib/res/values/styles.xml b/MPChartLib/res/values/styles.xml deleted file mode 100644 index fbe5d22f4c..0000000000 --- a/MPChartLib/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index af52c5d265..016f26ec7e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -56,7 +56,8 @@ * * @author Philipp Jahoda */ -public abstract class Chart>> extends View +public abstract class Chart>> extends + ViewGroup implements AnimatorUpdateListener, ChartInterface { public static final String LOG_TAG = "MPChart"; @@ -224,7 +225,7 @@ public Chart(Context context, AttributeSet attrs, int defStyle) { */ protected void init() { - setWillNotDraw(false); + setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_SOFTWARE, null); mTrans = new Transformer(); @@ -2181,11 +2182,10 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { prepareContentRect(); - - for (int i=0; i < getChildCount(); i++) - { - getChildAt(i).layout(left, top, right, bottom); - } + for (int i = 0; i < getChildCount(); i++) + { + getChildAt(i).layout(left, top, right, bottom); + } // // prepareContentRect(); // Log.i(LOG_TAG, @@ -2230,7 +2230,7 @@ public String getFormattedValue(float value) { return mFormat.format(value); } } - + @Override public View getChartView() { return this; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 1bef4c165d..bd96b02bd8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.charts; import android.content.Context; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.util.AttributeSet; @@ -62,6 +63,17 @@ protected void prepareBar(float x, float y, float barspace) { mBarShadow.set(mBarRect.left, mOffsetTop, mBarRect.right, getHeight() - mOffsetBottom); } } + + @Override + protected void calcModulus() { + + float[] values = new float[9]; + mTrans.getTouchMatrix().getValues(values); + + mXLabels.mYAxisLabelModulus = (int) Math + .ceil((mData.getXValCount() * mXLabels.mLabelHeight) + / (mContentRect.height() * values[Matrix.MSCALE_Y])); + } @Override protected void drawXLabels(float yPos) @@ -76,7 +88,7 @@ protected void drawXLabels(float yPos) int step = mData.getDataSetCount(); - for (int i = 0; i < mData.getXValCount(); i ++) { + for (int i = 0; i < mData.getXValCount(); i += mXLabels.mYAxisLabelModulus) { position[1] = i * step + i * mData.getGroupSpace() + mData.getGroupSpace() / 2f; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java b/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java index f7890ebe00..5f63eaf697 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java @@ -34,6 +34,13 @@ public class XLabels extends LabelBase { * 0 DRAW, else dont draw. */ public int mXAxisLabelModulus = 1; + + /** + * the modulus that indicates if a value at a specified index in an + * array(list) for the y-axis-labels is drawn or not. If index % modulus == + * 0 DRAW, else dont draw. THIS IS ONLY FOR HORIZONTAL BARCHART. + */ + public int mYAxisLabelModulus = 1; /** if true, x-axis label text is centered when using barcharts */ private boolean mCenterXAxisLabels = false; From 4ab4c0ba2e56877866653aa494e2c3ac89ba04fd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 29 Dec 2014 12:28:25 +0100 Subject: [PATCH 0045/1390] Minor changes concerning horizontal barchart, changed superclass to ViewGroup. --- .../mpchartexample/BarChartActivity.java | 7 +- .../HorizontalBarChartActivity.java | 312 +++++++++++++++++- .../charting/charts/HorizontalBarChart.java | 9 +- .../charting/renderer/Transformer.java | 4 +- 4 files changed, 305 insertions(+), 27 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 0baccf7cf2..1eeb4b8754 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -45,7 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(getLayout()); + setContentView(R.layout.activity_barchart); tvX = (TextView) findViewById(R.id.tvXMax); tvY = (TextView) findViewById(R.id.tvYMax); @@ -123,11 +123,6 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawLegend(false); } - protected int getLayout() - { - return R.layout.activity_barchart; - } - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 5732d3c7e7..8dfc2373bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -1,23 +1,301 @@ package com.xxmassdeveloper.mpchartexample; +import android.annotation.SuppressLint; +import android.graphics.PointF; +import android.graphics.RectF; +import android.graphics.Typeface; import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; -public class HorizontalBarChartActivity extends BarChartActivity -{ - @Override - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - //FIXME: Bar Shadow is not yet supported - mChart.setDrawBarShadow(false); - mChart.setDrawXLabels(true); - } - - @Override - protected int getLayout() - { - return R.layout.activity_horizontalbarchart; - } +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Legend; +import com.github.mikephil.charting.utils.Legend.LegendPosition; +import com.github.mikephil.charting.utils.XLabels; +import com.github.mikephil.charting.utils.XLabels.XLabelPosition; +import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.utils.YLabels.YLabelPosition; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + protected HorizontalBarChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + + mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + + mChart.setDrawBarShadow(false); + + // enable the drawing of values + mChart.setDrawYValues(true); + + mChart.setDrawValueAboveBar(true); + + mChart.setDescription(""); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + mChart.setMaxVisibleValueCount(60); + + // disable 3D + mChart.set3DEnabled(false); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + // draw shadows for each bar that show the maximum value + // mChart.setDrawBarShadow(true); + + mChart.setUnit(" €"); + + // mChart.setDrawXLabels(false); + + mChart.setDrawGridBackground(false); + mChart.setDrawHorizontalGrid(true); + mChart.setDrawVerticalGrid(false); + // mChart.setDrawYLabels(false); + + // sets the text size of the values inside the chart + mChart.setValueTextSize(10f); + + mChart.setDrawBorder(false); + // mChart.setBorderPositions(new BorderPosition[] {BorderPosition.LEFT, + // BorderPosition.RIGHT}); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + XLabels xl = mChart.getXLabels(); + xl.setPosition(XLabelPosition.BOTTOM); + xl.setCenterXLabelText(true); + xl.setTypeface(tf); + + YLabels yl = mChart.getYLabels(); + yl.setTypeface(tf); + yl.setLabelCount(8); + yl.setPosition(YLabelPosition.BOTH_SIDED); + + mChart.setValueTypeface(tf); + + setData(12, 50); + + // setting data + mSeekBarY.setProgress(50); + mSeekBarX.setProgress(12); + + mSeekBarY.setOnSeekBarChangeListener(this); + mSeekBarX.setOnSeekBarChangeListener(this); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setFormSize(8f); + l.setXEntrySpace(4f); + + // mChart.setDrawLegend(false); + } + +// @Override +// public boolean onCreateOptionsMenu(Menu menu) { +// getMenuInflater().inflate(R.menu.bar, menu); +// return true; +// } +// +// @Override +// public boolean onOptionsItemSelected(MenuItem item) { +// +// switch (item.getItemId()) { +// case R.id.actionToggleValues: { +// if (mChart.isDrawYValuesEnabled()) +// mChart.setDrawYValues(false); +// else +// mChart.setDrawYValues(true); +// mChart.invalidate(); +// break; +// } +// case R.id.actionToggle3D: { +// if (mChart.is3DEnabled()) +// mChart.set3DEnabled(false); +// else +// mChart.set3DEnabled(true); +// mChart.invalidate(); +// break; +// } +// case R.id.actionToggleHighlight: { +// if (mChart.isHighlightEnabled()) +// mChart.setHighlightEnabled(false); +// else +// mChart.setHighlightEnabled(true); +// mChart.invalidate(); +// break; +// } +// case R.id.actionTogglePinch: { +// if (mChart.isPinchZoomEnabled()) +// mChart.setPinchZoom(false); +// else +// mChart.setPinchZoom(true); +// +// mChart.invalidate(); +// break; +// } +// case R.id.actionToggleHighlightArrow: { +// if (mChart.isDrawHighlightArrowEnabled()) +// mChart.setDrawHighlightArrow(false); +// else +// mChart.setDrawHighlightArrow(true); +// mChart.invalidate(); +// break; +// } +// case R.id.actionToggleStartzero: { +// if (mChart.isStartAtZeroEnabled()) +// mChart.setStartAtZero(false); +// else +// mChart.setStartAtZero(true); +// +// mChart.invalidate(); +// break; +// } +// case R.id.animateX: { +// mChart.animateX(3000); +// break; +// } +// case R.id.animateY: { +// mChart.animateY(3000); +// break; +// } +// case R.id.animateXY: { +// +// mChart.animateXY(3000, 3000); +// break; +// } +// case R.id.actionToggleAdjustXLegend: { +// XLabels xLabels = mChart.getXLabels(); +// +// if (xLabels.isAdjustXLabelsEnabled()) +// xLabels.setAdjustXLabels(false); +// else +// xLabels.setAdjustXLabels(true); +// +// mChart.invalidate(); +// break; +// } +// case R.id.actionToggleFilter: { +// +// Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); +// +// if (!mChart.isFilteringEnabled()) { +// mChart.enableFiltering(a); +// } else { +// mChart.disableFiltering(); +// } +// mChart.invalidate(); +// break; +// } +// case R.id.actionSave: { +// if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { +// Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", +// Toast.LENGTH_SHORT).show(); +// } else +// Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) +// .show(); +// break; +// } +// } +// return true; +// } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + private void setData(int count, float range) { + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add(mMonths[i % 12]); + } + + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = (range + 1); + float val = (float) (Math.random() * mult); + yVals1.add(new BarEntry(val, i)); + } + + BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); + set1.setBarSpacePercent(35f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); + + BarData data = new BarData(xVals, dataSets); + + mChart.setData(data); + } + + @SuppressLint("NewApi") + @Override + public void onValueSelected(Entry e, int dataSetIndex) { + + if (e == null) + return; + + RectF bounds = mChart.getBarBounds((BarEntry) e); + PointF position = mChart.getPosition(e); + + Log.i("bounds", bounds.toString()); + Log.i("position", position.toString()); + } + + public void onNothingSelected() { + }; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index bd96b02bd8..c9c3cee96a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -7,6 +7,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.renderer.ColumnToBarTransformer; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.YLabels; public class HorizontalBarChart extends BarChart @@ -85,6 +86,8 @@ protected void drawXLabels(float yPos) float[] position = new float[] { 0f, 0f }; + + float offset = Utils.calcTextHeight(mXLabelPaint, mData.getXVals().get(0)) / 2f; int step = mData.getDataSetCount(); @@ -103,7 +106,7 @@ protected void drawXLabels(float yPos) { String label = mData.getXVals().get(i); - mDrawCanvas.drawText(label, mOffsetLeft-10, position[1], mXLabelPaint); + mDrawCanvas.drawText(label, mOffsetLeft-10, position[1] + offset, mXLabelPaint); } } } @@ -134,7 +137,9 @@ protected float getNegativeYOffset(boolean drawAboveValueBar) @Override protected void prepareYLabels() { - mYLabels = new XLabelsAsYLabels(); + mYLabels = new XLabelsAsYLabels(); + super.prepareYLabels(); + } private class XLabelsAsYLabels extends YLabels diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java index 8a772bdcf4..dff8e732e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -25,10 +25,10 @@ public class Transformer { protected Matrix mMatrixValueToPx = new Matrix(); /** matrix for handling the different offsets of the chart */ - private Matrix mMatrixOffset = new Matrix(); + protected Matrix mMatrixOffset = new Matrix(); /** matrix used for touch events */ - private final Matrix mMatrixTouch = new Matrix(); + protected final Matrix mMatrixTouch = new Matrix(); /** if set to true, the y-axis is inverted and low values start at the top */ private boolean mInvertYAxis = false; From 02309d118b47f8782a8ac75aaec6b7b1e1ad3b8f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 29 Dec 2014 12:29:37 +0100 Subject: [PATCH 0046/1390] Minor changes. --- .../com/github/mikephil/charting/charts/HorizontalBarChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index c9c3cee96a..742866aa6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -138,7 +138,7 @@ protected float getNegativeYOffset(boolean drawAboveValueBar) protected void prepareYLabels() { mYLabels = new XLabelsAsYLabels(); - super.prepareYLabels(); +// super.prepareYLabels(); } From 30ee7af1c1d92922bbd101e879eb601d12cef759 Mon Sep 17 00:00:00 2001 From: David Almilli Date: Wed, 31 Dec 2014 10:19:59 -0800 Subject: [PATCH 0047/1390] Fixed bug where an exception is thrown when the view has 0 sized dimensions. This can happen when using the xml tag. --- .../mikephil/charting/charts/Chart.java | 196 +++++++++--------- 1 file changed, 102 insertions(+), 94 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 016f26ec7e..843d3d4711 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -22,7 +22,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; - import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; @@ -43,7 +42,6 @@ import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -53,7 +51,7 @@ /** * Baseclass of all Chart-Views. - * + * * @author Philipp Jahoda */ public abstract class Chart>> extends @@ -321,7 +319,7 @@ protected void init() { /** * Sets a new data object for the chart. The data object contains all values * and information needed for displaying. - * + * * @param data */ public void setData(T data) { @@ -370,7 +368,7 @@ public void clear() { /** * Returns true if the chart is empty (meaning it's data object is either * null or contains no entries). - * + * * @return */ public boolean isEmpty() { @@ -924,7 +922,7 @@ protected void drawDescription() { * Returns true if there are values to highlight, false if there are no * values to highlight. Checks if the highlight array is null, has a length * of zero or if the first object is null. - * + * * @return */ public boolean valuesToHighlight() { @@ -938,7 +936,7 @@ public boolean valuesToHighlight() { * null or an empty array to undo all highlighting. This should be used to * programmatically highlight values. This DOES NOT generate a callback to * the OnChartValueSelectedListener. - * + * * @param highs */ public void highlightValues(Highlight[] highs) { @@ -953,7 +951,7 @@ public void highlightValues(Highlight[] highs) { /** * Highlights the value at the given x-index in the given DataSet. Provide * -1 as the x-index to undo all highlighting. - * + * * @param xIndex * @param dataSetIndex */ @@ -974,7 +972,7 @@ public void highlightValue(int xIndex, int dataSetIndex) { * Highlights the value selected by touch gesture. Unlike * highlightValues(...), this generates a callback to the * OnChartValueSelectedListener. - * + * * @param highs */ public void highlightTouch(Highlight high) { @@ -1062,14 +1060,14 @@ protected void drawMarkers() { /** * Returns the actual position in pixels of the MarkerView for the given * Entry in the given DataSet. - * + * * @param xIndex * @param dataSetIndex * @return */ private float[] getMarkerPosition(Entry e, int dataSetIndex) { - float xPos = (float) e.getXIndex(); + float xPos = e.getXIndex(); // make sure the marker is in the center of the bars in BarChart and // CandleStickChart @@ -1135,7 +1133,7 @@ else if (this instanceof BarChart) { * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. - * + * * @param durationMillisX * @param durationMillisY */ @@ -1164,7 +1162,7 @@ public void animateXY(int durationMillisX, int durationMillisY) { * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. - * + * * @param durationMillis */ public void animateX(int durationMillis) { @@ -1179,7 +1177,7 @@ public void animateX(int durationMillis) { * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. - * + * * @param durationMillis */ public void animateY(int durationMillis) { @@ -1201,7 +1199,7 @@ public void onAnimationUpdate(ValueAnimator va) { /** * This gets the y-phase that is used to animate the values. - * + * * @return */ public float getPhaseY() { @@ -1210,7 +1208,7 @@ public float getPhaseY() { /** * This modifys the y-phase that is used to animate the values. - * + * * @param phase */ public void setPhaseY(float phase) { @@ -1219,7 +1217,7 @@ public void setPhaseY(float phase) { /** * This gets the x-phase that is used to animate the values. - * + * * @return */ public float getPhaseX() { @@ -1228,7 +1226,7 @@ public float getPhaseX() { /** * This modifys the x-phase that is used to animate the values. - * + * * @param phase */ public void setPhaseX(float phase) { @@ -1274,7 +1272,7 @@ public void setPhaseX(float phase) { /** * Returns the canvas object the chart uses for drawing. - * + * * @return */ public Canvas getCanvas() { @@ -1283,7 +1281,7 @@ public Canvas getCanvas() { /** * set a selection listener for the chart - * + * * @param l */ public void setOnChartValueSelectedListener(OnChartValueSelectedListener l) { @@ -1293,7 +1291,7 @@ public void setOnChartValueSelectedListener(OnChartValueSelectedListener l) { /** * Sets a gesture-listener for the chart for custom callbacks when executing * gestures on the chart surface. - * + * * @param l */ public void setOnChartGestureListener(OnChartGestureListener l) { @@ -1302,7 +1300,7 @@ public void setOnChartGestureListener(OnChartGestureListener l) { /** * Returns the custom gesture listener. - * + * * @return */ public OnChartGestureListener getOnChartGestureListener() { @@ -1312,7 +1310,7 @@ public OnChartGestureListener getOnChartGestureListener() { /** * If set to true, value highlighting is enabled which means that values can * be highlighted programmatically or by touch gesture. - * + * * @param enabled */ public void setHighlightEnabled(boolean enabled) { @@ -1321,7 +1319,7 @@ public void setHighlightEnabled(boolean enabled) { /** * returns true if highlighting of values is enabled, false if not - * + * * @return */ public boolean isHighlightEnabled() { @@ -1330,7 +1328,7 @@ public boolean isHighlightEnabled() { /** * returns the total value (sum) of all y-values across all DataSets - * + * * @return */ public float getYValueSum() { @@ -1339,7 +1337,7 @@ public float getYValueSum() { /** * returns the current y-max value across all DataSets - * + * * @return */ public float getYMax() { @@ -1348,25 +1346,27 @@ public float getYMax() { /** * returns the lowest value the chart can display - * + * * @return */ - public float getYChartMin() { + @Override + public float getYChartMin() { return mYChartMin; } /** * returns the highest value the chart can display - * + * * @return */ - public float getYChartMax() { + @Override + public float getYChartMax() { return mYChartMax; } /** * returns the current y-min value across all DataSets - * + * * @return */ public float getYMin() { @@ -1375,25 +1375,27 @@ public float getYMin() { /** * Get the total number of X-values. - * + * * @return */ - public float getDeltaX() { + @Override + public float getDeltaX() { return mDeltaX; } /** * Returns the total range of values (on y-axis) the chart displays. - * + * * @return */ - public float getDeltaY() { + @Override + public float getDeltaY() { return mDeltaY; } /** * returns the average value of all values the chart holds - * + * * @return */ public float getAverage() { @@ -1403,7 +1405,7 @@ public float getAverage() { /** * returns the average value for a specific DataSet (with a specific label) * in the chart - * + * * @param dataSetLabel * @return */ @@ -1417,7 +1419,7 @@ public float getAverage(String dataSetLabel) { /** * returns the total number of values the chart holds (across all DataSets) - * + * * @return */ public int getValueCount() { @@ -1426,7 +1428,7 @@ public int getValueCount() { /** * Returns the center point of the chart (the whole View) in pixels. - * + * * @return */ public PointF getCenter() { @@ -1436,7 +1438,7 @@ public PointF getCenter() { /** * Returns the center of the chart taking offsets under consideration. * (returns the center of the content rectangle) - * + * * @return */ public PointF getCenterOffsets() { @@ -1445,7 +1447,7 @@ public PointF getCenterOffsets() { /** * sets the size of the description text in pixels, min 6f, max 16f - * + * * @param size */ public void setDescriptionTextSize(float size) { @@ -1461,7 +1463,7 @@ public void setDescriptionTextSize(float size) { /** * Set this to true to enable logcat outputs for the chart. Default: * disabled - * + * * @param enabled */ public void setLogEnabled(boolean enabled) { @@ -1471,7 +1473,7 @@ public void setLogEnabled(boolean enabled) { /** * set a description text that appears in the bottom right corner of the * chart, size = Y-legend text size - * + * * @param desc */ public void setDescription(String desc) { @@ -1481,7 +1483,7 @@ public void setDescription(String desc) { /** * Sets the text that informs the user that there is no data available with * which to draw the chart. - * + * * @param text */ public void setNoDataText(String text) { @@ -1491,7 +1493,7 @@ public void setNoDataText(String text) { /** * Sets descriptive text to explain to the user why there is no chart * available Defaults to empty if not set - * + * * @param text */ public void setNoDataTextDescription(String text) { @@ -1502,7 +1504,7 @@ public void setNoDataTextDescription(String text) { * Sets the offsets from the border of the view to the actual chart in every * direction manually. Provide density pixels -> they are then rendered to * pixels inside the chart - * + * * @param left * @param right * @param top @@ -1516,26 +1518,30 @@ public void setOffsets(float left, float top, float right, float bottom) { mOffsetTop = Utils.convertDpToPixel(top); } - public float getOffsetLeft() { + @Override + public float getOffsetLeft() { return mOffsetLeft; } - public float getOffsetBottom() { + @Override + public float getOffsetBottom() { return mOffsetBottom; } - public float getOffsetRight() { + @Override + public float getOffsetRight() { return mOffsetRight; } - public float getOffsetTop() { + @Override + public float getOffsetTop() { return mOffsetTop; } /** * Set this to false to disable all gestures and touches on the chart, * default: true - * + * * @param enabled */ public void setTouchEnabled(boolean enabled) { @@ -1546,7 +1552,7 @@ public void setTouchEnabled(boolean enabled) { * set this to true to draw y-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even * if this is enabled - * + * * @param enabled */ public void setDrawYValues(boolean enabled) { @@ -1555,7 +1561,7 @@ public void setDrawYValues(boolean enabled) { /** * sets the view that is displayed when a value is clicked on the chart - * + * * @param v */ public void setMarkerView(MarkerView v) { @@ -1564,7 +1570,7 @@ public void setMarkerView(MarkerView v) { /** * returns the view that is set as a marker view for the chart - * + * * @return */ public MarkerView getMarkerView() { @@ -1574,7 +1580,7 @@ public MarkerView getMarkerView() { /** * if set to true, units are drawn next to values in the chart, default: * false - * + * * @param enabled */ public void setDrawUnitsInChart(boolean enabled) { @@ -1583,7 +1589,7 @@ public void setDrawUnitsInChart(boolean enabled) { /** * sets the unit that is drawn next to the values in the chart, e.g. % - * + * * @param unit */ public void setUnit(String unit) { @@ -1592,7 +1598,7 @@ public void setUnit(String unit) { /** * Returns the unit that is used for the values in the chart - * + * * @return */ public String getUnit() { @@ -1601,7 +1607,7 @@ public String getUnit() { /** * set this to true to draw the legend, false if not - * + * * @param enabled */ public void setDrawLegend(boolean enabled) { @@ -1610,7 +1616,7 @@ public void setDrawLegend(boolean enabled) { /** * returns true if drawing the legend is enabled, false if not - * + * * @return */ public boolean isDrawLegendEnabled() { @@ -1621,7 +1627,7 @@ public boolean isDrawLegendEnabled() { * Returns the legend object of the chart. This method can be used to * customize the automatically generated legend. IMPORTANT: this will return * null if no data has been set for the chart when calling this method - * + * * @return */ public Legend getLegend() { @@ -1631,10 +1637,11 @@ public Legend getLegend() { /** * Returns the rectangle that defines the borders of the chart-value surface * (into which the actual values are drawn). - * + * * @return */ - public RectF getContentRect() { + @Override + public RectF getContentRect() { return mContentRect; } @@ -1642,7 +1649,7 @@ public RectF getContentRect() { * Returns the Transformer class that contains all matrices and is * responsible for transforming values into pixels on the screen and * backwards. - * + * * @return */ public Transformer getTransformer() { @@ -1719,7 +1726,7 @@ public void enableScroll() { /** * set a new paint object for the specified parameter in the chart e.g. * Chart.PAINT_VALUES - * + * * @param p the new paint object * @param which Chart.PAINT_VALUES, Chart.PAINT_GRID, Chart.PAINT_VALUES, * ... @@ -1759,7 +1766,7 @@ public void setPaint(Paint p, int which) { /** * Returns the paint object associated with the provided constant. - * + * * @param which e.g. Chart.PAINT_LEGEND_LABEL * @return */ @@ -1791,7 +1798,7 @@ public Paint getPaint(int which) { /** * returns true if drawing the marker-view is enabled when tapping on values * (use the setMarkerView(View v) method to specify a marker view) - * + * * @return */ public boolean isDrawMarkerViewEnabled() { @@ -1802,7 +1809,7 @@ public boolean isDrawMarkerViewEnabled() { * Set this to true to draw a user specified marker-view when tapping on * chart values (use the setMarkerView(MarkerView mv) method to specify a * marker view). Default: true - * + * * @param enabled */ public void setDrawMarkerViews(boolean enabled) { @@ -1814,7 +1821,7 @@ public void setDrawMarkerViews(boolean enabled) { * no formatter is set, the chart will automatically determine a reasonable * formatting (concerning decimals) for all the values that are drawn inside * the chart. Set this to NULL to re-enable auto formatting. - * + * * @param f */ public void setValueFormatter(ValueFormatter f) { @@ -1828,7 +1835,7 @@ public void setValueFormatter(ValueFormatter f) { /** * Returns the formatter used for drawing the values inside the chart. - * + * * @return */ public ValueFormatter getValueFormatter() { @@ -1837,7 +1844,7 @@ public ValueFormatter getValueFormatter() { /** * sets the draw color for the value paint object - * + * * @param color */ public void setValueTextColor(int color) { @@ -1846,7 +1853,7 @@ public void setValueTextColor(int color) { /** * Sets the font size of the values that are drawn inside the chart. - * + * * @param size */ public void setValueTextSize(float size) { @@ -1855,7 +1862,7 @@ public void setValueTextSize(float size) { /** * returns true if y-value drawing is enabled, false if not - * + * * @return */ public boolean isDrawYValuesEnabled() { @@ -1864,7 +1871,7 @@ public boolean isDrawYValuesEnabled() { /** * returns the x-value at the given index - * + * * @param index * @return */ @@ -1878,7 +1885,7 @@ public String getXValue(int index) { /** * returns the y-value for the given index from the DataSet with the given * label - * + * * @param index * @param dataSetLabel * @return @@ -1890,7 +1897,7 @@ public float getYValue(int index, String dataSetLabel) { /** * returns the y-value for the given x-index and DataSet index - * + * * @param index * @param dataSet * @return @@ -1903,7 +1910,7 @@ public float getYValue(int xIndex, int dataSetIndex) { /** * returns the DataSet with the given index in the DataSet array held by the * ChartData object. - * + * * @param index * @return */ @@ -1914,7 +1921,7 @@ public DataSet getDataSetByIndex(int index) { /** * returns the DataSet with the given label that is stored in the ChartData * object. - * + * * @param type * @return */ @@ -1926,7 +1933,7 @@ public DataSet getDataSetByLabel(String dataSetLabel) { * returns the Entry object from the first DataSet stored in the ChartData * object. If multiple DataSets are used, use getEntry(index, type) or * getEntryByDataSetIndex(xIndex, dataSetIndex); - * + * * @param index * @return */ @@ -1937,7 +1944,7 @@ public Entry getEntry(int index) { /** * returns the Entry object at the given index from the DataSet with the * given label. - * + * * @param index * @param dataSetLabel * @return @@ -1950,7 +1957,7 @@ public Entry getEntry(int index, String dataSetLabel) { * Returns the corresponding Entry object at the given xIndex from the given * DataSet. INFORMATION: This method does calculations at runtime. Do not * over-use in performance critical situations. - * + * * @param xIndex * @param dataSetIndex * @return @@ -1964,7 +1971,7 @@ public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { * objects give information about the value at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. - * + * * @param xIndex * @return */ @@ -1989,7 +1996,7 @@ public ArrayList getYValsAtIndex(int xIndex) { * Get all Entry objects at the given index across all DataSets. * INFORMATION: This method does calculations at runtime. Do not over-use in * performance critical situations. - * + * * @param xIndex * @return */ @@ -2015,7 +2022,7 @@ public ArrayList getEntriesAtIndex(int xIndex) { * Returns the ChartData object that ORIGINALLY has been set for the chart. * It contains all data in an unaltered state, before any filtering * algorithms have been applied. - * + * * @return */ public T getData() { @@ -2024,7 +2031,7 @@ public T getData() { /** * returns the percentage the given value has of the total y-value sum - * + * * @param val * @return */ @@ -2034,7 +2041,7 @@ public float getPercentOfTotal(float val) { /** * sets a typeface for the value-paint - * + * * @param t */ public void setValueTypeface(Typeface t) { @@ -2043,7 +2050,7 @@ public void setValueTypeface(Typeface t) { /** * sets the typeface for the description paint - * + * * @param t */ public void setDescriptionTypeface(Typeface t) { @@ -2052,7 +2059,7 @@ public void setDescriptionTypeface(Typeface t) { /** * Returns the bitmap that represents the chart. - * + * * @return */ public Bitmap getChartBitmap() { @@ -2080,7 +2087,7 @@ public Bitmap getChartBitmap() { * the sdcard leaving the path empty "" will put the saved file directly on * the SD card chart is saved as a PNG image, example: * saveToPath("myfilename", "foldername1/foldername2"); - * + * * @param title * @param pathOnSD e.g. "folder1/folder2/folder3" * @return returns true on success, false on error @@ -2114,7 +2121,7 @@ public boolean saveToPath(String title, String pathOnSD) { * Saves the current state of the chart to the gallery as a JPEG image. The * filename and compression can be set. 0 == maximum compression, 100 = low * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE - * + * * @param fileName e.g. "my_image" * @param quality e.g. 50, min = 0, max = 100 * @return returns true if saving was successfull, false if not @@ -2197,10 +2204,11 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - - // create a new bitmap with the new dimensions - mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); - mDrawCanvas = new Canvas(mDrawBitmap); + if (w > 0 && h > 0) { + // create a new bitmap with the new dimensions + mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); + mDrawCanvas = new Canvas(mDrawBitmap); + } // prepare content rect and matrices prepareContentRect(); @@ -2212,7 +2220,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { /** * Default formatter used for formatting values. Uses a DecimalFormat with * pre-calculated number of digits (depending on max and min value). - * + * * @author Philipp Jahoda */ private class DefaultValueFormatter implements ValueFormatter { From 0e08509b0c7bfb94b74aef4edf5d43aac6ad03f2 Mon Sep 17 00:00:00 2001 From: David Almilli Date: Wed, 31 Dec 2014 10:23:43 -0800 Subject: [PATCH 0048/1390] Reverted spacing to match source repo --- .../mikephil/charting/charts/Chart.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 843d3d4711..b12416718c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1350,7 +1350,7 @@ public float getYMax() { * @return */ @Override - public float getYChartMin() { + public float getYChartMin() { return mYChartMin; } @@ -1360,7 +1360,7 @@ public float getYChartMin() { * @return */ @Override - public float getYChartMax() { + public float getYChartMax() { return mYChartMax; } @@ -1379,7 +1379,7 @@ public float getYMin() { * @return */ @Override - public float getDeltaX() { + public float getDeltaX() { return mDeltaX; } @@ -1389,7 +1389,7 @@ public float getDeltaX() { * @return */ @Override - public float getDeltaY() { + public float getDeltaY() { return mDeltaY; } @@ -1519,22 +1519,22 @@ public void setOffsets(float left, float top, float right, float bottom) { } @Override - public float getOffsetLeft() { + public float getOffsetLeft() { return mOffsetLeft; } @Override - public float getOffsetBottom() { + public float getOffsetBottom() { return mOffsetBottom; } @Override - public float getOffsetRight() { + public float getOffsetRight() { return mOffsetRight; } @Override - public float getOffsetTop() { + public float getOffsetTop() { return mOffsetTop; } @@ -1641,7 +1641,7 @@ public Legend getLegend() { * @return */ @Override - public RectF getContentRect() { + public RectF getContentRect() { return mContentRect; } @@ -2204,11 +2204,11 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (w > 0 && h > 0) { - // create a new bitmap with the new dimensions - mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); - mDrawCanvas = new Canvas(mDrawBitmap); - } + if (w > 0 && h > 0) { + // create a new bitmap with the new dimensions + mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); + mDrawCanvas = new Canvas(mDrawBitmap); + } // prepare content rect and matrices prepareContentRect(); From 13682a154c47c2b8abe865cc61143f6d0c250911 Mon Sep 17 00:00:00 2001 From: LiJohnson <598420668@163.com> Date: Mon, 12 Jan 2015 11:21:12 +0800 Subject: [PATCH 0049/1390] update gradle-wrapper.properties(2.2.1) --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1e61d1fd3a..982af44537 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 10 15:27:10 PDT 2013 +#Sun Jan 11 01:47:43 CST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=http\://services.gradle.org/distributions/gradle-1.12-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip From c5b79024dbb3e77a941d04ec3aa2a3e75acc10ce Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 13 Jan 2015 10:01:22 +0100 Subject: [PATCH 0050/1390] Minor fixes, added PieChart transparent hole. --- .../mikephil/charting/charts/LineChart.java | 14 +++++---- .../mikephil/charting/charts/PieChart.java | 31 +++++++++++++++++-- .../mikephil/charting/data/DataSet.java | 17 ++++++---- .../charting/renderer/Transformer.java | 6 ++-- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 78a89b6549..e75bc0cf00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -169,8 +169,11 @@ protected void drawCubic(LineDataSet dataSet, ArrayList entries) Path spline = new Path(); ArrayList points = new ArrayList(); - for (Entry e : entries) - points.add(new CPoint(e.getXIndex(), e.getVal())); + + for (Entry e : entries) { + if(e != null) + points.add(new CPoint(e.getXIndex(), e.getVal())); + } if (points.size() > 1) { for (int j = 0; j < points.size() * mPhaseX; j++) { @@ -209,7 +212,7 @@ else if (j == points.size() - 1) { // if filled is enabled, close the path if (dataSet.isDrawFilledEnabled()) { - drawCubicFill(dataSet, entries, spline); + drawCubicFill(dataSet, spline); } else { mRenderPaint.setStyle(Paint.Style.STROKE); } @@ -217,15 +220,14 @@ else if (j == points.size() - 1) { mTrans.pathValueToPixel(spline); mDrawCanvas.drawPath(spline, mRenderPaint); - } - protected void drawCubicFill(LineDataSet dataSet, ArrayList entries, Path spline) + protected void drawCubicFill(LineDataSet dataSet, Path spline) { float fillMin = mFillFormatter .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); - spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); + spline.lineTo((mDeltaX + 1) * mPhaseX, fillMin); spline.lineTo(0, fillMin); spline.close(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index b8d836a831..c06f7bb3c0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -7,6 +7,8 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.PointF; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; @@ -543,15 +545,40 @@ public float[] getAbsoluteAngles() { } /** - * Sets the color for the hole that is drawn in the center of the piechart - * (if enabled). + * Sets the color for the hole that is drawn in the center of the PieChart + * (if enabled). NOTE: Use setHoleColorTransparent(boolean enabled) to make + * the hole transparent. * * @param color */ public void setHoleColor(int color) { + mHolePaint.setXfermode(null); mHolePaint.setColor(color); } + /** + * Set the hole in the center of the PieChart transparent. + * + * @param enable + */ + public void setHoleColorTransparent(boolean enable) { + if (enable) { + mHolePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } else { + mHolePaint.setXfermode(null); + } + } + + /** + * Returns true if the hole in the center of the PieChart is transparent, + * false if not. + * + * @return true if hole is transparent. + */ + public boolean isHoleTransparent() { + return mHolePaint.getXfermode() != null; + } + /** * set this to true to draw the pie center empty * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index cde61a02e4..d078bd18af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -90,11 +90,14 @@ protected void calcMinMax() { Entry e = mYVals.get(i); - if (e.getVal() < mYMin) - mYMin = e.getVal(); + if (e != null) { - if (e.getVal() > mYMax) - mYMax = e.getVal(); + if (e.getVal() < mYMin) + mYMin = e.getVal(); + + if (e.getVal() > mYMax) + mYMax = e.getVal(); + } } } @@ -106,7 +109,9 @@ private void calcYValueSum() { mYValueSum = 0; for (int i = 0; i < mYVals.size(); i++) { - mYValueSum += Math.abs(mYVals.get(i).getVal()); + Entry e = mYVals.get(i); + if (e != null) + mYValueSum += Math.abs(e.getVal()); } } @@ -462,7 +467,7 @@ public ArrayList getColors() { public int getColor(int index) { return mColors.get(index % mColors.size()); } - + /** * Returns the first color (index 0) of the colors-array this DataSet * contains. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java index dff8e732e6..cbcd0c3b60 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -116,8 +116,10 @@ public float[] generateTransformedValuesLineScatter(ArrayList e Entry e = entries.get(j / 2); - valuePoints[j] = e.getXIndex(); - valuePoints[j + 1] = e.getVal() * phaseY; + if (e != null) { + valuePoints[j] = e.getXIndex(); + valuePoints[j + 1] = e.getVal() * phaseY; + } } pointValuesToPixel(valuePoints); From 7240729df701095a9a41ad1a4045fa046be0a5eb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 13 Jan 2015 10:07:26 +0100 Subject: [PATCH 0051/1390] Fixed PieChart highligting math. --- .../mpchartexample/PieChartActivity.java | 4 ++-- .../com/github/mikephil/charting/charts/Chart.java | 6 ++++-- .../github/mikephil/charting/charts/PieChart.java | 14 ++++++-------- .../charting/charts/PieRadarChartBase.java | 1 - 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 94c8e12ef9..6670cd1bb8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample; -import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; @@ -52,7 +51,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); // change the color of the center-hole - mChart.setHoleColor(Color.rgb(235, 235, 235)); +// mChart.setHoleColor(Color.rgb(235, 235, 235)); + mChart.setHoleColorTransparent(true); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index b12416718c..d5e7d207ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1661,7 +1661,8 @@ public Transformer getTransformer() { */ public void disableScroll() { ViewParent parent = getParent(); - parent.requestDisallowInterceptTouchEvent(true); + if (parent != null) + parent.requestDisallowInterceptTouchEvent(true); } /** @@ -1669,7 +1670,8 @@ public void disableScroll() { */ public void enableScroll() { ViewParent parent = getParent(); - parent.requestDisallowInterceptTouchEvent(false); + if (parent != null) + parent.requestDisallowInterceptTouchEvent(false); } /** paint for the grid lines (only line and barchart) */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index c06f7bb3c0..80af87c3a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -231,8 +231,6 @@ protected void drawHighlights() { float sliceDegrees = mDrawAngles[xIndex]; - float shiftangle = (float) Math.toRadians(angle + sliceDegrees / 2f); - PieDataSet set = mData .getDataSetByIndex(mIndicesToHightlight[i] .getDataSetIndex()); @@ -241,12 +239,12 @@ protected void drawHighlights() { continue; float shift = set.getSelectionShift(); - float xShift = shift * (float) Math.cos(shiftangle); - float yShift = shift * (float) Math.sin(shiftangle); - - RectF highlighted = new RectF(mCircleBox.left + xShift, mCircleBox.top + yShift, - mCircleBox.right - + xShift, mCircleBox.bottom + yShift); + // make the box containing current arc larger equally + // in every dimension, to preserve shape of arc + RectF highlighted = new RectF(mCircleBox.left - shift, + mCircleBox.top - shift, + mCircleBox.right + shift, + mCircleBox.bottom + shift); mRenderPaint.setColor(set.getColor(xIndex)); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 177348f330..17fb1ec84a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -14,7 +14,6 @@ import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.nineoldandroids.animation.ObjectAnimator; /** From e5578bf8ba6a1c42e1cb499d1ee1c65b8b19e4e8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 13 Jan 2015 17:00:59 +0100 Subject: [PATCH 0052/1390] Minor changes to PieChart. --- .../github/mikephil/charting/charts/PieChart.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 80af87c3a2..b676b3524c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -239,8 +239,13 @@ protected void drawHighlights() { continue; float shift = set.getSelectionShift(); - // make the box containing current arc larger equally - // in every dimension, to preserve shape of arc + + /** + * Make the box containing current arc larger equally in every + * dimension, to preserve shape of arc. Code provided by: + * + * @link https://github.com/wogg + */ RectF highlighted = new RectF(mCircleBox.left - shift, mCircleBox.top - shift, mCircleBox.right + shift, @@ -555,8 +560,10 @@ public void setHoleColor(int color) { } /** - * Set the hole in the center of the PieChart transparent. - * + * Set the hole in the center of the PieChart transparent. Thank you, code + * provided by: + * + * @link https://github.com/wogg * @param enable */ public void setHoleColorTransparent(boolean enable) { From 2de56406b571d8b4f3f2189147b76764aefb0f08 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 13 Jan 2015 19:47:59 +0100 Subject: [PATCH 0053/1390] Improved MarkerView, fix issues. --- .../BarChartActivityMultiDataset.java | 2 +- .../InvertedLineChartActivity.java | 4 - .../mpchartexample/LineChartActivity1.java | 4 - .../mpchartexample/LineChartActivity2.java | 1 + .../mpchartexample/MyMarkerView.java | 17 +++++ .../mpchartexample/RadarChartActivitry.java | 4 - .../fragments/BarChartFrag.java | 1 - .../fragments/ScatterChartFrag.java | 1 - .../mikephil/charting/charts/Chart.java | 19 ++++- .../mikephil/charting/charts/PieChart.java | 2 +- .../mikephil/charting/utils/MarkerView.java | 76 +++++++++++-------- 11 files changed, 82 insertions(+), 49 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 3e47921f65..b3c1a54327 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -71,7 +71,7 @@ protected void onCreate(Bundle savedInstanceState) { // define an offset to change the original position of the marker // (optional) - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); +// mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); // set the marker to the chart mChart.setMarkerView(mv); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index e7fa55a40b..b57df88c24 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -92,10 +92,6 @@ protected void onCreate(Bundle savedInstanceState) { // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - // define an offset to change the original position of the marker - // (optional) - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); - // set the marker to the chart mChart.setMarkerView(mv); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 395f33e645..79611ae1df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -109,10 +109,6 @@ protected void onCreate(Bundle savedInstanceState) { // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - // define an offset to change the original position of the marker - // (optional) - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); - // set the marker to the chart mChart.setMarkerView(mv); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 1c0b942373..733fbc156e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); + mChart.setValueTextColor(Color.WHITE); mChart.setUnit(" $"); mChart.setDrawUnitsInChart(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java index fbef1da4b7..e1b18289c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java @@ -9,6 +9,11 @@ import com.github.mikephil.charting.utils.MarkerView; import com.github.mikephil.charting.utils.Utils; +/** + * Custom implementation of the MarkerView. + * + * @author Philipp Jahoda + */ public class MyMarkerView extends MarkerView { private TextView tvContent; @@ -34,4 +39,16 @@ public void refreshContent(Entry e, int dataSetIndex) { tvContent.setText("" + Utils.formatNumber(e.getVal(), 0, true)); } } + + @Override + public int getXOffset() { + // this will center the marker-view horizontally + return -(getWidth() / 2); + } + + @Override + public int getYOffset() { + // this will cause the marker-view to be above the selected value + return -getHeight(); + } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index a8c01f651a..56a8606ce1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -53,10 +53,6 @@ protected void onCreate(Bundle savedInstanceState) { // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - // define an offset to change the original position of the marker - // (optional) - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); - // set the marker to the chart mChart.setMarkerView(mv); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 6663c1df06..f664a59d6c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -31,7 +31,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDescription(""); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); mChart.setMarkerView(mv); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 3c4a416f1f..0f0c2b7234 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -35,7 +35,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa labels.setTypeface(tf); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); mChart.setMarkerView(mv); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index d5e7d207ca..848b3f37f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -145,7 +145,7 @@ public abstract class Chart Date: Wed, 14 Jan 2015 14:20:02 +0100 Subject: [PATCH 0054/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index ad905f78f2..b7286b72f5 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -17,3 +17,8 @@ https://play.google.com/store/apps/details?id=com.armsoft.mtrade Notification Analyser https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser + +Bluetooth Terminal/Graphics +https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics&hl=de + + From 5cb2c1a6a633dcb194d8822d7bfc820600d1574f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 14 Jan 2015 14:20:14 +0100 Subject: [PATCH 0055/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index b7286b72f5..e2e37f218f 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -19,6 +19,6 @@ Notification Analyser https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser Bluetooth Terminal/Graphics -https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics&hl=de +https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics From 7599c6becada07476fcad34b91864b5a9aa79bba Mon Sep 17 00:00:00 2001 From: Praveen2106 Date: Thu, 15 Jan 2015 21:01:08 +0530 Subject: [PATCH 0056/1390] Health Infinity loves MPAndroidChart Hey Phil, Thanks to your library! It is an awesome charting solution for Android. Planning to use it my future works as well. --- Projects_using_MPAndroidChart.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index e2e37f218f..68239bc903 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -21,4 +21,5 @@ https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser Bluetooth Terminal/Graphics https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics - +HI - Health & Fitness Tracker - All-in-one Diet, Health & Fitness Tracker +https://play.google.com/store/apps/details?id=com.droidinfinity.healthplus From a12c5e5ab7267517182a816725abb1337fad8383 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 16 Jan 2015 21:50:49 +0100 Subject: [PATCH 0057/1390] Bugfix in setOffsets(...) method. --- .../mpchartexample/LineChartActivity1.java | 1 - .../mpchartexample/MyMarkerView.java | 2 +- .../mikephil/charting/charts/Chart.java | 17 +- .../charting/charts/HorizontalBarChart.java | 352 +++++++++--------- .../charting/interfaces/ChartInterface.java | 5 + .../listener/BarLineChartTouchListener.java | 1 - .../renderer/ColumnToBarTransformer.java | 65 ---- .../HorizontalBarChartTransformer.java | 60 +++ .../charting/renderer/Transformer.java | 17 +- 9 files changed, 277 insertions(+), 243 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 79611ae1df..f204ea9ca4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -118,7 +118,6 @@ protected void onCreate(Bundle savedInstanceState) { // add data setData(45, 100); - mChart.animateX(2500); // // restrain the maximum scale-out factor diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java index e1b18289c9..6b4f17aeb6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java @@ -25,7 +25,7 @@ public MyMarkerView(Context context, int layoutResource) { } // callbacks everytime the MarkerView is redrawn, can be used to update the - // content + // content (user-interface) @Override public void refreshContent(Entry e, int dataSetIndex) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 848b3f37f6..4823ecdc97 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -22,6 +22,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; + import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; @@ -42,6 +43,7 @@ import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -1454,6 +1456,7 @@ public PointF getCenter() { * * @return */ + @Override public PointF getCenterOffsets() { return new PointF(mContentRect.centerX(), mContentRect.centerY()); } @@ -1517,8 +1520,9 @@ public void setNoDataTextDescription(String text) { /** * Sets the offsets from the border of the view to the actual chart in every - * direction manually. Provide density pixels -> they are then rendered to - * pixels inside the chart + * direction manually. This method needs to be recalled everytime a new data + * object is set for the chart. Provide density pixels -> they are then + * rendered to pixels inside the chart. * * @param left * @param right @@ -1531,6 +1535,10 @@ public void setOffsets(float left, float top, float right, float bottom) { mOffsetLeft = Utils.convertDpToPixel(left); mOffsetRight = Utils.convertDpToPixel(right); mOffsetTop = Utils.convertDpToPixel(top); + + mTrans.prepareMatrixValuePx(this); + mTrans.prepareMatrixOffset(this); + prepareContentRect(); } @Override @@ -2261,6 +2269,11 @@ public View getChartView() { return this; } + @Override + public PointF getCenterOfView() { + return getCenter(); + } + // @Override // protected void onAttachedToWindow() { // super.onAttachedToWindow(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 742866aa6d..9bcd7baa38 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.charts; import android.content.Context; @@ -6,181 +7,188 @@ import android.graphics.Rect; import android.util.AttributeSet; -import com.github.mikephil.charting.renderer.ColumnToBarTransformer; +import com.github.mikephil.charting.renderer.HorizontalBarChartTransformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.YLabels; +/** + * BarChart with horizontal bar orientation. In this implementation, x- and + * y-axis are switched. + */ public class HorizontalBarChart extends BarChart { - public HorizontalBarChart(Context context) - { - super(context); - } - - public HorizontalBarChart(Context context, AttributeSet attrs) - { - super(context, attrs); - } - - public HorizontalBarChart(Context context, AttributeSet attrs, - int defStyle) - { - super(context, attrs, defStyle); - } - - @Override - protected void init() - { - super.init(); - setDrawXLabels(false); - setDrawYLabels(true); - mTrans = new ColumnToBarTransformer(); - mValuePaint.setTextAlign(Paint.Align.LEFT); - } - - /** - * Prepares a bar for drawing on the specified x-index and y-position. Also - * prepares the shadow-bar if enabled. - * - * @param x the x-position - * @param y the y-position - * @param barspace the space between bars - */ - @Override - protected void prepareBar(float x, float y, float barspace) { - - super.prepareBar(x, y, barspace); - float spaceHalf = barspace / 2f; - - float top = x + spaceHalf; - float bottom = x + 1f - spaceHalf; - - mBarRect.set(0, top, y, bottom); - - mTrans.rectValueToPixel(mBarRect, mPhaseY); - - // if a shadow is drawn, prepare it too - if (mDrawBarShadow) { - mBarShadow.set(mBarRect.left, mOffsetTop, mBarRect.right, getHeight() - mOffsetBottom); - } - } - - @Override - protected void calcModulus() { - - float[] values = new float[9]; - mTrans.getTouchMatrix().getValues(values); - - mXLabels.mYAxisLabelModulus = (int) Math - .ceil((mData.getXValCount() * mXLabels.mLabelHeight) - / (mContentRect.height() * values[Matrix.MSCALE_Y])); - } - - @Override - protected void drawXLabels(float yPos) - { - if (!mDrawXLabels) return; - - mXLabelPaint.setTextAlign(Paint.Align.RIGHT); - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; - - float offset = Utils.calcTextHeight(mXLabelPaint, mData.getXVals().get(0)) / 2f; - - int step = mData.getDataSetCount(); - - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mYAxisLabelModulus) { - - position[1] = i * step + i * mData.getGroupSpace() - + mData.getGroupSpace() / 2f; - - // center the text - if (mXLabels.isCenterXLabelsEnabled()) - position[1] += (step / 2f); - - mTrans.pointValuesToPixel(position); - - if (position[1] >= mOffsetTop && position[1] <= getHeight() - mOffsetBottom) - { - String label = mData.getXVals().get(i); - - mDrawCanvas.drawText(label, mOffsetLeft-10, position[1] + offset, mXLabelPaint); - } - } - } - - private static String TALL_VALUE = "100%"; - @Override - protected float getPositiveYOffset(boolean drawAboveValueBar) - { - Rect bounds = new Rect(); - mValuePaint.getTextBounds(TALL_VALUE,0,TALL_VALUE.length(),bounds); - - return bounds.height()/2; - } - - @Override - protected float getNegativeYOffset(boolean drawAboveValueBar) - { - return getPositiveYOffset(drawAboveValueBar); - } - - /** - * Sets up the y-axis labels. Computes the desired number of labels between - * the two given extremes. Unlike the papareXLabels() method, this method - * needs to be called upon every refresh of the view. - * - * @return - */ - @Override - protected void prepareYLabels() - { - mYLabels = new XLabelsAsYLabels(); -// super.prepareYLabels(); - - } - - private class XLabelsAsYLabels extends YLabels - { - /** - * Returns the longest formatted label (in terms of characters) the y-labels - * contain. - * - * @return - */ - @Override - public String getLongestLabel() - { - String longest = ""; - - for (int i = 0; i < mData.getXValCount(); i ++) - { - String text = mData.getXVals().get(i); - - if (longest.length() < text.length()) - longest = text; - } - - return longest; - } - - /** - * Returns the formatted y-label at the specified index. This will either - * use the auto-formatter or the custom formatter (if one is set). - * - * @param index - * @return - */ - @Override - public String getFormattedLabel(int index) - { - super.getFormattedLabel(index); - if (index < 0) - return ""; - - return mData.getXVals().get(index); - } - } + public HorizontalBarChart(Context context) + { + super(context); + } + + public HorizontalBarChart(Context context, AttributeSet attrs) + { + super(context, attrs); + } + + public HorizontalBarChart(Context context, AttributeSet attrs, + int defStyle) + { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + setDrawXLabels(false); + setDrawYLabels(true); + mTrans = new HorizontalBarChartTransformer(); + mValuePaint.setTextAlign(Paint.Align.LEFT); + } + + /** + * Prepares a bar for drawing on the specified x-index and y-position. Also + * prepares the shadow-bar if enabled. + * + * @param x the x-position + * @param y the y-position + * @param barspace the space between bars + */ +// @Override +// protected void prepareBar(float x, float y, float barspace) { +// super.prepareBar(x, y, barspace); +// +// float spaceHalf = barspace / 2f; +// +// float top = x + spaceHalf; +// float bottom = x + 1f - spaceHalf; +// +// mBarRect.set(0, top, y, bottom); +// +// mTrans.rectValueToPixel(mBarRect, mPhaseY); +// +// // if a shadow is drawn, prepare it too +// if (mDrawBarShadow) { +// mBarShadow.set(mBarRect.left, mOffsetTop, mBarRect.right, getHeight() - mOffsetBottom); +// } +// } + +// @Override +// protected void calcModulus() { +// +// float[] values = new float[9]; +// mTrans.getTouchMatrix().getValues(values); +// +// mXLabels.mYAxisLabelModulus = (int) Math +// .ceil((mData.getXValCount() * mXLabels.mLabelHeight) +// / (mContentRect.height() * values[Matrix.MSCALE_Y])); +// } +// +// @Override +// protected void drawXLabels(float yPos) +// { +// if (!mDrawXLabels) +// return; +// +// mXLabelPaint.setTextAlign(Paint.Align.RIGHT); +// // pre allocate to save performance (dont allocate in loop) +// float[] position = new float[] { +// 0f, 0f +// }; +// +// float offset = Utils.calcTextHeight(mXLabelPaint, mData.getXVals().get(0)) / 2f; +// +// int step = mData.getDataSetCount(); +// +// for (int i = 0; i < mData.getXValCount(); i += mXLabels.mYAxisLabelModulus) { +// +// position[1] = i * step + i * mData.getGroupSpace() +// + mData.getGroupSpace() / 2f; +// +// // center the text +// if (mXLabels.isCenterXLabelsEnabled()) +// position[1] += (step / 2f); +// +// mTrans.pointValuesToPixel(position); +// +// if (position[1] >= mOffsetTop && position[1] <= getHeight() - mOffsetBottom) +// { +// String label = mData.getXVals().get(i); +// +// mDrawCanvas.drawText(label, mOffsetLeft - 10, position[1] + offset, mXLabelPaint); +// } +// } +// } + + private static String TALL_VALUE = "100%"; + + @Override + protected float getPositiveYOffset(boolean drawAboveValueBar) + { + Rect bounds = new Rect(); + mValuePaint.getTextBounds(TALL_VALUE, 0, TALL_VALUE.length(), bounds); + + return bounds.height() / 2; + } + + @Override + protected float getNegativeYOffset(boolean drawAboveValueBar) + { + return getPositiveYOffset(drawAboveValueBar); + } + +// /** +// * Sets up the y-axis labels. Computes the desired number of labels between +// * the two given extremes. Unlike the papareXLabels() method, this method +// * needs to be called upon every refresh of the view. +// * +// * @return +// */ +// @Override +// protected void prepareYLabels() +// { +// mYLabels = new XLabelsAsYLabels(); +// // super.prepareYLabels(); +// +// } + + private class XLabelsAsYLabels extends YLabels + { + /** + * Returns the longest formatted label (in terms of characters) the + * y-labels contain. + * + * @return + */ + @Override + public String getLongestLabel() + { + String longest = ""; + + for (int i = 0; i < mData.getXValCount(); i++) + { + String text = mData.getXVals().get(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } + + /** + * Returns the formatted y-label at the specified index. This will + * either use the auto-formatter or the custom formatter (if one is + * set). + * + * @param index + * @return + */ + @Override + public String getFormattedLabel(int index) + { + super.getFormattedLabel(index); + if (index < 0) + return ""; + + return mData.getXVals().get(index); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index b19b89b34b..e243e30c2f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.interfaces; +import android.graphics.PointF; import android.graphics.RectF; import android.view.View; @@ -32,6 +33,10 @@ public interface ChartInterface { public int getHeight(); + public PointF getCenterOfView(); + + public PointF getCenterOffsets(); + public RectF getContentRect(); public View getChartView(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 8f86b2cbb9..93b3fe579d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -424,7 +424,6 @@ public boolean onSingleTapUp(MotionEvent e) { OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { - l.onChartSingleTapped(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java deleted file mode 100644 index d4540b8ab5..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ColumnToBarTransformer.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.github.mikephil.charting.renderer; - -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.ChartInterface; - -import java.util.ArrayList; - -public class ColumnToBarTransformer extends Transformer -{ - /** - * Prepares the matrix that transforms values to pixels. - * - * @param chart - */ - @Override - public void prepareMatrixValuePx(ChartInterface chart) - { - float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); - float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); - - // setup all matrices - mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); - mMatrixValueToPx.postScale(scaleX, -scaleY); - } - - - /** - * Transforms an arraylist of Entry into a float array containing the x and - * y values transformed with all matrices for the BARCHART. - * - * @param entries - * @param dataSet the dataset index - * @return - */ - public float[] generateTransformedValuesBarChart(ArrayList entries, - int dataSet, BarData bd, float phaseY) { - - float[] valuePoints = new float[entries.size() * 2]; - - int setCount = bd.getDataSetCount(); - float space = bd.getGroupSpace(); - - for (int j = 0; j < valuePoints.length; j += 2) { - - int index = j/2; - Entry e = entries.get(index); - - //TODO: Need to find a better value than 1, should be dependant on yMax, I think - float x = e.getVal() + 1; - // calculate the y-position, depending on datasetcount - float y = e.getXIndex() + (index * (setCount - 1)) + dataSet + 0.5f + space * index - + space / 2f; - - valuePoints[j] = x; - valuePoints[j + 1] = y; - } - - pointValuesToPixel(valuePoints); - - return valuePoints; - } - -} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java new file mode 100644 index 0000000000..f1e7450e61 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java @@ -0,0 +1,60 @@ +package com.github.mikephil.charting.renderer; + +import com.github.mikephil.charting.interfaces.ChartInterface; + +public class HorizontalBarChartTransformer extends Transformer { + + /** + * Prepares the matrix that transforms values to pixels. + * + * @param chart + */ + @Override + public void prepareMatrixValuePx(ChartInterface chart) { + float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); + float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); + + // setup all matrices + mMatrixValueToPx.reset(); + mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + mMatrixValueToPx.postScale(scaleX, -scaleY); + mMatrixValueToPx.postRotate(90, chart.getHeight() / 2, chart.getWidth() / 2); + } + +// /** +// * Transforms an arraylist of Entry into a float array containing the x and +// * y values transformed with all matrices for the BARCHART. +// * +// * @param entries +// * @param dataSet the dataset index +// * @return +// */ +// public float[] generateTransformedValuesBarChart(ArrayList entries, +// int dataSet, BarData bd, float phaseY) { +// +// float[] valuePoints = new float[entries.size() * 2]; +// +// int setCount = bd.getDataSetCount(); +// float space = bd.getGroupSpace(); +// +// for (int j = 0; j < valuePoints.length; j += 2) { +// +// int index = j/2; +// Entry e = entries.get(index); +// +// //TODO: Need to find a better value than 1, should be dependant on yMax, I think +// float x = e.getVal() + 1; +// // calculate the y-position, depending on datasetcount +// float y = e.getXIndex() + (index * (setCount - 1)) + dataSet + 0.5f + space * index +// + space / 2f; +// +// valuePoints[j] = x; +// valuePoints[j + 1] = y; +// } +// +// pointValuesToPixel(valuePoints); +// +// return valuePoints; +// } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java index cbcd0c3b60..2112a26853 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -56,7 +56,8 @@ public Transformer() { } /** - * Prepares the matrix that transforms values to pixels. + * Prepares the matrix that transforms values to pixels. Calculates the + * scale factors from the charts size and offsets. * * @param chart */ @@ -73,6 +74,20 @@ public void prepareMatrixValuePx(ChartInterface chart) { mMatrixValueToPx.postScale(scaleX, -scaleY); } + /** + * Prepares the transformation matrix with the specified scales. + * + * @param chart + * @param scaleX + * @param scaleY + */ + public void prepareMatrixValuePx(ChartInterface chart, float scaleX, float scaleY) { + + mMatrixValueToPx.reset(); + mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + mMatrixValueToPx.postScale(scaleX, -scaleY); + } + /** * Prepares the matrix that contains all offsets. * From f6ad237f6f1e760abefbb632685204afaf50dbb0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 27 Jan 2015 17:36:45 +0100 Subject: [PATCH 0058/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index 68239bc903..fb05b900dd 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -23,3 +23,6 @@ https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics HI - Health & Fitness Tracker - All-in-one Diet, Health & Fitness Tracker https://play.google.com/store/apps/details?id=com.droidinfinity.healthplus + +БИТ.Лидер +https://play.google.com/store/apps/details?id=com.firstbit.bitlider From a6470f5ec0a8c579c3129abe3147b19925daa1be Mon Sep 17 00:00:00 2001 From: "JitPack.io" Date: Mon, 9 Feb 2015 20:45:55 +0000 Subject: [PATCH 0059/1390] Update build.gradle --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 7130c34e51..8d6e95140e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.github.dcendents:android-maven-plugin:1.2' } } From c2dd6d20d1803b5d06869fba12c8789eec9917e3 Mon Sep 17 00:00:00 2001 From: "JitPack.io" Date: Mon, 9 Feb 2015 20:47:04 +0000 Subject: [PATCH 0060/1390] Update build.gradle --- MPChartLib/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 782707587c..52a45ceebd 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,4 +1,5 @@ apply plugin: 'com.android.library' +apply plugin: 'android-maven' android { compileSdkVersion 19 From 0a5202da009279728c4e2b6f4f0d4b816a249feb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 10 Feb 2015 16:36:38 +0100 Subject: [PATCH 0061/1390] Massive changes to the architecture, implementing two axis feature. --- .../charting/animation/ChartAnimator.java | 128 +++ .../mikephil/charting/charts/BarChart.java | 22 +- .../charting/charts/BarLineChartBase.java | 759 ++++-------------- .../charting/charts/CandleStickChart.java | 14 +- .../mikephil/charting/charts/Chart.java | 326 +++----- .../charting/charts/HorizontalBarChart.java | 4 +- .../mikephil/charting/charts/LineChart.java | 399 +-------- .../mikephil/charting/charts/PieChart.java | 14 +- .../mikephil/charting/charts/RadarChart.java | 14 +- .../charting/charts/ScatterChart.java | 12 +- .../data/BarLineScatterCandleData.java | 2 +- .../data/BarLineScatterCandleRadarData.java | 107 --- .../mikephil/charting/data/DataSet.java | 64 +- .../mikephil/charting/data/RadarData.java | 2 +- .../charting/interfaces/ChartInterface.java | 16 +- .../listener/BarLineChartTouchListener.java | 15 +- .../charting/renderer/AxisRenderer.java | 47 ++ .../charting/renderer/DataRenderer.java | 54 ++ .../charting/renderer/LineChartRenderer.java | 435 ++++++++++ .../mikephil/charting/renderer/Renderer.java | 17 + .../charting/renderer/Transformer.java | 375 +-------- .../charting/renderer/ViewPortHandler.java | 438 ++++++++++ .../charting/renderer/XAxisRenderer.java | 156 ++++ .../charting/renderer/YAxisRenderer.java | 312 +++++++ .../utils/{LabelBase.java => AxisBase.java} | 68 +- .../mikephil/charting/utils/LimitLine.java | 21 + .../utils/{XLabels.java => XAxis.java} | 2 +- .../utils/{YLabels.java => YAxis.java} | 127 ++- 28 files changed, 2168 insertions(+), 1782 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java rename MPChartLib/src/com/github/mikephil/charting/utils/{LabelBase.java => AxisBase.java} (56%) rename MPChartLib/src/com/github/mikephil/charting/utils/{XLabels.java => XAxis.java} (99%) rename MPChartLib/src/com/github/mikephil/charting/utils/{YLabels.java => YAxis.java} (70%) diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java new file mode 100644 index 0000000000..702479360d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java @@ -0,0 +1,128 @@ +package com.github.mikephil.charting.animation; + +import com.nineoldandroids.animation.ObjectAnimator; +import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; + +public class ChartAnimator { + + /** object that is updated upon animation update */ + private AnimatorUpdateListener mListener; + + public ChartAnimator(AnimatorUpdateListener listener) { + mListener = listener; + } + + /** + * ################ ################ ################ ################ + * Animation support below Honeycomb thanks to Jake Wharton's awesome + * nineoldandroids library: https://github.com/JakeWharton/NineOldAndroids + */ + /** CODE BELOW THIS RELATED TO ANIMATION */ + + /** the phase that is animated and influences the drawn values on the y-axis */ + protected float mPhaseY = 1f; + + /** the phase that is animated and influences the drawn values on the x-axis */ + protected float mPhaseX = 1f; + + /** objectanimator used for animating values on y-axis */ + private ObjectAnimator mAnimatorY; + + /** objectanimator used for animating values on x-axis */ + private ObjectAnimator mAnimatorX; + + /** + * Animates the drawing / rendering of the chart on both x- and y-axis with + * the specified animation time. If animate(...) is called, no further + * calling of invalidate() is necessary to refresh the chart. + * + * @param durationMillisX + * @param durationMillisY + */ + public void animateXY(int durationMillisX, int durationMillisY) { + + mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + mAnimatorY.setDuration( + durationMillisY); + mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + mAnimatorX.setDuration( + durationMillisX); + + // make sure only one animator produces update-callbacks (which then + // call invalidate()) + if (durationMillisX > durationMillisY) { + mAnimatorX.addUpdateListener(mListener); + } else { + mAnimatorY.addUpdateListener(mListener); + } + + mAnimatorX.start(); + mAnimatorY.start(); + } + + /** + * Animates the rendering of the chart on the x-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. + * + * @param durationMillis + */ + public void animateX(int durationMillis) { + + mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + mAnimatorX.setDuration(durationMillis); + mAnimatorX.addUpdateListener(mListener); + mAnimatorX.start(); + } + + /** + * Animates the rendering of the chart on the y-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. + * + * @param durationMillis + */ + public void animateY(int durationMillis) { + + mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + mAnimatorY.setDuration(durationMillis); + mAnimatorY.addUpdateListener(mListener); + mAnimatorY.start(); + } + + /** + * This gets the y-phase that is used to animate the values. + * + * @return + */ + public float getPhaseY() { + return mPhaseY; + } + + /** + * This modifys the y-phase that is used to animate the values. + * + * @param phase + */ + public void setPhaseY(float phase) { + mPhaseY = phase; + } + + /** + * This gets the x-phase that is used to animate the values. + * + * @return + */ + public float getPhaseX() { + return mPhaseX; + } + + /** + * This modifys the x-phase that is used to animate the values. + * + * @param phase + */ + public void setPhaseX(float phase) { + mPhaseX = phase; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index f888cd7c6e..d508741dd9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -132,7 +132,7 @@ protected void drawHighlights() { // check outofbounds if (index < mData.getYValCount() && index >= 0 - && index < (mDeltaX * mPhaseX) / mData.getDataSetCount()) { + && index < (mDeltaX * xxx) / mData.getDataSetCount()) { Entry e = getEntryByDataSetIndex(index, dataSetIndex); @@ -179,7 +179,7 @@ protected void drawDataSet(int index) { ArrayList entries = dataSet.getYVals(); // do the drawing - for (int j = 0; j < dataSet.getEntryCount() * mPhaseX; j++) { + for (int j = 0; j < dataSet.getEntryCount() * xxx; j++) { BarEntry e = entries.get(j); @@ -281,7 +281,7 @@ protected void prepareBar(float x, float y, float barspace) { mBarRect.set(left, top, right, bottom); - mTrans.rectValueToPixel(mBarRect, mPhaseY); + mTrans.rectValueToPixel(mBarRect, yyy); // if a shadow is drawn, prepare it too if (mDrawBarShadow) { @@ -299,13 +299,13 @@ protected void drawXLabels(float yPos) { int step = mData.getDataSetCount(); - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { position[0] = i * step + i * mData.getGroupSpace() + mData.getGroupSpace() / 2f; // center the text - if (mXLabels.isCenterXLabelsEnabled()) + if (mXAxis.isCenterXLabelsEnabled()) position[0] += (step / 2f); mTrans.pointValuesToPixel(position); @@ -314,7 +314,7 @@ protected void drawXLabels(float yPos) { String label = mData.getXVals().get(i); - if (mXLabels.isAvoidFirstLastClippingEnabled()) { + if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last if (i == mData.getXValCount() - 1) { @@ -351,7 +351,7 @@ protected void drawVerticalGrid() { // take into consideration that multiple DataSets increase mDeltaX int step = mData.getDataSetCount(); - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { + for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { position[0] = i * step + i * mData.getGroupSpace(); @@ -387,12 +387,12 @@ protected void drawValues() { ArrayList entries = dataSet.getYVals(); float[] valuePoints = mTrans.generateTransformedValuesBarChart(entries, i, mData, - mPhaseY); + yyy); // if only single values are drawn (sum) if (!mDrawValuesForWholeStack) { - for (int j = 0; j < valuePoints.length * mPhaseX; j += 2) { + for (int j = 0; j < valuePoints.length * xxx; j += 2) { if (isOffContentRight(valuePoints[j])) break; @@ -410,7 +410,7 @@ protected void drawValues() { // if each value of a potential stack should be drawn } else { - for (int j = 0; j < (valuePoints.length - 1) * mPhaseX; j += 2) { + for (int j = 0; j < (valuePoints.length - 1) * xxx; j += 2) { if (isOffContentRight(valuePoints[j])) break; @@ -440,7 +440,7 @@ protected void drawValues() { for (int k = 0; k < transformed.length; k += 2) { add -= vals[cnt]; - transformed[k + 1] = (vals[cnt] + add) * mPhaseY; + transformed[k + 1] = (vals[cnt] + add) * yyy; cnt++; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 6a33e37f71..36d5c70cb2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -10,7 +10,6 @@ import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.PointF; -import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -18,11 +17,13 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.interfaces.OnDrawListener; import com.github.mikephil.charting.listener.BarLineChartTouchListener; +import com.github.mikephil.charting.renderer.Transformer; +import com.github.mikephil.charting.renderer.XAxisRenderer; +import com.github.mikephil.charting.renderer.YAxisRenderer; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.github.mikephil.charting.utils.LimitLine; @@ -30,10 +31,11 @@ import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; -import com.github.mikephil.charting.utils.YLabels.YLabelPosition; +import com.github.mikephil.charting.utils.XAxis; +import com.github.mikephil.charting.utils.XAxis.XLabelPosition; +import com.github.mikephil.charting.utils.YAxis; +import com.github.mikephil.charting.utils.YAxis.AxisDependency; +import com.github.mikephil.charting.utils.YAxis.YLabelPosition; import java.util.ArrayList; @@ -77,9 +79,6 @@ public abstract class BarLineChartBase 10 && !mTrans.isFullyZoomedOutY()) { - - PointD p1 = getValuesByTouchPoint(mContentRect.left, mContentRect.top); - PointD p2 = getValuesByTouchPoint(mContentRect.left, mContentRect.bottom); - - if (!mTrans.isInvertYAxisEnabled()) { - yMin = (float) p2.y; - yMax = (float) p1.y; - } else { - - if (!mStartAtZero) - yMin = (float) Math.min(p1.y, p2.y); - else - yMin = 0; - yMax = (float) Math.max(p1.y, p2.y); - } - - } else { - - if (!mTrans.isInvertYAxisEnabled()) { - yMin = mYChartMin; - yMax = mYChartMax; - } else { - - if (!mStartAtZero) - yMin = (float) Math.min(mYChartMax, mYChartMin); - else - yMin = 0; - yMax = (float) Math.max(mYChartMax, mYChartMin); - } - } - - int labelCount = mYLabels.getLabelCount(); - double range = Math.abs(yMax - yMin); - - if (labelCount == 0 || range <= 0) { - mYLabels.mEntries = new float[] {}; - mYLabels.mEntryCount = 0; - return; - } - - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); - int intervalSigDigit = (int) (interval / intervalMagnitude); - if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); - } - - // if the labels should only show min and max - if (mYLabels.isShowOnlyMinMaxEnabled()) { - - mYLabels.mEntryCount = 2; - mYLabels.mEntries = new float[2]; - mYLabels.mEntries[0] = mYChartMin; - mYLabels.mEntries[1] = mYChartMax; - - } else { - - double first = Math.ceil(yMin / interval) * interval; - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } - - mYLabels.mEntryCount = n; - - if (mYLabels.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYLabels.mEntries = new float[n]; - } - - for (f = first, i = 0; i < n; f += interval, ++i) { - mYLabels.mEntries[i] = (float) f; - } - } - - if (interval < 1) { - mYLabels.mDecimals = (int) Math.ceil(-Math.log10(interval)); - } else { - mYLabels.mDecimals = 0; - } - } - /** * draws the x-axis labels to the screen depending on their position */ private void drawXLabels() { - if (!mDrawXLabels) - return; - - float yoffset = Utils.convertDpToPixel(4f); - - mXLabelPaint.setTypeface(mXLabels.getTypeface()); - mXLabelPaint.setTextSize(mXLabels.getTextSize()); - mXLabelPaint.setColor(mXLabels.getTextColor()); - - if (mXLabels.getPosition() == XLabelPosition.TOP) { - - drawXLabels(getOffsetTop() - yoffset); - - } else if (mXLabels.getPosition() == XLabelPosition.BOTTOM) { - - drawXLabels(getHeight() - mOffsetBottom + mXLabels.mLabelHeight + yoffset * 1.5f); - - } else if (mXLabels.getPosition() == XLabelPosition.BOTTOM_INSIDE) { - - drawXLabels(getHeight() - getOffsetBottom() - yoffset); - - } else if (mXLabels.getPosition() == XLabelPosition.TOP_INSIDE) { - - drawXLabels(getOffsetTop() + yoffset + mXLabels.mLabelHeight); - - } else { // BOTH SIDED - - drawXLabels(getOffsetTop() - 7); - drawXLabels(getHeight() - mOffsetBottom + mXLabels.mLabelHeight + yoffset * 1.6f); - } - } - - /** - * draws the x-labels on the specified y-position - * - * @param yPos - */ - protected void drawXLabels(float yPos) { - - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; - - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { - - position[0] = i; - - // center the text - if (mXLabels.isCenterXLabelsEnabled()) - position[0] += 0.5f; - - mTrans.pointValuesToPixel(position); - - if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { - - String label = mData.getXVals().get(i); - - if (mXLabels.isAvoidFirstLastClippingEnabled()) { - - // avoid clipping of the last - if (i == mData.getXValCount() - 1) { - float width = Utils.calcTextWidth(mXLabelPaint, label); - - if (width > getOffsetRight() * 2 && position[0] + width > getWidth()) - position[0] -= width / 2; - - // avoid clipping of the first - } else if (i == 0) { - - float width = Utils.calcTextWidth(mXLabelPaint, label); - position[0] += width / 2; - } - } - - mDrawCanvas.drawText(label, position[0], - yPos, - mXLabelPaint); - } - } - } - - /** - * draws the y-axis labels to the screen - */ - private void drawYLabels() { - - if (!mDrawYLabels) - return; - - float[] positions = new float[mYLabels.mEntryCount * 2]; - - for (int i = 0; i < positions.length; i += 2) { - // only fill y values, x values are not needed since the y-labels - // are - // static on the x-axis - positions[i + 1] = mYLabels.mEntries[i / 2]; - } - - mTrans.pointValuesToPixel(positions); - - mYLabelPaint.setTypeface(mYLabels.getTypeface()); - mYLabelPaint.setTextSize(mYLabels.getTextSize()); - mYLabelPaint.setColor(mYLabels.getTextColor()); - - float xoffset = Utils.convertDpToPixel(5f); - float yoffset = Utils.calcTextHeight(mYLabelPaint, "A") / 2.5f; - - // determine position and draw adequately - if (mYLabels.getPosition() == YLabelPosition.LEFT) { - - mYLabelPaint.setTextAlign(Align.RIGHT); - drawYLabels(mOffsetLeft - xoffset, positions, yoffset); - - } else if (mYLabels.getPosition() == YLabelPosition.RIGHT) { - - mYLabelPaint.setTextAlign(Align.LEFT); - drawYLabels(getWidth() - mOffsetRight + xoffset, positions, yoffset); - - } else if (mYLabels.getPosition() == YLabelPosition.RIGHT_INSIDE) { - - mYLabelPaint.setTextAlign(Align.RIGHT); - drawYLabels(getWidth() - mOffsetRight - xoffset, positions, yoffset); - - } else if (mYLabels.getPosition() == YLabelPosition.LEFT_INSIDE) { - - mYLabelPaint.setTextAlign(Align.LEFT); - drawYLabels(mOffsetLeft + xoffset, positions, yoffset); - - } else { // BOTH SIDED Y-AXIS LABELS - - // draw left legend - mYLabelPaint.setTextAlign(Align.RIGHT); - drawYLabels(mOffsetLeft - xoffset, positions, yoffset); - - // draw right legend - mYLabelPaint.setTextAlign(Align.LEFT); - drawYLabels(getWidth() - mOffsetRight + xoffset, positions, yoffset); - } - } - - /** - * draws the y-labels on the specified x-position - * - * @param xPos - * @param positions - */ - private void drawYLabels(float xPos, float[] positions, float yOffset) { - - // draw - for (int i = 0; i < mYLabels.mEntryCount; i++) { - - String text = mYLabels.getFormattedLabel(i); - - if (!mYLabels.isDrawTopYLabelEntryEnabled() && i >= mYLabels.mEntryCount - 1) - return; - - if (mYLabels.isDrawUnitsInYLabelEnabled()) { - mDrawCanvas.drawText(text + mUnit, xPos, positions[i * 2 + 1] + yOffset, - mYLabelPaint); - } else { - mDrawCanvas.drawText(text, xPos, positions[i * 2 + 1] + yOffset, mYLabelPaint); - } - } } /** enums for all different border styles */ @@ -781,22 +506,24 @@ protected void drawBorder() { switch (mBorderPositions[i]) { case LEFT: - mDrawCanvas.drawLine(mOffsetLeft, mOffsetTop, mOffsetLeft, getHeight() - - mOffsetBottom, mBorderPaint); + mDrawCanvas.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mBorderPaint); break; case RIGHT: - mDrawCanvas.drawLine(getWidth() - mOffsetRight, mOffsetTop, getWidth() - - mOffsetRight, getHeight() - - mOffsetBottom, mBorderPaint); + mDrawCanvas.drawLine(mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mBorderPaint); break; case TOP: - mDrawCanvas.drawLine(mOffsetLeft, mOffsetTop, getWidth() - mOffsetRight, - mOffsetTop, mBorderPaint); + mDrawCanvas.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mBorderPaint); break; case BOTTOM: - mDrawCanvas.drawLine(mOffsetLeft, getHeight() - - mOffsetBottom, getWidth() - mOffsetRight, getHeight() - - mOffsetBottom, mBorderPaint); + mDrawCanvas.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mBorderPaint); break; } } @@ -810,190 +537,27 @@ protected void drawGridBackground() { if (!mDrawGridBackground) return; - Rect gridBackground = new Rect((int) mOffsetLeft + 1, (int) mOffsetTop + 1, getWidth() - - (int) mOffsetRight, - getHeight() - (int) mOffsetBottom); + // Rect gridBackground = new Rect((int) mOffsetLeft + 1, (int) + // mOffsetTop + 1, getWidth() + // - (int) mOffsetRight, + // getHeight() - (int) mOffsetBottom); // draw the grid background - mDrawCanvas.drawRect(gridBackground, mGridBackgroundPaint); - } - - /** - * draws the horizontal grid - */ - protected void drawHorizontalGrid() { - - if (!mDrawHorizontalGrid) - return; - - // pre alloc - float[] position = new float[2]; - - // draw the horizontal grid - for (int i = 0; i < mYLabels.mEntryCount; i++) { - - position[1] = mYLabels.mEntries[i]; - mTrans.pointValuesToPixel(position); - - mDrawCanvas.drawLine(mOffsetLeft, position[1], getWidth() - mOffsetRight, position[1], - mGridPaint); - } - } - - /** - * draws the vertical grid - */ - protected void drawVerticalGrid() { - - if (!mDrawVerticalGrid || mData == null) - return; - - float[] position = new float[] { - 0f, 0f - }; - - for (int i = 0; i < mData.getXValCount(); i += mXLabels.mXAxisLabelModulus) { - - position[0] = i; - - mTrans.pointValuesToPixel(position); - - if (position[0] >= mOffsetLeft && position[0] <= getWidth()) { - - mDrawCanvas.drawLine(position[0], mOffsetTop, position[0], getHeight() - - mOffsetBottom, mGridPaint); - } - } + mDrawCanvas.drawRect(mViewPortHandler.getContentRect(), mGridBackgroundPaint); } /** - * Draws the limit lines if there are one. - */ - private void drawLimitLines() { - - ArrayList limitLines = mData.getLimitLines(); - - if (limitLines == null) - return; - - float[] pts = new float[4]; - - for (int i = 0; i < limitLines.size(); i++) { - - LimitLine l = limitLines.get(i); - - pts[1] = l.getLimit(); - pts[3] = l.getLimit(); - - mTrans.pointValuesToPixel(pts); - - pts[0] = 0; - pts[2] = getWidth(); - - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - - mDrawCanvas.drawLines(pts, mLimitLinePaint); - - // if drawing the limit-value is enabled - if (l.isDrawValueEnabled()) { - - PointF pos = getPosition(new Entry(l.getLimit(), 0)); - - // save text align - Align align = mValuePaint.getTextAlign(); - - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + xOffset; - String label = mValueFormatter.getFormattedValue(l.getLimit()); - - if (mDrawUnitInChart) - label += mUnit; - - if (l.getLabelPosition() == LimitLabelPosition.RIGHT) { - - mValuePaint.setTextAlign(Align.RIGHT); - mDrawCanvas.drawText(label, getWidth() - mOffsetRight - - xOffset, - pos.y - yOffset, mValuePaint); - - } else { - mValuePaint.setTextAlign(Align.LEFT); - mDrawCanvas.drawText(label, mOffsetLeft - + xOffset, - pos.y - yOffset, mValuePaint); - } - - mValuePaint.setTextAlign(align); - } - } - } - -// @Override -// protected void drawData() { -// for (int i = 0; i < mData.getDataSetCount(); i++) { -// -// DataSet ds = mData.getDataSets().get(i); -// if (ds.isVisible()) -// drawDataSet(i); -// } -// } - - /** - * returns true if the specified point (x-axis) exceeds the limits of what - * is visible to the right side - * - * @param v - * @return - */ - protected boolean isOffContentRight(float p) { - if (p > mContentRect.right) - return true; - else - return false; - } - - /** - * returns true if the specified point (x-axis) exceeds the limits of what - * is visible to the left side - * - * @param v - * @return - */ - protected boolean isOffContentLeft(float p) { - if (p < mContentRect.left) - return true; - else - return false; - } - - /** - * returns true if the specified point (y-axis) exceeds the limits of what - * is visible on the top - * - * @param v - * @return - */ - protected boolean isOffContentTop(float p) { - if (p < mContentRect.top) - return true; - else - return false; - } - - /** - * returns true if the specified point (y-axis) exceeds the limits of what - * is visible on the bottom - * - * @param v + * Returns the Transformer class that contains all matrices and is + * responsible for transforming values into pixels on the screen and + * backwards. + * * @return */ - protected boolean isOffContentBottom(float p) { - if (p > mContentRect.bottom) - return true; + public Transformer getTransformer(AxisDependency which) { + if (which == AxisDependency.LEFT) + return mLeftAxisTransformer; else - return false; + return mRightAxisTransformer; } /** touchlistener that handles touches and gestures on the chart */ @@ -1022,16 +586,16 @@ public boolean onTouchEvent(MotionEvent event) { * Zooms in by 1.4f, into the charts center. center. */ public void zoomIn() { - Matrix save = mTrans.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); - mTrans.refresh(save, this); + Matrix save = mViewPortHandler.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); + mViewPortHandler.refresh(save, this); } /** * Zooms out by 0.7f, from the charts center. center. */ public void zoomOut() { - Matrix save = mTrans.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); - mTrans.refresh(save, this); + Matrix save = mViewPortHandler.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); + mViewPortHandler.refresh(save, this); } /** @@ -1044,8 +608,8 @@ public void zoomOut() { * @param y */ public void zoom(float scaleX, float scaleY, float x, float y) { - Matrix save = mTrans.zoom(scaleX, scaleY, x, -y); - mTrans.refresh(save, this); + Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, -y); + mViewPortHandler.refresh(save, this); } /** @@ -1053,27 +617,8 @@ public void zoom(float scaleX, float scaleY, float x, float y) { * bounds. */ public void fitScreen() { - Matrix save = mTrans.fitScreen(); - mTrans.refresh(save, this); - } - - /** - * If this is set to true, the y-axis is inverted which means that low - * values are on top of the chart, high values on bottom. - * - * @param enabled - */ - public void setInvertYAxisEnabled(boolean enabled) { - mTrans.setInvertYAxisEnabled(enabled); - } - - /** - * If this returns true, the y-axis is inverted. - * - * @return - */ - public boolean isInvertYAxisEnabled() { - return mTrans.isInvertYAxisEnabled(); + Matrix save = mViewPortHandler.fitScreen(); + mViewPortHandler.refresh(save, this); } /** @@ -1088,8 +633,8 @@ public boolean isInvertYAxisEnabled() { */ public synchronized void centerViewPort(final int xIndex, final float yVal) { - float indicesInView = mDeltaX / mTrans.getScaleX(); - float valsInView = mDeltaY / mTrans.getScaleY(); + float indicesInView = mDeltaX / mViewPortHandler.getScaleX(); + float valsInView = mDeltaY / mViewPortHandler.getScaleY(); Log.i(LOG_TAG, "indices: " + indicesInView + ", vals: " + valsInView); @@ -1098,7 +643,8 @@ public synchronized void centerViewPort(final int xIndex, final float yVal) { xIndex - indicesInView / 2f, yVal + valsInView / 2f }; - mTrans.centerViewPort(pts, this); + mLeftAxisTransformer.pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, this); } /** @@ -1143,7 +689,7 @@ public OnDrawListener getDrawListener() { * @param scaleYmin */ public void setScaleMinima(float scaleXmin, float scaleYmin) { - mTrans.setScaleMinima(scaleXmin, scaleYmin, this); + mViewPortHandler.setScaleMinima(scaleXmin, scaleYmin, this); } /** @@ -1213,7 +759,7 @@ public boolean hasFixedYValues() { * @param e * @return */ - public PointF getPosition(Entry e) { + public PointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; @@ -1229,20 +775,14 @@ public PointF getPosition(Entry e) { vals[0] += set.getBarSpace() / 2f; } - mTrans.pointValuesToPixel(vals); + if (axis == AxisDependency.LEFT) + mLeftAxisTransformer.pointValuesToPixel(vals); + else + mRightAxisTransformer.pointValuesToPixel(vals); return new PointF(vals[0], vals[1]); } - /** - * sets the color for the grid lines - * - * @param color - */ - public void setGridColor(int color) { - mGridPaint.setColor(color); - } - /** * sets the number of maximum visible drawn values on the chart only active * when setDrawValues() is enabled @@ -1253,6 +793,10 @@ public void setMaxVisibleValueCount(int count) { this.mMaxVisibleCount = count; } + public int getMaxVisibleCount() { + return mMaxVisibleCount; + } + /** * If set to true, the highlight indicators (cross of two lines for * LineChart and ScatterChart, dark bar overlay for BarChart) that give @@ -1281,6 +825,7 @@ public void setStartAtZero(boolean enabled) { * * @return */ + @Override public boolean isStartAtZeroEnabled() { return mStartAtZero; } @@ -1426,7 +971,7 @@ public void setDrawXLabels(boolean enabled) { * @param enabled */ public void setDrawYLabels(boolean enabled) { - mDrawYLabels = enabled; + mDrawYAxis = enabled; } /** @@ -1435,7 +980,7 @@ public void setDrawYLabels(boolean enabled) { * @return */ public boolean isDrawYLabelsEnabled() { - return mDrawYLabels; + return mDrawYAxis; } /** @@ -1565,14 +1110,17 @@ public Highlight getHighlightByTouchPoint(float x, float y) { * @param y * @return */ - public PointD getValuesByTouchPoint(float x, float y) { + public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { // create an array of the touch-point float[] pts = new float[2]; pts[0] = x; pts[1] = y; - mTrans.pixelsToValue(pts); + if (axis == AxisDependency.LEFT) + mLeftAxisTransformer.pixelsToValue(pts); + else + mRightAxisTransformer.pixelsToValue(pts); double xTouchVal = pts[0]; double yTouchVal = pts[1]; @@ -1588,13 +1136,16 @@ public PointD getValuesByTouchPoint(float x, float y) { * @param y * @return */ - public PointD getPixelsForValues(float x, float y) { + public PointD getPixelsForValues(float x, float y, AxisDependency axis) { float[] pts = new float[] { x, y }; - mTrans.pointValuesToPixel(pts); + if (axis == AxisDependency.LEFT) + mLeftAxisTransformer.pointValuesToPixel(pts); + else + mRightAxisTransformer.pointValuesToPixel(pts); return new PointD(pts[0], pts[1]); } @@ -1607,8 +1158,8 @@ public PointD getPixelsForValues(float x, float y) { * @param y * @return */ - public float getYValueByTouchPoint(float x, float y) { - return (float) getValuesByTouchPoint(x, y).y; + public float getYValueByTouchPoint(float x, float y, AxisDependency axis) { + return (float) getValuesByTouchPoint(x, y, axis).y; } /** @@ -1630,14 +1181,14 @@ public Entry getEntryByTouchPoint(float x, float y) { * returns the current x-scale factor */ public float getScaleX() { - return mTrans.getScaleX(); + return mViewPortHandler.getScaleX(); } /** * returns the current y-scale factor */ public float getScaleY() { - return mTrans.getScaleY(); + return mViewPortHandler.getScaleY(); } /** @@ -1646,18 +1197,15 @@ public float getScaleY() { * @return */ public boolean isFullyZoomedOut() { - return mTrans.isFullyZoomedOut(); + return mViewPortHandler.isFullyZoomedOut(); } - /** - * returns the object representing all y-labels, this method can be used to - * acquire the YLabels object and modify it (e.g. change the position of the - * labels) - * - * @return - */ - public YLabels getYLabels() { - return mYLabels; + public YAxis getAxisLeft() { + return mAxisLeft; + } + + public YAxis getAxisRight() { + return mAxisRight; } /** @@ -1667,8 +1215,8 @@ public YLabels getYLabels() { * * @return */ - public XLabels getXLabels() { - return mXLabels; + public XAxis getXAxis() { + return mXAxis; } /** @@ -1724,7 +1272,7 @@ public boolean isPinchZoomEnabled() { * @param offset */ public void setDragOffsetX(float offset) { - mTrans.setDragOffsetX(offset); + mViewPortHandler.setDragOffsetX(offset); } /** @@ -1734,7 +1282,7 @@ public void setDragOffsetX(float offset) { * @param offset */ public void setDragOffsetY(float offset) { - mTrans.setDragOffsetY(offset); + mViewPortHandler.setDragOffsetY(offset); } /** @@ -1743,7 +1291,7 @@ public void setDragOffsetY(float offset) { * @return */ public boolean hasNoDragOffset() { - return mTrans.hasNoDragOffset(); + return mViewPortHandler.hasNoDragOffset(); } /** @@ -1789,7 +1337,6 @@ public void setPaint(Paint p, int which) { switch (which) { case PAINT_GRID: - mGridPaint = p; break; case PAINT_GRID_BACKGROUND: mGridBackgroundPaint = p; @@ -1808,7 +1355,7 @@ public Paint getPaint(int which) { switch (which) { case PAINT_GRID: - return mGridPaint; + return null; case PAINT_GRID_BACKGROUND: return mGridBackgroundPaint; case PAINT_BORDER: diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 0ef55f4649..2ac4abb980 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -50,7 +50,7 @@ protected void drawDataSet(int index) { mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); - for (int j = 0; j < entries.size() * mPhaseX; j++) { + for (int j = 0; j < entries.size() * xxx; j++) { // get the color that is specified for this position from // the DataSet, this will reuse colors, if the index is out @@ -112,9 +112,9 @@ && isOffContentBottom(high)) private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace) { bodyPoints[0] = e.getXIndex() + bodySpace; - bodyPoints[1] = e.getClose() * mPhaseY; + bodyPoints[1] = e.getClose() * yyy; bodyPoints[2] = e.getXIndex() + (1f - bodySpace); - bodyPoints[3] = e.getOpen() * mPhaseY; + bodyPoints[3] = e.getOpen() * yyy; mTrans.pointValuesToPixel(bodyPoints); } @@ -128,9 +128,9 @@ private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace) { private void transformShadow(float[] shadowPoints, CandleEntry e) { shadowPoints[0] = e.getXIndex() + 0.5f; - shadowPoints[1] = e.getHigh() * mPhaseY; + shadowPoints[1] = e.getHigh() * yyy; shadowPoints[2] = e.getXIndex() + 0.5f; - shadowPoints[3] = e.getLow() * mPhaseY; + shadowPoints[3] = e.getLow() * yyy; mTrans.pointValuesToPixel(shadowPoints); } @@ -167,8 +167,8 @@ protected void drawHighlights() { if (e == null) continue; - float low = e.getLow() * mPhaseY; - float high = e.getHigh() * mPhaseY; + float low = e.getLow() * yyy; + float high = e.getHigh() * yyy; float[] vertPts = new float[] { xIndex, mYChartMax, xIndex, mYChartMin, xIndex + 1f, mYChartMax, xIndex + 1f, diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 22044c9bf2..4374073bd6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -16,6 +16,7 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import android.provider.MediaStore.Images; +import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -23,6 +24,7 @@ import android.view.ViewGroup; import android.view.ViewParent; +import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; @@ -32,7 +34,9 @@ import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.Transformer; +import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Legend; import com.github.mikephil.charting.utils.Legend.LegendPosition; @@ -40,7 +44,6 @@ import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; -import com.nineoldandroids.animation.ObjectAnimator; import com.nineoldandroids.animation.ValueAnimator; import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; @@ -80,18 +83,6 @@ public abstract class Chart= 0; i--) { @@ -784,8 +761,10 @@ protected void drawLegend() { } } - Log.i(LOG_TAG, "content bottom: " + mContentRect.bottom + ", height: " - + getHeight() + ", posY: " + posY + ", formSize: " + formSize); + // Log.i(LOG_TAG, "content bottom: " + mContentRect.bottom + + // ", height: " + // + getHeight() + ", posY: " + posY + ", formSize: " + + // formSize); break; case PIECHART_CENTER: @@ -885,8 +864,9 @@ protected void drawLegend() { protected void drawDescription() { mDrawCanvas - .drawText(mDescription, getWidth() - mOffsetRight - 10, getHeight() - mOffsetBottom - - 10, mDescPaint); + .drawText(mDescription, getWidth() - mViewPortHandler.offsetRight() - 10, + getHeight() - mViewPortHandler.offsetBottom() + - 10, mDescPaint); } /** @@ -894,21 +874,6 @@ protected void drawDescription() { */ protected abstract void drawValues(); - /** - * Draws the actual data by calling drawDataSet(...) for each DataSet. Skips - * DataSets that are set invisible. - */ - protected void drawData() { - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - DataSet ds = mData.getDataSets().get(i); - - if (ds.isVisible()) - drawDataSet(i); - } - } - /** * Draws the DataSet at the given index. * @@ -920,12 +885,7 @@ protected void drawData() { * draws additional stuff, whatever that might be */ protected abstract void drawAdditional(); - - /** - * draws the values of the chart that need highlightning - */ - protected abstract void drawHighlights(); - + /** * ################ ################ ################ ################ */ @@ -1049,7 +1009,7 @@ protected void drawMarkers() { int xIndex = mIndicesToHightlight[i].getXIndex(); int dataSetIndex = mIndicesToHightlight[i].getDataSetIndex(); - if (xIndex <= mDeltaX && xIndex <= mDeltaX * mPhaseX) { + if (xIndex <= mDeltaX && xIndex <= mDeltaX * mAnimator.getPhaseX()) { Entry e = getEntryByDataSetIndex(xIndex, dataSetIndex); @@ -1060,8 +1020,7 @@ protected void drawMarkers() { float[] pos = getMarkerPosition(e, dataSetIndex); // check bounds - if (pos[0] < mOffsetLeft || pos[0] > getWidth() - mOffsetRight - || pos[1] < mOffsetTop || pos[1] > getHeight() - mOffsetBottom) + if (!mViewPortHandler.isInBounds(pos[0], pos[1])) continue; // callbacks to update the content @@ -1134,7 +1093,7 @@ else if (this instanceof BarChart) { // position of the marker depends on selected value index and value float[] pts = new float[] { - xPos, e.getVal() * mPhaseY + xPos, e.getVal() * mAnimator.getPhaseY() }; mTrans.pointValuesToPixel(pts); @@ -1149,17 +1108,14 @@ else if (this instanceof BarChart) { */ /** CODE BELOW THIS RELATED TO ANIMATION */ - /** the phase that is animated and influences the drawn values on the y-axis */ - protected float mPhaseY = 1f; - - /** the phase that is animated and influences the drawn values on the x-axis */ - protected float mPhaseX = 1f; - - /** objectanimator used for animating values on y-axis */ - private ObjectAnimator mAnimatorY; - - /** objectanimator used for animating values on x-axis */ - private ObjectAnimator mAnimatorX; + /** + * Returns the animator responsible for animating chart values. + * + * @return + */ + public ChartAnimator getAnimator() { + return mAnimator; + } /** * Animates the drawing / rendering of the chart on both x- and y-axis with @@ -1170,24 +1126,7 @@ else if (this instanceof BarChart) { * @param durationMillisY */ public void animateXY(int durationMillisX, int durationMillisY) { - - mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - mAnimatorY.setDuration( - durationMillisY); - mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - mAnimatorX.setDuration( - durationMillisX); - - // make sure only one animator produces update-callbacks (which then - // call invalidate()) - if (durationMillisX > durationMillisY) { - mAnimatorX.addUpdateListener(this); - } else { - mAnimatorY.addUpdateListener(this); - } - - mAnimatorX.start(); - mAnimatorY.start(); + mAnimator.animateXY(durationMillisX, durationMillisY); } /** @@ -1198,11 +1137,7 @@ public void animateXY(int durationMillisX, int durationMillisY) { * @param durationMillis */ public void animateX(int durationMillis) { - - mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - mAnimatorX.setDuration(durationMillis); - mAnimatorX.addUpdateListener(this); - mAnimatorX.start(); + mAnimator.animateX(durationMillis); } /** @@ -1213,56 +1148,18 @@ public void animateX(int durationMillis) { * @param durationMillis */ public void animateY(int durationMillis) { - - mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - mAnimatorY.setDuration(durationMillis); - mAnimatorY.addUpdateListener(this); - mAnimatorY.start(); + mAnimator.animateY(durationMillis); } @Override public void onAnimationUpdate(ValueAnimator va) { // redraw everything after animation value change - invalidate(); + // invalidate(); - // Log.i(LOG_TAG, "UPDATING, x: " + mPhaseX + ", y: " + mPhaseY); - } + ViewCompat.postInvalidateOnAnimation(this); - /** - * This gets the y-phase that is used to animate the values. - * - * @return - */ - public float getPhaseY() { - return mPhaseY; - } - - /** - * This modifys the y-phase that is used to animate the values. - * - * @param phase - */ - public void setPhaseY(float phase) { - mPhaseY = phase; - } - - /** - * This gets the x-phase that is used to animate the values. - * - * @return - */ - public float getPhaseX() { - return mPhaseX; - } - - /** - * This modifys the x-phase that is used to animate the values. - * - * @param phase - */ - public void setPhaseX(float phase) { - mPhaseX = phase; + // Log.i(LOG_TAG, "UPDATING, x: " + mPhaseX + ", y: " + mPhaseY); } /** @@ -1475,7 +1372,7 @@ public PointF getCenter() { */ @Override public PointF getCenterOffsets() { - return new PointF(mContentRect.centerX(), mContentRect.centerY()); + return mViewPortHandler.getContentCenter(); } /** @@ -1535,48 +1432,31 @@ public void setNoDataTextDescription(String text) { mNoDataTextDescription = text; } - /** - * Sets the offsets from the border of the view to the actual chart in every - * direction manually. This method needs to be recalled everytime a new data - * object is set for the chart. Provide density pixels -> they are then - * rendered to pixels inside the chart. - * - * @param left - * @param right - * @param top - * @param bottom - */ - public void setOffsets(float left, float top, float right, float bottom) { - - mOffsetBottom = Utils.convertDpToPixel(bottom); - mOffsetLeft = Utils.convertDpToPixel(left); - mOffsetRight = Utils.convertDpToPixel(right); - mOffsetTop = Utils.convertDpToPixel(top); - - mTrans.prepareMatrixValuePx(this); - mTrans.prepareMatrixOffset(this); - prepareContentRect(); - } - - @Override - public float getOffsetLeft() { - return mOffsetLeft; - } - - @Override - public float getOffsetBottom() { - return mOffsetBottom; - } - - @Override - public float getOffsetRight() { - return mOffsetRight; - } - - @Override - public float getOffsetTop() { - return mOffsetTop; - } + // /** + // * Sets the offsets from the border of the view to the actual chart in + // every + // * direction manually. This method needs to be recalled everytime a new + // data + // * object is set for the chart. Provide density pixels -> they are then + // * rendered to pixels inside the chart. + // * + // * @param left + // * @param right + // * @param top + // * @param bottom + // */ + // public void setOffsets(float left, float top, float right, float bottom) + // { + // + // mOffsetBottom = Utils.convertDpToPixel(bottom); + // mOffsetLeft = Utils.convertDpToPixel(left); + // mOffsetRight = Utils.convertDpToPixel(right); + // mOffsetTop = Utils.convertDpToPixel(top); + // + // mTrans.prepareMatrixValuePx(this); + // mTrans.prepareMatrixOffset(this); + // prepareContentRect(); + // } /** * Set this to false to disable all gestures and touches on the chart, @@ -1588,17 +1468,6 @@ public void setTouchEnabled(boolean enabled) { this.mTouchEnabled = enabled; } - /** - * set this to true to draw y-values on the chart NOTE (for bar and - * linechart): if "maxvisiblecount" is reached, no values will be drawn even - * if this is enabled - * - * @param enabled - */ - public void setDrawYValues(boolean enabled) { - this.mDrawYValues = enabled; - } - /** * sets the view that is displayed when a value is clicked on the chart * @@ -1682,18 +1551,7 @@ public Legend getLegend() { */ @Override public RectF getContentRect() { - return mContentRect; - } - - /** - * Returns the Transformer class that contains all matrices and is - * responsible for transforming values into pixels on the screen and - * backwards. - * - * @return - */ - public Transformer getTransformer() { - return mTrans; + return mViewPortHandler.getContentRect(); } /** @@ -1902,15 +1760,6 @@ public void setValueTextSize(float size) { mValuePaint.setTextSize(Utils.convertDpToPixel(size)); } - /** - * returns true if y-value drawing is enabled, false if not - * - * @return - */ - public boolean isDrawYValuesEnabled() { - return mDrawYValues; - } - /** * returns the x-value at the given index * @@ -2099,6 +1948,16 @@ public void setDescriptionTypeface(Typeface t) { mDescPaint.setTypeface(t); } + /** + * Returns the ViewPortHandler of the chart that is responsible for the + * content area of the chart and its offsets and dimensions. + * + * @return + */ + public ViewPortHandler getViewPortHandler() { + return mViewPortHandler; + } + /** * Returns the bitmap that represents the chart. * @@ -2246,10 +2105,13 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - if (w > 0 && h > 0) { + Log.i("", "OnSizeChanged()"); + + if (w > 0 && h > 0 && w < 10000 && h < 10000) { // create a new bitmap with the new dimensions mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); mDrawCanvas = new Canvas(mDrawBitmap); + mViewPortHandler = new ViewPortHandler(w, h); } // prepare content rect and matrices diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 9bcd7baa38..28799a6a95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.renderer.HorizontalBarChartTransformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.utils.YAxis; /** * BarChart with horizontal bar orientation. In this implementation, x- and @@ -149,7 +149,7 @@ protected float getNegativeYOffset(boolean drawAboveValueBar) // // } - private class XLabelsAsYLabels extends YLabels + private class XLabelsAsYLabels extends YAxis { /** * Returns the longest formatted label (in terms of characters) the diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index df71eb4d18..ad12e0221a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -4,16 +4,13 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Path; import android.util.AttributeSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.renderer.LineChartRenderer; import com.github.mikephil.charting.utils.FillFormatter; -import java.util.ArrayList; - /** * Chart that draws lines, surfaces, circles, ... * @@ -24,9 +21,6 @@ public class LineChart extends BarLineChartBase { /** the width of the highlighning line */ protected float mHighlightWidth = 3f; - /** paint for the inner circle of the value indicators */ - protected Paint mCirclePaintInner; - private FillFormatter mFillFormatter; public LineChart(Context context) { @@ -45,16 +39,9 @@ public LineChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); + mFillFormatter = new DefaultFillFormatter(); - - mCirclePaintInner = new Paint(Paint.ANTI_ALIAS_FLAG); - mCirclePaintInner.setStyle(Paint.Style.FILL); - mCirclePaintInner.setColor(Color.WHITE); - - mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mHighlightPaint.setStyle(Paint.Style.STROKE); - mHighlightPaint.setStrokeWidth(2f); - mHighlightPaint.setColor(Color.rgb(255, 187, 115)); } @Override @@ -71,380 +58,21 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX = 1; } - @Override - protected void drawHighlights() { - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - LineDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i] - .getDataSetIndex()); - - if (set == null) - continue; - - mHighlightPaint.setColor(set.getHighLightColor()); - - int xIndex = mIndicesToHightlight[i].getXIndex(); // get the - // x-position - - if (xIndex > mDeltaX * mPhaseX) - continue; - - float y = set.getYValForXIndex(xIndex) * mPhaseY; // get the - // y-position - - float[] pts = new float[] { - xIndex, mYChartMax, xIndex, mYChartMin, 0, y, mDeltaX, y - }; - - mTrans.pointValuesToPixel(pts); - // draw the highlight lines - mDrawCanvas.drawLines(pts, mHighlightPaint); - } - } - - /** - * Class needed for saving the points when drawing cubic-lines. - * - * @author Philipp Jahoda - */ - protected class CPoint { - - public float x = 0f; - public float y = 0f; - - /** x-axis distance */ - public float dx = 0f; - - /** y-axis distance */ - public float dy = 0f; - - public CPoint(float x, float y) { - this.x = x; - this.y = y; - } - } - @Override protected void drawDataSet(int index) { - - LineDataSet dataSet = mData.getDataSets().get(index); - ArrayList entries = dataSet.getYVals(); - - if (entries.size() < 1) - return; - - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); - mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); - - // if drawing cubic lines is enabled - if (dataSet.isDrawCubicEnabled()) { - drawCubic(dataSet, entries); - - // draw normal (straight) lines - } else { - drawLinear(dataSet, entries); - } - - mRenderPaint.setPathEffect(null); - } - - protected void drawCubic(LineDataSet dataSet, ArrayList entries) - { - // get the color that is specified for this position from the - // DataSet - mRenderPaint.setColor(dataSet.getColor()); - - float intensity = dataSet.getCubicIntensity(); - - // the path for the cubic-spline - Path spline = new Path(); - - ArrayList points = new ArrayList(); - - for (Entry e : entries) { - if (e != null) - points.add(new CPoint(e.getXIndex(), e.getVal())); - } - - if (points.size() > 1) { - for (int j = 0; j < points.size() * mPhaseX; j++) { - - CPoint point = points.get(j); - - if (j == 0) { - CPoint next = points.get(j + 1); - point.dx = ((next.x - point.x) * intensity); - point.dy = ((next.y - point.y) * intensity); - } - else if (j == points.size() - 1) { - CPoint prev = points.get(j - 1); - point.dx = ((point.x - prev.x) * intensity); - point.dy = ((point.y - prev.y) * intensity); - } - else { - CPoint next = points.get(j + 1); - CPoint prev = points.get(j - 1); - point.dx = ((next.x - prev.x) * intensity); - point.dy = ((next.y - prev.y) * intensity); - } - - // create the cubic-spline path - if (j == 0) { - spline.moveTo(point.x, point.y * mPhaseY); - } - else { - CPoint prev = points.get(j - 1); - spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * mPhaseY, point.x - - point.dx, - (point.y - point.dy) * mPhaseY, point.x, point.y * mPhaseY); - } - } - } - - // if filled is enabled, close the path - if (dataSet.isDrawFilledEnabled()) { - drawCubicFill(dataSet, spline); - } else { - mRenderPaint.setStyle(Paint.Style.STROKE); - } - - mTrans.pathValueToPixel(spline); - - mDrawCanvas.drawPath(spline, mRenderPaint); - } - - protected void drawCubicFill(LineDataSet dataSet, Path spline) - { - float fillMin = mFillFormatter - .getFillLinePosition(dataSet, mData, mYChartMax, mYChartMin); - - spline.lineTo((mDeltaX + 1) * mPhaseX, fillMin); - spline.lineTo(0, fillMin); - spline.close(); - - mRenderPaint.setStyle(Paint.Style.FILL); - } - - protected void drawLinear(LineDataSet dataSet, ArrayList entries) - { - mRenderPaint.setStyle(Paint.Style.STROKE); - - // more than 1 color - if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - - float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); - - for (int j = 0; j < (valuePoints.length - 2) * mPhaseX; j += 2) { - - if (isOffContentRight(valuePoints[j])) - break; - - // make sure the lines don't do shitty things outside - // bounds - if (j != 0 && isOffContentLeft(valuePoints[j - 1]) - && isOffContentTop(valuePoints[j + 1]) - && isOffContentBottom(valuePoints[j + 1])) - continue; - - // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 2)); - - mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], - valuePoints[j + 2], valuePoints[j + 3], mRenderPaint); - } - - } else { // only one color per dataset - - mRenderPaint.setColor(dataSet.getColor()); - - Path line = generateLinePath(entries); - mTrans.pathValueToPixel(line); - - mDrawCanvas.drawPath(line, mRenderPaint); - } - - mRenderPaint.setPathEffect(null); - - // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { - drawLinearFill(dataSet, entries); - } - } - - protected void drawLinearFill(LineDataSet dataSet, ArrayList entries) - { - // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, - // valuePoints.length, valuePoints, 0, - // null, 0, null, 0, null, 0, 0, paint); - - mRenderPaint.setStyle(Paint.Style.FILL); - - mRenderPaint.setColor(dataSet.getFillColor()); - // filled is drawn with less alpha - mRenderPaint.setAlpha(dataSet.getFillAlpha()); - - // mRenderPaint.setShader(dataSet.getShader()); - - Path filled = generateFilledPath(entries, - mFillFormatter.getFillLinePosition(dataSet, mData, mYChartMax, - mYChartMin)); - - mTrans.pathValueToPixel(filled); - - mDrawCanvas.drawPath(filled, mRenderPaint); - - // restore alpha - mRenderPaint.setAlpha(255); - // mRenderPaint.setShader(null); - } - - /** - * Generates the path that is used for filled drawing. - * - * @param entries - * @return - */ - private Path generateFilledPath(ArrayList entries, float fillMin) { - - Path filled = new Path(); - filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * mPhaseY); - - // create a new path - for (int x = 1; x < entries.size() * mPhaseX; x++) { - - Entry e = entries.get(x); - filled.lineTo(e.getXIndex(), e.getVal() * mPhaseY); - } - - // close up - filled.lineTo(entries.get((int) ((entries.size() - 1) * mPhaseX)).getXIndex(), fillMin); - filled.lineTo(entries.get(0).getXIndex(), fillMin); - filled.close(); - - return filled; - } - - /** - * Generates the path that is used for drawing a single line. - * - * @param entries - * @return - */ - private Path generateLinePath(ArrayList entries) { - - Path line = new Path(); - line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * mPhaseY); - - // create a new path - for (int x = 1; x < entries.size() * mPhaseX; x++) { - - Entry e = entries.get(x); - line.lineTo(e.getXIndex(), e.getVal() * mPhaseY); - } - - return line; + } @Override protected void drawValues() { - // if values are drawn - if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - - ArrayList dataSets = mData.getDataSets(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - LineDataSet dataSet = dataSets.get(i); - - // make sure the values do not interfear with the circles - int valOffset = (int) (dataSet.getCircleSize() * 1.75f); - - if (!dataSet.isDrawCirclesEnabled()) - valOffset = valOffset / 2; - - ArrayList entries = dataSet.getYVals(); - - float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); - - for (int j = 0; j < positions.length * mPhaseX; j += 2) { - - if (isOffContentRight(positions[j])) - break; - - if (isOffContentLeft(positions[j]) || isOffContentTop(positions[j + 1]) - || isOffContentBottom(positions[j + 1])) - continue; - - float val = entries.get(j / 2).getVal(); - - if (mDrawUnitInChart) { - - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(val) + mUnit, - positions[j], - positions[j + 1] - - valOffset, mValuePaint); - } else { - - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(val), positions[j], - positions[j + 1] - valOffset, - mValuePaint); - } - } - } - } } - - /** - * draws the circle value indicators - */ + @Override protected void drawAdditional() { - mRenderPaint.setStyle(Paint.Style.FILL); - - ArrayList dataSets = mData.getDataSets(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - LineDataSet dataSet = dataSets.get(i); - - // if drawing circles is enabled for this dataset - if (dataSet.isDrawCirclesEnabled()) { - - ArrayList entries = dataSet.getYVals(); - - float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); - - for (int j = 0; j < positions.length * mPhaseX; j += 2) { - - // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); - - if (isOffContentRight(positions[j])) - break; - - // make sure the circles don't do shitty things outside - // bounds - if (isOffContentLeft(positions[j]) || - isOffContentTop(positions[j + 1]) - || isOffContentBottom(positions[j + 1])) - continue; - - mDrawCanvas.drawCircle(positions[j], positions[j + 1], dataSet.getCircleSize(), - mRenderPaint); - mDrawCanvas.drawCircle(positions[j], positions[j + 1], - dataSet.getCircleSize() / 2f, - mCirclePaintInner); - } - } // else do nothing - - } } - + /** * set the width of the highlightning lines, default 3f * @@ -469,7 +97,7 @@ public void setPaint(Paint p, int which) { switch (which) { case PAINT_CIRCLES_INNER: - mCirclePaintInner = p; +// mCirclePaintInner = p; break; } } @@ -482,7 +110,7 @@ public Paint getPaint(int which) { switch (which) { case PAINT_CIRCLES_INNER: - return mCirclePaintInner; + return null; } return null; @@ -498,8 +126,17 @@ public void setFillFormatter(FillFormatter formatter) { if (formatter == null) formatter = new DefaultFillFormatter(); + else + mFillFormatter = formatter; + } - mFillFormatter = formatter; + /** + * Returns the FillFormatter that handles the position of the filled-line. + * + * @return + */ + public FillFormatter getFillFormatter() { + return mFillFormatter; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 4ae6bc14a4..b26dd64a2e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -133,7 +133,7 @@ protected void onDraw(Canvas canvas) { drawHighlights(); - drawData(); +// drawData(); drawAdditional(); @@ -227,7 +227,7 @@ protected void drawHighlights() { else angle = mRotationAngle + mAbsoluteAngles[xIndex - 1]; - angle *= mPhaseY; + angle *= yyy; float sliceDegrees = mDrawAngles[xIndex]; @@ -284,7 +284,7 @@ protected void drawDataSet(int index) { if (!needsHighlight(e.getXIndex(), index)) { mRenderPaint.setColor(dataSet.getColor(j)); - mDrawCanvas.drawArc(mCircleBox, angle + sliceSpace / 2f, newangle * mPhaseY + mDrawCanvas.drawArc(mCircleBox, angle + sliceSpace / 2f, newangle * yyy - sliceSpace / 2f, true, mRenderPaint); } @@ -296,7 +296,7 @@ protected void drawDataSet(int index) { // } } - angle += newangle * mPhaseX; + angle += newangle * xxx; cnt++; } } @@ -422,7 +422,7 @@ protected void drawValues() { PieDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); - for (int j = 0; j < entries.size() * mPhaseX; j++) { + for (int j = 0; j < entries.size() * xxx; j++) { // offset needed to center the drawn text in the slice float offset = mDrawAngles[cnt] / 2; @@ -430,10 +430,10 @@ protected void drawValues() { // calculate the text position float x = (float) (r * Math.cos(Math.toRadians((mRotationAngle + mAbsoluteAngles[cnt] - offset) - * mPhaseY)) + center.x); + * yyy)) + center.x); float y = (float) (r * Math.sin(Math.toRadians((mRotationAngle + mAbsoluteAngles[cnt] - offset) - * mPhaseY)) + center.y); + * yyy)) + center.y); String val = ""; float value = entries.get(j).getVal(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 42a651b40d..f6c6b06015 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -14,8 +14,8 @@ import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.utils.LimitLine; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.utils.XAxis; +import com.github.mikephil.charting.utils.YAxis; import java.util.ArrayList; @@ -55,10 +55,10 @@ public class RadarChart extends PieRadarChartBase { private boolean mDrawWeb = true; /** the object reprsenting the y-axis labels */ - private YLabels mYLabels = new YLabels(); + private YAxis mYLabels = new YAxis(); /** the object representing the x-axis labels */ - private XLabels mXLabels = new XLabels(); + private XAxis mXLabels = new XAxis(); public RadarChart(Context context) { super(context); @@ -124,7 +124,7 @@ protected void onDraw(Canvas canvas) { drawLimitLines(); - drawData(); +// drawData(); drawAdditional(); @@ -530,7 +530,7 @@ public int getIndexForAngle(float angle) { * * @return */ - public YLabels getYLabels() { + public YAxis getYLabels() { return mYLabels; } @@ -539,7 +539,7 @@ public YLabels getYLabels() { * * @return */ - public XLabels getXLabels() { + public XAxis getXLabels() { return mXLabels; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index c764a5d50d..417313dc50 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -67,11 +67,11 @@ protected void drawDataSet(int index) { float shapeHalf = dataSet.getScatterShapeSize() / 2f; - float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); + float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, yyy); ScatterShape shape = dataSet.getScatterShape(); - for (int j = 0; j < valuePoints.length * mPhaseX; j += 2) { + for (int j = 0; j < valuePoints.length * xxx; j += 2) { if (isOffContentRight(valuePoints[j])) break; @@ -145,11 +145,11 @@ protected void drawValues() { ScatterDataSet dataSet = dataSets.get(i); ArrayList entries = dataSet.getYVals(); - float[] positions = mTrans.generateTransformedValuesLineScatter(entries, mPhaseY); + float[] positions = mTrans.generateTransformedValuesLineScatter(entries, yyy); float shapeSize = dataSet.getScatterShapeSize(); - for (int j = 0; j < positions.length * mPhaseX; j += 2) { + for (int j = 0; j < positions.length * xxx; j += 2) { if (isOffContentRight(positions[j])) break; @@ -192,10 +192,10 @@ protected void drawHighlights() { int xIndex = mIndicesToHightlight[i].getXIndex(); // get the // x-position - if (xIndex > mDeltaX * mPhaseX) + if (xIndex > mDeltaX * xxx) continue; - float y = set.getYValForXIndex(xIndex) * mPhaseY; // get the + float y = set.getYValForXIndex(xIndex) * yyy; // get the // y-position float[] pts = new float[] { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java index 801683c1c9..a4876b05b8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java @@ -9,7 +9,7 @@ * @author Philipp Jahoda */ public abstract class BarLineScatterCandleData> - extends BarLineScatterCandleRadarData { + extends ChartData { public BarLineScatterCandleData(ArrayList xVals) { super(xVals); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarData.java deleted file mode 100644 index 4e36f189bd..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarData.java +++ /dev/null @@ -1,107 +0,0 @@ - -package com.github.mikephil.charting.data; - -import com.github.mikephil.charting.utils.LimitLine; - -import java.util.ArrayList; - -/** - * Baseclass for all Line, Bar, Radar and ScatterData. Supports LimitLines. - * - * @author Philipp Jahoda - */ -public abstract class BarLineScatterCandleRadarData> - extends ChartData { - - /** array of limit-lines that are set for this data object */ - private ArrayList mLimitLines; - - public BarLineScatterCandleRadarData(ArrayList xVals) { - super(xVals); - } - - public BarLineScatterCandleRadarData(String[] xVals) { - super(xVals); - } - - public BarLineScatterCandleRadarData(ArrayList xVals, ArrayList sets) { - super(xVals, sets); - } - - public BarLineScatterCandleRadarData(String[] xVals, ArrayList sets) { - super(xVals, sets); - } - - /** - * Adds a new LimitLine to the data. - * - * @param limitLine - */ - public void addLimitLine(LimitLine limitLine) { - if (mLimitLines == null) - mLimitLines = new ArrayList(); - mLimitLines.add(limitLine); - updateMinMax(); - } - - /** - * Adds a new array of LimitLines. - * - * @param lines - */ - public void addLimitLines(ArrayList lines) { - mLimitLines = lines; - updateMinMax(); - } - - /** - * Resets the limit lines array to null. Causes no more limit lines to be - * set for this data object. - */ - public void resetLimitLines() { - mLimitLines = null; - calcMinMax(mDataSets); - } - - /** - * Returns the LimitLine array of this data object. - * - * @return - */ - public ArrayList getLimitLines() { - return mLimitLines; - } - - /** - * Returns the LimitLine from the limitlines array at the specified index. - * - * @param index - * @return - */ - public LimitLine getLimitLine(int index) { - if (mLimitLines == null || mLimitLines.size() <= index) - return null; - else - return mLimitLines.get(index); - } - - /** - * Updates the min and max y-value according to the set limits. - */ - private void updateMinMax() { - - if (mLimitLines == null) - return; - - for (int i = 0; i < mLimitLines.size(); i++) { - - LimitLine l = mLimitLines.get(i); - - if (l.getLimit() > mYMax) - mYMax = l.getLimit(); - - if (l.getLimit() < mYMin) - mYMin = l.getLimit(); - } - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 0dc872aed3..c0df61e86d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -5,6 +5,7 @@ import android.graphics.Color; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.YAxis.AxisDependency; import java.util.ArrayList; @@ -39,6 +40,11 @@ public abstract class DataSet { /** flag that indicates if the DataSet is visible or not */ private boolean mVisible = true; + /** if true, y-values are drawn on the chart */ + private boolean mDrawValues = true; + + private AxisDependency mAxisDependency = AxisDependency.LEFT; + /** * Creates a new DataSet object with the given values it represents. Also, a * label that describes the DataSet can be specified. The label can also be @@ -328,6 +334,34 @@ public void setVisible(boolean visible) { public boolean isVisible() { return mVisible; } + + public AxisDependency getAxisDependency() { + return mAxisDependency; + } + + public void setAxisDependency(AxisDependency dependency) { + mAxisDependency = dependency; + } + + /** + * set this to true to draw y-values on the chart NOTE (for bar and + * linechart): if "maxvisiblecount" is reached, no values will be drawn even + * if this is enabled + * + * @param enabled + */ + public void setDrawValues(boolean enabled) { + this.mDrawValues = enabled; + } + + /** + * returns true if y-value drawing is enabled, false if not + * + * @return + */ + public boolean isDrawValuesEnabled() { + return mDrawValues; + } /** * Adds an Entry to the DataSet dynamically. This will also recalculate the @@ -526,33 +560,9 @@ public int getEntryPosition(Entry e) { } // /** - // * Convenience method to create multiple DataSets of different types with - // * various double value arrays. Each double array represents the data of - // one - // * DataSet with a type created by this method, starting at 0 (and - // * incremented). - // * - // * @param yValues - // * @return + // * ################ ################ ################ ################ // */ - // public static ArrayList makeDataSets(ArrayList - // yValues) { - // - // ArrayList dataSets = new ArrayList(); - // - // for (int i = 0; i < yValues.size(); i++) { - // - // Double[] curValues = yValues.get(i); - // - // ArrayList entries = new ArrayList(); + // /** BELOW THIS CODE FOR DRAWING */ // - // for (int j = 0; j < curValues.length; j++) { - // entries.add(new Entry(curValues[j].floatValue(), j)); - // } - // - // dataSets.add(new DataSet(entries, "DS " + i)); - // } - // - // return dataSets; - // } + // public abstract void drawData(Canvas c); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 122e8778e3..6b3909f254 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -8,7 +8,7 @@ * * @author Philipp Jahoda */ -public class RadarData extends BarLineScatterCandleRadarData { +public class RadarData extends ChartData { public RadarData(ArrayList xVals) { super(xVals); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index e243e30c2f..a39de7d9ba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -13,13 +13,13 @@ */ public interface ChartInterface { - public float getOffsetBottom(); - - public float getOffsetTop(); - - public float getOffsetLeft(); - - public float getOffsetRight(); +// public float getOffsetBottom(); +// +// public float getOffsetTop(); +// +// public float getOffsetLeft(); +// +// public float getOffsetRight(); public float getDeltaX(); @@ -33,6 +33,8 @@ public interface ChartInterface { public int getHeight(); + public boolean isStartAtZeroEnabled(); + public PointF getCenterOfView(); public PointF getCenterOffsets(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 93b3fe579d..d2028b84bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.OnChartGestureListener; +import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; /** @@ -64,9 +65,9 @@ public class BarLineChartTouchListener entries = dataSet.getYVals(); + + if (entries.size() < 1) + return; + + mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); + mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); + + // if drawing cubic lines is enabled + if (dataSet.isDrawCubicEnabled()) { + drawCubic(c, dataSet, entries); + + // draw normal (straight) lines + } else { + drawLinear(c, dataSet, entries); + } + + mRenderPaint.setPathEffect(null); + } + + protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + // get the color that is specified for this position from the + // DataSet + mRenderPaint.setColor(dataSet.getColor()); + + float intensity = dataSet.getCubicIntensity(); + + // the path for the cubic-spline + Path spline = new Path(); + + ArrayList points = new ArrayList(); + + for (Entry e : entries) { + if (e != null) + points.add(new CPoint(e.getXIndex(), e.getVal())); + } + + if (points.size() > 1) { + for (int j = 0; j < points.size() * phaseX; j++) { + + CPoint point = points.get(j); + + if (j == 0) { + CPoint next = points.get(j + 1); + point.dx = ((next.x - point.x) * intensity); + point.dy = ((next.y - point.y) * intensity); + } + else if (j == points.size() - 1) { + CPoint prev = points.get(j - 1); + point.dx = ((point.x - prev.x) * intensity); + point.dy = ((point.y - prev.y) * intensity); + } + else { + CPoint next = points.get(j + 1); + CPoint prev = points.get(j - 1); + point.dx = ((next.x - prev.x) * intensity); + point.dy = ((next.y - prev.y) * intensity); + } + + // create the cubic-spline path + if (j == 0) { + spline.moveTo(point.x, point.y * phaseY); + } + else { + CPoint prev = points.get(j - 1); + spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * phaseY, point.x + - point.dx, + (point.y - point.dy) * phaseY, point.x, point.y * phaseY); + } + } + } + + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + drawCubicFill(dataSet, spline); + } else { + mRenderPaint.setStyle(Paint.Style.STROKE); + } + + trans.pathValueToPixel(spline); + + c.drawPath(spline, mRenderPaint); + } + + protected void drawCubicFill(LineDataSet dataSet, Path spline) { + float fillMin = mChart.getFillFormatter() + .getFillLinePosition(dataSet, mChart.getData(), mChart.getYChartMax(), + mChart.getYChartMin()); + + spline.lineTo((mChart.getDeltaX() + 1) * mAnimator.getPhaseX(), fillMin); + spline.lineTo(0, fillMin); + spline.close(); + + mRenderPaint.setStyle(Paint.Style.FILL); + } + + protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entries) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + mRenderPaint.setStyle(Paint.Style.STROKE); + + // more than 1 color + if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { + + float[] positions = trans.generateTransformedValuesLineScatter( + entries, phaseY); + + for (int j = 0; j < (positions.length - 2) * phaseX; j += 2) { + + if (!mViewPortHandler.isInBoundsRight(positions[j])) + break; + + // make sure the lines don't do shitty things outside + // bounds + if (j != 0 && !mViewPortHandler.isInBoundsLeft(positions[j - 1]) + && !mViewPortHandler.isInBoundsY(positions[j + 1])) + continue; + + // get the color that is set for this line-segment + mRenderPaint.setColor(dataSet.getColor(j / 2)); + + c.drawLine(positions[j], positions[j + 1], + positions[j + 2], positions[j + 3], mRenderPaint); + } + + } else { // only one color per dataset + + mRenderPaint.setColor(dataSet.getColor()); + + Path line = generateLinePath(entries); + trans.pathValueToPixel(line); + + c.drawPath(line, mRenderPaint); + } + + mRenderPaint.setPathEffect(null); + + // if drawing filled is enabled + if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { + drawLinearFill(c, dataSet, entries, trans); + } + } + + protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList entries, + Transformer trans) { + + // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, + // valuePoints.length, valuePoints, 0, + // null, 0, null, 0, null, 0, 0, paint); + + mRenderPaint.setStyle(Paint.Style.FILL); + + mRenderPaint.setColor(dataSet.getFillColor()); + // filled is drawn with less alpha + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + + // mRenderPaint.setShader(dataSet.getShader()); + + Path filled = generateFilledPath( + entries, + mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getData(), + mChart.getYChartMax(), mChart.getYChartMin())); + + trans.pathValueToPixel(filled); + + c.drawPath(filled, mRenderPaint); + + // restore alpha + mRenderPaint.setAlpha(255); + // mRenderPaint.setShader(null); + } + + /** + * Generates the path that is used for filled drawing. + * + * @param entries + * @return + */ + private Path generateFilledPath(ArrayList entries, float fillMin) { + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + Path filled = new Path(); + filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); + + // create a new path + for (int x = 1; x < entries.size() * phaseX; x++) { + + Entry e = entries.get(x); + filled.lineTo(e.getXIndex(), e.getVal() * phaseY); + } + + // close up + filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex(), fillMin); + filled.lineTo(entries.get(0).getXIndex(), fillMin); + filled.close(); + + return filled; + } + + /** + * Generates the path that is used for drawing a single line. + * + * @param entries + * @return + */ + private Path generateLinePath(ArrayList entries) { + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + Path line = new Path(); + line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); + + // create a new path + for (int x = 1; x < entries.size() * phaseX; x++) { + + Entry e = entries.get(x); + line.lineTo(e.getXIndex(), e.getVal() * phaseY); + } + + return line; + } + + @Override + public void drawValues(Canvas c) { + + // if values are drawn + if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleX()) { + + ArrayList dataSets = mChart.getData().getDataSets(); + + for (int i = 0; i < dataSets.size(); i++) { + + LineDataSet dataSet = dataSets.get(i); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + if (!dataSet.isDrawValuesEnabled()) + continue; + + // make sure the values do not interfear with the circles + int valOffset = (int) (dataSet.getCircleSize() * 1.75f); + + if (!dataSet.isDrawCirclesEnabled()) + valOffset = valOffset / 2; + + ArrayList entries = dataSet.getYVals(); + + float[] positions = trans.generateTransformedValuesLineScatter( + entries, mAnimator.getPhaseY()); + + for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + + float x = positions[j]; + float y = positions[j + 1]; + + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) + continue; + + float val = entries.get(j / 2).getVal(); + + c.drawText(mChart.getValueFormatter().getFormattedValue(val), x, y - valOffset, + mValuePaint); + } + } + } + } + + @Override + public void drawExtras(Canvas c) { + drawCircles(c); + } + + private void drawCircles(Canvas c) { + mRenderPaint.setStyle(Paint.Style.FILL); + + ArrayList dataSets = mChart.getData().getDataSets(); + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + LineDataSet dataSet = dataSets.get(i); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + // if drawing circles is enabled for this dataset + if (dataSet.isDrawCirclesEnabled()) { + + ArrayList entries = dataSet.getYVals(); + + float[] positions = trans.generateTransformedValuesLineScatter( + entries, mAnimator.getPhaseY()); + + for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + + mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); + + float x = positions[j]; + float y = positions[j + 1]; + + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + // make sure the circles don't do shitty things outside + // bounds + if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) + continue; + + c.drawCircle(x, y, dataSet.getCircleSize(), + mRenderPaint); + c.drawCircle(x, y, + dataSet.getCircleSize() / 2f, + mCirclePaintInner); + } + } // else do nothing + } + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + for (int i = 0; i < indices.length; i++) { + + LineDataSet set = mChart.getData().getDataSetByIndex(indices[i] + .getDataSetIndex()); + + if (set == null) + continue; + + mHighlightPaint.setColor(set.getHighLightColor()); + + int xIndex = indices[i].getXIndex(); // get the + // x-position + + if (xIndex > mChart.getDeltaX() * mAnimator.getPhaseX()) + continue; + + float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get the + // y-position + + float[] pts = new float[] { + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, mChart.getDeltaX(), y + }; + + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + // draw the highlight lines + c.drawLines(pts, mHighlightPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java new file mode 100644 index 0000000000..2d4af3f83a --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -0,0 +1,17 @@ + +package com.github.mikephil.charting.renderer; + + +/** + * Abstract baseclass of all Renderers. + * + * @author Philipp Jahoda + */ +public abstract class Renderer { + + protected ViewPortHandler mViewPortHandler; + + public Renderer(ViewPortHandler viewPortHandler) { + this.mViewPortHandler = viewPortHandler; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java index 2112a26853..e61fdabf70 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java @@ -4,12 +4,11 @@ import android.graphics.Matrix; import android.graphics.Path; import android.graphics.RectF; -import android.view.View; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.PointD; import java.util.ArrayList; @@ -26,33 +25,11 @@ public class Transformer { /** matrix for handling the different offsets of the chart */ protected Matrix mMatrixOffset = new Matrix(); + + private ViewPortHandler mViewPortHandler; - /** matrix used for touch events */ - protected final Matrix mMatrixTouch = new Matrix(); - - /** if set to true, the y-axis is inverted and low values start at the top */ - private boolean mInvertYAxis = false; - - /** minimum scale value on the y-axis */ - private float mMinScaleY = 1f; - - /** minimum scale value on the x-axis */ - private float mMinScaleX = 1f; - - /** contains the current scale factor of the x-axis */ - private float mScaleX = 1f; - - /** contains the current scale factor of the y-axis */ - private float mScaleY = 1f; - - /** offset that allows the chart to be dragged over its bounds on the x-axis */ - private float mTransOffsetX = 0f; - - /** offset that allows the chart to be dragged over its bounds on the x-axis */ - private float mTransOffsetY = 0f; - - public Transformer() { - + public Transformer(ViewPortHandler viewPortHandler) { + this.mViewPortHandler = viewPortHandler; } /** @@ -61,16 +38,14 @@ public Transformer() { * * @param chart */ - public void prepareMatrixValuePx(ChartInterface chart) { + public void prepareMatrixValuePx(ViewPortHandler viewport, float deltaX, float deltaY, float yChartMin) { - float scaleX = (float) ((chart.getWidth() - chart.getOffsetRight() - chart - .getOffsetLeft()) / chart.getDeltaX()); - float scaleY = (float) ((chart.getHeight() - chart.getOffsetTop() - chart - .getOffsetBottom()) / chart.getDeltaY()); + float scaleX = (float) ((viewport.getChartWidth() - viewport.contentRight() - viewport.offsetLeft()) / deltaX); + float scaleY = (float) ((viewport.getChartHeight() - viewport.offsetTop() - viewport.offsetBottom()) / deltaY); // setup all matrices mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + mMatrixValueToPx.postTranslate(0, -yChartMin); mMatrixValueToPx.postScale(scaleX, -scaleY); } @@ -93,17 +68,17 @@ public void prepareMatrixValuePx(ChartInterface chart, float scaleX, float scale * * @param chart */ - public void prepareMatrixOffset(ChartInterface chart) { + public void prepareMatrixOffset(ViewPortHandler viewport, boolean inverted) { mMatrixOffset.reset(); // offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); - if (!mInvertYAxis) - mMatrixOffset.postTranslate(chart.getOffsetLeft(), - chart.getHeight() - chart.getOffsetBottom()); + if (!inverted) + mMatrixOffset.postTranslate(viewport.offsetLeft(), + viewport.getChartHeight() - viewport.offsetBottom()); else { - mMatrixOffset.setTranslate(chart.getOffsetLeft(), -chart.getOffsetTop()); + mMatrixOffset.setTranslate(viewport.offsetLeft(), -viewport.offsetTop()); mMatrixOffset.postScale(1.0f, -1.0f); } @@ -185,7 +160,7 @@ public float[] generateTransformedValuesBarChart(ArrayList entr public void pathValueToPixel(Path path) { path.transform(mMatrixValueToPx); - path.transform(mMatrixTouch); + path.transform(mViewPortHandler.getMatrixTouch()); path.transform(mMatrixOffset); } @@ -210,7 +185,7 @@ public void pathValuesToPixel(ArrayList paths) { public void pointValuesToPixel(float[] pts) { mMatrixValueToPx.mapPoints(pts); - mMatrixTouch.mapPoints(pts); + mViewPortHandler.getMatrixTouch().mapPoints(pts); mMatrixOffset.mapPoints(pts); } @@ -222,7 +197,7 @@ public void pointValuesToPixel(float[] pts) { public void rectValueToPixel(RectF r) { mMatrixValueToPx.mapRect(r); - mMatrixTouch.mapRect(r); + mViewPortHandler.getMatrixTouch().mapRect(r); mMatrixOffset.mapRect(r); } @@ -241,7 +216,7 @@ public void rectValueToPixel(RectF r, float phaseY) { r.bottom *= phaseY; mMatrixValueToPx.mapRect(r); - mMatrixTouch.mapRect(r); + mViewPortHandler.getMatrixTouch().mapRect(r); mMatrixOffset.mapRect(r); } @@ -270,7 +245,7 @@ public void pixelsToValue(float[] pixels) { mMatrixOffset.invert(tmp); tmp.mapPoints(pixels); - mMatrixTouch.invert(tmp); + mViewPortHandler.getMatrixTouch().invert(tmp); tmp.mapPoints(pixels); mMatrixValueToPx.invert(tmp); @@ -278,229 +253,28 @@ public void pixelsToValue(float[] pixels) { } /** - * ################ ################ ################ ################ - */ - /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ - - /** - * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom - * center. - * - * @param x - * @param y - */ - public Matrix zoomIn(float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(1.4f, 1.4f, x, y); - - return save; - } - - /** - * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom - * center. - */ - public Matrix zoomOut(float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(0.7f, 0.7f, x, y); - - return save; - } - - /** - * Zooms in or out by the given scale factor. x and y are the coordinates - * (in pixels) of the zoom center. + * Returns the x and y values in the chart at the given touch point + * (encapsulated in a PointD). This method transforms pixel coordinates to + * coordinates / values in the chart. This is the opposite method to + * getPixelsForValues(...). * - * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in - * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in * @param x * @param y - */ - public Matrix zoom(float scaleX, float scaleY, float x, float y) { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - // Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y); - - save.postScale(scaleX, scaleY, x, y); - - return save; - } - - /** - * Resets all zooming and dragging and makes the chart fit exactly it's - * bounds. - */ - public Matrix fitScreen() { - - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - float[] vals = new float[9]; - - save.getValues(vals); - - // reset all translations and scaling - vals[Matrix.MTRANS_X] = 0f; - vals[Matrix.MTRANS_Y] = 0f; - vals[Matrix.MSCALE_X] = 1f; - vals[Matrix.MSCALE_Y] = 1f; - - save.setValues(vals); - - return save; - } - - /** - * If this is set to true, the y-axis is inverted which means that low - * values are on top of the chart, high values on bottom. - * - * @param enabled - */ - public void setInvertYAxisEnabled(boolean enabled) { - mInvertYAxis = enabled; - } - - /** - * If this returns true, the y-axis is inverted. - * * @return */ - public boolean isInvertYAxisEnabled() { - return mInvertYAxis; - } - - /** - * Centers the viewport around the specified position (x-index and y-value) - * in the chart. Centering the viewport outside the bounds of the chart is - * not possible. Makes most sense in combination with the - * setScaleMinima(...) method. - * - * @param pts the position to center view viewport to - * @param chart - * @return save - */ - public synchronized void centerViewPort(final float[] pts, final ChartInterface chart) { - - final View v = chart.getChartView(); - - v.post(new Runnable() { - - @Override - public void run() { - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - pointValuesToPixel(pts); - - final float x = pts[0] - chart.getOffsetLeft(); - final float y = pts[1] - chart.getOffsetTop(); - - save.postTranslate(-x, -y); - - refresh(save, chart); - } - }); - } - - /** - * call this method to refresh the graph with a given matrix - * - * @param newMatrix - * @return - */ - public Matrix refresh(Matrix newMatrix, ChartInterface chart) { - - mMatrixTouch.set(newMatrix); - - // make sure scale and translation are within their bounds - limitTransAndScale(mMatrixTouch, chart.getContentRect()); - - chart.getChartView().invalidate(); - - newMatrix.set(mMatrixTouch); - return newMatrix; - } - - /** - * limits the maximum scale and X translation of the given matrix - * - * @param matrix - */ - private void limitTransAndScale(Matrix matrix, RectF content) { - - float[] vals = new float[9]; - matrix.getValues(vals); - - float curTransX = vals[Matrix.MTRANS_X]; - float curScaleX = vals[Matrix.MSCALE_X]; - - float curTransY = vals[Matrix.MTRANS_Y]; - float curScaleY = vals[Matrix.MSCALE_Y]; - - // min scale-x is 1f - mScaleX = Math.max(mMinScaleX, curScaleX); - - // min scale-y is 1f - mScaleY = Math.max(mMinScaleY, curScaleY); - - float width = 0f; - float height = 0f; - - if (content != null) { - width = content.width(); - height = content.height(); - } - - float maxTransX = -width * (mScaleX - 1f); - float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); - - // if(curScaleX < mMinScaleX) { - // newTransX = (-width * (mScaleX - 1f)) / 2f; - // } - - float maxTransY = height * (mScaleY - 1f); - float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); + public PointD getValuesByTouchPoint(float x, float y) { - // if(curScaleY < mMinScaleY) { - // newTransY = (height * (mScaleY - 1f)) / 2f; - // } + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + pts[1] = y; - vals[Matrix.MTRANS_X] = newTransX; - vals[Matrix.MSCALE_X] = mScaleX; + pixelsToValue(pts); - vals[Matrix.MTRANS_Y] = newTransY; - vals[Matrix.MSCALE_Y] = mScaleY; + double xTouchVal = pts[0]; + double yTouchVal = pts[1]; - matrix.setValues(vals); - } - - /** - * Sets the minimum scale values for both axes. This limits the extent to - * which the user can zoom-out. - * - * @param scaleXmin - * @param scaleYmin - */ - public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { - - if (scaleXmin < 1f) - scaleXmin = 1f; - if (scaleYmin < 1f) - scaleYmin = 1f; - - mMinScaleX = scaleXmin; - mMinScaleY = scaleYmin; - - Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); - refresh(save, chart); + return new PointD(xTouchVal, yTouchVal); } // /** @@ -525,10 +299,6 @@ public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface char // } // } - public Matrix getTouchMatrix() { - return mMatrixTouch; - } - public Matrix getValueMatrix() { return mMatrixValueToPx; } @@ -536,85 +306,4 @@ public Matrix getValueMatrix() { public Matrix getOffsetMatrix() { return mMatrixOffset; } - - /** - * returns the current x-scale factor - */ - public float getScaleX() { - return mScaleX; - } - - /** - * returns the current y-scale factor - */ - public float getScaleY() { - return mScaleY; - } - - /** - * if the chart is fully zoomed out, return true - * - * @return - */ - public boolean isFullyZoomedOut() { - - if (isFullyZoomedOutX() && isFullyZoomedOutY()) - return true; - else - return false; - } - - /** - * Returns true if the chart is fully zoomed out on it's y-axis (vertical). - * - * @return - */ - public boolean isFullyZoomedOutY() { - if (mScaleY > mMinScaleY || mMinScaleY > 1f) - return false; - else - return true; - } - - /** - * Returns true if the chart is fully zoomed out on it's x-axis - * (horizontal). - * - * @return - */ - public boolean isFullyZoomedOutX() { - if (mScaleX > mMinScaleX || mMinScaleX > 1f) - return false; - else - return true; - } - - /** - * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the x-axis. - * - * @param offset - */ - public void setDragOffsetX(float offset) { - mTransOffsetX = Utils.convertDpToPixel(offset); - } - - /** - * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the y-axis. - * - * @param offset - */ - public void setDragOffsetY(float offset) { - mTransOffsetY = Utils.convertDpToPixel(offset); - } - - /** - * Returns true if both drag offsets (x and y) are zero or smaller. - * - * @return - */ - public boolean hasNoDragOffset() { - return mTransOffsetX <= 0 && mTransOffsetY <= 0 ? true : false; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java new file mode 100644 index 0000000000..ae1e488d4c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -0,0 +1,438 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Matrix; +import android.graphics.PointF; +import android.graphics.RectF; +import android.view.View; + +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.Utils; + +public class ViewPortHandler { + + /** matrix used for touch events */ + protected final Matrix mMatrixTouch = new Matrix(); + + /** this rectangle defines the area in which graph values can be drawn */ + protected RectF mContentRect = new RectF(); + + protected float mChartWidth = 0f; + protected float mChartHeight = 0f; + + /** minimum scale value on the y-axis */ + private float mMinScaleY = 1f; + + /** minimum scale value on the x-axis */ + private float mMinScaleX = 1f; + + /** contains the current scale factor of the x-axis */ + private float mScaleX = 1f; + + /** contains the current scale factor of the y-axis */ + private float mScaleY = 1f; + + /** offset that allows the chart to be dragged over its bounds on the x-axis */ + private float mTransOffsetX = 0f; + + /** offset that allows the chart to be dragged over its bounds on the x-axis */ + private float mTransOffsetY = 0f; + + public ViewPortHandler(float width, float height) { + mChartHeight = height; + mChartWidth = width; + } + + public void restrainViewPort(float offsetLeft, float offsetRight, float offsetTop, float offsetBottom) { + mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight - offsetBottom); + } + + public float offsetLeft() { + return mContentRect.left; + } + + public float offsetRight() { + return mChartWidth - mContentRect.right; + } + + public float offsetTop() { + return mContentRect.top; + } + + public float offsetBottom() { + return mChartHeight - mContentRect.bottom; + } + + public float contentTop() { + return mContentRect.top; + } + + public float contentLeft() { + return mContentRect.left; + } + + public float contentRight() { + return mContentRect.right; + } + + public float contentBottom() { + return mContentRect.bottom; + } + + public float contentWidth() { + return mContentRect.width(); + } + + public float contentHeight() { + return mContentRect.height(); + } + + public RectF getContentRect() { + return mContentRect; + } + + public PointF getContentCenter() { + return new PointF(mContentRect.centerX(), mContentRect.centerY()); + } + + public float getChartHeight() { + return mChartHeight; + } + + public float getChartWidth() { + return mChartWidth; + } + + /** + * ################ ################ ################ ################ + */ + /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ + + /** + * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom + * center. + * + * @param x + * @param y + */ + public Matrix zoomIn(float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.postScale(1.4f, 1.4f, x, y); + + return save; + } + + /** + * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom + * center. + */ + public Matrix zoomOut(float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.postScale(0.7f, 0.7f, x, y); + + return save; + } + + /** + * Zooms in or out by the given scale factor. x and y are the coordinates + * (in pixels) of the zoom center. + * + * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in + * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in + * @param x + * @param y + */ + public Matrix zoom(float scaleX, float scaleY, float x, float y) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + // Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y); + + save.postScale(scaleX, scaleY, x, y); + + return save; + } + + /** + * Resets all zooming and dragging and makes the chart fit exactly it's + * bounds. + */ + public Matrix fitScreen() { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + float[] vals = new float[9]; + + save.getValues(vals); + + // reset all translations and scaling + vals[Matrix.MTRANS_X] = 0f; + vals[Matrix.MTRANS_Y] = 0f; + vals[Matrix.MSCALE_X] = 1f; + vals[Matrix.MSCALE_Y] = 1f; + + save.setValues(vals); + + return save; + } + + /** + * Centers the viewport around the specified position (x-index and y-value) + * in the chart. Centering the viewport outside the bounds of the chart is + * not possible. Makes most sense in combination with the + * setScaleMinima(...) method. + * + * @param pts the position to center view viewport to + * @param chart + * @return save + */ + public synchronized void centerViewPort(final float[] transformedPts, final ChartInterface chart) { + + final View v = chart.getChartView(); + + v.post(new Runnable() { + + @Override + public void run() { + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + final float x = transformedPts[0] - offsetLeft(); + final float y = transformedPts[1] - offsetTop(); + + save.postTranslate(-x, -y); + + refresh(save, chart); + } + }); + } + + /** + * call this method to refresh the graph with a given matrix + * + * @param newMatrix + * @return + */ + public Matrix refresh(Matrix newMatrix, ChartInterface chart) { + + mMatrixTouch.set(newMatrix); + + // make sure scale and translation are within their bounds + limitTransAndScale(mMatrixTouch, mContentRect); + + chart.getChartView().invalidate(); + + newMatrix.set(mMatrixTouch); + return newMatrix; + } + + /** + * limits the maximum scale and X translation of the given matrix + * + * @param matrix + */ + public void limitTransAndScale(Matrix matrix, RectF content) { + + float[] vals = new float[9]; + matrix.getValues(vals); + + float curTransX = vals[Matrix.MTRANS_X]; + float curScaleX = vals[Matrix.MSCALE_X]; + + float curTransY = vals[Matrix.MTRANS_Y]; + float curScaleY = vals[Matrix.MSCALE_Y]; + + // min scale-x is 1f + mScaleX = Math.max(mMinScaleX, curScaleX); + + // min scale-y is 1f + mScaleY = Math.max(mMinScaleY, curScaleY); + + float width = 0f; + float height = 0f; + + if (content != null) { + width = content.width(); + height = content.height(); + } + + float maxTransX = -width * (mScaleX - 1f); + float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); + + // if(curScaleX < mMinScaleX) { + // newTransX = (-width * (mScaleX - 1f)) / 2f; + // } + + float maxTransY = height * (mScaleY - 1f); + float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); + + // if(curScaleY < mMinScaleY) { + // newTransY = (height * (mScaleY - 1f)) / 2f; + // } + + vals[Matrix.MTRANS_X] = newTransX; + vals[Matrix.MSCALE_X] = mScaleX; + + vals[Matrix.MTRANS_Y] = newTransY; + vals[Matrix.MSCALE_Y] = mScaleY; + + matrix.setValues(vals); + } + + /** + * Sets the minimum scale values for both axes. This limits the extent to + * which the user can zoom-out. + * + * @param scaleXmin + * @param scaleYmin + */ + public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { + + if (scaleXmin < 1f) + scaleXmin = 1f; + if (scaleYmin < 1f) + scaleYmin = 1f; + + mMinScaleX = scaleXmin; + mMinScaleY = scaleYmin; + + Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); + refresh(save, chart); + } + + public Matrix getMatrixTouch() { + return mMatrixTouch; + } + + /** + * ################ ################ ################ ################ + */ + /** BELOW METHODS FOR BOUNDS CHECK */ + + public boolean isInBoundsX(float x) { + if (isInBoundsLeft(x) && isInBoundsRight(x)) + return true; + else + return false; + } + + public boolean isInBoundsY(float y) { + if (isInBoundsTop(y) && isInBoundsBottom(y)) + return true; + else + return false; + } + + public boolean isInBounds(float x, float y) { + if (isInBoundsX(x) && isInBoundsY(y)) + return true; + else + return false; + } + + public boolean isInBoundsLeft(float x) { + return mContentRect.left <= x ? true : false; + } + + public boolean isInBoundsRight(float x) { + return mContentRect.right >= x ? true : false; + } + + public boolean isInBoundsTop(float y) { + return mContentRect.top <= y ? true : false; + } + + public boolean isInBoundsBottom(float y) { + return mContentRect.bottom >= y ? true : false; + } + + + /** + * returns the current x-scale factor + */ + public float getScaleX() { + return mScaleX; + } + + /** + * returns the current y-scale factor + */ + public float getScaleY() { + return mScaleY; + } + + /** + * if the chart is fully zoomed out, return true + * + * @return + */ + public boolean isFullyZoomedOut() { + + if (isFullyZoomedOutX() && isFullyZoomedOutY()) + return true; + else + return false; + } + + /** + * Returns true if the chart is fully zoomed out on it's y-axis (vertical). + * + * @return + */ + public boolean isFullyZoomedOutY() { + if (mScaleY > mMinScaleY || mMinScaleY > 1f) + return false; + else + return true; + } + + /** + * Returns true if the chart is fully zoomed out on it's x-axis + * (horizontal). + * + * @return + */ + public boolean isFullyZoomedOutX() { + if (mScaleX > mMinScaleX || mMinScaleX > 1f) + return false; + else + return true; + } + + /** + * Set an offset in dp that allows the user to drag the chart over it's + * bounds on the x-axis. + * + * @param offset + */ + public void setDragOffsetX(float offset) { + mTransOffsetX = Utils.convertDpToPixel(offset); + } + + /** + * Set an offset in dp that allows the user to drag the chart over it's + * bounds on the y-axis. + * + * @param offset + */ + public void setDragOffsetY(float offset) { + mTransOffsetY = Utils.convertDpToPixel(offset); + } + + /** + * Returns true if both drag offsets (x and y) are zero or smaller. + * + * @return + */ + public boolean hasNoDragOffset() { + return mTransOffsetX <= 0 && mTransOffsetY <= 0 ? true : false; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java new file mode 100644 index 0000000000..ee9d7f01b7 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -0,0 +1,156 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Align; + +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.XAxis; +import com.github.mikephil.charting.utils.XAxis.XLabelPosition; + +public class XAxisRenderer extends AxisRenderer { + + /** paint for the x-label values */ + protected Paint mXLabelPaint; + + protected XAxis mXAxis; + + public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { + super(viewPortHandler, trans); + + this.mXAxis = xAxis; + + mXLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mXLabelPaint.setColor(Color.BLACK); + mXLabelPaint.setTextAlign(Align.CENTER); + mXLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + } + + public void computeAxis(float xValAverageLength) { + + StringBuffer a = new StringBuffer(); + + int max = (int) Math.round(xValAverageLength + + mXAxis.getSpaceBetweenLabels()); + + for (int i = 0; i < max; i++) { + a.append("h"); + } + + mXAxis.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); + mXAxis.mLabelHeight = Utils.calcTextHeight(mXLabelPaint, "Q"); + } + + @Override + public void renderAxis(Canvas c) { + + float yoffset = Utils.convertDpToPixel(4f); + + mXLabelPaint.setTypeface(mXAxis.getTypeface()); + mXLabelPaint.setTextSize(mXAxis.getTextSize()); + mXLabelPaint.setColor(mXAxis.getTextColor()); + + if (mXAxis.getPosition() == XLabelPosition.TOP) { + + drawLabels(c, mViewPortHandler.offsetTop() - yoffset); + + } else if (mXAxis.getPosition() == XLabelPosition.BOTTOM) { + + drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.5f); + + } else if (mXAxis.getPosition() == XLabelPosition.BOTTOM_INSIDE) { + + drawLabels(c, mViewPortHandler.contentBottom() - yoffset); + + } else if (mXAxis.getPosition() == XLabelPosition.TOP_INSIDE) { + + drawLabels(c, mViewPortHandler.offsetTop() + yoffset + mXAxis.mLabelHeight); + + } else { // BOTH SIDED + + drawLabels(c, mViewPortHandler.offsetTop() - yoffset); + drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.6f); + } + } + + /** + * draws the x-labels on the specified y-position + * + * @param yPos + */ + private void drawLabels(Canvas c, float yPos) { + + // pre allocate to save performance (dont allocate in loop) + float[] position = new float[] { + 0f, 0f + }; + + for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { + + position[0] = i; + + // center the text + if (mXAxis.isCenterXLabelsEnabled()) + position[0] += 0.5f; + + mTrans.pointValuesToPixel(position); + + if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { + + String label = mData.getXVals().get(i); + + if (mXAxis.isAvoidFirstLastClippingEnabled()) { + + // avoid clipping of the last + if (i == mData.getXValCount() - 1) { + float width = Utils.calcTextWidth(mXLabelPaint, label); + + if (width > mViewPortHandler.offsetRight() * 2 + && position[0] + width > mViewPortHandler.getChartWidth()) + position[0] -= width / 2; + + // avoid clipping of the first + } else if (i == 0) { + + float width = Utils.calcTextWidth(mXLabelPaint, label); + position[0] += width / 2; + } + } + + c.drawText(label, position[0], + yPos, + mXLabelPaint); + } + } + } + + @Override + public void renderGridLines(Canvas c) { + + if (!mXAxis.isDrawGridLinesEnabled()) + return; + + float[] position = new float[] { + 0f, 0f + }; + + mGridPaint.setColor(mXAxis.getGridColor()); + + for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { + + position[0] = i; + + mTrans.pointValuesToPixel(position); + + if (position[0] >= mViewPortHandler.offsetLeft() + && position[0] <= mViewPortHandler.getChartWidth()) { + + c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], + mViewPortHandler.contentBottom(), mGridPaint); + } + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java new file mode 100644 index 0000000000..5206fca9b4 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -0,0 +1,312 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Align; + +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.LimitLine; +import com.github.mikephil.charting.utils.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.utils.YAxis; +import com.github.mikephil.charting.utils.YAxis.AxisDependency; +import com.github.mikephil.charting.utils.YAxis.YLabelPosition; + +import java.util.ArrayList; + +public class YAxisRenderer extends AxisRenderer { + + /** paint for the y-label values */ + protected Paint mYAxisPaint; + + /** paint used for the limit lines */ + protected Paint mLimitLinePaint; + + protected YAxis mYAxis; + + public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { + super(viewPortHandler, trans); + + this.mYAxis = yAxis; + + mYAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mYAxisPaint.setColor(Color.BLACK); + mYAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); + + mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + } + + public void computeAxis(ChartInterface chart) { + + float yMin = 0f; + float yMax = 0f; + + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom()); + + if (!mYAxis.isInverted()) { + yMin = (float) p2.y; + yMax = (float) p1.y; + } else { + + if (!chart.isStartAtZeroEnabled()) + yMin = (float) Math.min(p1.y, p2.y); + else + yMin = 0; + yMax = (float) Math.max(p1.y, p2.y); + } + + } else { + + if (!mYAxis.isInverted()) { + yMin = chart.getYChartMin(); + yMax = chart.getYChartMax(); + } else { + + if (!chart.isStartAtZeroEnabled()) + yMin = (float) Math.min(chart.getYChartMax(), chart.getYChartMin()); + else + yMin = 0; + yMax = (float) Math.max(chart.getYChartMax(), chart.getYChartMin()); + } + } + + computeAxisValues(yMin, yMax); + } + + /** + * Sets up the y-axis labels. Computes the desired number of labels between + * the two given extremes. Unlike the papareXLabels() method, this method + * needs to be called upon every refresh of the view. + * + * @return + */ + private void computeAxisValues(float min, float max) { + + float yMin = min; + float yMax = max; + + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[] {}; + mYAxis.mEntryCount = 0; + return; + } + + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } + + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { + + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; + + } else { + + double first = Math.ceil(yMin / interval) * interval; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } + + mYAxis.mEntryCount = n; + + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } + + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + + if (interval < 1) { + mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mYAxis.mDecimals = 0; + } + } + + /** + * draws the y-axis labels to the screen + */ + @Override + public void renderAxis(Canvas c) { + + float[] positions = new float[mYAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + // only fill y values, x values are not needed since the y-labels + // are + // static on the x-axis + positions[i + 1] = mYAxis.mEntries[i / 2]; + } + + mTrans.pointValuesToPixel(positions); + + mYAxisPaint.setTypeface(mYAxis.getTypeface()); + mYAxisPaint.setTextSize(mYAxis.getTextSize()); + mYAxisPaint.setColor(mYAxis.getTextColor()); + + float xoffset = Utils.convertDpToPixel(5f); + float yoffset = Utils.calcTextHeight(mYAxisPaint, "A") / 2.5f; + + AxisDependency dependency = mYAxis.getAxisDependency(); + YLabelPosition labelPosition = mYAxis.getLabelPosition(); + + float xPos = 0f; + + if (dependency == AxisDependency.LEFT) { + + if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + mYAxisPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.offsetLeft() - xoffset; + } else { + mYAxisPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.offsetLeft() + xoffset; + } + + } else { + + if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + mYAxisPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.contentRight() + xoffset; + } else { + mYAxisPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.contentRight() - xoffset; + } + } + + drawYLabels(c, xPos, positions, yoffset); + } + + /** + * draws the y-labels on the specified x-position + * + * @param xPos + * @param positions + */ + private void drawYLabels(Canvas c, float xPos, float[] positions, float yOffset) { + + // draw + for (int i = 0; i < mYAxis.mEntryCount; i++) { + + String text = mYAxis.getFormattedLabel(i); + + if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) + return; + + c.drawText(text, xPos, positions[i * 2 + 1] + yOffset, mYAxisPaint); + } + } + + @Override + public void renderGridLines(Canvas c) { + + if (!mYAxis.isDrawGridLinesEnabled()) + return; + + // pre alloc + float[] position = new float[2]; + + mGridPaint.setColor(mYAxis.getGridColor()); + + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { + + position[1] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); + + c.drawLine(mViewPortHandler.offsetLeft(), position[1], mViewPortHandler.contentRight(), + position[1], + mGridPaint); + } + } + + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { + + ArrayList limitLines = mYAxis.getLimitLines(); + + if (limitLines == null) + return; + + float[] pts = new float[4]; + + for (int i = 0; i < limitLines.size(); i++) { + + LimitLine l = limitLines.get(i); + + pts[1] = l.getLimit(); + pts[3] = l.getLimit(); + + mTrans.pointValuesToPixel(pts); + + pts[0] = 0; + pts[2] = mViewPortHandler.getChartWidth(); + + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + + c.drawLines(pts, mLimitLinePaint); + + // if drawing the limit-value is enabled + if (l.isDrawValueEnabled()) { + + float xOffset = Utils.convertDpToPixel(4f); + float yOffset = l.getLineWidth() + xOffset; + String label = valueFormatter.getFormattedValue(l.getLimit()); + + mLimitLinePaint.setPathEffect(null); + mLimitLinePaint.setColor(l.getTextColor()); + + if (l.getLabelPosition() == LimitLabelPosition.RIGHT) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, mViewPortHandler.contentRight() + - xOffset, + pts[1] - yOffset, mLimitLinePaint); + + } else { + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, mViewPortHandler.offsetLeft() + + xOffset, + pts[1] - yOffset, mLimitLinePaint); + } + } + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LabelBase.java b/MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java similarity index 56% rename from MPChartLib/src/com/github/mikephil/charting/utils/LabelBase.java rename to MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java index 471d15a0fb..59ebde37f0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LabelBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java @@ -9,19 +9,27 @@ * * @author Philipp Jahoda */ -public abstract class LabelBase { +public abstract class AxisBase { /** the typeface to use for the labels */ private Typeface mTypeface; /** the size of the label text */ private float mTextSize = 10f; - + /** the text color to use */ private int mTextColor = Color.BLACK; + /** the color of the axis lines */ + private int mAxisColor = Color.BLACK; + + private int mGridColor = Color.GRAY; + + /** flag indicating if the grid lines for this axis should be drawn */ + private boolean mDrawGridLines = true; + /** default constructor */ - public LabelBase() { + public AxisBase() { mTextSize = Utils.convertDpToPixel(10f); } @@ -86,4 +94,58 @@ public void setTextColor(int color) { public int getTextColor() { return mTextColor; } + + /** + * Returns the color of the axis line. + * + * @return + */ + public int getAxisColor() { + return mAxisColor; + } + + /** + * Sets the color of the axis line. + * + * @param color + */ + public void setAxisColor(int color) { + mAxisColor = color; + } + + /** + * Set this to true to enable drawing the grid lines for this axis. + * + * @param enabled + */ + public void setDrawGridLines(boolean enabled) { + mDrawGridLines = enabled; + } + + /** + * Returns true if drawing grid lines is enabled for this axis. + * + * @return + */ + public boolean isDrawGridLinesEnabled() { + return mDrawGridLines; + } + + /** + * Sets the color of the grid lines for this axis. + * + * @param color + */ + public void setGridColor(int color) { + mGridColor = color; + } + + /** + * Returns the color of the grid lines for this axis. + * + * @return + */ + public int getGridColor() { + return mGridColor; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java index 7ed06e2418..a2a8a98870 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java @@ -22,6 +22,9 @@ public class LimitLine { /** the color of the limit line */ private int mLineColor = Color.rgb(237, 91, 91); + /** the color of the value-text */ + private int mValueTextColor = Color.BLACK; + /** flag that indicates if the value of the limit line is drawn or not */ private boolean mDrawValue = true; @@ -155,6 +158,24 @@ public boolean isDrawValueEnabled() { return mDrawValue; } + /** + * Sets the color of the value-text that is drawn next to the LimitLine. + * + * @param color + */ + public void setTextColor(int color) { + mValueTextColor = color; + } + + /** + * Returns the color of the value-text that is drawn next to the LimitLine. + * + * @return + */ + public int getTextColor() { + return mValueTextColor; + } + /** * Sets the position of the LimitLine value label (either on the right or on * the left edge of the chart). Not supported for RadarChart. diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java b/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java similarity index 99% rename from MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java rename to MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java index 5f63eaf697..d723296a11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XLabels.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java @@ -8,7 +8,7 @@ * * @author Philipp Jahoda */ -public class XLabels extends LabelBase { +public class XAxis extends AxisBase { /** * width of the x-axis labels in pixels - this is calculated by the diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/YLabels.java b/MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java similarity index 70% rename from MPChartLib/src/com/github/mikephil/charting/utils/YLabels.java rename to MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java index 952f838d18..fa3d364d96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/YLabels.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.utils; +import java.util.ArrayList; + /** * Class representing the y-axis labels settings and its entries. Only use the * setter methods to modify it. Do not access public variables directly. Be @@ -9,7 +11,7 @@ * * @author Philipp Jahoda */ -public class YLabels extends LabelBase { +public class YAxis extends AxisBase { /** the actual array of entries */ public float[] mEntries = new float[] {}; @@ -23,11 +25,6 @@ public class YLabels extends LabelBase { /** the number of y-label entries the y-labels should have, default 6 */ private int mLabelCount = 6; - /** - * if true, units are drawn next to the values of the y-axis labels - */ - private boolean mDrawUnitsInLabels = true; - /** indicates if the top y-label entry is drawn or not */ private boolean mDrawTopYLabelEntry = true; @@ -37,21 +34,44 @@ public class YLabels extends LabelBase { /** if true, the y-labels show only the minimum and maximum value */ protected boolean mShowOnlyMinMax = false; + /** flag that indicates if this axis is enabled or not */ + protected boolean mEnabled = true; + + /** flag that indicates if the axis is inverted or not */ + protected boolean mInverted = false; + /** the formatter used to customly format the y-labels */ private ValueFormatter mFormatter = null; + private ArrayList mLimitLines; + /** the position of the y-labels relative to the chart */ - private YLabelPosition mPosition = YLabelPosition.LEFT; + private YLabelPosition mPosition = YLabelPosition.OUTSIDE_CHART; /** enum for the position of the y-labels relative to the chart */ public enum YLabelPosition { - LEFT, RIGHT, BOTH_SIDED, LEFT_INSIDE, RIGHT_INSIDE + OUTSIDE_CHART, INSIDE_CHART + } + + private AxisDependency mAxisDependency; + + public enum AxisDependency { + LEFT, RIGHT + } + + public YAxis(AxisDependency position) { + this.mAxisDependency = position; + this.mLimitLines = new ArrayList(); + } + + public AxisDependency getAxisDependency() { + return mAxisDependency; } /** * returns the position of the y-labels */ - public YLabelPosition getPosition() { + public YLabelPosition getLabelPosition() { return mPosition; } @@ -64,24 +84,6 @@ public void setPosition(YLabelPosition pos) { mPosition = pos; } - /** - * returns true if drawing units in y-axis labels is enabled - * - * @return - */ - public boolean isDrawUnitsInYLabelEnabled() { - return mDrawUnitsInLabels; - } - - /** - * if set to true, units are drawn next to y-label values, default: true - * - * @param enabled - */ - public void setDrawUnitsInYLabel(boolean enabled) { - mDrawUnitsInLabels = enabled; - } - /** * returns true if drawing the top y-axis label entry is enabled * @@ -183,6 +185,77 @@ public boolean isShowOnlyMinMaxEnabled() { return mShowOnlyMinMax; } + /** + * Set this to true to enable this axis from being drawn to the screen. + * + * @param enabled + */ + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } + + /** + * Returns true if the axis is enabled (will be drawn). + * + * @return + */ + public boolean isEnabled() { + return mEnabled; + } + + /** + * If this is set to true, the y-axis is inverted which means that low + * values are on top of the chart, high values on bottom. + * + * @param enabled + */ + public void setInvertAxis(boolean enabled) { + mInverted = enabled; + } + + /** + * If this returns true, the y-axis is inverted. + * + * @return + */ + public boolean isInverted() { + return mInverted; + } + + /** + * Adds a new LimitLine to this axis. + * + * @param l + */ + public void addLimitLine(LimitLine l) { + mLimitLines.add(l); + } + + /** + * Removes the specified LimitLine from the axis. + * + * @param l + */ + public void removeLimitLine(LimitLine l) { + mLimitLines.remove(l); + } + + /** + * Removes all LimitLines from the axis. + */ + public void removeAllLimitLines() { + mLimitLines = new ArrayList(); + } + + /** + * Returns the LimitLines of this axis. + * + * @return + */ + public ArrayList getLimitLines() { + return mLimitLines; + } + /** * Returns the longest formatted label (in terms of characters) the y-labels * contain. From ba18feecf862e4f287510b0e268d9c051d1f7db5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 10 Feb 2015 17:13:37 +0100 Subject: [PATCH 0062/1390] Worked on BarChartRenderer. --- .../mikephil/charting/charts/BarChart.java | 425 +++--------------- .../charting/renderer/BarChartRenderer.java | 357 +++++++++++++++ .../charting/renderer/LineChartRenderer.java | 12 +- 3 files changed, 429 insertions(+), 365 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index d508741dd9..2f30568907 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -26,14 +26,14 @@ */ public class BarChart extends BarLineChartBase { - /** indicates the angle of the 3d effect */ - private float mSkew = 0.3f; - - /** indicates how much the 3d effect goes back */ - private float mDepth = 0.3f; - - /** flag the enables or disables 3d bars */ - private boolean m3DEnabled = false; +// /** indicates the angle of the 3d effect */ +// private float mSkew = 0.3f; +// +// /** indicates how much the 3d effect goes back */ +// private float mDepth = 0.3f; +// +// /** flag the enables or disables 3d bars */ +// private boolean m3DEnabled = false; /** flag that enables or disables the highlighting arrow */ private boolean mDrawHighlightArrow = false; @@ -56,12 +56,6 @@ public class BarChart extends BarLineChartBase { */ protected boolean mDrawBarShadow = true; - /** the rect object that is used for drawing the bar shadow */ - protected RectF mBarShadow = new RectF(); - - /** the rect object that is used for drawing the bars */ - protected RectF mBarRect = new RectF(); - public BarChart(Context context) { super(context); } @@ -77,14 +71,6 @@ public BarChart(Context context, AttributeSet attrs, int defStyle) { @Override protected void init() { super.init(); - - mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mHighlightPaint.setStyle(Paint.Style.FILL); - mHighlightPaint.setColor(Color.rgb(0, 0, 0)); - // set alpha after color - mHighlightPaint.setAlpha(120); - - // calculate3DColors(); } @Override @@ -114,179 +100,12 @@ protected void calcMinMax(boolean fixedValues) { @Override protected void drawHighlights() { - int setCount = mData.getDataSetCount(); - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - Highlight h = mIndicesToHightlight[i]; - int index = h.getXIndex(); - - int dataSetIndex = h.getDataSetIndex(); - BarDataSet set = (BarDataSet) mData.getDataSetByIndex(dataSetIndex); - - if (set == null) - continue; - - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setAlpha(set.getHighLightAlpha()); - - // check outofbounds - if (index < mData.getYValCount() && index >= 0 - && index < (mDeltaX * xxx) / mData.getDataSetCount()) { - - Entry e = getEntryByDataSetIndex(index, dataSetIndex); - - if (e == null) - continue; - - // calculate the correct x-position - float x = index * setCount + dataSetIndex + mData.getGroupSpace() / 2f - + mData.getGroupSpace() * index; - float y = e.getVal(); - - prepareBar(x, y, set.getBarSpace()); - - mDrawCanvas.drawRect(mBarRect, mHighlightPaint); - - if (mDrawHighlightArrow) { - - mHighlightPaint.setAlpha(255); - - // distance between highlight arrow and bar - float offsetY = mDeltaY * 0.07f; - - Path arrow = new Path(); - arrow.moveTo(x + 0.5f, y + offsetY * 0.3f); - arrow.lineTo(x + 0.2f, y + offsetY); - arrow.lineTo(x + 0.8f, y + offsetY); - - mTrans.pathValueToPixel(arrow); - mDrawCanvas.drawPath(arrow, mHighlightPaint); - } - } - } } @Override protected void drawDataSet(int index) { - // the space between bar-groups - float space = mData.getGroupSpace(); - - BarDataSet dataSet = mData.getDataSets().get(index); - boolean noStacks = dataSet.getStackSize() == 1 ? true : false; - - ArrayList entries = dataSet.getYVals(); - - // do the drawing - for (int j = 0; j < dataSet.getEntryCount() * xxx; j++) { - - BarEntry e = entries.get(j); - - // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + j * (mData.getDataSetCount() - 1) + index + space * j + space / 2f; - float y = e.getVal(); - - // no stacks - if (noStacks) { - - prepareBar(x, y, dataSet.getBarSpace()); - - // avoid drawing outofbounds values - if (isOffContentRight(mBarRect.left)) - break; - - if (isOffContentLeft(mBarRect.right)) { - continue; - } - - // if drawing the bar shadow is enabled - if (mDrawBarShadow) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - mDrawCanvas.drawRect(mBarShadow, mRenderPaint); - } - - // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j)); - mDrawCanvas.drawRect(mBarRect, mRenderPaint); - - } else { // stacked bars - - float[] vals = e.getVals(); - - // we still draw stacked bars, but there could be one - // non-stacked - // in between - if (vals == null) { - - prepareBar(x, y, dataSet.getBarSpace()); - - // if drawing the bar shadow is enabled - if (mDrawBarShadow) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - mDrawCanvas.drawRect(mBarShadow, mRenderPaint); - } - - mRenderPaint.setColor(dataSet.getColor(0)); - mDrawCanvas.drawRect(mBarRect, mRenderPaint); - - } else { - - float all = e.getVal(); - - // if drawing the bar shadow is enabled - if (mDrawBarShadow) { - - prepareBar(x, y, dataSet.getBarSpace()); - mRenderPaint.setColor(dataSet.getBarShadowColor()); - mDrawCanvas.drawRect(mBarShadow, mRenderPaint); - } - - // draw the stack - for (int k = 0; k < vals.length; k++) { - - all -= vals[k]; - - prepareBar(x, vals[k] + all, dataSet.getBarSpace()); - - mRenderPaint.setColor(dataSet.getColor(k)); - mDrawCanvas.drawRect(mBarRect, mRenderPaint); - } - } - - // avoid drawing outofbounds values - if (isOffContentRight(mBarRect.left)) - break; - } - } - } - - /** - * Prepares a bar for drawing on the specified x-index and y-position. Also - * prepares the shadow-bar if enabled. - * - * @param x the x-position - * @param y the y-position - * @param barspace the space between bars - */ - protected void prepareBar(float x, float y, float barspace) { - - float spaceHalf = barspace / 2f; - float left = x + spaceHalf; - float right = x + 1f - spaceHalf; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - - mBarRect.set(left, top, right, bottom); - - mTrans.rectValueToPixel(mBarRect, yyy); - - // if a shadow is drawn, prepare it too - if (mDrawBarShadow) { - mBarShadow.set(mBarRect.left, mOffsetTop, mBarRect.right, getHeight() - mOffsetBottom); - } + } @Override @@ -368,95 +187,7 @@ protected void drawVerticalGrid() { @Override protected void drawValues() { - // if values are drawn - if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - - ArrayList dataSets = ((BarData) mData).getDataSets(); - - float posOffset = 0f; - float negOffset = 0f; - - // calculate the correct offset depending on the draw position of - // the value - posOffset = getPositiveYOffset(mDrawValueAboveBar); - negOffset = getNegativeYOffset(mDrawValueAboveBar); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - BarDataSet dataSet = dataSets.get(i); - ArrayList entries = dataSet.getYVals(); - - float[] valuePoints = mTrans.generateTransformedValuesBarChart(entries, i, mData, - yyy); - - // if only single values are drawn (sum) - if (!mDrawValuesForWholeStack) { - - for (int j = 0; j < valuePoints.length * xxx; j += 2) { - - if (isOffContentRight(valuePoints[j])) - break; - - if (isOffContentLeft(valuePoints[j]) || isOffContentTop(valuePoints[j + 1]) - || isOffContentBottom(valuePoints[j + 1])) - continue; - - float val = entries.get(j / 2).getVal(); - - drawValue(val, valuePoints[j], - valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset)); - } - - // if each value of a potential stack should be drawn - } else { - - for (int j = 0; j < (valuePoints.length - 1) * xxx; j += 2) { - - if (isOffContentRight(valuePoints[j])) - break; - - if (isOffContentLeft(valuePoints[j]) || isOffContentTop(valuePoints[j + 1]) - || isOffContentBottom(valuePoints[j + 1])) - continue; - - BarEntry e = entries.get(j / 2); - - float[] vals = e.getVals(); - - // we still draw stacked bars, but there is one - // non-stacked - // in between - if (vals == null) { - - drawValue(e.getVal(), valuePoints[j], - valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset)); - - } else { - - float[] transformed = new float[vals.length * 2]; - int cnt = 0; - float add = e.getVal(); - - for (int k = 0; k < transformed.length; k += 2) { - - add -= vals[cnt]; - transformed[k + 1] = (vals[cnt] + add) * yyy; - cnt++; - } - - mTrans.pointValuesToPixel(transformed); - - for (int k = 0; k < transformed.length; k += 2) { - - drawValue(vals[k / 2], valuePoints[j], - transformed[k + 1] - + (vals[k / 2] >= 0 ? posOffset : negOffset)); - } - } - } - } - } - } + } protected float getPositiveYOffset(boolean drawAboveValueBar) @@ -471,28 +202,6 @@ protected float getNegativeYOffset(boolean drawAboveValueBar) .convertDpToPixel(5)); } - /** - * Draws a value at the specified x and y position. - * - * @param value - * @param xPos - * @param yPos - */ - private void drawValue(float val, float xPos, float yPos) { - - String value = mValueFormatter.getFormattedValue(val); - - if (mDrawUnitInChart) { - - mDrawCanvas.drawText(value + mUnit, xPos, yPos, - mValuePaint); - } else { - - mDrawCanvas.drawText(value, xPos, yPos, - mValuePaint); - } - } - /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the BarChart. @@ -573,67 +282,67 @@ public RectF getBarBounds(BarEntry e) { RectF bounds = new RectF(left, top, right, bottom); - mTrans.rectValueToPixel(bounds); + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); return bounds; } - /** - * sets the skew (default 0.3f), the skew indicates how much the 3D effect - * of the chart is turned to the right - * - * @param skew - */ - public void setSkew(float skew) { - this.mSkew = skew; - } - - /** - * returns the skew value that indicates how much the 3D effect is turned to - * the right - * - * @return - */ - public float getSkew() { - return mSkew; - } - - /** - * set the depth of the chart (default 0.3f), the depth indicates how much - * the 3D effect of the chart goes back - * - * @param depth - */ - public void setDepth(float depth) { - this.mDepth = depth; - } - - /** - * returhs the depth, which indicates how much the 3D effect goes back - * - * @return - */ - public float getDepth() { - return mDepth; - } - - /** - * if enabled, chart will be drawn in 3d - * - * @param enabled - */ - public void set3DEnabled(boolean enabled) { - this.m3DEnabled = enabled; - } - - /** - * returns true if 3d bars is enabled, false if not - * - * @return - */ - public boolean is3DEnabled() { - return m3DEnabled; - } +// /** +// * sets the skew (default 0.3f), the skew indicates how much the 3D effect +// * of the chart is turned to the right +// * +// * @param skew +// */ +// public void setSkew(float skew) { +// this.mSkew = skew; +// } +// +// /** +// * returns the skew value that indicates how much the 3D effect is turned to +// * the right +// * +// * @return +// */ +// public float getSkew() { +// return mSkew; +// } +// +// /** +// * set the depth of the chart (default 0.3f), the depth indicates how much +// * the 3D effect of the chart goes back +// * +// * @param depth +// */ +// public void setDepth(float depth) { +// this.mDepth = depth; +// } +// +// /** +// * returhs the depth, which indicates how much the 3D effect goes back +// * +// * @return +// */ +// public float getDepth() { +// return mDepth; +// } +// +// /** +// * if enabled, chart will be drawn in 3d +// * +// * @param enabled +// */ +// public void set3DEnabled(boolean enabled) { +// this.m3DEnabled = enabled; +// } +// +// /** +// * returns true if 3d bars is enabled, false if not +// * +// * @return +// */ +// public boolean is3DEnabled() { +// return m3DEnabled; +// } /** * set this to true to draw the highlightning arrow diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java new file mode 100644 index 0000000000..a3e7e94d6d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -0,0 +1,357 @@ + +package com.github.mikephil.charting.renderer; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; + + +public class BarChartRenderer extends DataRenderer { + + protected BarChart mChart; + + /** the rect object that is used for drawing the bar shadow */ + protected RectF mBarShadow = new RectF(); + + /** the rect object that is used for drawing the bars */ + protected RectF mBarRect = new RectF(); + + public BarChartRenderer(BarChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + this.mChart = chart; + + mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHighlightPaint.setStyle(Paint.Style.FILL); + mHighlightPaint.setColor(Color.rgb(0, 0, 0)); + // set alpha after color + mHighlightPaint.setAlpha(120); + } + + @Override + public void drawData(Canvas c) { + + BarData barData = mChart.getData(); + + for(int i = 0; i < barData.getDataSetCount(); i++) { + + BarDataSet set = barData.getDataSetByIndex(i); + + if(set.isVisible()) { + drawDataSet(c, set, i); + } + } + } + + private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + // the space between bar-groups + float space = mChart.getData().getGroupSpace(); + + boolean noStacks = dataSet.getStackSize() == 1 ? true : false; + + ArrayList entries = dataSet.getYVals(); + + // do the drawing + for (int j = 0; j < dataSet.getEntryCount() * mAnimator.getPhaseX(); j++) { + + BarEntry e = entries.get(j); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + j * (mChart.getData().getDataSetCount() - 1) + index + space * j + space / 2f; + float y = e.getVal(); + + // no stacks + if (noStacks) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + + // avoid drawing outofbounds values + if (!mViewPortHandler.isInBoundsRight(mBarRect.left)) + break; + + if (!mViewPortHandler.isInBoundsLeft(mBarRect.right)) + continue; + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + // Set the color for the currently drawn value. If the index + // is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j)); + c.drawRect(mBarRect, mRenderPaint); + + } else { // stacked bars + + float[] vals = e.getVals(); + + // we still draw stacked bars, but there could be one + // non-stacked + // in between + if (vals == null) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + mRenderPaint.setColor(dataSet.getColor(0)); + c.drawRect(mBarRect, mRenderPaint); + + } else { + + float all = e.getVal(); + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + // draw the stack + for (int k = 0; k < vals.length; k++) { + + all -= vals[k]; + + prepareBar(x, vals[k] + all, dataSet.getBarSpace(), trans); + + mRenderPaint.setColor(dataSet.getColor(k)); + c.drawRect(mBarRect, mRenderPaint); + } + } + + // avoid drawing outofbounds values + if (!mViewPortHandler.isInBoundsRight(mBarRect.left)) + break; + } + } + } + + + /** + * Prepares a bar for drawing on the specified x-index and y-position. Also + * prepares the shadow-bar if enabled. + * + * @param x the x-position + * @param y the y-position + * @param barspace the space between bars + */ + protected void prepareBar(float x, float y, float barspace, Transformer trans) { + + float spaceHalf = barspace / 2f; + float left = x + spaceHalf; + float right = x + 1f - spaceHalf; + float top = y >= 0 ? y : 0; + float bottom = y <= 0 ? y : 0; + + mBarRect.set(left, top, right, bottom); + + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + + // if a shadow is drawn, prepare it too + if (mChart.isDrawBarShadowEnabled()) { + mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, mViewPortHandler.contentBottom()); + } + } + + @Override + public void drawValues(Canvas c) { + // if values are drawn + if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleX()) { + + ArrayList dataSets = mChart.getData().getDataSets(); + + float posOffset = 0f; + float negOffset = 0f; + + // calculate the correct offset depending on the draw position of + // the value + posOffset = (mChart.isDrawValueAboveBarEnabled() ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, + "8") * 1.5f); + negOffset = (mChart.isDrawValueAboveBarEnabled() ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils + .convertDpToPixel(5)); + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + BarDataSet dataSet = dataSets.get(i); + + if(!dataSet.isDrawValuesEnabled()) + continue; + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + ArrayList entries = dataSet.getYVals(); + + float[] valuePoints = trans.generateTransformedValuesBarChart(entries, i, mChart.getData(), + mAnimator.getPhaseY()); + + // if only single values are drawn (sum) + if (!mChart.isDrawValuesForWholeStackEnabled()) { + + for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + break; + + if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + continue; + + float val = entries.get(j / 2).getVal(); + + drawValue(c, val, valuePoints[j], + valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset)); + } + + // if each value of a potential stack should be drawn + } else { + + for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + break; + + if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + continue; + + BarEntry e = entries.get(j / 2); + + float[] vals = e.getVals(); + + // we still draw stacked bars, but there is one + // non-stacked + // in between + if (vals == null) { + + drawValue(c, e.getVal(), valuePoints[j], + valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset)); + + } else { + + float[] transformed = new float[vals.length * 2]; + int cnt = 0; + float add = e.getVal(); + + for (int k = 0; k < transformed.length; k += 2) { + + add -= vals[cnt]; + transformed[k + 1] = (vals[cnt] + add) * mAnimator.getPhaseY(); + cnt++; + } + + trans.pointValuesToPixel(transformed); + + for (int k = 0; k < transformed.length; k += 2) { + + drawValue(c, vals[k / 2], valuePoints[j], + transformed[k + 1] + + (vals[k / 2] >= 0 ? posOffset : negOffset)); + } + } + } + } + } + } + } + + + /** + * Draws a value at the specified x and y position. + * + * @param value + * @param xPos + * @param yPos + */ + private void drawValue(Canvas c, float val, float xPos, float yPos) { + + String value = mChart.getValueFormatter().getFormattedValue(val); + c.drawText(value, xPos, yPos, + mValuePaint); + } + + @Override + public void drawExtras(Canvas c) { } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + int setCount = mChart.getData().getDataSetCount(); + + for (int i = 0; i < indices.length; i++) { + + Highlight h = indices[i]; + int index = h.getXIndex(); + + int dataSetIndex = h.getDataSetIndex(); + BarDataSet set = mChart.getData().getDataSetByIndex(dataSetIndex); + + if (set == null) + continue; + + Transformer trans = mChart.getTransformer(set.getAxisDependency()); + + mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setAlpha(set.getHighLightAlpha()); + + // check outofbounds + if (index < mChart.getData().getYValCount() && index >= 0 + && index < (mChart.getDeltaX() * mAnimator.getPhaseX()) / setCount) { + + Entry e = mChart.getEntryByDataSetIndex(index, dataSetIndex); + + if (e == null) + continue; + + float groupspace = mChart.getData().getGroupSpace(); + + // calculate the correct x-position + float x = index * setCount + dataSetIndex + groupspace / 2f + + groupspace * index; + float y = e.getVal(); + + prepareBar(x, y, set.getBarSpace(), trans); + + c.drawRect(mBarRect, mHighlightPaint); + + if (mChart.isDrawHighlightArrowEnabled()) { + + mHighlightPaint.setAlpha(255); + + // distance between highlight arrow and bar + float offsetY = mAnimator.getPhaseY() * 0.07f; + + Path arrow = new Path(); + arrow.moveTo(x + 0.5f, y + offsetY * 0.3f); + arrow.lineTo(x + 0.2f, y + offsetY); + arrow.lineTo(x + 0.8f, y + offsetY); + + trans.pathValueToPixel(arrow); + c.drawPath(arrow, mHighlightPaint); + } + } + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1bf104171d..3d717d5fb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -17,7 +17,7 @@ public class LineChartRenderer extends DataRenderer { - private LineChart mChart; + protected LineChart mChart; /** paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; @@ -37,12 +37,10 @@ public void drawData(Canvas c) { LineData lineData = mChart.getData(); - for (int i = 0; i < lineData.getDataSetCount(); i++) { - - LineDataSet ds = lineData.getDataSets().get(i); - - if (ds.isVisible()) - drawDataSet(c, ds); + for (LineDataSet set : lineData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); } } From 174bf4da9191c6ddf671ad6a6b5d009aea3ad1ae Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 10 Feb 2015 22:27:05 +0100 Subject: [PATCH 0063/1390] Worked on XAxisRenderer, worked on Scatter- and BarChart Renderer. --- .../mikephil/charting/charts/BarChart.java | 86 +------- .../charting/charts/BarLineChartBase.java | 8 +- .../charting/charts/ScatterChart.java | 177 ++-------------- .../charting/renderer/LineChartRenderer.java | 12 +- .../renderer/ScatterChartRenderer.java | 189 ++++++++++++++++++ .../charting/renderer/ViewPortHandler.java | 2 +- .../charting/renderer/XAxisRenderer.java | 18 +- .../renderer/XAxisRendererBarChart.java | 105 ++++++++++ .../github/mikephil/charting/utils/XAxis.java | 25 ++- 9 files changed, 364 insertions(+), 258 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 2f30568907..63e21eae6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.renderer.XAxisRendererBarChart; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; @@ -71,6 +72,8 @@ public BarChart(Context context, AttributeSet attrs, int defStyle) { @Override protected void init() { super.init(); + + mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); } @Override @@ -97,93 +100,12 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX += maxEntry * groupSpace; } - @Override - protected void drawHighlights() { - - } - @Override protected void drawDataSet(int index) { } - - @Override - protected void drawXLabels(float yPos) { - - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; - - int step = mData.getDataSetCount(); - - for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { - - position[0] = i * step + i * mData.getGroupSpace() - + mData.getGroupSpace() / 2f; - - // center the text - if (mXAxis.isCenterXLabelsEnabled()) - position[0] += (step / 2f); - - mTrans.pointValuesToPixel(position); - - if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { - - String label = mData.getXVals().get(i); - - if (mXAxis.isAvoidFirstLastClippingEnabled()) { - - // avoid clipping of the last - if (i == mData.getXValCount() - 1) { - float width = Utils.calcTextWidth(mXLabelPaint, label); - - if (width > getOffsetRight() * 2 && position[0] + width > getWidth()) - position[0] -= width / 2; - - // avoid clipping of the first - } else if (i == 0) { - - float width = Utils.calcTextWidth(mXLabelPaint, label); - position[0] += width / 2; - } - } - - mDrawCanvas.drawText(label, position[0], - yPos, - mXLabelPaint); - } - } - } - - @Override - protected void drawVerticalGrid() { - - if (!mDrawVerticalGrid || mData == null) - return; - - float[] position = new float[] { - 0f, 0f - }; - - // take into consideration that multiple DataSets increase mDeltaX - int step = mData.getDataSetCount(); - - for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { - - position[0] = i * step + i * mData.getGroupSpace(); - - mTrans.pointValuesToPixel(position); - - if (position[0] >= mOffsetLeft && position[0] <= getWidth()) { - - mDrawCanvas.drawLine(position[0], mOffsetTop, position[0], getHeight() - - mOffsetBottom, mGridPaint); - } - } - } - + @Override protected void drawValues() { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 36d5c70cb2..e7013f97ae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -154,6 +154,8 @@ protected void init() { mAxisRendererLeft = new YAxisRenderer(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); mAxisRendererRight = new YAxisRenderer(mViewPortHandler, mAxisRight, mRightAxisTransformer); + + mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); mListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); @@ -262,7 +264,7 @@ public void prepare() { mAxisRendererLeft.computeAxis(this); mAxisRendererRight.computeAxis(this); - mXAxisRenderer.computeAxis(mData.getXValAverageLength()); + mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); prepareLegend(); @@ -273,7 +275,7 @@ public void prepare() { * Sets up all the matrices that will be used for scaling the coordinates to * the display. Offset and Value-px. */ - private void prepareMatrix() { + protected void prepareMatrix() { mRightAxisTransformer.prepareMatrixValuePx(this, mDeltaX, mDeltaY); mLeftAxisTransformer.prepareMatrixValuePx(this, mDeltaX, mDeltaY); @@ -391,7 +393,7 @@ protected void calculateOffsets() { mLegend.setOffsetLeft(offsetLeft); } - mViewPortHandler.restrainViewPort(offsetLeft, offsetRight, offsetTop, offsetBottom); + mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom); prepareMatrix(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 417313dc50..973498b620 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -2,14 +2,10 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Path; import android.util.AttributeSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.ScatterDataSet; - -import java.util.ArrayList; +import com.github.mikephil.charting.renderer.ScatterChartRenderer; /** * The ScatterChart. Draws dots, triangles, squares and custom shapes into the @@ -37,18 +33,22 @@ public ScatterChart(Context context, AttributeSet attrs, int defStyle) { } @Override - protected void prepareContentRect() { - if (isEmpty()) { - super.prepareContentRect(); - } else { - - float offset = mData.getGreatestShapeSize() / 2f; - - mContentRect.set(mOffsetLeft - offset, - mOffsetTop, - getWidth() - mOffsetRight + offset, - getHeight() - mOffsetBottom); - } + protected void init() { + super.init(); + + mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); + } + + @Override + protected void calculateOffsets() { + super.calculateOffsets(); + + float offset = mData.getGreatestShapeSize() / 2f; + mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, + mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, + mViewPortHandler.offsetBottom()); + + prepareMatrix(); } @Override @@ -62,150 +62,11 @@ protected void calcMinMax(boolean fixedValues) { @Override protected void drawDataSet(int index) { - ScatterDataSet dataSet = mData.getDataSets().get(index); - ArrayList entries = dataSet.getYVals(); - - float shapeHalf = dataSet.getScatterShapeSize() / 2f; - - float[] valuePoints = mTrans.generateTransformedValuesLineScatter(entries, yyy); - - ScatterShape shape = dataSet.getScatterShape(); - - for (int j = 0; j < valuePoints.length * xxx; j += 2) { - - if (isOffContentRight(valuePoints[j])) - break; - - // make sure the lines don't do shitty things outside bounds - if (j != 0 && isOffContentLeft(valuePoints[j - 1]) - && isOffContentTop(valuePoints[j + 1]) - && isOffContentBottom(valuePoints[j + 1])) - continue; - - // Set the color for the currently drawn value. If the index is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j)); - - if (shape == ScatterShape.SQUARE) { - - mDrawCanvas.drawRect(valuePoints[j] - shapeHalf, - valuePoints[j + 1] - shapeHalf, valuePoints[j] - + shapeHalf, valuePoints[j + 1] - + shapeHalf, mRenderPaint); - - } else if (shape == ScatterShape.CIRCLE) { - - mDrawCanvas.drawCircle(valuePoints[j], valuePoints[j + 1], shapeHalf, - mRenderPaint); - - } else if (shape == ScatterShape.CROSS) { - - mDrawCanvas.drawLine(valuePoints[j] - shapeHalf, valuePoints[j + 1], - valuePoints[j] + shapeHalf, - valuePoints[j + 1], mRenderPaint); - mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1] - shapeHalf, - valuePoints[j], valuePoints[j + 1] - + shapeHalf, mRenderPaint); - - } else if (shape == ScatterShape.TRIANGLE) { - - // create a triangle path - Path tri = new Path(); - tri.moveTo(valuePoints[j], valuePoints[j + 1] - shapeHalf); - tri.lineTo(valuePoints[j] + shapeHalf, valuePoints[j + 1] + shapeHalf); - tri.lineTo(valuePoints[j] - shapeHalf, valuePoints[j + 1] + shapeHalf); - tri.close(); - - mDrawCanvas.drawPath(tri, mRenderPaint); - - } else if (shape == ScatterShape.CUSTOM) { - - Path customShape = dataSet.getCustomScatterShape(); - - if (customShape == null) - return; - - // transform the provided custom path - mTrans.pathValueToPixel(customShape); - mDrawCanvas.drawPath(customShape, mRenderPaint); - } - } } @Override protected void drawValues() { - // if values are drawn - if (mDrawYValues && mData.getYValCount() < mMaxVisibleCount * mTrans.getScaleX()) { - - ArrayList dataSets = mData - .getDataSets(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - ScatterDataSet dataSet = dataSets.get(i); - ArrayList entries = dataSet.getYVals(); - - float[] positions = mTrans.generateTransformedValuesLineScatter(entries, yyy); - - float shapeSize = dataSet.getScatterShapeSize(); - - for (int j = 0; j < positions.length * xxx; j += 2) { - - if (isOffContentRight(positions[j])) - break; - - if (isOffContentLeft(positions[j]) || isOffContentTop(positions[j + 1]) - || isOffContentBottom(positions[j + 1])) - continue; - - float val = entries.get(j / 2).getVal(); - - if (mDrawUnitInChart) { - - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(val) + mUnit, - positions[j], - positions[j + 1] - shapeSize, mValuePaint); - } else { - - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(val), positions[j], - positions[j + 1] - shapeSize, - mValuePaint); - } - } - } - } - } - - @Override - protected void drawHighlights() { - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - ScatterDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i] - .getDataSetIndex()); - - if (set == null) - continue; - - mHighlightPaint.setColor(set.getHighLightColor()); - - int xIndex = mIndicesToHightlight[i].getXIndex(); // get the - // x-position - - if (xIndex > mDeltaX * xxx) - continue; - - float y = set.getYValForXIndex(xIndex) * yyy; // get the - // y-position - - float[] pts = new float[] { - xIndex, mYChartMax, xIndex, mYChartMin, 0, y, mDeltaX, y - }; - - mTrans.pointValuesToPixel(pts); - // draw the highlight lines - mDrawCanvas.drawLines(pts, mHighlightPaint); - } + } @Override @@ -214,7 +75,7 @@ protected void drawAdditional() { } /** - * Returns all possible predefined scattershapes. + * Returns all possible predefined ScatterShapes (excluding CUSTOM). * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 3d717d5fb6..b98e123cbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -38,7 +38,7 @@ public void drawData(Canvas c) { LineData lineData = mChart.getData(); for (LineDataSet set : lineData.getDataSets()) { - + if (set.isVisible()) drawDataSet(c, set); } @@ -413,16 +413,18 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mHighlightPaint.setColor(set.getHighLightColor()); int xIndex = indices[i].getXIndex(); // get the - // x-position + // x-position if (xIndex > mChart.getDeltaX() * mAnimator.getPhaseX()) continue; - float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get the - // y-position + float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get + // the + // y-position float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, mChart.getDeltaX(), y + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, + mChart.getDeltaX(), y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java new file mode 100644 index 0000000000..704ae7d092 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -0,0 +1,189 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Path; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.utils.Highlight; + +import java.util.ArrayList; + +public class ScatterChartRenderer extends DataRenderer { + + protected ScatterChart mChart; + + public ScatterChartRenderer(ScatterChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + mChart = chart; + } + + @Override + public void drawData(Canvas c) { + + ScatterData scatterData = mChart.getData(); + + for (ScatterDataSet set : scatterData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); + } + } + + protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { + + ArrayList entries = dataSet.getYVals(); + + float shapeHalf = dataSet.getScatterShapeSize() / 2f; + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + float[] valuePoints = trans.generateTransformedValuesLineScatter(entries, + mAnimator.getPhaseY()); + + ScatterShape shape = dataSet.getScatterShape(); + + for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + break; + + // make sure the lines don't do shitty things outside bounds + if (j != 0 && !mViewPortHandler.isInBoundsLeft(valuePoints[j - 1]) + && !mViewPortHandler.isInBoundsY(valuePoints[j + 1])) + continue; + + // Set the color for the currently drawn value. If the index is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j)); + + if (shape == ScatterShape.SQUARE) { + + c.drawRect(valuePoints[j] - shapeHalf, + valuePoints[j + 1] - shapeHalf, valuePoints[j] + + shapeHalf, valuePoints[j + 1] + + shapeHalf, mRenderPaint); + + } else if (shape == ScatterShape.CIRCLE) { + + c.drawCircle(valuePoints[j], valuePoints[j + 1], shapeHalf, + mRenderPaint); + + } else if (shape == ScatterShape.CROSS) { + + c.drawLine(valuePoints[j] - shapeHalf, valuePoints[j + 1], + valuePoints[j] + shapeHalf, + valuePoints[j + 1], mRenderPaint); + c.drawLine(valuePoints[j], valuePoints[j + 1] - shapeHalf, + valuePoints[j], valuePoints[j + 1] + + shapeHalf, mRenderPaint); + + } else if (shape == ScatterShape.TRIANGLE) { + + // create a triangle path + Path tri = new Path(); + tri.moveTo(valuePoints[j], valuePoints[j + 1] - shapeHalf); + tri.lineTo(valuePoints[j] + shapeHalf, valuePoints[j + 1] + shapeHalf); + tri.lineTo(valuePoints[j] - shapeHalf, valuePoints[j + 1] + shapeHalf); + tri.close(); + + c.drawPath(tri, mRenderPaint); + + } else if (shape == ScatterShape.CUSTOM) { + + Path customShape = dataSet.getCustomScatterShape(); + + if (customShape == null) + return; + + // transform the provided custom path + trans.pathValueToPixel(customShape); + c.drawPath(customShape, mRenderPaint); + } + } + } + + @Override + public void drawValues(Canvas c) { + + // if values are drawn + if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleX()) { + + ArrayList dataSets = mChart.getData().getDataSets(); + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + ScatterDataSet dataSet = dataSets.get(i); + ArrayList entries = dataSet.getYVals(); + + float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) + .generateTransformedValuesLineScatter(entries, + mAnimator.getPhaseY()); + + float shapeSize = dataSet.getScatterShapeSize(); + + for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsRight(positions[j])) + break; + + // make sure the lines don't do shitty things outside bounds + if (j != 0 && !mViewPortHandler.isInBoundsLeft(positions[j - 1]) + && !mViewPortHandler.isInBoundsY(positions[j + 1])) + continue; + + float val = entries.get(j / 2).getVal(); + + c.drawText(mChart.getValueFormatter().getFormattedValue(val), positions[j], + positions[j + 1] - shapeSize, + mValuePaint); + } + } + } + } + + @Override + public void drawExtras(Canvas c) { + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + for (int i = 0; i < indices.length; i++) { + + ScatterDataSet set = mChart.getData().getDataSetByIndex(indices[i] + .getDataSetIndex()); + + if (set == null) + continue; + + mHighlightPaint.setColor(set.getHighLightColor()); + + int xIndex = indices[i].getXIndex(); // get the + // x-position + + if (xIndex > mChart.getDeltaX() * mAnimator.getPhaseX()) + continue; + + float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get + // the + // y-position + + float[] pts = new float[] { + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, + mChart.getDeltaX(), y + }; + + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + // draw the highlight lines + c.drawLines(pts, mHighlightPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index ae1e488d4c..4272f96f65 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -43,7 +43,7 @@ public ViewPortHandler(float width, float height) { mChartWidth = width; } - public void restrainViewPort(float offsetLeft, float offsetRight, float offsetTop, float offsetBottom) { + public void restrainViewPort(float offsetLeft, float offsetTop, float offsetRight, float offsetBottom) { mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight - offsetBottom); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index ee9d7f01b7..09a9ada125 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,11 +6,12 @@ import android.graphics.Paint; import android.graphics.Paint.Align; -import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.XAxis; import com.github.mikephil.charting.utils.XAxis.XLabelPosition; +import java.util.ArrayList; + public class XAxisRenderer extends AxisRenderer { /** paint for the x-label values */ @@ -29,7 +30,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mXLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } - public void computeAxis(float xValAverageLength) { + public void computeAxis(float xValAverageLength, ArrayList xValues) { StringBuffer a = new StringBuffer(); @@ -42,6 +43,7 @@ public void computeAxis(float xValAverageLength) { mXAxis.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); mXAxis.mLabelHeight = Utils.calcTextHeight(mXLabelPaint, "Q"); + mXAxis.setValues(xValues); } @Override @@ -81,14 +83,14 @@ public void renderAxis(Canvas c) { * * @param yPos */ - private void drawLabels(Canvas c, float yPos) { + protected void drawLabels(Canvas c, float yPos) { // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { 0f, 0f }; - for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { position[0] = i; @@ -98,14 +100,14 @@ private void drawLabels(Canvas c, float yPos) { mTrans.pointValuesToPixel(position); - if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight) { + if (mViewPortHandler.isInBoundsX(position[0])) { - String label = mData.getXVals().get(i); + String label = mXAxis.getValues().get(i); if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mData.getXValCount() - 1) { + if (i == mXAxis.getValues().size() - 1) { float width = Utils.calcTextWidth(mXLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 @@ -139,7 +141,7 @@ public void renderGridLines(Canvas c) { mGridPaint.setColor(mXAxis.getGridColor()); - for (int i = 0; i < mData.getXValCount(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { position[0] = i; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java new file mode 100644 index 0000000000..5fd754ca8f --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -0,0 +1,105 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.XAxis; + +public class XAxisRendererBarChart extends XAxisRenderer { + + private BarChart mChart; + + public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, + BarChart chart) { + super(viewPortHandler, xAxis, trans); + + this.mChart = chart; + } + + /** + * draws the x-labels on the specified y-position + * + * @param yPos + */ + @Override + protected void drawLabels(Canvas c, float yPos) { + + // pre allocate to save performance (dont allocate in loop) + float[] position = new float[] { + 0f, 0f + }; + + BarData bd = mChart.getData(); + int step = bd.getDataSetCount(); + + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + + position[0] = i * step + i * bd.getGroupSpace() + + bd.getGroupSpace() / 2f; + + // center the text + if (mXAxis.isCenterXLabelsEnabled()) + position[0] += (step / 2f); + + mTrans.pointValuesToPixel(position); + + if (mViewPortHandler.isInBoundsX(position[0])) { + + String label = mXAxis.getValues().get(i); + + if (mXAxis.isAvoidFirstLastClippingEnabled()) { + + // avoid clipping of the last + if (i == mXAxis.getValues().size() - 1) { + float width = Utils.calcTextWidth(mXLabelPaint, label); + + if (width > mViewPortHandler.offsetRight() * 2 + && position[0] + width > mViewPortHandler.getChartWidth()) + position[0] -= width / 2; + + // avoid clipping of the first + } else if (i == 0) { + + float width = Utils.calcTextWidth(mXLabelPaint, label); + position[0] += width / 2; + } + } + + c.drawText(label, position[0], + yPos, + mXLabelPaint); + } + } + } + + @Override + public void renderGridLines(Canvas c) { + + if (!mXAxis.isDrawGridLinesEnabled()) + return; + + float[] position = new float[] { + 0f, 0f + }; + + BarData bd = mChart.getData(); + // take into consideration that multiple DataSets increase mDeltaX + int step = bd.getDataSetCount(); + + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + + position[0] = i * step + i * bd.getGroupSpace(); + + mTrans.pointValuesToPixel(position); + + if (mViewPortHandler.isInBoundsX(position[0])) { + + c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], + mViewPortHandler.contentBottom(), mGridPaint); + } + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java index d723296a11..4eb33d35c5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.utils; +import java.util.ArrayList; + /** * Class representing the x-axis labels settings. Only use the setter methods to * modify it. Do not access public variables directly. Be aware that not all @@ -10,6 +12,9 @@ */ public class XAxis extends AxisBase { + /** the arraylist containing all the x-axis labels */ + protected ArrayList mValues = new ArrayList(); + /** * width of the x-axis labels in pixels - this is calculated by the * calcTextWidth() method of the utils @@ -34,7 +39,7 @@ public class XAxis extends AxisBase { * 0 DRAW, else dont draw. */ public int mXAxisLabelModulus = 1; - + /** * the modulus that indicates if a value at a specified index in an * array(list) for the y-axis-labels is drawn or not. If index % modulus == @@ -159,4 +164,22 @@ public void setAvoidFirstLastClipping(boolean enabled) { public boolean isAvoidFirstLastClippingEnabled() { return mAvoidFirstLastClipping; } + + /** + * Sets the labels for this axis. + * + * @param values + */ + public void setValues(ArrayList values) { + mValues = values; + } + + /** + * Returns the labels for this axis. + * + * @return + */ + public ArrayList getValues() { + return mValues; + } } From 442585756e9d55cc24699a7a1c405485c78aa8c0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Feb 2015 00:04:20 +0100 Subject: [PATCH 0064/1390] Implemented CandleStickChartRenderer. --- .../charting/charts/CandleStickChart.java | 150 +------------- .../renderer/CandleStickChartRenderer.java | 196 ++++++++++++++++++ 2 files changed, 205 insertions(+), 141 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 2ac4abb980..472581dd38 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -2,14 +2,10 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Paint; import android.util.AttributeSet; import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.CandleDataSet; -import com.github.mikephil.charting.data.CandleEntry; - -import java.util.ArrayList; +import com.github.mikephil.charting.renderer.CandleStickChartRenderer; /** * Financial chart type that draws candle-sticks. @@ -29,6 +25,13 @@ public CandleStickChart(Context context, AttributeSet attrs) { public CandleStickChart(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } + + @Override + protected void init() { + super.init(); + + mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); + } @Override protected void calcMinMax(boolean fixedValues) { @@ -41,98 +44,7 @@ protected void calcMinMax(boolean fixedValues) { @Override protected void drawDataSet(int index) { - // pre allocate - float[] shadowPoints = new float[4]; - float[] bodyPoints = new float[4]; - - CandleDataSet dataSet = mData.getDataSets().get(index); - ArrayList entries = dataSet.getYVals(); - - mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); - - for (int j = 0; j < entries.size() * xxx; j++) { - - // get the color that is specified for this position from - // the DataSet, this will reuse colors, if the index is out - // of bounds - mRenderPaint.setColor(dataSet.getColor(j)); - - // get the entry - CandleEntry e = entries.get(j); - - // transform the entries values for shadow and body - transformShadow(shadowPoints, e); - transformBody(bodyPoints, e, dataSet.getBodySpace()); - - float xShadow = shadowPoints[0]; - float leftBody = bodyPoints[0]; - float rightBody = bodyPoints[2]; - - float high = shadowPoints[1]; - float low = shadowPoints[3]; - - float open = bodyPoints[1]; - float close = bodyPoints[3]; - - if (isOffContentRight(leftBody)) - break; - - // make sure the lines don't do shitty things outside bounds - if (isOffContentLeft(rightBody) - && isOffContentTop(low) - && isOffContentBottom(high)) - continue; - - // draw the shadow - mDrawCanvas.drawLine(xShadow, low, xShadow, high, mRenderPaint); - - // decide weather the body is hollow or filled - if (open > close) { - - mRenderPaint.setStyle(Paint.Style.FILL); - // draw the body - mDrawCanvas.drawRect(leftBody, close, rightBody, open, mRenderPaint); - - } else { - - mRenderPaint.setStyle(Paint.Style.STROKE); - // draw the body - mDrawCanvas.drawRect(leftBody, open, rightBody, close, mRenderPaint); - } - } - } - - /** - * Transforms the values of an entry in order to draw the candle-body. - * - * @param bodyPoints - * @param e - * @param bodySpace - */ - private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace) { - - bodyPoints[0] = e.getXIndex() + bodySpace; - bodyPoints[1] = e.getClose() * yyy; - bodyPoints[2] = e.getXIndex() + (1f - bodySpace); - bodyPoints[3] = e.getOpen() * yyy; - - mTrans.pointValuesToPixel(bodyPoints); - } - - /** - * Transforms the values of an entry in order to draw the candle-shadow. - * - * @param shadowPoints - * @param e - */ - private void transformShadow(float[] shadowPoints, CandleEntry e) { - - shadowPoints[0] = e.getXIndex() + 0.5f; - shadowPoints[1] = e.getHigh() * yyy; - shadowPoints[2] = e.getXIndex() + 0.5f; - shadowPoints[3] = e.getLow() * yyy; - - mTrans.pointValuesToPixel(shadowPoints); + } @Override @@ -146,48 +58,4 @@ protected void drawAdditional() { // TODO Auto-generated method stub } - - @Override - protected void drawHighlights() { - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - int xIndex = mIndicesToHightlight[i].getXIndex(); // get the - // x-position - - CandleDataSet set = mData.getDataSetByIndex(mIndicesToHightlight[i].getDataSetIndex()); - - if (set == null) - continue; - - mHighlightPaint.setColor(set.getHighLightColor()); - - CandleEntry e = set.getEntryForXIndex(xIndex); - - if (e == null) - continue; - - float low = e.getLow() * yyy; - float high = e.getHigh() * yyy; - - float[] vertPts = new float[] { - xIndex, mYChartMax, xIndex, mYChartMin, xIndex + 1f, mYChartMax, xIndex + 1f, - mYChartMin - }; - - float[] horPts = new float[] { - 0, low, mDeltaX, low, 0, high, mDeltaX, high - }; - - mTrans.pointValuesToPixel(vertPts); - mTrans.pointValuesToPixel(horPts); - - // draw the vertical highlight lines - mDrawCanvas.drawLines(vertPts, mHighlightPaint); - - // draw the horizontal highlight lines - mDrawCanvas.drawLines(horPts, mHighlightPaint); - } - } - } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java new file mode 100644 index 0000000000..429066ceff --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -0,0 +1,196 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.CandleStickChart; +import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.data.CandleDataSet; +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.utils.Highlight; + +import java.util.ArrayList; + +public class CandleStickChartRenderer extends DataRenderer { + + protected CandleStickChart mChart; + + public CandleStickChartRenderer(CandleStickChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + mChart = chart; + } + + @Override + public void drawData(Canvas c) { + + CandleData candleData = mChart.getData(); + + for (CandleDataSet set : candleData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); + } + } + + protected void drawDataSet(Canvas c, CandleDataSet dataSet) { + + // pre allocate + float[] shadowPoints = new float[4]; + float[] bodyPoints = new float[4]; + + ArrayList entries = dataSet.getYVals(); + + mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); + + for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { + + // get the color that is specified for this position from + // the DataSet, this will reuse colors, if the index is out + // of bounds + mRenderPaint.setColor(dataSet.getColor(j)); + + // get the entry + CandleEntry e = entries.get(j); + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + // transform the entries values for shadow and body + transformShadow(shadowPoints, e, trans); + transformBody(bodyPoints, e, dataSet.getBodySpace(), trans); + + float xShadow = shadowPoints[0]; + float leftBody = bodyPoints[0]; + float rightBody = bodyPoints[2]; + + float high = shadowPoints[1]; + float low = shadowPoints[3]; + + float open = bodyPoints[1]; + float close = bodyPoints[3]; + + if (!mViewPortHandler.isInBoundsRight(leftBody)) + break; + + // make sure the lines don't do shitty things outside + // bounds + if (j != 0 && !mViewPortHandler.isInBoundsLeft(rightBody) + && !mViewPortHandler.isInBoundsTop(low) + && !mViewPortHandler.isInBoundsBottom(high)) + continue; + + // draw the shadow + c.drawLine(xShadow, low, xShadow, high, mRenderPaint); + + // decide weather the body is hollow or filled + if (open > close) { + + mRenderPaint.setStyle(Paint.Style.FILL); + // draw the body + c.drawRect(leftBody, close, rightBody, open, mRenderPaint); + + } else { + + mRenderPaint.setStyle(Paint.Style.STROKE); + // draw the body + c.drawRect(leftBody, open, rightBody, close, mRenderPaint); + } + } + } + + /** + * Transforms the values of an entry in order to draw the candle-body. + * + * @param bodyPoints + * @param e + * @param bodySpace + */ + private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace, Transformer trans) { + + float phase = mAnimator.getPhaseY(); + + bodyPoints[0] = e.getXIndex() + bodySpace; + bodyPoints[1] = e.getClose() * phase; + bodyPoints[2] = e.getXIndex() + (1f - bodySpace); + bodyPoints[3] = e.getOpen() * phase; + + trans.pointValuesToPixel(bodyPoints); + } + + /** + * Transforms the values of an entry in order to draw the candle-shadow. + * + * @param shadowPoints + * @param e + */ + private void transformShadow(float[] shadowPoints, CandleEntry e, Transformer trans) { + + float phase = mAnimator.getPhaseY(); + + shadowPoints[0] = e.getXIndex() + 0.5f; + shadowPoints[1] = e.getHigh() * phase; + shadowPoints[2] = e.getXIndex() + 0.5f; + shadowPoints[3] = e.getLow() * phase; + + trans.pointValuesToPixel(shadowPoints); + } + + @Override + public void drawValues(Canvas c) { + // TODO Auto-generated method stub + + } + + @Override + public void drawExtras(Canvas c) { + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + for (int i = 0; i < indices.length; i++) { + + int xIndex = indices[i].getXIndex(); // get the + // x-position + + CandleDataSet set = mChart.getData().getDataSetByIndex(indices[i].getDataSetIndex()); + + if (set == null) + continue; + + mHighlightPaint.setColor(set.getHighLightColor()); + + CandleEntry e = set.getEntryForXIndex(xIndex); + + if (e == null) + continue; + + float low = e.getLow() * mAnimator.getPhaseY(); + float high = e.getHigh() * mAnimator.getPhaseY(); + + float min = mChart.getYChartMin(); + float max = mChart.getYChartMax(); + + float[] vertPts = new float[] { + xIndex, max, xIndex, min, xIndex + 1f, max, xIndex + 1f, + min + }; + + float[] horPts = new float[] { + 0, low, mChart.getDeltaX(), low, 0, high, mChart.getDeltaX(), high + }; + + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(vertPts); + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(horPts); + + // draw the vertical highlight lines + c.drawLines(vertPts, mHighlightPaint); + + // draw the horizontal highlight lines + c.drawLines(horPts, mHighlightPaint); + } + } + +} From 7c512cd7d456fdf3151e3d51bc9f152eec8eb7ef Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Feb 2015 00:17:39 +0100 Subject: [PATCH 0065/1390] Did some work on Pie- and RadarChart. --- .../mikephil/charting/charts/Chart.java | 17 ++---- .../mikephil/charting/charts/PieChart.java | 27 +++++++-- .../charting/charts/PieRadarChartBase.java | 53 +++++++++-------- .../mikephil/charting/charts/RadarChart.java | 58 +++++++++---------- 4 files changed, 85 insertions(+), 70 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 4374073bd6..3b18d02e33 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -217,12 +217,6 @@ protected void init() { // initialize the utils Utils.init(getContext().getResources()); - // do screen density conversions - mOffsetBottom = (int) Utils.convertDpToPixel(mOffsetBottom); - mOffsetLeft = (int) Utils.convertDpToPixel(mOffsetLeft); - mOffsetRight = (int) Utils.convertDpToPixel(mOffsetRight); - mOffsetTop = (int) Utils.convertDpToPixel(mOffsetTop); - mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRenderPaint.setStyle(Style.FILL); @@ -1656,10 +1650,10 @@ public void setPaint(Paint p, int which) { mYLabelPaint = p; break; case PAINT_HIGHLIGHT: - mHighlightPaint = p; +// mHighlightPaint = p; break; case PAINT_LIMIT_LINE: - mLimitLinePaint = p; +// mLimitLinePaint = p; break; } } @@ -1687,9 +1681,9 @@ public Paint getPaint(int which) { case PAINT_YLABEL: return mYLabelPaint; case PAINT_HIGHLIGHT: - return mHighlightPaint; +// return mHighlightPaint; case PAINT_LIMIT_LINE: - return mLimitLinePaint; +// return mLimitLinePaint; } return null; @@ -2090,8 +2084,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { prepareContentRect(); - for (int i = 0; i < getChildCount(); i++) - { + for (int i = 0; i < getChildCount(); i++) { getChildAt(i).layout(left, top, right, bottom); } // diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index b26dd64a2e..d7808c3144 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -147,11 +147,11 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } - + @Override - protected void prepareContentRect() { - super.prepareContentRect(); - + protected void calculateOffsets() { + super.calculateOffsets(); + // prevent nullpointer when no data set if (mDataNotSet) return; @@ -167,6 +167,25 @@ protected void prepareContentRect() { c.x + boxSize, c.y + boxSize); } +// @Override +// protected void prepareContentRect() { +// super.prepareContentRect(); +// +// // prevent nullpointer when no data set +// if (mDataNotSet) +// return; +// +// float diameter = getDiameter(); +// float boxSize = diameter / 2f; +// +// PointF c = getCenterOffsets(); +// +// // create the circle box that will contain the pie-chart (the bounds of +// // the pie-chart) +// mCircleBox.set(c.x - boxSize, c.y - boxSize, +// c.x + boxSize, c.y + boxSize); +// } + @Override protected void calcMinMax(boolean fixedValues) { super.calcMinMax(fixedValues); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 17fb1ec84a..44f6aac574 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -2,9 +2,9 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Matrix; import android.graphics.Paint.Align; import android.graphics.PointF; +import android.graphics.RectF; import android.util.AttributeSet; import android.view.MotionEvent; @@ -103,7 +103,8 @@ protected void calculateOffsets() { float legendWidth = getFullLegendWidth() + spacing; - float legendHeight = mLegend.getFullHeight(mLegendLabelPaint) + mOffsetTop; + float legendHeight = mLegend.getFullHeight(mLegendLabelPaint);// + + // mOffsetTop; PointF c = getCenter(); @@ -148,10 +149,12 @@ protected void calculateOffsets() { mLegend.setOffsetLeft(min); } - mOffsetLeft = Math.max(min, getRequiredBaseOffset()); - mOffsetTop = Math.max(min, legendTop); - mOffsetRight = Math.max(min, legendRight); - mOffsetBottom = Math.max(min, Math.max(getRequiredBaseOffset(), legendBottom)); + float offsetLeft = Math.max(min, getRequiredBaseOffset()); + float offsetTop = Math.max(min, legendTop); + float offsetRight = Math.max(min, legendRight); + float offsetBottom = Math.max(min, Math.max(getRequiredBaseOffset(), legendBottom)); + + mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom); applyCalculatedOffsets(); } @@ -166,21 +169,23 @@ protected void drawAdditional() { */ protected void applyCalculatedOffsets() { - prepareContentRect(); - - float scaleX = (float) ((getWidth() - mOffsetLeft - mOffsetRight) / mDeltaX); - float scaleY = (float) ((getHeight() - mOffsetBottom - mOffsetTop) / mDeltaY); - - Matrix val = new Matrix(); - val.postTranslate(0, -mYChartMin); - val.postScale(scaleX, -scaleY); - - mTrans.getValueMatrix().set(val); - - Matrix offset = new Matrix(); - offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); - - mTrans.getOffsetMatrix().set(offset); + // prepareContentRect(); + // + // float scaleX = (float) ((getWidth() - mOffsetLeft - mOffsetRight) / + // mDeltaX); + // float scaleY = (float) ((getHeight() - mOffsetBottom - mOffsetTop) / + // mDeltaY); + // + // Matrix val = new Matrix(); + // val.postTranslate(0, -mYChartMin); + // val.postScale(scaleX, -scaleY); + // + // mTrans.getValueMatrix().set(val); + // + // Matrix offset = new Matrix(); + // offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); + // + // mTrans.getOffsetMatrix().set(offset); } /** the angle where the dragging started */ @@ -358,10 +363,8 @@ public boolean isRotationEnabled() { * @return */ public float getDiameter() { - if (mContentRect == null) - return 0; - else - return Math.min(mContentRect.width(), mContentRect.height()); + RectF content = mViewPortHandler.getContentRect(); + return Math.min(content.width(), content.height()); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index f6c6b06015..02a232d43c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -7,6 +7,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; +import android.graphics.RectF; import android.util.AttributeSet; import com.github.mikephil.charting.data.Entry; @@ -55,10 +56,10 @@ public class RadarChart extends PieRadarChartBase { private boolean mDrawWeb = true; /** the object reprsenting the y-axis labels */ - private YAxis mYLabels = new YAxis(); + private YAxis mYAxis = new YAxis(); /** the object representing the x-axis labels */ - private XAxis mXLabels = new XAxis(); + private XAxis mXAxis = new XAxis(); public RadarChart(Context context) { super(context); @@ -124,7 +125,7 @@ protected void onDraw(Canvas canvas) { drawLimitLines(); -// drawData(); + // drawData(); drawAdditional(); @@ -176,7 +177,7 @@ private void drawWeb() { mWebPaint.setColor(mWebColorInner); mWebPaint.setAlpha(mWebAlpha); - int labelCount = mYLabels.mEntryCount; + int labelCount = mYAxis.mEntryCount; for (int j = 0; j < labelCount; j++) { @@ -292,7 +293,7 @@ private void drawLimitLines() { */ private void prepareYLabels() { - int labelCount = mYLabels.getLabelCount(); + int labelCount = mYAxis.getLabelCount(); double max = mData.getYMax() > 0 ? mData.getYMax() : 1.0; double range = max - mYChartMin; @@ -316,7 +317,7 @@ private void prepareYLabels() { ++n; } - mYLabels.mEntryCount = n; + mYAxis.mEntryCount = n; mYChartMax = (float) interval * n; @@ -332,18 +333,18 @@ private void drawYLabels() { if (!mDrawYLabels) return; - mYLabelPaint.setTypeface(mYLabels.getTypeface()); - mYLabelPaint.setTextSize(mYLabels.getTextSize()); - mYLabelPaint.setColor(mYLabels.getTextColor()); + mYLabelPaint.setTypeface(mYAxis.getTypeface()); + mYLabelPaint.setTextSize(mYAxis.getTextSize()); + mYLabelPaint.setColor(mYAxis.getTextColor()); PointF c = getCenterOffsets(); float factor = getFactor(); - int labelCount = mYLabels.mEntryCount; + int labelCount = mYAxis.mEntryCount; for (int j = 0; j < labelCount; j++) { - if (j == labelCount - 1 && mYLabels.isDrawTopYLabelEntryEnabled() == false) + if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) break; float r = ((mYChartMax / labelCount) * j) * factor; @@ -352,10 +353,10 @@ private void drawYLabels() { float val = r / factor; - String label = Utils.formatNumber(val, mYLabels.mDecimals, - mYLabels.isSeparateThousandsEnabled()); + String label = Utils.formatNumber(val, mYAxis.mDecimals, + mYAxis.isSeparateThousandsEnabled()); - if (mYLabels.isDrawUnitsInYLabelEnabled()) + if (mYAxis.isDrawUnitsInYLabelEnabled()) mDrawCanvas.drawText(label + mUnit, p.x + 10, p.y - 5, mYLabelPaint); else { mDrawCanvas.drawText(label, p.x + 10, p.y - 5, mYLabelPaint); @@ -376,8 +377,8 @@ private void prepareXLabels() { a.append("h"); } - mXLabels.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); - mXLabels.mLabelHeight = Utils.calcTextWidth(mXLabelPaint, "Q"); + mXAxis.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); + mXAxis.mLabelHeight = Utils.calcTextWidth(mXLabelPaint, "Q"); } /** @@ -388,9 +389,9 @@ private void drawXLabels() { if (!mDrawXLabels) return; - mXLabelPaint.setTypeface(mXLabels.getTypeface()); - mXLabelPaint.setTextSize(mXLabels.getTextSize()); - mXLabelPaint.setColor(mXLabels.getTextColor()); + mXLabelPaint.setTypeface(mXAxis.getTypeface()); + mXLabelPaint.setTextSize(mXAxis.getTextSize()); + mXLabelPaint.setColor(mXAxis.getTextColor()); float sliceangle = getSliceAngle(); @@ -406,9 +407,9 @@ private void drawXLabels() { float angle = (sliceangle * i + mRotationAngle) % 360f; - PointF p = getPosition(c, mYChartMax * factor + mXLabels.mLabelWidth / 2f, angle); + PointF p = getPosition(c, mYChartMax * factor + mXAxis.mLabelWidth / 2f, angle); - mDrawCanvas.drawText(text, p.x, p.y + mXLabels.mLabelHeight / 2f, mXLabelPaint); + mDrawCanvas.drawText(text, p.x, p.y + mXAxis.mLabelHeight / 2f, mXLabelPaint); } } @@ -496,7 +497,8 @@ protected void drawHighlights() { * @return */ public float getFactor() { - return (float) Math.min(mContentRect.width() / 2, mContentRect.height() / 2) + RectF content = mViewPortHandler.getContentRect(); + return (float) Math.min(content.width() / 2, content.height() / 2) / mYChartMax; } @@ -531,7 +533,7 @@ public int getIndexForAngle(float angle) { * @return */ public YAxis getYLabels() { - return mYLabels; + return mYAxis; } /** @@ -540,7 +542,7 @@ public YAxis getYLabels() { * @return */ public XAxis getXLabels() { - return mXLabels; + return mXAxis; } /** @@ -647,15 +649,13 @@ protected float getRequiredBottomOffset() { @Override protected float getRequiredBaseOffset() { - return mXLabels.mLabelWidth; + return mXAxis.mLabelWidth; } @Override public float getRadius() { - if (mContentRect == null) - return 0; - else - return Math.min(mContentRect.width() / 2f, mContentRect.height() / 2f); + RectF content = mViewPortHandler.getContentRect(); + return Math.min(content.width() / 2f, content.height() / 2f); } @Override From 8d59446596a7aa50c9f8f36f0bcf075a02518ff2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Feb 2015 11:32:16 +0100 Subject: [PATCH 0066/1390] Some changes to the package structure, implemented PieChart renderer. --- .../mikephil/charting/charts/BarChart.java | 16 - .../charting/charts/BarLineChartBase.java | 18 +- .../charting/charts/CandleStickChart.java | 18 - .../mikephil/charting/charts/Chart.java | 59 +-- .../charting/charts/HorizontalBarChart.java | 4 +- .../mikephil/charting/charts/LineChart.java | 15 - .../mikephil/charting/charts/PieChart.java | 404 +++--------------- .../charting/charts/PieRadarChartBase.java | 7 +- .../mikephil/charting/charts/RadarChart.java | 6 +- .../charting/charts/ScatterChart.java | 15 - .../{utils => components}/AxisBase.java | 4 +- .../{utils => components}/Legend.java | 4 +- .../{utils => components}/LimitLine.java | 4 +- .../{utils => components}/MarkerView.java | 2 +- .../charting/{utils => components}/XAxis.java | 2 +- .../charting/{utils => components}/YAxis.java | 5 +- .../mikephil/charting/data/ChartData.java | 17 + .../mikephil/charting/data/DataSet.java | 4 +- .../mikephil/charting/data/PieDataSet.java | 1 - .../charting/renderer/AxisRenderer.java | 2 + .../charting/renderer/BarChartRenderer.java | 1 + .../renderer/CandleStickChartRenderer.java | 1 + .../charting/renderer/DataRenderer.java | 8 + .../charting/renderer/LineChartRenderer.java | 1 + .../charting/renderer/PieChartRenderer.java | 324 ++++++++++++++ .../mikephil/charting/renderer/Renderer.java | 4 +- .../renderer/ScatterChartRenderer.java | 1 + .../charting/renderer/XAxisRenderer.java | 5 +- .../renderer/XAxisRendererBarChart.java | 3 +- .../charting/renderer/YAxisRenderer.java | 11 +- .../HorizontalBarChartTransformer.java | 2 +- .../{renderer => utils}/Transformer.java | 4 +- 32 files changed, 466 insertions(+), 506 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/AxisBase.java (96%) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/Legend.java (99%) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/LimitLine.java (97%) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/MarkerView.java (98%) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/XAxis.java (98%) rename MPChartLib/src/com/github/mikephil/charting/{utils => components}/YAxis.java (97%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java rename MPChartLib/src/com/github/mikephil/charting/{renderer => utils}/HorizontalBarChartTransformer.java (97%) rename MPChartLib/src/com/github/mikephil/charting/{renderer => utils}/Transformer.java (98%) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 63e21eae6d..200217104c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -100,18 +100,6 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX += maxEntry * groupSpace; } - @Override - protected void drawDataSet(int index) { - - - } - - @Override - protected void drawValues() { - - - } - protected float getPositiveYOffset(boolean drawAboveValueBar) { return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, @@ -341,8 +329,4 @@ public void setDrawBarShadow(boolean enabled) { public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; } - - @Override - protected void drawAdditional() { - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index e7013f97ae..25f07dbabd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -14,6 +14,14 @@ import android.util.Log; import android.view.MotionEvent; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; @@ -21,21 +29,13 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.interfaces.OnDrawListener; import com.github.mikephil.charting.listener.BarLineChartTouchListener; -import com.github.mikephil.charting.renderer.Transformer; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.LimitLine; -import com.github.mikephil.charting.utils.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelInfo; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XAxis; -import com.github.mikephil.charting.utils.XAxis.XLabelPosition; -import com.github.mikephil.charting.utils.YAxis; -import com.github.mikephil.charting.utils.YAxis.AxisDependency; -import com.github.mikephil.charting.utils.YAxis.YLabelPosition; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 472581dd38..4ffc162849 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -40,22 +40,4 @@ protected void calcMinMax(boolean fixedValues) { // increase deltax by 1 because the candles have a width of 1 mDeltaX++; } - - @Override - protected void drawDataSet(int index) { - - - } - - @Override - protected void drawValues() { - // TODO Auto-generated method stub - - } - - @Override - protected void drawAdditional() { - // TODO Auto-generated method stub - - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3b18d02e33..5dad6e6bc3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -25,6 +25,9 @@ import android.view.ViewParent; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.MarkerView; +import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; @@ -35,13 +38,10 @@ import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; -import com.github.mikephil.charting.renderer.Transformer; import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.MarkerView; import com.github.mikephil.charting.utils.SelInfo; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import com.nineoldandroids.animation.ValueAnimator; @@ -68,12 +68,6 @@ public abstract class Chart 0) mDeltaX = 1; } - - @Override - protected void drawDataSet(int index) { - - } - - @Override - protected void drawValues() { - - } - - @Override - protected void drawAdditional() { - - } /** * set the width of the highlightning lines, default 3f diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index d7808c3144..37f0d7eea2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -3,9 +3,7 @@ import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Paint.Align; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; @@ -17,6 +15,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -58,7 +57,7 @@ public class PieChart extends PieRadarChartBase { /** * the radius of the transparent circle next to the chart-hole in the center */ - private float mTransparentCircleRadius = 55f; + private float mTransparentCircleRadiusPercent = 55f; /** if enabled, centertext is drawn */ private boolean mDrawCenterText = true; @@ -69,23 +68,6 @@ public class PieChart extends PieRadarChartBase { */ private boolean mDrawXVals = true; - /** - * if set to true, all values show up in percent instead of their real value - */ - private boolean mUsePercentValues = false; - - /** - * paint for the hole in the center of the pie chart and the transparent - * circle - */ - private Paint mHolePaint; - - /** - * paint object for the text that can be displayed in the center of the - * chart - */ - private Paint mCenterTextPaint; - public PieChart(Context context) { super(context); } @@ -102,26 +84,7 @@ public PieChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); - // // piechart has no offsets - // mOffsetTop = 0; - // mOffsetBottom = 0; - // mOffsetLeft = 0; - // mOffsetRight = 0; - - mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mHolePaint.setColor(Color.WHITE); - - mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mCenterTextPaint.setColor(Color.BLACK); - mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); - mCenterTextPaint.setTextAlign(Align.CENTER); - - mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); - mValuePaint.setColor(Color.WHITE); - mValuePaint.setTextAlign(Align.CENTER); - - // for the piechart, drawing values is enabled - mDrawYValues = true; + mRenderer = new PieChartRenderer(this, mAnimator, mViewPortHandler); } @Override @@ -131,27 +94,26 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - drawHighlights(); + if (mHighlightEnabled && valuesToHighlight()) + mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); -// drawData(); + mRenderer.drawData(mDrawCanvas); - drawAdditional(); + mRenderer.drawExtras(mDrawCanvas); - drawValues(); + mRenderer.drawValues(mDrawCanvas); drawLegend(); drawDescription(); - drawCenterText(); - canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } - + @Override protected void calculateOffsets() { super.calculateOffsets(); - + // prevent nullpointer when no data set if (mDataNotSet) return; @@ -167,24 +129,24 @@ protected void calculateOffsets() { c.x + boxSize, c.y + boxSize); } -// @Override -// protected void prepareContentRect() { -// super.prepareContentRect(); -// -// // prevent nullpointer when no data set -// if (mDataNotSet) -// return; -// -// float diameter = getDiameter(); -// float boxSize = diameter / 2f; -// -// PointF c = getCenterOffsets(); -// -// // create the circle box that will contain the pie-chart (the bounds of -// // the pie-chart) -// mCircleBox.set(c.x - boxSize, c.y - boxSize, -// c.x + boxSize, c.y + boxSize); -// } + // @Override + // protected void prepareContentRect() { + // super.prepareContentRect(); + // + // // prevent nullpointer when no data set + // if (mDataNotSet) + // return; + // + // float diameter = getDiameter(); + // float boxSize = diameter / 2f; + // + // PointF c = getCenterOffsets(); + // + // // create the circle box that will contain the pie-chart (the bounds of + // // the pie-chart) + // mCircleBox.set(c.x - boxSize, c.y - boxSize, + // c.x + boxSize, c.y + boxSize); + // } @Override protected void calcMinMax(boolean fixedValues) { @@ -226,100 +188,6 @@ private void calcAngles() { } - @Override - protected void drawHighlights() { - - // if there are values to highlight and highlighnting is enabled, do it - if (mHighlightEnabled && valuesToHighlight()) { - - float angle = 0f; - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - // get the index to highlight - int xIndex = mIndicesToHightlight[i].getXIndex(); - if (xIndex >= mDrawAngles.length) - continue; - - if (xIndex == 0) - angle = mRotationAngle; - else - angle = mRotationAngle + mAbsoluteAngles[xIndex - 1]; - - angle *= yyy; - - float sliceDegrees = mDrawAngles[xIndex]; - - PieDataSet set = mData - .getDataSetByIndex(mIndicesToHightlight[i] - .getDataSetIndex()); - - if (set == null) - continue; - - float shift = set.getSelectionShift(); - - /** - * Make the box containing current arc larger equally in every - * dimension, to preserve shape of arc. Code provided by: - * - * @link https://github.com/wogg - */ - RectF highlighted = new RectF(mCircleBox.left - shift, - mCircleBox.top - shift, - mCircleBox.right + shift, - mCircleBox.bottom + shift); - - mRenderPaint.setColor(set.getColor(xIndex)); - - // redefine the rect that contains the arc so that the - // highlighted pie is not cut off - mDrawCanvas.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceDegrees - - set.getSliceSpace() / 2f, true, mRenderPaint); - } - } - } - - @Override - protected void drawDataSet(int index) { - - float angle = mRotationAngle; - - int cnt = 0; - - PieDataSet dataSet = mData.getDataSets().get(index); - ArrayList entries = dataSet.getYVals(); - - for (int j = 0; j < entries.size(); j++) { - - float newangle = mDrawAngles[cnt]; - float sliceSpace = dataSet.getSliceSpace(); - - Entry e = entries.get(j); - - // draw only if the value is greater than zero - if ((Math.abs(e.getVal()) > 0.000001)) { - - if (!needsHighlight(e.getXIndex(), index)) { - - mRenderPaint.setColor(dataSet.getColor(j)); - mDrawCanvas.drawArc(mCircleBox, angle + sliceSpace / 2f, newangle * yyy - - sliceSpace / 2f, true, mRenderPaint); - } - - // if(sliceSpace > 0f) { - // - // PointF outer = getPosition(c, radius, angle); - // PointF inner = getPosition(c, radius * mHoleRadiusPercent - // / 100f, angle); - // } - } - - angle += newangle * xxx; - cnt++; - } - } - /** * checks if the given index in the given DataSet is set for highlighting or * not @@ -328,10 +196,10 @@ protected void drawDataSet(int index) { * @param dataSetIndex * @return */ - private boolean needsHighlight(int xIndex, int dataSetIndex) { + public boolean needsHighlight(int xIndex, int dataSetIndex) { // no highlight - if (!valuesToHighlight()) + if (!valuesToHighlight() || dataSetIndex < 0) return false; for (int i = 0; i < mIndicesToHightlight.length; i++) @@ -344,160 +212,6 @@ private boolean needsHighlight(int xIndex, int dataSetIndex) { return false; } - /** - * draws the hole in the center of the chart and the transparent circle / - * hole - */ - private void drawHole() { - - if (mDrawHole) { - - float radius = getRadius(); - - PointF c = getCenterCircleBox(); - - int color = mHolePaint.getColor(); - - // draw the hole-circle - mDrawCanvas.drawCircle(c.x, c.y, - radius / 100 * mHoleRadiusPercent, mHolePaint); - - if (mTransparentCircleRadius > mHoleRadiusPercent) { - - // make transparent - mHolePaint.setColor(color & 0x60FFFFFF); - - // draw the transparent-circle - mDrawCanvas.drawCircle(c.x, c.y, - radius / 100 * mTransparentCircleRadius, mHolePaint); - - mHolePaint.setColor(color); - } - } - } - - /** - * draws the description text in the center of the pie chart makes most - * sense when center-hole is enabled - */ - private void drawCenterText() { - - if (mDrawCenterText && mCenterText != null) { - - PointF c = getCenterCircleBox(); - - // get all lines from the text - String[] lines = mCenterText.split("\n"); - - // calculate the height for each line - float lineHeight = Utils.calcTextHeight(mCenterTextPaint, lines[0]); - float linespacing = lineHeight * 0.2f; - - float totalheight = lineHeight * lines.length - linespacing * (lines.length - 1); - - int cnt = lines.length; - - float y = c.y; - - for (int i = 0; i < lines.length; i++) { - - String line = lines[lines.length - i - 1]; - - mDrawCanvas.drawText(line, c.x, y - + lineHeight * cnt - totalheight / 2f, - mCenterTextPaint); - cnt--; - y -= linespacing; - } - } - } - - @Override - protected void drawValues() { - - // if neither xvals nor yvals are drawn, return - if (!mDrawXVals && !mDrawYValues) - return; - - PointF center = getCenterCircleBox(); - - // get whole the radius - float r = getRadius(); - - float off = r / 2f; - - if (mDrawHole) { - off = (r - (r / 100f * mHoleRadiusPercent)) / 2f; - } - - r -= off; // offset to keep things inside the chart - - ArrayList dataSets = mData.getDataSets(); - - int cnt = 0; - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - PieDataSet dataSet = dataSets.get(i); - ArrayList entries = dataSet.getYVals(); - - for (int j = 0; j < entries.size() * xxx; j++) { - - // offset needed to center the drawn text in the slice - float offset = mDrawAngles[cnt] / 2; - - // calculate the text position - float x = (float) (r - * Math.cos(Math.toRadians((mRotationAngle + mAbsoluteAngles[cnt] - offset) - * yyy)) + center.x); - float y = (float) (r - * Math.sin(Math.toRadians((mRotationAngle + mAbsoluteAngles[cnt] - offset) - * yyy)) + center.y); - - String val = ""; - float value = entries.get(j).getVal(); - - if (mUsePercentValues) - val = mValueFormatter.getFormattedValue(Math.abs(getPercentOfTotal(value))) - + " %"; - else - val = mValueFormatter.getFormattedValue(value); - - if (mDrawUnitInChart) - val = val + mUnit; - - // draw everything, depending on settings - if (mDrawXVals && mDrawYValues) { - - // use ascent and descent to calculate the new line - // position, - // 1.6f is the line spacing - float lineHeight = (mValuePaint.ascent() + mValuePaint.descent()) * 1.6f; - y -= lineHeight / 2; - - mDrawCanvas.drawText(val, x, y, mValuePaint); - if (j < mData.getXValCount()) - mDrawCanvas.drawText(mData.getXVals().get(j), x, y + lineHeight, - mValuePaint); - - } else if (mDrawXVals && !mDrawYValues) { - if (j < mData.getXValCount()) - mDrawCanvas.drawText(mData.getXVals().get(j), x, y, mValuePaint); - } else if (!mDrawXVals && mDrawYValues) { - - mDrawCanvas.drawText(val, x, y, mValuePaint); - } - - cnt++; - } - } - } - - @Override - protected void drawAdditional() { - drawHole(); - } - /** * calculates the needed angle for a given value * @@ -569,8 +283,8 @@ public float[] getAbsoluteAngles() { * @param color */ public void setHoleColor(int color) { - mHolePaint.setXfermode(null); - mHolePaint.setColor(color); + ((PieChartRenderer) mRenderer).getPaintHole().setXfermode(null); + ((PieChartRenderer) mRenderer).getPaintHole().setColor(color); } /** @@ -582,9 +296,10 @@ public void setHoleColor(int color) { */ public void setHoleColorTransparent(boolean enable) { if (enable) { - mHolePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + ((PieChartRenderer) mRenderer).getPaintHole().setXfermode( + new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); } else { - mHolePaint.setXfermode(null); + ((PieChartRenderer) mRenderer).getPaintHole().setXfermode(null); } } @@ -595,7 +310,7 @@ public void setHoleColorTransparent(boolean enable) { * @return true if hole is transparent. */ public boolean isHoleTransparent() { - return mHolePaint.getXfermode() != null; + return ((PieChartRenderer) mRenderer).getPaintHole().getXfermode() != null; } /** @@ -655,24 +370,6 @@ public boolean isDrawCenterTextEnabled() { return mDrawCenterText; } - /** - * set this to true to draw percent values instead of the actual values - * - * @param enabled - */ - public void setUsePercentValues(boolean enabled) { - mUsePercentValues = enabled; - } - - /** - * returns true if drawing percent values is enabled - * - * @return - */ - public boolean isUsePercentValuesEnabled() { - return mUsePercentValues; - } - /** * set this to true to draw the x-value text into the pie slices * @@ -733,7 +430,7 @@ public PointF getCenterCircleBox() { * @param t */ public void setCenterTextTypeface(Typeface t) { - mCenterTextPaint.setTypeface(t); + ((PieChartRenderer) mRenderer).getPaintCenterText().setTypeface(t); } /** @@ -742,7 +439,8 @@ public void setCenterTextTypeface(Typeface t) { * @param size */ public void setCenterTextSize(float size) { - mCenterTextPaint.setTextSize(Utils.convertDpToPixel(size)); + ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize( + Utils.convertDpToPixel(size)); } /** @@ -755,6 +453,10 @@ public void setHoleRadius(final float percent) { mHoleRadiusPercent = percent; } + public float getHoleRadius() { + return mHoleRadiusPercent; + } + /** * sets the radius of the transparent circle that is drawn next to the hole * in the piechart in percent of the maximum radius (max = the radius of the @@ -764,7 +466,11 @@ public void setHoleRadius(final float percent) { * @param percent */ public void setTransparentCircleRadius(final float percent) { - mTransparentCircleRadius = percent; + mTransparentCircleRadiusPercent = percent; + } + + public float getTransparentCircleRadius() { + return mTransparentCircleRadiusPercent; } @Override @@ -773,10 +479,10 @@ public void setPaint(Paint p, int which) { switch (which) { case PAINT_HOLE: - mHolePaint = p; + // mHolePaint = p; break; case PAINT_CENTER_TEXT: - mCenterTextPaint = p; + // mCenterTextPaint = p; break; } } @@ -789,11 +495,17 @@ public Paint getPaint(int which) { switch (which) { case PAINT_HOLE: - return mHolePaint; + // return mHolePaint; case PAINT_CENTER_TEXT: - return mCenterTextPaint; + // return mCenterTextPaint; } return null; } + + @Override + public boolean isStartAtZeroEnabled() { + // TODO Auto-generated method stub + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 44f6aac574..f62f7e270e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -8,11 +8,11 @@ import android.util.AttributeSet; import android.view.MotionEvent; +import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; -import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.github.mikephil.charting.utils.Utils; import com.nineoldandroids.animation.ObjectAnimator; @@ -159,11 +159,6 @@ protected void calculateOffsets() { applyCalculatedOffsets(); } - @Override - protected void drawAdditional() { - // TODO Auto-generated method stub - } - /** * Applys the newly calculated offsets to the matrices. */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 02a232d43c..998352f0ba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -10,13 +10,13 @@ import android.graphics.RectF; import android.util.AttributeSet; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; -import com.github.mikephil.charting.utils.LimitLine; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XAxis; -import com.github.mikephil.charting.utils.YAxis; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 973498b620..b43e7e0904 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -59,21 +59,6 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX = 1; } - @Override - protected void drawDataSet(int index) { - - } - - @Override - protected void drawValues() { - - } - - @Override - protected void drawAdditional() { - - } - /** * Returns all possible predefined ScatterShapes (excluding CUSTOM). * diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java similarity index 96% rename from MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java rename to MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 59ebde37f0..6b400253f8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -1,9 +1,11 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; import android.graphics.Color; import android.graphics.Typeface; +import com.github.mikephil.charting.utils.Utils; + /** * Baseclass of all labels. * diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java similarity index 99% rename from MPChartLib/src/com/github/mikephil/charting/utils/Legend.java rename to MPChartLib/src/com/github/mikephil/charting/components/Legend.java index f8d22eb9c5..66e3b06472 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -1,11 +1,13 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; +import com.github.mikephil.charting.utils.Utils; + import java.util.ArrayList; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java similarity index 97% rename from MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java rename to MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java index a2a8a98870..55b116410f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java @@ -1,9 +1,11 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; import android.graphics.Color; import android.graphics.DashPathEffect; +import com.github.mikephil.charting.utils.Utils; + /** * The limit line is an additional feature for all Line-, Bar- and * ScatterCharts. It allows the displaying of an additional line in the chart diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/utils/MarkerView.java rename to MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index 651ad5e0f2..3c57172fe1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; import android.content.Context; import android.graphics.Canvas; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java rename to MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 4eb33d35c5..2299e43e48 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java similarity index 97% rename from MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java rename to MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index fa3d364d96..6efe60ad8d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -1,5 +1,8 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.components; + +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9c4f2e27e6..534bf65ce3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -638,6 +638,23 @@ public int[] getColors() { return colors; } + /** + * Returns the index of the provided DataSet inside the DataSets array of + * this data object. Returns -1 if the DataSet was not found. + * + * @param dataSet + * @return + */ + public int getIndexOfDataSet(T dataSet) { + + for (int i = 0; i < mDataSets.size(); i++) { + if (mDataSets.get(i) == dataSet) + return i; + } + + return -1; + } + /** * Generates an x-values array filled with numbers in range specified by the * parameters. Can be used for convenience. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index c0df61e86d..1c53541bdd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -4,8 +4,8 @@ import android.content.Context; import android.graphics.Color; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.YAxis.AxisDependency; import java.util.ArrayList; @@ -41,7 +41,7 @@ public abstract class DataSet { private boolean mVisible = true; /** if true, y-values are drawn on the chart */ - private boolean mDrawValues = true; + protected boolean mDrawValues = true; private AxisDependency mAxisDependency = AxisDependency.LEFT; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index 0d1d36c81c..cc866b2a93 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -15,7 +15,6 @@ public class PieDataSet extends DataSet { public PieDataSet(ArrayList yVals, String label) { super(yVals, label); - // mShift = Utils.convertDpToPixel(12f); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index fb897ac542..f47284c940 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -6,6 +6,8 @@ import android.graphics.Paint; import android.graphics.Paint.Style; +import com.github.mikephil.charting.utils.Transformer; + public abstract class AxisRenderer extends Renderer { protected Transformer mTrans; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index a3e7e94d6d..b54f22d26a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 429066ceff..155c4d6f80 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index a40d4135a5..b4f0ae4ffc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -43,6 +43,14 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { mHighlightPaint.setStrokeWidth(2f); mHighlightPaint.setColor(Color.rgb(255, 187, 115)); } + + public Paint getPaintValues() { + return mValuePaint; + } + + public Paint getPaintHighlight() { + return mHighlightPaint; + } public abstract void drawData(Canvas c); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index b98e123cbf..67efd727ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java new file mode 100644 index 0000000000..1d65808d8b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -0,0 +1,324 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Align; +import android.graphics.PointF; +import android.graphics.RectF; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; + +public class PieChartRenderer extends DataRenderer { + + protected PieChart mChart; + + /** + * paint for the hole in the center of the pie chart and the transparent + * circle + */ + private Paint mHolePaint; + + /** + * paint object for the text that can be displayed in the center of the + * chart + */ + private Paint mCenterTextPaint; + + public PieChartRenderer(PieChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + mChart = chart; + + mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHolePaint.setColor(Color.WHITE); + + mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mCenterTextPaint.setColor(Color.BLACK); + mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); + mCenterTextPaint.setTextAlign(Align.CENTER); + + mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); + mValuePaint.setColor(Color.WHITE); + mValuePaint.setTextAlign(Align.CENTER); + } + + public Paint getPaintHole() { + return mHolePaint; + } + + public Paint getPaintCenterText() { + return mCenterTextPaint; + } + + @Override + public void drawData(Canvas c) { + + PieData pieData = mChart.getData(); + + for (PieDataSet set : pieData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); + } + } + + protected void drawDataSet(Canvas c, PieDataSet dataSet) { + + float angle = mChart.getRotationAngle(); + + int cnt = 0; + + ArrayList entries = dataSet.getYVals(); + float[] drawAngles = mChart.getDrawAngles(); + + for (int j = 0; j < entries.size(); j++) { + + float newangle = drawAngles[cnt]; + float sliceSpace = dataSet.getSliceSpace(); + + Entry e = entries.get(j); + + // draw only if the value is greater than zero + if ((Math.abs(e.getVal()) > 0.000001)) { + + if (!mChart.needsHighlight(e.getXIndex(), + mChart.getData().getIndexOfDataSet(dataSet))) { + + mRenderPaint.setColor(dataSet.getColor(j)); + c.drawArc(mChart.getCircleBox(), angle + sliceSpace / 2f, + newangle * mAnimator.getPhaseY() + - sliceSpace / 2f, true, mRenderPaint); + } + + // if(sliceSpace > 0f) { + // + // PointF outer = getPosition(c, radius, angle); + // PointF inner = getPosition(c, radius * mHoleRadiusPercent + // / 100f, angle); + // } + } + + angle += newangle * mAnimator.getPhaseX(); + cnt++; + } + } + + @Override + public void drawValues(Canvas c) { + + PointF center = mChart.getCenterCircleBox(); + + // get whole the radius + float r = mChart.getRadius(); + float rotationAngle = mChart.getRotationAngle(); + float[] drawAngles = mChart.getDrawAngles(); + float[] absoluteAngles = mChart.getAbsoluteAngles(); + + float off = r / 2f; + + if (mChart.isDrawHoleEnabled()) { + off = (r - (r / 100f * mChart.getHoleRadius())) / 2f; + } + + r -= off; // offset to keep things inside the chart + + PieData data = mChart.getData(); + ArrayList dataSets = data.getDataSets(); + + int cnt = 0; + + for (int i = 0; i < dataSets.size(); i++) { + + PieDataSet dataSet = dataSets.get(i); + ArrayList entries = dataSet.getYVals(); + + for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { + + // offset needed to center the drawn text in the slice + float offset = drawAngles[cnt] / 2; + + // calculate the text position + float x = (float) (r + * Math.cos(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) + * mAnimator.getPhaseY())) + center.x); + float y = (float) (r + * Math.sin(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) + * mAnimator.getPhaseY())) + center.y); + + float value = entries.get(j).getVal(); + + String val = mChart.getValueFormatter().getFormattedValue(value); + + boolean drawXVals = mChart.isDrawXValuesEnabled(); + boolean drawYVals = dataSet.isDrawValuesEnabled(); + + // draw everything, depending on settings + if (drawXVals && drawYVals) { + + // use ascent and descent to calculate the new line + // position, + // 1.6f is the line spacing + float lineHeight = (mValuePaint.ascent() + mValuePaint.descent()) * 1.6f; + y -= lineHeight / 2; + + c.drawText(val, x, y, mValuePaint); + if (j < data.getXValCount()) + c.drawText(data.getXVals().get(j), x, y + lineHeight, + mValuePaint); + + } else if (drawXVals && !drawYVals) { + if (j < data.getXValCount()) + c.drawText(data.getXVals().get(j), x, y, mValuePaint); + } else if (!drawXVals && drawYVals) { + + c.drawText(val, x, y, mValuePaint); + } + + cnt++; + } + } + } + + @Override + public void drawExtras(Canvas c) { + drawHole(c); + drawCenterText(c); + } + + /** + * draws the hole in the center of the chart and the transparent circle / + * hole + */ + private void drawHole(Canvas c) { + + if (mChart.isDrawHoleEnabled()) { + + float transparentCircleRadius = mChart.getTransparentCircleRadius(); + float holeRadius = mChart.getHoleRadius(); + float radius = mChart.getRadius(); + + PointF center = mChart.getCenterCircleBox(); + + int color = mHolePaint.getColor(); + + // draw the hole-circle + c.drawCircle(center.x, center.y, + radius / 100 * holeRadius, mHolePaint); + + if (transparentCircleRadius > holeRadius) { + + // make transparent + mHolePaint.setColor(color & 0x60FFFFFF); + + // draw the transparent-circle + c.drawCircle(center.x, center.y, + radius / 100 * transparentCircleRadius, mHolePaint); + + mHolePaint.setColor(color); + } + } + } + + /** + * draws the description text in the center of the pie chart makes most + * sense when center-hole is enabled + */ + private void drawCenterText(Canvas c) { + + String centerText = mChart.getCenterText(); + + if (mChart.isDrawCenterTextEnabled() && centerText != null) { + + PointF center = mChart.getCenterCircleBox(); + + // get all lines from the text + String[] lines = centerText.split("\n"); + + // calculate the height for each line + float lineHeight = Utils.calcTextHeight(mCenterTextPaint, lines[0]); + float linespacing = lineHeight * 0.2f; + + float totalheight = lineHeight * lines.length - linespacing * (lines.length - 1); + + int cnt = lines.length; + + float y = center.y; + + for (int i = 0; i < lines.length; i++) { + + String line = lines[lines.length - i - 1]; + + c.drawText(line, center.x, y + + lineHeight * cnt - totalheight / 2f, + mCenterTextPaint); + cnt--; + y -= linespacing; + } + } + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + float rotationAngle = mChart.getRotationAngle(); + float angle = 0f; + + float[] drawAngles = mChart.getDrawAngles(); + float[] absoluteAngles = mChart.getAbsoluteAngles(); + + for (int i = 0; i < indices.length; i++) { + + // get the index to highlight + int xIndex = indices[i].getXIndex(); + if (xIndex >= drawAngles.length) + continue; + + if (xIndex == 0) + angle = rotationAngle; + else + angle = rotationAngle + absoluteAngles[xIndex - 1]; + + angle *= mAnimator.getPhaseY(); + + float sliceDegrees = drawAngles[xIndex]; + + PieDataSet set = mChart.getData() + .getDataSetByIndex(indices[i] + .getDataSetIndex()); + + if (set == null) + continue; + + float shift = set.getSelectionShift(); + RectF circleBox = mChart.getCircleBox(); + + /** + * Make the box containing current arc larger equally in every + * dimension, to preserve shape of arc. Code provided by: + * + * @link https://github.com/wogg + */ + RectF highlighted = new RectF(circleBox.left - shift, + circleBox.top - shift, + circleBox.right + shift, + circleBox.bottom + shift); + + mRenderPaint.setColor(set.getColor(xIndex)); + + // redefine the rect that contains the arc so that the + // highlighted pie is not cut off + c.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceDegrees + - set.getSliceSpace() / 2f, true, mRenderPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index 2d4af3f83a..a76bea0811 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.renderer; - /** * Abstract baseclass of all Renderers. * @@ -9,6 +8,9 @@ */ public abstract class Renderer { + /** + * the component that handles the drawing area of the chart and it's offsets + */ protected ViewPortHandler mViewPortHandler; public Renderer(ViewPortHandler viewPortHandler) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 704ae7d092..fee356817d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 09a9ada125..e5328776a3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,9 +6,10 @@ import android.graphics.Paint; import android.graphics.Paint.Align; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XAxis; -import com.github.mikephil.charting.utils.XAxis.XLabelPosition; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 5fd754ca8f..83f40946ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -4,9 +4,10 @@ import android.graphics.Canvas; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.XAxis; public class XAxisRendererBarChart extends XAxisRenderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 5206fca9b4..24de99762d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -6,15 +6,16 @@ import android.graphics.Paint; import android.graphics.Paint.Align; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.utils.LimitLine; -import com.github.mikephil.charting.utils.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; -import com.github.mikephil.charting.utils.YAxis; -import com.github.mikephil.charting.utils.YAxis.AxisDependency; -import com.github.mikephil.charting.utils.YAxis.YLabelPosition; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java similarity index 97% rename from MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java rename to MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java index f1e7450e61..7f5f9bd80d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartTransformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.renderer; +package com.github.mikephil.charting.utils; import com.github.mikephil.charting.interfaces.ChartInterface; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java rename to MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index e61fdabf70..d6fc10f1f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.renderer; +package com.github.mikephil.charting.utils; import android.graphics.Matrix; import android.graphics.Path; @@ -8,7 +8,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.renderer.ViewPortHandler; import java.util.ArrayList; From e3f3dded5b4a9d0466f34bb931e681029027de4c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Feb 2015 17:41:46 +0100 Subject: [PATCH 0067/1390] Worked on RadarChart, out-commented Horizontal-BarChart. --- .../charting/charts/BarLineChartBase.java | 32 +- .../mikephil/charting/charts/Chart.java | 45 +- .../charting/charts/HorizontalBarChart.java | 9 +- .../mikephil/charting/charts/PieChart.java | 24 - .../charting/charts/PieRadarChartBase.java | 23 +- .../mikephil/charting/charts/RadarChart.java | 423 +++--------------- .../charting/renderer/AxisRenderer.java | 14 + .../charting/renderer/PieChartRenderer.java | 2 +- .../charting/renderer/RadarChartRenderer.java | 226 ++++++++++ .../charting/renderer/XAxisRenderer.java | 26 +- .../renderer/XAxisRendererBarChart.java | 6 +- .../renderer/XAxisRendererRadarChart.java | 48 ++ .../charting/renderer/YAxisRenderer.java | 26 +- .../renderer/YAxisRendererRadarChart.java | 105 +++++ .../utils/HorizontalBarChartTransformer.java | 30 +- .../github/mikephil/charting/utils/Utils.java | 18 + 16 files changed, 564 insertions(+), 493 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 25f07dbabd..b4af7a92f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -338,25 +338,29 @@ protected void calculateOffsets() { // String label = mYLabels.getFormattedLabel(mYLabels.mEntryCount - 1); String label = mAxisLeft.getLongestLabel(); - // calculate the maximum y-label width (including eventual offsets) - float ylabelwidth = Utils.calcTextWidth(mYLabelPaint, - label + mUnit + (mYChartMin < 0 ? "----" : "+++")); // offsets - if (mDrawYAxis) { // offsets for y-labels if (mAxisLeft.isEnabled()) { + + // calculate the maximum y-label width (including eventual offsets) + float ylabelwidth = Utils.calcTextWidth(mAxisRendererLeft.getAxisPaint(), + label + (mYChartMin < 0 ? "----" : "+++")); // offsets yleft = ylabelwidth; } if (mAxisRight.isEnabled()) { + + // calculate the maximum y-label width (including eventual offsets) + float ylabelwidth = Utils.calcTextWidth(mAxisRendererRight.getAxisPaint(), + label + (mYChartMin < 0 ? "----" : "+++")); // offsets yright = ylabelwidth; } } float xtop = 0f, xbottom = 0f; - float xlabelheight = Utils.calcTextHeight(mXLabelPaint, "Q") * 2f; + float xlabelheight = Utils.calcTextHeight(mXAxisRenderer.getAxisPaint(), "Q") * 2f; if (mDrawXLabels) { @@ -967,24 +971,6 @@ public void setDrawXLabels(boolean enabled) { mDrawXLabels = enabled; } - /** - * set this to true to enable drawing the y-labels, false if not - * - * @param enabled - */ - public void setDrawYLabels(boolean enabled) { - mDrawYAxis = enabled; - } - - /** - * Returns true if drawing y-labels is enabled, false if not. - * - * @return - */ - public boolean isDrawYLabelsEnabled() { - return mDrawYAxis; - } - /** * Returns true if drawing x-labels is enabled, false if not. * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 5dad6e6bc3..3165ab8964 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -91,13 +91,7 @@ public abstract class Chart { /** if enabled, centertext is drawn */ private boolean mDrawCenterText = true; - /** - * set this to true to draw the x-values next to the values in the pie - * slices - */ - private boolean mDrawXVals = true; - public PieChart(Context context) { super(context); } @@ -370,24 +364,6 @@ public boolean isDrawCenterTextEnabled() { return mDrawCenterText; } - /** - * set this to true to draw the x-value text into the pie slices - * - * @param enabled - */ - public void setDrawXValues(boolean enabled) { - mDrawXVals = enabled; - } - - /** - * returns true if drawing x-values is enabled, false if not - * - * @return - */ - public boolean isDrawXValuesEnabled() { - return mDrawXVals; - } - @Override protected float getRequiredBottomOffset() { return mLegendLabelPaint.getTextSize() * 4f; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index f62f7e270e..0d0942ed71 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -28,7 +28,10 @@ public abstract class PieRadarChartBase { - /** paint for drawing the web */ - private Paint mWebPaint; - /** width of the main web lines */ private float mWebLineWidth = 2.5f; @@ -46,9 +40,6 @@ public class RadarChart extends PieRadarChartBase { /** transparency the grid is drawn with (0-255) */ private int mWebAlpha = 150; - /** flag indicating if the y-labels should be drawn or not */ - private boolean mDrawYLabels = true; - /** flag indicating if the x-labels should be drawn or not */ private boolean mDrawXLabels = true; @@ -56,11 +47,14 @@ public class RadarChart extends PieRadarChartBase { private boolean mDrawWeb = true; /** the object reprsenting the y-axis labels */ - private YAxis mYAxis = new YAxis(); + private YAxis mYAxis = new YAxis(AxisDependency.LEFT); /** the object representing the x-axis labels */ private XAxis mXAxis = new XAxis(); + protected YAxisRendererRadarChart mYAxisRenderer; + protected XAxisRendererRadarChart mXAxisRenderer; + public RadarChart(Context context) { super(context); } @@ -77,16 +71,14 @@ public RadarChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + mXAxis.setSpaceBetweenLabels(0); + mWebLineWidth = Utils.convertDpToPixel(1.5f); mInnerWebLineWidth = Utils.convertDpToPixel(0.75f); - mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mWebPaint.setStyle(Paint.Style.STROKE); - - mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mHighlightPaint.setStyle(Paint.Style.STROKE); - mHighlightPaint.setStrokeWidth(2f); - mHighlightPaint.setColor(Color.rgb(255, 187, 115)); + mRenderer = new RadarChartRenderer(this, mAnimator, mViewPortHandler); + mYAxisRenderer = new YAxisRendererRadarChart(mViewPortHandler, mYAxis, this); + mXAxisRenderer = new XAxisRendererRadarChart(mViewPortHandler, mXAxis, this); } @Override @@ -108,8 +100,9 @@ protected void calcMinMax(boolean fixedValues) { public void prepare() { super.prepare(); + mYAxisRenderer.computeAxis(this); prepareYLabels(); - prepareXLabels(); + mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); } @Override @@ -119,21 +112,23 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - drawXLabels(); + if (mDrawXLabels) + mXAxisRenderer.renderAxis(mDrawCanvas); - drawWeb(); + if (mDrawWeb) + mRenderer.drawExtras(mDrawCanvas); - drawLimitLines(); + mYAxisRenderer.renderLimitLines(mDrawCanvas, mValueFormatter); - // drawData(); + mRenderer.drawData(mDrawCanvas); - drawAdditional(); + if (mHighlightEnabled && valuesToHighlight()) + mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); - drawHighlights(); + if (mYAxis.isEnabled()) + mYAxisRenderer.renderAxis(mDrawCanvas); - drawYLabels(); - - drawValues(); + mRenderer.drawValues(mDrawCanvas); drawLegend(); @@ -144,149 +139,6 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } - /** - * Draws the spider web. - */ - private void drawWeb() { - - if (!mDrawWeb) - return; - - float sliceangle = getSliceAngle(); - - // calculate the factor that is needed for transforming the value to - // pixels - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - // draw the web lines that come from the center - mWebPaint.setStrokeWidth(mWebLineWidth); - mWebPaint.setColor(mWebColor); - mWebPaint.setAlpha(mWebAlpha); - - for (int i = 0; i < mData.getXValCount(); i++) { - - PointF p = getPosition(c, mYChartMax * factor, sliceangle * i + mRotationAngle); - - mDrawCanvas.drawLine(c.x, c.y, p.x, p.y, mWebPaint); - } - - // draw the inner-web - mWebPaint.setStrokeWidth(mInnerWebLineWidth); - mWebPaint.setColor(mWebColorInner); - mWebPaint.setAlpha(mWebAlpha); - - int labelCount = mYAxis.mEntryCount; - - for (int j = 0; j < labelCount; j++) { - - for (int i = 0; i < mData.getXValCount(); i++) { - - float r = ((mYChartMax / labelCount) * (j + 1)) * factor; - - PointF p1 = getPosition(c, r, sliceangle * i + mRotationAngle); - PointF p2 = getPosition(c, r, sliceangle * (i + 1) + mRotationAngle); - - mDrawCanvas.drawLine(p1.x, p1.y, p2.x, p2.y, mWebPaint); - } - } - } - - @Override - protected void drawDataSet(int index) { - - float sliceangle = getSliceAngle(); - - // calculate the factor that is needed for transforming the value to - // pixels - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - RadarDataSet dataSet = mData.getDataSets().get(index); - ArrayList entries = dataSet.getYVals(); - - Path surface = new Path(); - - for (int j = 0; j < entries.size(); j++) { - - mRenderPaint.setColor(dataSet.getColor(j)); - - Entry e = entries.get(j); - - PointF p = getPosition(c, e.getVal() * factor, sliceangle * j + mRotationAngle); - - if (j == 0) - surface.moveTo(p.x, p.y); - else - surface.lineTo(p.x, p.y); - } - - surface.close(); - - // draw filled - if (dataSet.isDrawFilledEnabled()) { - mRenderPaint.setStyle(Paint.Style.FILL); - mRenderPaint.setAlpha(dataSet.getFillAlpha()); - mDrawCanvas.drawPath(surface, mRenderPaint); - mRenderPaint.setAlpha(255); - } - - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); - mRenderPaint.setStyle(Paint.Style.STROKE); - - // draw the line (only if filled is disabled or alpha is below 255) - if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) - mDrawCanvas.drawPath(surface, mRenderPaint); - } - - /** - * Draws the limit lines if there are one. - */ - private void drawLimitLines() { - - ArrayList limitLines = mData.getLimitLines(); - - if (limitLines == null) - return; - - float sliceangle = getSliceAngle(); - - // calculate the factor that is needed for transforming the value to - // pixels - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - for (int i = 0; i < limitLines.size(); i++) { - - LimitLine l = limitLines.get(i); - - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - - float r = l.getLimit() * factor; - - Path limitPath = new Path(); - - for (int j = 0; j < mData.getXValCount(); j++) { - - PointF p = getPosition(c, r, sliceangle * j + mRotationAngle); - - if (j == 0) - limitPath.moveTo(p.x, p.y); - else - limitPath.lineTo(p.x, p.y); - } - - limitPath.close(); - - mDrawCanvas.drawPath(limitPath, mLimitLinePaint); - } - } - /** * Calculates the required maximum y-value in order to be able to provide * the desired number of label entries and rounded label values. @@ -325,172 +177,6 @@ private void prepareYLabels() { mDeltaY = Math.abs(mYChartMax - mYChartMin); } - /** - * Draws the y-labels of the RadarChart. - */ - private void drawYLabels() { - - if (!mDrawYLabels) - return; - - mYLabelPaint.setTypeface(mYAxis.getTypeface()); - mYLabelPaint.setTextSize(mYAxis.getTextSize()); - mYLabelPaint.setColor(mYAxis.getTextColor()); - - PointF c = getCenterOffsets(); - float factor = getFactor(); - - int labelCount = mYAxis.mEntryCount; - - for (int j = 0; j < labelCount; j++) { - - if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) - break; - - float r = ((mYChartMax / labelCount) * j) * factor; - - PointF p = getPosition(c, r, mRotationAngle); - - float val = r / factor; - - String label = Utils.formatNumber(val, mYAxis.mDecimals, - mYAxis.isSeparateThousandsEnabled()); - - if (mYAxis.isDrawUnitsInYLabelEnabled()) - mDrawCanvas.drawText(label + mUnit, p.x + 10, p.y - 5, mYLabelPaint); - else { - mDrawCanvas.drawText(label, p.x + 10, p.y - 5, mYLabelPaint); - } - } - } - - /** - * setup the x-axis labels - */ - private void prepareXLabels() { - - StringBuffer a = new StringBuffer(); - - int max = (int) Math.round(mData.getXValAverageLength()); - - for (int i = 0; i < max; i++) { - a.append("h"); - } - - mXAxis.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); - mXAxis.mLabelHeight = Utils.calcTextWidth(mXLabelPaint, "Q"); - } - - /** - * Draws the x-labels of the chart. - */ - private void drawXLabels() { - - if (!mDrawXLabels) - return; - - mXLabelPaint.setTypeface(mXAxis.getTypeface()); - mXLabelPaint.setTextSize(mXAxis.getTextSize()); - mXLabelPaint.setColor(mXAxis.getTextColor()); - - float sliceangle = getSliceAngle(); - - // calculate the factor that is needed for transforming the value to - // pixels - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - for (int i = 0; i < mData.getXValCount(); i++) { - - String text = mData.getXVals().get(i); - - float angle = (sliceangle * i + mRotationAngle) % 360f; - - PointF p = getPosition(c, mYChartMax * factor + mXAxis.mLabelWidth / 2f, angle); - - mDrawCanvas.drawText(text, p.x, p.y + mXAxis.mLabelHeight / 2f, mXLabelPaint); - } - } - - @Override - protected void drawValues() { - - // if values are drawn - if (mDrawYValues) { - - float sliceangle = getSliceAngle(); - - // calculate the factor that is needed for transforming the value to - // pixels - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - float yoffset = Utils.convertDpToPixel(5f); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - RadarDataSet dataSet = mData.getDataSetByIndex(i); - ArrayList entries = dataSet.getYVals(); - - for (int j = 0; j < entries.size(); j++) { - - Entry e = entries.get(j); - - PointF p = getPosition(c, e.getVal() * factor, sliceangle * j + mRotationAngle); - - if (mDrawUnitInChart) - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(e.getVal()) + mUnit, - p.x, p.y - yoffset, mValuePaint); - else - mDrawCanvas.drawText(mValueFormatter.getFormattedValue(e.getVal()), - p.x, p.y - yoffset, mValuePaint); - } - } - } - } - - @Override - protected void drawHighlights() { - - // if there are values to highlight and highlighnting is enabled, do it - if (mHighlightEnabled && valuesToHighlight()) { - - float sliceangle = getSliceAngle(); - float factor = getFactor(); - - PointF c = getCenterOffsets(); - - for (int i = 0; i < mIndicesToHightlight.length; i++) { - - RadarDataSet set = mData - .getDataSetByIndex(mIndicesToHightlight[i] - .getDataSetIndex()); - - if (set == null) - continue; - - mHighlightPaint.setColor(set.getHighLightColor()); - - // get the index to highlight - int xIndex = mIndicesToHightlight[i].getXIndex(); - - Entry e = set.getEntryForXIndex(xIndex); - int j = set.getEntryPosition(e); - float y = e.getVal(); - - PointF p = getPosition(c, y * factor, sliceangle * j + mRotationAngle); - - float[] pts = new float[] { - p.x, 0, p.x, getHeight(), 0, p.y, getWidth(), p.y - }; - - mDrawCanvas.drawLines(pts, mHighlightPaint); - } - } - } - /** * Returns the factor that is needed to transform values into pixels. * @@ -532,7 +218,7 @@ public int getIndexForAngle(float angle) { * * @return */ - public YAxis getYLabels() { + public YAxis getYAxis() { return mYAxis; } @@ -541,7 +227,7 @@ public YAxis getYLabels() { * * @return */ - public XAxis getXLabels() { + public XAxis getXAxis() { return mXAxis; } @@ -554,6 +240,10 @@ public void setWebLineWidth(float width) { mWebLineWidth = Utils.convertDpToPixel(width); } + public float getWebLineWidth() { + return mWebLineWidth; + } + /** * Sets the width of the web lines that are in between the lines coming from * the center. @@ -564,6 +254,10 @@ public void setWebLineWidthInner(float width) { mInnerWebLineWidth = Utils.convertDpToPixel(width); } + public float getWebLineWidthInner() { + return mInnerWebLineWidth; + } + /** * Sets the transparency (alpha) value for all web lines, default: 150, 255 * = 100% opaque, 0 = 100% transparent @@ -574,6 +268,15 @@ public void setWebAlpha(int alpha) { mWebAlpha = alpha; } + /** + * Returns the alpha value for all web lines. + * + * @return + */ + public int getWebAlpha() { + return mWebAlpha; + } + /** * Sets the color for the web lines that come from the center. Don't forget * to use getResources().getColor(...) when loading a color from the @@ -585,6 +288,10 @@ public void setWebColor(int color) { mWebColor = color; } + public int getWebColor() { + return mWebColor; + } + /** * Sets the color for the web lines in between the lines that come from the * center. Don't forget to use getResources().getColor(...) when loading a @@ -596,6 +303,10 @@ public void setWebColorInner(int color) { mWebColorInner = color; } + public int getWebColorInner() { + return mWebColorInner; + } + /** * If set to true, drawing the web is enabled, if set to false, drawing the * whole web is disabled. Default: true @@ -606,15 +317,6 @@ public void setDrawWeb(boolean enabled) { mDrawWeb = enabled; } - /** - * set this to true to enable drawing the y-labels, false if not - * - * @param enabled - */ - public void setDrawYLabels(boolean enabled) { - mDrawYLabels = enabled; - } - /** * set this to true to enable drawing the x-labels, false if not * @@ -624,15 +326,6 @@ public void setDrawXLabels(boolean enabled) { mDrawXLabels = enabled; } - /** - * Returns true if drawing y-labels is enabled, false if not. - * - * @return - */ - public boolean isDrawYLabelsEnabled() { - return mDrawYLabels; - } - /** * Returns true if drawing x-labels is enabled, false if not. * @@ -664,7 +357,7 @@ public void setPaint(Paint p, int which) { switch (which) { case PAINT_RADAR_WEB: - mWebPaint = p; + // mWebPaint = p; break; } } @@ -677,9 +370,15 @@ public Paint getPaint(int which) { switch (which) { case PAINT_RADAR_WEB: - return mWebPaint; + // return mWebPaint; } return null; } + + @Override + public boolean isStartAtZeroEnabled() { + // TODO Auto-generated method stub + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index f47284c940..0bab566676 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -15,11 +15,16 @@ public abstract class AxisRenderer extends Renderer { /** paint object for the grid lines */ protected Paint mGridPaint; + /** paint for the x-label values */ + protected Paint mAxisPaint; + public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans) { super(viewPortHandler); this.mTrans = trans; + mAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mGridPaint = new Paint(); mGridPaint.setColor(Color.GRAY); mGridPaint.setStrokeWidth(1f); @@ -27,6 +32,15 @@ public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans) { mGridPaint.setAlpha(90); } + /** + * Returns the Paint object used for drawing the axis. + * + * @return + */ + public Paint getAxisPaint() { + return mAxisPaint; + } + public Transformer getTransformer() { return mTrans; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 1d65808d8b..51f2a4715c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -159,7 +159,7 @@ public void drawValues(Canvas c) { String val = mChart.getValueFormatter().getFormattedValue(value); - boolean drawXVals = mChart.isDrawXValuesEnabled(); + boolean drawXVals = mChart.isDrawAxisLabelsEnabled(); boolean drawYVals = dataSet.isDrawValuesEnabled(); // draw everything, depending on settings diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java new file mode 100644 index 0000000000..0ea66b20e8 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -0,0 +1,226 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PointF; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.RadarData; +import com.github.mikephil.charting.data.RadarDataSet; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; + +public class RadarChartRenderer extends DataRenderer { + + protected RadarChart mChart; + + /** paint for drawing the web */ + protected Paint mWebPaint; + + public RadarChartRenderer(RadarChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + mChart = chart; + + mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mHighlightPaint.setStyle(Paint.Style.STROKE); + mHighlightPaint.setStrokeWidth(2f); + mHighlightPaint.setColor(Color.rgb(255, 187, 115)); + + mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mWebPaint.setStyle(Paint.Style.STROKE); + } + + public Paint getWebPaint() { + return mWebPaint; + } + + @Override + public void drawData(Canvas c) { + + RadarData radarData = mChart.getData(); + + for (RadarDataSet set : radarData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); + } + } + + protected void drawDataSet(Canvas c, RadarDataSet dataSet) { + + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); + + ArrayList entries = dataSet.getYVals(); + + Path surface = new Path(); + + for (int j = 0; j < entries.size(); j++) { + + mRenderPaint.setColor(dataSet.getColor(j)); + + Entry e = entries.get(j); + + PointF p = Utils.getPosition(center, e.getVal() * factor, + sliceangle * j + mChart.getRotationAngle()); + + if (j == 0) + surface.moveTo(p.x, p.y); + else + surface.lineTo(p.x, p.y); + } + + surface.close(); + + // draw filled + if (dataSet.isDrawFilledEnabled()) { + mRenderPaint.setStyle(Paint.Style.FILL); + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + c.drawPath(surface, mRenderPaint); + mRenderPaint.setAlpha(255); + } + + mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); + mRenderPaint.setStyle(Paint.Style.STROKE); + + // draw the line (only if filled is disabled or alpha is below 255) + if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) + c.drawPath(surface, mRenderPaint); + } + + @Override + public void drawValues(Canvas c) { + + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); + + float yoffset = Utils.convertDpToPixel(5f); + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + RadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); + + if (!dataSet.isDrawValuesEnabled()) + continue; + + ArrayList entries = dataSet.getYVals(); + + for (int j = 0; j < entries.size(); j++) { + + Entry e = entries.get(j); + + PointF p = Utils.getPosition(center, e.getVal() * factor, + sliceangle * j + mChart.getRotationAngle()); + + c.drawText(mChart.getValueFormatter().getFormattedValue(e.getVal()), + p.x, p.y - yoffset, mValuePaint); + } + } + } + + @Override + public void drawExtras(Canvas c) { + drawWeb(c); + } + + private void drawWeb(Canvas c) { + + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + float rotationangle = mChart.getRotationAngle(); + + PointF center = mChart.getCenterOffsets(); + + // draw the web lines that come from the center + mWebPaint.setStrokeWidth(mChart.getWebLineWidth()); + mWebPaint.setColor(mChart.getWebColor()); + mWebPaint.setAlpha(mChart.getWebAlpha()); + + for (int i = 0; i < mChart.getData().getXValCount(); i++) { + + PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor, sliceangle * i + rotationangle); + + c.drawLine(center.x, center.y, p.x, p.y, mWebPaint); + } + + // draw the inner-web + mWebPaint.setStrokeWidth(mChart.getWebLineWidthInner()); + mWebPaint.setColor(mChart.getWebColorInner()); + mWebPaint.setAlpha(mChart.getWebAlpha()); + + int labelCount = mChart.getYAxis().mEntryCount; + + for (int j = 0; j < labelCount; j++) { + + for (int i = 0; i < mChart.getData().getXValCount(); i++) { + + float r = ((mChart.getYChartMax() / labelCount) * (j + 1)) * factor; + + PointF p1 = Utils.getPosition(center, r, sliceangle * i + rotationangle); + PointF p2 = Utils.getPosition(center, r, sliceangle * (i + 1) + rotationangle); + + c.drawLine(p1.x, p1.y, p2.x, p2.y, mWebPaint); + } + } + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + float sliceangle = mChart.getSliceAngle(); + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); + + for (int i = 0; i < indices.length; i++) { + + RadarDataSet set = mChart.getData() + .getDataSetByIndex(indices[i] + .getDataSetIndex()); + + if (set == null) + continue; + + mHighlightPaint.setColor(set.getHighLightColor()); + + // get the index to highlight + int xIndex = indices[i].getXIndex(); + + Entry e = set.getEntryForXIndex(xIndex); + int j = set.getEntryPosition(e); + float y = e.getVal(); + + PointF p = Utils.getPosition(center, y * factor, + sliceangle * j + mChart.getRotationAngle()); + + float[] pts = new float[] { + p.x, 0, p.x, mViewPortHandler.getChartHeight(), 0, p.y, + mViewPortHandler.getChartWidth(), p.y + }; + + c.drawLines(pts, mHighlightPaint); + } + } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index e5328776a3..8e6dbdc9b1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -15,9 +15,6 @@ public class XAxisRenderer extends AxisRenderer { - /** paint for the x-label values */ - protected Paint mXLabelPaint; - protected XAxis mXAxis; public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { @@ -25,10 +22,9 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t this.mXAxis = xAxis; - mXLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mXLabelPaint.setColor(Color.BLACK); - mXLabelPaint.setTextAlign(Align.CENTER); - mXLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + mAxisPaint.setColor(Color.BLACK); + mAxisPaint.setTextAlign(Align.CENTER); + mAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); } public void computeAxis(float xValAverageLength, ArrayList xValues) { @@ -42,8 +38,8 @@ public void computeAxis(float xValAverageLength, ArrayList xValues) { a.append("h"); } - mXAxis.mLabelWidth = Utils.calcTextWidth(mXLabelPaint, a.toString()); - mXAxis.mLabelHeight = Utils.calcTextHeight(mXLabelPaint, "Q"); + mXAxis.mLabelWidth = Utils.calcTextWidth(mAxisPaint, a.toString()); + mXAxis.mLabelHeight = Utils.calcTextHeight(mAxisPaint, "Q"); mXAxis.setValues(xValues); } @@ -52,9 +48,9 @@ public void renderAxis(Canvas c) { float yoffset = Utils.convertDpToPixel(4f); - mXLabelPaint.setTypeface(mXAxis.getTypeface()); - mXLabelPaint.setTextSize(mXAxis.getTextSize()); - mXLabelPaint.setColor(mXAxis.getTextColor()); + mAxisPaint.setTypeface(mXAxis.getTypeface()); + mAxisPaint.setTextSize(mXAxis.getTextSize()); + mAxisPaint.setColor(mXAxis.getTextColor()); if (mXAxis.getPosition() == XLabelPosition.TOP) { @@ -109,7 +105,7 @@ protected void drawLabels(Canvas c, float yPos) { // avoid clipping of the last if (i == mXAxis.getValues().size() - 1) { - float width = Utils.calcTextWidth(mXLabelPaint, label); + float width = Utils.calcTextWidth(mAxisPaint, label); if (width > mViewPortHandler.offsetRight() * 2 && position[0] + width > mViewPortHandler.getChartWidth()) @@ -118,14 +114,14 @@ protected void drawLabels(Canvas c, float yPos) { // avoid clipping of the first } else if (i == 0) { - float width = Utils.calcTextWidth(mXLabelPaint, label); + float width = Utils.calcTextWidth(mAxisPaint, label); position[0] += width / 2; } } c.drawText(label, position[0], yPos, - mXLabelPaint); + mAxisPaint); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 83f40946ec..76f7fb03e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -55,7 +55,7 @@ protected void drawLabels(Canvas c, float yPos) { // avoid clipping of the last if (i == mXAxis.getValues().size() - 1) { - float width = Utils.calcTextWidth(mXLabelPaint, label); + float width = Utils.calcTextWidth(mAxisPaint, label); if (width > mViewPortHandler.offsetRight() * 2 && position[0] + width > mViewPortHandler.getChartWidth()) @@ -64,14 +64,14 @@ protected void drawLabels(Canvas c, float yPos) { // avoid clipping of the first } else if (i == 0) { - float width = Utils.calcTextWidth(mXLabelPaint, label); + float width = Utils.calcTextWidth(mAxisPaint, label); position[0] += width / 2; } } c.drawText(label, position[0], yPos, - mXLabelPaint); + mAxisPaint); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java new file mode 100644 index 0000000000..34af78cdca --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -0,0 +1,48 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.PointF; + +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.utils.Utils; + +public class XAxisRendererRadarChart extends XAxisRenderer { + + private RadarChart mChart; + + public XAxisRendererRadarChart(ViewPortHandler viewPortHandler, XAxis xAxis, RadarChart chart) { + super(viewPortHandler, xAxis, null); + + mChart = chart; + } + + @Override + public void renderAxis(Canvas c) { + + mAxisPaint.setTypeface(mXAxis.getTypeface()); + mAxisPaint.setTextSize(mXAxis.getTextSize()); + mAxisPaint.setColor(mXAxis.getTextColor()); + + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); + + for (int i = 0; i < mXAxis.getValues().size(); i++) { + + String text = mXAxis.getValues().get(i); + + float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; + + PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor + + mXAxis.mLabelWidth / 2f, angle); + + c.drawText(text, p.x, p.y + mXAxis.mLabelHeight / 2f, mAxisPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 24de99762d..501af1774d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -21,9 +21,6 @@ public class YAxisRenderer extends AxisRenderer { - /** paint for the y-label values */ - protected Paint mYAxisPaint; - /** paint used for the limit lines */ protected Paint mLimitLinePaint; @@ -34,9 +31,8 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t this.mYAxis = yAxis; - mYAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mYAxisPaint.setColor(Color.BLACK); - mYAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); + mAxisPaint.setColor(Color.BLACK); + mAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLimitLinePaint.setStyle(Paint.Style.STROKE); @@ -173,12 +169,12 @@ public void renderAxis(Canvas c) { mTrans.pointValuesToPixel(positions); - mYAxisPaint.setTypeface(mYAxis.getTypeface()); - mYAxisPaint.setTextSize(mYAxis.getTextSize()); - mYAxisPaint.setColor(mYAxis.getTextColor()); + mAxisPaint.setTypeface(mYAxis.getTypeface()); + mAxisPaint.setTextSize(mYAxis.getTextSize()); + mAxisPaint.setColor(mYAxis.getTextColor()); float xoffset = Utils.convertDpToPixel(5f); - float yoffset = Utils.calcTextHeight(mYAxisPaint, "A") / 2.5f; + float yoffset = Utils.calcTextHeight(mAxisPaint, "A") / 2.5f; AxisDependency dependency = mYAxis.getAxisDependency(); YLabelPosition labelPosition = mYAxis.getLabelPosition(); @@ -188,20 +184,20 @@ public void renderAxis(Canvas c) { if (dependency == AxisDependency.LEFT) { if (labelPosition == YLabelPosition.OUTSIDE_CHART) { - mYAxisPaint.setTextAlign(Align.RIGHT); + mAxisPaint.setTextAlign(Align.RIGHT); xPos = mViewPortHandler.offsetLeft() - xoffset; } else { - mYAxisPaint.setTextAlign(Align.LEFT); + mAxisPaint.setTextAlign(Align.LEFT); xPos = mViewPortHandler.offsetLeft() + xoffset; } } else { if (labelPosition == YLabelPosition.OUTSIDE_CHART) { - mYAxisPaint.setTextAlign(Align.LEFT); + mAxisPaint.setTextAlign(Align.LEFT); xPos = mViewPortHandler.contentRight() + xoffset; } else { - mYAxisPaint.setTextAlign(Align.RIGHT); + mAxisPaint.setTextAlign(Align.RIGHT); xPos = mViewPortHandler.contentRight() - xoffset; } } @@ -225,7 +221,7 @@ private void drawYLabels(Canvas c, float xPos, float[] positions, float yOffset) if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) return; - c.drawText(text, xPos, positions[i * 2 + 1] + yOffset, mYAxisPaint); + c.drawText(text, xPos, positions[i * 2 + 1] + yOffset, mAxisPaint); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java new file mode 100644 index 0000000000..089d2ced42 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -0,0 +1,105 @@ +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.PointF; + +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ValueFormatter; + +import java.util.ArrayList; + +public class YAxisRendererRadarChart extends YAxisRenderer { + + private RadarChart mChart; + + public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { + super(viewPortHandler, yAxis, null); + + mChart = chart; + } + + @Override + public void computeAxis(ChartInterface chart) { + + + } + + @Override + public void renderAxis(Canvas c) { + + mAxisPaint.setTypeface(mYAxis.getTypeface()); + mAxisPaint.setTextSize(mYAxis.getTextSize()); + mAxisPaint.setColor(mYAxis.getTextColor()); + + PointF center = mChart.getCenterOffsets(); + float factor = mChart.getFactor(); + + int labelCount = mYAxis.mEntryCount; + + for (int j = 0; j < labelCount; j++) { + + if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) + break; + + float r = ((mChart.getYChartMax() / labelCount) * j) * factor; + + PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); + + float val = r / factor; + + String label = Utils.formatNumber(val, mYAxis.mDecimals, + mYAxis.isSeparateThousandsEnabled()); + + c.drawText(label, p.x + 10, p.y - 5, mAxisPaint); + } + } + + @Override + public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { + + ArrayList limitLines = mYAxis.getLimitLines(); + + if (limitLines == null) + return; + + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); + + for (int i = 0; i < limitLines.size(); i++) { + + LimitLine l = limitLines.get(i); + + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + + float r = l.getLimit() * factor; + + Path limitPath = new Path(); + + for (int j = 0; j < mChart.getData().getXValCount(); j++) { + + PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); + + if (j == 0) + limitPath.moveTo(p.x, p.y); + else + limitPath.lineTo(p.x, p.y); + } + + limitPath.close(); + + c.drawPath(limitPath, mLimitLinePaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java index 7f5f9bd80d..8fbd76e635 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java @@ -1,25 +1,31 @@ package com.github.mikephil.charting.utils; import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.renderer.ViewPortHandler; public class HorizontalBarChartTransformer extends Transformer { - /** + public HorizontalBarChartTransformer(ViewPortHandler viewPortHandler) { + super(viewPortHandler); + // TODO Auto-generated constructor stub + } + + /** * Prepares the matrix that transforms values to pixels. * * @param chart */ - @Override - public void prepareMatrixValuePx(ChartInterface chart) { - float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); - float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); - - // setup all matrices - mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); - mMatrixValueToPx.postScale(scaleX, -scaleY); - mMatrixValueToPx.postRotate(90, chart.getHeight() / 2, chart.getWidth() / 2); - } +// @Override +// public void prepareMatrixValuePx(ChartInterface chart) { +// float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); +// float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); +// +// // setup all matrices +// mMatrixValueToPx.reset(); +// mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); +// mMatrixValueToPx.postScale(scaleX, -scaleY); +// mMatrixValueToPx.postRotate(90, chart.getHeight() / 2, chart.getWidth() / 2); +// } // /** // * Transforms an arraylist of Entry into a float array containing the x and diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 991fc7734a..3f00259d69 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -3,6 +3,7 @@ import android.content.res.Resources; import android.graphics.Paint; +import android.graphics.PointF; import android.graphics.Rect; import android.util.DisplayMetrics; import android.util.Log; @@ -376,4 +377,21 @@ public static int getClosestDataSetIndex(ArrayList valsAtIndex, float v return index; } + + + /** + * Calculates the position around a center point, depending on the distance + * from the center, and the angle of the position around the center. + * + * @param center + * @param dist + * @param angle in degrees, converted to radians internally + * @return + */ + public static PointF getPosition(PointF center, float dist, float angle) { + + PointF p = new PointF((float) (center.x + dist * Math.cos(Math.toRadians(angle))), + (float) (center.y + dist * Math.sin(Math.toRadians(angle)))); + return p; + } } From ed145616bce33f719940060e7380cfb8e00d4bf7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Feb 2015 17:54:05 +0100 Subject: [PATCH 0068/1390] Did some cleanup. --- .../mikephil/charting/charts/BarChart.java | 22 ++++---- .../charting/charts/BarLineChartBase.java | 44 ++++++++++++--- .../mikephil/charting/charts/Chart.java | 53 ++----------------- .../charting/charts/HorizontalBarChart.java | 40 ++++++-------- .../mikephil/charting/charts/LineChart.java | 1 - .../mikephil/charting/charts/PieChart.java | 6 +++ .../mikephil/charting/charts/RadarChart.java | 17 ++++++ 7 files changed, 92 insertions(+), 91 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 200217104c..e9ec0c792d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -100,17 +100,17 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX += maxEntry * groupSpace; } - protected float getPositiveYOffset(boolean drawAboveValueBar) - { - return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, - "8") * 1.5f); - } - - protected float getNegativeYOffset(boolean drawAboveValueBar) - { - return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils - .convertDpToPixel(5)); - } +// protected float getPositiveYOffset(boolean drawAboveValueBar) +// { +// return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, +// "8") * 1.5f); +// } +// +// protected float getNegativeYOffset(boolean drawAboveValueBar) +// { +// return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils +// .convertDpToPixel(5)); +// } /** * Returns the Highlight object (contains x-index and DataSet index) of the diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b4af7a92f4..b577de4659 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.components.XAxis.XLabelPosition; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YLabelPosition; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; @@ -154,7 +155,7 @@ protected void init() { mAxisRendererLeft = new YAxisRenderer(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); mAxisRendererRight = new YAxisRenderer(mViewPortHandler, mAxisRight, mRightAxisTransformer); - + mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); mListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); @@ -343,7 +344,8 @@ protected void calculateOffsets() { // offsets for y-labels if (mAxisLeft.isEnabled()) { - // calculate the maximum y-label width (including eventual offsets) + // calculate the maximum y-label width (including eventual + // offsets) float ylabelwidth = Utils.calcTextWidth(mAxisRendererLeft.getAxisPaint(), label + (mYChartMin < 0 ? "----" : "+++")); // offsets yleft = ylabelwidth; @@ -351,7 +353,8 @@ protected void calculateOffsets() { if (mAxisRight.isEnabled()) { - // calculate the maximum y-label width (including eventual offsets) + // calculate the maximum y-label width (including eventual + // offsets) float ylabelwidth = Utils.calcTextWidth(mAxisRendererRight.getAxisPaint(), label + (mYChartMin < 0 ? "----" : "+++")); // offsets yright = ylabelwidth; @@ -478,11 +481,38 @@ protected void calcMinMax(boolean fixedValues) { mDeltaY = Math.abs(mYChartMax - mYChartMin); } - /** - * draws the x-axis labels to the screen depending on their position - */ - private void drawXLabels() { + @Override + protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + + float xPos = e.getXIndex(); + + // make sure the marker is in the center of the bars in BarChart and + // CandleStickChart + if (this instanceof CandleStickChart) + xPos += 0.5f; + + else if (this instanceof BarChart) { + + BarData bd = (BarData) mData; + float space = bd.getGroupSpace(); + float j = mData.getDataSetByIndex(dataSetIndex) + .getEntryPosition(e); + + float x = (j * (mData.getDataSetCount() - 1)) + dataSetIndex + space * j + space + / 2f + 0.5f; + + xPos += x; + } + + // position of the marker depends on selected value index and value + float[] pts = new float[] { + xPos, e.getVal() * mAnimator.getPhaseY() + }; + + getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) + .pointValuesToPixel(pts); + return pts; } /** enums for all different border styles */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3165ab8964..0a3e73da89 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -26,9 +26,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; @@ -41,7 +40,6 @@ import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.SelInfo; -import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import com.nineoldandroids.animation.ValueAnimator; @@ -1002,50 +1000,7 @@ protected void drawMarkers() { * @param dataSetIndex * @return */ - private float[] getMarkerPosition(Entry e, int dataSetIndex) { - - float xPos = e.getXIndex(); - - // make sure the marker is in the center of the bars in BarChart and - // CandleStickChart - if (this instanceof CandleStickChart) - xPos += 0.5f; - - else if (this instanceof BarChart) { - - BarData bd = (BarData) mData; - float space = bd.getGroupSpace(); - float j = mData.getDataSetByIndex(dataSetIndex) - .getEntryPosition(e); - - float x = (j * (mData.getDataSetCount() - 1)) + dataSetIndex + space * j + space - / 2f + 0.5f; - - xPos += x; - } else if (this instanceof RadarChart) { - - RadarChart rc = (RadarChart) this; - float angle = rc.getSliceAngle() * e.getXIndex() + rc.getRotationAngle(); - float val = e.getVal() * rc.getFactor(); - PointF c = getCenterOffsets(); - - PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), - (float) (c.y + val * Math.sin(Math.toRadians(angle)))); - - return new float[] { - p.x, p.y - }; - } - - // position of the marker depends on selected value index and value - float[] pts = new float[] { - xPos, e.getVal() * mAnimator.getPhaseY() - }; - - mTrans.pointValuesToPixel(pts); - - return pts; - } + protected abstract float[] getMarkerPosition(Entry e, int dataSetIndex); /** * ################ ################ ################ ################ @@ -2007,7 +1962,7 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - prepareContentRect(); +// prepareContentRect(); for (int i = 0; i < getChildCount(); i++) { getChildAt(i).layout(left, top, right, bottom); } @@ -2032,7 +1987,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { } // prepare content rect and matrices - prepareContentRect(); +// prepareContentRect(); prepare(); super.onSizeChanged(w, h, oldw, oldh); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 20e2d8e402..c208dac4ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -2,14 +2,9 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Rect; import android.util.AttributeSet; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.utils.HorizontalBarChartTransformer; -import com.github.mikephil.charting.utils.Utils; /** * BarChart with horizontal bar orientation. In this implementation, x- and @@ -40,7 +35,6 @@ protected void init() { setDrawXLabels(false); // setDrawYLabels(true); // mTrans = new HorizontalBarChartTransformer(); - mValuePaint.setTextAlign(Paint.Align.LEFT); } /** @@ -116,23 +110,23 @@ protected void init() { // } // } // } - - private static String TALL_VALUE = "100%"; - - @Override - protected float getPositiveYOffset(boolean drawAboveValueBar) - { - Rect bounds = new Rect(); - mValuePaint.getTextBounds(TALL_VALUE, 0, TALL_VALUE.length(), bounds); - - return bounds.height() / 2; - } - - @Override - protected float getNegativeYOffset(boolean drawAboveValueBar) - { - return getPositiveYOffset(drawAboveValueBar); - } +// +// private static String TALL_VALUE = "100%"; +// +// @Override +// protected float getPositiveYOffset(boolean drawAboveValueBar) +// { +// Rect bounds = new Rect(); +// mValuePaint.getTextBounds(TALL_VALUE, 0, TALL_VALUE.length(), bounds); +// +// return bounds.height() / 2; +// } +// +// @Override +// protected float getNegativeYOffset(boolean drawAboveValueBar) +// { +// return getPositiveYOffset(drawAboveValueBar); +// } // /** // * Sets up the y-axis labels. Computes the desired number of labels between diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index a1a4927fbd..df3a6bbf2a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -2,7 +2,6 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 03edc1571b..529b8b0ac5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -149,6 +149,12 @@ protected void calcMinMax(boolean fixedValues) { calcAngles(); } + /** PieChart does not support MarkerView */ + @Override + protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + return new float[0]; + } + /** * calculates the needed angles for the chart slices */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index e62ca0258a..7f44165e87 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -5,12 +5,14 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.renderer.RadarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererRadarChart; @@ -96,6 +98,21 @@ protected void calcMinMax(boolean fixedValues) { mDeltaY = Math.abs(mYChartMax - mYChartMin); } + @Override + protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + + float angle = getSliceAngle() * e.getXIndex() + getRotationAngle(); + float val = e.getVal() * getFactor(); + PointF c = getCenterOffsets(); + + PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), + (float) (c.y + val * Math.sin(Math.toRadians(angle)))); + + return new float[] { + p.x, p.y + }; + } + @Override public void prepare() { super.prepare(); From a3bf07615f470ff9f2c5c946d43c1f51cbf7eba8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Feb 2015 18:01:54 +0100 Subject: [PATCH 0069/1390] Removed all errors from Lib-project. --- .../mikephil/charting/charts/BarChart.java | 2 +- .../charting/charts/BarLineChartBase.java | 2 +- .../charting/charts/PieRadarChartBase.java | 10 ++++---- .../charting/components/LimitLine.java | 4 ++-- .../listener/BarLineChartTouchListener.java | 23 +++++++++++-------- .../charting/renderer/YAxisRenderer.java | 2 +- 6 files changed, 24 insertions(+), 19 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index e9ec0c792d..e353fd8622 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -133,7 +133,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { pts[0] = x; pts[1] = y; - mTrans.pixelsToValue(pts); + mLeftAxisTransformer.pixelsToValue(pts); // for barchart, we only need x-val double xTouchVal = pts[0]; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b577de4659..c99dc80651 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1068,7 +1068,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { pts[0] = x; pts[1] = y; - mTrans.pixelsToValue(pts); + mLeftAxisTransformer.pixelsToValue(pts); double xTouchVal = pts[0]; double yTouchVal = pts[1]; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 0d0942ed71..077cbf40ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -31,7 +31,7 @@ public abstract class PieRadarChartBase Date: Thu, 12 Feb 2015 18:17:24 +0100 Subject: [PATCH 0070/1390] Started fixing the example-project. --- MPChartExample/res/menu/bar.xml | 4 -- .../mpchartexample/AnotherBarActivity.java | 70 ++++++++----------- .../mpchartexample/BarChartActivity.java | 46 ++++-------- .../BarChartActivityMultiDataset.java | 39 ++++------- .../CandleStickChartActivity.java | 23 +++--- .../CubicLineChartActivity.java | 23 +++--- .../mpchartexample/DrawChartActivity.java | 18 +++-- .../DynamicalAddingActivity.java | 1 - .../HorizontalBarChartActivity.java | 34 +++------ .../InvertedLineChartActivity.java | 24 +++---- .../mpchartexample/LineChartActivity1.java | 34 ++++----- .../mpchartexample/LineChartActivity2.java | 28 +++----- .../mpchartexample/MyMarkerView.java | 2 +- 13 files changed, 133 insertions(+), 213 deletions(-) diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index e368c4a3f6..52eadc6458 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -13,10 +13,6 @@ android:id="@+id/actionToggleHighlightArrow" android:title="Toggle Highlight Arrow"> - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index a0572fd002..e746de6525 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -11,14 +11,15 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -46,49 +47,41 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mChart = (BarChart) findViewById(R.id.chart1); - - mChart.setDrawYValues(false); - mChart.setUnit(" €"); mChart.setDescription(""); - - mChart.setDrawYValues(true); // if more than 60 entries are displayed in the chart, no values will be // drawn mChart.setMaxVisibleValueCount(60); - // disable 3D - mChart.set3DEnabled(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); - + mChart.setDrawVerticalGrid(false); mChart.setDrawHorizontalGrid(false); mChart.setDrawGridBackground(false); - XLabels xLabels = mChart.getXLabels(); - xLabels.setPosition(XLabelPosition.BOTTOM); - xLabels.setCenterXLabelText(true); - xLabels.setSpaceBetweenLabels(0); + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setCenterXLabelText(true); + xAxis.setSpaceBetweenLabels(0); - mChart.setDrawYLabels(false); - mChart.setDrawLegend(false); + mChart.setDrawLegend(false); // setting data mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); - + // add a nice and smooth animation mChart.animateY(2500); -// Legend l = mChart.getLegend(); -// l.setPosition(LegendPosition.BELOW_CHART_CENTER); -// l.setFormSize(8f); -// l.setFormToTextSpace(4f); -// l.setXEntrySpace(6f); + // Legend l = mChart.getLegend(); + // l.setPosition(LegendPosition.BELOW_CHART_CENTER); + // l.setFormSize(8f); + // l.setFormToTextSpace(4f); + // l.setXEntrySpace(6f); // mChart.setDrawLegend(false); } @@ -104,18 +97,10 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); - mChart.invalidate(); - break; - } - case R.id.actionToggle3D: { - if (mChart.is3DEnabled()) - mChart.set3DEnabled(false); - else - mChart.set3DEnabled(true); + + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -154,12 +139,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xAxis = mChart.getXAxis(); - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); + if (xAxis.isAdjustXLabelsEnabled()) + xAxis.setAdjustXLabels(false); else - xLabels.setAdjustXLabels(true); + xAxis.setAdjustXLabels(true); mChart.invalidate(); break; @@ -210,19 +195,20 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList yVals1 = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress()+1; i++) { + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { float mult = (mSeekBarY.getProgress() + 1); float val1 = (float) (Math.random() * mult) + mult / 3; yVals1.add(new BarEntry((int) val1, i)); } - + ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress()+1; i++) { - xVals.add((int) yVals1.get(i).getVal() + " " + mChart.getUnit()); + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { + xVals.add((int) yVals1.get(i).getVal() + ""); } BarDataSet set1 = new BarDataSet(yVals1, "Data Set"); set1.setColors(ColorTemplate.VORDIPLOM_COLORS); + set1.setDrawValues(false); ArrayList dataSets = new ArrayList(); dataSets.add(set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 1eeb4b8754..c8275c2ced 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -16,19 +16,20 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; -import com.github.mikephil.charting.utils.YLabels.YLabelPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -55,9 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - - // enable the drawing of values - mChart.setDrawYValues(true); mChart.setDrawValueAboveBar(true); @@ -67,16 +65,11 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // disable 3D - mChart.set3DEnabled(false); - // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); - - mChart.setUnit(" €"); // mChart.setDrawXLabels(false); @@ -94,15 +87,15 @@ protected void onCreate(Bundle savedInstanceState) { Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setPosition(XLabelPosition.BOTTOM); xl.setCenterXLabelText(true); xl.setTypeface(tf); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setLabelCount(8); - yl.setPosition(YLabelPosition.BOTH_SIDED); +// yl.setPosition(YLabelPosition.BOTH_SIDED); mChart.setValueTypeface(tf); @@ -134,18 +127,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); - mChart.invalidate(); - break; - } - case R.id.actionToggle3D: { - if (mChart.is3DEnabled()) - mChart.set3DEnabled(false); - else - mChart.set3DEnabled(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -197,7 +181,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); @@ -288,7 +272,7 @@ public void onValueSelected(Entry e, int dataSetIndex) { return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e); + PointF position = mChart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index b3c1a54327..fb1e912c4f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -13,16 +13,17 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.LargeValueFormatter; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -52,9 +53,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDescription(""); - - // disable the drawing of values - mChart.setDrawYValues(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); @@ -85,11 +83,11 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); l.setTypeface(tf); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setCenterXLabelText(true); xl.setTypeface(tf); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setFormatter(new LargeValueFormatter()); @@ -107,10 +105,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -123,14 +120,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggle3D: { - if (mChart.is3DEnabled()) - mChart.set3DEnabled(false); - else - mChart.set3DEnabled(true); - mChart.invalidate(); - break; - } case R.id.actionToggleHighlight: { if (mChart.isHighlightEnabled()) mChart.setHighlightEnabled(false); @@ -157,12 +146,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xAxis = mChart.getXAxis(); - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); + if (xAxis.isAdjustXLabelsEnabled()) + xAxis.setAdjustXLabels(false); else - xLabels.setAdjustXLabels(true); + xAxis.setAdjustXLabels(true); mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 2af987cd6d..60dd49f9bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -12,13 +12,13 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.CandleStickChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; -import com.github.mikephil.charting.utils.YLabels.YLabelPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -59,16 +59,15 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawVerticalGrid(false); mChart.setDrawGridBackground(false); - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XLabelPosition.BOTTOM); xLabels.setCenterXLabelText(true); xLabels.setSpaceBetweenLabels(2); - YLabels yLabels = mChart.getYLabels(); + YAxis yLabels = mChart.getAxisLeft(); yLabels.setLabelCount(7); - yLabels.setPosition(YLabelPosition.LEFT); +// yLabels.setPosition(YLabelPosition.LEFT); - mChart.setDrawYLabels(true); mChart.setDrawLegend(false); // setting data @@ -121,12 +120,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xAxis = mChart.getXAxis(); - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); + if (xAxis.isAdjustXLabelsEnabled()) + xAxis.setAdjustXLabels(false); else - xLabels.setAdjustXLabels(true); + xAxis.setAdjustXLabels(true); mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index c43a434c27..676635ada2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -13,13 +13,14 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -52,17 +53,12 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); // if enabled, the chart will always start at zero on the y-axis mChart.setStartAtZero(true); - - // disable the drawing of values into the chart - mChart.setDrawYValues(false); - mChart.setDrawBorder(false); mChart.setDrawLegend(false); // no description text mChart.setDescription(""); - mChart.setUnit(" $"); // enable value highlighting mChart.setHighlightEnabled(true); @@ -83,10 +79,10 @@ protected void onCreate(Bundle savedInstanceState) { Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setValueTypeface(tf); - XLabels x = mChart.getXLabels(); + XAxis x = mChart.getXAxis(); x.setTypeface(tf); - YLabels y = mChart.getYLabels(); + YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); y.setLabelCount(5); @@ -110,10 +106,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -196,7 +191,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 4aa36593eb..52aa2990aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -9,14 +9,14 @@ import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.interfaces.OnDrawListener; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -48,7 +48,6 @@ protected void onCreate(Bundle savedInstanceState) { // enable drawing with the finger // mChart.setDrawingEnabled(true); - mChart.setDrawYValues(false); // mChart.setLineWidth(5f); // mChart.setCircleSize(5f); @@ -66,11 +65,11 @@ protected void onCreate(Bundle savedInstanceState) { Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setAvoidFirstLastClipping(true); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); mChart.setValueTypeface(tf); @@ -113,10 +112,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -138,7 +136,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 0fc081710d..fd2b85fb66 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -31,7 +31,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setDrawYValues(false); mChart.setDrawGridBackground(false); mChart.setDescription(""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 8dfc2373bf..c16a74f3c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -7,28 +7,24 @@ import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; -import com.github.mikephil.charting.utils.YLabels.YLabelPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -57,9 +53,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setDrawBarShadow(false); - - // enable the drawing of values - mChart.setDrawYValues(true); mChart.setDrawValueAboveBar(true); @@ -69,16 +62,11 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // disable 3D - mChart.set3DEnabled(false); - // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); - - mChart.setUnit(" €"); // mChart.setDrawXLabels(false); @@ -96,15 +84,15 @@ protected void onCreate(Bundle savedInstanceState) { Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setPosition(XLabelPosition.BOTTOM); xl.setCenterXLabelText(true); xl.setTypeface(tf); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setLabelCount(8); - yl.setPosition(YLabelPosition.BOTH_SIDED); +// yl.setPosition(YLabelPosition.BOTH_SIDED); mChart.setValueTypeface(tf); @@ -290,7 +278,7 @@ public void onValueSelected(Entry e, int dataSetIndex) { return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e); + PointF position = mChart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index b57df88c24..59eca818d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -13,15 +13,16 @@ import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendForm; -import com.github.mikephil.charting.utils.XLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -58,9 +59,6 @@ protected void onCreate(Bundle savedInstanceState) { // if enabled, the chart will always start at zero on the y-axis mChart.setStartAtZero(true); - // enable the drawing of values into the chart - mChart.setDrawYValues(true); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -70,7 +68,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); // invert the y-axis - mChart.setInvertYAxisEnabled(true); + // MAKE THIS RIGHT +// mChart.setInvertYAxisEnabled(true); // enable value highlighting mChart.setHighlightEnabled(true); @@ -99,7 +98,7 @@ protected void onCreate(Bundle savedInstanceState) { // highlighted Entry) mChart.setHighlightIndicatorEnabled(false); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); // add data @@ -133,10 +132,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -207,7 +205,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f204ea9ca4..053a7e3408 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -15,6 +15,12 @@ import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -22,11 +28,6 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendForm; -import com.github.mikephil.charting.utils.LimitLine; -import com.github.mikephil.charting.utils.LimitLine.LimitLabelPosition; -import com.github.mikephil.charting.utils.XLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -61,15 +62,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartGestureListener(this); mChart.setOnChartValueSelectedListener(this); - mChart.setUnit(" $"); - mChart.setDrawUnitsInChart(true); - // if enabled, the chart will always start at zero on the y-axis mChart.setStartAtZero(false); - // disable the drawing of values into the chart - mChart.setDrawYValues(false); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -148,10 +143,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -234,7 +228,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); @@ -352,16 +346,16 @@ private void setData(int count, float range) { ll1.setLineWidth(4f); ll1.enableDashedLine(10f, 10f, 0f); ll1.setDrawValue(true); - ll1.setLabelPosition(LimitLabelPosition.RIGHT); + ll1.setLabelPosition(LimitLabelPosition.POS_RIGHT); LimitLine ll2 = new LimitLine(-30f); ll2.setLineWidth(4f); ll2.enableDashedLine(10f, 10f, 0f); ll2.setDrawValue(true); - ll2.setLabelPosition(LimitLabelPosition.RIGHT); + ll2.setLabelPosition(LimitLabelPosition.POS_RIGHT); - data.addLimitLine(ll1); - data.addLimitLine(ll2); + mChart.getAxisLeft().addLimitLine(ll1); + mChart.getAxisLeft().addLimitLine(ll2); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 733fbc156e..c61d90d141 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -15,6 +15,11 @@ import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -22,10 +27,6 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendForm; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -59,15 +60,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setValueTextColor(Color.WHITE); - mChart.setUnit(" $"); - mChart.setDrawUnitsInChart(true); - // if enabled, the chart will always start at zero on the y-axis mChart.setStartAtZero(false); - // disable the drawing of values into the chart - mChart.setDrawYValues(false); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -112,11 +107,11 @@ protected void onCreate(Bundle savedInstanceState) { l.setTypeface(tf); l.setTextColor(Color.WHITE); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setTextColor(Color.WHITE); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setTextColor(Color.WHITE); } @@ -132,10 +127,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -218,7 +212,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java index 6b4f17aeb6..e9fecf5e00 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java @@ -4,9 +4,9 @@ import android.content.Context; import android.widget.TextView; +import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.MarkerView; import com.github.mikephil.charting.utils.Utils; /** From a84056024c5620615e9ceb93277cf4941004bbdc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Feb 2015 18:32:43 +0100 Subject: [PATCH 0071/1390] Finished applying all changes to the example project. --- .../LineChartActivityColored.java | 17 ++++---- .../ListViewBarChartActivity.java | 10 ++--- .../MultiLineChartActivity.java | 19 ++++----- .../mpchartexample/PieChartActivity.java | 41 ++++++------------ .../mpchartexample/RadarChartActivitry.java | 32 ++++++-------- .../mpchartexample/ScatterChartActivity.java | 23 +++++----- .../mpchartexample/StackedBarActivity.java | 42 ++++++------------- .../fragments/BarChartFrag.java | 8 ++-- .../fragments/ComplexityFragment.java | 8 ++-- .../fragments/PieChartFrag.java | 5 +-- .../fragments/ScatterChartFrag.java | 10 ++--- .../fragments/SineCosineFragment.java | 8 ++-- .../listviewitems/BarChartItem.java | 10 ++--- .../listviewitems/LineChartItem.java | 11 +++-- .../listviewitems/PieChartItem.java | 6 +-- .../charting/charts/BarLineChartBase.java | 12 ++++++ .../mikephil/charting/charts/Chart.java | 36 +++++++++------- .../charting/charts/PieRadarChartBase.java | 12 +++--- 18 files changed, 135 insertions(+), 175 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index d2c00f07bf..321968b46e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -7,13 +7,13 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendForm; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -56,9 +56,6 @@ private void setupChart(LineChart chart, LineData data, int color) { // if enabled, the chart will always start at zero on the y-axis chart.setStartAtZero(true); - // disable the drawing of values into the chart - chart.setDrawYValues(false); - chart.setDrawBorder(false); // no description text @@ -71,7 +68,7 @@ private void setupChart(LineChart chart, LineData data, int color) { // // enable / disable grid background chart.setDrawGridBackground(false); - chart.setGridColor(Color.WHITE & 0x70FFFFFF); +// chart.getRenderer().getGridPaint().setGridColor(Color.WHITE & 0x70FFFFFF); chart.setGridWidth(1.25f); // enable touch gestures @@ -101,12 +98,12 @@ private void setupChart(LineChart chart, LineData data, int color) { l.setTextColor(Color.WHITE); l.setTypeface(mTf); - YLabels y = chart.getYLabels(); + YAxis y = chart.getAxisLeft(); y.setTextColor(Color.WHITE); y.setTypeface(mTf); y.setLabelCount(4); - XLabels x = chart.getXLabels(); + XAxis x = chart.getXAxis(); x.setTextColor(Color.WHITE); x.setTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index b70c355c1c..3462ebd116 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -13,13 +13,13 @@ import android.widget.ListView; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -91,12 +91,12 @@ public View getView(int position, View convertView, ViewGroup parent) { holder.chart.setDrawGridBackground(false); holder.chart.setValueTextColor(Color.WHITE); - XLabels xl = holder.chart.getXLabels(); + XAxis xl = holder.chart.getXAxis(); xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); - YLabels yl = holder.chart.getYLabels(); + YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); yl.setLabelCount(5); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 2d32dd7818..2f47eae94b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -11,6 +11,10 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -18,9 +22,6 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -55,9 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setStartAtZero(true); - // disable the drawing of values into the chart - mChart.setDrawYValues(false); - // enable value highlighting mChart.setHighlightEnabled(true); @@ -89,10 +87,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -162,7 +159,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 6670cd1bb8..26e4e126e2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -12,13 +12,14 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -51,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); // change the color of the center-hole -// mChart.setHoleColor(Color.rgb(235, 235, 235)); + // mChart.setHoleColor(Color.rgb(235, 235, 235)); mChart.setHoleColorTransparent(true); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -63,21 +64,14 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); - mChart.setDrawYValues(true); mChart.setDrawCenterText(true); mChart.setDrawHoleEnabled(true); mChart.setRotationAngle(0); - - // draws the corresponding description value into the slice - mChart.setDrawXValues(true); - // enable rotation of the chart by touch mChart.setRotationEnabled(true); - // display percentage values - mChart.setUsePercentValues(true); // mChart.setUnit(" €"); // mChart.setDrawUnitsInChart(true); @@ -110,18 +104,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); - mChart.invalidate(); - break; - } - case R.id.actionTogglePercent: { - if (mChart.isUsePercentValuesEnabled()) - mChart.setUsePercentValues(false); - else - mChart.setUsePercentValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -142,10 +127,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleXVals: { - if (mChart.isDrawXValuesEnabled()) - mChart.setDrawXValues(false); - else - mChart.setDrawXValues(true); + + mChart.setDrawAxisLabels(!mChart.isDrawAxisLabelsEnabled()); mChart.invalidate(); break; } @@ -199,7 +182,7 @@ private void setData(int count, float range) { PieDataSet set1 = new PieDataSet(yVals1, "Election Results"); set1.setSliceSpace(3f); - + // add a lot of colors ArrayList colors = new ArrayList(); @@ -215,10 +198,10 @@ private void setData(int count, float range) { for (int c : ColorTemplate.LIBERTY_COLORS) colors.add(c); - + for (int c : ColorTemplate.PASTEL_COLORS) colors.add(c); - + colors.add(ColorTemplate.getHoloBlue()); set1.setColors(colors); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 56a8606ce1..dd69c4a624 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -9,15 +9,15 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.LimitLine; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -40,15 +40,11 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setValueTypeface(tf); mChart.setDescription(""); - mChart.setUnit(" $"); - mChart.setDrawUnitsInChart(true); mChart.setWebLineWidth(1.5f); mChart.setWebLineWidthInner(0.75f); mChart.setWebAlpha(100); - mChart.setDrawYValues(false); - // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); @@ -58,15 +54,14 @@ protected void onCreate(Bundle savedInstanceState) { setData(); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setTextSize(9f); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getYAxis(); yl.setTypeface(tf); yl.setLabelCount(5); yl.setTextSize(9f); - yl.setDrawUnitsInYLabel(true); // mChart.animateXY(1500, 1500); @@ -88,10 +83,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -143,10 +137,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleYLabels: { - if (mChart.isDrawYLabelsEnabled()) - mChart.setDrawYLabels(false); - else - mChart.setDrawYLabels(true); + + mChart.getYAxis().setEnabled(!mChart.getYAxis().isEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 58822ea69a..1f3183028b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -13,6 +13,11 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; @@ -20,10 +25,6 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -63,7 +64,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setTouchEnabled(true); mChart.setHighlightEnabled(true); - mChart.setDrawYValues(false); // enable scaling and dragging mChart.setDragEnabled(true); @@ -79,10 +79,10 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.RIGHT_OF_CHART); l.setTypeface(tf); - YLabels yl = mChart.getYLabels(); + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); - XLabels xl = mChart.getXLabels(); + XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); } @@ -97,10 +97,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -131,7 +130,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 892827580d..8e5d97707c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -12,23 +12,22 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; -import com.github.mikephil.charting.utils.YLabels.YLabelPosition; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import java.text.DecimalFormat; import java.util.ArrayList; public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, @@ -57,9 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - // enable the drawing of values - mChart.setDrawYValues(true); - mChart.setDescription(""); // if more than 60 entries are displayed in the chart, no values will be @@ -73,21 +69,18 @@ protected void onCreate(Bundle savedInstanceState) { // if false values are only drawn for the stack sum, else each value is drawn mChart.setDrawValuesForWholeStack(true); - - // disable 3D - mChart.set3DEnabled(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); // change the position of the y-labels - YLabels yLabels = mChart.getYLabels(); - yLabels.setPosition(YLabelPosition.BOTH_SIDED); + YAxis yLabels = mChart.getAxisLeft(); +// yLabels.setPosition(YLabelPosition.BOTH_SIDED); yLabels.setLabelCount(5); yLabels.setFormatter(customFormatter); - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XLabelPosition.TOP); xLabels.setCenterXLabelText(true); @@ -118,18 +111,9 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - if (mChart.isDrawYValuesEnabled()) - mChart.setDrawYValues(false); - else - mChart.setDrawYValues(true); - mChart.invalidate(); - break; - } - case R.id.actionToggle3D: { - if (mChart.is3DEnabled()) - mChart.set3DEnabled(false); - else - mChart.set3DEnabled(true); + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + mChart.invalidate(); break; } @@ -168,7 +152,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleAdjustXLegend: { - XLabels xLabels = mChart.getXLabels(); + XAxis xLabels = mChart.getXAxis(); if (xLabels.isAdjustXLabelsEnabled()) xLabels.setAdjustXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index f664a59d6c..85b2db6572 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -8,8 +8,8 @@ import android.widget.FrameLayout; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; @@ -40,8 +40,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setDrawYValues(false); - mChart.setUnit(" €"); mChart.setDrawBarShadow(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); @@ -51,7 +49,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YLabels labels = mChart.getYLabels(); + YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); // labels.setPosition(YLabelPosition.BOTH_SIDED); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 9611695607..505a111133 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -7,8 +7,8 @@ import android.view.ViewGroup; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.R; @@ -27,14 +27,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart = (LineChart) v.findViewById(R.id.lineChart1); mChart.setDescription(""); - mChart.setDrawYValues(false); mChart.setHighlightIndicatorEnabled(false); mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setDrawYValues(false); mChart.setStartAtZero(false); mChart.setData(getComplexity()); @@ -48,7 +46,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YLabels labels = mChart.getYLabels(); + YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); return v; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index 9ced17ad3f..06dbdcd1a1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -7,8 +7,8 @@ import android.view.ViewGroup; import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; import com.xxmassdeveloper.mpchartexample.R; @@ -31,7 +31,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setValueTypeface(tf); mChart.setCenterTextTypeface(Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf")); - mChart.setUsePercentValues(true); mChart.setCenterText("Quarterly\nRevenue"); mChart.setCenterTextSize(22f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 0f0c2b7234..445dd58423 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -7,8 +7,8 @@ import android.view.ViewGroup; import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; @@ -26,12 +26,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View v = inflater.inflate(R.layout.frag_simple_scatter, container, false); mChart = (ScatterChart) v.findViewById(R.id.scatterChart1); - mChart.setDrawYValues(false); mChart.setDescription(""); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - YLabels labels = mChart.getYLabels(); + YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); @@ -44,8 +43,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setUnit(" $"); - + mChart.setData(generateScatterData(3, 10000, 150)); Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index b954f7d620..b69a312b54 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -7,8 +7,8 @@ import android.view.ViewGroup; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.YLabels; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.R; @@ -27,7 +27,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart = (LineChart) v.findViewById(R.id.lineChart1); mChart.setDescription(""); - mChart.setDrawYValues(false); // mChart.setCircleSize(5f); mChart.setHighlightIndicatorEnabled(false); @@ -35,7 +34,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setDrawYValues(false); mChart.setStartAtZero(false); mChart.setYRange(-1.2f, 1.2f, false); @@ -51,7 +49,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YLabels labels = mChart.getYLabels(); + YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); return v; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index e6def5964f..6d36172d39 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -6,11 +6,11 @@ import android.view.View; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.R; public class BarChartItem extends ChartItem { @@ -54,12 +54,12 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDrawGridBackground(false); holder.chart.setDrawBarShadow(false); - XLabels xl = holder.chart.getXLabels(); + XAxis xl = holder.chart.getXAxis(); xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); - YLabels yl = holder.chart.getYLabels(); + YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); yl.setLabelCount(5); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index ad530d226d..6c5c984c5a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -7,11 +7,11 @@ import android.view.View; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.utils.XLabels; -import com.github.mikephil.charting.utils.XLabels.XLabelPosition; -import com.github.mikephil.charting.utils.YLabels; import com.xxmassdeveloper.mpchartexample.R; public class LineChartItem extends ChartItem { @@ -50,17 +50,16 @@ public View getView(int position, View convertView, Context c) { // apply styling // holder.chart.setValueTypeface(mTf); - holder.chart.setDrawYValues(false); holder.chart.setDescription(""); holder.chart.setDrawVerticalGrid(false); holder.chart.setDrawGridBackground(false); - XLabels xl = holder.chart.getXLabels(); + XAxis xl = holder.chart.getXAxis(); xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); - YLabels yl = holder.chart.getYLabels(); + YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); yl.setLabelCount(5); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 1b5cf29871..859b67d404 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -7,10 +7,10 @@ import android.view.View; import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.utils.Legend; -import com.github.mikephil.charting.utils.Legend.LegendPosition; import com.xxmassdeveloper.mpchartexample.R; public class PieChartItem extends ChartItem { @@ -55,8 +55,6 @@ public View getView(int position, View convertView, Context c) { holder.chart.setCenterText("MPChart\nAndroid"); holder.chart.setCenterTextTypeface(mTf); holder.chart.setCenterTextSize(18f); - holder.chart.setDrawXValues(false); - holder.chart.setUsePercentValues(true); // set data holder.chart.setData((PieData) mChartData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c99dc80651..d82b2e8b4c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1311,6 +1311,18 @@ public void setDragOffsetY(float offset) { public boolean hasNoDragOffset() { return mViewPortHandler.hasNoDragOffset(); } + + public XAxisRenderer getRendererXAxis() { + return mXAxisRenderer; + } + + public YAxisRenderer getRendererLeftYAxis() { + return mAxisRendererLeft; + } + + public YAxisRenderer getRendererRightYAxis() { + return mAxisRendererRight; + } /** * returns the filtered ChartData object depending on approximator settings, diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 0a3e73da89..9a7128c01d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -89,7 +89,7 @@ public abstract class Chart Date: Fri, 13 Feb 2015 11:06:28 +0100 Subject: [PATCH 0072/1390] Did some bugfixing. --- .../mikephil/charting/charts/BarChart.java | 158 +++++++++--------- .../charting/charts/BarLineChartBase.java | 62 ++++--- .../mikephil/charting/charts/Chart.java | 17 +- .../mikephil/charting/charts/RadarChart.java | 2 + .../mikephil/charting/components/XAxis.java | 2 +- .../charting/renderer/ViewPortHandler.java | 9 + .../charting/renderer/XAxisRenderer.java | 4 +- .../renderer/XAxisRendererBarChart.java | 4 +- .../charting/renderer/YAxisRenderer.java | 22 ++- .../mikephil/charting/utils/Transformer.java | 28 ++-- 10 files changed, 185 insertions(+), 123 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index e353fd8622..8884d95505 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; @@ -27,14 +28,14 @@ */ public class BarChart extends BarLineChartBase { -// /** indicates the angle of the 3d effect */ -// private float mSkew = 0.3f; -// -// /** indicates how much the 3d effect goes back */ -// private float mDepth = 0.3f; -// -// /** flag the enables or disables 3d bars */ -// private boolean m3DEnabled = false; + // /** indicates the angle of the 3d effect */ + // private float mSkew = 0.3f; + // + // /** indicates how much the 3d effect goes back */ + // private float mDepth = 0.3f; + // + // /** flag the enables or disables 3d bars */ + // private boolean m3DEnabled = false; /** flag that enables or disables the highlighting arrow */ private boolean mDrawHighlightArrow = false; @@ -73,7 +74,9 @@ public BarChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); - mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); + mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, + this); } @Override @@ -100,17 +103,19 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX += maxEntry * groupSpace; } -// protected float getPositiveYOffset(boolean drawAboveValueBar) -// { -// return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, -// "8") * 1.5f); -// } -// -// protected float getNegativeYOffset(boolean drawAboveValueBar) -// { -// return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils -// .convertDpToPixel(5)); -// } + // protected float getPositiveYOffset(boolean drawAboveValueBar) + // { + // return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : + // Utils.calcTextHeight(mValuePaint, + // "8") * 1.5f); + // } + // + // protected float getNegativeYOffset(boolean drawAboveValueBar) + // { + // return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * + // 1.5f : -Utils + // .convertDpToPixel(5)); + // } /** * Returns the Highlight object (contains x-index and DataSet index) of the @@ -197,62 +202,63 @@ public RectF getBarBounds(BarEntry e) { return bounds; } -// /** -// * sets the skew (default 0.3f), the skew indicates how much the 3D effect -// * of the chart is turned to the right -// * -// * @param skew -// */ -// public void setSkew(float skew) { -// this.mSkew = skew; -// } -// -// /** -// * returns the skew value that indicates how much the 3D effect is turned to -// * the right -// * -// * @return -// */ -// public float getSkew() { -// return mSkew; -// } -// -// /** -// * set the depth of the chart (default 0.3f), the depth indicates how much -// * the 3D effect of the chart goes back -// * -// * @param depth -// */ -// public void setDepth(float depth) { -// this.mDepth = depth; -// } -// -// /** -// * returhs the depth, which indicates how much the 3D effect goes back -// * -// * @return -// */ -// public float getDepth() { -// return mDepth; -// } -// -// /** -// * if enabled, chart will be drawn in 3d -// * -// * @param enabled -// */ -// public void set3DEnabled(boolean enabled) { -// this.m3DEnabled = enabled; -// } -// -// /** -// * returns true if 3d bars is enabled, false if not -// * -// * @return -// */ -// public boolean is3DEnabled() { -// return m3DEnabled; -// } + // /** + // * sets the skew (default 0.3f), the skew indicates how much the 3D effect + // * of the chart is turned to the right + // * + // * @param skew + // */ + // public void setSkew(float skew) { + // this.mSkew = skew; + // } + // + // /** + // * returns the skew value that indicates how much the 3D effect is turned + // to + // * the right + // * + // * @return + // */ + // public float getSkew() { + // return mSkew; + // } + // + // /** + // * set the depth of the chart (default 0.3f), the depth indicates how much + // * the 3D effect of the chart goes back + // * + // * @param depth + // */ + // public void setDepth(float depth) { + // this.mDepth = depth; + // } + // + // /** + // * returhs the depth, which indicates how much the 3D effect goes back + // * + // * @return + // */ + // public float getDepth() { + // return mDepth; + // } + // + // /** + // * if enabled, chart will be drawn in 3d + // * + // * @param enabled + // */ + // public void set3DEnabled(boolean enabled) { + // this.m3DEnabled = enabled; + // } + // + // /** + // * returns true if 3d bars is enabled, false if not + // * + // * @return + // */ + // public boolean is3DEnabled() { + // return m3DEnabled; + // } /** * set this to true to draw the highlightning arrow diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d82b2e8b4c..bed8dbe9db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -14,14 +14,11 @@ import android.util.Log; import android.view.MotionEvent; -import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; @@ -117,11 +114,11 @@ public abstract class BarLineChartBase 0 && h > 0 && w < 10000 && h < 10000) { // create a new bitmap with the new dimensions mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); mDrawCanvas = new Canvas(mDrawBitmap); - mViewPortHandler = new ViewPortHandler(w, h); + mViewPortHandler.setChartDimens(w, h); + + if (mLogEnabled) + Log.i(LOG_TAG, "Setting chart dimens, width: " + w + ", height: " + h); } // prepare content rect and matrices diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 7f44165e87..8edb0e7d48 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -73,6 +73,8 @@ public RadarChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + mYAxis = new YAxis(AxisDependency.LEFT); + mXAxis = new XAxis(); mXAxis.setSpaceBetweenLabels(0); mWebLineWidth = Utils.convertDpToPixel(1.5f); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 2299e43e48..b931fefc74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -38,7 +38,7 @@ public class XAxis extends AxisBase { * array(list) for the x-axis-labels is drawn or not. If index % modulus == * 0 DRAW, else dont draw. */ - public int mXAxisLabelModulus = 1; + public int mAxisLabelModulus = 1; /** * the modulus that indicates if a value at a specified index in an diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index 4272f96f65..621db217cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -37,12 +37,21 @@ public class ViewPortHandler { /** offset that allows the chart to be dragged over its bounds on the x-axis */ private float mTransOffsetY = 0f; + + public ViewPortHandler() { + + } public ViewPortHandler(float width, float height) { mChartHeight = height; mChartWidth = width; } + public void setChartDimens(float width, float height) { + mChartHeight = height; + mChartWidth = width; + } + public void restrainViewPort(float offsetLeft, float offsetTop, float offsetRight, float offsetBottom) { mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight - offsetBottom); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 8e6dbdc9b1..9c3078f70e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -87,7 +87,7 @@ protected void drawLabels(Canvas c, float yPos) { 0f, 0f }; - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i; @@ -138,7 +138,7 @@ public void renderGridLines(Canvas c) { mGridPaint.setColor(mXAxis.getGridColor()); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 76f7fb03e7..48507ce45d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -36,7 +36,7 @@ protected void drawLabels(Canvas c, float yPos) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; @@ -90,7 +90,7 @@ public void renderGridLines(Canvas c) { // take into consideration that multiple DataSets increase mDeltaX int step = bd.getDataSetCount(); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mXAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 8b0018c750..4280bcdc8b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -26,6 +26,8 @@ public class YAxisRenderer extends AxisRenderer { protected YAxis mYAxis; + protected float mXOffset = 5f; + public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { super(viewPortHandler, trans); @@ -38,6 +40,24 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mLimitLinePaint.setStyle(Paint.Style.STROKE); } + /** + * Returns the used offset on the x-axis for drawing the axis labels. + * + * @return + */ + public float getXOffset() { + return Utils.convertDpToPixel(mXOffset); + } + + /** + * Sets the used offset for the labels on the x-axis. + * + * @param xOffset + */ + public void setXOffset(float xOffset) { + mXOffset = xOffset; + } + public void computeAxis(ChartInterface chart) { float yMin = 0f; @@ -173,7 +193,7 @@ public void renderAxis(Canvas c) { mAxisPaint.setTextSize(mYAxis.getTextSize()); mAxisPaint.setColor(mYAxis.getTextColor()); - float xoffset = Utils.convertDpToPixel(5f); + float xoffset = getXOffset(); float yoffset = Utils.calcTextHeight(mAxisPaint, "A") / 2.5f; AxisDependency dependency = mYAxis.getAxisDependency(); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index d6fc10f1f6..f7bdccd02b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -40,7 +40,7 @@ public Transformer(ViewPortHandler viewPortHandler) { */ public void prepareMatrixValuePx(ViewPortHandler viewport, float deltaX, float deltaY, float yChartMin) { - float scaleX = (float) ((viewport.getChartWidth() - viewport.contentRight() - viewport.offsetLeft()) / deltaX); + float scaleX = (float) ((viewport.getChartWidth() - viewport.offsetRight() - viewport.offsetLeft()) / deltaX); float scaleY = (float) ((viewport.getChartHeight() - viewport.offsetTop() - viewport.offsetBottom()) / deltaY); // setup all matrices @@ -49,19 +49,19 @@ public void prepareMatrixValuePx(ViewPortHandler viewport, float deltaX, float d mMatrixValueToPx.postScale(scaleX, -scaleY); } - /** - * Prepares the transformation matrix with the specified scales. - * - * @param chart - * @param scaleX - * @param scaleY - */ - public void prepareMatrixValuePx(ChartInterface chart, float scaleX, float scaleY) { - - mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); - mMatrixValueToPx.postScale(scaleX, -scaleY); - } +// /** +// * Prepares the transformation matrix with the specified scales. +// * +// * @param chart +// * @param scaleX +// * @param scaleY +// */ +// public void prepareMatrixValuePx(ChartInterface chart, float scaleX, float scaleY) { +// +// mMatrixValueToPx.reset(); +// mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); +// mMatrixValueToPx.postScale(scaleX, -scaleY); +// } /** * Prepares the matrix that contains all offsets. From 7beee61c22961c883027d48bb8a0139059d1ddfe Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 13 Feb 2015 18:03:06 +0100 Subject: [PATCH 0073/1390] Worked on dual-axis support. --- .../mpchartexample/AnotherBarActivity.java | 8 +- .../mpchartexample/BarChartActivity.java | 7 +- .../BarChartActivityMultiDataset.java | 7 +- .../CandleStickChartActivity.java | 7 +- .../CubicLineChartActivity.java | 9 +- .../mpchartexample/DrawChartActivity.java | 9 +- .../InvertedLineChartActivity.java | 10 +- .../mpchartexample/LineChartActivity1.java | 10 +- .../mpchartexample/LineChartActivity2.java | 10 +- .../LineChartActivityColored.java | 4 - .../MultiLineChartActivity.java | 7 +- .../mpchartexample/ScatterChartActivity.java | 7 +- .../mpchartexample/StackedBarActivity.java | 7 +- .../fragments/ComplexityFragment.java | 1 - .../fragments/SineCosineFragment.java | 3 +- .../charting/charts/BarLineChartBase.java | 348 +++++++++++------- .../mikephil/charting/charts/Chart.java | 70 +--- .../mikephil/charting/charts/LineChart.java | 2 +- .../mikephil/charting/charts/PieChart.java | 6 - .../charting/charts/PieRadarChartBase.java | 5 + .../mikephil/charting/charts/RadarChart.java | 34 +- .../mikephil/charting/components/YAxis.java | 52 +++ .../mikephil/charting/data/ChartData.java | 101 +++++ .../charting/interfaces/ChartInterface.java | 8 +- .../charting/renderer/YAxisRenderer.java | 35 +- .../renderer/YAxisRendererRadarChart.java | 2 +- 26 files changed, 448 insertions(+), 321 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index e746de6525..4a4b4b9f51 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -130,11 +130,9 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index c8275c2ced..567687072c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -159,11 +159,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index fb1e912c4f..b9b212db9b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -137,11 +137,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 60dd49f9bc..7649e003e6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -111,11 +111,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 676635ada2..233c99781d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -52,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); // if enabled, the chart will always start at zero on the y-axis - mChart.setStartAtZero(true); + mChart.setDrawBorder(false); mChart.setDrawLegend(false); @@ -161,11 +161,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 52aa2990aa..74e976e54a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -74,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setValueTypeface(tf); - mChart.setYRange(-40f, 40f, true); +// mChart.setYRange(-40f, 40f, true); // call this to reset the changed y-range // mChart.resetYRange(true); } @@ -127,11 +127,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 59eca818d1..d1fa310fda 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -56,9 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - // if enabled, the chart will always start at zero on the y-axis - mChart.setStartAtZero(true); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -174,11 +171,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 053a7e3408..03719f5e00 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -62,9 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartGestureListener(this); mChart.setOnChartValueSelectedListener(this); - // if enabled, the chart will always start at zero on the y-axis - mChart.setStartAtZero(false); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -198,11 +195,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index c61d90d141..2b09bba19a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -60,9 +60,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setValueTextColor(Color.WHITE); - // if enabled, the chart will always start at zero on the y-axis - mChart.setStartAtZero(false); - mChart.setDrawBorder(true); mChart.setBorderPositions(new BorderPosition[] { BorderPosition.BOTTOM @@ -182,11 +179,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 321968b46e..04abb590a8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -52,10 +52,6 @@ protected void onCreate(Bundle savedInstanceState) { }; private void setupChart(LineChart chart, LineData data, int color) { - - // if enabled, the chart will always start at zero on the y-axis - chart.setStartAtZero(true); - chart.setDrawBorder(false); // no description text diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 2f47eae94b..95a6986cd5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -150,11 +150,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 1f3183028b..86341c9801 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -121,11 +121,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 8e5d97707c..1be97dd5f6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -143,11 +143,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleStartzero: { - if (mChart.isStartAtZeroEnabled()) - mChart.setStartAtZero(false); - else - mChart.setStartAtZero(true); - + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 505a111133..048ac788fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -33,7 +33,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setStartAtZero(false); mChart.setData(getComplexity()); mChart.animateX(3000); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index b69a312b54..baa60a8d30 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -34,9 +34,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawGridBackground(false); mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); - mChart.setStartAtZero(false); - mChart.setYRange(-1.2f, 1.2f, false); +// mChart.setYRange(-1.2f, 1.2f, false); mChart.setData(generateLineData()); mChart.animateX(3000); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index bed8dbe9db..2e03982fae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -68,12 +68,6 @@ public abstract class BarLineChartBase 0 ? mData.getYMax() : 1.0; - double range = max - mYChartMin; + double range = max - mYAxis.mAxisMinimum; double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -179,7 +179,7 @@ private void prepareYLabels() { interval = Math.floor(10 * intervalMagnitude); } - double first = Math.ceil(mYChartMin / interval) * interval; + double first = Math.ceil(mYAxis.mAxisMinimum / interval) * interval; double last = Utils.nextUp(Math.floor(max / interval) * interval); double f; @@ -190,10 +190,10 @@ private void prepareYLabels() { mYAxis.mEntryCount = n; - mYChartMax = (float) interval * n; + mYAxis.mAxisMaximum = (float) interval * n; // calc delta - mDeltaY = Math.abs(mYChartMax - mYChartMin); +// mDeltaY = Math.abs(mYChartMax - mYChartMin); } /** @@ -204,7 +204,7 @@ private void prepareYLabels() { public float getFactor() { RectF content = mViewPortHandler.getContentRect(); return (float) Math.min(content.width() / 2, content.height() / 2) - / mYChartMax; + / mYAxis.mAxisMaximum; } /** @@ -369,6 +369,14 @@ public float getRadius() { RectF content = mViewPortHandler.getContentRect(); return Math.min(content.width() / 2f, content.height() / 2f); } + + public float getYChartMax() { + return mYAxis.mAxisMaximum; + } + + public float getYChartMin() { + return mYAxis.mAxisMinimum; + } @Override public void setPaint(Paint p, int which) { @@ -394,10 +402,4 @@ public Paint getPaint(int which) { return null; } - - @Override - public boolean isStartAtZeroEnabled() { - // TODO Auto-generated method stub - return false; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 6efe60ad8d..ab1a426182 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -43,11 +43,21 @@ public class YAxis extends AxisBase { /** flag that indicates if the axis is inverted or not */ protected boolean mInverted = false; + /** if true, the y-label entries will always start at zero */ + protected boolean mStartAtZero = true; + /** the formatter used to customly format the y-labels */ private ValueFormatter mFormatter = null; private ArrayList mLimitLines; + protected float mCustomAxisMin = Float.NaN; + + protected float mCustomAxisMax = Float.NaN; + + public float mAxisMaximum = 0f; + public float mAxisMinimum = 0f; + /** the position of the y-labels relative to the chart */ private YLabelPosition mPosition = YLabelPosition.OUTSIDE_CHART; @@ -225,6 +235,24 @@ public boolean isInverted() { return mInverted; } + /** + * enable this to force the y-axis labels to always start at zero + * + * @param enabled + */ + public void setStartAtZero(boolean enabled) { + this.mStartAtZero = enabled; + } + + /** + * returns true if the chart is set to start at zero, false otherwise + * + * @return + */ + public boolean isStartAtZeroEnabled() { + return mStartAtZero; + } + /** * Adds a new LimitLine to this axis. * @@ -259,6 +287,30 @@ public ArrayList getLimitLines() { return mLimitLines; } + public float getAxisMinValue() { + return mCustomAxisMin; + } + + public void setAxisMinValue(float min) { + mCustomAxisMin = min; + } + + public void resetAxisMinValue() { + mCustomAxisMin = Float.NaN; + } + + public float getAxisMaxValue() { + return mCustomAxisMax; + } + + public void setAxisMaxValue(float max) { + mCustomAxisMax = max; + } + + public void resetAxisMaxValue() { + mCustomAxisMax = Float.NaN; + } + /** * Returns the longest formatted label (in terms of characters) the y-labels * contain. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 534bf65ce3..7f33a1bfa0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -3,6 +3,7 @@ import android.util.Log; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.Highlight; import java.util.ArrayList; @@ -21,6 +22,14 @@ public abstract class ChartData> { /** the minimum y-value in the y-value array */ protected float mYMin = 0.0f; + protected float mLeftAxisMax = 0.0f; + + protected float mLeftAxisMin = 0.0f; + + protected float mRightAxisMax = 0.0f; + + protected float mRightAxisMin = 0.0f; + /** the total sum of all y-values */ private float mYValueSum = 0f; @@ -183,6 +192,7 @@ protected void calcMinMax(ArrayList dataSets) { mYMin = 0f; } else { + // calculate absolute min and max mYMin = dataSets.get(0).getYMin(); mYMax = dataSets.get(0).getYMax(); @@ -193,6 +203,53 @@ protected void calcMinMax(ArrayList dataSets) { if (dataSets.get(i).getYMax() > mYMax) mYMax = dataSets.get(i).getYMax(); } + + // left axis + T firstLeft = getFirstLeft(); + + if (firstLeft != null) { + + mLeftAxisMax = firstLeft.getYMax(); + mLeftAxisMin = firstLeft.getYMin(); + + for (T dataSet : dataSets) { + if (dataSet.getAxisDependency() == AxisDependency.LEFT) { + if (dataSet.getYMin() < mLeftAxisMin) + mLeftAxisMin = dataSet.getYMin(); + + if (dataSet.getYMax() > mLeftAxisMax) + mLeftAxisMax = dataSet.getYMax(); + } + } + } + + // right axis + T firstRight = getFirstLeft(); + + if (firstRight != null) { + + mRightAxisMax = firstRight.getYMax(); + mRightAxisMin = firstRight.getYMin(); + + for (T dataSet : dataSets) { + if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { + if (dataSet.getYMin() < mRightAxisMin) + mRightAxisMin = dataSet.getYMin(); + + if (dataSet.getYMax() > mRightAxisMax) + mRightAxisMax = dataSet.getYMax(); + } + } + } + + // in case there is only one axis, adjust the second axis + if (firstLeft == null) { + mLeftAxisMax = mRightAxisMax; + mLeftAxisMin = mRightAxisMin; + } else { + mRightAxisMax = mLeftAxisMax; + mRightAxisMin = mLeftAxisMin; + } } } @@ -254,6 +311,19 @@ public int getDataSetCount() { public float getYMin() { return mYMin; } + + /** + * Returns the minimum y-value for the specified axis. + * + * @param axis + * @return + */ + public float getYMin(AxisDependency axis) { + if (axis == AxisDependency.LEFT) + return mLeftAxisMin; + else + return mRightAxisMin; + } /** * Returns the greatest y-value the data object contains. @@ -264,6 +334,19 @@ public float getYMax() { return mYMax; } + /** + * Returns the maximum y-value for the specified axis. + * + * @param axis + * @return + */ + public float getYMax(AxisDependency axis) { + if (axis == AxisDependency.LEFT) + return mLeftAxisMax; + else + return mRightAxisMax; + } + /** * returns the average length (in characters) across all values in the * x-vals array @@ -655,6 +738,24 @@ public int getIndexOfDataSet(T dataSet) { return -1; } + private T getFirstLeft() { + for (T dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.LEFT) + return dataSet; + } + + return null; + } + + private T getFirstRight() { + for (T dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.RIGHT) + return dataSet; + } + + return null; + } + /** * Generates an x-values array filled with numbers in range specified by the * parameters. Can be used for convenience. diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index a39de7d9ba..daf7de0114 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -23,17 +23,17 @@ public interface ChartInterface { public float getDeltaX(); - public float getDeltaY(); +// public float getDeltaY(); - public float getYChartMin(); +// public float getYChartMin(); - public float getYChartMax(); +// public float getYChartMax(); public int getWidth(); public int getHeight(); - public boolean isStartAtZeroEnabled(); +// public boolean isStartAtZeroEnabled(); public PointF getCenterOfView(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 4280bcdc8b..cebdce9ba8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -58,10 +58,12 @@ public void setXOffset(float xOffset) { mXOffset = xOffset; } - public void computeAxis(ChartInterface chart) { - - float yMin = 0f; - float yMax = 0f; + /** + * Computes the axis values. + * @param yMin - the minimum y-value in the data object for this axis + * @param yMax - the maximum y-value in the data object for this axis + */ + public void computeAxis(float yMin, float yMax) { // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) @@ -77,7 +79,7 @@ public void computeAxis(ChartInterface chart) { yMax = (float) p1.y; } else { - if (!chart.isStartAtZeroEnabled()) + if (!mYAxis.isStartAtZeroEnabled()) yMin = (float) Math.min(p1.y, p2.y); else yMin = 0; @@ -85,19 +87,24 @@ public void computeAxis(ChartInterface chart) { } } else { - - if (!mYAxis.isInverted()) { - yMin = chart.getYChartMin(); - yMax = chart.getYChartMax(); + + // in case a custom maximum is set + if(!Float.isNaN(mYAxis.getAxisMaxValue())) { + yMax = mYAxis.getAxisMaxValue(); + } + + // in case a custom minimum is set + if(!Float.isNaN(mYAxis.getAxisMinValue())) { + yMin = mYAxis.getAxisMinValue(); } else { - - if (!chart.isStartAtZeroEnabled()) - yMin = (float) Math.min(chart.getYChartMax(), chart.getYChartMin()); - else + if (mYAxis.isStartAtZeroEnabled()) { yMin = 0; - yMax = (float) Math.max(chart.getYChartMax(), chart.getYChartMin()); + } } } + + mYAxis.mAxisMaximum = yMax; + mYAxis.mAxisMinimum = yMin; computeAxisValues(yMin, yMax); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 089d2ced42..0db36fba68 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -24,7 +24,7 @@ public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, Rad } @Override - public void computeAxis(ChartInterface chart) { + public void computeAxis(float yMin, float yMax) { } From 0ab6605e4267023e445a533eabb8db43d26f2ded Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 13 Feb 2015 22:07:24 +0100 Subject: [PATCH 0074/1390] More bugfixes, still some issues with axis. --- .../charting/charts/BarLineChartBase.java | 67 ++++++++----------- .../mikephil/charting/charts/Chart.java | 11 +-- .../charting/charts/PieRadarChartBase.java | 8 +-- .../mikephil/charting/charts/RadarChart.java | 5 +- .../charting/charts/ScatterChart.java | 2 +- .../mikephil/charting/components/YAxis.java | 24 ++++++- .../renderer/ScatterChartRenderer.java | 4 ++ .../charting/renderer/YAxisRenderer.java | 9 +-- .../mikephil/charting/utils/Transformer.java | 47 +++++++------ 9 files changed, 90 insertions(+), 87 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 2e03982fae..d4cdfc63b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -254,13 +254,25 @@ protected void onDraw(Canvas canvas) { Log.i(LOG_TAG, "DrawTime: " + (System.currentTimeMillis() - starttime) + " ms"); } - /** - * does all necessary preparations, needed when data is changed or flags - * that effect the data are changed - */ - @Override - public void prepare() { + private void prepareValuePxMatrix() { + if(mLogEnabled) Log.i(LOG_TAG, "Preparing Value-Px Matrix, deltaLeft: " + mDeltaYLeft + ", deltaRight: " + mDeltaYRight); + + mRightAxisTransformer.prepareMatrixValuePx(mDeltaX, mDeltaYRight, + mAxisRight.mAxisMinimum); + mLeftAxisTransformer.prepareMatrixValuePx(mDeltaX, mDeltaYLeft, + mAxisLeft.mAxisMinimum); + } + + protected void prepareOffsetMatrix() { + + mRightAxisTransformer.prepareMatrixOffset(mAxisRight.isInverted()); + mLeftAxisTransformer.prepareMatrixOffset(mAxisLeft.isInverted()); + } + + @Override + public void notifyDataSetChanged() { + if (mDataNotSet) { if (mLogEnabled) Log.i(LOG_TAG, "Preparing... DATA NOT SET."); @@ -269,9 +281,9 @@ public void prepare() { if (mLogEnabled) Log.i(LOG_TAG, "Preparing..."); } - + calcMinMax(false); - + float minLeft = mData.getYMin(AxisDependency.LEFT); float maxLeft = mData.getYMax(AxisDependency.LEFT); float minRight = mData.getYMin(AxisDependency.RIGHT); @@ -284,36 +296,7 @@ public void prepare() { prepareLegend(); - calculateOffsets(); - } - - /** - * Sets up all the matrices that will be used for scaling the coordinates to - * the display. Offset and Value-px. - */ - protected void prepareMatrix() { - - mRightAxisTransformer.prepareMatrixValuePx(mViewPortHandler, mDeltaX, mDeltaYRight, - mAxisRight.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mViewPortHandler, mDeltaX, mDeltaYLeft, - mAxisLeft.mAxisMinimum); - - mRightAxisTransformer.prepareMatrixOffset(mViewPortHandler, mAxisRight.isInverted()); - mLeftAxisTransformer.prepareMatrixOffset(mViewPortHandler, mAxisLeft.isInverted()); - - if (mLogEnabled) - Log.i(LOG_TAG, "Matrices prepared."); - } - - @Override - public void notifyDataSetChanged() { - prepare(); - // prepareContentRect(); - mRightAxisTransformer.prepareMatrixValuePx(mViewPortHandler, mDeltaX, mDeltaYRight, - mAxisRight.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mViewPortHandler, mDeltaX, mDeltaYLeft, - mAxisLeft.mAxisMinimum); - + calculateOffsets(); } @Override @@ -424,7 +407,8 @@ protected void calculateOffsets() { Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); } - prepareMatrix(); + prepareOffsetMatrix(); + prepareValuePxMatrix(); } /** @@ -479,6 +463,11 @@ protected void calcMinMax(boolean fixedValues) { mDeltaX = mData.getXVals().size() - 1; mDeltaYLeft = Math.abs(maxLeft - minLeft); mDeltaYRight = Math.abs(maxRight - minRight); + + mAxisLeft.mAxisMaximum = maxLeft; + mAxisRight.mAxisMaximum = maxRight; + mAxisLeft.mAxisMinimum = minLeft; + mAxisRight.mAxisMinimum = minRight; // // only calculate values if not fixed values // if (!fixedValues) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 00a0329f2e..3834bcbfaa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -279,7 +279,7 @@ public void setData(T data) { mData = data; mData = data; - prepare(); + notifyDataSetChanged(); // calculate how many digits are needed calcFormats(data.getYMin(), data.getYMax()); @@ -316,12 +316,7 @@ public boolean isEmpty() { return false; } } - - /** - * does needed preparations for drawing - */ - public abstract void prepare(); - + /** * Lets the chart know its underlying data has changed and performs all * necessary recalculations. @@ -1955,7 +1950,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { // prepare content rect and matrices // prepareContentRect(); - prepare(); + notifyDataSetChanged(); super.onSizeChanged(w, h, oldw, oldh); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 2784c3ff55..c45408003e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -70,8 +70,7 @@ public boolean onTouchEvent(MotionEvent event) { } @Override - public void prepare() { - + public void notifyDataSetChanged() { if (mDataNotSet) return; @@ -82,11 +81,6 @@ public void prepare() { calculateOffsets(); } - @Override - public void notifyDataSetChanged() { - prepare(); - } - @Override protected void calculateOffsets() { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index a6fb45c0b1..03b75959e4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -116,9 +116,8 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { } @Override - public void prepare() { - super.prepare(); - + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); mYAxisRenderer.computeAxis(0f, 0f); prepareYLabels(); mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index b43e7e0904..390fb163cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -48,7 +48,7 @@ protected void calculateOffsets() { mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, mViewPortHandler.offsetBottom()); - prepareMatrix(); + prepareOffsetMatrix(); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index ab1a426182..07e5f13294 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -54,7 +54,7 @@ public class YAxis extends AxisBase { protected float mCustomAxisMin = Float.NaN; protected float mCustomAxisMax = Float.NaN; - + public float mAxisMaximum = 0f; public float mAxisMinimum = 0f; @@ -291,10 +291,21 @@ public float getAxisMinValue() { return mCustomAxisMin; } + /** + * Set a custom minimum value for this axis. If set, this value will not be + * calculated automatically depending on the provided data. Use + * resetAxisMinValue() to undo this. + * + * @param min + */ public void setAxisMinValue(float min) { mCustomAxisMin = min; } + /** + * By calling this method, any custom minimum value that has been previously + * set is reseted, and the calculation is done automatically. + */ public void resetAxisMinValue() { mCustomAxisMin = Float.NaN; } @@ -303,10 +314,21 @@ public float getAxisMaxValue() { return mCustomAxisMax; } + /** + * Set a custom maximum value for this axis. If set, this value will not be + * calculated automatically depending on the provided data. Use + * resetAxisMaxValue() to undo this. + * + * @param max + */ public void setAxisMaxValue(float max) { mCustomAxisMax = max; } + /** + * By calling this method, any custom maximum value that has been previously + * set is reseted, and the calculation is done automatically. + */ public void resetAxisMaxValue() { mCustomAxisMax = Float.NaN; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index fee356817d..397a52d3b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -122,6 +122,10 @@ public void drawValues(Canvas c) { for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { ScatterDataSet dataSet = dataSets.get(i); + + if (!dataSet.isDrawValuesEnabled()) + continue; + ArrayList entries = dataSet.getYVals(); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index cebdce9ba8..f8fa9fd65d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -5,13 +5,13 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.util.Log; import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YLabelPosition; -import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -102,9 +102,6 @@ public void computeAxis(float yMin, float yMax) { } } } - - mYAxis.mAxisMaximum = yMax; - mYAxis.mAxisMinimum = yMin; computeAxisValues(yMin, yMax); } @@ -284,7 +281,7 @@ public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { ArrayList limitLines = mYAxis.getLimitLines(); - if (limitLines == null) + if (limitLines == null || limitLines.size() <= 0) return; float[] pts = new float[4]; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index f7bdccd02b..ccc83f078a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -7,7 +7,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.renderer.ViewPortHandler; import java.util.ArrayList; @@ -25,7 +24,7 @@ public class Transformer { /** matrix for handling the different offsets of the chart */ protected Matrix mMatrixOffset = new Matrix(); - + private ViewPortHandler mViewPortHandler; public Transformer(ViewPortHandler viewPortHandler) { @@ -38,10 +37,12 @@ public Transformer(ViewPortHandler viewPortHandler) { * * @param chart */ - public void prepareMatrixValuePx(ViewPortHandler viewport, float deltaX, float deltaY, float yChartMin) { + public void prepareMatrixValuePx(float deltaX, float deltaY, float yChartMin) { - float scaleX = (float) ((viewport.getChartWidth() - viewport.offsetRight() - viewport.offsetLeft()) / deltaX); - float scaleY = (float) ((viewport.getChartHeight() - viewport.offsetTop() - viewport.offsetBottom()) / deltaY); + float scaleX = (float) ((mViewPortHandler.getChartWidth() - mViewPortHandler.offsetRight() - mViewPortHandler + .offsetLeft()) / deltaX); + float scaleY = (float) ((mViewPortHandler.getChartHeight() - mViewPortHandler.offsetTop() - mViewPortHandler + .offsetBottom()) / deltaY); // setup all matrices mMatrixValueToPx.reset(); @@ -49,36 +50,38 @@ public void prepareMatrixValuePx(ViewPortHandler viewport, float deltaX, float d mMatrixValueToPx.postScale(scaleX, -scaleY); } -// /** -// * Prepares the transformation matrix with the specified scales. -// * -// * @param chart -// * @param scaleX -// * @param scaleY -// */ -// public void prepareMatrixValuePx(ChartInterface chart, float scaleX, float scaleY) { -// -// mMatrixValueToPx.reset(); -// mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); -// mMatrixValueToPx.postScale(scaleX, -scaleY); -// } + // /** + // * Prepares the transformation matrix with the specified scales. + // * + // * @param chart + // * @param scaleX + // * @param scaleY + // */ + // public void prepareMatrixValuePx(ChartInterface chart, float scaleX, + // float scaleY) { + // + // mMatrixValueToPx.reset(); + // mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); + // mMatrixValueToPx.postScale(scaleX, -scaleY); + // } /** * Prepares the matrix that contains all offsets. * * @param chart */ - public void prepareMatrixOffset(ViewPortHandler viewport, boolean inverted) { + public void prepareMatrixOffset(boolean inverted) { mMatrixOffset.reset(); // offset.postTranslate(mOffsetLeft, getHeight() - mOffsetBottom); if (!inverted) - mMatrixOffset.postTranslate(viewport.offsetLeft(), - viewport.getChartHeight() - viewport.offsetBottom()); + mMatrixOffset.postTranslate(mViewPortHandler.offsetLeft(), + mViewPortHandler.getChartHeight() - mViewPortHandler.offsetBottom()); else { - mMatrixOffset.setTranslate(viewport.offsetLeft(), -viewport.offsetTop()); + mMatrixOffset + .setTranslate(mViewPortHandler.offsetLeft(), -mViewPortHandler.offsetTop()); mMatrixOffset.postScale(1.0f, -1.0f); } From d78756e9280bbd5b69995e42d9abd7deb51e6702 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 10:44:31 +0100 Subject: [PATCH 0075/1390] Fixed axis issues. --- .../mikephil/charting/charts/BarChart.java | 4 +- .../charting/charts/BarLineChartBase.java | 166 +++++++++--------- .../charting/charts/CandleStickChart.java | 4 +- .../mikephil/charting/charts/Chart.java | 2 +- .../mikephil/charting/charts/LineChart.java | 4 +- .../mikephil/charting/charts/PieChart.java | 4 +- .../charting/charts/PieRadarChartBase.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 4 +- .../charting/charts/ScatterChart.java | 4 +- .../mikephil/charting/components/YAxis.java | 39 ++++ .../charting/renderer/YAxisRenderer.java | 6 +- 11 files changed, 139 insertions(+), 102 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 8884d95505..218b127a5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -80,8 +80,8 @@ protected void init() { } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); // increase deltax by 1 because the bars have a width of 1 mDeltaX++; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d4cdfc63b4..dbf6e8cae5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -198,14 +198,9 @@ protected void onDraw(Canvas canvas) { // execute all drawing commands drawGridBackground(); - float minLeft = mData.getYMin(AxisDependency.LEFT); - float maxLeft = mData.getYMax(AxisDependency.LEFT); - float minRight = mData.getYMin(AxisDependency.RIGHT); - float maxRight = mData.getYMax(AxisDependency.RIGHT); - - mAxisRendererLeft.computeAxis(minLeft, maxLeft); - mAxisRendererRight.computeAxis(minRight, maxRight); - + mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); + mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + // make sure the graph values and grid cannot be drawn outside the // content-rect int clipRestoreCount = mDrawCanvas.save(); @@ -256,14 +251,16 @@ protected void onDraw(Canvas canvas) { private void prepareValuePxMatrix() { - if(mLogEnabled) Log.i(LOG_TAG, "Preparing Value-Px Matrix, deltaLeft: " + mDeltaYLeft + ", deltaRight: " + mDeltaYRight); - + if (mLogEnabled) + Log.i(LOG_TAG, "Preparing Value-Px Matrix, deltaLeft: " + mDeltaYLeft + + ", deltaRight: " + mDeltaYRight); + mRightAxisTransformer.prepareMatrixValuePx(mDeltaX, mDeltaYRight, mAxisRight.mAxisMinimum); mLeftAxisTransformer.prepareMatrixValuePx(mDeltaX, mDeltaYLeft, mAxisLeft.mAxisMinimum); } - + protected void prepareOffsetMatrix() { mRightAxisTransformer.prepareMatrixOffset(mAxisRight.isInverted()); @@ -272,7 +269,7 @@ protected void prepareOffsetMatrix() { @Override public void notifyDataSetChanged() { - + if (mDataNotSet) { if (mLogEnabled) Log.i(LOG_TAG, "Preparing... DATA NOT SET."); @@ -281,22 +278,89 @@ public void notifyDataSetChanged() { if (mLogEnabled) Log.i(LOG_TAG, "Preparing..."); } - - calcMinMax(false); - + + calcMinMax(); + + mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); + mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + + mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + + prepareLegend(); + + calculateOffsets(); + } + + @Override + protected void calcMinMax() { + float minLeft = mData.getYMin(AxisDependency.LEFT); float maxLeft = mData.getYMax(AxisDependency.LEFT); float minRight = mData.getYMin(AxisDependency.RIGHT); float maxRight = mData.getYMax(AxisDependency.RIGHT); + + float leftRange = Math.abs(maxLeft - minLeft); + float rightRange = Math.abs(maxRight - minRight); + + float topSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceTop(); + float topSpaceRight = rightRange / 100f * mAxisRight.getSpaceTop(); + float bottomSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceBottom(); + float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); - mAxisRendererLeft.computeAxis(minLeft, maxLeft); - mAxisRendererRight.computeAxis(minRight, maxRight); + mDeltaX = mData.getXVals().size() - 1; - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + mAxisLeft.mAxisMaximum = maxLeft + topSpaceLeft; + mAxisRight.mAxisMaximum = maxRight + topSpaceRight; + mAxisLeft.mAxisMinimum = minLeft - bottomSpaceLeft; + mAxisRight.mAxisMinimum = minRight - bottomSpaceRight; - prepareLegend(); + mDeltaYLeft = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); + mDeltaYRight = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); - calculateOffsets(); + // // only calculate values if not fixed values + // if (!fixedValues) { + // mYChartMin = mData.getYMin(); + // mYChartMax = mData.getYMax(); + // } + // + // // calc delta + // mDeltaY = Math.abs(mYChartMax - mYChartMin); + // mDeltaX = mData.getXVals().size() - 1; + // + // if (!fixedValues) { + // + // // additional handling for space (default 15% space) + // // float space = Math.abs(mDeltaY / 100f * 15f); + // float space = Math + // .abs(Math.abs(Math.max(Math.abs(mYChartMax), Math.abs(mYChartMin))) / + // 100f * 20f); + // + // if (Math.abs(mYChartMax - mYChartMin) < 0.00001f) { + // if (Math.abs(mYChartMax) < 10f) + // space = 1f; + // else + // space = Math.abs(mYChartMax / 100f * 20f); + // } + // + // if (mStartAtZero) { + // + // if (mYChartMax < 0) { + // mYChartMax = 0; + // // calc delta + // mYChartMin = mYChartMin - space; + // } else { + // mYChartMin = 0; + // // calc delta + // mYChartMax = mYChartMax + space; + // } + // } else { + // + // mYChartMin = mYChartMin - space / 2f; + // mYChartMax = mYChartMax + space / 2f; + // } + // } + // + // mDeltaY = Math.abs(mYChartMax - mYChartMin); } @Override @@ -452,68 +516,6 @@ protected void calcModulus() { + mXAxis.mLabelWidth + ", content width: " + mViewPortHandler.contentWidth()); } - @Override - protected void calcMinMax(boolean fixedValues) { - - float minLeft = mData.getYMin(AxisDependency.LEFT); - float maxLeft = mData.getYMax(AxisDependency.LEFT); - float minRight = mData.getYMin(AxisDependency.RIGHT); - float maxRight = mData.getYMax(AxisDependency.RIGHT); - - mDeltaX = mData.getXVals().size() - 1; - mDeltaYLeft = Math.abs(maxLeft - minLeft); - mDeltaYRight = Math.abs(maxRight - minRight); - - mAxisLeft.mAxisMaximum = maxLeft; - mAxisRight.mAxisMaximum = maxRight; - mAxisLeft.mAxisMinimum = minLeft; - mAxisRight.mAxisMinimum = minRight; - -// // only calculate values if not fixed values -// if (!fixedValues) { -// mYChartMin = mData.getYMin(); -// mYChartMax = mData.getYMax(); -// } -// -// // calc delta -// mDeltaY = Math.abs(mYChartMax - mYChartMin); -// mDeltaX = mData.getXVals().size() - 1; -// -// if (!fixedValues) { -// -// // additional handling for space (default 15% space) -// // float space = Math.abs(mDeltaY / 100f * 15f); -// float space = Math -// .abs(Math.abs(Math.max(Math.abs(mYChartMax), Math.abs(mYChartMin))) / 100f * 20f); -// -// if (Math.abs(mYChartMax - mYChartMin) < 0.00001f) { -// if (Math.abs(mYChartMax) < 10f) -// space = 1f; -// else -// space = Math.abs(mYChartMax / 100f * 20f); -// } -// -// if (mStartAtZero) { -// -// if (mYChartMax < 0) { -// mYChartMax = 0; -// // calc delta -// mYChartMin = mYChartMin - space; -// } else { -// mYChartMin = 0; -// // calc delta -// mYChartMax = mYChartMax + space; -// } -// } else { -// -// mYChartMin = mYChartMin - space / 2f; -// mYChartMax = mYChartMax + space / 2f; -// } -// } -// -// mDeltaY = Math.abs(mYChartMax - mYChartMin); - } - @Override protected float[] getMarkerPosition(Entry e, int dataSetIndex) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 4ffc162849..1e41a8e165 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -34,8 +34,8 @@ protected void init() { } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); // increase deltax by 1 because the candles have a width of 1 mDeltaX++; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3834bcbfaa..7a18d1c0d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -333,7 +333,7 @@ public boolean isEmpty() { /** * calcualtes the y-min and y-max value and the y-delta and x-delta value */ - protected abstract void calcMinMax(boolean fixedValues); + protected abstract void calcMinMax(); /** * calculates the required number of digits for the values that might be diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 22e9cd80f2..47447a508b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -44,8 +44,8 @@ protected void init() { } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); // // if there is only one value in the chart // if (mOriginalData.getYValCount() == 1 diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index e41705b575..3656c511ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -143,8 +143,8 @@ protected void calculateOffsets() { // } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); calcAngles(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index c45408003e..7745d60fe2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -56,7 +56,7 @@ protected void init() { } @Override - protected void calcMinMax(boolean fixedValues) { + protected void calcMinMax() { mDeltaX = mData.getXVals().size() - 1; } @@ -74,7 +74,7 @@ public void notifyDataSetChanged() { if (mDataNotSet) return; - calcMinMax(false); + calcMinMax(); prepareLegend(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 03b75959e4..ec44933c82 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -86,8 +86,8 @@ protected void init() { } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); // additional handling for space (default 15% space) // float space = Math.abs(mDeltaY / 100f * 15f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 390fb163cc..84c2963476 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -52,8 +52,8 @@ protected void calculateOffsets() { } @Override - protected void calcMinMax(boolean fixedValues) { - super.calcMinMax(fixedValues); + protected void calcMinMax() { + super.calcMinMax(); if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 07e5f13294..b4a9918cdb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -55,6 +55,9 @@ public class YAxis extends AxisBase { protected float mCustomAxisMax = Float.NaN; + protected float mSpacePercentTop = 10f; + protected float mSpacePercentBottom = 10f; + public float mAxisMaximum = 0f; public float mAxisMinimum = 0f; @@ -333,6 +336,42 @@ public void resetAxisMaxValue() { mCustomAxisMax = Float.NaN; } + /** + * Sets the top axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceTop(float percent) { + mSpacePercentTop = percent; + } + + /** + * Returns the top axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceTop() { + return mSpacePercentTop; + } + + /** + * Sets the bottom axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceBottom(float percent) { + mSpacePercentBottom = percent; + } + + /** + * Returns the bottom axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceBottom() { + return mSpacePercentBottom; + } + /** * Returns the longest formatted label (in terms of characters) the y-labels * contain. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index f8fa9fd65d..56ecbe9405 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -96,11 +96,7 @@ public void computeAxis(float yMin, float yMax) { // in case a custom minimum is set if(!Float.isNaN(mYAxis.getAxisMinValue())) { yMin = mYAxis.getAxisMinValue(); - } else { - if (mYAxis.isStartAtZeroEnabled()) { - yMin = 0; - } - } + } } computeAxisValues(yMin, yMax); From a621b1aee65ad67b5d471c32fc3d7c5a4ae9b0b9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 11:06:09 +0100 Subject: [PATCH 0076/1390] Fixed more issues concerning axis, custom axis range now working. --- .../mpchartexample/LineChartActivity2.java | 2 + .../charting/charts/BarLineChartBase.java | 41 ++++++++++--------- .../mikephil/charting/charts/Chart.java | 4 +- .../mikephil/charting/components/YAxis.java | 2 + .../charting/renderer/YAxisRenderer.java | 13 ------ 5 files changed, 27 insertions(+), 35 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 2b09bba19a..fa11b7c448 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -111,6 +111,8 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setTextColor(Color.WHITE); + yl.setAxisMaxValue(300); + yl.setAxisMinValue(-100f); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index dbf6e8cae5..c013c23540 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -104,9 +104,6 @@ public abstract class BarLineChartBase Date: Sat, 14 Feb 2015 11:20:49 +0100 Subject: [PATCH 0077/1390] Now possible to plot with 2 different axes. --- .../mpchartexample/LineChartActivity2.java | 47 +++++++++++++++---- .../mikephil/charting/data/ChartData.java | 8 ++-- 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index fa11b7c448..9fcf31821c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; @@ -108,11 +109,16 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(tf); xl.setTextColor(Color.WHITE); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); - yl.setTextColor(Color.WHITE); - yl.setAxisMaxValue(300); - yl.setAxisMinValue(-100f); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setTextColor(ColorTemplate.getHoloBlue()); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setTypeface(tf); + rightAxis.setTextColor(Color.RED); + +// yl.setAxisMaxValue(300f); +// yl.setAxisMinValue(-100f); } @Override @@ -265,18 +271,19 @@ private void setData(int count, float range) { xVals.add((i) + ""); } - ArrayList yVals = new ArrayList(); + ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * // 0.1) / 10); - yVals.add(new Entry(val, i)); + yVals1.add(new Entry(val, i)); } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); + set1.setAxisDependency(AxisDependency.LEFT); set1.setColor(ColorTemplate.getHoloBlue()); set1.setCircleColor(ColorTemplate.getHoloBlue()); set1.setLineWidth(2f); @@ -285,8 +292,30 @@ private void setData(int count, float range) { set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); + ArrayList yVals2 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = (range / 10); + float val = (float) (Math.random() * mult) + 500;// + (float) + // ((mult * + // 0.1) / 10); + yVals2.add(new Entry(val, i)); + } + + // create a dataset and give it a type + LineDataSet set2 = new LineDataSet(yVals2, "DataSet 2"); + set2.setAxisDependency(AxisDependency.RIGHT); + set2.setColor(Color.RED); + set2.setCircleColor(Color.RED); + set2.setLineWidth(2f); + set2.setCircleSize(4f); + set2.setFillAlpha(65); + set2.setFillColor(Color.RED); + set2.setHighLightColor(Color.rgb(244, 117, 117)); + ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets + dataSets.add(set1); + dataSets.add(set2); // add the datasets // create a data object with the datasets LineData data = new LineData(xVals, dataSets); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 7f33a1bfa0..274641ce06 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -224,7 +224,7 @@ protected void calcMinMax(ArrayList dataSets) { } // right axis - T firstRight = getFirstLeft(); + T firstRight = getFirstRight(); if (firstRight != null) { @@ -241,12 +241,12 @@ protected void calcMinMax(ArrayList dataSets) { } } } - + // in case there is only one axis, adjust the second axis if (firstLeft == null) { mLeftAxisMax = mRightAxisMax; mLeftAxisMin = mRightAxisMin; - } else { + } else if (firstRight == null) { mRightAxisMax = mLeftAxisMax; mRightAxisMin = mLeftAxisMin; } @@ -311,7 +311,7 @@ public int getDataSetCount() { public float getYMin() { return mYMin; } - + /** * Returns the minimum y-value for the specified axis. * From 8029f91f2fc534cd49ff60a87816c716c9c1de9d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 14:50:43 +0100 Subject: [PATCH 0078/1390] Fixed issues concerning grid lines and axis enabling / disabling. --- .../mpchartexample/AnotherBarActivity.java | 6 +- .../mpchartexample/BarChartActivity.java | 10 +- .../BarChartActivityMultiDataset.java | 51 +++++---- .../CandleStickChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../HorizontalBarChartActivity.java | 3 +- .../mpchartexample/LineChartActivity2.java | 18 ++-- .../LineChartActivityColored.java | 5 +- .../ListViewBarChartActivity.java | 2 +- .../fragments/BarChartFrag.java | 6 +- .../fragments/ComplexityFragment.java | 5 +- .../fragments/ScatterChartFrag.java | 5 +- .../fragments/SineCosineFragment.java | 5 +- .../listviewitems/BarChartItem.java | 2 +- .../listviewitems/LineChartItem.java | 2 +- .../charting/charts/BarLineChartBase.java | 102 +++++------------- .../charting/components/AxisBase.java | 25 ++++- .../mikephil/charting/components/YAxis.java | 23 +--- .../charting/renderer/XAxisRenderer.java | 5 +- .../renderer/XAxisRendererBarChart.java | 2 +- .../renderer/XAxisRendererRadarChart.java | 3 + .../charting/renderer/YAxisRenderer.java | 6 +- .../renderer/YAxisRendererRadarChart.java | 20 ++-- 23 files changed, 145 insertions(+), 165 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 4a4b4b9f51..03e69be33d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -58,15 +58,15 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); - - mChart.setDrawVerticalGrid(false); - mChart.setDrawHorizontalGrid(false); mChart.setDrawGridBackground(false); XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XLabelPosition.BOTTOM); xAxis.setCenterXLabelText(true); xAxis.setSpaceBetweenLabels(0); + xAxis.setDrawGridLines(false); + + mChart.getAxisLeft().setDrawGridLines(false); mChart.setDrawLegend(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 567687072c..92d4e37d04 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - + mChart.setDrawValueAboveBar(true); mChart.setDescription(""); @@ -70,12 +70,10 @@ protected void onCreate(Bundle savedInstanceState) { // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); - + // mChart.setDrawXLabels(false); mChart.setDrawGridBackground(false); - mChart.setDrawHorizontalGrid(true); - mChart.setDrawVerticalGrid(false); // mChart.setDrawYLabels(false); // sets the text size of the values inside the chart @@ -91,11 +89,13 @@ protected void onCreate(Bundle savedInstanceState) { xl.setPosition(XLabelPosition.BOTTOM); xl.setCenterXLabelText(true); xl.setTypeface(tf); + xl.setDrawGridLines(false); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setLabelCount(8); -// yl.setPosition(YLabelPosition.BOTH_SIDED); + + mChart.getAxisRight().setDrawGridLines(false); mChart.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index b9b212db9b..afedbf1097 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -28,7 +28,8 @@ import java.util.ArrayList; -public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { +public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { private BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; @@ -59,38 +60,41 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setValueFormatter(new LargeValueFormatter()); mChart.setDrawBarShadow(false); - + mChart.setDrawGridBackground(false); - mChart.setDrawHorizontalGrid(false); - + // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); // define an offset to change the original position of the marker // (optional) -// mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); + // mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); // set the marker to the chart mChart.setMarkerView(mv); mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); - + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - + Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); l.setTypeface(tf); - - XAxis xl = mChart.getXAxis(); + + XAxis xl = mChart.getXAxis(); xl.setCenterXLabelText(true); xl.setTypeface(tf); - - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); - yl.setFormatter(new LargeValueFormatter()); - + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setFormatter(new LargeValueFormatter()); + leftAxis.setDrawGridLines(false); + leftAxis.setSpaceTop(25f); + + mChart.getAxisRight().setEnabled(false); + mChart.setValueTypeface(tf); } @@ -144,7 +148,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleAdjustXLegend: { XAxis xAxis = mChart.getXAxis(); - + if (xAxis.isAdjustXLabelsEnabled()) xAxis.setAdjustXLabels(false); else @@ -177,19 +181,19 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - + tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add((i+1990) + ""); + xVals.add((i + 1990) + ""); } ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); - + float mult = mSeekBarY.getProgress() * 10000000f; for (int i = 0; i < mSeekBarX.getProgress(); i++) { @@ -209,20 +213,21 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create 3 datasets with different types BarDataSet set1 = new BarDataSet(yVals1, "Company A"); -// set1.setColors(ColorTemplate.createColors(getApplicationContext(), ColorTemplate.FRESH_COLORS)); + // set1.setColors(ColorTemplate.createColors(getApplicationContext(), + // ColorTemplate.FRESH_COLORS)); set1.setColor(Color.rgb(104, 241, 175)); BarDataSet set2 = new BarDataSet(yVals2, "Company B"); set2.setColor(Color.rgb(164, 228, 251)); BarDataSet set3 = new BarDataSet(yVals3, "Company C"); set3.setColor(Color.rgb(242, 247, 158)); - + ArrayList dataSets = new ArrayList(); dataSets.add(set1); dataSets.add(set2); dataSets.add(set3); BarData data = new BarData(xVals, dataSets); - + // add space between the dataset groups in percent of bar-width data.setGroupSpace(110f); @@ -241,12 +246,12 @@ public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } - + @Override public void onValueSelected(Entry e, int dataSetIndex) { Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + dataSetIndex); } - + @Override public void onNothingSelected() { Log.i("Activity", "Nothing selected."); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 7649e003e6..d5fca0bc5b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -56,7 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); - mChart.setDrawVerticalGrid(false); mChart.setDrawGridBackground(false); XAxis xLabels = mChart.getXAxis(); @@ -66,6 +65,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yLabels = mChart.getAxisLeft(); yLabels.setLabelCount(7); + yLabels.setDrawGridLines(false); // yLabels.setPosition(YLabelPosition.LEFT); mChart.setDrawLegend(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 233c99781d..35ab61f825 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -74,7 +74,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setValueTypeface(tf); @@ -85,6 +84,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); y.setLabelCount(5); + y.setDrawGridLines(false); // add data setData(45, 100); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index c16a74f3c9..4205f8b667 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -71,8 +71,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawXLabels(false); mChart.setDrawGridBackground(false); - mChart.setDrawHorizontalGrid(true); - mChart.setDrawVerticalGrid(false); + // mChart.setDrawYLabels(false); // sets the text size of the values inside the chart diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9fcf31821c..9de2433951 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -80,17 +80,15 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); - mChart.setDrawHorizontalGrid(false); // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color - mChart.setBackgroundColor(Color.GRAY); + mChart.setBackgroundColor(Color.LTGRAY); // add data - setData(45, 100); + setData(20, 30); mChart.animateX(2500); @@ -108,14 +106,18 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setTextColor(Color.WHITE); + xl.setDrawGridLines(false); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); + leftAxis.setAxisMaxValue(200f); + leftAxis.setDrawGridLines(true); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setTextColor(Color.RED); + rightAxis.setDrawGridLines(false); // yl.setAxisMaxValue(300f); // yl.setAxisMinValue(-100f); @@ -274,8 +276,8 @@ private void setData(int count, float range) { ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) + float mult = range / 2f; + float val = (float) (Math.random() * mult) + 50;// + (float) // ((mult * // 0.1) / 10); yVals1.add(new Entry(val, i)); @@ -295,8 +297,8 @@ private void setData(int count, float range) { ArrayList yVals2 = new ArrayList(); for (int i = 0; i < count; i++) { - float mult = (range / 10); - float val = (float) (Math.random() * mult) + 500;// + (float) + float mult = range; + float val = (float) (Math.random() * mult) + 450;// + (float) // ((mult * // 0.1) / 10); yVals2.add(new Entry(val, i)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 04abb590a8..17c260cc51 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -57,9 +57,7 @@ private void setupChart(LineChart chart, LineData data, int color) { // no description text chart.setDescription(""); chart.setNoDataTextDescription("You need to provide data for the chart."); - - // enable / disable grid lines - chart.setDrawVerticalGrid(false); + // mChart.setDrawHorizontalGrid(false); // // enable / disable grid background @@ -102,6 +100,7 @@ private void setupChart(LineChart chart, LineData data, int color) { XAxis x = chart.getXAxis(); x.setTextColor(Color.WHITE); x.setTypeface(mTf); + x.setDrawGridLines(false); // animate calls invalidate()... chart.animateX(2500); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 3462ebd116..efe921c370 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -87,7 +87,6 @@ public View getView(int position, View convertView, ViewGroup parent) { // apply styling holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); - holder.chart.setDrawVerticalGrid(false); holder.chart.setDrawGridBackground(false); holder.chart.setValueTextColor(Color.WHITE); @@ -95,6 +94,7 @@ public View getView(int position, View convertView, ViewGroup parent) { xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); + xl.setDrawGridLines(false); YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 85b2db6572..a4d4cd6353 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; @@ -38,7 +39,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawBorder(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); mChart.setDrawBarShadow(false); @@ -51,7 +51,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); -// labels.setPosition(YLabelPosition.BOTH_SIDED); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setDrawGridLines(false); // programatically add the chart FrameLayout parent = (FrameLayout) v.findViewById(R.id.parentLayout); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 048ac788fa..4175e4e46d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.R; @@ -31,7 +32,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setHighlightIndicatorEnabled(false); mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); mChart.setData(getComplexity()); @@ -48,6 +48,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); + XAxis xAxis = mChart.getXAxis(); + xAxis.setDrawGridLines(false); + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 445dd58423..d80377985c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; @@ -41,11 +42,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawBorder(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); mChart.setData(generateScatterData(3, 10000, 150)); + XAxis xAxis = mChart.getXAxis(); + xAxis.setDrawGridLines(false); + Legend l = mChart.getLegend(); l.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index baa60a8d30..ebdd4734b1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.R; @@ -32,7 +33,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setHighlightIndicatorEnabled(false); mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); - mChart.setDrawVerticalGrid(false); mChart.setDrawXLabels(false); // mChart.setYRange(-1.2f, 1.2f, false); @@ -51,6 +51,9 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis labels = mChart.getAxisLeft(); labels.setTypeface(tf); + XAxis xAxis = mChart.getXAxis(); + xAxis.setDrawGridLines(false); + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index 6d36172d39..149844c576 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -50,7 +50,6 @@ public View getView(int position, View convertView, Context c) { // apply styling holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); - holder.chart.setDrawVerticalGrid(false); holder.chart.setDrawGridBackground(false); holder.chart.setDrawBarShadow(false); @@ -58,6 +57,7 @@ public View getView(int position, View convertView, Context c) { xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); + xl.setDrawGridLines(false); YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 6c5c984c5a..49d6c07279 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -51,13 +51,13 @@ public View getView(int position, View convertView, Context c) { // apply styling // holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); - holder.chart.setDrawVerticalGrid(false); holder.chart.setDrawGridBackground(false); XAxis xl = holder.chart.getXAxis(); xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); + xl.setDrawGridLines(false); YAxis yl = holder.chart.getAxisLeft(); yl.setTypeface(mTf); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c013c23540..8860e32fc0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -83,15 +83,6 @@ public abstract class BarLineChartBase xValues) { @Override public void renderAxis(Canvas c) { + if (!mXAxis.isEnabled()) + return; + float yoffset = Utils.convertDpToPixel(4f); mAxisPaint.setTypeface(mXAxis.getTypeface()); @@ -129,7 +132,7 @@ protected void drawLabels(Canvas c, float yPos) { @Override public void renderGridLines(Canvas c) { - if (!mXAxis.isDrawGridLinesEnabled()) + if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; float[] position = new float[] { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 48507ce45d..c8fab8c242 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -79,7 +79,7 @@ protected void drawLabels(Canvas c, float yPos) { @Override public void renderGridLines(Canvas c) { - if (!mXAxis.isDrawGridLinesEnabled()) + if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; float[] position = new float[] { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 34af78cdca..edbca7caf0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -21,6 +21,9 @@ public XAxisRendererRadarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Rad @Override public void renderAxis(Canvas c) { + if (!mXAxis.isEnabled()) + return; + mAxisPaint.setTypeface(mXAxis.getTypeface()); mAxisPaint.setTextSize(mXAxis.getTextSize()); mAxisPaint.setColor(mXAxis.getTextColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 953cbb67dc..1e9147fcfc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -59,6 +59,7 @@ public void setXOffset(float xOffset) { /** * Computes the axis values. + * * @param yMin - the minimum y-value in the data object for this axis * @param yMax - the maximum y-value in the data object for this axis */ @@ -165,6 +166,9 @@ private void computeAxisValues(float min, float max) { @Override public void renderAxis(Canvas c) { + if (!mYAxis.isEnabled()) + return; + float[] positions = new float[mYAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { @@ -235,7 +239,7 @@ private void drawYLabels(Canvas c, float xPos, float[] positions, float yOffset) @Override public void renderGridLines(Canvas c) { - if (!mYAxis.isDrawGridLinesEnabled()) + if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) return; // pre alloc diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 0db36fba68..57ca7640f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,31 +8,32 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; public class YAxisRendererRadarChart extends YAxisRenderer { - + private RadarChart mChart; public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { super(viewPortHandler, yAxis, null); - + mChart = chart; } @Override public void computeAxis(float yMin, float yMax) { - - + } - + @Override public void renderAxis(Canvas c) { - + + if (!mYAxis.isEnabled()) + return; + mAxisPaint.setTypeface(mYAxis.getTypeface()); mAxisPaint.setTextSize(mYAxis.getTextSize()); mAxisPaint.setColor(mYAxis.getTextColor()); @@ -58,10 +60,10 @@ public void renderAxis(Canvas c) { c.drawText(label, p.x + 10, p.y - 5, mAxisPaint); } } - + @Override public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { - + ArrayList limitLines = mYAxis.getLimitLines(); if (limitLines == null) From a59887f72c6feca104d83a2f7510b41859b1cff0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 15:11:11 +0100 Subject: [PATCH 0079/1390] Improved example, fixed more bugs. --- .../mpchartexample/BarChartActivity.java | 15 ++++++++---- .../BarChartActivityMultiDataset.java | 1 + .../InvertedLineChartActivity.java | 1 + .../mpchartexample/LineChartActivity1.java | 1 + .../ListViewBarChartActivity.java | 22 +++++++++++------- .../ListViewMultiChartActivity.java | 3 ++- .../mpchartexample/RadarChartActivitry.java | 1 + .../{ => custom}/MyMarkerView.java | 4 +++- .../custom/MyValueFormatter.java | 20 ++++++++++++++++ .../custom/PercentFormatter.java | 23 +++++++++++++++++++ .../fragments/BarChartFrag.java | 2 +- .../fragments/ScatterChartFrag.java | 2 +- .../listviewitems/BarChartItem.java | 22 +++++++++++------- .../listviewitems/LineChartItem.java | 11 ++++++--- .../listviewitems/PieChartItem.java | 7 ++++-- 15 files changed, 105 insertions(+), 30 deletions(-) rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/{ => custom}/MyMarkerView.java (90%) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 92d4e37d04..038bc87270 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -20,8 +20,8 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XLabelPosition; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -91,11 +91,16 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(tf); xl.setDrawGridLines(false); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); - yl.setLabelCount(8); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setLabelCount(8); - mChart.getAxisRight().setDrawGridLines(false); + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setDrawGridLines(false); + rightAxis.setTypeface(tf); + rightAxis.setLabelCount(8); + + mChart.setValueFormatter(new MyValueFormatter()); mChart.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index afedbf1097..78df5d9aed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -24,6 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.LargeValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index d1fa310fda..40cd1ca438 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 03719f5e00..a1bec4b041 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -28,6 +28,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index efe921c370..c5732065b2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -90,15 +90,21 @@ public View getView(int position, View convertView, ViewGroup parent) { holder.chart.setDrawGridBackground(false); holder.chart.setValueTextColor(Color.WHITE); - XAxis xl = holder.chart.getXAxis(); - xl.setCenterXLabelText(true); - xl.setPosition(XLabelPosition.BOTTOM); - xl.setTypeface(mTf); - xl.setDrawGridLines(false); + XAxis xAxis = holder.chart.getXAxis(); + xAxis.setCenterXLabelText(true); + xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setTypeface(mTf); + xAxis.setDrawGridLines(false); - YAxis yl = holder.chart.getAxisLeft(); - yl.setTypeface(mTf); - yl.setLabelCount(5); + YAxis leftAxis = holder.chart.getAxisLeft(); + leftAxis.setTypeface(mTf); + leftAxis.setLabelCount(5); + leftAxis.setSpaceTop(15f); + + YAxis rightAxis = holder.chart.getAxisRight(); + rightAxis.setTypeface(mTf); + rightAxis.setLabelCount(5); + rightAxis.setSpaceTop(15f); // set data holder.chart.setData(c); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 3c050bfcbf..df69414d9a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -105,6 +104,7 @@ private LineData generateDataLine(int cnt) { d1.setLineWidth(3f); d1.setCircleSize(5f); d1.setHighLightColor(Color.rgb(244, 117, 117)); + d1.setDrawValues(false); ArrayList e2 = new ArrayList(); @@ -118,6 +118,7 @@ private LineData generateDataLine(int cnt) { d2.setHighLightColor(Color.rgb(244, 117, 117)); d2.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); + d2.setDrawValues(false); ArrayList sets = new ArrayList(); sets.add(d1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index dd69c4a624..42aebf5f33 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java similarity index 90% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index e9fecf5e00..8f316a06ae 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -1,5 +1,5 @@ -package com.xxmassdeveloper.mpchartexample; +package com.xxmassdeveloper.mpchartexample.custom; import android.content.Context; import android.widget.TextView; @@ -8,6 +8,8 @@ import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.Utils; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.R.id; /** * Custom implementation of the MarkerView. diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java new file mode 100644 index 0000000000..c71b1ac1b8 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -0,0 +1,20 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.utils.ValueFormatter; + +import java.text.DecimalFormat; + +public class MyValueFormatter implements ValueFormatter { + + private DecimalFormat mFormat; + + public MyValueFormatter() { + mFormat = new DecimalFormat("###,###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value) { + return mFormat.format(value) + " $"; + } + +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java new file mode 100644 index 0000000000..3244626717 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java @@ -0,0 +1,23 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.utils.ValueFormatter; + +import java.text.DecimalFormat; + +public class PercentFormatter implements ValueFormatter { + + private DecimalFormat mFormat; + private PieChart mChart; + + public PercentFormatter(PieChart chart) { + mFormat = new DecimalFormat("#,##0.0"); + this.mChart = chart; + } + + @Override + public String getFormattedValue(float value) { + return mFormat.format(mChart.getPercentOfTotal(value)) + " %"; + } + +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index a4d4cd6353..0fc906395f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; public class BarChartFrag extends SimpleFragment { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index d80377985c..e26be13092 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -10,8 +10,8 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.xxmassdeveloper.mpchartexample.MyMarkerView; import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; public class ScatterChartFrag extends SimpleFragment { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index 149844c576..ce31ba2786 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -53,15 +53,21 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDrawGridBackground(false); holder.chart.setDrawBarShadow(false); - XAxis xl = holder.chart.getXAxis(); - xl.setCenterXLabelText(true); - xl.setPosition(XLabelPosition.BOTTOM); - xl.setTypeface(mTf); - xl.setDrawGridLines(false); + XAxis xAxis = holder.chart.getXAxis(); + xAxis.setCenterXLabelText(true); + xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setTypeface(mTf); + xAxis.setDrawGridLines(false); - YAxis yl = holder.chart.getAxisLeft(); - yl.setTypeface(mTf); - yl.setLabelCount(5); + YAxis leftAxis = holder.chart.getAxisLeft(); + leftAxis.setTypeface(mTf); + leftAxis.setLabelCount(5); + leftAxis.setSpaceTop(20f); + + YAxis rightAxis = holder.chart.getAxisRight(); + rightAxis.setTypeface(mTf); + rightAxis.setLabelCount(5); + rightAxis.setSpaceTop(20f); // set data holder.chart.setData((BarData) mChartData); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 49d6c07279..ea3d2c3113 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -59,9 +59,14 @@ public View getView(int position, View convertView, Context c) { xl.setTypeface(mTf); xl.setDrawGridLines(false); - YAxis yl = holder.chart.getAxisLeft(); - yl.setTypeface(mTf); - yl.setLabelCount(5); + YAxis leftAxis = holder.chart.getAxisLeft(); + leftAxis.setTypeface(mTf); + leftAxis.setLabelCount(5); + + YAxis rightAxis = holder.chart.getAxisRight(); + rightAxis.setTypeface(mTf); + rightAxis.setLabelCount(5); + rightAxis.setDrawGridLines(false); // set data holder.chart.setData((LineData) mChartData); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 859b67d404..666090685e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.PercentFormatter; public class PieChartItem extends ChartItem { @@ -50,11 +51,13 @@ public View getView(int position, View convertView, Context c) { // apply styling holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); - holder.chart.setHoleRadius(60f); - holder.chart.setTransparentCircleRadius(65f); + holder.chart.setHoleRadius(52f); + holder.chart.setTransparentCircleRadius(57f); holder.chart.setCenterText("MPChart\nAndroid"); holder.chart.setCenterTextTypeface(mTf); holder.chart.setCenterTextSize(18f); + holder.chart.setValueTextSize(11f); + holder.chart.setValueFormatter(new PercentFormatter(holder.chart)); // set data holder.chart.setData((PieData) mChartData); From 6492d59eb1f2772365570891ae10426906f90eb4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 16:05:22 +0100 Subject: [PATCH 0080/1390] Fixed bug concerning x-axis enable / disable, improved example. --- .../mpchartexample/LineChartActivity1.java | 3 ++- .../ListViewMultiChartActivity.java | 2 +- .../fragments/BarChartFrag.java | 9 ++++---- .../fragments/ComplexityFragment.java | 9 ++++---- .../fragments/ScatterChartFrag.java | 14 ++++++----- .../fragments/SineCosineFragment.java | 14 ++++++----- .../listviewitems/BarChartItem.java | 2 +- .../listviewitems/ChartItem.java | 4 ++-- .../listviewitems/LineChartItem.java | 2 +- .../listviewitems/PieChartItem.java | 2 +- .../charting/charts/BarLineChartBase.java | 23 +------------------ .../charting/charts/HorizontalBarChart.java | 2 -- .../listener/BarLineChartTouchListener.java | 2 +- 13 files changed, 36 insertions(+), 52 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index a1bec4b041..3bb6ecd6c3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -117,7 +118,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setScaleMinima(3f, 3f); // // // center the view to a specific position inside the chart -// mChart.centerViewPort(10, 50); +// mChart.centerViewPort(10, 50, AxisDependency.LEFT); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index df69414d9a..a7e12dac7a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -166,7 +166,7 @@ private PieData generateDataPie(int cnt) { PieDataSet d = new PieDataSet(entries, ""); // space between slices - d.setSliceSpace(5f); + d.setSliceSpace(2f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); PieData cd = new PieData(getQuarters(), d); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 0fc906395f..6a263daf18 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -39,7 +39,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawBorder(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); - mChart.setDrawXLabels(false); mChart.setDrawBarShadow(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); @@ -49,11 +48,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YAxis labels = mChart.getAxisLeft(); - labels.setTypeface(tf); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + mChart.getAxisRight().setEnabled(false); + XAxis xAxis = mChart.getXAxis(); - xAxis.setDrawGridLines(false); + xAxis.setEnabled(false); // programatically add the chart FrameLayout parent = (FrameLayout) v.findViewById(R.id.parentLayout); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 4175e4e46d..58dfa3e9bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -32,7 +32,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setHighlightIndicatorEnabled(false); mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); - mChart.setDrawXLabels(false); mChart.setData(getComplexity()); mChart.animateX(3000); @@ -45,11 +44,13 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YAxis labels = mChart.getAxisLeft(); - labels.setTypeface(tf); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + + mChart.getAxisRight().setEnabled(false); XAxis xAxis = mChart.getXAxis(); - xAxis.setDrawGridLines(false); + xAxis.setEnabled(false); return v; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index e26be13092..903092bccd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -31,9 +31,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - YAxis labels = mChart.getAxisLeft(); - labels.setTypeface(tf); - MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); mChart.setMarkerView(mv); @@ -42,12 +39,17 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDrawBorder(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); - mChart.setDrawXLabels(false); - mChart.setData(generateScatterData(3, 10000, 150)); XAxis xAxis = mChart.getXAxis(); - xAxis.setDrawGridLines(false); + xAxis.setEnabled(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setTypeface(tf); + rightAxis.setDrawGridLines(false); Legend l = mChart.getLegend(); l.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index ebdd4734b1..cdf5bf515a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -33,9 +33,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setHighlightIndicatorEnabled(false); mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); - mChart.setDrawXLabels(false); - -// mChart.setYRange(-1.2f, 1.2f, false); mChart.setData(generateLineData()); mChart.animateX(3000); @@ -48,11 +45,16 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Legend l = mChart.getLegend(); l.setTypeface(tf); - YAxis labels = mChart.getAxisLeft(); - labels.setTypeface(tf); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setStartAtZero(false); + leftAxis.setAxisMaxValue(1.2f); + leftAxis.setAxisMinValue(-1.2f); + + mChart.getAxisRight().setEnabled(false); XAxis xAxis = mChart.getXAxis(); - xAxis.setDrawGridLines(false); + xAxis.setEnabled(false); return v; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index ce31ba2786..fb25c5c220 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -17,7 +17,7 @@ public class BarChartItem extends ChartItem { private Typeface mTf; - public BarChartItem(ChartData cd, Context c) { + public BarChartItem(ChartData cd, Context c) { super(cd); mTf = Typeface.createFromAsset(c.getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java index 9abd27c5ef..0e6182165c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java @@ -16,9 +16,9 @@ public abstract class ChartItem { protected static final int TYPE_LINECHART = 1; protected static final int TYPE_PIECHART = 2; - protected ChartData mChartData; + protected ChartData mChartData; - public ChartItem(ChartData cd) { + public ChartItem(ChartData cd) { this.mChartData = cd; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index ea3d2c3113..78bd575ef4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -18,7 +18,7 @@ public class LineChartItem extends ChartItem { private Typeface mTf; - public LineChartItem(ChartData cd, Context c) { + public LineChartItem(ChartData cd, Context c) { super(cd); mTf = Typeface.createFromAsset(c.getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 666090685e..5cb63449d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -18,7 +18,7 @@ public class PieChartItem extends ChartItem { private Typeface mTf; - public PieChartItem(ChartData cd, Context c) { + public PieChartItem(ChartData cd, Context c) { super(cd); mTf = Typeface.createFromAsset(c.getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 8860e32fc0..0b9f4b76ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -83,9 +83,6 @@ public abstract class BarLineChartBase 25f) { + mTouchStartPoint.y)) > 5f) { if (mChart.hasNoDragOffset()) { From 131ecce79868f15a861a03d12a8e6dc0fe75c4df Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 18:50:25 +0100 Subject: [PATCH 0081/1390] Fixed bug in dynamical data adding. --- .../DynamicalAddingActivity.java | 4 +- .../LineChartActivityColored.java | 12 ++-- .../charting/charts/BarLineChartBase.java | 2 + .../mikephil/charting/charts/Chart.java | 21 ++++--- .../mikephil/charting/components/YAxis.java | 14 +++++ .../mikephil/charting/data/ChartData.java | 57 ++++++++++++++----- .../mikephil/charting/data/DataSet.java | 17 +++++- 7 files changed, 96 insertions(+), 31 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index fd2b85fb66..93f0febc7b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -9,6 +9,7 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -48,7 +49,7 @@ private void addEntry() { if(data != null) { LineDataSet set = data.getDataSetByIndex(0); - // set.addEntry(...); + // set.addEntry(...); // can be called as well if (set == null) { set = createSet(); @@ -202,6 +203,7 @@ private LineDataSet createSet() { set.setColor(Color.rgb(240, 99, 99)); set.setCircleColor(Color.rgb(240, 99, 99)); set.setHighLightColor(Color.rgb(190, 190, 190)); + set.setAxisDependency(AxisDependency.LEFT); return set; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 17c260cc51..0849a43cbe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -92,10 +92,13 @@ private void setupChart(LineChart chart, LineData data, int color) { l.setTextColor(Color.WHITE); l.setTypeface(mTf); - YAxis y = chart.getAxisLeft(); - y.setTextColor(Color.WHITE); - y.setTypeface(mTf); - y.setLabelCount(4); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTextColor(Color.WHITE); + leftAxis.setTypeface(mTf); + leftAxis.setLabelCount(4); + leftAxis.setDrawGridLines(false); + + chart.getAxisRight().setEnabled(false); XAxis x = chart.getXAxis(); x.setTextColor(Color.WHITE); @@ -130,6 +133,7 @@ private LineData getData(int count, float range) { set1.setColor(Color.WHITE); set1.setCircleColor(Color.WHITE); set1.setHighLightColor(Color.WHITE); + set1.setDrawValues(false); ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 0b9f4b76ea..4b485acb8e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -288,6 +288,8 @@ protected void calcMinMax() { float topSpaceRight = rightRange / 100f * mAxisRight.getSpaceTop(); float bottomSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceBottom(); float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); + + Log.i(LOG_TAG, "minLeft: " + minLeft + ", maxLeft: " + maxLeft); mDeltaX = mData.getXVals().size() - 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 4b622a4a64..d059b87176 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -64,7 +64,7 @@ public abstract class Chart mLimitLines; + /** custom minimum value this axis represents */ protected float mCustomAxisMin = Float.NaN; + /** custom maximum value this axis represents */ protected float mCustomAxisMax = Float.NaN; + /** + * axis space from the largest value to the top in percent of the total axis + * range + */ protected float mSpacePercentTop = 10f; + + /** + * axis space from the smallest value to the bottom in percent of the total + * axis range + */ protected float mSpacePercentBottom = 10f; public float mAxisMaximum = 0f; public float mAxisMinimum = 0f; + /** the total range of values this axis covers */ public float mAxisRange = 0f; /** the position of the y-labels relative to the chart */ @@ -68,6 +81,7 @@ public enum YLabelPosition { OUTSIDE_CHART, INSIDE_CHART } + /** the side this axis object represents */ private AxisDependency mAxisDependency; public enum AxisDependency { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 274641ce06..9c0ba9304a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -56,7 +56,7 @@ public abstract class ChartData> { */ public ChartData(ArrayList xVals) { this.mXVals = xVals; - + this.mDataSets = new ArrayList(); init(); } @@ -68,7 +68,7 @@ public ChartData(ArrayList xVals) { */ public ChartData(String[] xVals) { this.mXVals = arrayToArrayList(xVals); - + this.mDataSets = new ArrayList(); init(); } @@ -241,7 +241,7 @@ protected void calcMinMax(ArrayList dataSets) { } } } - + // in case there is only one axis, adjust the second axis if (firstLeft == null) { mLeftAxisMax = mRightAxisMax; @@ -535,6 +535,19 @@ public void addDataSet(T d) { mYMax = d.getYMax(); if (mYMin > d.getYMin()) mYMin = d.getYMin(); + + if (d.getAxisDependency() == AxisDependency.LEFT) { + + if (mLeftAxisMax < d.getYMax()) + mLeftAxisMax = d.getYMax(); + if (mLeftAxisMin > d.getYMin()) + mLeftAxisMin = d.getYMin(); + } else { + if (mRightAxisMax < d.getYMax()) + mRightAxisMax = d.getYMax(); + if (mRightAxisMin > d.getYMin()) + mRightAxisMin = d.getYMin(); + } } /** @@ -588,30 +601,46 @@ public boolean removeDataSet(int index) { */ public void addEntry(Entry e, int dataSetIndex) { - float val = e.getVal(); + if (mDataSets == null) + mDataSets = new ArrayList(); - mYValCount += 1; - mYValueSum += val; + if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; + float val = e.getVal(); - if (mDataSets == null) - mDataSets = new ArrayList(); + mYValCount += 1; + mYValueSum += val; - if (mDataSets.size() > dataSetIndex) { + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; + + if (mDataSets == null) + mDataSets = new ArrayList(); T set = mDataSets.get(dataSetIndex); if (set != null) { + if (set.getAxisDependency() == AxisDependency.LEFT) { + + if (mLeftAxisMax < e.getVal()) + mLeftAxisMax = e.getVal(); + if (mLeftAxisMin > e.getVal()) + mLeftAxisMin = e.getVal(); + } else { + if (mRightAxisMax < e.getVal()) + mRightAxisMax = e.getVal(); + if (mRightAxisMin > e.getVal()) + mRightAxisMin = e.getVal(); + } + // add the entry to the dataset set.addEntry(e); } } else { - Log.e("addEntry", "Cannot add Entry because dataSetIndex too high."); + Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 1c53541bdd..e894f2b846 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -42,7 +42,7 @@ public abstract class DataSet { /** if true, y-values are drawn on the chart */ protected boolean mDrawValues = true; - + private AxisDependency mAxisDependency = AxisDependency.LEFT; /** @@ -334,11 +334,22 @@ public void setVisible(boolean visible) { public boolean isVisible() { return mVisible; } - + + /** + * Returns the axis this DataSet should be plotted against. + * + * @return + */ public AxisDependency getAxisDependency() { return mAxisDependency; } - + + /** + * Set the y-axis this DataSet should be plotted against (either LEFT or + * RIGHT). Default: LEFT + * + * @param dependency + */ public void setAxisDependency(AxisDependency dependency) { mAxisDependency = dependency; } From bbc81841cf9bb756e0391811277743d748017c15 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Feb 2015 19:03:09 +0100 Subject: [PATCH 0082/1390] Improved dynamical data adding. --- .../DynamicalAddingActivity.java | 38 +++++++++++-------- .../mikephil/charting/data/BarData.java | 4 ++ .../data/BarLineScatterCandleData.java | 4 ++ .../mikephil/charting/data/CandleData.java | 4 ++ .../mikephil/charting/data/ChartData.java | 23 +++++++++++ .../mikephil/charting/data/LineData.java | 4 ++ .../mikephil/charting/data/PieData.java | 4 ++ .../mikephil/charting/data/RadarData.java | 4 ++ .../mikephil/charting/data/ScatterData.java | 4 ++ 9 files changed, 73 insertions(+), 16 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 93f0febc7b..d74fe64f4b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -35,7 +35,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setDescription(""); - addEmptyData(); + // add an empty data object + mChart.setData(new LineData()); mChart.invalidate(); } @@ -56,6 +57,8 @@ private void addEntry() { data.addDataSet(set); } + // add a new x-value first + data.addXValue((set.getEntryCount()+1) + ""); data.addEntry(new Entry((float) (Math.random() * 50) + 50f, set.getEntryCount()), 0); // let the chart know it's data has changed @@ -131,20 +134,22 @@ private void removeDataSet() { } } - private void addEmptyData() { - - // create 30 x-vals - String[] xVals = new String[30]; - - for (int i = 0; i < 30; i++) - xVals[i] = "" + i; - - // create a chartdata object that contains only the x-axis labels (no entries or datasets) - LineData data = new LineData(xVals); - - mChart.setData(data); - mChart.invalidate(); - } +// private void addEmptyData() { +// +// int size = 1; +// +// // create 30 x-vals +// String[] xVals = new String[size]; +// +// for (int i = 0; i < size; i++) +// xVals[i] = "" + i; +// +// // create a chartdata object that contains only the x-axis labels (no entries or datasets) +// LineData data = new LineData(); +// +// mChart.setData(data); +// mChart.invalidate(); +// } @Override public void onValueSelected(Entry e, int dataSetIndex) { @@ -183,7 +188,8 @@ public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "DataSet removed!", Toast.LENGTH_SHORT).show(); break; case R.id.actionAddEmptyLineData: - addEmptyData(); + mChart.setData(new LineData()); + mChart.invalidate(); Toast.makeText(this, "Empty data added!", Toast.LENGTH_SHORT).show(); break; case R.id.actionClear: diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 53b6ca04f9..433aeaeab7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -13,6 +13,10 @@ public class BarData extends BarLineScatterCandleData { /** the space that is left between groups of bars */ private float mGroupSpace = 0.8f; + public BarData() { + super(); + } + public BarData(ArrayList xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java index a4876b05b8..e9dc9cba0d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java @@ -11,6 +11,10 @@ public abstract class BarLineScatterCandleData> extends ChartData { + public BarLineScatterCandleData() { + super(); + } + public BarLineScatterCandleData(ArrayList xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index 37faf69fd1..96d8c6cff1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -4,6 +4,10 @@ public class CandleData extends BarLineScatterCandleData { + public CandleData() { + super(); + } + public CandleData(ArrayList xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9c0ba9304a..9ca91d0573 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -47,6 +47,11 @@ public abstract class ChartData> { /** array that holds all DataSets the ChartData object represents */ protected ArrayList mDataSets; + + public ChartData() { + mXVals = new ArrayList(); + mDataSets = new ArrayList(); + } /** * Constructor for only x-values. This constructor can be used for setting @@ -401,6 +406,24 @@ public ArrayList getXVals() { return mXVals; } + /** + * Adds a new x-value to the chart data. + * + * @param xVal + */ + public void addXValue(String xVal) { + mXVals.add(xVal); + } + + /** + * Removes the x-value at the specified index. + * + * @param index + */ + public void removeXValue(int index) { + mXVals.remove(index); + } + /** * Returns an the array of DataSets this object holds. * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 508f58f9e4..d37a1a08af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -4,6 +4,10 @@ import java.util.ArrayList; public class LineData extends BarLineScatterCandleData { + + public LineData() { + super(); + } public LineData(ArrayList xVals) { super(xVals); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 5a09de0448..124e22d4ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -12,6 +12,10 @@ */ public class PieData extends ChartData { + public PieData() { + super(); + } + public PieData(ArrayList xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 6b3909f254..aca96e00a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -10,6 +10,10 @@ */ public class RadarData extends ChartData { + public RadarData() { + super(); + } + public RadarData(ArrayList xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index 6afca37b13..815b7249a5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -5,6 +5,10 @@ public class ScatterData extends BarLineScatterCandleData { + public ScatterData() { + super(); + } + public ScatterData(ArrayList xVals) { super(xVals); } From 5bd73bcb0a98d43ea0919e1e1f938c793b3a944c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 15 Feb 2015 17:11:49 +0100 Subject: [PATCH 0083/1390] Worked on chart viewport handling and dynamical data adding. --- .../DynamicalAddingActivity.java | 10 +- .../charting/charts/BarLineChartBase.java | 135 ++++++++++++++---- .../listener/BarLineChartTouchListener.java | 2 +- .../charting/renderer/ViewPortHandler.java | 62 +++++--- 4 files changed, 158 insertions(+), 51 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index d74fe64f4b..ad67cd33aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -58,11 +58,17 @@ private void addEntry() { } // add a new x-value first - data.addXValue((set.getEntryCount()+1) + ""); - data.addEntry(new Entry((float) (Math.random() * 50) + 50f, set.getEntryCount()), 0); + data.addXValue(set.getEntryCount() + ""); + data.addEntry(new Entry((float) (Math.random() * 10) + 50f, set.getEntryCount()), 0); // let the chart know it's data has changed mChart.notifyDataSetChanged(); + +// mChart.setVisibleXRange(6); +// mChart.setVisibleYRange(30, AxisDependency.LEFT); +// +// // this automatically refreshes the chart (calls invalidate()) +// mChart.moveViewTo(data.getXValCount()-7, 55f, AxisDependency.LEFT); // redraw the chart mChart.invalidate(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 4b485acb8e..01ab415d01 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -288,7 +288,7 @@ protected void calcMinMax() { float topSpaceRight = rightRange / 100f * mAxisRight.getSpaceTop(); float bottomSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceBottom(); float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); - + Log.i(LOG_TAG, "minLeft: " + minLeft + ", maxLeft: " + maxLeft); mDeltaX = mData.getXVals().size() - 1; @@ -646,7 +646,7 @@ public boolean onTouchEvent(MotionEvent event) { */ public void zoomIn() { Matrix save = mViewPortHandler.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); - mViewPortHandler.refresh(save, this); + mViewPortHandler.refresh(save, this, true); } /** @@ -654,7 +654,7 @@ public void zoomIn() { */ public void zoomOut() { Matrix save = mViewPortHandler.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); - mViewPortHandler.refresh(save, this); + mViewPortHandler.refresh(save, this, true); } /** @@ -668,7 +668,7 @@ public void zoomOut() { */ public void zoom(float scaleX, float scaleY, float x, float y) { Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, -y); - mViewPortHandler.refresh(save, this); + mViewPortHandler.refresh(save, this, true); } /** @@ -677,29 +677,108 @@ public void zoom(float scaleX, float scaleY, float x, float y) { */ public void fitScreen() { Matrix save = mViewPortHandler.fitScreen(); - mViewPortHandler.refresh(save, this); + mViewPortHandler.refresh(save, this, true); + } + + // /** + // * Centers the viewport around the specified x-index and the specified + // * y-value in the chart. Centering the viewport outside the bounds of the + // * chart is not possible. Makes most sense in combination with the + // * setScaleMinima(...) method. First set the scale minima, then center the + // * viewport. SHOULD BE CALLED AFTER setting data for the chart. + // * + // * @param xIndex the index on the x-axis to center to + // * @param yVal the value ont he y-axis to center to + // */ + // public synchronized void centerViewPort(final int xIndex, final float + // yVal, AxisDependency axis) { + // + // float indicesInView = mDeltaX / mViewPortHandler.getScaleX(); + // float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + // + // // Log.i(LOG_TAG, "indices: " + indicesInView + ", vals: " + + // // valsInView); + // + // float[] pts = new float[] { + // xIndex - indicesInView / 2f, yVal + valsInView / 2f + // }; + // + // getTransformer(axis).pointValuesToPixel(pts); + // mViewPortHandler.centerViewPort(pts, this); + // } + + /** + * Sets the size of the area (range on the x-axis) that should be maximum + * visible at once. If this is e.g. set to 10, no more than 10 values on the + * x-axis can be viewed at once without scrolling. + * + * @param xRange + */ + public void setVisibleXRange(float xRange) { + float xScale = mDeltaX / (xRange + 0.01f); + mViewPortHandler.setMinimumScaleX(xScale); + } + + /** + * Sets the size of the area (range on the y-axis) that should be maximum + * visible at once. + * + * @param yRange + * @param axis - the axis for which this limit should apply + */ + public void setVisibleYRange(float yRange, AxisDependency axis) { + float yScale = getDeltaY(axis) / yRange; + mViewPortHandler.setMinimumScaleY(yScale); + } + + /** + * Moves the left side of the current viewport to the specified x-index. + * + * @param xIndex + */ + public void moveViewToX(int xIndex) { + + float[] pts = new float[] { + xIndex, 0f + }; + + getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, this); } /** - * Centers the viewport around the specified x-index and the specified - * y-value in the chart. Centering the viewport outside the bounds of the - * chart is not possible. Makes most sense in combination with the - * setScaleMinima(...) method. First set the scale minima, then center the - * viewport. SHOULD BE CALLED AFTER setting data for the chart. + * Centers the viewport to the specified y-value on the y-axis. * - * @param xIndex the index on the x-axis to center to - * @param yVal the value ont he y-axis to center to + * @param yValue + * @param axis - which axis should be used as a reference for the y-axis */ - public synchronized void centerViewPort(final int xIndex, final float yVal, AxisDependency axis) { + public void moveViewToY(float yValue, AxisDependency axis) { - float indicesInView = mDeltaX / mViewPortHandler.getScaleX(); float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Log.i(LOG_TAG, "indices: " + indicesInView + ", vals: " + - valsInView); + float[] pts = new float[] { + 0f, yValue + valsInView / 2f + }; + + getTransformer(axis).pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, this); + } + + /** + * This will move the left side of the current viewport to the specified + * x-index on the x-axis, and center the viewport to the specified y-value + * on the y-axis. + * + * @param xIndex + * @param yValue + * @param axis - which axis should be used as a reference for the y-axis + */ + public void moveViewTo(int xIndex, float yValue, AxisDependency axis) { + + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float[] pts = new float[] { - xIndex - indicesInView / 2f, yVal + valsInView / 2f + xIndex, yValue + valsInView / 2f }; getTransformer(axis).pointValuesToPixel(pts); @@ -752,17 +831,17 @@ public OnDrawListener getDrawListener() { return mDrawListener; } - /** - * Sets the minimum scale values for both axes. This limits the extent to - * which the user can zoom-out. Scale 2f means the user cannot zoom out - * further than 2x zoom, ... Min = 1f - * - * @param scaleXmin - * @param scaleYmin - */ - public void setScaleMinima(float scaleXmin, float scaleYmin) { - mViewPortHandler.setScaleMinima(scaleXmin, scaleYmin, this); - } + // /** + // * Sets the minimum scale values for both axes. This limits the extent to + // * which the user can zoom-out. Scale 2f means the user cannot zoom out + // * further than 2x zoom, ... Min = 1f + // * + // * @param scaleXmin + // * @param scaleYmin + // */ + // public void setScaleMinima(float scaleXmin, float scaleYmin) { + // mViewPortHandler.setScaleMinima(scaleXmin, scaleYmin, this); + // } // /** // * Sets the effective range of y-values the chart can display. If this is diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 1f78bd79c4..1c7f00e05a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -164,7 +164,7 @@ public boolean onTouch(View v, MotionEvent event) { } // Perform the transformation, update the chart - mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart); + mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); return true; // indicate event was handled } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index 621db217cb..397e9dc501 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -219,7 +219,7 @@ public void run() { save.postTranslate(-x, -y); - refresh(save, chart); + refresh(save, chart, false); } }); } @@ -230,7 +230,7 @@ public void run() { * @param newMatrix * @return */ - public Matrix refresh(Matrix newMatrix, ChartInterface chart) { + public Matrix refresh(Matrix newMatrix, ChartInterface chart, boolean invalidate) { mMatrixTouch.set(newMatrix); @@ -295,27 +295,49 @@ public void limitTransAndScale(Matrix matrix, RectF content) { matrix.setValues(vals); } + + public void setMinimumScaleX(float xScale) { + + if (xScale < 1f) + xScale = 1f; - /** - * Sets the minimum scale values for both axes. This limits the extent to - * which the user can zoom-out. - * - * @param scaleXmin - * @param scaleYmin - */ - public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { - - if (scaleXmin < 1f) - scaleXmin = 1f; - if (scaleYmin < 1f) - scaleYmin = 1f; - - mMinScaleX = scaleXmin; - mMinScaleY = scaleYmin; + mMinScaleX = xScale; + + limitTransAndScale(mMatrixTouch, mContentRect); + } + + public void setMinimumScaleY(float yScale) { + + if (yScale < 1f) + yScale = 1f; - Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); - refresh(save, chart); + mMinScaleY = yScale; + + limitTransAndScale(mMatrixTouch, mContentRect); } + +// /** +// * Sets the minimum scale values for both axes. This limits the extent to +// * which the user can zoom-out. +// * +// * @param scaleXmin +// * @param scaleYmin +// */ +// public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { +// +// if (scaleXmin < 1f) +// scaleXmin = 1f; +// if (scaleYmin < 1f) +// scaleYmin = 1f; +// +// mMinScaleX = scaleXmin; +// mMinScaleY = scaleYmin; +//// +//// Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); +//// refresh(mMatrixTouch, chart); +// +// limitTransAndScale(mMatrixTouch, mContentRect); +// } public Matrix getMatrixTouch() { return mMatrixTouch; From fb11b6e07ccf7fd6448ba8833055a53da41a77c2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 15 Feb 2015 17:47:36 +0100 Subject: [PATCH 0084/1390] Added new realtime-chart example. --- MPChartExample/AndroidManifest.xml | 1 + .../layout/activity_realtime_linechart.xml | 11 ++ MPChartExample/res/menu/realtime.xml | 8 + .../mpchartexample/LineChartActivity1.java | 15 +- .../RealtimeLineChartActivity.java | 177 ++++++++++++++++++ .../notimportant/MainActivity.java | 10 +- .../mikephil/charting/data/ChartData.java | 32 +++- .../charting/renderer/ViewPortHandler.java | 40 ++-- .../charting/renderer/XAxisRenderer.java | 3 +- 9 files changed, 258 insertions(+), 39 deletions(-) create mode 100644 MPChartExample/res/layout/activity_realtime_linechart.xml create mode 100644 MPChartExample/res/menu/realtime.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 60adb59fd4..d1fe8ecc70 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -44,6 +44,7 @@ + diff --git a/MPChartExample/res/layout/activity_realtime_linechart.xml b/MPChartExample/res/layout/activity_realtime_linechart.xml new file mode 100644 index 0000000000..0f09b88325 --- /dev/null +++ b/MPChartExample/res/layout/activity_realtime_linechart.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/res/menu/realtime.xml new file mode 100644 index 0000000000..03f4e7c8a9 --- /dev/null +++ b/MPChartExample/res/menu/realtime.xml @@ -0,0 +1,8 @@ + +

+ + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3bb6ecd6c3..c79aa62ca2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -19,7 +19,6 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -73,16 +72,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); - // // enable / disable grid lines - // mChart.setDrawVerticalGrid(false); - // mChart.setDrawHorizontalGrid(false); - // - // // enable / disable grid background - // mChart.setDrawGridBackground(false); - // - // mChart.setDrawXLegend(false); - // mChart.setDrawYLegend(false); - // enable value highlighting mChart.setHighlightEnabled(true); @@ -109,10 +98,11 @@ protected void onCreate(Bundle savedInstanceState) { // enable/disable highlight indicators (the lines that indicate the // highlighted Entry) mChart.setHighlightIndicatorEnabled(false); - + // add data setData(45, 100); mChart.animateX(2500); +// mChart.setVisibleYRange(30, AxisDependency.LEFT); // // restrain the maximum scale-out factor // mChart.setScaleMinima(3f, 3f); @@ -282,7 +272,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - // redraw mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java new file mode 100644 index 0000000000..7c8786fe78 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -0,0 +1,177 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +public class RealtimeLineChartActivity extends DemoBase implements + OnChartValueSelectedListener { + + private LineChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_realtime_linechart); + + mChart = (LineChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + mChart.setValueTextColor(Color.WHITE); + + mChart.setDrawBorder(true); + mChart.setBorderPositions(new BorderPosition[] { + BorderPosition.BOTTOM + }); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable value highlighting + mChart.setHighlightEnabled(true); + + // enable touch gestures + mChart.setTouchEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + mChart.setDrawGridBackground(false); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(true); + + // set an alternative background color + mChart.setBackgroundColor(Color.LTGRAY); + + // add empty data + mChart.setData(new LineData()); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + // get the legend (only possible after setting data) + Legend l = mChart.getLegend(); + + // modify the legend ... + // l.setPosition(LegendPosition.LEFT_OF_CHART); + l.setForm(LegendForm.LINE); + l.setTypeface(tf); + l.setTextColor(Color.WHITE); + + XAxis xl = mChart.getXAxis(); + xl.setTypeface(tf); + xl.setTextColor(Color.WHITE); + xl.setDrawGridLines(false); + xl.setAvoidFirstLastClipping(true); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setTextColor(Color.WHITE); + leftAxis.setAxisMaxValue(120f); + leftAxis.setDrawGridLines(true); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setEnabled(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.realtime, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionAdd: { + addEntry(); + break; + } + } + return true; + } + + private int year = 15; + + private void addEntry() { + + LineData data = mChart.getData(); + + if (data != null) { + + LineDataSet set = data.getDataSetByIndex(0); + // set.addEntry(...); // can be called as well + + if (set == null) { + set = createSet(); + data.addDataSet(set); + } + + // add a new x-value first + data.addXValue(mMonths[data.getXValCount() % 12] + " " + (year + data.getXValCount() / 12)); + data.addEntry(new Entry((float) (Math.random() * 40) + 40f, set.getEntryCount()), 0); + + // let the chart know it's data has changed + mChart.notifyDataSetChanged(); + + // limit the number of visible entries + mChart.setVisibleXRange(6); + // mChart.setVisibleYRange(30, AxisDependency.LEFT); + + // move to the latest entry + mChart.moveViewToX(data.getXValCount()-7); + + // this automatically refreshes the chart (calls invalidate()) +// mChart.moveViewTo(data.getXValCount()-7, 55f, AxisDependency.LEFT); + + // redraw the chart +// mChart.invalidate(); + } + } + + private LineDataSet createSet() { + + LineDataSet set = new LineDataSet(null, "Dynamic Data"); + set.setAxisDependency(AxisDependency.LEFT); + set.setColor(ColorTemplate.getHoloBlue()); + set.setCircleColor(ColorTemplate.getHoloBlue()); + set.setLineWidth(2f); + set.setCircleSize(4f); + set.setFillAlpha(65); + set.setFillColor(ColorTemplate.getHoloBlue()); + set.setHighLightColor(Color.rgb(244, 117, 117)); + return set; + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex) { + Log.i("Entry selected", e.toString()); + } + + @Override + public void onNothingSelected() { + Log.i("Nothing selected", "Nothing selected."); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 66004618fa..9ec4919f1d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -37,6 +37,7 @@ import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; +import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; @@ -98,6 +99,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Colored Line Chart", "Shows a LineChart with different background and line color.")); + objects.add(new ContentItem( + "Realtime Chart", + "This chart is fed with new data in realtime.")); objects.add(new ContentItem( "Dynamical data adding", "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); @@ -198,7 +202,11 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 19: + case 19 : + i = new Intent(this, RealtimeLineChartActivity.class); + startActivity(i); + break; + case 20: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9ca91d0573..bb05af080b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -47,7 +47,7 @@ public abstract class ChartData> { /** array that holds all DataSets the ChartData object represents */ protected ArrayList mDataSets; - + public ChartData() { mXVals = new ArrayList(); mDataSets = new ArrayList(); @@ -248,13 +248,7 @@ protected void calcMinMax(ArrayList dataSets) { } // in case there is only one axis, adjust the second axis - if (firstLeft == null) { - mLeftAxisMax = mRightAxisMax; - mLeftAxisMin = mRightAxisMin; - } else if (firstRight == null) { - mRightAxisMax = mLeftAxisMax; - mRightAxisMin = mLeftAxisMin; - } + handleEmptyAxis(firstLeft, firstRight); } } @@ -571,6 +565,26 @@ public void addDataSet(T d) { if (mRightAxisMin > d.getYMin()) mRightAxisMin = d.getYMin(); } + + handleEmptyAxis(getFirstLeft(), getFirstRight()); + } + + /** + * This adjusts the other axis if one axis is empty and the other is not. + * + * @param firstLeft + * @param firstRight + */ + private void handleEmptyAxis(T firstLeft, T firstRight) { + + // in case there is only one axis, adjust the second axis + if (firstLeft == null) { + mLeftAxisMax = mRightAxisMax; + mLeftAxisMin = mRightAxisMin; + } else if (firstRight == null) { + mRightAxisMax = mLeftAxisMax; + mRightAxisMin = mLeftAxisMin; + } } /** @@ -659,6 +673,8 @@ public void addEntry(Entry e, int dataSetIndex) { mRightAxisMin = e.getVal(); } + handleEmptyAxis(getFirstLeft(), getFirstRight()); + // add the entry to the dataset set.addEntry(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index 397e9dc501..4e74a56f14 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -205,23 +205,33 @@ public Matrix fitScreen() { */ public synchronized void centerViewPort(final float[] transformedPts, final ChartInterface chart) { - final View v = chart.getChartView(); - - v.post(new Runnable() { - - @Override - public void run() { - Matrix save = new Matrix(); - save.set(mMatrixTouch); - - final float x = transformedPts[0] - offsetLeft(); - final float y = transformedPts[1] - offsetTop(); + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + final float x = transformedPts[0] - offsetLeft(); + final float y = transformedPts[1] - offsetTop(); - save.postTranslate(-x, -y); + save.postTranslate(-x, -y); - refresh(save, chart, false); - } - }); + refresh(save, chart, false); + +// final View v = chart.getChartView(); +// +// v.post(new Runnable() { +// +// @Override +// public void run() { +// Matrix save = new Matrix(); +// save.set(mMatrixTouch); +// +// final float x = transformedPts[0] - offsetLeft(); +// final float y = transformedPts[1] - offsetTop(); +// +// save.postTranslate(-x, -y); +// +// refresh(save, chart, false); +// } +// }); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index df5e2175b6..7faf175d70 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.Paint.Align; import com.github.mikephil.charting.components.XAxis; @@ -107,7 +106,7 @@ protected void drawLabels(Canvas c, float yPos) { if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mXAxis.getValues().size() - 1) { + if (i == mXAxis.getValues().size() - 1 && mXAxis.getValues().size() > 1) { float width = Utils.calcTextWidth(mAxisPaint, label); if (width > mViewPortHandler.offsetRight() * 2 From 58ad281d635c4d8d9aa79f3c7a83b82a66cd8216 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Feb 2015 16:15:52 +0100 Subject: [PATCH 0085/1390] Worked on combined charts. --- MPChartExample/AndroidManifest.xml | 1 + .../res/layout/activity_combined.xml | 11 ++ .../mpchartexample/CombinedChartActivity.java | 88 +++++++++++ .../mpchartexample/LineChartActivity1.java | 1 + .../mpchartexample/ScatterChartActivity.java | 3 + .../notimportant/MainActivity.java | 40 ++--- .../mikephil/charting/charts/BarChart.java | 8 +- .../charting/charts/BarLineChartBase.java | 44 ++++++ .../charting/charts/CandleStickChart.java | 8 +- .../mikephil/charting/charts/Chart.java | 1 - .../charting/charts/CombinedChart.java | 137 ++++++++++++++++++ .../mikephil/charting/charts/LineChart.java | 65 ++------- .../charting/charts/PieRadarChartBase.java | 12 ++ .../charting/charts/ScatterChart.java | 29 ++-- .../mikephil/charting/data/ChartData.java | 34 ++--- .../mikephil/charting/data/CombinedData.java | 71 +++++++++ .../github/mikephil/charting/data/Data.java | 5 + .../mikephil/charting/data/LineData.java | 12 +- .../mikephil/charting/data/LineDataSet.java | 2 +- .../charting/data/LineRadarDataSet.java | 2 +- .../charting/interfaces/BarDataProvider.java | 12 ++ .../BarLineScatterCandleDataProvider.java | 10 ++ .../interfaces/CandleDataProvider.java | 8 + .../charting/interfaces/ChartInterface.java | 10 +- .../charting/interfaces/LineDataProvider.java | 34 +++++ .../interfaces/ScatterDataProvider.java | 9 ++ .../charting/renderer/BarChartRenderer.java | 98 +++++++------ .../renderer/CandleStickChartRenderer.java | 10 +- .../renderer/CombinedChartRenderer.java | 90 ++++++++++++ .../charting/renderer/LineChartRenderer.java | 58 ++++---- .../renderer/ScatterChartRenderer.java | 24 +-- .../mikephil/charting/utils/Transformer.java | 31 +++- 32 files changed, 767 insertions(+), 201 deletions(-) create mode 100644 MPChartExample/res/layout/activity_combined.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/Data.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index d1fe8ecc70..799037bfd8 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -45,6 +45,7 @@ + diff --git a/MPChartExample/res/layout/activity_combined.xml b/MPChartExample/res/layout/activity_combined.xml new file mode 100644 index 0000000000..2c7e9b16ba --- /dev/null +++ b/MPChartExample/res/layout/activity_combined.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java new file mode 100644 index 0000000000..c2b25a1928 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -0,0 +1,88 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.CombinedChart; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class CombinedChartActivity extends DemoBase { + + private CombinedChart mChart; + private final int itemcount = 12; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_combined); + + mChart = (CombinedChart) findViewById(R.id.chart1); + mChart.setDescription(""); + mChart.setDrawGridBackground(false); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setDrawGridLines(false); + + CombinedData data = new CombinedData(mMonths); + + data.setData(generateLineData()); + data.setData(generateBarData()); + + mChart.setData(data); + mChart.invalidate(); + } + + private LineData generateLineData() { + + LineData d = new LineData(); + + ArrayList entries = new ArrayList(); + + for (int index = 0; index < itemcount; index++) + entries.add(new Entry(getRandom(), index)); + + LineDataSet set = new LineDataSet(entries, "Line DataSet"); + set.setColor(Color.RED); + set.setLineWidth(2.5f); + set.setCircleColor(Color.RED); + set.setCircleSize(5f); + set.setFillColor(Color.RED); + set.setDrawCubic(true); + d.addDataSet(set); + + return d; + } + + private BarData generateBarData() { + + BarData d = new BarData(); + + ArrayList entries = new ArrayList(); + + for (int index = 0; index < itemcount; index++) + entries.add(new BarEntry(getRandom(), index)); + + BarDataSet set = new BarDataSet(entries, "Bar DataSet"); + d.addDataSet(set); + + return d; + } + + private float getRandom() { + return (float) (Math.random() * 20f) + 25f; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index c79aa62ca2..ada8d02af2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 86341c9801..03b8ddfd45 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -81,9 +81,12 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); + + mChart.getAxisRight().setEnabled(false); XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); + xl.setDrawGridLines(false); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 9ec4919f1d..0a64fefa3a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -24,6 +24,7 @@ import com.xxmassdeveloper.mpchartexample.BarChartActivity; import com.xxmassdeveloper.mpchartexample.BarChartActivityMultiDataset; import com.xxmassdeveloper.mpchartexample.CandleStickChartActivity; +import com.xxmassdeveloper.mpchartexample.CombinedChartActivity; import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; @@ -63,6 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Line Chart 2", "Another simple demonstration of the linechart.")); objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); objects.add(new ContentItem("Horizontal Bar Chart", "A simple demonstration of the horizontal bar chart.")); + objects.add(new ContentItem("Combined Chart", "Demonstrates how to create a combined chart.")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Stacked Bar Chart", @@ -136,31 +138,35 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, HorizontalBarChartActivity.class); startActivity(i); break; - case 4: - i = new Intent(this, PieChartActivity.class); + case 4: + i = new Intent(this, CombinedChartActivity.class); startActivity(i); break; case 5: - i = new Intent(this, ScatterChartActivity.class); + i = new Intent(this, PieChartActivity.class); startActivity(i); break; case 6: - i = new Intent(this, StackedBarActivity.class); + i = new Intent(this, ScatterChartActivity.class); startActivity(i); break; case 7: - i = new Intent(this, AnotherBarActivity.class); + i = new Intent(this, StackedBarActivity.class); startActivity(i); break; case 8: - i = new Intent(this, MultiLineChartActivity.class); + i = new Intent(this, AnotherBarActivity.class); startActivity(i); break; case 9: - i = new Intent(this, BarChartActivityMultiDataset.class); + i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; case 10: + i = new Intent(this, BarChartActivityMultiDataset.class); + startActivity(i); + break; + case 11: // i = new Intent(this, DrawChartActivity.class); // startActivity(i); @@ -170,43 +176,43 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { b.setPositiveButton("OK", null); b.create().show(); break; - case 11: + case 12: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 12: + case 13: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 13: + case 14: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 14: + case 15: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 15: + case 16: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 16: + case 17: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 17: + case 18: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 18: + case 19: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 19 : + case 20 : i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; - case 20: + case 21: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 218b127a5b..547a7d3965 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; import com.github.mikephil.charting.utils.Highlight; @@ -26,7 +27,7 @@ * * @author Philipp Jahoda */ -public class BarChart extends BarLineChartBase { +public class BarChart extends BarLineChartBase implements BarDataProvider { // /** indicates the angle of the 3d effect */ // private float mSkew = 0.3f; @@ -335,4 +336,9 @@ public void setDrawBarShadow(boolean enabled) { public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; } + + @Override + public BarData getBarData() { + return mData; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 01ab415d01..d01e60a709 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -24,11 +24,14 @@ import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.interfaces.OnDrawListener; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; +import com.github.mikephil.charting.utils.FillFormatter; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelInfo; @@ -1480,4 +1483,45 @@ public Paint getPaint(int which) { return null; } + + /** + * Default formatter that calculates the position of the filled line. + * + * @author Philipp Jahoda + */ + protected class DefaultFillFormatter implements FillFormatter { + + @Override + public float getFillLinePosition(LineDataSet dataSet, LineData data, + float chartMaxY, float chartMinY) { + + float fillMin = 0f; + + if (dataSet.getYMax() > 0 && dataSet.getYMin() < 0) { + fillMin = 0f; + } else { + + if (!getAxis(dataSet.getAxisDependency()).isStartAtZeroEnabled()) { + + float max, min; + + if (data.getYMax() > 0) + max = 0f; + else + max = chartMaxY; + if (data.getYMin() < 0) + min = 0f; + else + min = chartMinY; + + fillMin = dataSet.getYMin() >= 0 ? min : max; + } else { + fillMin = 0f; + } + + } + + return fillMin; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 1e41a8e165..a6178ec491 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -5,6 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.interfaces.CandleDataProvider; import com.github.mikephil.charting.renderer.CandleStickChartRenderer; /** @@ -12,7 +13,7 @@ * * @author Philipp Jahoda */ -public class CandleStickChart extends BarLineChartBase { +public class CandleStickChart extends BarLineChartBase implements CandleDataProvider { public CandleStickChart(Context context) { super(context); @@ -40,4 +41,9 @@ protected void calcMinMax() { // increase deltax by 1 because the candles have a width of 1 mDeltaX++; } + + @Override + public CandleData getCandleData() { + return mData; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index d059b87176..bdeda49498 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1688,7 +1688,6 @@ public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * - * @param xIndex * @return */ public ArrayList getYValsAtIndex(int xIndex) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java new file mode 100644 index 0000000000..01e8d9d2c0 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -0,0 +1,137 @@ + +package com.github.mikephil.charting.charts; + +import android.content.Context; +import android.util.AttributeSet; + +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.CandleDataProvider; +import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.ScatterDataProvider; +import com.github.mikephil.charting.renderer.CombinedChartRenderer; +import com.github.mikephil.charting.utils.FillFormatter; + +public class CombinedChart extends BarLineChartBase implements LineDataProvider, + BarDataProvider, ScatterDataProvider, CandleDataProvider { + + private float mXAxisInset = 0f; + + private FillFormatter mFillFormatter; + + public CombinedChart(Context context) { + super(context); + } + + public CombinedChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CombinedChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + mFillFormatter = new DefaultFillFormatter(); + // mRenderer = new CombinedChartRenderer(this, mAnimator, + // mViewPortHandler); + } + + @Override + protected void calcMinMax() { + super.calcMinMax(); + + if (getBarData() != null) { + mDeltaX += 1; + mXAxisInset = 0.5f; + mXAxis.setCenterXLabelText(true); + } + } + + @Override + public void setData(CombinedData data) { + super.setData(data); + mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); + } + + public void setFillFormatter(FillFormatter formatter) { + + if (formatter == null) + formatter = new DefaultFillFormatter(); + else + mFillFormatter = formatter; + } + + @Override + public FillFormatter getFillFormatter() { + return mFillFormatter; + } + + @Override + public LineData getLineData() { + if (mData == null) + return null; + return mData.getLineData(); + } + + @Override + public BarData getBarData() { + if (mData == null) + return null; + return mData.getBarData(); + } + + @Override + public ScatterData getScatterData() { + if (mData == null) + return null; + return mData.getScatterData(); + } + + @Override + public CandleData getCandleData() { + if (mData == null) + return null; + return mData.getCandleData(); + } + + @Override + public boolean isDrawBarShadowEnabled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isDrawValueAboveBarEnabled() { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean isDrawHighlightArrowEnabled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isDrawValuesForWholeStackEnabled() { + // TODO Auto-generated method stub + return false; + } + + @Override + public float getXAxisInset() { + return mXAxisInset; + } + + public void setXAxisInset(float inset) { + mXAxisInset = inset; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 47447a508b..137d5bf389 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; import com.github.mikephil.charting.utils.FillFormatter; @@ -15,7 +16,7 @@ * * @author Philipp Jahoda */ -public class LineChart extends BarLineChartBase { +public class LineChart extends BarLineChartBase implements LineDataProvider { /** the width of the highlighning line */ protected float mHighlightWidth = 3f; @@ -100,12 +101,7 @@ public Paint getPaint(int which) { return null; } - /** - * Sets a custom FillFormatter to the chart that handles the position of the - * filled-line for each DataSet. Set this to null to use the default logic. - * - * @param formatter - */ + @Override public void setFillFormatter(FillFormatter formatter) { if (formatter == null) @@ -114,53 +110,18 @@ public void setFillFormatter(FillFormatter formatter) { mFillFormatter = formatter; } - /** - * Returns the FillFormatter that handles the position of the filled-line. - * - * @return - */ + @Override public FillFormatter getFillFormatter() { return mFillFormatter; } - - /** - * Default formatter that calculates the position of the filled line. - * - * @author Philipp Jahoda - */ - private class DefaultFillFormatter implements FillFormatter { - - @Override - public float getFillLinePosition(LineDataSet dataSet, LineData data, - float chartMaxY, float chartMinY) { - - float fillMin = 0f; - - if (dataSet.getYMax() > 0 && dataSet.getYMin() < 0) { - fillMin = 0f; - } else { - - if (!getAxis(dataSet.getAxisDependency()).isStartAtZeroEnabled()) { - - float max, min; - - if (data.getYMax() > 0) - max = 0f; - else - max = chartMaxY; - if (data.getYMin() < 0) - min = 0f; - else - min = chartMinY; - - fillMin = dataSet.getYMin() >= 0 ? min : max; - } else { - fillMin = 0f; - } - - } - - return fillMin; - } + + @Override + public float getXAxisInset() { + return 0f; + } + + @Override + public LineData getLineData() { + return mData; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 7745d60fe2..ef0b13abe1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -423,6 +423,18 @@ private float getFullLegendWidth() { public void setOnTouchListener(OnTouchListener l) { this.mListener = l; } + + @Override + public float getYChartMax() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public float getYChartMin() { + // TODO Auto-generated method stub + return 0; + } /** * ################ ################ ################ ################ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 84c2963476..9dea2dbc11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -5,6 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.interfaces.ScatterDataProvider; import com.github.mikephil.charting.renderer.ScatterChartRenderer; /** @@ -13,7 +14,7 @@ * * @author Philipp Jahoda */ -public class ScatterChart extends BarLineChartBase { +public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { /** enum that defines the shape that is drawn where the values are */ public enum ScatterShape { @@ -39,17 +40,17 @@ protected void init() { mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); } - @Override - protected void calculateOffsets() { - super.calculateOffsets(); - - float offset = mData.getGreatestShapeSize() / 2f; - mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, - mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, - mViewPortHandler.offsetBottom()); - - prepareOffsetMatrix(); - } +// @Override +// protected void calculateOffsets() { +// super.calculateOffsets(); +// +// float offset = mData.getGreatestShapeSize() / 2f; +// mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, +// mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, +// mViewPortHandler.offsetBottom()); +// +// prepareOffsetMatrix(); +// } @Override protected void calcMinMax() { @@ -69,4 +70,8 @@ public static ScatterShape[] getAllPossibleShapes() { ScatterShape.SQUARE, ScatterShape.CIRCLE, ScatterShape.TRIANGLE, ScatterShape.CROSS }; } + + public ScatterData getScatterData() { + return mData; + }; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index bb05af080b..bf3c7a9294 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -14,7 +14,7 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> { +public abstract class ChartData> extends Data { /** maximum y-value in the y-value array */ protected float mYMax = 0.0f; @@ -62,7 +62,7 @@ public ChartData() { public ChartData(ArrayList xVals) { this.mXVals = xVals; this.mDataSets = new ArrayList(); - init(); + init(mDataSets); } /** @@ -74,7 +74,7 @@ public ChartData(ArrayList xVals) { public ChartData(String[] xVals) { this.mXVals = arrayToArrayList(xVals); this.mDataSets = new ArrayList(); - init(); + init(mDataSets); } /** @@ -89,7 +89,7 @@ public ChartData(ArrayList xVals, ArrayList sets) { this.mXVals = xVals; this.mDataSets = sets; - init(); + init(mDataSets); } /** @@ -104,7 +104,7 @@ public ChartData(String[] xVals, ArrayList sets) { this.mXVals = arrayToArrayList(xVals); this.mDataSets = sets; - init(); + init(mDataSets); } /** @@ -127,13 +127,13 @@ private ArrayList arrayToArrayList(String[] array) { * performs all kinds of initialization calculations, such as min-max and * value count and sum */ - private void init() { + protected void init(ArrayList> dataSets) { - isLegal(mDataSets); + isLegal(dataSets); - calcMinMax(mDataSets); - calcYValueSum(mDataSets); - calcYValueCount(mDataSets); + calcMinMax(dataSets); + calcYValueSum(dataSets); + calcYValueCount(dataSets); calcXValAverageLength(); } @@ -163,7 +163,7 @@ private void calcXValAverageLength() { * * @param dataSets */ - private void isLegal(ArrayList dataSets) { + private void isLegal(ArrayList> dataSets) { if (dataSets == null) return; @@ -183,13 +183,13 @@ private void isLegal(ArrayList dataSets) { * changed. */ public void notifyDataChanged() { - init(); + init(mDataSets); } /** * calc minimum and maximum y value over all datasets */ - protected void calcMinMax(ArrayList dataSets) { + protected void calcMinMax(ArrayList> dataSets) { if (dataSets == null || dataSets.size() < 1) { @@ -217,7 +217,7 @@ protected void calcMinMax(ArrayList dataSets) { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - for (T dataSet : dataSets) { + for (DataSet dataSet : dataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -236,7 +236,7 @@ protected void calcMinMax(ArrayList dataSets) { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - for (T dataSet : dataSets) { + for (DataSet dataSet : dataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -255,7 +255,7 @@ protected void calcMinMax(ArrayList dataSets) { /** * calculates the sum of all y-values in all datasets */ - protected void calcYValueSum(ArrayList dataSets) { + protected void calcYValueSum(ArrayList>dataSets) { mYValueSum = 0; @@ -273,7 +273,7 @@ protected void calcYValueSum(ArrayList dataSets) { * * @return */ - protected void calcYValueCount(ArrayList dataSets) { + protected void calcYValueCount(ArrayList> dataSets) { mYValCount = 0; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java new file mode 100644 index 0000000000..13cfbacb8b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -0,0 +1,71 @@ +package com.github.mikephil.charting.data; + +import java.util.ArrayList; + +public class CombinedData extends BarLineScatterCandleData> { + + private LineData mLineData; + private BarData mBarData; + private ScatterData mScatterData; + private CandleData mCandleData; + + public CombinedData() { + super(); + } + + public CombinedData(ArrayList xVals) { + super(xVals); + } + + public CombinedData(String[] xVals) { + super(xVals); + } + + public void setData(LineData data) { + mLineData = data; + mDataSets.addAll(data.getDataSets()); + init(data.getDataSets()); + } + + public void setData(BarData data) { + mBarData = data; + mDataSets.addAll(data.getDataSets()); + init(data.getDataSets()); + } + + public void setData(ScatterData data) { + mScatterData = data; + mDataSets.addAll(data.getDataSets()); + init(data.getDataSets()); + } + + public void setData(CandleData data) { + mCandleData = data; + mDataSets.addAll(data.getDataSets()); + init(data.getDataSets()); + } + + public LineData getLineData() { + return mLineData; + } + + public BarData getBarData() { + return mBarData; + } + + public ScatterData getScatterData() { + return mScatterData; + } + + public CandleData getCandleData() { + return mCandleData; + } + + @Override + public void notifyDataChanged() { + mLineData.notifyDataChanged(); + mBarData.notifyDataChanged(); + mCandleData.notifyDataChanged(); + mScatterData.notifyDataChanged(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/Data.java b/MPChartLib/src/com/github/mikephil/charting/data/Data.java new file mode 100644 index 0000000000..5ddc9e14b1 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/Data.java @@ -0,0 +1,5 @@ +package com.github.mikephil.charting.data; + +public abstract class Data> { + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index d37a1a08af..5ee6fc702e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -8,11 +8,11 @@ public class LineData extends BarLineScatterCandleData { public LineData() { super(); } - + public LineData(ArrayList xVals) { super(xVals); } - + public LineData(String[] xVals) { super(xVals); } @@ -24,15 +24,15 @@ public LineData(ArrayList xVals, ArrayList dataSets) { public LineData(String[] xVals, ArrayList dataSets) { super(xVals, dataSets); } - + public LineData(ArrayList xVals, LineDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toArrayList(dataSet)); } - + public LineData(String[] xVals, LineDataSet dataSet) { super(xVals, toArrayList(dataSet)); } - + private static ArrayList toArrayList(LineDataSet dataSet) { ArrayList sets = new ArrayList(); sets.add(dataSet); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index a583c5426c..60220a3ac5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -16,7 +16,7 @@ public class LineDataSet extends LineRadarDataSet { private ArrayList mCircleColors = null; /** the radius of the circle-shaped value indicators */ - private float mCircleSize = 4f; + private float mCircleSize = 8f; /** sets the intensity of the cubic lines */ private float mCubicIntensity = 0.2f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 8c7b656b45..867483c273 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -21,7 +21,7 @@ public abstract class LineRadarDataSet extends BarLineScatterCa private int mFillAlpha = 85; /** the width of the drawn data lines */ - private float mLineWidth = 1f; + private float mLineWidth = 2.5f; /** if true, the data will also be drawn filled */ private boolean mDrawFilled = false; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java new file mode 100644 index 0000000000..6b9b19da8d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java @@ -0,0 +1,12 @@ +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.data.BarData; + +public interface BarDataProvider extends BarLineScatterCandleDataProvider { + + public BarData getBarData(); + public boolean isDrawBarShadowEnabled(); + public boolean isDrawValueAboveBarEnabled(); + public boolean isDrawHighlightArrowEnabled(); + public boolean isDrawValuesForWholeStackEnabled(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java new file mode 100644 index 0000000000..584ac129d7 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java @@ -0,0 +1,10 @@ +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.utils.Transformer; + +public interface BarLineScatterCandleDataProvider extends ChartInterface { + + public Transformer getTransformer(AxisDependency axis); + public int getMaxVisibleCount(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java new file mode 100644 index 0000000000..7e58121f8f --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java @@ -0,0 +1,8 @@ +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.data.CandleData; + +public interface CandleDataProvider extends BarLineScatterCandleDataProvider { + + public CandleData getCandleData(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index daf7de0114..e30e698cb2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -5,6 +5,8 @@ import android.graphics.RectF; import android.view.View; +import com.github.mikephil.charting.utils.ValueFormatter; + /** * Interface that provides everything there is to know about the dimensions, * bounds, and range of the chart. @@ -16,7 +18,7 @@ public interface ChartInterface { // public float getOffsetBottom(); // // public float getOffsetTop(); -// +// // public float getOffsetLeft(); // // public float getOffsetRight(); @@ -25,9 +27,9 @@ public interface ChartInterface { // public float getDeltaY(); -// public float getYChartMin(); + public float getYChartMin(); -// public float getYChartMax(); + public float getYChartMax(); public int getWidth(); @@ -42,4 +44,6 @@ public interface ChartInterface { public RectF getContentRect(); public View getChartView(); + + public ValueFormatter getValueFormatter(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java new file mode 100644 index 0000000000..6186d026ab --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -0,0 +1,34 @@ + +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.utils.FillFormatter; + +public interface LineDataProvider extends BarLineScatterCandleDataProvider { + + public LineData getLineData(); + + /** + * Sets a custom FillFormatter to the chart that handles the position of the + * filled-line for each DataSet. Set this to null to use the default logic. + * + * @param formatter + */ + public void setFillFormatter(FillFormatter formatter); + + /** + * Returns the FillFormatter that handles the position of the filled-line. + * + * @return + */ + public FillFormatter getFillFormatter(); + + /** + * Returns the inset the chart should have on the x-axis. Inset of e.g. 1f + * would mean all values of this LineChart are shifted 1 x-index to the + * right. + * + * @return + */ + public float getXAxisInset(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java new file mode 100644 index 0000000000..a5570f1483 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.data.ScatterData; + +public interface ScatterDataProvider extends BarLineScatterCandleDataProvider { + + public ScatterData getScatterData(); + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index b54f22d26a..973640af4a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.renderer; + import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -12,28 +13,28 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; - public class BarChartRenderer extends DataRenderer { - protected BarChart mChart; - + protected BarDataProvider mChart; + /** the rect object that is used for drawing the bar shadow */ protected RectF mBarShadow = new RectF(); /** the rect object that is used for drawing the bars */ protected RectF mBarRect = new RectF(); - public BarChartRenderer(BarChart chart, ChartAnimator animator, + public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); this.mChart = chart; - + mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.FILL); mHighlightPaint.setColor(Color.rgb(0, 0, 0)); @@ -43,26 +44,26 @@ public BarChartRenderer(BarChart chart, ChartAnimator animator, @Override public void drawData(Canvas c) { - - BarData barData = mChart.getData(); - - for(int i = 0; i < barData.getDataSetCount(); i++) { - + + BarData barData = mChart.getBarData(); + + for (int i = 0; i < barData.getDataSetCount(); i++) { + BarDataSet set = barData.getDataSetByIndex(i); - - if(set.isVisible()) { + + if (set.isVisible()) { drawDataSet(c, set, i); } } } - + private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { - + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - + // the space between bar-groups - float space = mChart.getData().getGroupSpace(); - + float space = mChart.getBarData().getGroupSpace(); + boolean noStacks = dataSet.getStackSize() == 1 ? true : false; ArrayList entries = dataSet.getYVals(); @@ -73,7 +74,8 @@ private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { BarEntry e = entries.get(j); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + j * (mChart.getData().getDataSetCount() - 1) + index + space * j + space / 2f; + float x = e.getXIndex() + j * (mChart.getBarData().getDataSetCount() - 1) + index + + space * j + space / 2f; float y = e.getVal(); // no stacks @@ -150,7 +152,6 @@ private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { } } } - /** * Prepares a bar for drawing on the specified x-index and y-position. Also @@ -174,40 +175,44 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { // if a shadow is drawn, prepare it too if (mChart.isDrawBarShadowEnabled()) { - mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, mViewPortHandler.contentBottom()); + mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, + mViewPortHandler.contentBottom()); } } @Override public void drawValues(Canvas c) { // if values are drawn - if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + if (mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getData().getDataSets(); + ArrayList dataSets = mChart.getBarData().getDataSets(); float posOffset = 0f; float negOffset = 0f; + boolean drawValueAboveBar = mChart.isDrawValueAboveBarEnabled(); // calculate the correct offset depending on the draw position of // the value - posOffset = (mChart.isDrawValueAboveBarEnabled() ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight(mValuePaint, + posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( + mValuePaint, "8") * 1.5f); - negOffset = (mChart.isDrawValueAboveBarEnabled() ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils + negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils .convertDpToPixel(5)); - for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { BarDataSet dataSet = dataSets.get(i); - - if(!dataSet.isDrawValuesEnabled()) + + if (!dataSet.isDrawValuesEnabled()) continue; - + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - + ArrayList entries = dataSet.getYVals(); - float[] valuePoints = trans.generateTransformedValuesBarChart(entries, i, mChart.getData(), + float[] valuePoints = trans.generateTransformedValuesBarChart(entries, i, + mChart.getBarData(), mAnimator.getPhaseY()); // if only single values are drawn (sum) @@ -215,10 +220,11 @@ public void drawValues(Canvas c) { for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) break; - if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) + || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) continue; float val = entries.get(j / 2).getVal(); @@ -232,10 +238,11 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) break; - if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) + || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) continue; BarEntry e = entries.get(j / 2); @@ -277,7 +284,6 @@ public void drawValues(Canvas c) { } } } - /** * Draws a value at the specified x and y position. @@ -290,16 +296,17 @@ private void drawValue(Canvas c, float val, float xPos, float yPos) { String value = mChart.getValueFormatter().getFormattedValue(val); c.drawText(value, xPos, yPos, - mValuePaint); + mValuePaint); } @Override - public void drawExtras(Canvas c) { } + public void drawExtras(Canvas c) { + } @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - - int setCount = mChart.getData().getDataSetCount(); + + int setCount = mChart.getBarData().getDataSetCount(); for (int i = 0; i < indices.length; i++) { @@ -307,26 +314,27 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int index = h.getXIndex(); int dataSetIndex = h.getDataSetIndex(); - BarDataSet set = mChart.getData().getDataSetByIndex(dataSetIndex); + BarDataSet set = mChart.getBarData().getDataSetByIndex(dataSetIndex); if (set == null) continue; - + Transformer trans = mChart.getTransformer(set.getAxisDependency()); mHighlightPaint.setColor(set.getHighLightColor()); mHighlightPaint.setAlpha(set.getHighLightAlpha()); // check outofbounds - if (index < mChart.getData().getYValCount() && index >= 0 + if (index < mChart.getBarData().getYValCount() && index >= 0 && index < (mChart.getDeltaX() * mAnimator.getPhaseX()) / setCount) { - Entry e = mChart.getEntryByDataSetIndex(index, dataSetIndex); + Entry e = mChart.getBarData().getDataSetByIndex(dataSetIndex) + .getEntryForXIndex(index); if (e == null) continue; - - float groupspace = mChart.getData().getGroupSpace(); + + float groupspace = mChart.getBarData().getGroupSpace(); // calculate the correct x-position float x = index * setCount + dataSetIndex + groupspace / 2f diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 155c4d6f80..a4ed5143f2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -5,10 +5,10 @@ import android.graphics.Paint; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.CandleStickChart; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.CandleDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -16,9 +16,9 @@ public class CandleStickChartRenderer extends DataRenderer { - protected CandleStickChart mChart; + protected CandleDataProvider mChart; - public CandleStickChartRenderer(CandleStickChart chart, ChartAnimator animator, + public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -27,7 +27,7 @@ public CandleStickChartRenderer(CandleStickChart chart, ChartAnimator animator, @Override public void drawData(Canvas c) { - CandleData candleData = mChart.getData(); + CandleData candleData = mChart.getCandleData(); for (CandleDataSet set : candleData.getDataSets()) { @@ -156,7 +156,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int xIndex = indices[i].getXIndex(); // get the // x-position - CandleDataSet set = mChart.getData().getDataSetByIndex(indices[i].getDataSetIndex()); + CandleDataSet set = mChart.getCandleData().getDataSetByIndex(indices[i].getDataSetIndex()); if (set == null) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java new file mode 100644 index 0000000000..95cec1f090 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -0,0 +1,90 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.CombinedChart; +import com.github.mikephil.charting.utils.Highlight; + +public class CombinedChartRenderer extends DataRenderer { + + private LineChartRenderer mLineRenderer; + private BarChartRenderer mBarRenderer; + private CandleStickChartRenderer mCandleRenderer; + private ScatterChartRenderer mScatterRenderer; + + public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + + if (chart.getLineData() != null) + mLineRenderer = new LineChartRenderer(chart, animator, viewPortHandler); + + if (chart.getBarData() != null) + mBarRenderer = new BarChartRenderer(chart, animator, viewPortHandler); + + if (chart.getScatterData() != null) + mScatterRenderer = new ScatterChartRenderer(chart, animator, viewPortHandler); + + if (chart.getCandleData() != null) + mCandleRenderer = new CandleStickChartRenderer(chart, animator, viewPortHandler); + } + + @Override + public void drawData(Canvas c) { + + if (mBarRenderer != null) + mBarRenderer.drawData(c); + + if (mCandleRenderer != null) + mCandleRenderer.drawData(c); + + if (mLineRenderer != null) + mLineRenderer.drawData(c); + + if (mScatterRenderer != null) + mScatterRenderer.drawData(c); + } + + @Override + public void drawValues(Canvas c) { + + if (mBarRenderer != null) + mBarRenderer.drawValues(c); + + if (mCandleRenderer != null) + mCandleRenderer.drawValues(c); + + if (mLineRenderer != null) + mLineRenderer.drawValues(c); + + if (mScatterRenderer != null) + mScatterRenderer.drawValues(c); + } + + @Override + public void drawExtras(Canvas c) { + + if (mBarRenderer != null) + mBarRenderer.drawExtras(c); + + if (mCandleRenderer != null) + mCandleRenderer.drawExtras(c); + + if (mLineRenderer != null) + mLineRenderer.drawExtras(c); + + if (mScatterRenderer != null) + mScatterRenderer.drawExtras(c); + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + // mBarRenderer.drawHighlighted(c, indices); + // mCandleRenderer.drawHighlighted(c, indices); + // mLineRenderer.drawHighlighted(c, indices); + // mScatterRenderer.drawHighlighted(c, indices); + } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 67efd727ab..d71205fed7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -18,12 +19,12 @@ public class LineChartRenderer extends DataRenderer { - protected LineChart mChart; + protected LineDataProvider mChart; /** paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; - public LineChartRenderer(LineChart chart, ChartAnimator animator, + public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -36,7 +37,7 @@ public LineChartRenderer(LineChart chart, ChartAnimator animator, @Override public void drawData(Canvas c) { - LineData lineData = mChart.getData(); + LineData lineData = mChart.getLineData(); for (LineDataSet set : lineData.getDataSets()) { @@ -106,10 +107,12 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Path spline = new Path(); ArrayList points = new ArrayList(); + + float inset = mChart.getXAxisInset(); for (Entry e : entries) { if (e != null) - points.add(new CPoint(e.getXIndex(), e.getVal())); + points.add(new CPoint(e.getXIndex() + inset, e.getVal())); } if (points.size() > 1) { @@ -160,12 +163,15 @@ else if (j == points.size() - 1) { } protected void drawCubicFill(LineDataSet dataSet, Path spline) { + + float inset = mChart.getXAxisInset(); + float fillMin = mChart.getFillFormatter() - .getFillLinePosition(dataSet, mChart.getData(), mChart.getYChartMax(), + .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo((mChart.getDeltaX() + 1) * mAnimator.getPhaseX(), fillMin); - spline.lineTo(0, fillMin); + spline.lineTo(dataSet.getYVals().get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())).getXIndex() + inset, fillMin); + spline.lineTo(inset, fillMin); spline.close(); mRenderPaint.setStyle(Paint.Style.FILL); @@ -183,8 +189,8 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie // more than 1 color if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { - float[] positions = trans.generateTransformedValuesLineScatter( - entries, phaseY); + float[] positions = trans.generateTransformedValuesLine( + entries, phaseY, mChart.getXAxisInset()); for (int j = 0; j < (positions.length - 2) * phaseX; j += 2) { @@ -239,7 +245,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en Path filled = generateFilledPath( entries, - mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getData(), + mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin())); trans.pathValueToPixel(filled); @@ -261,20 +267,21 @@ private Path generateFilledPath(ArrayList entries, float fillMin) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + float inset = mChart.getXAxisInset(); Path filled = new Path(); - filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); + filled.moveTo(entries.get(0).getXIndex() + inset, entries.get(0).getVal() * phaseY); // create a new path for (int x = 1; x < entries.size() * phaseX; x++) { Entry e = entries.get(x); - filled.lineTo(e.getXIndex(), e.getVal() * phaseY); + filled.lineTo(e.getXIndex() + inset, e.getVal() * phaseY); } // close up - filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex(), fillMin); - filled.lineTo(entries.get(0).getXIndex(), fillMin); + filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex() + inset, fillMin); + filled.lineTo(entries.get(0).getXIndex() + inset, fillMin); filled.close(); return filled; @@ -290,15 +297,16 @@ private Path generateLinePath(ArrayList entries) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + float inset = mChart.getXAxisInset(); Path line = new Path(); - line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); + line.moveTo(entries.get(0).getXIndex() + inset, entries.get(0).getVal() * phaseY); // create a new path for (int x = 1; x < entries.size() * phaseX; x++) { Entry e = entries.get(x); - line.lineTo(e.getXIndex(), e.getVal() * phaseY); + line.lineTo(e.getXIndex() + inset, e.getVal() * phaseY); } return line; @@ -308,10 +316,10 @@ private Path generateLinePath(ArrayList entries) { public void drawValues(Canvas c) { // if values are drawn - if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + if (mChart.getLineData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getData().getDataSets(); + ArrayList dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { @@ -329,8 +337,8 @@ public void drawValues(Canvas c) { ArrayList entries = dataSet.getYVals(); - float[] positions = trans.generateTransformedValuesLineScatter( - entries, mAnimator.getPhaseY()); + float[] positions = trans.generateTransformedValuesLine( + entries, mAnimator.getPhaseY(), mChart.getXAxisInset()); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { @@ -360,9 +368,9 @@ public void drawExtras(Canvas c) { private void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); - ArrayList dataSets = mChart.getData().getDataSets(); + ArrayList dataSets = mChart.getLineData().getDataSets(); - for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + for (int i = 0; i < mChart.getLineData().getDataSetCount(); i++) { LineDataSet dataSet = dataSets.get(i); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -372,8 +380,8 @@ private void drawCircles(Canvas c) { ArrayList entries = dataSet.getYVals(); - float[] positions = trans.generateTransformedValuesLineScatter( - entries, mAnimator.getPhaseY()); + float[] positions = trans.generateTransformedValuesLine( + entries, mAnimator.getPhaseY(), mChart.getXAxisInset()); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { @@ -405,7 +413,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { - LineDataSet set = mChart.getData().getDataSetByIndex(indices[i] + LineDataSet set = mChart.getLineData().getDataSetByIndex(indices[i] .getDataSetIndex()); if (set == null) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 397a52d3b6..20c205f194 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -5,11 +5,11 @@ import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.interfaces.ScatterDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -17,9 +17,9 @@ public class ScatterChartRenderer extends DataRenderer { - protected ScatterChart mChart; + protected ScatterDataProvider mChart; - public ScatterChartRenderer(ScatterChart chart, ChartAnimator animator, + public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -28,7 +28,7 @@ public ScatterChartRenderer(ScatterChart chart, ChartAnimator animator, @Override public void drawData(Canvas c) { - ScatterData scatterData = mChart.getData(); + ScatterData scatterData = mChart.getScatterData(); for (ScatterDataSet set : scatterData.getDataSets()) { @@ -45,7 +45,7 @@ protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float[] valuePoints = trans.generateTransformedValuesLineScatter(entries, + float[] valuePoints = trans.generateTransformedValuesScatter(entries, mAnimator.getPhaseY()); ScatterShape shape = dataSet.getScatterShape(); @@ -114,12 +114,12 @@ protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { public void drawValues(Canvas c) { // if values are drawn - if (mChart.getData().getYValCount() < mChart.getMaxVisibleCount() + if (mChart.getScatterData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getData().getDataSets(); + ArrayList dataSets = mChart.getScatterData().getDataSets(); - for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + for (int i = 0; i < mChart.getScatterData().getDataSetCount(); i++) { ScatterDataSet dataSet = dataSets.get(i); @@ -129,7 +129,7 @@ public void drawValues(Canvas c) { ArrayList entries = dataSet.getYVals(); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) - .generateTransformedValuesLineScatter(entries, + .generateTransformedValuesScatter(entries, mAnimator.getPhaseY()); float shapeSize = dataSet.getScatterShapeSize(); @@ -140,8 +140,8 @@ public void drawValues(Canvas c) { break; // make sure the lines don't do shitty things outside bounds - if (j != 0 && !mViewPortHandler.isInBoundsLeft(positions[j - 1]) - && !mViewPortHandler.isInBoundsY(positions[j + 1])) + if (j != 0 && (!mViewPortHandler.isInBoundsLeft(positions[j]) + || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; float val = entries.get(j / 2).getVal(); @@ -163,7 +163,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { - ScatterDataSet set = mChart.getData().getDataSetByIndex(indices[i] + ScatterDataSet set = mChart.getScatterData().getDataSetByIndex(indices[i] .getDataSetIndex()); if (set == null) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index ccc83f078a..6a474cbbbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -95,12 +95,12 @@ public void prepareMatrixOffset(boolean inverted) { /** * Transforms an arraylist of Entry into a float array containing the x and - * y values transformed with all matrices for the LINECHART or SCATTERCHART. + * y values transformed with all matrices for the SCATTERCHART. * * @param entries * @return */ - public float[] generateTransformedValuesLineScatter(ArrayList entries, + public float[] generateTransformedValuesScatter(ArrayList entries, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -119,6 +119,33 @@ public float[] generateTransformedValuesLineScatter(ArrayList e return valuePoints; } + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the LINECHART. + * + * @param entries + * @return + */ + public float[] generateTransformedValuesLine(ArrayList entries, + float phaseY, float xAxisInset) { + + float[] valuePoints = new float[entries.size() * 2]; + + for (int j = 0; j < valuePoints.length; j += 2) { + + Entry e = entries.get(j / 2); + + if (e != null) { + valuePoints[j] = e.getXIndex() + xAxisInset; + valuePoints[j + 1] = e.getVal() * phaseY; + } + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } /** * Transforms an arraylist of Entry into a float array containing the x and From 934b20bd5f2ab87a201740a6cdc578704c3d08e6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Feb 2015 21:35:40 +0100 Subject: [PATCH 0086/1390] Worked on multi-dataset barchart selection. --- .../mpchartexample/BarChartActivity.java | 1 - .../listviewitems/LineChartItem.java | 1 - .../mikephil/charting/charts/BarChart.java | 52 ++++++++++++------- .../charting/charts/BarLineChartBase.java | 14 ++--- .../mikephil/charting/charts/Chart.java | 27 +++++++--- .../charting/charts/CombinedChart.java | 17 ++---- .../mikephil/charting/charts/LineChart.java | 5 -- .../charting/interfaces/ChartInterface.java | 3 +- .../charting/interfaces/LineDataProvider.java | 9 ---- .../charting/renderer/BarChartRenderer.java | 6 +-- .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 35 +++++-------- .../renderer/ScatterChartRenderer.java | 4 +- .../charting/renderer/ViewPortHandler.java | 2 +- .../renderer/XAxisRendererBarChart.java | 4 +- .../mikephil/charting/utils/Transformer.java | 10 ++-- 16 files changed, 93 insertions(+), 99 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 038bc87270..ff56bf2d50 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -87,7 +87,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setPosition(XLabelPosition.BOTTOM); - xl.setCenterXLabelText(true); xl.setTypeface(tf); xl.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 78bd575ef4..172401b252 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -54,7 +54,6 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDrawGridBackground(false); XAxis xl = holder.chart.getXAxis(); - xl.setCenterXLabelText(true); xl.setPosition(XLabelPosition.BOTTOM); xl.setTypeface(mTf); xl.setDrawGridLines(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 547a7d3965..43c2bf87c5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -2,9 +2,6 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; @@ -18,9 +15,8 @@ import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; +import java.math.BigDecimal; /** * Chart that draws bars. @@ -74,10 +70,12 @@ public BarChart(Context context, AttributeSet attrs, int defStyle) { @Override protected void init() { super.init(); - + mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + + mXChartMin = -0.5f; } @Override @@ -85,7 +83,7 @@ protected void calcMinMax() { super.calcMinMax(); // increase deltax by 1 because the bars have a width of 1 - mDeltaX++; + mDeltaX += 0.5f; // extend xDelta to make space for multiple datasets (if ther are one) mDeltaX *= mData.getDataSetCount(); @@ -102,6 +100,7 @@ protected void calcMinMax() { float groupSpace = mData.getGroupSpace(); mDeltaX += maxEntry * groupSpace; + mXChartMax = mDeltaX - mXChartMin; } // protected float getPositiveYOffset(boolean drawAboveValueBar) @@ -145,29 +144,44 @@ public Highlight getHighlightByTouchPoint(float x, float y) { double xTouchVal = pts[0]; double base = xTouchVal; - if (xTouchVal < 0 || xTouchVal > mDeltaX) + if (xTouchVal < mXChartMin || xTouchVal > mXChartMax) return null; - if (base < 0) - base = 0; - if (base >= mDeltaX) - base = mDeltaX - 1; + Log.i(LOG_TAG, "base: " + base); int setCount = mData.getDataSetCount(); int valCount = setCount * mData.getXValCount(); + if (setCount <= 1) { + return new Highlight((int) Math.round(base), 0); + } + // calculate the amount of bar-space between index 0 and touch position - float space = (float) (((float) valCount / (float) setCount) / (mDeltaX / base)); + float space = (float) ((((float) valCount / (float) setCount) / (mDeltaX / base))); float reduction = (float) space * mData.getGroupSpace(); - int xIndex = (int) ((base - reduction) / setCount); + Log.i(LOG_TAG, "space: " + space); + Log.i(LOG_TAG, "reduction: " + reduction); + + float beforeRound = (float) ((base - reduction) / setCount); - int dataSetIndex = ((int) (base - reduction)) % setCount; + int xIndex = (int) beforeRound; + Log.i(LOG_TAG, "touch x-index: " + xIndex); - if (dataSetIndex == -1) + float dataSetBeforeRound = (float) ((base - reduction) % setCount); + + Log.i(LOG_TAG, "datasetindex before round: " + dataSetBeforeRound); + + int dataSetIndex = (int) Math.round(dataSetBeforeRound); + Log.i(LOG_TAG, "touch dataset-index: " + dataSetIndex); + + if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) return null; + if (xIndex < 0) + xIndex = 0; + return new Highlight(xIndex, dataSetIndex); } @@ -191,8 +205,8 @@ public RectF getBarBounds(BarEntry e) { float x = e.getXIndex(); float spaceHalf = barspace / 2f; - float left = x + spaceHalf; - float right = x + 1f - spaceHalf; + float left = x - 0.5f + spaceHalf; + float right = x + 0.5f - spaceHalf; float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; @@ -336,7 +350,7 @@ public void setDrawBarShadow(boolean enabled) { public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; } - + @Override public BarData getBarData() { return mData; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d01e60a709..0b7842c95d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -237,12 +237,11 @@ protected void onDraw(Canvas canvas) { private void prepareValuePxMatrix() { if (mLogEnabled) - Log.i(LOG_TAG, "Preparing Value-Px Matrix, deltaLeft: " + mAxisLeft.mAxisRange - + ", deltaRight: " + mAxisRight.mAxisRange); + Log.i(LOG_TAG, "Preparing Value-Px Matrix, xmin: " + mXChartMin + ", xmax: " + mXChartMax + ", xdelta: " + mDeltaX); - mRightAxisTransformer.prepareMatrixValuePx(mDeltaX, mAxisRight.mAxisRange, + mRightAxisTransformer.prepareMatrixValuePx(mXChartMin, mDeltaX, mAxisRight.mAxisRange, mAxisRight.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mDeltaX, mAxisLeft.mAxisRange, + mLeftAxisTransformer.prepareMatrixValuePx(mXChartMin, mDeltaX, mAxisLeft.mAxisRange, mAxisLeft.mAxisMinimum); } @@ -293,8 +292,9 @@ protected void calcMinMax() { float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); Log.i(LOG_TAG, "minLeft: " + minLeft + ", maxLeft: " + maxLeft); - - mDeltaX = mData.getXVals().size() - 1; + + mXChartMax = mData.getXVals().size() - 1; + mDeltaX = Math.abs(mXChartMax - mXChartMin); mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft .getAxisMaxValue() : maxLeft + topSpaceLeft; @@ -525,7 +525,7 @@ else if (this instanceof BarChart) { .getEntryPosition(e); float x = (j * (mData.getDataSetCount() - 1)) + dataSetIndex + space * j + space - / 2f + 0.5f; + / 2f; xPos += x; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index bdeda49498..c6cbb8b022 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -122,6 +122,9 @@ public abstract class Chart implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider { - - private float mXAxisInset = 0f; private FillFormatter mFillFormatter; @@ -49,9 +47,9 @@ protected void calcMinMax() { super.calcMinMax(); if (getBarData() != null) { - mDeltaX += 1; - mXAxisInset = 0.5f; - mXAxis.setCenterXLabelText(true); + mXChartMin = -0.5f; + mXChartMax = mData.getXVals().size() - 0.5f; + mDeltaX = Math.abs(mXChartMax - mXChartMin); } } @@ -125,13 +123,4 @@ public boolean isDrawValuesForWholeStackEnabled() { // TODO Auto-generated method stub return false; } - - @Override - public float getXAxisInset() { - return mXAxisInset; - } - - public void setXAxisInset(float inset) { - mXAxisInset = inset; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 137d5bf389..6cd464595c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -115,11 +115,6 @@ public FillFormatter getFillFormatter() { return mFillFormatter; } - @Override - public float getXAxisInset() { - return 0f; - } - @Override public LineData getLineData() { return mData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index e30e698cb2..e2d1a50d3b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -23,7 +23,8 @@ public interface ChartInterface { // // public float getOffsetRight(); - public float getDeltaX(); + public float getXChartMin(); + public float getXChartMax(); // public float getDeltaY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java index 6186d026ab..479e0d86bc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -22,13 +22,4 @@ public interface LineDataProvider extends BarLineScatterCandleDataProvider { * @return */ public FillFormatter getFillFormatter(); - - /** - * Returns the inset the chart should have on the x-axis. Inset of e.g. 1f - * would mean all values of this LineChart are shifted 1 x-index to the - * right. - * - * @return - */ - public float getXAxisInset(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 973640af4a..378cd762a9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -164,8 +164,8 @@ private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { protected void prepareBar(float x, float y, float barspace, Transformer trans) { float spaceHalf = barspace / 2f; - float left = x + spaceHalf; - float right = x + 1f - spaceHalf; + float left = x - 0.5f + spaceHalf; + float right = x + 0.5f - spaceHalf; float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; @@ -326,7 +326,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // check outofbounds if (index < mChart.getBarData().getYValCount() && index >= 0 - && index < (mChart.getDeltaX() * mAnimator.getPhaseX()) / setCount) { + && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { Entry e = mChart.getBarData().getDataSetByIndex(dataSetIndex) .getEntryForXIndex(index); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index a4ed5143f2..2d82dcc7db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -180,7 +180,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { }; float[] horPts = new float[] { - 0, low, mChart.getDeltaX(), low, 0, high, mChart.getDeltaX(), high + 0, low, mChart.getXChartMax(), low, 0, high, mChart.getXChartMax(), high }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(vertPts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index d71205fed7..eeb6d66d3c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -107,12 +107,9 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Path spline = new Path(); ArrayList points = new ArrayList(); - - float inset = mChart.getXAxisInset(); - for (Entry e : entries) { if (e != null) - points.add(new CPoint(e.getXIndex() + inset, e.getVal())); + points.add(new CPoint(e.getXIndex(), e.getVal())); } if (points.size() > 1) { @@ -164,14 +161,12 @@ else if (j == points.size() - 1) { protected void drawCubicFill(LineDataSet dataSet, Path spline) { - float inset = mChart.getXAxisInset(); - float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo(dataSet.getYVals().get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())).getXIndex() + inset, fillMin); - spline.lineTo(inset, fillMin); + spline.lineTo(dataSet.getYVals().get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())).getXIndex(), fillMin); + spline.lineTo(mChart.getXChartMin(), fillMin); spline.close(); mRenderPaint.setStyle(Paint.Style.FILL); @@ -190,7 +185,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { float[] positions = trans.generateTransformedValuesLine( - entries, phaseY, mChart.getXAxisInset()); + entries, phaseY); for (int j = 0; j < (positions.length - 2) * phaseX; j += 2) { @@ -267,21 +262,20 @@ private Path generateFilledPath(ArrayList entries, float fillMin) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - float inset = mChart.getXAxisInset(); Path filled = new Path(); - filled.moveTo(entries.get(0).getXIndex() + inset, entries.get(0).getVal() * phaseY); + filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); // create a new path for (int x = 1; x < entries.size() * phaseX; x++) { Entry e = entries.get(x); - filled.lineTo(e.getXIndex() + inset, e.getVal() * phaseY); + filled.lineTo(e.getXIndex(), e.getVal() * phaseY); } // close up - filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex() + inset, fillMin); - filled.lineTo(entries.get(0).getXIndex() + inset, fillMin); + filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex(), fillMin); + filled.lineTo(entries.get(0).getXIndex(), fillMin); filled.close(); return filled; @@ -297,16 +291,15 @@ private Path generateLinePath(ArrayList entries) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - float inset = mChart.getXAxisInset(); Path line = new Path(); - line.moveTo(entries.get(0).getXIndex() + inset, entries.get(0).getVal() * phaseY); + line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); // create a new path for (int x = 1; x < entries.size() * phaseX; x++) { Entry e = entries.get(x); - line.lineTo(e.getXIndex() + inset, e.getVal() * phaseY); + line.lineTo(e.getXIndex(), e.getVal() * phaseY); } return line; @@ -338,7 +331,7 @@ public void drawValues(Canvas c) { ArrayList entries = dataSet.getYVals(); float[] positions = trans.generateTransformedValuesLine( - entries, mAnimator.getPhaseY(), mChart.getXAxisInset()); + entries, mAnimator.getPhaseY()); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { @@ -381,7 +374,7 @@ private void drawCircles(Canvas c) { ArrayList entries = dataSet.getYVals(); float[] positions = trans.generateTransformedValuesLine( - entries, mAnimator.getPhaseY(), mChart.getXAxisInset()); + entries, mAnimator.getPhaseY()); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { @@ -424,7 +417,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int xIndex = indices[i].getXIndex(); // get the // x-position - if (xIndex > mChart.getDeltaX() * mAnimator.getPhaseX()) + if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get @@ -433,7 +426,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] pts = new float[] { xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, - mChart.getDeltaX(), y + mChart.getXChartMax(), y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 20c205f194..abc3d617d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -174,7 +174,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int xIndex = indices[i].getXIndex(); // get the // x-position - if (xIndex > mChart.getDeltaX() * mAnimator.getPhaseX()) + if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get @@ -183,7 +183,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] pts = new float[] { xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, - mChart.getDeltaX(), y + mChart.getXChartMax(), y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index 4e74a56f14..c7166a6449 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -4,7 +4,7 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; -import android.view.View; +import android.util.Log; import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index c8fab8c242..fe3c2cef8a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -39,7 +39,7 @@ protected void drawLabels(Canvas c, float yPos) { for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() - + bd.getGroupSpace() / 2f; + + bd.getGroupSpace() / 2f - 0.5f; // center the text if (mXAxis.isCenterXLabelsEnabled()) @@ -92,7 +92,7 @@ public void renderGridLines(Canvas c) { for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { - position[0] = i * step + i * bd.getGroupSpace(); + position[0] = i * step + i * bd.getGroupSpace() - 0.5f; mTrans.pointValuesToPixel(position); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 6a474cbbbf..607119aeed 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -37,7 +37,7 @@ public Transformer(ViewPortHandler viewPortHandler) { * * @param chart */ - public void prepareMatrixValuePx(float deltaX, float deltaY, float yChartMin) { + public void prepareMatrixValuePx(float xChartMin, float deltaX, float deltaY, float yChartMin) { float scaleX = (float) ((mViewPortHandler.getChartWidth() - mViewPortHandler.offsetRight() - mViewPortHandler .offsetLeft()) / deltaX); @@ -46,7 +46,7 @@ public void prepareMatrixValuePx(float deltaX, float deltaY, float yChartMin) { // setup all matrices mMatrixValueToPx.reset(); - mMatrixValueToPx.postTranslate(0, -yChartMin); + mMatrixValueToPx.postTranslate(-xChartMin, -yChartMin); mMatrixValueToPx.postScale(scaleX, -scaleY); } @@ -128,7 +128,7 @@ public float[] generateTransformedValuesScatter(ArrayList entri * @return */ public float[] generateTransformedValuesLine(ArrayList entries, - float phaseY, float xAxisInset) { + float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -137,7 +137,7 @@ public float[] generateTransformedValuesLine(ArrayList entries, Entry e = entries.get(j / 2); if (e != null) { - valuePoints[j] = e.getXIndex() + xAxisInset; + valuePoints[j] = e.getXIndex(); valuePoints[j + 1] = e.getVal() * phaseY; } } @@ -168,7 +168,7 @@ public float[] generateTransformedValuesBarChart(ArrayList entr Entry e = entries.get(j / 2); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + 0.5f + space * (j / 2) + float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + space * (j / 2) + space / 2f; float y = e.getVal(); From ac22b06a9673165d9a80ce1851df8a784d537b65 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 17 Feb 2015 01:08:29 +0100 Subject: [PATCH 0087/1390] Worked on combined charts. --- .../BarChartActivityMultiDataset.java | 2 +- .../CandleStickChartActivity.java | 3 +- .../mpchartexample/CombinedChartActivity.java | 40 +++++++++++++++++++ .../mikephil/charting/charts/BarChart.java | 12 ++++-- .../charting/charts/BarLineChartBase.java | 10 +---- .../charting/charts/CandleStickChart.java | 4 +- .../charting/data/ScatterDataSet.java | 2 +- .../listener/BarLineChartTouchListener.java | 29 +++++++------- .../renderer/CandleStickChartRenderer.java | 10 ++--- 9 files changed, 75 insertions(+), 37 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 78df5d9aed..21b17ac4c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -230,7 +230,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BarData data = new BarData(xVals, dataSets); // add space between the dataset groups in percent of bar-width - data.setGroupSpace(110f); + data.setGroupSpace(80f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index d5fca0bc5b..408d0b9c65 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -60,13 +60,14 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XLabelPosition.BOTTOM); - xLabels.setCenterXLabelText(true); xLabels.setSpaceBetweenLabels(2); YAxis yLabels = mChart.getAxisLeft(); yLabels.setLabelCount(7); yLabels.setDrawGridLines(false); // yLabels.setPosition(YLabelPosition.LEFT); + + mChart.getAxisRight().setEnabled(false); mChart.setDrawLegend(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index c2b25a1928..6b9ae9fd1a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -10,10 +10,15 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.data.CandleDataSet; +import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.data.ScatterDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -41,6 +46,8 @@ protected void onCreate(Bundle savedInstanceState) { data.setData(generateLineData()); data.setData(generateBarData()); + data.setData(generateScatterData()); + data.setData(generateCandleData()); mChart.setData(data); mChart.invalidate(); @@ -81,6 +88,39 @@ private BarData generateBarData() { return d; } + + private ScatterData generateScatterData() { + + ScatterData d = new ScatterData(); + + ArrayList entries = new ArrayList(); + + for (int index = 0; index < itemcount; index++) + entries.add(new Entry(getRandom(), index)); + + ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); + set.setColor(Color.GREEN); + set.setScatterShapeSize(7.5f); + d.addDataSet(set); + + return d; + } + + private CandleData generateCandleData() { + + CandleData d = new CandleData(); + + ArrayList entries = new ArrayList(); + + for (int index = 0; index < itemcount; index++) + entries.add(new CandleEntry(index, 25f, 10f, 12f, 22f)); + + CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); + set.setColor(Color.rgb(80, 80, 80)); + d.addDataSet(set); + + return d; + } private float getRandom() { return (float) (Math.random() * 20f) + 25f; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 43c2bf87c5..2ecdee2001 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -158,18 +158,22 @@ public Highlight getHighlightByTouchPoint(float x, float y) { // calculate the amount of bar-space between index 0 and touch position float space = (float) ((((float) valCount / (float) setCount) / (mDeltaX / base))); +// + float border = (float) setCount + mData.getGroupSpace(); + + float steps = 0.5f + (int) (((float) base + 0.5f) / ((float) setCount)); - float reduction = (float) space * mData.getGroupSpace(); + float reduction = (float) (steps) * mData.getGroupSpace(); - Log.i(LOG_TAG, "space: " + space); Log.i(LOG_TAG, "reduction: " + reduction); float beforeRound = (float) ((base - reduction) / setCount); - + Log.i(LOG_TAG, "touch x-index before round: " + beforeRound); + int xIndex = (int) beforeRound; Log.i(LOG_TAG, "touch x-index: " + xIndex); - float dataSetBeforeRound = (float) ((base - reduction) % setCount); + float dataSetBeforeRound = (float) ((base - reduction) % (setCount - 0.5f)); Log.i(LOG_TAG, "datasetindex before round: " + dataSetBeforeRound); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 0b7842c95d..7b203c4c9d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -512,12 +512,7 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { float xPos = e.getXIndex(); - // make sure the marker is in the center of the bars in BarChart and - // CandleStickChart - if (this instanceof CandleStickChart) - xPos += 0.5f; - - else if (this instanceof BarChart) { + if (this instanceof BarChart) { BarData bd = (BarData) mData; float space = bd.getGroupSpace(); @@ -1144,9 +1139,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset) return null; - if (this instanceof CandleStickChart) - base -= 0.5; - if (base < 0) base = 0; if (base >= mDeltaX) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index a6178ec491..5a5955fe5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -32,14 +32,14 @@ protected void init() { super.init(); mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); + mXChartMin = -0.5f; } @Override protected void calcMinMax() { super.calcMinMax(); - // increase deltax by 1 because the candles have a width of 1 - mDeltaX++; + mDeltaX = Math.abs(mXChartMax - mXChartMin); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 35549471b3..70cec2a761 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -11,7 +11,7 @@ public class ScatterDataSet extends BarLineScatterCandleRadarDataSet { /** the size the scattershape will have, in screen pixels */ - private float mShapeSize = 12f; + private float mShapeSize = 15f; /** * the type of shape that is set to be drawn where the values are at, diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 1c7f00e05a..2089f71c61 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -409,21 +409,22 @@ public void onLongPress(MotionEvent e) { if (l != null) { l.onChartLongPressed(e); - } else if (mTouchMode == NONE) { - - mChart.fitScreen(); - - Log.i("BarlineChartTouch", - "Longpress, resetting zoom and drag, adjusting chart bounds to screen."); - - // PointF trans = getTrans(e.getX(), e.getY()); - // - // mChart.zoomOut(trans.x, trans.y); - // - // Log.i("BarlineChartTouch", "Longpress, Zooming Out, x: " + - // trans.x + - // ", y: " + trans.y); } +// else if (mTouchMode == NONE) { +// +// mChart.fitScreen(); +// +// Log.i("BarlineChartTouch", +// "Longpress, resetting zoom and drag, adjusting chart bounds to screen."); +// +// // PointF trans = getTrans(e.getX(), e.getY()); +// // +// // mChart.zoomOut(trans.x, trans.y); +// // +// // Log.i("BarlineChartTouch", "Longpress, Zooming Out, x: " + +// // trans.x + +// // ", y: " + trans.y); +// } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 2d82dcc7db..12925b3d26 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -112,9 +112,9 @@ private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace, T float phase = mAnimator.getPhaseY(); - bodyPoints[0] = e.getXIndex() + bodySpace; + bodyPoints[0] = e.getXIndex() -0.5f + bodySpace; bodyPoints[1] = e.getClose() * phase; - bodyPoints[2] = e.getXIndex() + (1f - bodySpace); + bodyPoints[2] = e.getXIndex() + 0.5f - bodySpace; bodyPoints[3] = e.getOpen() * phase; trans.pointValuesToPixel(bodyPoints); @@ -130,9 +130,9 @@ private void transformShadow(float[] shadowPoints, CandleEntry e, Transformer tr float phase = mAnimator.getPhaseY(); - shadowPoints[0] = e.getXIndex() + 0.5f; + shadowPoints[0] = e.getXIndex(); shadowPoints[1] = e.getHigh() * phase; - shadowPoints[2] = e.getXIndex() + 0.5f; + shadowPoints[2] = e.getXIndex(); shadowPoints[3] = e.getLow() * phase; trans.pointValuesToPixel(shadowPoints); @@ -175,7 +175,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float max = mChart.getYChartMax(); float[] vertPts = new float[] { - xIndex, max, xIndex, min, xIndex + 1f, max, xIndex + 1f, + xIndex - 0.5f, max, xIndex - 0.5f, min, xIndex + 0.5f, max, xIndex + 0.5f, min }; From d91e47ea71eeab6ee6f9dfd012b87f169ca44bdd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 17 Feb 2015 10:05:31 +0100 Subject: [PATCH 0088/1390] Fixed bug in CandleStickChart, worked on combined charts. --- .../mpchartexample/CombinedChartActivity.java | 9 +++- .../charting/charts/CandleStickChart.java | 1 + .../mikephil/charting/data/CandleDataSet.java | 2 +- .../renderer/CandleStickChartRenderer.java | 41 ++++++++++++++++++- .../charting/renderer/LineChartRenderer.java | 1 - .../mikephil/charting/utils/Transformer.java | 28 +++++++++++++ 6 files changed, 77 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 6b9ae9fd1a..99d88b523c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -46,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { data.setData(generateLineData()); data.setData(generateBarData()); - data.setData(generateScatterData()); +// data.setData(generateScatterData()); data.setData(generateCandleData()); mChart.setData(data); @@ -69,6 +70,7 @@ private LineData generateLineData() { set.setCircleSize(5f); set.setFillColor(Color.RED); set.setDrawCubic(true); + set.setDrawValues(false); d.addDataSet(set); return d; @@ -101,6 +103,7 @@ private ScatterData generateScatterData() { ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); set.setColor(Color.GREEN); set.setScatterShapeSize(7.5f); + set.setDrawValues(false); d.addDataSet(set); return d; @@ -113,10 +116,12 @@ private CandleData generateCandleData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new CandleEntry(index, 25f, 10f, 12f, 22f)); + entries.add(new CandleEntry(index, 20f, 10f, 13f, 17f)); CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); set.setColor(Color.rgb(80, 80, 80)); + set.setBodySpace(0.3f); + set.setDrawValues(false); d.addDataSet(set); return d; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 5a5955fe5a..28c373e5a6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -39,6 +39,7 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); + mXChartMax += 0.5f; mDeltaX = Math.abs(mXChartMax - mXChartMin); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 084125a6db..3096cc86a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -15,7 +15,7 @@ public class CandleDataSet extends BarLineScatterCandleRadarDataSet /** the width of the shadow of the candle */ private float mShadowWidth = 3f; - /** the space between the candle entries, default 0.2f (20%) */ + /** the space between the candle entries, default 0.1f (10%) */ private float mBodySpace = 0.1f; public CandleDataSet(ArrayList yVals, String label) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 12925b3d26..01a46a2a8b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.interfaces.CandleDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -140,8 +141,46 @@ private void transformShadow(float[] shadowPoints, CandleEntry e, Transformer tr @Override public void drawValues(Canvas c) { - // TODO Auto-generated method stub + + // if values are drawn + if (mChart.getCandleData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleX()) { + ArrayList dataSets = mChart.getCandleData().getDataSets(); + + for (int i = 0; i < dataSets.size(); i++) { + + CandleDataSet dataSet = dataSets.get(i); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + if (!dataSet.isDrawValuesEnabled()) + continue; + + ArrayList entries = dataSet.getYVals(); + + float[] positions = trans.generateTransformedValuesCandle( + entries, mAnimator.getPhaseY()); + + float yOffset = Utils.convertDpToPixel(5f); + + for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + + float x = positions[j]; + float y = positions[j + 1]; + + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) + continue; + + float val = entries.get(j / 2).getVal(); + + c.drawText(mChart.getValueFormatter().getFormattedValue(val), x, y - yOffset, + mValuePaint); + } + } + } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index eeb6d66d3c..12078b6dea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -308,7 +308,6 @@ private Path generateLinePath(ArrayList entries) { @Override public void drawValues(Canvas c) { - // if values are drawn if (mChart.getLineData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 607119aeed..9eed1c420c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -6,6 +6,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.renderer.ViewPortHandler; @@ -146,6 +147,33 @@ public float[] generateTransformedValuesLine(ArrayList entries, return valuePoints; } + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the CANDLESTICKCHART. + * + * @param entries + * @return + */ + public float[] generateTransformedValuesCandle(ArrayList entries, + float phaseY) { + + float[] valuePoints = new float[entries.size() * 2]; + + for (int j = 0; j < valuePoints.length; j += 2) { + + CandleEntry e = entries.get(j / 2); + + if (e != null) { + valuePoints[j] = e.getXIndex(); + valuePoints[j + 1] = e.getHigh() * phaseY; + } + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } /** * Transforms an arraylist of Entry into a float array containing the x and From ddde6c8dc01d4d9bb89e86982e283006d898a0f2 Mon Sep 17 00:00:00 2001 From: Walter Ching Date: Tue, 17 Feb 2015 10:37:57 -0600 Subject: [PATCH 0089/1390] Update README.md Just a minor typo I found. Awesome lib. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1f1c5799dc..cb8aa21828 100644 --- a/README.md +++ b/README.md @@ -408,11 +408,11 @@ All chart types support animations that can be used to create / build up the cha - `animateXY(int xDuration, int yDuration)`: Animates both horizontal and vertical axis, resulting in a left/right bottom/top build-up. ```java -mChart.animateX(3000f); // animate horizontal 3000 milliseconds +mChart.animateX(3000); // animate horizontal 3000 milliseconds // or: -mChart.animateY(3000f); // animate vertical 3000 milliseconds +mChart.animateY(3000); // animate vertical 3000 milliseconds // or: -mChart.animateXY(3000f, 3000f); // animate horizontal and vertical 3000 milliseconds +mChart.animateXY(3000, 3000); // animate horizontal and vertical 3000 milliseconds ``` If `animate(...)` (of any kind) is called, no further calling of `invalidate()` is necessary to refresh the chart. From 9bdfbf72a16cc4fc51f45ad8e257a8e2033bd922 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 18 Feb 2015 15:16:29 +0100 Subject: [PATCH 0090/1390] General bugfixes, fixed issues concerning RadarChart labels and offset. --- .../ListViewMultiChartActivity.java | 8 +- .../mpchartexample/PieChartActivity.java | 2 +- .../mpchartexample/RadarChartActivitry.java | 9 +- .../charting/charts/BarLineChartBase.java | 9 +- .../mikephil/charting/charts/Chart.java | 204 +++++++++--------- .../mikephil/charting/charts/PieChart.java | 21 ++ .../charting/charts/PieRadarChartBase.java | 75 +++---- .../mikephil/charting/charts/RadarChart.java | 81 +------ .../charting/charts/ScatterChart.java | 1 + .../mikephil/charting/data/BarDataSet.java | 2 +- .../data/BarLineScatterCandleData.java | 2 +- ....java => BarLineScatterCandleDataSet.java} | 4 +- .../mikephil/charting/data/CandleDataSet.java | 2 +- .../mikephil/charting/data/ChartData.java | 6 +- .../mikephil/charting/data/CombinedData.java | 2 +- .../github/mikephil/charting/data/Data.java | 5 - .../charting/data/LineRadarDataSet.java | 2 +- .../charting/data/ScatterDataSet.java | 2 +- .../listener/BarLineChartTouchListener.java | 4 +- .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/PieChartRenderer.java | 2 +- .../charting/renderer/ViewPortHandler.java | 1 - .../renderer/YAxisRendererRadarChart.java | 32 ++- 23 files changed, 215 insertions(+), 263 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/data/{BarLineScatterCandleRadarDataSet.java => BarLineScatterCandleDataSet.java} (83%) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/data/Data.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index a7e12dac7a..4a47000f90 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -101,8 +101,8 @@ private LineData generateDataLine(int cnt) { } LineDataSet d1 = new LineDataSet(e1, "New DataSet " + cnt + ", (1)"); - d1.setLineWidth(3f); - d1.setCircleSize(5f); + d1.setLineWidth(2.5f); + d1.setCircleSize(4.5f); d1.setHighLightColor(Color.rgb(244, 117, 117)); d1.setDrawValues(false); @@ -113,8 +113,8 @@ private LineData generateDataLine(int cnt) { } LineDataSet d2 = new LineDataSet(e2, "New DataSet " + cnt + ", (2)"); - d2.setLineWidth(3f); - d2.setCircleSize(5f); + d2.setLineWidth(2.5f); + d2.setCircleSize(4.5f); d2.setHighLightColor(Color.rgb(244, 117, 117)); d2.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 26e4e126e2..d6e4c00669 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -128,7 +128,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleXVals: { - mChart.setDrawAxisLabels(!mChart.isDrawAxisLabelsEnabled()); + mChart.setDrawSliceText(!mChart.isDrawSliceTextEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 42aebf5f33..e1abd1bd79 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -130,15 +130,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleXLabels: { - if (mChart.isDrawXLabelsEnabled()) - mChart.setDrawXLabels(false); - else - mChart.setDrawXLabels(true); + mChart.getXAxis().setEnabled(!mChart.getXAxis().isEnabled()); mChart.invalidate(); break; } case R.id.actionToggleYLabels: { - + mChart.getYAxis().setEnabled(!mChart.getYAxis().isEnabled()); mChart.invalidate(); break; @@ -195,7 +192,7 @@ public void setData() { sets.add(set2); RadarData data = new RadarData(xVals, sets); - + mChart.setData(data); // undo all highlights diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 7b203c4c9d..3283459567 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -22,7 +22,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; -import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; +import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -46,7 +46,7 @@ * @author Philipp Jahoda */ @SuppressLint("RtlHardcoded") -public abstract class BarLineChartBase>> +public abstract class BarLineChartBase>> extends Chart { /** the maximum number of entried to which values will be drawn */ @@ -918,10 +918,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { vals[0] += set.getBarSpace() / 2f; } - if (axis == AxisDependency.LEFT) - mLeftAxisTransformer.pointValuesToPixel(vals); - else - mRightAxisTransformer.pointValuesToPixel(vals); + getTransformer(axis).pointValuesToPixel(vals); return new PointF(vals[0], vals[1]); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index c6cbb8b022..d81ce25ad7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -283,7 +283,6 @@ public void setData(T data) { mDataNotSet = false; mOffsetsCalculated = false; mData = data; - mData = data; notifyDataSetChanged(); @@ -298,7 +297,6 @@ public void setData(T data) { * invalidate()). */ public void clear() { - mData = null; mData = null; mDataNotSet = true; invalidate(); @@ -409,10 +407,7 @@ protected void onDraw(Canvas canvas) { mOffsetsCalculated = true; } - if (mDrawBitmap == null || mDrawCanvas == null) { - - mDrawBitmap = Bitmap.createBitmap(getWidth(), getHeight(), - Bitmap.Config.ARGB_4444); + if ( mDrawCanvas == null) { mDrawCanvas = new Canvas(mDrawBitmap); } @@ -904,8 +899,7 @@ public void highlightTouch(Highlight high) { mSelectionListener.onNothingSelected(); else { - Entry e = getEntryByDataSetIndex(high.getXIndex(), - high.getDataSetIndex()); + Entry e = mData.getEntryForHighlight(high); // notify the listener mSelectionListener.onValueSelected(e, high.getDataSetIndex()); @@ -940,7 +934,7 @@ protected void drawMarkers() { if (xIndex <= mDeltaX && xIndex <= mDeltaX * mAnimator.getPhaseX()) { - Entry e = getEntryByDataSetIndex(xIndex, dataSetIndex); + Entry e = mData.getEntryForHighlight(mIndicesToHightlight[i]); // make sure entry not null if (e == null) @@ -1598,102 +1592,102 @@ public void setValueTextSize(float size) { mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); } - /** - * returns the x-value at the given index - * - * @param index - * @return - */ - public String getXValue(int index) { - if (mData == null || mData.getXValCount() <= index) - return null; - else - return mData.getXVals().get(index); - } - - /** - * returns the y-value for the given index from the DataSet with the given - * label - * - * @param index - * @param dataSetLabel - * @return - */ - public float getYValue(int index, String dataSetLabel) { - DataSet set = mData.getDataSetByLabel(dataSetLabel, true); - return set.getYVals().get(index).getVal(); - } - - /** - * returns the y-value for the given x-index and DataSet index - * - * @param index - * @param dataSet - * @return - */ - public float getYValue(int xIndex, int dataSetIndex) { - DataSet set = mData.getDataSetByIndex(dataSetIndex); - return set.getYValForXIndex(xIndex); - } - - /** - * returns the DataSet with the given index in the DataSet array held by the - * ChartData object. - * - * @param index - * @return - */ - public DataSet getDataSetByIndex(int index) { - return mData.getDataSetByIndex(index); - } - - /** - * returns the DataSet with the given label that is stored in the ChartData - * object. - * - * @param type - * @return - */ - public DataSet getDataSetByLabel(String dataSetLabel) { - return mData.getDataSetByLabel(dataSetLabel, true); - } - - /** - * returns the Entry object from the first DataSet stored in the ChartData - * object. If multiple DataSets are used, use getEntry(index, type) or - * getEntryByDataSetIndex(xIndex, dataSetIndex); - * - * @param index - * @return - */ - public Entry getEntry(int index) { - return mData.getDataSetByIndex(0).getYVals().get(index); - } - - /** - * returns the Entry object at the given index from the DataSet with the - * given label. - * - * @param index - * @param dataSetLabel - * @return - */ - public Entry getEntry(int index, String dataSetLabel) { - return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); - } - - /** - * Returns the corresponding Entry object at the given xIndex from the given - * DataSet. INFORMATION: This method does calculations at runtime. Do not - * over-use in performance critical situations. - * - * @param xIndex - * @param dataSetIndex - * @return - */ - public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { - return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); - } +// /** +// * returns the x-value at the given index +// * +// * @param index +// * @return +// */ +// public String getXValue(int index) { +// if (mData == null || mData.getXValCount() <= index) +// return null; +// else +// return mData.getXVals().get(index); +// } +// +// /** +// * returns the y-value for the given index from the DataSet with the given +// * label +// * +// * @param index +// * @param dataSetLabel +// * @return +// */ +// public float getYValue(int index, String dataSetLabel) { +// DataSet set = mData.getDataSetByLabel(dataSetLabel, true); +// return set.getYVals().get(index).getVal(); +// } +// +// /** +// * returns the y-value for the given x-index and DataSet index +// * +// * @param index +// * @param dataSet +// * @return +// */ +// public float getYValue(int xIndex, int dataSetIndex) { +// DataSet set = mData.getDataSetByIndex(dataSetIndex); +// return set.getYValForXIndex(xIndex); +// } +// +// /** +// * returns the DataSet with the given index in the DataSet array held by the +// * ChartData object. +// * +// * @param index +// * @return +// */ +// public DataSet getDataSetByIndex(int index) { +// return mData.getDataSetByIndex(index); +// } +// +// /** +// * returns the DataSet with the given label that is stored in the ChartData +// * object. +// * +// * @param type +// * @return +// */ +// public DataSet getDataSetByLabel(String dataSetLabel) { +// return mData.getDataSetByLabel(dataSetLabel, true); +// } +// +// /** +// * returns the Entry object from the first DataSet stored in the ChartData +// * object. If multiple DataSets are used, use getEntry(index, type) or +// * getEntryByDataSetIndex(xIndex, dataSetIndex); +// * +// * @param index +// * @return +// */ +// public Entry getEntry(int index) { +// return mData.getDataSetByIndex(0).getYVals().get(index); +// } +// +// /** +// * returns the Entry object at the given index from the DataSet with the +// * given label. +// * +// * @param index +// * @param dataSetLabel +// * @return +// */ +// public Entry getEntry(int index, String dataSetLabel) { +// return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); +// } +// +// /** +// * Returns the corresponding Entry object at the given xIndex from the given +// * DataSet. INFORMATION: This method does calculations at runtime. Do not +// * over-use in performance critical situations. +// * +// * @param xIndex +// * @param dataSetIndex +// * @return +// */ +// public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { +// return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); +// } /** * Returns an array of SelInfo objects for the given x-index. The SelInfo diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 3656c511ac..8b21042a54 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -32,6 +32,9 @@ public class PieChart extends PieRadarChartBase { * drawing the circle */ private RectF mCircleBox = new RectF(); + + /** flag indicating if the x-labels should be drawn or not */ + protected boolean mDrawXLabels = true; /** array that holds the width of each pie-slice in degrees */ private float[] mDrawAngles; @@ -453,6 +456,24 @@ public void setTransparentCircleRadius(final float percent) { public float getTransparentCircleRadius() { return mTransparentCircleRadiusPercent; + } + + /** + * set this to true to draw the x-value text into the pie slices + * + * @param enabled + */ + public void setDrawSliceText(boolean enabled) { + mDrawXLabels = enabled; + } + + /** + * returns true if drawing x-values is enabled, false if not + * + * @return + */ + public boolean isDrawSliceTextEnabled() { + return mDrawXLabels; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index ef0b13abe1..345ab74cff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -6,6 +6,7 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; +import android.util.Log; import android.view.MotionEvent; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -29,9 +30,6 @@ public abstract class PieRadarChartBase { /** transparency the grid is drawn with (0-255) */ private int mWebAlpha = 150; - /** flag indicating if the x-labels should be drawn or not */ - private boolean mDrawXLabels = true; - /** flag indicating if the web lines should be drawn or not */ private boolean mDrawWeb = true; /** the object reprsenting the y-axis labels */ - private YAxis mYAxis = new YAxis(AxisDependency.LEFT); + private YAxis mYAxis; /** the object representing the x-axis labels */ - private XAxis mXAxis = new XAxis(); + private XAxis mXAxis; protected YAxisRendererRadarChart mYAxisRenderer; protected XAxisRendererRadarChart mXAxisRenderer; @@ -97,7 +94,7 @@ protected void calcMinMax() { mYAxis.mAxisMinimum = 0; -// mDeltaY = Math.abs(mYChartMax - mYChartMin); + // mDeltaY = Math.abs(mYChartMax - mYChartMin); } @Override @@ -118,8 +115,7 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); - mYAxisRenderer.computeAxis(0f, 0f); - prepareYLabels(); + mYAxisRenderer.computeAxis(0f, mData.getYMax()); mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); } @@ -130,8 +126,7 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - if (mDrawXLabels) - mXAxisRenderer.renderAxis(mDrawCanvas); + mXAxisRenderer.renderAxis(mDrawCanvas); if (mDrawWeb) mRenderer.drawExtras(mDrawCanvas); @@ -143,8 +138,7 @@ protected void onDraw(Canvas canvas) { if (mHighlightEnabled && valuesToHighlight()) mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); - if (mYAxis.isEnabled()) - mYAxisRenderer.renderAxis(mDrawCanvas); + mYAxisRenderer.renderAxis(mDrawCanvas); mRenderer.drawValues(mDrawCanvas); @@ -157,44 +151,6 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } - /** - * Calculates the required maximum y-value in order to be able to provide - * the desired number of label entries and rounded label values. - */ - private void prepareYLabels() { - - int labelCount = mYAxis.getLabelCount(); - - double max = mData.getYMax() > 0 ? mData.getYMax() : 1.0; - double range = max - mYAxis.mAxisMinimum; - - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); - int intervalSigDigit = (int) (interval / intervalMagnitude); - if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); - } - - double first = Math.ceil(mYAxis.mAxisMinimum / interval) * interval; - double last = Utils.nextUp(Math.floor(max / interval) * interval); - - double f; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } - - mYAxis.mEntryCount = n; - - mYAxis.mAxisMaximum = (float) interval * n; - - // calc delta -// mDeltaY = Math.abs(mYChartMax - mYChartMin); - } - /** * Returns the factor that is needed to transform values into pixels. * @@ -241,7 +197,8 @@ public YAxis getYAxis() { } /** - * Returns the object that represents all x-labels of the RadarChart. + * Returns the object that represents all x-labels that are placed around + * the RadarChart. * * @return */ @@ -335,24 +292,6 @@ public void setDrawWeb(boolean enabled) { mDrawWeb = enabled; } - /** - * set this to true to enable drawing the x-labels, false if not - * - * @param enabled - */ - public void setDrawXLabels(boolean enabled) { - mDrawXLabels = enabled; - } - - /** - * Returns true if drawing x-labels is enabled, false if not. - * - * @return - */ - public boolean isDrawXLabelsEnabled() { - return mDrawXLabels; - } - @Override protected float getRequiredBottomOffset() { return mLegendLabelPaint.getTextSize() * 6.5f; @@ -368,11 +307,11 @@ public float getRadius() { RectF content = mViewPortHandler.getContentRect(); return Math.min(content.width() / 2f, content.height() / 2f); } - + public float getYChartMax() { return mYAxis.mAxisMaximum; } - + public float getYChartMin() { return mYAxis.mAxisMinimum; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 9dea2dbc11..ec04d59184 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -38,6 +38,7 @@ protected void init() { super.init(); mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); + mXChartMin = -0.5f; } // @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index fa2eb8306a..4638467050 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -5,7 +5,7 @@ import java.util.ArrayList; -public class BarDataSet extends BarLineScatterCandleRadarDataSet { +public class BarDataSet extends BarLineScatterCandleDataSet { /** space indicator between the bars 0.1f == 10 % */ private float mBarSpace = 0.15f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java index e9dc9cba0d..2b5e13bf5d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java @@ -8,7 +8,7 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleData> +public abstract class BarLineScatterCandleData> extends ChartData { public BarLineScatterCandleData() { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java similarity index 83% rename from MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java index 3de79fd1ca..43c6173ddd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java @@ -10,12 +10,12 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleRadarDataSet extends DataSet { +public abstract class BarLineScatterCandleDataSet extends DataSet { /** default highlight color */ protected int mHighLightColor = Color.rgb(255, 187, 115); - public BarLineScatterCandleRadarDataSet(ArrayList yVals, String label) { + public BarLineScatterCandleDataSet(ArrayList yVals, String label) { super(yVals, label); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 3096cc86a8..9acd447cee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -10,7 +10,7 @@ * * @author Philipp Jahoda */ -public class CandleDataSet extends BarLineScatterCandleRadarDataSet { +public class CandleDataSet extends BarLineScatterCandleDataSet { /** the width of the shadow of the candle */ private float mShadowWidth = 3f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index bf3c7a9294..57af315190 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -14,12 +14,12 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> extends Data { +public abstract class ChartData> { - /** maximum y-value in the y-value array */ + /** maximum y-value in the y-value array across all axes */ protected float mYMax = 0.0f; - /** the minimum y-value in the y-value array */ + /** the minimum y-value in the y-value array across all axes */ protected float mYMin = 0.0f; protected float mLeftAxisMax = 0.0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 13cfbacb8b..ab836c667f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -2,7 +2,7 @@ import java.util.ArrayList; -public class CombinedData extends BarLineScatterCandleData> { +public class CombinedData extends BarLineScatterCandleData> { private LineData mLineData; private BarData mBarData; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/Data.java b/MPChartLib/src/com/github/mikephil/charting/data/Data.java deleted file mode 100644 index 5ddc9e14b1..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/data/Data.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.mikephil.charting.data; - -public abstract class Data> { - -} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 867483c273..048b481828 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -12,7 +12,7 @@ * * @author Philipp Jahoda */ -public abstract class LineRadarDataSet extends BarLineScatterCandleRadarDataSet { +public abstract class LineRadarDataSet extends BarLineScatterCandleDataSet { /** the color that is used for filling the line surface */ private int mFillColor = Color.rgb(140, 234, 255); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 70cec2a761..13adf227ae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -8,7 +8,7 @@ import java.util.ArrayList; -public class ScatterDataSet extends BarLineScatterCandleRadarDataSet { +public class ScatterDataSet extends BarLineScatterCandleDataSet { /** the size the scattershape will have, in screen pixels */ private float mShapeSize = 15f; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 2089f71c61..3c4b0f663a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.data.BarLineScatterCandleData; -import com.github.mikephil.charting.data.BarLineScatterCandleRadarDataSet; +import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.renderer.ViewPortHandler; @@ -25,7 +25,7 @@ * * @author Philipp Jahoda */ -public class BarLineChartTouchListener>>> +public class BarLineChartTouchListener>>> extends SimpleOnGestureListener implements OnTouchListener { /** the original touch-matrix from the chart */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 01a46a2a8b..e00339a8f3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -174,7 +174,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - float val = entries.get(j / 2).getVal(); + float val = entries.get(j / 2).getHigh(); c.drawText(mChart.getValueFormatter().getFormattedValue(val), x, y - yOffset, mValuePaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 51f2a4715c..6bf00e94be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -159,7 +159,7 @@ public void drawValues(Canvas c) { String val = mChart.getValueFormatter().getFormattedValue(value); - boolean drawXVals = mChart.isDrawAxisLabelsEnabled(); + boolean drawXVals = mChart.isDrawSliceTextEnabled(); boolean drawYVals = dataSet.isDrawValuesEnabled(); // draw everything, depending on settings diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index c7166a6449..086214a076 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -4,7 +4,6 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; -import android.util.Log; import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 57ca7640f6..b9f3ec44d9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Path; import android.graphics.PointF; +import android.util.Log; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.LimitLine; @@ -20,12 +21,41 @@ public class YAxisRendererRadarChart extends YAxisRenderer { public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { super(viewPortHandler, yAxis, null); - mChart = chart; + this.mChart = chart; } @Override public void computeAxis(float yMin, float yMax) { + + int labelCount = mYAxis.getLabelCount(); + + double max = yMax > 0 ? yMax : 1.0; + double range = max - mYAxis.mAxisMinimum; + + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } + + double first = Math.ceil(mYAxis.mAxisMinimum / interval) * interval; + double last = Utils.nextUp(Math.floor(max / interval) * interval); + + double f; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } + + mYAxis.mEntryCount = n; + mYAxis.mAxisMaximum = (float) interval * n; + + Log.i("", "Maximum: " + mYAxis.mAxisMaximum); } @Override From 28e8ae56d33561b913e53e722b17348c92daf9d2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 18 Feb 2015 22:21:41 +0100 Subject: [PATCH 0091/1390] PieChart can now again represent percent values. --- .../mpchartexample/PieChartActivity.java | 14 +++++-- .../custom/PercentFormatter.java | 7 +--- .../listviewitems/PieChartItem.java | 2 +- .../mikephil/charting/charts/PieChart.java | 22 ++++++++++- .../mikephil/charting/data/PieData.java | 38 +++++++++++++++---- .../charting/renderer/PieChartRenderer.java | 7 ++-- 6 files changed, 68 insertions(+), 22 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index d6e4c00669..0f2c5977df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -50,6 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mChart = (PieChart) findViewById(R.id.chart1); + mChart.setValueFormatter(new PercentFormatter()); // change the color of the center-hole // mChart.setHoleColor(Color.rgb(235, 235, 235)); @@ -137,6 +139,10 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.saveToPath("title" + System.currentTimeMillis(), ""); break; } + case R.id.actionTogglePercent: + mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); + mChart.invalidate(); + break; case R.id.animateX: { mChart.animateX(1800); break; @@ -180,8 +186,8 @@ private void setData(int count, float range) { for (int i = 0; i < count + 1; i++) xVals.add(mParties[i % mParties.length]); - PieDataSet set1 = new PieDataSet(yVals1, "Election Results"); - set1.setSliceSpace(3f); + PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); + dataSet.setSliceSpace(3f); // add a lot of colors @@ -204,9 +210,9 @@ private void setData(int count, float range) { colors.add(ColorTemplate.getHoloBlue()); - set1.setColors(colors); + dataSet.setColors(colors); - PieData data = new PieData(xVals, set1); + PieData data = new PieData(xVals, dataSet); mChart.setData(data); // undo all highlights diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java index 3244626717..1e3e223f72 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java @@ -1,6 +1,5 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.utils.ValueFormatter; import java.text.DecimalFormat; @@ -8,16 +7,14 @@ public class PercentFormatter implements ValueFormatter { private DecimalFormat mFormat; - private PieChart mChart; - public PercentFormatter(PieChart chart) { + public PercentFormatter() { mFormat = new DecimalFormat("#,##0.0"); - this.mChart = chart; } @Override public String getFormattedValue(float value) { - return mFormat.format(mChart.getPercentOfTotal(value)) + " %"; + return mFormat.format(value) + " %"; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 5cb63449d1..f08cc62c1b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -57,7 +57,7 @@ public View getView(int position, View convertView, Context c) { holder.chart.setCenterTextTypeface(mTf); holder.chart.setCenterTextSize(18f); holder.chart.setValueTextSize(11f); - holder.chart.setValueFormatter(new PercentFormatter(holder.chart)); + holder.chart.setValueFormatter(new PercentFormatter()); // set data holder.chart.setData((PieData) mChartData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 8b21042a54..9c96048039 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -32,7 +32,7 @@ public class PieChart extends PieRadarChartBase { * drawing the circle */ private RectF mCircleBox = new RectF(); - + /** flag indicating if the x-labels should be drawn or not */ protected boolean mDrawXLabels = true; @@ -45,6 +45,9 @@ public class PieChart extends PieRadarChartBase { /** if true, the white hole inside the chart will be drawn */ private boolean mDrawHole = true; + /** if true, the values inside the piechart are drawn as percent values */ + private boolean mUsePercentValues = false; + /** * variable for the text that is drawn in the center of the pie-chart. If * this value is null, the default is "Total Value\n + getYValueSum()" @@ -456,7 +459,7 @@ public void setTransparentCircleRadius(final float percent) { public float getTransparentCircleRadius() { return mTransparentCircleRadiusPercent; - } + } /** * set this to true to draw the x-value text into the pie slices @@ -476,6 +479,21 @@ public boolean isDrawSliceTextEnabled() { return mDrawXLabels; } + /** + * If this is enabled, values inside the PieChart are drawn in percent and + * not with their original value. Values provided for the ValueFormatter to + * format are then provided in percent. + * + * @param enabled + */ + public void setUsePercentValues(boolean enabled) { + mUsePercentValues = enabled; + } + + public boolean isUsePercentValuesEnabled() { + return mUsePercentValues; + } + @Override public void setPaint(Paint p, int which) { super.setPaint(p, which); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 124e22d4ea..feb6348adb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -6,20 +6,21 @@ /** * A PieData object can only represent one DataSet. Unlike all other charts, the * legend labels of the PieChart are created from the x-values array, and not - * from the DataSet labels. + * from the DataSet labels. Each PieData object can only represent one + * PieDataSet (multiple PieDataSets inside a single PieChart are not possible). * * @author Philipp Jahoda */ public class PieData extends ChartData { - + public PieData() { super(); } - + public PieData(ArrayList xVals) { super(xVals); } - + public PieData(String[] xVals) { super(xVals); } @@ -31,7 +32,7 @@ public PieData(ArrayList xVals, PieDataSet dataSet) { public PieData(String[] xVals, PieDataSet dataSet) { super(xVals, toArrayList(dataSet)); } - + private static ArrayList toArrayList(PieDataSet dataSet) { ArrayList sets = new ArrayList(); sets.add(dataSet); @@ -39,11 +40,34 @@ private static ArrayList toArrayList(PieDataSet dataSet) { } /** - * Returns the DataSet this PieData object represents. + * Sets the PieDataSet this data object should represent. + * + * @param dataSet + */ + public void setDataSet(PieDataSet dataSet) { + mDataSets.clear(); + mDataSets.add(dataSet); + init(mDataSets); + } + + /** + * Returns the DataSet this PieData object represents. A PieData object can + * only contain one DataSet. * * @return */ public PieDataSet getDataSet() { - return (PieDataSet) mDataSets.get(0); + return mDataSets.get(0); + } + + @Override + public PieDataSet getDataSetByIndex(int index) { + return index == 0 ? getDataSet() : null; + } + + @Override + public PieDataSet getDataSetByLabel(String label, boolean ignorecase) { + return ignorecase ? label.equalsIgnoreCase(mDataSets.get(0).getLabel()) ? mDataSets.get(0) + : null : label.equals(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 6bf00e94be..2522addfe2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -51,11 +51,11 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mValuePaint.setColor(Color.WHITE); mValuePaint.setTextAlign(Align.CENTER); } - + public Paint getPaintHole() { return mHolePaint; } - + public Paint getPaintCenterText() { return mCenterTextPaint; } @@ -155,7 +155,8 @@ public void drawValues(Canvas c) { * Math.sin(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) * mAnimator.getPhaseY())) + center.y); - float value = entries.get(j).getVal(); + float value = mChart.isUsePercentValuesEnabled() ? entries.get(j).getVal() + / mChart.getYValueSum() * 100f : entries.get(j).getVal(); String val = mChart.getValueFormatter().getFormattedValue(value); From 266fb4d5d6497ea28ab71012d0f6657921f42583 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Feb 2015 11:28:04 +0100 Subject: [PATCH 0092/1390] Highlighting with multiple datasets and different axes now working. --- .../mpchartexample/PieChartActivity.java | 1 + .../listviewitems/PieChartItem.java | 1 + .../charting/charts/BarLineChartBase.java | 71 +++++++++++++------ .../mikephil/charting/charts/Chart.java | 25 ------- .../charting/charts/PieRadarChartBase.java | 30 ++++++++ .../mikephil/charting/data/ChartData.java | 4 +- .../listener/PieRadarChartTouchListener.java | 4 +- .../mikephil/charting/utils/SelInfo.java | 6 +- .../github/mikephil/charting/utils/Utils.java | 51 +++++++++++-- 9 files changed, 136 insertions(+), 57 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 0f2c5977df..3fd65f5bce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -52,6 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setValueFormatter(new PercentFormatter()); + mChart.setUsePercentValues(true); // change the color of the center-hole // mChart.setHoleColor(Color.rgb(235, 235, 235)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index f08cc62c1b..d071322e52 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -58,6 +58,7 @@ public View getView(int position, View convertView, Context c) { holder.chart.setCenterTextSize(18f); holder.chart.setValueTextSize(11f); holder.chart.setValueFormatter(new PercentFormatter()); + holder.chart.setUsePercentValues(true); // set data holder.chart.setData((PieData) mChartData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 3283459567..a895a5772a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -13,6 +13,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; +import android.widget.Toast; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; @@ -23,6 +24,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -237,7 +239,8 @@ protected void onDraw(Canvas canvas) { private void prepareValuePxMatrix() { if (mLogEnabled) - Log.i(LOG_TAG, "Preparing Value-Px Matrix, xmin: " + mXChartMin + ", xmax: " + mXChartMax + ", xdelta: " + mDeltaX); + Log.i(LOG_TAG, "Preparing Value-Px Matrix, xmin: " + mXChartMin + ", xmax: " + + mXChartMax + ", xdelta: " + mDeltaX); mRightAxisTransformer.prepareMatrixValuePx(mXChartMin, mDeltaX, mAxisRight.mAxisRange, mAxisRight.mAxisMinimum); @@ -292,7 +295,7 @@ protected void calcMinMax() { float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); Log.i(LOG_TAG, "minLeft: " + minLeft + ", maxLeft: " + maxLeft); - + mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); @@ -1116,21 +1119,14 @@ public Highlight getHighlightByTouchPoint(float x, float y) { // create an array of the touch-point float[] pts = new float[2]; pts[0] = x; - pts[1] = y; + // take any transformer to determine the x-axis value mLeftAxisTransformer.pixelsToValue(pts); double xTouchVal = pts[0]; - double yTouchVal = pts[1]; double base = Math.floor(xTouchVal); double touchOffset = mDeltaX * 0.025; - // Log.i(LOG_TAG, "touchindex x: " + xTouchVal + ", touchindex y: " + - // yTouchVal + ", offset: " - // + touchOffset); - // Toast.makeText(getContext(), "touchindex x: " + xTouchVal + - // ", touchindex y: " + yTouchVal + ", offset: " + touchOffset, - // Toast.LENGTH_SHORT).show(); // touch out of chart if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset) @@ -1143,9 +1139,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { int xIndex = (int) base; - int dataSetIndex = 0; // index of the DataSet inside the ChartData - // object - // check if we are more than half of a x-value or not if (xTouchVal - base > 0.5) { xIndex = (int) base + 1; @@ -1153,18 +1146,56 @@ public Highlight getHighlightByTouchPoint(float x, float y) { ArrayList valsAtIndex = getYValsAtIndex(xIndex); - dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, (float) yTouchVal); + float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); + float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); + + if (mData.getFirstRight() == null) + rightdist = Float.MAX_VALUE; + if (mData.getFirstLeft() == null) + leftdist = Float.MAX_VALUE; + + AxisDependency axis = leftdist < rightdist ? AxisDependency.LEFT : AxisDependency.RIGHT; + + int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); if (dataSetIndex == -1) return null; - // Toast.makeText(getContext(), "xindex: " + xIndex + ", dataSetIndex: " - // + dataSetIndex, - // Toast.LENGTH_SHORT).show(); - return new Highlight(xIndex, dataSetIndex); } + /** + * Returns an array of SelInfo objects for the given x-index. The SelInfo + * objects give information about the value at the selected index and the + * DataSet it belongs to. INFORMATION: This method does calculations at + * runtime. Do not over-use in performance critical situations. + * + * @return + */ + public ArrayList getYValsAtIndex(int xIndex) { + + ArrayList vals = new ArrayList(); + + float[] pts = new float[2]; + + for (int i = 0; i < mData.getDataSetCount(); i++) { + + DataSet dataSet = mData.getDataSetByIndex(i); + + // extract all y-values from all DataSets at the given x-index + float yVal = dataSet.getYValForXIndex(xIndex); + pts[1] = yVal; + + getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + + if (!Float.isNaN(pts[1])) { + vals.add(new SelInfo(pts[1], i, dataSet)); + } + } + + return vals; + } + /** * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to @@ -1472,7 +1503,7 @@ public Paint getPaint(int which) { return null; } - + /** * Default formatter that calculates the position of the filled line. * @@ -1512,5 +1543,5 @@ public float getFillLinePosition(LineDataSet dataSet, LineData data, return fillMin; } - } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index d81ce25ad7..accdc466d4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1689,31 +1689,6 @@ public void setValueTextSize(float size) { // return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); // } - /** - * Returns an array of SelInfo objects for the given x-index. The SelInfo - * objects give information about the value at the selected index and the - * DataSet it belongs to. INFORMATION: This method does calculations at - * runtime. Do not over-use in performance critical situations. - * - * @return - */ - public ArrayList getYValsAtIndex(int xIndex) { - - ArrayList vals = new ArrayList(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - // extract all y-values from all DataSets at the given x-index - float yVal = mData.getDataSetByIndex(i).getYValForXIndex(xIndex); - - if (!Float.isNaN(yVal)) { - vals.add(new SelInfo(yVal, i)); - } - } - - return vals; - } - /** * Get all Entry objects at the given index across all DataSets. * INFORMATION: This method does calculations at runtime. Do not over-use in diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 345ab74cff..1cbcc3207d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -14,9 +14,12 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; +import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; import com.nineoldandroids.animation.ObjectAnimator; +import java.util.ArrayList; + /** * Baseclass of PieChart and RadarChart. * @@ -415,6 +418,33 @@ public float getYChartMin() { return 0; } + /** + * Returns an array of SelInfo objects for the given x-index. The SelInfo + * objects give information about the value at the selected index and the + * DataSet it belongs to. INFORMATION: This method does calculations at + * runtime. Do not over-use in performance critical situations. + * + * @return + */ + public ArrayList getYValsAtIndex(int xIndex) { + + ArrayList vals = new ArrayList(); + + for (int i = 0; i < mData.getDataSetCount(); i++) { + + DataSet dataSet = mData.getDataSetByIndex(i); + + // extract all y-values from all DataSets at the given x-index + float yVal = dataSet.getYValForXIndex(xIndex); + + if (!Float.isNaN(yVal)) { + vals.add(new SelInfo(yVal, i, dataSet)); + } + } + + return vals; + } + /** * ################ ################ ################ ################ */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 57af315190..7aac6a907f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -806,7 +806,7 @@ public int getIndexOfDataSet(T dataSet) { return -1; } - private T getFirstLeft() { + public T getFirstLeft() { for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; @@ -815,7 +815,7 @@ private T getFirstLeft() { return null; } - private T getFirstRight() { + public T getFirstRight() { for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 37006d13ce..0be00e2d79 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -127,7 +127,7 @@ public boolean onSingleTapUp(MotionEvent e) { mChart.highlightValues(null); mLastHighlight = null; - + } else { ArrayList valsAtIndex = mChart.getYValsAtIndex(index); @@ -140,7 +140,7 @@ public boolean onSingleTapUp(MotionEvent e) { if (mChart instanceof RadarChart) { dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, distance - / ((RadarChart) mChart).getFactor()); + / ((RadarChart) mChart).getFactor(), null); } Highlight h = new Highlight(index, dataSetIndex); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java index 3213500a3b..4c3749a9a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.utils; +import com.github.mikephil.charting.data.DataSet; + /** * Class that encapsulates information of a value that has been * selected/highlighted and its DataSet index. The SelInfo objects give @@ -13,9 +15,11 @@ public class SelInfo { public float val; public int dataSetIndex; + public DataSet dataSet; - public SelInfo(float val, int dataSetIndex) { + public SelInfo(float val, int dataSetIndex, DataSet set) { this.val = val; this.dataSetIndex = dataSetIndex; + this.dataSet = set; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 3f00259d69..0513dfb91d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -8,6 +8,8 @@ import android.util.DisplayMetrics; import android.util.Log; +import com.github.mikephil.charting.components.YAxis.AxisDependency; + import java.text.DecimalFormat; import java.util.ArrayList; @@ -359,17 +361,23 @@ public static double nextUp(double d) { * @param valsAtIndex all the values at a specific index * @return */ - public static int getClosestDataSetIndex(ArrayList valsAtIndex, float val) { + public static int getClosestDataSetIndex(ArrayList valsAtIndex, float val, + AxisDependency axis) { int index = -1; float distance = Float.MAX_VALUE; for (int i = 0; i < valsAtIndex.size(); i++) { - float cdistance = Math.abs((float) valsAtIndex.get(i).val - val); - if (cdistance < distance) { - index = valsAtIndex.get(i).dataSetIndex; - distance = cdistance; + SelInfo sel = valsAtIndex.get(i); + + if (axis == null || sel.dataSet.getAxisDependency() == axis) { + + float cdistance = Math.abs((float) sel.val - val); + if (cdistance < distance) { + index = valsAtIndex.get(i).dataSetIndex; + distance = cdistance; + } } } @@ -377,8 +385,37 @@ public static int getClosestDataSetIndex(ArrayList valsAtIndex, float v return index; } - - + + /** + * Returns the minimum distance from a touch-y-value (in pixels) to the + * closest y-value (in pixels) that is displayed in the chart. + * + * @param valsAtIndex + * @param val + * @param axis + * @return + */ + public static float getMinimumDistance(ArrayList valsAtIndex, float val, + AxisDependency axis) { + + float distance = Float.MAX_VALUE; + + for (int i = 0; i < valsAtIndex.size(); i++) { + + SelInfo sel = valsAtIndex.get(i); + + if (sel.dataSet.getAxisDependency() == axis) { + + float cdistance = Math.abs((float) sel.val - val); + if (cdistance < distance) { + distance = cdistance; + } + } + } + + return distance; + } + /** * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. From c9df99a643186ee96acb7e16a6aa39da1d812ba9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 20 Feb 2015 21:59:06 +0100 Subject: [PATCH 0093/1390] Removed chart-borders, instead intruducing axis-lines alongside each axis. --- .../mpchartexample/AnotherBarActivity.java | 4 +- .../mpchartexample/BarChartActivity.java | 8 +- .../CandleStickChartActivity.java | 5 +- .../CubicLineChartActivity.java | 2 - .../HorizontalBarChartActivity.java | 9 +- .../InvertedLineChartActivity.java | 8 +- .../mpchartexample/LineChartActivity1.java | 7 - .../mpchartexample/LineChartActivity2.java | 19 +-- .../LineChartActivityColored.java | 1 - .../ListViewBarChartActivity.java | 4 +- .../RealtimeLineChartActivity.java | 6 - .../mpchartexample/StackedBarActivity.java | 4 +- .../fragments/BarChartFrag.java | 3 +- .../fragments/ComplexityFragment.java | 1 - .../fragments/ScatterChartFrag.java | 1 - .../fragments/SineCosineFragment.java | 1 - .../listviewitems/BarChartItem.java | 4 +- .../listviewitems/LineChartItem.java | 4 +- .../mikephil/charting/charts/BarChart.java | 2 - .../charting/charts/BarLineChartBase.java | 145 +++--------------- .../charting/charts/CombinedChart.java | 8 +- .../charting/components/AxisBase.java | 88 ++++++++--- .../mikephil/charting/components/XAxis.java | 8 +- .../mikephil/charting/data/CombinedData.java | 25 +-- .../charting/renderer/AxisRenderer.java | 24 ++- .../charting/renderer/XAxisRenderer.java | 39 ++++- .../charting/renderer/YAxisRenderer.java | 22 +++ 27 files changed, 213 insertions(+), 239 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 03e69be33d..f45d0417ce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -61,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); XAxis xAxis = mChart.getXAxis(); - xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setCenterXLabelText(true); xAxis.setSpaceBetweenLabels(0); xAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index ff56bf2d50..65fd9db9ae 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -19,7 +19,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; @@ -79,14 +79,10 @@ protected void onCreate(Bundle savedInstanceState) { // sets the text size of the values inside the chart mChart.setValueTextSize(10f); - mChart.setDrawBorder(false); - // mChart.setBorderPositions(new BorderPosition[] {BorderPosition.LEFT, - // BorderPosition.RIGHT}); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xl = mChart.getXAxis(); - xl.setPosition(XLabelPosition.BOTTOM); + xl.setPosition(XAxisPosition.BOTTOM); xl.setTypeface(tf); xl.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 408d0b9c65..a9d4cb8e05 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -13,9 +13,8 @@ import com.github.mikephil.charting.charts.CandleStickChart; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; @@ -59,7 +58,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); XAxis xLabels = mChart.getXAxis(); - xLabels.setPosition(XLabelPosition.BOTTOM); + xLabels.setPosition(XAxisPosition.BOTTOM); xLabels.setSpaceBetweenLabels(2); YAxis yLabels = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 35ab61f825..8422acf956 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -52,8 +52,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); // if enabled, the chart will always start at zero on the y-axis - - mChart.setDrawBorder(false); mChart.setDrawLegend(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 4205f8b667..9a9eccb9b0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -16,10 +16,9 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -77,14 +76,10 @@ protected void onCreate(Bundle savedInstanceState) { // sets the text size of the values inside the chart mChart.setValueTextSize(10f); - mChart.setDrawBorder(false); - // mChart.setBorderPositions(new BorderPosition[] {BorderPosition.LEFT, - // BorderPosition.RIGHT}); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xl = mChart.getXAxis(); - xl.setPosition(XLabelPosition.BOTTOM); + xl.setPosition(XAxisPosition.BOTTOM); xl.setCenterXLabelText(true); xl.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 40cd1ca438..0d91fd1e7c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -11,7 +11,6 @@ import android.widget.TextView; import android.widget.Toast; -import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; @@ -56,12 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - - mChart.setDrawBorder(true); - mChart.setBorderPositions(new BorderPosition[] { - BorderPosition.BOTTOM - }); - + // no description text mChart.setDescription(""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index ada8d02af2..f684a5e9da 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -13,14 +13,12 @@ import android.widget.TextView; import android.widget.Toast; -import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -64,11 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartGestureListener(this); mChart.setOnChartValueSelectedListener(this); - mChart.setDrawBorder(true); - mChart.setBorderPositions(new BorderPosition[] { - BorderPosition.BOTTOM - }); - // no description text mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9de2433951..2b3f981bed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -13,13 +13,12 @@ import android.widget.TextView; import android.widget.Toast; -import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -60,12 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setValueTextColor(Color.WHITE); - - mChart.setDrawBorder(true); - mChart.setBorderPositions(new BorderPosition[] { - BorderPosition.BOTTOM - }); - + // no description text mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); @@ -103,10 +97,10 @@ protected void onCreate(Bundle savedInstanceState) { l.setTypeface(tf); l.setTextColor(Color.WHITE); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); - xl.setTextColor(Color.WHITE); - xl.setDrawGridLines(false); + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(tf); + xAxis.setTextColor(Color.WHITE); + xAxis.setDrawGridLines(false); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -117,6 +111,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setTextColor(Color.RED); + rightAxis.setAxisMaxValue(900); rightAxis.setDrawGridLines(false); // yl.setAxisMaxValue(300f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 0849a43cbe..214e26857a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -52,7 +52,6 @@ protected void onCreate(Bundle savedInstanceState) { }; private void setupChart(LineChart chart, LineData data, int color) { - chart.setDrawBorder(false); // no description text chart.setDescription(""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index c5732065b2..3dd51f1b18 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -14,7 +14,7 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; @@ -92,7 +92,7 @@ public View getView(int position, View convertView, ViewGroup parent) { XAxis xAxis = holder.chart.getXAxis(); xAxis.setCenterXLabelText(true); - xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 7c8786fe78..75df73fc48 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -9,7 +9,6 @@ import android.view.MenuItem; import android.view.WindowManager; -import com.github.mikephil.charting.charts.BarLineChartBase.BorderPosition; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; @@ -39,11 +38,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setValueTextColor(Color.WHITE); - mChart.setDrawBorder(true); - mChart.setBorderPositions(new BorderPosition[] { - BorderPosition.BOTTOM - }); - // no description text mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 1be97dd5f6..846d1e47ef 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -15,7 +15,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; @@ -81,7 +81,7 @@ protected void onCreate(Bundle savedInstanceState) { yLabels.setFormatter(customFormatter); XAxis xLabels = mChart.getXAxis(); - xLabels.setPosition(XLabelPosition.TOP); + xLabels.setPosition(XAxisPosition.TOP); xLabels.setCenterXLabelText(true); // mChart.setDrawXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 6a263daf18..91c8316e5f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -36,8 +36,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setMarkerView(mv); mChart.setHighlightIndicatorEnabled(false); - mChart.setDrawBorder(false); -// mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); + mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 58dfa3e9bf..6968d09b1f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -30,7 +30,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setDescription(""); mChart.setHighlightIndicatorEnabled(false); - mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); mChart.setData(getComplexity()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 903092bccd..41a44d4104 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -36,7 +36,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setMarkerView(mv); mChart.setHighlightIndicatorEnabled(false); - mChart.setDrawBorder(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); mChart.setData(generateScatterData(3, 10000, 150)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index cdf5bf515a..35f459eff4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -31,7 +31,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa // mChart.setCircleSize(5f); mChart.setHighlightIndicatorEnabled(false); - mChart.setDrawBorder(false); mChart.setDrawGridBackground(false); mChart.setData(generateLineData()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index fb25c5c220..17880d7aa6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.ChartData; @@ -55,7 +55,7 @@ public View getView(int position, View convertView, Context c) { XAxis xAxis = holder.chart.getXAxis(); xAxis.setCenterXLabelText(true); - xAxis.setPosition(XLabelPosition.BOTTOM); + xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 172401b252..002203488b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -8,7 +8,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.LineData; @@ -54,7 +54,7 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDrawGridBackground(false); XAxis xl = holder.chart.getXAxis(); - xl.setPosition(XLabelPosition.BOTTOM); + xl.setPosition(XAxisPosition.BOTTOM); xl.setTypeface(mTf); xl.setDrawGridLines(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 2ecdee2001..1f98b6b9c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -16,8 +16,6 @@ import com.github.mikephil.charting.renderer.XAxisRendererBarChart; import com.github.mikephil.charting.utils.Highlight; -import java.math.BigDecimal; - /** * Chart that draws bars. * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a895a5772a..1359352bc4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -13,11 +13,10 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; -import android.widget.Toast; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; @@ -79,18 +78,12 @@ public abstract class BarLineChartBase implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider { - + private FillFormatter mFillFormatter; public CombinedChart(Context context) { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 4fa76d2f9b..85dbde0d60 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -22,10 +22,11 @@ public abstract class AxisBase { /** the text color to use */ private int mTextColor = Color.BLACK; - /** the color of the axis lines */ - private int mAxisColor = Color.BLACK; + private int mGridColor = Color.GRAY; - private int mGridColor = Color.GRAY; + private int mAxisLineColor = Color.GRAY; + + private float mAxisLineWidth = 1f; /** flag that indicates if this axis is enabled or not */ protected boolean mEnabled = true; @@ -33,21 +34,24 @@ public abstract class AxisBase { /** flag indicating if the grid lines for this axis should be drawn */ protected boolean mDrawGridLines = true; + /** flag that indicates if the line alongside the axis is drawn or not */ + protected boolean mDrawAxisLine = false; + /** default constructor */ public AxisBase() { mTextSize = Utils.convertDpToPixel(10f); } /** - * sets the size of the label text in pixels min = 6f, max = 16f, default + * sets the size of the label text in pixels min = 6f, max = 24f, default * 10f * * @param size */ public void setTextSize(float size) { - if (size > 16f) - size = 16f; + if (size > 24f) + size = 24f; if (size < 6f) size = 6f; @@ -101,43 +105,44 @@ public int getTextColor() { } /** - * Returns the color of the axis line. + * Set this to true to enable drawing the grid lines for this axis. * - * @return + * @param enabled */ - public int getAxisColor() { - return mAxisColor; + public void setDrawGridLines(boolean enabled) { + mDrawGridLines = enabled; } /** - * Sets the color of the axis line. + * Returns true if drawing grid lines is enabled for this axis. * - * @param color + * @return */ - public void setAxisColor(int color) { - mAxisColor = color; + public boolean isDrawGridLinesEnabled() { + return mDrawGridLines; } /** - * Set this to true to enable drawing the grid lines for this axis. + * Set this to true if the line alongside the axis should be drawn or not. * * @param enabled */ - public void setDrawGridLines(boolean enabled) { - mDrawGridLines = enabled; + public void setDrawAxisLine(boolean enabled) { + mDrawAxisLine = enabled; } /** - * Returns true if drawing grid lines is enabled for this axis. + * Returns true if the line alongside the axis should be drawn. * * @return */ - public boolean isDrawGridLinesEnabled() { - return mDrawGridLines; + public boolean isDrawAxisLineEnabled() { + return mDrawAxisLine; } /** - * Sets the color of the grid lines for this axis. + * Sets the color of the grid lines for this axis (the horizontal lines + * coming from each label). * * @param color */ @@ -146,13 +151,50 @@ public void setGridColor(int color) { } /** - * Returns the color of the grid lines for this axis. + * Returns the color of the grid lines for this axis (the horizontal lines + * coming from each label). * * @return */ public int getGridColor() { return mGridColor; - } + } + + /** + * Sets the width of the border surrounding the chart in dp. + * + * @param width + */ + public void setAxisLineWidth(float width) { + mAxisLineWidth = Utils.convertDpToPixel(width); + } + + /** + * Returns the width of the axis line (line alongside the axis). + * + * @return + */ + public float getAxisLineWidth() { + return mAxisLineWidth; + } + + /** + * Sets the color of the border surrounding the chart. + * + * @param color + */ + public void setAxisLineColor(int color) { + mAxisLineColor = color; + } + + /** + * Returns the color of the axis line (line alongside the axis). + * + * @return + */ + public int getAxisLineColor() { + return mAxisLineColor; + } /** * Set this to true to enable this axis from being drawn to the screen. diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index b931fefc74..950a85b03f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -63,10 +63,10 @@ public class XAxis extends AxisBase { protected boolean mAdjustXAxisLabels = true; /** the position of the x-labels relative to the chart */ - private XLabelPosition mPosition = XLabelPosition.TOP; + private XAxisPosition mPosition = XAxisPosition.TOP; /** enum for the position of the x-labels relative to the chart */ - public enum XLabelPosition { + public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } @@ -113,7 +113,7 @@ public boolean isAdjustXLabelsEnabled() { /** * returns the position of the x-labels */ - public XLabelPosition getPosition() { + public XAxisPosition getPosition() { return mPosition; } @@ -122,7 +122,7 @@ public XLabelPosition getPosition() { * * @param pos */ - public void setPosition(XLabelPosition pos) { + public void setPosition(XAxisPosition pos) { mPosition = pos; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index ab836c667f..369988d861 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,50 +1,57 @@ + package com.github.mikephil.charting.data; import java.util.ArrayList; +/** + * Data object that allows the combination of Line-, Bar-, Scatter- and + * CandleData. Used in the CombinedChart class. + * + * @author Philipp Jahoda + */ public class CombinedData extends BarLineScatterCandleData> { private LineData mLineData; private BarData mBarData; private ScatterData mScatterData; private CandleData mCandleData; - + public CombinedData() { super(); } - + public CombinedData(ArrayList xVals) { super(xVals); } - + public CombinedData(String[] xVals) { super(xVals); } - + public void setData(LineData data) { mLineData = data; mDataSets.addAll(data.getDataSets()); init(data.getDataSets()); } - + public void setData(BarData data) { mBarData = data; mDataSets.addAll(data.getDataSets()); init(data.getDataSets()); } - + public void setData(ScatterData data) { mScatterData = data; mDataSets.addAll(data.getDataSets()); init(data.getDataSets()); } - + public void setData(CandleData data) { mCandleData = data; mDataSets.addAll(data.getDataSets()); init(data.getDataSets()); - } - + } + public LineData getLineData() { return mLineData; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index 0bab566676..5e7bd0617e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -16,7 +16,10 @@ public abstract class AxisRenderer extends Renderer { protected Paint mGridPaint; /** paint for the x-label values */ - protected Paint mAxisPaint; + protected Paint mAxisPaint; + + /** paint for the line surrounding the chart */ + protected Paint mAxisLinePaint; public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans) { super(viewPortHandler); @@ -30,6 +33,11 @@ public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans) { mGridPaint.setStrokeWidth(1f); mGridPaint.setStyle(Style.STROKE); mGridPaint.setAlpha(90); + + mAxisLinePaint = new Paint(); + mAxisLinePaint.setColor(Color.BLACK); + mAxisLinePaint.setStrokeWidth(1f); + mAxisLinePaint.setStyle(Style.STROKE); } /** @@ -41,12 +49,15 @@ public Paint getAxisPaint() { return mAxisPaint; } + /** + * Returns the Transformer object used for transforming the axis values. + * + * @return + */ public Transformer getTransformer() { return mTrans; } - // public abstract void computeAxis(ChartInterface chart); - /** * Draws the axis labels to the screen. * @@ -60,4 +71,11 @@ public Transformer getTransformer() { * @param c */ public abstract void renderGridLines(Canvas c); + + /** + * Draws the line that goes alongside the axis. + * + * @param c + */ + protected abstract void drawAxisLine(Canvas c); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 7faf175d70..96348f58a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,7 +6,8 @@ import android.graphics.Paint.Align; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.XAxis.XLabelPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -54,19 +55,19 @@ public void renderAxis(Canvas c) { mAxisPaint.setTextSize(mXAxis.getTextSize()); mAxisPaint.setColor(mXAxis.getTextColor()); - if (mXAxis.getPosition() == XLabelPosition.TOP) { + if (mXAxis.getPosition() == XAxisPosition.TOP) { drawLabels(c, mViewPortHandler.offsetTop() - yoffset); - } else if (mXAxis.getPosition() == XLabelPosition.BOTTOM) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.5f); - } else if (mXAxis.getPosition() == XLabelPosition.BOTTOM_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { drawLabels(c, mViewPortHandler.contentBottom() - yoffset); - } else if (mXAxis.getPosition() == XLabelPosition.TOP_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { drawLabels(c, mViewPortHandler.offsetTop() + yoffset + mXAxis.mLabelHeight); @@ -75,6 +76,34 @@ public void renderAxis(Canvas c) { drawLabels(c, mViewPortHandler.offsetTop() - yoffset); drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.6f); } + + drawAxisLine(c); + } + + @Override + protected void drawAxisLine(Canvas c) { + + if (!mXAxis.isDrawAxisLineEnabled()) + return; + + mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mXAxis.getAxisLineWidth()); + + if (mXAxis.getPosition() == XAxisPosition.TOP + || mXAxis.getPosition() == XAxisPosition.TOP_INSIDE + || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mAxisLinePaint); + } + + if (mXAxis.getPosition() == XAxisPosition.BOTTOM + || mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE + || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 1e9147fcfc..8693795a0a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -214,6 +214,28 @@ public void renderAxis(Canvas c) { } drawYLabels(c, xPos, positions, yoffset); + + drawAxisLine(c); + } + + @Override + protected void drawAxisLine(Canvas c) { + + if (!mYAxis.isDrawAxisLineEnabled()) + return; + + mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); + + if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } else { + c.drawLine(mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } } /** From 976dbbbdef1d30602ba18923d3a1e3dac4f2dc44 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 20 Feb 2015 22:25:02 +0100 Subject: [PATCH 0094/1390] Fixed issues concerning limit lines. --- .../mpchartexample/LineChartActivity1.java | 18 +++-- .../charting/charts/BarLineChartBase.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 2 +- .../charting/components/LimitLine.java | 78 +++++++++++++------ .../charting/renderer/XAxisRenderer.java | 1 - .../charting/renderer/YAxisRenderer.java | 11 ++- .../renderer/YAxisRendererRadarChart.java | 2 +- 7 files changed, 79 insertions(+), 37 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f684a5e9da..9254dde235 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -321,20 +322,25 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); - LimitLine ll1 = new LimitLine(130f); + LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); ll1.enableDashedLine(10f, 10f, 0f); - ll1.setDrawValue(true); ll1.setLabelPosition(LimitLabelPosition.POS_RIGHT); + ll1.setTextSize(10f); - LimitLine ll2 = new LimitLine(-30f); + LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); ll2.setLineWidth(4f); ll2.enableDashedLine(10f, 10f, 0f); - ll2.setDrawValue(true); ll2.setLabelPosition(LimitLabelPosition.POS_RIGHT); + ll2.setTextSize(10f); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.addLimitLine(ll1); + leftAxis.addLimitLine(ll2); + leftAxis.setAxisMaxValue(220f); + leftAxis.setAxisMinValue(-50f); - mChart.getAxisLeft().addLimitLine(ll1); - mChart.getAxisLeft().addLimitLine(ll2); + mChart.getAxisRight().setEnabled(false); // set data mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 1359352bc4..fbcfdb9966 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -190,8 +190,8 @@ protected void onDraw(Canvas canvas) { mRenderer.drawData(mDrawCanvas); - mAxisRendererLeft.renderLimitLines(mDrawCanvas, mValueFormatter); - mAxisRendererRight.renderLimitLines(mDrawCanvas, mValueFormatter); + mAxisRendererLeft.renderLimitLines(mDrawCanvas); + mAxisRendererRight.renderLimitLines(mDrawCanvas); // if highlighting is enabled if (mHighlightEnabled && mHighLightIndicatorEnabled && valuesToHighlight()) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index e75022d741..f49ebd76d9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -131,7 +131,7 @@ protected void onDraw(Canvas canvas) { if (mDrawWeb) mRenderer.drawExtras(mDrawCanvas); - mYAxisRenderer.renderLimitLines(mDrawCanvas, mValueFormatter); + mYAxisRenderer.renderLimitLines(mDrawCanvas); mRenderer.drawData(mDrawCanvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java index e6bc158f7d..2f00ef7a80 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java @@ -27,8 +27,11 @@ public class LimitLine { /** the color of the value-text */ private int mValueTextColor = Color.BLACK; - /** flag that indicates if the value of the limit line is drawn or not */ - private boolean mDrawValue = true; + /** the size of the label text */ + private float mTextSize = 13f; + + /** label string that is drawn next to the limit line */ + private String mLabel = ""; /** the path effect of this LimitLine that makes dashed lines possible */ private DashPathEffect mDashPathEffect = null; @@ -44,12 +47,25 @@ public enum LimitLabelPosition { /** * Constructor with limit. * - * @param limit + * @param limit - the position (the value) on the y-axis where this line + * should appear */ public LimitLine(float limit) { mLimit = limit; } + /** + * Constructor with limit and label. + * + * @param limit - the position (the value) on the y-axis where this line + * should appear + * @param label - provide "" if no label is required + */ + public LimitLine(float limit, String label) { + mLimit = limit; + mLabel = label; + } + /** * Returns the limit that is set for this line. * @@ -141,25 +157,6 @@ public DashPathEffect getDashPathEffect() { return mDashPathEffect; } - /** - * Set this to true to enable the value of the LimitLine to be drawn next to - * it. Default: true, not supported for RadarChart. - * - * @param enabled - */ - public void setDrawValue(boolean enabled) { - mDrawValue = enabled; - } - - /** - * Returns true if drawing the value is enabled, false if not. - * - * @return - */ - public boolean isDrawValueEnabled() { - return mDrawValue; - } - /** * Sets the color of the value-text that is drawn next to the LimitLine. * @@ -196,4 +193,41 @@ public void setLabelPosition(LimitLabelPosition pos) { public LimitLabelPosition getLabelPosition() { return mLabelPosition; } + + /** + * Sets the label that is drawn next to the limit line. Provide "" if no + * label is required. + * + * @param label + */ + public void setLabel(String label) { + mLabel = label; + } + + /** + * Returns the label that is drawn next to the limit line. + * + * @return + */ + public String getLabel() { + return mLabel; + } + + /** + * Sets the size of the label-text. + * + * @param size + */ + public void setTextSize(float size) { + mTextSize = Utils.convertDpToPixel(size); + } + + /** + * Returns the size of the label text. + * + * @return + */ + public float getTextSize() { + return mTextSize; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 96348f58a2..315eea0c1b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -7,7 +7,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 8693795a0a..2d2934c821 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -36,7 +36,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mLimitLinePaint.setStyle(Paint.Style.STROKE); + mLimitLinePaint.setStyle(Paint.Style.FILL_AND_STROKE); } /** @@ -286,7 +286,7 @@ public void renderGridLines(Canvas c) { * * @param c */ - public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { + public void renderLimitLines(Canvas c) { ArrayList limitLines = mYAxis.getLimitLines(); @@ -312,16 +312,19 @@ public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { mLimitLinePaint.setStrokeWidth(l.getLineWidth()); c.drawLines(pts, mLimitLinePaint); + + String label = l.getLabel(); // if drawing the limit-value is enabled - if (l.isDrawValueEnabled()) { + if (label != null && !label.equals("")) { float xOffset = Utils.convertDpToPixel(4f); float yOffset = l.getLineWidth() + xOffset; - String label = valueFormatter.getFormattedValue(l.getLimit()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); + mLimitLinePaint.setStrokeWidth(1f); + mLimitLinePaint.setTextSize(l.getTextSize()); if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index b9f3ec44d9..bd89ed590d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -92,7 +92,7 @@ public void renderAxis(Canvas c) { } @Override - public void renderLimitLines(Canvas c, ValueFormatter valueFormatter) { + public void renderLimitLines(Canvas c) { ArrayList limitLines = mYAxis.getLimitLines(); From 8ea1b3b234621f4eb74cfd3651b451acccb53449 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 20 Feb 2015 22:41:28 +0100 Subject: [PATCH 0095/1390] Fixed issue concerning start-at-zero. --- .../xxmassdeveloper/mpchartexample/BarChartActivity.java | 8 ++++---- .../mpchartexample/LineChartActivity1.java | 1 + .../github/mikephil/charting/renderer/YAxisRenderer.java | 7 +++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 65fd9db9ae..a1218c84b3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -81,10 +81,10 @@ protected void onCreate(Bundle savedInstanceState) { Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XAxis xl = mChart.getXAxis(); - xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(tf); - xl.setDrawGridLines(false); + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setTypeface(tf); + xAxis.setDrawGridLines(false); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 9254dde235..eeddb0ba86 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -339,6 +339,7 @@ private void setData(int count, float range) { leftAxis.addLimitLine(ll2); leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); + leftAxis.setStartAtZero(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 2d2934c821..4b9ce25cb3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -14,7 +14,6 @@ import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; @@ -315,15 +314,15 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-value is enabled + // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + xOffset; + float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) / 2f; mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); - mLimitLinePaint.setStrokeWidth(1f); + mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { From d6ddb47d20805c4bd27fe25bcb3772955cc294c2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 21 Feb 2015 12:18:18 +0100 Subject: [PATCH 0096/1390] Fixed Stacked-BarChart legend issue. --- .../mikephil/charting/charts/Chart.java | 2 +- .../mikephil/charting/data/BarData.java | 33 ++++++++++++++++--- .../charting/renderer/BarChartRenderer.java | 1 - 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index accdc466d4..afc4cf929a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -454,7 +454,7 @@ public void prepareLegend() { BarDataSet bds = (BarDataSet) dataSet; String[] sLabels = bds.getStackLabels(); - for (int j = 0; j < clrs.size() && j < entryCount && j < bds.getStackSize(); j++) { + for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { labels.add(sLabels[j % sLabels.length]); colors.add(clrs.get(j)); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 433aeaeab7..5f810a2b61 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -12,15 +12,20 @@ public class BarData extends BarLineScatterCandleData { /** the space that is left between groups of bars */ private float mGroupSpace = 0.8f; - + +// /** +// * The maximum space (in pixels on the screen) a single bar can consume. +// */ +// private float mMaximumBarWidth = 100f; + public BarData() { super(); } - + public BarData(ArrayList xVals) { super(xVals); } - + public BarData(String[] xVals) { super(xVals); } @@ -40,7 +45,7 @@ public BarData(ArrayList xVals, BarDataSet dataSet) { public BarData(String[] xVals, BarDataSet dataSet) { super(xVals, toArrayList(dataSet)); } - + private static ArrayList toArrayList(BarDataSet dataSet) { ArrayList sets = new ArrayList(); sets.add(dataSet); @@ -72,4 +77,24 @@ public float getGroupSpace() { public void setGroupSpace(float percent) { mGroupSpace = percent / 100f; } +// +// /** +// * Sets the maximum width (in density pixels) a single bar in the barchart +// * should consume. +// * +// * @param max +// */ +// public void setBarWidthMaximum(float max) { +// mMaximumBarWidth = Utils.convertDpToPixel(max); +// } +// +// /** +// * Returns the maximum width (in density pixels) a single bar in the +// * barchart should consume. +// * +// * @return +// */ +// public float getBarWidthMaximum() { +// return mMaximumBarWidth; +// } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 378cd762a9..e795dcdfc0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -8,7 +8,6 @@ import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; From e29f40112b73efc36dc50c872c9845a0f776691b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 21 Feb 2015 14:56:03 +0100 Subject: [PATCH 0097/1390] Removed nineoldandroids library. Animations now only supported for API level 11 and higher. (issue #362) --- .../listviewitems/LineChartItem.java | 2 +- MPChartLib/libs/nineoldandroids-2.4.0-2.jar | Bin 110746 -> 0 bytes .../charting/animation/ChartAnimator.java | 26 +- .../charting/charts/BarLineChartBase.java | 8 +- .../mikephil/charting/charts/Chart.java | 253 +++++++++--------- .../charting/charts/PieRadarChartBase.java | 33 ++- .../charting/renderer/YAxisRenderer.java | 9 +- 7 files changed, 184 insertions(+), 147 deletions(-) delete mode 100644 MPChartLib/libs/nineoldandroids-2.4.0-2.jar diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 002203488b..1b0f87b207 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -72,7 +72,7 @@ public View getView(int position, View convertView, Context c) { // do not forget to refresh the chart // holder.chart.invalidate(); - holder.chart.animateX(1000); + holder.chart.animateX(750); return convertView; } diff --git a/MPChartLib/libs/nineoldandroids-2.4.0-2.jar b/MPChartLib/libs/nineoldandroids-2.4.0-2.jar deleted file mode 100644 index 43ee45ffcd10dd922d79c23d55a05fc9d41c7c16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110746 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 z 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 QzsZMSV5L#O5DV=80PK}`R{#J2 diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java index 702479360d..1b825f270e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java @@ -1,21 +1,26 @@ + package com.github.mikephil.charting.animation; -import com.nineoldandroids.animation.ObjectAnimator; -import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.SuppressLint; +@SuppressLint("NewApi") public class ChartAnimator { - + /** object that is updated upon animation update */ private AnimatorUpdateListener mListener; - + + public ChartAnimator() { + + } + public ChartAnimator(AnimatorUpdateListener listener) { mListener = listener; } /** * ################ ################ ################ ################ - * Animation support below Honeycomb thanks to Jake Wharton's awesome - * nineoldandroids library: https://github.com/JakeWharton/NineOldAndroids */ /** CODE BELOW THIS RELATED TO ANIMATION */ @@ -41,6 +46,9 @@ public ChartAnimator(AnimatorUpdateListener listener) { */ public void animateXY(int durationMillisX, int durationMillisY) { + if (android.os.Build.VERSION.SDK_INT < 11) + return; + mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); mAnimatorY.setDuration( durationMillisY); @@ -69,6 +77,9 @@ public void animateXY(int durationMillisX, int durationMillisY) { */ public void animateX(int durationMillis) { + if (android.os.Build.VERSION.SDK_INT < 11) + return; + mAnimatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); mAnimatorX.setDuration(durationMillis); mAnimatorX.addUpdateListener(mListener); @@ -84,6 +95,9 @@ public void animateX(int durationMillis) { */ public void animateY(int durationMillis) { + if (android.os.Build.VERSION.SDK_INT < 11) + return; + mAnimatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); mAnimatorY.setDuration(durationMillis); mAnimatorY.addUpdateListener(mListener); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index fbcfdb9966..44619e6550 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -178,7 +178,7 @@ protected void onDraw(Canvas canvas) { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); - + // make sure the graph values and grid cannot be drawn outside the // content-rect int clipRestoreCount = mDrawCanvas.save(); @@ -187,12 +187,12 @@ protected void onDraw(Canvas canvas) { mXAxisRenderer.renderGridLines(mDrawCanvas); mAxisRendererLeft.renderGridLines(mDrawCanvas); mAxisRendererRight.renderGridLines(mDrawCanvas); - - mRenderer.drawData(mDrawCanvas); - + mAxisRendererLeft.renderLimitLines(mDrawCanvas); mAxisRendererRight.renderLimitLines(mDrawCanvas); + mRenderer.drawData(mDrawCanvas); + // if highlighting is enabled if (mHighlightEnabled && mHighLightIndicatorEnabled && valuesToHighlight()) mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index afc4cf929a..c477c815d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1,6 +1,9 @@ package com.github.mikephil.charting.charts; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.graphics.Bitmap; @@ -39,11 +42,8 @@ import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; -import com.nineoldandroids.animation.ValueAnimator; -import com.nineoldandroids.animation.ValueAnimator.AnimatorUpdateListener; import java.io.File; import java.io.FileOutputStream; @@ -57,9 +57,10 @@ * * @author Philipp Jahoda */ +@SuppressLint("NewApi") public abstract class Chart>> extends ViewGroup - implements AnimatorUpdateListener, ChartInterface { + implements ChartInterface { public static final String LOG_TAG = "MPAndroidChart"; @@ -122,7 +123,7 @@ public abstract class Chart set = mData.getDataSetByLabel(dataSetLabel, true); -// return set.getYVals().get(index).getVal(); -// } -// -// /** -// * returns the y-value for the given x-index and DataSet index -// * -// * @param index -// * @param dataSet -// * @return -// */ -// public float getYValue(int xIndex, int dataSetIndex) { -// DataSet set = mData.getDataSetByIndex(dataSetIndex); -// return set.getYValForXIndex(xIndex); -// } -// -// /** -// * returns the DataSet with the given index in the DataSet array held by the -// * ChartData object. -// * -// * @param index -// * @return -// */ -// public DataSet getDataSetByIndex(int index) { -// return mData.getDataSetByIndex(index); -// } -// -// /** -// * returns the DataSet with the given label that is stored in the ChartData -// * object. -// * -// * @param type -// * @return -// */ -// public DataSet getDataSetByLabel(String dataSetLabel) { -// return mData.getDataSetByLabel(dataSetLabel, true); -// } -// -// /** -// * returns the Entry object from the first DataSet stored in the ChartData -// * object. If multiple DataSets are used, use getEntry(index, type) or -// * getEntryByDataSetIndex(xIndex, dataSetIndex); -// * -// * @param index -// * @return -// */ -// public Entry getEntry(int index) { -// return mData.getDataSetByIndex(0).getYVals().get(index); -// } -// -// /** -// * returns the Entry object at the given index from the DataSet with the -// * given label. -// * -// * @param index -// * @param dataSetLabel -// * @return -// */ -// public Entry getEntry(int index, String dataSetLabel) { -// return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); -// } -// -// /** -// * Returns the corresponding Entry object at the given xIndex from the given -// * DataSet. INFORMATION: This method does calculations at runtime. Do not -// * over-use in performance critical situations. -// * -// * @param xIndex -// * @param dataSetIndex -// * @return -// */ -// public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { -// return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); -// } + // /** + // * returns the x-value at the given index + // * + // * @param index + // * @return + // */ + // public String getXValue(int index) { + // if (mData == null || mData.getXValCount() <= index) + // return null; + // else + // return mData.getXVals().get(index); + // } + // + // /** + // * returns the y-value for the given index from the DataSet with the given + // * label + // * + // * @param index + // * @param dataSetLabel + // * @return + // */ + // public float getYValue(int index, String dataSetLabel) { + // DataSet set = mData.getDataSetByLabel(dataSetLabel, + // true); + // return set.getYVals().get(index).getVal(); + // } + // + // /** + // * returns the y-value for the given x-index and DataSet index + // * + // * @param index + // * @param dataSet + // * @return + // */ + // public float getYValue(int xIndex, int dataSetIndex) { + // DataSet set = mData.getDataSetByIndex(dataSetIndex); + // return set.getYValForXIndex(xIndex); + // } + // + // /** + // * returns the DataSet with the given index in the DataSet array held by + // the + // * ChartData object. + // * + // * @param index + // * @return + // */ + // public DataSet getDataSetByIndex(int index) { + // return mData.getDataSetByIndex(index); + // } + // + // /** + // * returns the DataSet with the given label that is stored in the + // ChartData + // * object. + // * + // * @param type + // * @return + // */ + // public DataSet getDataSetByLabel(String dataSetLabel) { + // return mData.getDataSetByLabel(dataSetLabel, true); + // } + // + // /** + // * returns the Entry object from the first DataSet stored in the ChartData + // * object. If multiple DataSets are used, use getEntry(index, type) or + // * getEntryByDataSetIndex(xIndex, dataSetIndex); + // * + // * @param index + // * @return + // */ + // public Entry getEntry(int index) { + // return mData.getDataSetByIndex(0).getYVals().get(index); + // } + // + // /** + // * returns the Entry object at the given index from the DataSet with the + // * given label. + // * + // * @param index + // * @param dataSetLabel + // * @return + // */ + // public Entry getEntry(int index, String dataSetLabel) { + // return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); + // } + // + // /** + // * Returns the corresponding Entry object at the given xIndex from the + // given + // * DataSet. INFORMATION: This method does calculations at runtime. Do not + // * over-use in performance critical situations. + // * + // * @param xIndex + // * @param dataSetIndex + // * @return + // */ + // public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { + // return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); + // } /** * Get all Entry objects at the given index across all DataSets. diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 1cbcc3207d..616ef67e6c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -1,13 +1,20 @@ package com.github.mikephil.charting.charts; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.animation.ValueAnimator.AnimatorUpdateListener; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Paint.Align; import android.graphics.PointF; import android.graphics.RectF; +import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; @@ -16,7 +23,6 @@ import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; -import com.nineoldandroids.animation.ObjectAnimator; import java.util.ArrayList; @@ -159,8 +165,8 @@ protected void calculateOffsets() { mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom); - Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop - + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); + Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); } // /** @@ -431,12 +437,12 @@ public ArrayList getYValsAtIndex(int xIndex) { ArrayList vals = new ArrayList(); for (int i = 0; i < mData.getDataSetCount(); i++) { - + DataSet dataSet = mData.getDataSetByIndex(i); // extract all y-values from all DataSets at the given x-index float yVal = dataSet.getYValForXIndex(xIndex); - + if (!Float.isNaN(yVal)) { vals.add(new SelInfo(yVal, i, dataSet)); } @@ -444,7 +450,7 @@ public ArrayList getYValsAtIndex(int xIndex) { return vals; } - + /** * ################ ################ ################ ################ */ @@ -460,13 +466,26 @@ public ArrayList getYValsAtIndex(int xIndex) { * @param fromangle * @param toangle */ + @SuppressLint("NewApi") public void spin(int durationmillis, float fromangle, float toangle) { + if (android.os.Build.VERSION.SDK_INT < 11) + return; + mRotationAngle = fromangle; mSpinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); mSpinAnimator.setDuration(durationmillis); - mSpinAnimator.addUpdateListener(this); + + final ViewGroup view = this; + + mSpinAnimator.addUpdateListener(new AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + ViewCompat.postInvalidateOnAnimation(view); + } + }); mSpinAnimator.start(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 4b9ce25cb3..e8f66d8fa9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -303,22 +303,23 @@ public void renderLimitLines(Canvas c) { mTrans.pointValuesToPixel(pts); - pts[0] = 0; - pts[2] = mViewPortHandler.getChartWidth(); + pts[0] = mViewPortHandler.contentLeft(); + pts[2] = mViewPortHandler.contentRight(); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setPathEffect(l.getDashPathEffect()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); c.drawLines(pts, mLimitLinePaint); - + String label = l.getLabel(); // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) / 2f; + float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) + / 2f; mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); From aee1ed09da06f17770910e33f895624b9df15835 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 21 Feb 2015 22:22:24 +0100 Subject: [PATCH 0098/1390] Worked on Horizontal-BarChart. --- MPChartExample/AndroidManifest.xml | 4 +- MPChartExample/build.gradle | 4 +- .../HorizontalBarChartActivity.java | 9 +- .../charting/charts/BarLineChartBase.java | 2 +- .../charting/charts/HorizontalBarChart.java | 128 +++------------ .../charting/renderer/BarChartRenderer.java | 4 +- .../renderer/HorizontalBarChartRenderer.java | 40 +++++ .../charting/renderer/YAxisRenderer.java | 8 +- .../YAxisRendererHorizontalBarChart.java | 149 ++++++++++++++++++ .../utils/HorizontalBarChartTransformer.java | 66 -------- 10 files changed, 225 insertions(+), 189 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 799037bfd8..b57370e86b 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="30" + android:versionName="2.0.0" > = mOffsetTop && position[1] <= getHeight() - mOffsetBottom) -// { -// String label = mData.getXVals().get(i); -// -// mDrawCanvas.drawText(label, mOffsetLeft - 10, position[1] + offset, mXLabelPaint); -// } -// } -// } -// -// private static String TALL_VALUE = "100%"; -// -// @Override -// protected float getPositiveYOffset(boolean drawAboveValueBar) -// { -// Rect bounds = new Rect(); -// mValuePaint.getTextBounds(TALL_VALUE, 0, TALL_VALUE.length(), bounds); -// -// return bounds.height() / 2; -// } -// -// @Override -// protected float getNegativeYOffset(boolean drawAboveValueBar) -// { -// return getPositiveYOffset(drawAboveValueBar); -// } - -// /** -// * Sets up the y-axis labels. Computes the desired number of labels between -// * the two given extremes. Unlike the papareXLabels() method, this method -// * needs to be called upon every refresh of the view. -// * -// * @return -// */ -// @Override -// protected void prepareYLabels() -// { -// mYLabels = new XLabelsAsYLabels(); -// // super.prepareYLabels(); -// -// } + @Override + protected void prepareValuePxMatrix() { + mRightAxisTransformer.prepareMatrixValuePx(mXChartMin, mAxisRight.mAxisRange, mDeltaX, + mAxisRight.mAxisMinimum); + mLeftAxisTransformer.prepareMatrixValuePx(mXChartMin, mAxisLeft.mAxisRange, mDeltaX, + mAxisLeft.mAxisMinimum); + } private class XLabelsAsYLabels extends YAxis { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index e795dcdfc0..ed84402573 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -56,7 +56,7 @@ public void drawData(Canvas c) { } } - private void drawDataSet(Canvas c, BarDataSet dataSet, int index) { + protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -291,7 +291,7 @@ public void drawValues(Canvas c) { * @param xPos * @param yPos */ - private void drawValue(Canvas c, float val, float xPos, float yPos) { + protected void drawValue(Canvas c, float val, float xPos, float yPos) { String value = mChart.getValueFormatter().getFormattedValue(val); c.drawText(value, xPos, yPos, diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java new file mode 100644 index 0000000000..82ea9a3e03 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -0,0 +1,40 @@ + +package com.github.mikephil.charting.renderer; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.utils.Transformer; + +/** + * Renderer for the HorizontalBarChart. + * + * @author Philipp Jahoda + */ +public class HorizontalBarChartRenderer extends BarChartRenderer { + + public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(chart, animator, viewPortHandler); + } + + @Override + protected void prepareBar(float x, float y, float barspace, Transformer trans) { + + float spaceHalf = barspace / 2f; + + float top = x - 0.5f + spaceHalf; + float bottom = x + 0.5f - spaceHalf; + float left = y >= 0 ? y : 0; + float right = y <= 0 ? y : 0; + + mBarRect.set(left, top, right, bottom); + + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + + // if a shadow is drawn, prepare it too + if (mChart.isDrawBarShadowEnabled()) { + mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, + mViewPortHandler.contentBottom()); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index e8f66d8fa9..ca4947a43e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -96,7 +96,7 @@ public void computeAxis(float yMin, float yMax) { * * @return */ - private void computeAxisValues(float min, float max) { + protected void computeAxisValues(float min, float max) { float yMin = min; float yMax = max; @@ -240,10 +240,10 @@ protected void drawAxisLine(Canvas c) { /** * draws the y-labels on the specified x-position * - * @param xPos + * @param fixedPosition * @param positions */ - private void drawYLabels(Canvas c, float xPos, float[] positions, float yOffset) { + protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { // draw for (int i = 0; i < mYAxis.mEntryCount; i++) { @@ -253,7 +253,7 @@ private void drawYLabels(Canvas c, float xPos, float[] positions, float yOffset) if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) return; - c.drawText(text, xPos, positions[i * 2 + 1] + yOffset, mAxisPaint); + c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisPaint); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java new file mode 100644 index 0000000000..78ab1a52ab --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -0,0 +1,149 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint.Align; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YLabelPosition; +import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; + +public class YAxisRendererHorizontalBarChart extends YAxisRenderer { + + public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yAxis, + Transformer trans) { + super(viewPortHandler, yAxis, trans); + } + + /** + * Computes the axis values. + * + * @param yMin - the minimum y-value in the data object for this axis + * @param yMax - the maximum y-value in the data object for this axis + */ + public void computeAxis(float yMin, float yMax) { + + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentHeight() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + mViewPortHandler.contentTop()); + + if (!mYAxis.isInverted()) { + yMin = (float) p1.x; + yMax = (float) p2.x; + } else { + + if (!mYAxis.isStartAtZeroEnabled()) + yMin = (float) Math.min(p1.x, p2.x); + else + yMin = 0; + yMax = (float) Math.max(p1.x, p2.x); + } + } + + computeAxisValues(yMin, yMax); + } + + /** + * draws the y-axis labels to the screen + */ + @Override + public void renderAxis(Canvas c) { + + if (!mYAxis.isEnabled()) + return; + + float[] positions = new float[mYAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + // only fill y values, x values are not needed since the y-labels + // are + // static on the x-axis + positions[i] = mYAxis.mEntries[i / 2]; + } + + mTrans.pointValuesToPixel(positions); + + mAxisPaint.setTypeface(mYAxis.getTypeface()); + mAxisPaint.setTextSize(mYAxis.getTextSize()); + mAxisPaint.setColor(mYAxis.getTextColor()); + mAxisPaint.setTextAlign(Align.CENTER); + + float yoffset = Utils.calcTextHeight(mAxisPaint, "A") * 1.3f; + + AxisDependency dependency = mYAxis.getAxisDependency(); + YLabelPosition labelPosition = mYAxis.getLabelPosition(); + + float yPos = 0f; + + if (dependency == AxisDependency.LEFT) { + + if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + yoffset = Utils.convertDpToPixel(3f); + yPos = mViewPortHandler.contentTop() - yoffset; + } else { + yPos = mViewPortHandler.contentTop() + yoffset; + } + + } else { + + if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + yPos = mViewPortHandler.contentBottom() + yoffset; + } else { + yoffset = Utils.convertDpToPixel(4f); + yPos = mViewPortHandler.contentBottom() - yoffset; + } + } + + drawYLabels(c, yPos, positions, yoffset); + + drawAxisLine(c); + } + + @Override + protected void drawAxisLine(Canvas c) { + + if (!mYAxis.isDrawAxisLineEnabled()) + return; + + mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); + + if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mAxisLinePaint); + } else { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } + } + + /** + * draws the y-labels on the specified x-position + * + * @param fixedPosition + * @param positions + */ + @Override + protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { + + for (int i = 0; i < mYAxis.mEntryCount; i++) { + + String text = mYAxis.getFormattedLabel(i); + + if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) + return; + + c.drawText(text, positions[i * 2 ] + offset, fixedPosition, mAxisPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java deleted file mode 100644 index 8fbd76e635..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/utils/HorizontalBarChartTransformer.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.github.mikephil.charting.utils; - -import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.renderer.ViewPortHandler; - -public class HorizontalBarChartTransformer extends Transformer { - - public HorizontalBarChartTransformer(ViewPortHandler viewPortHandler) { - super(viewPortHandler); - // TODO Auto-generated constructor stub - } - - /** - * Prepares the matrix that transforms values to pixels. - * - * @param chart - */ -// @Override -// public void prepareMatrixValuePx(ChartInterface chart) { -// float scaleX = (chart.getWidth() - chart.getOffsetRight() - chart.getOffsetLeft()) / chart.getDeltaY(); -// float scaleY = (chart.getHeight() - chart.getOffsetTop() - chart.getOffsetBottom()) / chart.getDeltaX(); -// -// // setup all matrices -// mMatrixValueToPx.reset(); -// mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); -// mMatrixValueToPx.postScale(scaleX, -scaleY); -// mMatrixValueToPx.postRotate(90, chart.getHeight() / 2, chart.getWidth() / 2); -// } - -// /** -// * Transforms an arraylist of Entry into a float array containing the x and -// * y values transformed with all matrices for the BARCHART. -// * -// * @param entries -// * @param dataSet the dataset index -// * @return -// */ -// public float[] generateTransformedValuesBarChart(ArrayList entries, -// int dataSet, BarData bd, float phaseY) { -// -// float[] valuePoints = new float[entries.size() * 2]; -// -// int setCount = bd.getDataSetCount(); -// float space = bd.getGroupSpace(); -// -// for (int j = 0; j < valuePoints.length; j += 2) { -// -// int index = j/2; -// Entry e = entries.get(index); -// -// //TODO: Need to find a better value than 1, should be dependant on yMax, I think -// float x = e.getVal() + 1; -// // calculate the y-position, depending on datasetcount -// float y = e.getXIndex() + (index * (setCount - 1)) + dataSet + 0.5f + space * index -// + space / 2f; -// -// valuePoints[j] = x; -// valuePoints[j + 1] = y; -// } -// -// pointValuesToPixel(valuePoints); -// -// return valuePoints; -// } - -} From ccfbf3da4a4b3b02021db290f3e6cd852245c5a7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 11:10:57 +0100 Subject: [PATCH 0099/1390] Worked on horizontal barchart. --- .../HorizontalBarChartActivity.java | 3 +- .../charting/charts/HorizontalBarChart.java | 24 +++- .../renderer/HorizontalBarChartRenderer.java | 2 +- .../charting/renderer/XAxisRenderer.java | 6 +- .../renderer/XAxisRendererBarChart.java | 8 +- .../XAxisRendererHorizontalBarChart.java | 122 ++++++++++++++++++ .../mikephil/charting/utils/Transformer.java | 19 +++ 7 files changed, 171 insertions(+), 13 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index b5069e56cf..338eaba4c1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -81,7 +81,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); xl.setTypeface(tf); - xl.setEnabled(false); +// xl.setEnabled(false); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); @@ -94,6 +94,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setValueTypeface(tf); setData(12, 50); + mChart.animateY(2500); // setting data mSeekBarY.setProgress(50); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 2591e33b7b..52a43dfdac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -2,10 +2,12 @@ package com.github.mikephil.charting.charts; import android.content.Context; +import android.graphics.Matrix; import android.util.AttributeSet; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; +import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; /** @@ -41,14 +43,28 @@ protected void init() { mLeftAxisTransformer); mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, mRightAxisTransformer); + mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, + mLeftAxisTransformer, this); } @Override protected void prepareValuePxMatrix() { - mRightAxisTransformer.prepareMatrixValuePx(mXChartMin, mAxisRight.mAxisRange, mDeltaX, - mAxisRight.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mXChartMin, mAxisLeft.mAxisRange, mDeltaX, - mAxisLeft.mAxisMinimum); + mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, + mDeltaX, + mXChartMin); + mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, + mDeltaX, + mXChartMin); + } + + @Override + protected void calcModulus() { + float[] values = new float[9]; + mViewPortHandler.getMatrixTouch().getValues(values); + + mXAxis.mAxisLabelModulus = (int) Math + .ceil((mData.getXValCount() * mXAxis.mLabelHeight) + / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); } private class XLabelsAsYLabels extends YAxis diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 82ea9a3e03..4d2a9f9200 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -29,7 +29,7 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { mBarRect.set(left, top, right, bottom); - trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + trans.rectValueToPixelHorizontal(mBarRect, mAnimator.getPhaseY()); // if a shadow is drawn, prepare it too if (mChart.isDrawBarShadowEnabled()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 315eea0c1b..ec4c6091cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -108,9 +108,9 @@ protected void drawAxisLine(Canvas c) { /** * draws the x-labels on the specified y-position * - * @param yPos + * @param pos */ - protected void drawLabels(Canvas c, float yPos) { + protected void drawLabels(Canvas c, float pos) { // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { @@ -150,7 +150,7 @@ protected void drawLabels(Canvas c, float yPos) { } c.drawText(label, position[0], - yPos, + pos, mAxisPaint); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index fe3c2cef8a..f09edb0d06 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -11,7 +11,7 @@ public class XAxisRendererBarChart extends XAxisRenderer { - private BarChart mChart; + protected BarChart mChart; public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, BarChart chart) { @@ -23,10 +23,10 @@ public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Trans /** * draws the x-labels on the specified y-position * - * @param yPos + * @param pos */ @Override - protected void drawLabels(Canvas c, float yPos) { + protected void drawLabels(Canvas c, float pos) { // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { @@ -70,7 +70,7 @@ protected void drawLabels(Canvas c, float yPos) { } c.drawText(label, position[0], - yPos, + pos, mAxisPaint); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java new file mode 100644 index 0000000000..ca5b680623 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -0,0 +1,122 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint.Align; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; + +public class XAxisRendererHorizontalBarChart extends XAxisRendererBarChart { + + public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, + Transformer trans, BarChart chart) { + super(viewPortHandler, xAxis, trans, chart); + } + + @Override + public void renderAxis(Canvas c) { + + if (!mXAxis.isEnabled()) + return; + + float xoffset = Utils.convertDpToPixel(4f); + + mAxisPaint.setTypeface(mXAxis.getTypeface()); + mAxisPaint.setTextSize(mXAxis.getTextSize()); + mAxisPaint.setColor(mXAxis.getTextColor()); + + if (mXAxis.getPosition() == XAxisPosition.TOP) { + + mAxisPaint.setTextAlign(Align.LEFT); + drawLabels(c, mViewPortHandler.contentRight() + xoffset); + + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + + mAxisPaint.setTextAlign(Align.RIGHT); + drawLabels(c, mViewPortHandler.contentLeft() - xoffset); + + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { + + mAxisPaint.setTextAlign(Align.LEFT); + drawLabels(c, mViewPortHandler.contentLeft() + xoffset); + + } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { + + mAxisPaint.setTextAlign(Align.RIGHT); + drawLabels(c, mViewPortHandler.contentRight() - xoffset); + + } else { // BOTH SIDED + + drawLabels(c, mViewPortHandler.contentLeft()); + drawLabels(c, mViewPortHandler.contentRight()); + } + + drawAxisLine(c); + } + + /** + * draws the x-labels on the specified y-position + * + * @param pos + */ + @Override + protected void drawLabels(Canvas c, float pos) { + + // pre allocate to save performance (dont allocate in loop) + float[] position = new float[] { + 0f, 0f + }; + + BarData bd = mChart.getData(); + int step = bd.getDataSetCount(); + + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + + position[1] = i * step + i * bd.getGroupSpace() + + bd.getGroupSpace() / 2f; + + mTrans.pointValuesToPixel(position); + + if (mViewPortHandler.isInBoundsY(position[1])) { + + String label = mXAxis.getValues().get(i); + c.drawText(label, pos, position[1] + mXAxis.mLabelHeight / 2f, + mAxisPaint); + } + } + } + + @Override + public void renderGridLines(Canvas c) { + + if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) + return; + + float[] position = new float[] { + 0f, 0f + }; + + BarData bd = mChart.getData(); + // take into consideration that multiple DataSets increase mDeltaX + int step = bd.getDataSetCount(); + + for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + + position[1] = i * step + i * bd.getGroupSpace() - 0.5f; + + mTrans.pointValuesToPixel(position); + + if (mViewPortHandler.isInBoundsY(position[1])) { + + c.drawLine(mViewPortHandler.contentLeft(), position[1], + mViewPortHandler.contentRight(), position[1], mGridPaint); + } + } + } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 9eed1c420c..9e66e5afb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -277,6 +277,25 @@ public void rectValueToPixel(RectF r, float phaseY) { mViewPortHandler.getMatrixTouch().mapRect(r); mMatrixOffset.mapRect(r); } + + /** + * Transform a rectangle with all matrices with potential animation phases. + * + * @param r + * @param phaseY + */ + public void rectValueToPixelHorizontal(RectF r, float phaseY) { + + // multiply the height of the rect with the phase + if (r.left > 0) + r.left *= phaseY; + else + r.right *= phaseY; + + mMatrixValueToPx.mapRect(r); + mViewPortHandler.getMatrixTouch().mapRect(r); + mMatrixOffset.mapRect(r); + } /** * transforms multiple rects with all matrices From 74040310d1e1c6d9f0ea8d539a901afb9025e15d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 12:27:20 +0100 Subject: [PATCH 0100/1390] Improved Horizontal-BarChart, now x- and y-axis working. TODO: offset-calculation. --- .../HorizontalBarChartActivity.java | 4 ++ .../charting/charts/HorizontalBarChart.java | 49 ------------------ .../mikephil/charting/components/YAxis.java | 8 +-- .../XAxisRendererHorizontalBarChart.java | 25 +++++++++ .../charting/renderer/YAxisRenderer.java | 8 +-- .../YAxisRendererHorizontalBarChart.java | 51 ++++++++++++++----- 6 files changed, 75 insertions(+), 70 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 338eaba4c1..1c189aff45 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -81,15 +81,19 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); xl.setTypeface(tf); + xl.setDrawAxisLine(true); + xl.setDrawGridLines(true); // xl.setEnabled(false); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setDrawAxisLine(true); + yl.setDrawGridLines(true); YAxis yr = mChart.getAxisRight(); yr.setTypeface(tf); yr.setDrawAxisLine(true); + yr.setDrawGridLines(true); mChart.setValueTypeface(tf); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 52a43dfdac..d8f6b3456e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -5,7 +5,6 @@ import android.graphics.Matrix; import android.util.AttributeSet; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; @@ -66,52 +65,4 @@ protected void calcModulus() { .ceil((mData.getXValCount() * mXAxis.mLabelHeight) / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); } - - private class XLabelsAsYLabels extends YAxis - { - public XLabelsAsYLabels(AxisDependency position) { - super(position); - // TODO Auto-generated constructor stub - } - - /** - * Returns the longest formatted label (in terms of characters) the - * y-labels contain. - * - * @return - */ - @Override - public String getLongestLabel() - { - String longest = ""; - - for (int i = 0; i < mData.getXValCount(); i++) - { - String text = mData.getXVals().get(i); - - if (longest.length() < text.length()) - longest = text; - } - - return longest; - } - - /** - * Returns the formatted y-label at the specified index. This will - * either use the auto-formatter or the custom formatter (if one is - * set). - * - * @param index - * @return - */ - @Override - public String getFormattedLabel(int index) - { - super.getFormattedLabel(index); - if (index < 0) - return ""; - - return mData.getXVals().get(index); - } - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 09dbbb97b3..6a8a2e6f73 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -74,10 +74,10 @@ public class YAxis extends AxisBase { public float mAxisRange = 0f; /** the position of the y-labels relative to the chart */ - private YLabelPosition mPosition = YLabelPosition.OUTSIDE_CHART; + private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; /** enum for the position of the y-labels relative to the chart */ - public enum YLabelPosition { + public enum YAxisLabelPosition { OUTSIDE_CHART, INSIDE_CHART } @@ -100,7 +100,7 @@ public AxisDependency getAxisDependency() { /** * returns the position of the y-labels */ - public YLabelPosition getLabelPosition() { + public YAxisLabelPosition getLabelPosition() { return mPosition; } @@ -109,7 +109,7 @@ public YLabelPosition getLabelPosition() { * * @param pos */ - public void setPosition(YLabelPosition pos) { + public void setPosition(YAxisLabelPosition pos) { mPosition = pos; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index ca5b680623..636e3f358b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -119,4 +119,29 @@ public void renderGridLines(Canvas c) { } } + @Override + protected void drawAxisLine(Canvas c) { + + if (!mXAxis.isDrawAxisLineEnabled()) + return; + + mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mXAxis.getAxisLineWidth()); + + if (mXAxis.getPosition() == XAxisPosition.TOP + || mXAxis.getPosition() == XAxisPosition.TOP_INSIDE + || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + c.drawLine(mViewPortHandler.contentRight(), + mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } + + if (mXAxis.getPosition() == XAxisPosition.BOTTOM + || mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE + || mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + c.drawLine(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index ca4947a43e..555f8ae08c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YLabelPosition; +import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -187,13 +187,13 @@ public void renderAxis(Canvas c) { float yoffset = Utils.calcTextHeight(mAxisPaint, "A") / 2.5f; AxisDependency dependency = mYAxis.getAxisDependency(); - YLabelPosition labelPosition = mYAxis.getLabelPosition(); + YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); float xPos = 0f; if (dependency == AxisDependency.LEFT) { - if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { mAxisPaint.setTextAlign(Align.RIGHT); xPos = mViewPortHandler.offsetLeft() - xoffset; } else { @@ -203,7 +203,7 @@ public void renderAxis(Canvas c) { } else { - if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { mAxisPaint.setTextAlign(Align.LEFT); xPos = mViewPortHandler.contentRight() + xoffset; } else { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 78ab1a52ab..36cf3fbe58 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YLabelPosition; +import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -50,7 +50,7 @@ public void computeAxis(float yMin, float yMax) { computeAxisValues(yMin, yMax); } - + /** * draws the y-axis labels to the screen */ @@ -79,26 +79,28 @@ public void renderAxis(Canvas c) { float yoffset = Utils.calcTextHeight(mAxisPaint, "A") * 1.3f; AxisDependency dependency = mYAxis.getAxisDependency(); - YLabelPosition labelPosition = mYAxis.getLabelPosition(); + YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); float yPos = 0f; if (dependency == AxisDependency.LEFT) { - - if (labelPosition == YLabelPosition.OUTSIDE_CHART) { + + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { yoffset = Utils.convertDpToPixel(3f); - yPos = mViewPortHandler.contentTop() - yoffset; + yPos = mViewPortHandler.contentTop(); } else { - yPos = mViewPortHandler.contentTop() + yoffset; + yoffset = yoffset * -1f; + yPos = mViewPortHandler.contentTop(); } } else { - if (labelPosition == YLabelPosition.OUTSIDE_CHART) { - yPos = mViewPortHandler.contentBottom() + yoffset; + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { + yoffset = yoffset * -1f; + yPos = mViewPortHandler.contentBottom(); } else { yoffset = Utils.convertDpToPixel(4f); - yPos = mViewPortHandler.contentBottom() - yoffset; + yPos = mViewPortHandler.contentBottom(); } } @@ -106,7 +108,7 @@ public void renderAxis(Canvas c) { drawAxisLine(c); } - + @Override protected void drawAxisLine(Canvas c) { @@ -126,7 +128,7 @@ protected void drawAxisLine(Canvas c) { mViewPortHandler.contentBottom(), mAxisLinePaint); } } - + /** * draws the y-labels on the specified x-position * @@ -143,7 +145,30 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) return; - c.drawText(text, positions[i * 2 ] + offset, fixedPosition, mAxisPaint); + c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisPaint); + } + } + + @Override + public void renderGridLines(Canvas c) { + + if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) + return; + + // pre alloc + float[] position = new float[2]; + + mGridPaint.setColor(mYAxis.getGridColor()); + + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { + + position[0] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); + + c.drawLine(position[0], mViewPortHandler.contentTop(), position[0], + mViewPortHandler.contentBottom(), + mGridPaint); } } } From 61799c09329b4bc4f2ff85b285c7d8d7aa725d40 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 15:11:51 +0100 Subject: [PATCH 0101/1390] Code cleanup. --- .../LineChartActivityColored.java | 1 - .../mikephil/charting/charts/BarChart.java | 81 ------- .../charting/charts/BarLineChartBase.java | 199 +----------------- .../mikephil/charting/charts/Chart.java | 52 ----- .../charting/charts/HorizontalBarChart.java | 11 +- .../mikephil/charting/charts/LineChart.java | 25 --- .../mikephil/charting/charts/RadarChart.java | 32 +-- .../renderer/HorizontalBarChartRenderer.java | 5 +- 8 files changed, 23 insertions(+), 383 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 214e26857a..b143c23451 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -62,7 +62,6 @@ private void setupChart(LineChart chart, LineData data, int color) { // enable / disable grid background chart.setDrawGridBackground(false); // chart.getRenderer().getGridPaint().setGridColor(Color.WHITE & 0x70FFFFFF); - chart.setGridWidth(1.25f); // enable touch gestures chart.setTouchEnabled(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 1f98b6b9c2..a91a58b9a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -23,15 +23,6 @@ */ public class BarChart extends BarLineChartBase implements BarDataProvider { - // /** indicates the angle of the 3d effect */ - // private float mSkew = 0.3f; - // - // /** indicates how much the 3d effect goes back */ - // private float mDepth = 0.3f; - // - // /** flag the enables or disables 3d bars */ - // private boolean m3DEnabled = false; - /** flag that enables or disables the highlighting arrow */ private boolean mDrawHighlightArrow = false; @@ -101,20 +92,6 @@ protected void calcMinMax() { mXChartMax = mDeltaX - mXChartMin; } - // protected float getPositiveYOffset(boolean drawAboveValueBar) - // { - // return (mDrawValueAboveBar ? -Utils.convertDpToPixel(5) : - // Utils.calcTextHeight(mValuePaint, - // "8") * 1.5f); - // } - // - // protected float getNegativeYOffset(boolean drawAboveValueBar) - // { - // return (mDrawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * - // 1.5f : -Utils - // .convertDpToPixel(5)); - // } - /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the BarChart. @@ -219,64 +196,6 @@ public RectF getBarBounds(BarEntry e) { return bounds; } - // /** - // * sets the skew (default 0.3f), the skew indicates how much the 3D effect - // * of the chart is turned to the right - // * - // * @param skew - // */ - // public void setSkew(float skew) { - // this.mSkew = skew; - // } - // - // /** - // * returns the skew value that indicates how much the 3D effect is turned - // to - // * the right - // * - // * @return - // */ - // public float getSkew() { - // return mSkew; - // } - // - // /** - // * set the depth of the chart (default 0.3f), the depth indicates how much - // * the 3D effect of the chart goes back - // * - // * @param depth - // */ - // public void setDepth(float depth) { - // this.mDepth = depth; - // } - // - // /** - // * returhs the depth, which indicates how much the 3D effect goes back - // * - // * @return - // */ - // public float getDepth() { - // return mDepth; - // } - // - // /** - // * if enabled, chart will be drawn in 3d - // * - // * @param enabled - // */ - // public void set3DEnabled(boolean enabled) { - // this.m3DEnabled = enabled; - // } - // - // /** - // * returns true if 3d bars is enabled, false if not - // * - // * @return - // */ - // public boolean is3DEnabled() { - // return m3DEnabled; - // } - /** * set this to true to draw the highlightning arrow * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index dbf6e68653..7c16eced81 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -53,9 +53,6 @@ public abstract class BarLineChartBase 3.0f) - width = 3.0f; - mGridWidth = width; + public void setGridBackgroundColor(int color) { + mGridBackgroundPaint.setColor(color); } /** @@ -1368,14 +1198,9 @@ public void setPaint(Paint p, int which) { super.setPaint(p, which); switch (which) { - case PAINT_GRID: - break; case PAINT_GRID_BACKGROUND: mGridBackgroundPaint = p; break; - case PAINT_BORDER: -// mBorderPaint = p; - break; } } @@ -1386,12 +1211,8 @@ public Paint getPaint(int which) { return p; switch (which) { - case PAINT_GRID: - return null; case PAINT_GRID_BACKGROUND: return mGridBackgroundPaint; -// case PAINT_BORDER: -// return mBorderPaint; } return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 084c406b5b..0f57362c68 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1405,57 +1405,30 @@ public void enableScroll() { parent.requestDisallowInterceptTouchEvent(false); } - /** paint for the grid lines (only line and barchart) */ - public static final int PAINT_GRID = 3; - /** paint for the grid background (only line and barchart) */ public static final int PAINT_GRID_BACKGROUND = 4; - /** paint for the y-legend values (only line and barchart) */ - public static final int PAINT_YLABEL = 5; - - /** paint for the x-legend values (only line and barchart) */ - public static final int PAINT_XLABEL = 6; - /** * paint for the info text that is displayed when there are no values in the * chart */ public static final int PAINT_INFO = 7; - /** paint for the value text */ - public static final int PAINT_VALUES = 8; - - /** paint for the inner circle (linechart) */ - public static final int PAINT_CIRCLES_INNER = 10; - /** paint for the description text in the bottom right corner */ public static final int PAINT_DESCRIPTION = 11; - /** paint for the line surrounding the chart (only line and barchart) */ - public static final int PAINT_BORDER = 12; - /** paint for the hole in the middle of the pie chart */ public static final int PAINT_HOLE = 13; /** paint for the text in the middle of the pie chart */ public static final int PAINT_CENTER_TEXT = 14; - /** paint for highlightning the values of a linechart */ - public static final int PAINT_HIGHLIGHT = 15; - - /** paint object used for the limit lines */ - public static final int PAINT_RADAR_WEB = 16; - /** paint used for all rendering processes */ public static final int PAINT_RENDER = 17; /** paint used for the legend */ public static final int PAINT_LEGEND_LABEL = 18; - /** paint object used for the limit lines */ - public static final int PAINT_LIMIT_LINE = 19; - /** * set a new paint object for the specified parameter in the chart e.g. * Chart.PAINT_VALUES @@ -1473,27 +1446,12 @@ public void setPaint(Paint p, int which) { case PAINT_DESCRIPTION: mDescPaint = p; break; - case PAINT_VALUES: - // mValuePaint = p; - break; case PAINT_RENDER: mRenderPaint = p; break; case PAINT_LEGEND_LABEL: mLegendLabelPaint = p; break; - case PAINT_XLABEL: - // mXLabelPaint = p; - break; - case PAINT_YLABEL: - // mYLabelPaint = p; - break; - case PAINT_HIGHLIGHT: - // mHighlightPaint = p; - break; - case PAINT_LIMIT_LINE: - // mLimitLinePaint = p; - break; } } @@ -1509,20 +1467,10 @@ public Paint getPaint(int which) { return mInfoPaint; case PAINT_DESCRIPTION: return mDescPaint; - case PAINT_VALUES: - // return mValuePaint; case PAINT_RENDER: return mRenderPaint; case PAINT_LEGEND_LABEL: return mLegendLabelPaint; - case PAINT_XLABEL: - // return mXLabelPaint; - case PAINT_YLABEL: - // return mYLabelPaint; - case PAINT_HIGHLIGHT: - // return mHighlightPaint; - case PAINT_LIMIT_LINE: - // return mLimitLinePaint; } return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index d8f6b3456e..e7c7c53b99 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -17,19 +17,16 @@ */ public class HorizontalBarChart extends BarChart { - public HorizontalBarChart(Context context) - { + public HorizontalBarChart(Context context) { super(context); } - public HorizontalBarChart(Context context, AttributeSet attrs) - { + public HorizontalBarChart(Context context, AttributeSet attrs) { super(context, attrs); } public HorizontalBarChart(Context context, AttributeSet attrs, - int defStyle) - { + int defStyle) { super(context, attrs, defStyle); } @@ -55,7 +52,7 @@ protected void prepareValuePxMatrix() { mDeltaX, mXChartMin); } - + @Override protected void calcModulus() { float[] values = new float[9]; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 6cd464595c..a2532a71f5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -76,31 +76,6 @@ public float getHighlightLineWidth() { return mHighlightWidth; } - @Override - public void setPaint(Paint p, int which) { - super.setPaint(p, which); - - switch (which) { - case PAINT_CIRCLES_INNER: -// mCirclePaintInner = p; - break; - } - } - - @Override - public Paint getPaint(int which) { - Paint p = super.getPaint(which); - if (p != null) - return p; - - switch (which) { - case PAINT_CIRCLES_INNER: - return null; - } - - return null; - } - @Override public void setFillFormatter(FillFormatter formatter) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index f49ebd76d9..d69e53f369 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -4,7 +4,6 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; @@ -308,36 +307,17 @@ public float getRadius() { return Math.min(content.width() / 2f, content.height() / 2f); } + /** + * Returns the maximum value this chart can display on it's y-axis. + */ public float getYChartMax() { return mYAxis.mAxisMaximum; } + /** + * Returns the minimum value this chart can display on it's y-axis. + */ public float getYChartMin() { return mYAxis.mAxisMinimum; } - - @Override - public void setPaint(Paint p, int which) { - super.setPaint(p, which); - - switch (which) { - case PAINT_RADAR_WEB: - // mWebPaint = p; - break; - } - } - - @Override - public Paint getPaint(int which) { - Paint p = super.getPaint(which); - if (p != null) - return p; - - switch (which) { - case PAINT_RADAR_WEB: - // return mWebPaint; - } - - return null; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 4d2a9f9200..27839a8075 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -33,8 +33,9 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { // if a shadow is drawn, prepare it too if (mChart.isDrawBarShadowEnabled()) { - mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, - mViewPortHandler.contentBottom()); + mBarShadow.set(mViewPortHandler.contentLeft(), mBarRect.top, + mViewPortHandler.contentRight(), + mBarRect.bottom); } } } From 3fdc4517587190fe199ad9a835358cc2537ec192 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 15:19:44 +0100 Subject: [PATCH 0102/1390] Fixed bug concerning x-label centering in BarChart. --- .../mpchartexample/AnotherBarActivity.java | 1 - .../BarChartActivityMultiDataset.java | 1 - .../ListViewBarChartActivity.java | 1 - .../mpchartexample/StackedBarActivity.java | 1 - .../listviewitems/BarChartItem.java | 1 - .../mikephil/charting/components/XAxis.java | 23 ------------------- .../charting/renderer/XAxisRenderer.java | 4 ---- .../renderer/XAxisRendererBarChart.java | 9 ++++---- 8 files changed, 5 insertions(+), 36 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index f45d0417ce..f9b7d4deec 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -62,7 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setCenterXLabelText(true); xAxis.setSpaceBetweenLabels(0); xAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 21b17ac4c8..67db0880f5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -85,7 +85,6 @@ protected void onCreate(Bundle savedInstanceState) { l.setTypeface(tf); XAxis xl = mChart.getXAxis(); - xl.setCenterXLabelText(true); xl.setTypeface(tf); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 3dd51f1b18..3b627a0d70 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -91,7 +91,6 @@ public View getView(int position, View convertView, ViewGroup parent) { holder.chart.setValueTextColor(Color.WHITE); XAxis xAxis = holder.chart.getXAxis(); - xAxis.setCenterXLabelText(true); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 846d1e47ef..039e94a944 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -82,7 +82,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XAxisPosition.TOP); - xLabels.setCenterXLabelText(true); // mChart.setDrawXLabels(false); // mChart.setDrawYLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index 17880d7aa6..f7e55255ce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -54,7 +54,6 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDrawBarShadow(false); XAxis xAxis = holder.chart.getXAxis(); - xAxis.setCenterXLabelText(true); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 950a85b03f..ed898f09c9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -47,9 +47,6 @@ public class XAxis extends AxisBase { */ public int mYAxisLabelModulus = 1; - /** if true, x-axis label text is centered when using barcharts */ - private boolean mCenterXAxisLabels = false; - /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart @@ -70,26 +67,6 @@ public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } - /** - * returns true if centering x-axis labels when using barcharts is enabled, - * false if not - * - * @return - */ - public boolean isCenterXLabelsEnabled() { - return mCenterXAxisLabels; - } - - /** - * set this to true to center the x-label text when using barcharts , - * default: false - * - * @param enabled - */ - public void setCenterXLabelText(boolean enabled) { - mCenterXAxisLabels = enabled; - } - /** * if set to true, the x-label entries will adjust themselves when scaling * the graph default: true diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index ec4c6091cb..60eb0c6df3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -121,10 +121,6 @@ protected void drawLabels(Canvas c, float pos) { position[0] = i; - // center the text - if (mXAxis.isCenterXLabelsEnabled()) - position[0] += 0.5f; - mTrans.pointValuesToPixel(position); if (mViewPortHandler.isInBoundsX(position[0])) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index f09edb0d06..990d42d4ce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -39,11 +39,12 @@ protected void drawLabels(Canvas c, float pos) { for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() - + bd.getGroupSpace() / 2f - 0.5f; + + bd.getGroupSpace() / 2f; - // center the text - if (mXAxis.isCenterXLabelsEnabled()) - position[0] += (step / 2f); + // consider groups (center label for each group) + if (step > 1) { + position[0] += ((float) step - 1f) / 2f; + } mTrans.pointValuesToPixel(position); From 5696d6d562164579c29705339220c7d9dbd579e4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 17:51:15 +0100 Subject: [PATCH 0103/1390] Introducing LegendRenderer class. --- MPChartExample/res/menu/main.xml | 23 +- .../mpchartexample/AnotherBarActivity.java | 4 +- .../CandleStickChartActivity.java | 3 +- .../CubicLineChartActivity.java | 4 +- .../mpchartexample/DrawChartActivity.java | 25 +- .../notimportant/MainActivity.java | 7 +- .../charting/charts/BarLineChartBase.java | 24 +- .../mikephil/charting/charts/Chart.java | 426 +---------------- .../mikephil/charting/charts/PieChart.java | 4 +- .../charting/charts/PieRadarChartBase.java | 15 +- .../mikephil/charting/charts/RadarChart.java | 4 +- .../mikephil/charting/components/Legend.java | 89 ++-- .../charting/renderer/LegendRenderer.java | 450 ++++++++++++++++++ 13 files changed, 578 insertions(+), 500 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java diff --git a/MPChartExample/res/menu/main.xml b/MPChartExample/res/menu/main.xml index ff337220a6..b45d3bbb9f 100644 --- a/MPChartExample/res/menu/main.xml +++ b/MPChartExample/res/menu/main.xml @@ -1,6 +1,21 @@ - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index f9b7d4deec..e15f57b7e2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -67,14 +67,14 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisLeft().setDrawGridLines(false); - mChart.setDrawLegend(false); - // setting data mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); // add a nice and smooth animation mChart.animateY(2500); + + mChart.getLegend().setEnabled(false); // Legend l = mChart.getLegend(); // l.setPosition(LegendPosition.BELOW_CHART_CENTER); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index a9d4cb8e05..25655fe0e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -68,11 +68,12 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisRight().setEnabled(false); - mChart.setDrawLegend(false); // setting data mSeekBarX.setProgress(15); mSeekBarY.setProgress(100); + + mChart.getLegend().setEnabled(false); // Legend l = mChart.getLegend(); // l.setPosition(LegendPosition.BELOW_CHART_CENTER); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 8422acf956..6b7f9da59c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -52,8 +52,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); // if enabled, the chart will always start at zero on the y-axis - - mChart.setDrawLegend(false); // no description text mChart.setDescription(""); @@ -87,6 +85,8 @@ protected void onCreate(Bundle savedInstanceState) { // add data setData(45, 100); + mChart.getLegend().setEnabled(false); + mChart.animateXY(2000, 2000); // dont forget to refresh the drawing diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 74e976e54a..1d8ae7c5f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.graphics.Typeface; @@ -46,37 +47,37 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnDrawListener(this); // enable drawing with the finger -// mChart.setDrawingEnabled(true); + // mChart.setDrawingEnabled(true); -// mChart.setLineWidth(5f); -// mChart.setCircleSize(5f); + // mChart.setLineWidth(5f); + // mChart.setCircleSize(5f); mChart.setHighlightEnabled(true); // if disabled, drawn datasets with the finger will not be automatically // finished -// mChart.setAutoFinish(true); + // mChart.setAutoFinish(true); mChart.setDrawGridBackground(false); - - mChart.setDrawLegend(false); // add dummy-data to the chart initWithDummyData(); - + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setAvoidFirstLastClipping(true); - + YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); + mChart.getLegend().setEnabled(false); + mChart.setValueTypeface(tf); -// mChart.setYRange(-40f, 40f, true); + // mChart.setYRange(-40f, 40f, true); // call this to reset the changed y-range - // mChart.resetYRange(true); + // mChart.resetYRange(true); } private void initWithDummyData() { @@ -184,8 +185,8 @@ public void onDrawFinished(DataSet dataSet) { Log.i(Chart.LOG_TAG, "DataSet drawn. " + dataSet.toSimpleString()); // prepare the legend again - mChart.prepareLegend(); - + mChart.getLegendRenderer().computeLegend(mChart.getData(), mChart.getLegend()); + mChart.calculateLegendOffsets(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 0a64fefa3a..99c23cc462 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -245,11 +245,16 @@ public boolean onOptionsItemSelected(MenuItem item) { i.putExtra(Intent.EXTRA_TEXT, "Your error report here..."); startActivity(Intent.createChooser(i, "Report Problem")); break; - case R.id.website: + case R.id.blog: i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse("http://www.xxmassdeveloper.com")); startActivity(i); break; + case R.id.website: + i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("http://at.linkedin.com/in/philippjahoda")); + startActivity(i); + break; } return true; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 7c16eced81..ab6d736747 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -207,7 +207,8 @@ protected void onDraw(Canvas canvas) { mRenderer.drawValues(mDrawCanvas); - drawLegend(); + mLegendRenderer.renderLegend(mDrawCanvas, mLegend); +// drawLegend(); drawMarkers(); @@ -256,7 +257,8 @@ public void notifyDataSetChanged() { mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); - prepareLegend(); + mLegend = mLegendRenderer.computeLegend(mData, mLegend); +// prepareLegend(); calculateOffsets(); } @@ -307,7 +309,7 @@ protected void calculateOffsets() { float legendRight = 0f, legendBottom = 0f; // setup offsets for legend - if (mDrawLegend && mLegend != null && mLegend.getPosition() != LegendPosition.NONE) { + if (mLegend != null && mLegend.isEnabled()) { if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { @@ -315,19 +317,19 @@ protected void calculateOffsets() { // this is the space between the legend and the chart float spacing = Utils.convertDpToPixel(12f); - legendRight = mLegend.getMaximumEntryLength(mLegendLabelPaint) + legendRight = mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint()) + mLegend.getFormSize() + mLegend.getFormToTextSpace() + spacing; - mLegendLabelPaint.setTextAlign(Align.LEFT); + mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { if (mXAxis.getPosition() == XAxisPosition.TOP) - legendBottom = mLegendLabelPaint.getTextSize() * 3.5f; + legendBottom = mLegendRenderer.getLabelPaint().getTextSize() * 3.5f; else { - legendBottom = mLegendLabelPaint.getTextSize() * 2.5f; + legendBottom = mLegendRenderer.getLabelPaint().getTextSize() * 2.5f; } } @@ -418,16 +420,16 @@ public void calculateLegendOffsets() { // setup offsets for legend if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { - mLegend.setOffsetRight(mLegend.getMaximumEntryLength(mLegendLabelPaint)); - mLegendLabelPaint.setTextAlign(Align.LEFT); + mLegend.setOffsetRight(mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint())); + mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT) { if (mXAxis.getPosition() == XAxisPosition.TOP) - mLegend.setOffsetBottom(mLegendLabelPaint.getTextSize() * 3.5f); + mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 3.5f); else { - mLegend.setOffsetBottom(mLegendLabelPaint.getTextSize() * 2.5f); + mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 2.5f); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 0f57362c68..ec2123016a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -40,6 +40,7 @@ import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; +import com.github.mikephil.charting.renderer.LegendRenderer; import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; @@ -106,12 +107,6 @@ public abstract class Chart labels = new ArrayList(); - ArrayList colors = new ArrayList(); - - // loop for building up the colors and labels used in the legend - for (int i = 0; i < mData.getDataSetCount(); i++) { - - DataSet dataSet = mData.getDataSetByIndex(i); - - ArrayList clrs = dataSet.getColors(); - int entryCount = dataSet.getEntryCount(); - - // if we have a barchart with stacked bars - if (dataSet instanceof BarDataSet && ((BarDataSet) dataSet).getStackSize() > 1) { - - BarDataSet bds = (BarDataSet) dataSet; - String[] sLabels = bds.getStackLabels(); - - for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { - - labels.add(sLabels[j % sLabels.length]); - colors.add(clrs.get(j)); - } - - // add the legend description label - colors.add(-2); - labels.add(bds.getLabel()); - - } else if (dataSet instanceof PieDataSet) { - - ArrayList xVals = mData.getXVals(); - PieDataSet pds = (PieDataSet) dataSet; - - for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { - - labels.add(xVals.get(j)); - colors.add(clrs.get(j)); - } - - // add the legend description label - colors.add(-2); - labels.add(pds.getLabel()); - - } else { // all others - - for (int j = 0; j < clrs.size() && j < entryCount; j++) { - - // if multiple colors are set for a DataSet, group them - if (j < clrs.size() - 1 && j < entryCount - 1) { - - labels.add(null); - } else { // add label to the last entry - - String label = mData.getDataSetByIndex(i).getLabel(); - labels.add(label); - } - - colors.add(clrs.get(j)); - } - } - } - - Legend l = new Legend(colors, labels); - - if (mLegend != null) { - // apply the old legend settings to a potential new legend - l.apply(mLegend); - } - - mLegend = l; - } - - /** - * draws the legend - */ - protected void drawLegend() { - - if (!mDrawLegend || mLegend == null || mLegend.getPosition() == LegendPosition.NONE) - return; - - String[] labels = mLegend.getLegendLabels(); - Typeface tf = mLegend.getTypeface(); - - if (tf != null) - mLegendLabelPaint.setTypeface(tf); - - mLegendLabelPaint.setTextSize(mLegend.getTextSize()); - mLegendLabelPaint.setColor(mLegend.getTextColor()); - - float formSize = mLegend.getFormSize(); - - // space between text and shape/form of entry - float formTextSpaceAndForm = mLegend.getFormToTextSpace() + formSize; - - // space between the entries - float stackSpace = mLegend.getStackSpace(); - - float textSize = mLegend.getTextSize(); - - // the amount of pixels the text needs to be set down to be on the same - // height as the form - float textDrop = (Utils.calcTextHeight(mLegendLabelPaint, "AQJ") + formSize) / 2f; - - float posX, posY; - - // contains the stacked legend size in pixels - float stack = 0f; - - boolean wasStacked = false; - - switch (mLegend.getPosition()) { - case BELOW_CHART_LEFT: - - posX = mLegend.getOffsetLeft(); - posY = getHeight() - mLegend.getOffsetBottom() / 2f - formSize / 2f; - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX, posY, mLegendFormPaint, i); - - // grouped forms have null labels - if (labels[i] != null) { - - // make a step to the left - if (mLegend.getColors()[i] != -2) - posX += formTextSpaceAndForm; - - mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop, mLegendLabelPaint, i); - posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) - + mLegend.getXEntrySpace(); - } else { - posX += formSize + stackSpace; - } - } - - break; - case BELOW_CHART_RIGHT: - - posX = mViewPortHandler.contentRight(); - posY = getHeight() - mLegend.getOffsetBottom() / 2f - formSize / 2f; - - for (int i = labels.length - 1; i >= 0; i--) { - - if (labels[i] != null) { - - posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]) - + mLegend.getXEntrySpace(); - mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop, mLegendLabelPaint, i); - if (mLegend.getColors()[i] != -2) - posX -= formTextSpaceAndForm; - } else { - posX -= stackSpace + formSize; - } - - mLegend.drawForm(mDrawCanvas, posX, posY, mLegendFormPaint, i); - } - - break; - case RIGHT_OF_CHART: - - posX = getWidth() - mLegend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; - posY = mLegend.getOffsetTop(); - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX + stack, posY, mLegendFormPaint, i); - - if (labels[i] != null) { - - if (!wasStacked) { - - float x = posX; - - if (mLegend.getColors()[i] != -2) - x += formTextSpaceAndForm; - - posY += textDrop; - - mLegend.drawLabel(mDrawCanvas, x, posY, - mLegendLabelPaint, i); - } else { - - posY += textSize * 1.2f + formSize; - - mLegend.drawLabel(mDrawCanvas, posX, posY, - mLegendLabelPaint, i); - - } - - // make a step down - posY += mLegend.getYEntrySpace(); - stack = 0f; - } else { - stack += formSize + stackSpace; - wasStacked = true; - } - } - break; - case RIGHT_OF_CHART_CENTER: - posX = getWidth() - mLegend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; - posY = getHeight() / 2f - mLegend.getFullHeight(mLegendLabelPaint) / 2f; - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX + stack, posY, mLegendFormPaint, i); - - if (labels[i] != null) { - - if (!wasStacked) { - - float x = posX; - - if (mLegend.getColors()[i] != -2) - x += formTextSpaceAndForm; - - posY += textDrop; - - mLegend.drawLabel(mDrawCanvas, x, posY, - mLegendLabelPaint, i); - } else { - - posY += textSize * 1.2f + formSize; - - mLegend.drawLabel(mDrawCanvas, posX, posY, - mLegendLabelPaint, i); - - } - - // make a step down - posY += mLegend.getYEntrySpace(); - stack = 0f; - } else { - stack += formSize + stackSpace; - wasStacked = true; - } - } - - break; - case BELOW_CHART_CENTER: - - float fullSize = mLegend.getFullWidth(mLegendLabelPaint); - - posX = getWidth() / 2f - fullSize / 2f; - posY = getHeight() - mLegend.getOffsetBottom() / 2f - formSize / 2f; - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX, posY, mLegendFormPaint, i); - - // grouped forms have null labels - if (labels[i] != null) { - - // make a step to the left - if (mLegend.getColors()[i] != -2) - posX += formTextSpaceAndForm; - - mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop, mLegendLabelPaint, i); - posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) - + mLegend.getXEntrySpace(); - } else { - posX += formSize + stackSpace; - } - } - - // Log.i(LOG_TAG, "content bottom: " + mContentRect.bottom + - // ", height: " - // + getHeight() + ", posY: " + posY + ", formSize: " + - // formSize); - - break; - case PIECHART_CENTER: - - posX = getWidth() - / 2f - - (mLegend.getMaximumEntryLength(mLegendLabelPaint) + mLegend - .getXEntrySpace()) - / 2f; - posY = getHeight() / 2f - mLegend.getFullHeight(mLegendLabelPaint) / 2f; - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX + stack, posY, mLegendFormPaint, i); - - if (labels[i] != null) { - - if (!wasStacked) { - - float x = posX; - - if (mLegend.getColors()[i] != -2) - x += formTextSpaceAndForm; - - posY += textDrop; - - mLegend.drawLabel(mDrawCanvas, x, posY, - mLegendLabelPaint, i); - } else { - - posY += textSize * 1.2f + formSize; - - mLegend.drawLabel(mDrawCanvas, posX, posY, - mLegendLabelPaint, i); - - } - - // make a step down - posY += mLegend.getYEntrySpace(); - stack = 0f; - } else { - stack += formSize + stackSpace; - wasStacked = true; - } - } - - break; - case RIGHT_OF_CHART_INSIDE: - - posX = getWidth() - mLegend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; - posY = mLegend.getOffsetTop(); - - for (int i = 0; i < labels.length; i++) { - - mLegend.drawForm(mDrawCanvas, posX + stack, posY, mLegendFormPaint, i); - - if (labels[i] != null) { - - if (!wasStacked) { - - float x = posX; - - if (mLegend.getColors()[i] != -2) - x += formTextSpaceAndForm; - - posY += textDrop; - - mLegend.drawLabel(mDrawCanvas, x, posY, - mLegendLabelPaint, i); - } else { - - posY += textSize * 1.2f + formSize; - - mLegend.drawLabel(mDrawCanvas, posX, posY, - mLegendLabelPaint, i); - - } - - // make a step down - posY += mLegend.getYEntrySpace(); - stack = 0f; - } else { - stack += formSize + stackSpace; - wasStacked = true; - } - } - break; - case NONE: - break; - } - } - /** * draws the description text in the bottom right corner of the chart */ @@ -1347,24 +970,6 @@ public MarkerView getMarkerView() { return mMarkerView; } - /** - * set this to true to draw the legend, false if not - * - * @param enabled - */ - public void setDrawLegend(boolean enabled) { - mDrawLegend = enabled; - } - - /** - * returns true if drawing the legend is enabled, false if not - * - * @return - */ - public boolean isDrawLegendEnabled() { - return mDrawLegend; - } - /** * Returns the legend object of the chart. This method can be used to * customize the automatically generated legend. IMPORTANT: this will return @@ -1376,6 +981,16 @@ public Legend getLegend() { return mLegend; } + /** + * Returns the renderer object responsible for rendering / drawing the + * Legend. + * + * @return + */ + public LegendRenderer getLegendRenderer() { + return mLegendRenderer; + } + /** * Returns the rectangle that defines the borders of the chart-value surface * (into which the actual values are drawn). @@ -1449,9 +1064,6 @@ public void setPaint(Paint p, int which) { case PAINT_RENDER: mRenderPaint = p; break; - case PAINT_LEGEND_LABEL: - mLegendLabelPaint = p; - break; } } @@ -1469,8 +1081,6 @@ public Paint getPaint(int which) { return mDescPaint; case PAINT_RENDER: return mRenderPaint; - case PAINT_LEGEND_LABEL: - return mLegendLabelPaint; } return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 9c96048039..0cd2fa41c8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -103,7 +103,7 @@ protected void onDraw(Canvas canvas) { mRenderer.drawValues(mDrawCanvas); - drawLegend(); + mLegendRenderer.renderLegend(mDrawCanvas, mLegend); drawDescription(); @@ -378,7 +378,7 @@ public boolean isDrawCenterTextEnabled() { @Override protected float getRequiredBottomOffset() { - return mLegendLabelPaint.getTextSize() * 4f; + return mLegendRenderer.getLabelPaint().getTextSize() * 4f; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 616ef67e6c..b5c08fa15d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -13,7 +13,6 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; -import android.view.View; import android.view.ViewGroup; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -83,7 +82,7 @@ public void notifyDataSetChanged() { calcMinMax(); - prepareLegend(); + mLegend = mLegendRenderer.computeLegend(mData, mLegend); calculateOffsets(); } @@ -93,7 +92,7 @@ protected void calculateOffsets() { float legendRight = 0f, legendBottom = 0f, legendTop = 0f; - if (mDrawLegend && mLegend != null && mLegend.getPosition() != LegendPosition.NONE) { + if (mLegend != null && mLegend.isEnabled()) { if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { @@ -102,7 +101,7 @@ protected void calculateOffsets() { legendRight = getFullLegendWidth() + spacing; - mLegendLabelPaint.setTextAlign(Align.LEFT); + mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); // legendTop = mLegend.getFullHeight(mLegendLabelPaint); } else if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { @@ -112,7 +111,7 @@ protected void calculateOffsets() { float legendWidth = getFullLegendWidth() + spacing; - float legendHeight = mLegend.getFullHeight(mLegendLabelPaint);// + + float legendHeight = mLegend.getFullHeight(mLegendRenderer.getLabelPaint());// + // mOffsetTop; PointF c = getCenter(); @@ -136,7 +135,7 @@ protected void calculateOffsets() { legendRight = legendWidth; } - mLegendLabelPaint.setTextAlign(Align.LEFT); + mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT @@ -148,7 +147,7 @@ protected void calculateOffsets() { legendRight += getRequiredBaseOffset(); legendTop += getRequiredBaseOffset(); - mLegend.setOffsetBottom(mLegendLabelPaint.getTextSize() * 4f); + mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 4f); mLegend.setOffsetRight(legendRight); } @@ -398,7 +397,7 @@ public float getDiameter() { * @return */ private float getFullLegendWidth() { - return mLegend.getMaximumEntryLength(mLegendLabelPaint) + return mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint()) + mLegend.getFormSize() + mLegend.getFormToTextSpace(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index d69e53f369..0f0d467597 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -141,7 +141,7 @@ protected void onDraw(Canvas canvas) { mRenderer.drawValues(mDrawCanvas); - drawLegend(); + mLegendRenderer.renderLegend(mDrawCanvas, mLegend); drawDescription(); @@ -293,7 +293,7 @@ public void setDrawWeb(boolean enabled) { @Override protected float getRequiredBottomOffset() { - return mLegendLabelPaint.getTextSize() * 6.5f; + return mLegendRenderer.getLabelPaint().getTextSize() * 6.5f; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 66e3b06472..e248f5b3cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -20,7 +20,7 @@ public class Legend { public enum LegendPosition { - RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, PIECHART_CENTER, NONE + RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, PIECHART_CENTER } public enum LegendForm { @@ -31,11 +31,14 @@ public enum LegendForm { private float mLegendOffsetBottom = 12f, mLegendOffsetRight = 12f, mLegendOffsetLeft = 12f, mLegendOffsetTop = 12f; + /** flag indicating if the legend should be drawn or not */ + private boolean mEnabled = true; + /** the legend colors */ private int[] mColors; /** the legend labels */ - private String[] mLegendLabels; + private String[] mLabels; /** the position relative to the chart the legend is drawn on */ private LegendPosition mPosition = LegendPosition.BELOW_CHART_LEFT; @@ -105,7 +108,7 @@ public Legend(int[] colors, String[] labels) { } this.mColors = colors; - this.mLegendLabels = labels; + this.mLabels = labels; } /** @@ -127,7 +130,7 @@ public Legend(ArrayList colors, ArrayList labels) { } this.mColors = Utils.convertIntegers(colors); - this.mLegendLabels = Utils.convertStrings(labels); + this.mLabels = Utils.convertStrings(labels); } /** @@ -140,11 +143,11 @@ public int getMaximumEntryLength(Paint p) { int max = 0; - for (int i = 0; i < mLegendLabels.length; i++) { + for (int i = 0; i < mLabels.length; i++) { - if (mLegendLabels[i] != null) { + if (mLabels[i] != null) { - int length = Utils.calcTextWidth(p, mLegendLabels[i]); + int length = Utils.calcTextWidth(p, mLabels[i]); if (length > max) max = length; @@ -169,7 +172,7 @@ public int[] getColors() { * @return */ public String[] getLegendLabels() { - return mLegendLabels; + return mLabels; } /** @@ -185,7 +188,7 @@ public void setLegendLabels(String[] labels) { "colors array and labels array need to be of same size"); } - this.mLegendLabels = labels; + this.mLabels = labels; } /** @@ -320,37 +323,6 @@ public void setFormToTextSpace(float space) { this.mFormToTextSpace = Utils.convertDpToPixel(space); } - /** - * draws the form at the given position with the color at the given index - * - * @param c canvas to draw with - * @param x - * @param y - * @param p paint to use for drawing - * @param index the index of the color to use (in the colors array) - */ - public void drawForm(Canvas c, float x, float y, Paint p, int index) { - - if (mColors[index] == -2) - return; - - p.setColor(mColors[index]); - - float half = mFormSize / 2f; - - switch (getForm()) { - case CIRCLE: - c.drawCircle(x + half, y + half, half, p); - break; - case SQUARE: - c.drawRect(x, y, x + mFormSize, y + mFormSize, p); - break; - case LINE: - c.drawLine(x, y + half, x + mFormSize, y + half, p); - break; - } - } - /** * draws the label at the given index in the labels array at the given * position @@ -363,7 +335,7 @@ public void drawForm(Canvas c, float x, float y, Paint p, int index) { */ public void drawLabel(Canvas c, float x, float y, Paint p, int index) { - c.drawText(mLegendLabels[index], x, y, p); + c.drawText(mLabels[index], x, y, p); } /** @@ -509,16 +481,16 @@ public float getFullWidth(Paint labelpaint) { float width = 0f; - for (int i = 0; i < mLegendLabels.length; i++) { + for (int i = 0; i < mLabels.length; i++) { // grouped forms have null labels - if (mLegendLabels[i] != null) { + if (mLabels[i] != null) { // make a step to the left if (mColors[i] != -2) width += mFormSize + mFormToTextSpace; - width += Utils.calcTextWidth(labelpaint, mLegendLabels[i]) + width += Utils.calcTextWidth(labelpaint, mLabels[i]) + mXEntrySpace; } else { width += mFormSize + mStackSpace; @@ -538,12 +510,12 @@ public float getFullHeight(Paint labelpaint) { float height = 0f; - for (int i = 0; i < mLegendLabels.length; i++) { + for (int i = 0; i < mLabels.length; i++) { // grouped forms have null labels - if (mLegendLabels[i] != null) { + if (mLabels[i] != null) { - height += Utils.calcTextHeight(labelpaint, mLegendLabels[i]) + height += Utils.calcTextHeight(labelpaint, mLabels[i]) + mYEntrySpace; } } @@ -569,4 +541,27 @@ public void setTextColor(int color) { public int getTextColor() { return mTextColor; } + + /** + * Set this to true if the legend should be enabled (should be drawn), false + * if not. Default: true + * + * @param enabled + */ + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } + + /** + * Returns true if the legend is enabled (should be drawn), false if not. + * + * @return + */ + public boolean isEnabled() { + return mEnabled; + } + + public boolean isSetUp() { + return mLabels != null && mColors != null; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java new file mode 100644 index 0000000000..94ed5f1ac0 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -0,0 +1,450 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Typeface; + +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; + +public class LegendRenderer extends Renderer { + + /** paint for the legend labels */ + protected Paint legendLabelPaint; + + /** paint used for the legend forms */ + protected Paint legendFormPaint; + + public LegendRenderer(ViewPortHandler viewPortHandler) { + super(viewPortHandler); + + legendLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + legendLabelPaint.setTextSize(Utils.convertDpToPixel(9f)); + + legendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + legendFormPaint.setStyle(Paint.Style.FILL); + legendFormPaint.setStrokeWidth(3f); + } + + /** + * Returns the Paint object used for drawing the Legend labels. + * + * @return + */ + public Paint getLabelPaint() { + return legendLabelPaint; + } + + /** + * Returns the Paint object used for drawing the Legend forms. + * + * @return + */ + public Paint getFormPaint() { + return legendFormPaint; + } + + /** + * Prepares the legend and calculates all needed forms and colors. + * + * @param data + */ + public Legend computeLegend(ChartData data, Legend legend) { + + ArrayList labels = new ArrayList(); + ArrayList colors = new ArrayList(); + + // loop for building up the colors and labels used in the legend + for (int i = 0; i < data.getDataSetCount(); i++) { + + DataSet dataSet = data.getDataSetByIndex(i); + + ArrayList clrs = dataSet.getColors(); + int entryCount = dataSet.getEntryCount(); + + // if we have a barchart with stacked bars + if (dataSet instanceof BarDataSet && ((BarDataSet) dataSet).getStackSize() > 1) { + + BarDataSet bds = (BarDataSet) dataSet; + String[] sLabels = bds.getStackLabels(); + + for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { + + labels.add(sLabels[j % sLabels.length]); + colors.add(clrs.get(j)); + } + + // add the legend description label + colors.add(-2); + labels.add(bds.getLabel()); + + } else if (dataSet instanceof PieDataSet) { + + ArrayList xVals = data.getXVals(); + PieDataSet pds = (PieDataSet) dataSet; + + for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { + + labels.add(xVals.get(j)); + colors.add(clrs.get(j)); + } + + // add the legend description label + colors.add(-2); + labels.add(pds.getLabel()); + + } else { // all others + + for (int j = 0; j < clrs.size() && j < entryCount; j++) { + + // if multiple colors are set for a DataSet, group them + if (j < clrs.size() - 1 && j < entryCount - 1) { + + labels.add(null); + } else { // add label to the last entry + + String label = data.getDataSetByIndex(i).getLabel(); + labels.add(label); + } + + colors.add(clrs.get(j)); + } + } + } + + Legend l = new Legend(colors, labels); + + if (legend != null) { + // apply the old legend settings to a potential new legend + l.apply(legend); + } + + return l; + } + + public void renderLegend(Canvas c, Legend legend) { + + if (legend == null || !legend.isEnabled()) + return; + + String[] labels = legend.getLegendLabels(); + Typeface tf = legend.getTypeface(); + + if (tf != null) + legendLabelPaint.setTypeface(tf); + + legendLabelPaint.setTextSize(legend.getTextSize()); + legendLabelPaint.setColor(legend.getTextColor()); + + float formSize = legend.getFormSize(); + + // space between text and shape/form of entry + float formTextSpaceAndForm = legend.getFormToTextSpace() + formSize; + + // space between the entries + float stackSpace = legend.getStackSpace(); + + float textSize = legend.getTextSize(); + + // the amount of pixels the text needs to be set down to be on the same + // height as the form + float textDrop = (Utils.calcTextHeight(legendLabelPaint, "AQJ") + formSize) / 2f; + + float posX, posY; + + // contains the stacked legend size in pixels + float stack = 0f; + + boolean wasStacked = false; + + switch (legend.getPosition()) { + case BELOW_CHART_LEFT: + + posX = legend.getOffsetLeft(); + posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f + - formSize / 2f; + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX, posY, i, legend); + + // grouped forms have null labels + if (labels[i] != null) { + + // make a step to the left + if (legend.getColors()[i] != -2) + posX += formTextSpaceAndForm; + + legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); + posX += Utils.calcTextWidth(legendLabelPaint, labels[i]) + + legend.getXEntrySpace(); + } else { + posX += formSize + stackSpace; + } + } + + break; + case BELOW_CHART_RIGHT: + + posX = mViewPortHandler.contentRight(); + posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f + - formSize / 2f; + + for (int i = labels.length - 1; i >= 0; i--) { + + if (labels[i] != null) { + + posX -= Utils.calcTextWidth(legendLabelPaint, labels[i]) + + legend.getXEntrySpace(); + legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); + if (legend.getColors()[i] != -2) + posX -= formTextSpaceAndForm; + } else { + posX -= stackSpace + formSize; + } + + drawForm(c, posX, posY, i, legend); + } + + break; + case RIGHT_OF_CHART: + + posX = mViewPortHandler.getChartWidth() + - legend.getMaximumEntryLength(legendLabelPaint) + - formTextSpaceAndForm; + posY = legend.getOffsetTop(); + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX + stack, posY, i, legend); + + if (labels[i] != null) { + + if (!wasStacked) { + + float x = posX; + + if (legend.getColors()[i] != -2) + x += formTextSpaceAndForm; + + posY += textDrop; + + legend.drawLabel(c, x, posY, + legendLabelPaint, i); + } else { + + posY += textSize * 1.2f + formSize; + + legend.drawLabel(c, posX, posY, + legendLabelPaint, i); + } + + // make a step down + posY += legend.getYEntrySpace(); + stack = 0f; + } else { + stack += formSize + stackSpace; + wasStacked = true; + } + } + break; + case RIGHT_OF_CHART_CENTER: + posX = mViewPortHandler.getChartWidth() + - legend.getMaximumEntryLength(legendLabelPaint) + - formTextSpaceAndForm; + posY = mViewPortHandler.getChartHeight() / 2f + - legend.getFullHeight(legendLabelPaint) / 2f; + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX + stack, posY, i, legend); + + if (labels[i] != null) { + + if (!wasStacked) { + + float x = posX; + + if (legend.getColors()[i] != -2) + x += formTextSpaceAndForm; + + posY += textDrop; + + legend.drawLabel(c, x, posY, + legendLabelPaint, i); + } else { + + posY += textSize * 1.2f + formSize; + + legend.drawLabel(c, posX, posY, + legendLabelPaint, i); + } + + // make a step down + posY += legend.getYEntrySpace(); + stack = 0f; + } else { + stack += formSize + stackSpace; + wasStacked = true; + } + } + + break; + case BELOW_CHART_CENTER: + + float fullSize = legend.getFullWidth(legendLabelPaint); + + posX = mViewPortHandler.getChartWidth() / 2f - fullSize / 2f; + posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f + - formSize / 2f; + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX, posY, i, legend); + + // grouped forms have null labels + if (labels[i] != null) { + + // make a step to the left + if (legend.getColors()[i] != -2) + posX += formTextSpaceAndForm; + + legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); + posX += Utils.calcTextWidth(legendLabelPaint, labels[i]) + + legend.getXEntrySpace(); + } else { + posX += formSize + stackSpace; + } + } + + break; + case PIECHART_CENTER: + + posX = mViewPortHandler.getChartWidth() + / 2f + - (legend.getMaximumEntryLength(legendLabelPaint) + legend + .getXEntrySpace()) + / 2f; + posY = mViewPortHandler.getChartHeight() / 2f + - legend.getFullHeight(legendLabelPaint) / 2f; + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX + stack, posY, i, legend); + + if (labels[i] != null) { + + if (!wasStacked) { + + float x = posX; + + if (legend.getColors()[i] != -2) + x += formTextSpaceAndForm; + + posY += textDrop; + + legend.drawLabel(c, x, posY, + legendLabelPaint, i); + } else { + + posY += textSize * 1.2f + formSize; + + legend.drawLabel(c, posX, posY, + legendLabelPaint, i); + + } + + // make a step down + posY += legend.getYEntrySpace(); + stack = 0f; + } else { + stack += formSize + stackSpace; + wasStacked = true; + } + } + + break; + case RIGHT_OF_CHART_INSIDE: + + posX = mViewPortHandler.getChartWidth() + - legend.getMaximumEntryLength(legendLabelPaint) + - formTextSpaceAndForm; + posY = legend.getOffsetTop(); + + for (int i = 0; i < labels.length; i++) { + + drawForm(c, posX + stack, posY, i, legend); + + if (labels[i] != null) { + + if (!wasStacked) { + + float x = posX; + + if (legend.getColors()[i] != -2) + x += formTextSpaceAndForm; + + posY += textDrop; + + legend.drawLabel(c, x, posY, + legendLabelPaint, i); + } else { + + posY += textSize * 1.2f + formSize; + + legend.drawLabel(c, posX, posY, + legendLabelPaint, i); + + } + + // make a step down + posY += legend.getYEntrySpace(); + stack = 0f; + } else { + stack += formSize + stackSpace; + wasStacked = true; + } + } + break; + } + } + + /** + * draws the form at the given position with the color at the given index + * + * @param c canvas to draw with + * @param x + * @param y + * @param index the index of the color to use (in the colors array) + */ + protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { + + if (legend.getColors()[index] == -2) + return; + + legendFormPaint.setColor(legend.getColors()[index]); + + float formsize = legend.getFormSize(); + float half = formsize / 2f; + + switch (legend.getForm()) { + case CIRCLE: + c.drawCircle(x + half, y + half, half, legendFormPaint); + break; + case SQUARE: + c.drawRect(x, y, x + formsize, y + formsize, legendFormPaint); + break; + case LINE: + c.drawLine(x, y + half, x + formsize, y + half, legendFormPaint); + break; + } + } +} From cf40c0846d7af3b5cd2741e615ca11400ddf7a3d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 19:16:40 +0100 Subject: [PATCH 0104/1390] Code cleanup. --- .../mikephil/charting/charts/Chart.java | 142 +++--------------- .../mikephil/charting/components/Legend.java | 17 +-- .../charting/renderer/LegendRenderer.java | 3 +- 3 files changed, 27 insertions(+), 135 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index ec2123016a..6ea96c790f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -29,13 +29,10 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.MarkerView; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; @@ -200,7 +197,7 @@ public void onAnimationUpdate(ValueAnimator animation) { Utils.init(getContext().getResources()); mViewPortHandler = new ViewPortHandler(); - + mLegendRenderer = new LegendRenderer(mViewPortHandler); mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -971,9 +968,11 @@ public MarkerView getMarkerView() { } /** - * Returns the legend object of the chart. This method can be used to - * customize the automatically generated legend. IMPORTANT: this will return - * null if no data has been set for the chart when calling this method + * Returns the Legend object of the chart. This method can be used to + * customize the automatically generated Legend. IMPORTANT: Since the Legend + * is generated from data provided by the user (via setData(...) method), + * this will return NULL if no data has been set for the chart. You need to + * set data for the chart before calling this method. * * @return */ @@ -1151,106 +1150,18 @@ public void setValueTextSize(float size) { mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); } - // /** - // * returns the x-value at the given index - // * - // * @param index - // * @return - // */ - // public String getXValue(int index) { - // if (mData == null || mData.getXValCount() <= index) - // return null; - // else - // return mData.getXVals().get(index); - // } - // - // /** - // * returns the y-value for the given index from the DataSet with the given - // * label - // * - // * @param index - // * @param dataSetLabel - // * @return - // */ - // public float getYValue(int index, String dataSetLabel) { - // DataSet set = mData.getDataSetByLabel(dataSetLabel, - // true); - // return set.getYVals().get(index).getVal(); - // } - // - // /** - // * returns the y-value for the given x-index and DataSet index - // * - // * @param index - // * @param dataSet - // * @return - // */ - // public float getYValue(int xIndex, int dataSetIndex) { - // DataSet set = mData.getDataSetByIndex(dataSetIndex); - // return set.getYValForXIndex(xIndex); - // } - // - // /** - // * returns the DataSet with the given index in the DataSet array held by - // the - // * ChartData object. - // * - // * @param index - // * @return - // */ - // public DataSet getDataSetByIndex(int index) { - // return mData.getDataSetByIndex(index); - // } - // - // /** - // * returns the DataSet with the given label that is stored in the - // ChartData - // * object. - // * - // * @param type - // * @return - // */ - // public DataSet getDataSetByLabel(String dataSetLabel) { - // return mData.getDataSetByLabel(dataSetLabel, true); - // } - // - // /** - // * returns the Entry object from the first DataSet stored in the ChartData - // * object. If multiple DataSets are used, use getEntry(index, type) or - // * getEntryByDataSetIndex(xIndex, dataSetIndex); - // * - // * @param index - // * @return - // */ - // public Entry getEntry(int index) { - // return mData.getDataSetByIndex(0).getYVals().get(index); - // } - // - // /** - // * returns the Entry object at the given index from the DataSet with the - // * given label. - // * - // * @param index - // * @param dataSetLabel - // * @return - // */ - // public Entry getEntry(int index, String dataSetLabel) { - // return mData.getDataSetByLabel(dataSetLabel, true).getYVals().get(index); - // } - // - // /** - // * Returns the corresponding Entry object at the given xIndex from the - // given - // * DataSet. INFORMATION: This method does calculations at runtime. Do not - // * over-use in performance critical situations. - // * - // * @param xIndex - // * @param dataSetIndex - // * @return - // */ - // public Entry getEntryByDataSetIndex(int xIndex, int dataSetIndex) { - // return mData.getDataSetByIndex(dataSetIndex).getEntryForXIndex(xIndex); - // } + /** + * returns the x-value at the given index + * + * @param index + * @return + */ + public String getXValue(int index) { + if (mData == null || mData.getXValCount() <= index) + return null; + else + return mData.getXVals().get(index); + } /** * Get all Entry objects at the given index across all DataSets. @@ -1471,13 +1382,6 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto for (int i = 0; i < getChildCount(); i++) { getChildAt(i).layout(left, top, right, bottom); } - // - // prepareContentRect(); - // Log.i(LOG_TAG, - // "onLayout(), width: " + mContentRect.width() + ", height: " + - // mContentRect.height()); - // - // calculateOffsets(); } @Override @@ -1495,8 +1399,6 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { Log.i(LOG_TAG, "Setting chart dimens, width: " + w + ", height: " + h); } - // prepare content rect and matrices - // prepareContentRect(); notifyDataSetChanged(); super.onSizeChanged(w, h, oldw, oldh); @@ -1533,12 +1435,4 @@ public View getChartView() { public PointF getCenterOfView() { return getCenter(); } - - // @Override - // protected void onAttachedToWindow() { - // super.onAttachedToWindow(); - // if (isInEditMode()) { - // initWithDummyData(); - // } - // } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index e248f5b3cc..29de0f3454 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -356,12 +356,13 @@ public void apply(Legend l) { mTextSize = l.mTextSize; mStackSpace = l.mStackSpace; mTextColor = l.mTextColor; - - // apply offsets - mLegendOffsetBottom = l.mLegendOffsetBottom; - mLegendOffsetLeft = l.mLegendOffsetLeft; - mLegendOffsetRight = l.mLegendOffsetRight; - mLegendOffsetTop = l.mLegendOffsetTop; + mEnabled = l.mEnabled; +// +// // apply offsets +// mLegendOffsetBottom = l.mLegendOffsetBottom; +// mLegendOffsetLeft = l.mLegendOffsetLeft; +// mLegendOffsetRight = l.mLegendOffsetRight; +// mLegendOffsetTop = l.mLegendOffsetTop; } /** @@ -560,8 +561,4 @@ public void setEnabled(boolean enabled) { public boolean isEnabled() { return mEnabled; } - - public boolean isSetUp() { - return mLabels != null && mColors != null; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 94ed5f1ac0..0fe786f6ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -418,7 +418,8 @@ public void renderLegend(Canvas c, Legend legend) { } /** - * draws the form at the given position with the color at the given index + * Draws the Legend-form at the given position with the color at the given + * index. * * @param c canvas to draw with * @param x From 8e193e26d7f6e3edf0da09c83e4b2a40622c8b8e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 19:24:30 +0100 Subject: [PATCH 0105/1390] Worked on LegendRenderer. --- .../mikephil/charting/components/Legend.java | 37 ++++--- .../charting/renderer/LegendRenderer.java | 96 ++++++++++--------- 2 files changed, 66 insertions(+), 67 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 29de0f3454..5a59acdd46 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -191,6 +191,16 @@ public void setLegendLabels(String[] labels) { this.mLabels = labels; } + /** + * Returns the legend-label at the given index. + * + * @param index + * @return + */ + public String getLabel(int index) { + return mLabels[index]; + } + /** * returns the position of the legend relative to the chart * @@ -323,21 +333,6 @@ public void setFormToTextSpace(float space) { this.mFormToTextSpace = Utils.convertDpToPixel(space); } - /** - * draws the label at the given index in the labels array at the given - * position - * - * @param c canvas to draw with - * @param x - * @param y - * @param p paint to use for drawing - * @param index index in the labels-array - */ - public void drawLabel(Canvas c, float x, float y, Paint p, int index) { - - c.drawText(mLabels[index], x, y, p); - } - /** * applies the state from the legend in the parameter to this legend (except * colors, labels and offsets) @@ -357,12 +352,12 @@ public void apply(Legend l) { mStackSpace = l.mStackSpace; mTextColor = l.mTextColor; mEnabled = l.mEnabled; -// -// // apply offsets -// mLegendOffsetBottom = l.mLegendOffsetBottom; -// mLegendOffsetLeft = l.mLegendOffsetLeft; -// mLegendOffsetRight = l.mLegendOffsetRight; -// mLegendOffsetTop = l.mLegendOffsetTop; + // + // // apply offsets + // mLegendOffsetBottom = l.mLegendOffsetBottom; + // mLegendOffsetLeft = l.mLegendOffsetLeft; + // mLegendOffsetRight = l.mLegendOffsetRight; + // mLegendOffsetTop = l.mLegendOffsetTop; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 0fe786f6ad..1b2b630800 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -18,20 +18,20 @@ public class LegendRenderer extends Renderer { /** paint for the legend labels */ - protected Paint legendLabelPaint; + protected Paint mLegendLabelPaint; /** paint used for the legend forms */ - protected Paint legendFormPaint; + protected Paint mLegendFormPaint; public LegendRenderer(ViewPortHandler viewPortHandler) { super(viewPortHandler); - legendLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - legendLabelPaint.setTextSize(Utils.convertDpToPixel(9f)); + mLegendLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLegendLabelPaint.setTextSize(Utils.convertDpToPixel(9f)); - legendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - legendFormPaint.setStyle(Paint.Style.FILL); - legendFormPaint.setStrokeWidth(3f); + mLegendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLegendFormPaint.setStyle(Paint.Style.FILL); + mLegendFormPaint.setStrokeWidth(3f); } /** @@ -40,7 +40,7 @@ public LegendRenderer(ViewPortHandler viewPortHandler) { * @return */ public Paint getLabelPaint() { - return legendLabelPaint; + return mLegendLabelPaint; } /** @@ -49,7 +49,7 @@ public Paint getLabelPaint() { * @return */ public Paint getFormPaint() { - return legendFormPaint; + return mLegendFormPaint; } /** @@ -139,10 +139,10 @@ public void renderLegend(Canvas c, Legend legend) { Typeface tf = legend.getTypeface(); if (tf != null) - legendLabelPaint.setTypeface(tf); + mLegendLabelPaint.setTypeface(tf); - legendLabelPaint.setTextSize(legend.getTextSize()); - legendLabelPaint.setColor(legend.getTextColor()); + mLegendLabelPaint.setTextSize(legend.getTextSize()); + mLegendLabelPaint.setColor(legend.getTextColor()); float formSize = legend.getFormSize(); @@ -156,7 +156,7 @@ public void renderLegend(Canvas c, Legend legend) { // the amount of pixels the text needs to be set down to be on the same // height as the form - float textDrop = (Utils.calcTextHeight(legendLabelPaint, "AQJ") + formSize) / 2f; + float textDrop = (Utils.calcTextHeight(mLegendLabelPaint, "AQJ") + formSize) / 2f; float posX, posY; @@ -183,8 +183,8 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) posX += formTextSpaceAndForm; - legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); - posX += Utils.calcTextWidth(legendLabelPaint, labels[i]) + drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); + posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); } else { posX += formSize + stackSpace; @@ -202,9 +202,9 @@ public void renderLegend(Canvas c, Legend legend) { if (labels[i] != null) { - posX -= Utils.calcTextWidth(legendLabelPaint, labels[i]) + posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); - legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); + drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); if (legend.getColors()[i] != -2) posX -= formTextSpaceAndForm; } else { @@ -218,7 +218,7 @@ public void renderLegend(Canvas c, Legend legend) { case RIGHT_OF_CHART: posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(legendLabelPaint) + - legend.getMaximumEntryLength(mLegendLabelPaint) - formTextSpaceAndForm; posY = legend.getOffsetTop(); @@ -237,14 +237,12 @@ public void renderLegend(Canvas c, Legend legend) { posY += textDrop; - legend.drawLabel(c, x, posY, - legendLabelPaint, i); + drawLabel(c, x, posY, legend.getLabel(i)); } else { posY += textSize * 1.2f + formSize; - legend.drawLabel(c, posX, posY, - legendLabelPaint, i); + drawLabel(c, posX, posY, legend.getLabel(i)); } // make a step down @@ -258,10 +256,10 @@ public void renderLegend(Canvas c, Legend legend) { break; case RIGHT_OF_CHART_CENTER: posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(legendLabelPaint) + - legend.getMaximumEntryLength(mLegendLabelPaint) - formTextSpaceAndForm; posY = mViewPortHandler.getChartHeight() / 2f - - legend.getFullHeight(legendLabelPaint) / 2f; + - legend.getFullHeight(mLegendLabelPaint) / 2f; for (int i = 0; i < labels.length; i++) { @@ -278,14 +276,12 @@ public void renderLegend(Canvas c, Legend legend) { posY += textDrop; - legend.drawLabel(c, x, posY, - legendLabelPaint, i); + drawLabel(c, x, posY, legend.getLabel(i)); } else { posY += textSize * 1.2f + formSize; - legend.drawLabel(c, posX, posY, - legendLabelPaint, i); + drawLabel(c, posX, posY, legend.getLabel(i)); } // make a step down @@ -300,7 +296,7 @@ public void renderLegend(Canvas c, Legend legend) { break; case BELOW_CHART_CENTER: - float fullSize = legend.getFullWidth(legendLabelPaint); + float fullSize = legend.getFullWidth(mLegendLabelPaint); posX = mViewPortHandler.getChartWidth() / 2f - fullSize / 2f; posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f @@ -317,8 +313,8 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) posX += formTextSpaceAndForm; - legend.drawLabel(c, posX, posY + textDrop, legendLabelPaint, i); - posX += Utils.calcTextWidth(legendLabelPaint, labels[i]) + drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); + posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); } else { posX += formSize + stackSpace; @@ -330,11 +326,11 @@ public void renderLegend(Canvas c, Legend legend) { posX = mViewPortHandler.getChartWidth() / 2f - - (legend.getMaximumEntryLength(legendLabelPaint) + legend + - (legend.getMaximumEntryLength(mLegendLabelPaint) + legend .getXEntrySpace()) / 2f; posY = mViewPortHandler.getChartHeight() / 2f - - legend.getFullHeight(legendLabelPaint) / 2f; + - legend.getFullHeight(mLegendLabelPaint) / 2f; for (int i = 0; i < labels.length; i++) { @@ -351,14 +347,12 @@ public void renderLegend(Canvas c, Legend legend) { posY += textDrop; - legend.drawLabel(c, x, posY, - legendLabelPaint, i); + drawLabel(c, x, posY, legend.getLabel(i)); } else { posY += textSize * 1.2f + formSize; - legend.drawLabel(c, posX, posY, - legendLabelPaint, i); + drawLabel(c, posX, posY, legend.getLabel(i)); } @@ -375,7 +369,7 @@ public void renderLegend(Canvas c, Legend legend) { case RIGHT_OF_CHART_INSIDE: posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(legendLabelPaint) + - legend.getMaximumEntryLength(mLegendLabelPaint) - formTextSpaceAndForm; posY = legend.getOffsetTop(); @@ -394,14 +388,12 @@ public void renderLegend(Canvas c, Legend legend) { posY += textDrop; - legend.drawLabel(c, x, posY, - legendLabelPaint, i); + drawLabel(c, x, posY, legend.getLabel(i)); } else { posY += textSize * 1.2f + formSize; - legend.drawLabel(c, posX, posY, - legendLabelPaint, i); + drawLabel(c, posX, posY, legend.getLabel(i)); } @@ -431,21 +423,33 @@ protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { if (legend.getColors()[index] == -2) return; - legendFormPaint.setColor(legend.getColors()[index]); + mLegendFormPaint.setColor(legend.getColors()[index]); float formsize = legend.getFormSize(); float half = formsize / 2f; switch (legend.getForm()) { case CIRCLE: - c.drawCircle(x + half, y + half, half, legendFormPaint); + c.drawCircle(x + half, y + half, half, mLegendFormPaint); break; case SQUARE: - c.drawRect(x, y, x + formsize, y + formsize, legendFormPaint); + c.drawRect(x, y, x + formsize, y + formsize, mLegendFormPaint); break; case LINE: - c.drawLine(x, y + half, x + formsize, y + half, legendFormPaint); + c.drawLine(x, y + half, x + formsize, y + half, mLegendFormPaint); break; } } + + /** + * Draws the provided label at the given position. + * + * @param c canvas to draw with + * @param x + * @param y + * @param label the label to draw + */ + protected void drawLabel(Canvas c, float x, float y, String label) { + c.drawText(label, x, y, mLegendLabelPaint); + } } From a7dd58ab2aa82d50f050a18a2d06c0360dc0c2fc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 22 Feb 2015 22:24:00 +0100 Subject: [PATCH 0106/1390] Worked on LegendRenderer. --- .../mpchartexample/BarChartActivity.java | 7 +- .../mpchartexample/LineChartActivity2.java | 2 + .../mpchartexample/PieChartActivity.java | 1 - .../charting/charts/BarLineChartBase.java | 4 +- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/components/Legend.java | 43 ++++++-- .../charting/renderer/LegendRenderer.java | 101 +++++++----------- 7 files changed, 86 insertions(+), 74 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index a1218c84b3..d9cc045e1a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -109,8 +110,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); - l.setFormSize(8f); + l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setForm(LegendForm.SQUARE); + l.setFormSize(9f); + l.setTextSize(11f); l.setXEntrySpace(4f); // mChart.setDrawLegend(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 2b3f981bed..38c42ac0cd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; @@ -96,6 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { l.setForm(LegendForm.LINE); l.setTypeface(tf); l.setTextColor(Color.WHITE); + l.setPosition(LegendPosition.BELOW_CHART_LEFT); XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 3fd65f5bce..2bf7b11804 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -93,7 +93,6 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.RIGHT_OF_CHART); l.setXEntrySpace(7f); l.setYEntrySpace(5f); - } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index ab6d736747..79d6e4e706 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -317,7 +317,7 @@ protected void calculateOffsets() { // this is the space between the legend and the chart float spacing = Utils.convertDpToPixel(12f); - legendRight = mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint()) + legendRight = mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint()) + mLegend.getFormSize() + mLegend.getFormToTextSpace() + spacing; mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); @@ -420,7 +420,7 @@ public void calculateLegendOffsets() { // setup offsets for legend if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { - mLegend.setOffsetRight(mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint())); + mLegend.setOffsetRight(mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint())); mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index b5c08fa15d..6803838423 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -397,7 +397,7 @@ public float getDiameter() { * @return */ private float getFullLegendWidth() { - return mLegend.getMaximumEntryLength(mLegendRenderer.getLabelPaint()) + return mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint()) + mLegend.getFormSize() + mLegend.getFormToTextSpace(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 5a59acdd46..79b891de95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.components; -import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Typeface; @@ -50,7 +49,7 @@ public enum LegendForm { private Typeface mTypeface = null; /** the text size of the legend labels */ - private float mTextSize = 9f; + private float mTextSize = 10f; /** the text color to use */ private int mTextColor = Color.BLACK; @@ -78,6 +77,9 @@ public enum LegendForm { /** the space that should be left between stacked forms */ private float mStackSpace = 3f; + public float mTextHeight = 0f; + public float mTextWidth = 0f; + /** default constructor */ public Legend() { @@ -85,7 +87,7 @@ public Legend() { mXEntrySpace = Utils.convertDpToPixel(6f); mYEntrySpace = Utils.convertDpToPixel(5f); mFormToTextSpace = Utils.convertDpToPixel(5f); - mTextSize = Utils.convertDpToPixel(9f); + mTextSize = Utils.convertDpToPixel(10f); mStackSpace = Utils.convertDpToPixel(3f); } @@ -134,27 +136,52 @@ public Legend(ArrayList colors, ArrayList labels) { } /** - * returns the maximum length in pixels over all legend labels + their forms + * returns the maximum length in pixels across all legend labels + formsize + * + formtotextspace + * + * @param p the paint object used for rendering the text + * @return + */ + public float getMaximumEntryWidth(Paint p) { + + float max = 0f; + + for (int i = 0; i < mLabels.length; i++) { + + if (mLabels[i] != null) { + + float length = (float) Utils.calcTextWidth(p, mLabels[i]); + + if (length > max) + max = length; + } + } + + return max + mFormSize + mFormToTextSpace; + } + + /** + * returns the maximum height in pixels across all legend labels * * @param p the paint object used for rendering the text * @return */ - public int getMaximumEntryLength(Paint p) { + public float getMaximumEntryHeight(Paint p) { - int max = 0; + float max = 0f; for (int i = 0; i < mLabels.length; i++) { if (mLabels[i] != null) { - int length = Utils.calcTextWidth(p, mLabels[i]); + float length = (float) Utils.calcTextHeight(p, mLabels[i]); if (length > max) max = length; } } - return max + (int) mFormSize; + return max; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 1b2b630800..bfc0d91df0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -144,6 +144,9 @@ public void renderLegend(Canvas c, Legend legend) { mLegendLabelPaint.setTextSize(legend.getTextSize()); mLegendLabelPaint.setColor(legend.getTextColor()); + legend.mTextWidth = legend.getMaximumEntryWidth(mLegendLabelPaint); + legend.mTextHeight = legend.getMaximumEntryHeight(mLegendLabelPaint); + float formSize = legend.getFormSize(); // space between text and shape/form of entry @@ -152,8 +155,6 @@ public void renderLegend(Canvas c, Legend legend) { // space between the entries float stackSpace = legend.getStackSpace(); - float textSize = legend.getTextSize(); - // the amount of pixels the text needs to be set down to be on the same // height as the form float textDrop = (Utils.calcTextHeight(mLegendLabelPaint, "AQJ") + formSize) / 2f; @@ -165,16 +166,18 @@ public void renderLegend(Canvas c, Legend legend) { boolean wasStacked = false; + float yoffset = Utils.convertDpToPixel(4f); + float xoffset = Utils.convertDpToPixel(3f); + switch (legend.getPosition()) { case BELOW_CHART_LEFT: - posX = legend.getOffsetLeft(); - posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f - - formSize / 2f; + posX = mViewPortHandler.contentLeft(); + posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = 0; i < labels.length; i++) { - drawForm(c, posX, posY, i, legend); + drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); // grouped forms have null labels if (labels[i] != null) { @@ -183,7 +186,7 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) posX += formTextSpaceAndForm; - drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); + drawLabel(c, posX, posY, legend.getLabel(i)); posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); } else { @@ -195,8 +198,7 @@ public void renderLegend(Canvas c, Legend legend) { case BELOW_CHART_RIGHT: posX = mViewPortHandler.contentRight(); - posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f - - formSize / 2f; + posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = labels.length - 1; i >= 0; i--) { @@ -204,23 +206,21 @@ public void renderLegend(Canvas c, Legend legend) { posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); - drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); + drawLabel(c, posX, posY, legend.getLabel(i)); if (legend.getColors()[i] != -2) posX -= formTextSpaceAndForm; } else { posX -= stackSpace + formSize; } - drawForm(c, posX, posY, i, legend); + drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); } break; case RIGHT_OF_CHART: - posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; - posY = legend.getOffsetTop(); + posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; + posY = mViewPortHandler.contentTop() + yoffset; for (int i = 0; i < labels.length; i++) { @@ -235,14 +235,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - posY += textDrop; + drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); - drawLabel(c, x, posY, legend.getLabel(i)); + posY += textDrop; } else { - - posY += textSize * 1.2f + formSize; - - drawLabel(c, posX, posY, legend.getLabel(i)); + posY += legend.mTextHeight * 3f; + drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); } // make a step down @@ -255,9 +253,7 @@ public void renderLegend(Canvas c, Legend legend) { } break; case RIGHT_OF_CHART_CENTER: - posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; + posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; posY = mViewPortHandler.getChartHeight() / 2f - legend.getFullHeight(mLegendLabelPaint) / 2f; @@ -274,14 +270,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - posY += textDrop; + drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); - drawLabel(c, x, posY, legend.getLabel(i)); + posY += textDrop; } else { - - posY += textSize * 1.2f + formSize; - - drawLabel(c, posX, posY, legend.getLabel(i)); + posY += legend.mTextHeight * 3f; + drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); } // make a step down @@ -299,12 +293,11 @@ public void renderLegend(Canvas c, Legend legend) { float fullSize = legend.getFullWidth(mLegendLabelPaint); posX = mViewPortHandler.getChartWidth() / 2f - fullSize / 2f; - posY = mViewPortHandler.getChartHeight() - legend.getOffsetBottom() / 2f - - formSize / 2f; + posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = 0; i < labels.length; i++) { - drawForm(c, posX, posY, i, legend); + drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); // grouped forms have null labels if (labels[i] != null) { @@ -313,7 +306,7 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) posX += formTextSpaceAndForm; - drawLabel(c, posX, posY + textDrop, legend.getLabel(i)); + drawLabel(c, posX, posY, legend.getLabel(i)); posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + legend.getXEntrySpace(); } else { @@ -324,11 +317,7 @@ public void renderLegend(Canvas c, Legend legend) { break; case PIECHART_CENTER: - posX = mViewPortHandler.getChartWidth() - / 2f - - (legend.getMaximumEntryLength(mLegendLabelPaint) + legend - .getXEntrySpace()) - / 2f; + posX = mViewPortHandler.getChartWidth() / 2f - legend.mTextWidth / 2f; posY = mViewPortHandler.getChartHeight() / 2f - legend.getFullHeight(mLegendLabelPaint) / 2f; @@ -345,15 +334,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - posY += textDrop; + drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); - drawLabel(c, x, posY, legend.getLabel(i)); + posY += textDrop; } else { - - posY += textSize * 1.2f + formSize; - - drawLabel(c, posX, posY, legend.getLabel(i)); - + posY += legend.mTextHeight * 3f; + drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); } // make a step down @@ -368,10 +354,8 @@ public void renderLegend(Canvas c, Legend legend) { break; case RIGHT_OF_CHART_INSIDE: - posX = mViewPortHandler.getChartWidth() - - legend.getMaximumEntryLength(mLegendLabelPaint) - - formTextSpaceAndForm; - posY = legend.getOffsetTop(); + posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; + posY = mViewPortHandler.contentTop() + yoffset; for (int i = 0; i < labels.length; i++) { @@ -386,15 +370,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - posY += textDrop; + drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); - drawLabel(c, x, posY, legend.getLabel(i)); + posY += textDrop; } else { - - posY += textSize * 1.2f + formSize; - - drawLabel(c, posX, posY, legend.getLabel(i)); - + posY += legend.mTextHeight * 3f; + drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); } // make a step down @@ -430,13 +411,13 @@ protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { switch (legend.getForm()) { case CIRCLE: - c.drawCircle(x + half, y + half, half, mLegendFormPaint); + c.drawCircle(x + half, y, half, mLegendFormPaint); break; case SQUARE: - c.drawRect(x, y, x + formsize, y + formsize, mLegendFormPaint); + c.drawRect(x, y - half, x + formsize, y + half, mLegendFormPaint); break; case LINE: - c.drawLine(x, y + half, x + formsize, y + half, mLegendFormPaint); + c.drawLine(x, y, x + formsize, y, mLegendFormPaint); break; } } From 50edcd1868ad91e09e434b0dc53e960e6810d337 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 23 Feb 2015 00:13:54 +0100 Subject: [PATCH 0107/1390] Worked on offset calculation for the Legend. TODO: Pie- and RadarChart. --- .../mpchartexample/BarChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 - .../charting/charts/BarLineChartBase.java | 87 +++---------- .../charting/charts/PieRadarChartBase.java | 7 -- .../mikephil/charting/components/Legend.java | 117 ++++++------------ .../charting/renderer/LegendRenderer.java | 69 ++++++----- 6 files changed, 92 insertions(+), 192 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index d9cc045e1a..4054fa464d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -110,7 +110,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setPosition(LegendPosition.BELOW_CHART_LEFT); l.setForm(LegendForm.SQUARE); l.setFormSize(9f); l.setTextSize(11f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 1d8ae7c5f2..905fbbab82 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -186,8 +186,6 @@ public void onDrawFinished(DataSet dataSet) { // prepare the legend again mChart.getLegendRenderer().computeLegend(mChart.getData(), mChart.getLegend()); - - mChart.calculateLegendOffsets(); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 79d6e4e706..db4cbba444 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -7,7 +7,6 @@ import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.PointF; import android.util.AttributeSet; @@ -208,7 +207,7 @@ protected void onDraw(Canvas canvas) { mRenderer.drawValues(mDrawCanvas); mLegendRenderer.renderLegend(mDrawCanvas, mLegend); -// drawLegend(); + // drawLegend(); drawMarkers(); @@ -258,7 +257,7 @@ public void notifyDataSetChanged() { mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); mLegend = mLegendRenderer.computeLegend(mData, mLegend); -// prepareLegend(); + // prepareLegend(); calculateOffsets(); } @@ -306,7 +305,7 @@ protected void calcMinMax() { @Override protected void calculateOffsets() { - float legendRight = 0f, legendBottom = 0f; + float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; // setup offsets for legend if (mLegend != null && mLegend.isEnabled()) { @@ -314,31 +313,16 @@ protected void calculateOffsets() { if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(12f); - - legendRight = mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint()) - + mLegend.getFormSize() + mLegend.getFormToTextSpace() + spacing; - - mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); + offsetRight += mLegend.mTextWidthMax; } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - if (mXAxis.getPosition() == XAxisPosition.TOP) - legendBottom = mLegendRenderer.getLabelPaint().getTextSize() * 3.5f; - else { - legendBottom = mLegendRenderer.getLabelPaint().getTextSize() * 2.5f; - } + offsetBottom += mLegend.mTextHeightMax * 3f; } - - mLegend.setOffsetBottom(legendBottom); - mLegend.setOffsetRight(legendRight); } - float yleft = 0f, yright = 0f; - // offsets for y-labels if (mAxisLeft.isEnabled()) { String label = mAxisLeft.getLongestLabel(); @@ -346,8 +330,8 @@ protected void calculateOffsets() { // calculate the maximum y-label width (including eventual // offsets) float ylabelwidth = Utils.calcTextWidth(mAxisRendererLeft.getAxisPaint(), - label + (mAxisLeft.mAxisMinimum < 0 ? "----" : "+++")); // offsets - yleft = ylabelwidth + mAxisRendererLeft.getXOffset() / 2f; + label + (mAxisLeft.mAxisMinimum < 0 ? "---" : "++")); // offsets + offsetLeft += ylabelwidth + mAxisRendererLeft.getXOffset() / 2f; } if (mAxisRight.isEnabled()) { @@ -356,12 +340,10 @@ protected void calculateOffsets() { // calculate the maximum y-label width (including eventual // offsets) float ylabelwidth = Utils.calcTextWidth(mAxisRendererRight.getAxisPaint(), - label + (mAxisLeft.mAxisMinimum < 0 ? "----" : "+++")); // offsets - yright = ylabelwidth + mAxisRendererRight.getXOffset() / 2f; + label + (mAxisLeft.mAxisMinimum < 0 ? "---" : "++")); // offsets + offsetRight += ylabelwidth + mAxisRendererRight.getXOffset() / 2f; } - float xtop = 0f, xbottom = 0f; - float xlabelheight = Utils.calcTextHeight(mXAxisRenderer.getAxisPaint(), "Q") * 2f; if (mXAxis.isEnabled()) { @@ -369,37 +351,24 @@ protected void calculateOffsets() { // offsets for x-labels if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - xbottom = xlabelheight; + offsetBottom += xlabelheight; } else if (mXAxis.getPosition() == XAxisPosition.TOP) { - xtop = xlabelheight; + offsetTop += xlabelheight; } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { - xbottom = xlabelheight; - xtop = xlabelheight; + offsetBottom += xlabelheight; + offsetTop += xlabelheight; } } - // all required offsets are calculated, now find largest and apply - float min = Utils.convertDpToPixel(11f); + float min = Utils.convertDpToPixel(10f); - float offsetBottom = Math.max(min, xbottom + legendBottom); - float offsetTop = Math.max(min, xtop); + mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), + Math.max(min, offsetRight), Math.max(min, offsetBottom)); - float offsetLeft = Math.max(min, yleft); - float offsetRight = Math.max(min, yright + legendRight); - - if (mLegend != null) { - - // those offsets are equal for legend and other chart, just apply - // them - mLegend.setOffsetTop(offsetTop + min / 3f); - mLegend.setOffsetLeft(offsetLeft); - } - - mViewPortHandler.restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom); if (mLogEnabled) { Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); @@ -410,30 +379,6 @@ protected void calculateOffsets() { prepareValuePxMatrix(); } - /** - * Calculates the offsets that belong to the legend, this method is only - * relevant when drawing into the chart. It can be used to refresh the - * legend. - */ - public void calculateLegendOffsets() { - - // setup offsets for legend - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { - - mLegend.setOffsetRight(mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint())); - mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); - - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT) { - - if (mXAxis.getPosition() == XAxisPosition.TOP) - mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 3.5f); - else { - mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 2.5f); - } - } - } - /** * calculates the modulus for x-labels and grid */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 6803838423..eacb26d97c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -146,17 +146,10 @@ protected void calculateOffsets() { legendRight += getRequiredBaseOffset(); legendTop += getRequiredBaseOffset(); - - mLegend.setOffsetBottom(mLegendRenderer.getLabelPaint().getTextSize() * 4f); - mLegend.setOffsetRight(legendRight); } float min = Utils.convertDpToPixel(11f); - if (mLegend != null) { - mLegend.setOffsetLeft(min); - } - float offsetLeft = Math.max(min, getRequiredBaseOffset()); float offsetTop = Math.max(min, legendTop); float offsetRight = Math.max(min, legendRight); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 79b891de95..27a52b9f73 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -25,11 +25,7 @@ public enum LegendPosition { public enum LegendForm { SQUARE, CIRCLE, LINE } - - /** offsets for the legend */ - private float mLegendOffsetBottom = 12f, mLegendOffsetRight = 12f, mLegendOffsetLeft = 12f, - mLegendOffsetTop = 12f; - + /** flag indicating if the legend should be drawn or not */ private boolean mEnabled = true; @@ -77,9 +73,6 @@ public enum LegendForm { /** the space that should be left between stacked forms */ private float mStackSpace = 3f; - public float mTextHeight = 0f; - public float mTextWidth = 0f; - /** default constructor */ public Legend() { @@ -387,78 +380,6 @@ public void apply(Legend l) { // mLegendOffsetTop = l.mLegendOffsetTop; } - /** - * returns the bottom offset - * - * @return - */ - public float getOffsetBottom() { - return mLegendOffsetBottom; - } - - /** - * returns the right offset - * - * @return - */ - public float getOffsetRight() { - return mLegendOffsetRight; - } - - /** - * sets the bottom offset - * - * @param off - */ - public void setOffsetBottom(float off) { - mLegendOffsetBottom = off; - } - - /** - * sets the right offset - * - * @param off - */ - public void setOffsetRight(float off) { - mLegendOffsetRight = off; - } - - /** - * returns the bottom offset - * - * @return - */ - public float getOffsetTop() { - return mLegendOffsetTop; - } - - /** - * returns the left offset - * - * @return - */ - public float getOffsetLeft() { - return mLegendOffsetLeft; - } - - /** - * sets the bottom offset - * - * @param off - */ - public void setOffsetTop(float off) { - mLegendOffsetTop = off; - } - - /** - * sets the left offset - * - * @param off - */ - public void setOffsetLeft(float off) { - mLegendOffsetLeft = off; - } - /** * sets the text size of the legend labels, default 9f * @@ -546,6 +467,42 @@ public float getFullHeight(Paint labelpaint) { return height; } + /** the total width of the legend (needed width space) */ + public float mNeededWidth = 0f; + + /** the total height of the legend (needed height space) */ + public float mNeededHeight = 0f; + + public float mTextHeightMax = 0f; + + public float mTextWidthMax = 0f; + + /** + * Calculates the dimensions of the Legend. This includes the maximum width + * and height of a single entry, as well as the total width and height of + * the Legend. + * + * @param labelpaint + */ + public void calculateDimensions(Paint labelpaint) { + + if (mPosition == LegendPosition.RIGHT_OF_CHART + || mPosition == LegendPosition.RIGHT_OF_CHART_CENTER + || mPosition == LegendPosition.PIECHART_CENTER) { + mNeededWidth = getMaximumEntryWidth(labelpaint); + mNeededHeight = getFullHeight(labelpaint); + mTextWidthMax = mNeededWidth; + mTextHeightMax = getMaximumEntryHeight(labelpaint); + + } else { + + mNeededWidth = getFullWidth(labelpaint); + mNeededHeight = getMaximumEntryHeight(labelpaint); + mTextWidthMax = getMaximumEntryWidth(labelpaint); + mTextHeightMax = mNeededHeight; + } + } + /** * Sets the text color to use for the legend labels. Make sure to use * getResources().getColor(...) when using a color from the resources. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index bfc0d91df0..c3bad69fd7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; +import android.graphics.Paint.Align; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.data.BarDataSet; @@ -28,6 +29,7 @@ public LegendRenderer(ViewPortHandler viewPortHandler) { mLegendLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLegendLabelPaint.setTextSize(Utils.convertDpToPixel(9f)); + mLegendLabelPaint.setTextAlign(Align.LEFT); mLegendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLegendFormPaint.setStyle(Paint.Style.FILL); @@ -126,6 +128,17 @@ public Legend computeLegend(ChartData data, Legend legend) { // apply the old legend settings to a potential new legend l.apply(legend); } + + Typeface tf = l.getTypeface(); + + if (tf != null) + mLegendLabelPaint.setTypeface(tf); + + mLegendLabelPaint.setTextSize(l.getTextSize()); + mLegendLabelPaint.setColor(l.getTextColor()); + + // calculate all dimensions of the legend + l.calculateDimensions(mLegendLabelPaint); return l; } @@ -134,8 +147,7 @@ public void renderLegend(Canvas c, Legend legend) { if (legend == null || !legend.isEnabled()) return; - - String[] labels = legend.getLegendLabels(); + Typeface tf = legend.getTypeface(); if (tf != null) @@ -144,8 +156,7 @@ public void renderLegend(Canvas c, Legend legend) { mLegendLabelPaint.setTextSize(legend.getTextSize()); mLegendLabelPaint.setColor(legend.getTextColor()); - legend.mTextWidth = legend.getMaximumEntryWidth(mLegendLabelPaint); - legend.mTextHeight = legend.getMaximumEntryHeight(mLegendLabelPaint); + String[] labels = legend.getLegendLabels(); float formSize = legend.getFormSize(); @@ -171,13 +182,13 @@ public void renderLegend(Canvas c, Legend legend) { switch (legend.getPosition()) { case BELOW_CHART_LEFT: - + posX = mViewPortHandler.contentLeft(); posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = 0; i < labels.length; i++) { - drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); + drawForm(c, posX, posY - legend.mTextHeightMax / 2f, i, legend); // grouped forms have null labels if (labels[i] != null) { @@ -213,13 +224,13 @@ public void renderLegend(Canvas c, Legend legend) { posX -= stackSpace + formSize; } - drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); + drawForm(c, posX, posY - legend.mTextHeightMax / 2f, i, legend); } break; case RIGHT_OF_CHART: - posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; + posX = mViewPortHandler.getChartWidth() - legend.mTextWidthMax - xoffset; posY = mViewPortHandler.contentTop() + yoffset; for (int i = 0; i < labels.length; i++) { @@ -235,12 +246,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); + drawLabel(c, x, posY + legend.mTextHeightMax / 2f, legend.getLabel(i)); posY += textDrop; } else { - posY += legend.mTextHeight * 3f; - drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); + posY += legend.mTextHeightMax * 3f; + drawLabel(c, posX, posY - legend.mTextHeightMax, legend.getLabel(i)); } // make a step down @@ -253,9 +264,8 @@ public void renderLegend(Canvas c, Legend legend) { } break; case RIGHT_OF_CHART_CENTER: - posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; - posY = mViewPortHandler.getChartHeight() / 2f - - legend.getFullHeight(mLegendLabelPaint) / 2f; + posX = mViewPortHandler.getChartWidth() - legend.mTextWidthMax - xoffset; + posY = mViewPortHandler.getChartHeight() / 2f - legend.mNeededHeight / 2f; for (int i = 0; i < labels.length; i++) { @@ -270,12 +280,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); + drawLabel(c, x, posY + legend.mTextHeightMax / 2f, legend.getLabel(i)); posY += textDrop; } else { - posY += legend.mTextHeight * 3f; - drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); + posY += legend.mTextHeightMax * 3f; + drawLabel(c, posX, posY - legend.mTextHeightMax, legend.getLabel(i)); } // make a step down @@ -290,14 +300,12 @@ public void renderLegend(Canvas c, Legend legend) { break; case BELOW_CHART_CENTER: - float fullSize = legend.getFullWidth(mLegendLabelPaint); - - posX = mViewPortHandler.getChartWidth() / 2f - fullSize / 2f; + posX = mViewPortHandler.getChartWidth() / 2f - legend.mNeededWidth / 2f; posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = 0; i < labels.length; i++) { - drawForm(c, posX, posY - legend.mTextHeight / 2f, i, legend); + drawForm(c, posX, posY - legend.mTextHeightMax / 2f, i, legend); // grouped forms have null labels if (labels[i] != null) { @@ -317,9 +325,8 @@ public void renderLegend(Canvas c, Legend legend) { break; case PIECHART_CENTER: - posX = mViewPortHandler.getChartWidth() / 2f - legend.mTextWidth / 2f; - posY = mViewPortHandler.getChartHeight() / 2f - - legend.getFullHeight(mLegendLabelPaint) / 2f; + posX = mViewPortHandler.getChartWidth() / 2f - legend.mTextWidthMax / 2f; + posY = mViewPortHandler.getChartHeight() / 2f - legend.mNeededHeight / 2f; for (int i = 0; i < labels.length; i++) { @@ -334,12 +341,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); + drawLabel(c, x, posY + legend.mTextHeightMax / 2f, legend.getLabel(i)); posY += textDrop; } else { - posY += legend.mTextHeight * 3f; - drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); + posY += legend.mTextHeightMax * 3f; + drawLabel(c, posX, posY - legend.mTextHeightMax, legend.getLabel(i)); } // make a step down @@ -354,7 +361,7 @@ public void renderLegend(Canvas c, Legend legend) { break; case RIGHT_OF_CHART_INSIDE: - posX = mViewPortHandler.getChartWidth() - legend.mTextWidth - xoffset; + posX = mViewPortHandler.getChartWidth() - legend.mTextWidthMax - xoffset; posY = mViewPortHandler.contentTop() + yoffset; for (int i = 0; i < labels.length; i++) { @@ -370,12 +377,12 @@ public void renderLegend(Canvas c, Legend legend) { if (legend.getColors()[i] != -2) x += formTextSpaceAndForm; - drawLabel(c, x, posY + legend.mTextHeight / 2f, legend.getLabel(i)); + drawLabel(c, x, posY + legend.mTextHeightMax / 2f, legend.getLabel(i)); posY += textDrop; } else { - posY += legend.mTextHeight * 3f; - drawLabel(c, posX, posY - legend.mTextHeight, legend.getLabel(i)); + posY += legend.mTextHeightMax * 3f; + drawLabel(c, posX, posY - legend.mTextHeightMax, legend.getLabel(i)); } // make a step down From 918a91869f987fa7cad28c626b9f3e4f3998b2c7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 23 Feb 2015 01:43:14 +0100 Subject: [PATCH 0108/1390] Worked on offset calculation for pie- and radarchart. --- .../mikephil/charting/charts/PieChart.java | 25 ++--------- .../charting/charts/PieRadarChartBase.java | 43 ++++++++++--------- 2 files changed, 26 insertions(+), 42 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 0cd2fa41c8..33561668f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -3,12 +3,14 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; +import android.graphics.Paint.Style; import android.util.AttributeSet; import com.github.mikephil.charting.data.DataSet; @@ -106,7 +108,7 @@ protected void onDraw(Canvas canvas) { mLegendRenderer.renderLegend(mDrawCanvas, mLegend); drawDescription(); - + canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } @@ -128,26 +130,7 @@ protected void calculateOffsets() { mCircleBox.set(c.x - boxSize, c.y - boxSize, c.x + boxSize, c.y + boxSize); } - - // @Override - // protected void prepareContentRect() { - // super.prepareContentRect(); - // - // // prevent nullpointer when no data set - // if (mDataNotSet) - // return; - // - // float diameter = getDiameter(); - // float boxSize = diameter / 2f; - // - // PointF c = getCenterOffsets(); - // - // // create the circle box that will contain the pie-chart (the bounds of - // // the pie-chart) - // mCircleBox.set(c.x - boxSize, c.y - boxSize, - // c.x + boxSize, c.y + boxSize); - // } - + @Override protected void calcMinMax() { super.calcMinMax(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index eacb26d97c..13d0d9093e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -6,7 +6,9 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.Paint.Align; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Paint.Style; import android.graphics.PointF; import android.graphics.RectF; import android.support.v4.view.ViewCompat; @@ -87,6 +89,9 @@ public void notifyDataSetChanged() { calculateOffsets(); } + PointF ref; + PointF bot; + @Override protected void calculateOffsets() { @@ -101,42 +106,39 @@ protected void calculateOffsets() { legendRight = getFullLegendWidth() + spacing; - mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); - // legendTop = mLegend.getFullHeight(mLegendLabelPaint); - } else if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(13f); + float spacing = Utils.convertDpToPixel(8f); float legendWidth = getFullLegendWidth() + spacing; - float legendHeight = mLegend.getFullHeight(mLegendRenderer.getLabelPaint());// + - // mOffsetTop; + float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax; PointF c = getCenter(); - PointF bottomRight = new PointF(getWidth() - legendWidth, legendHeight); - PointF reference = getPosition(c, getRadius(), 320); - + PointF bottomRight = new PointF(getWidth() - legendWidth + 15, legendHeight + 15); float distLegend = distanceToCenter(bottomRight.x, bottomRight.y); + + PointF reference = getPosition(c, getRadius(), + getAngleForPoint(bottomRight.x, bottomRight.y)); + + ref = reference; + bot = bottomRight; + float distReference = distanceToCenter(reference.x, reference.y); float min = Utils.convertDpToPixel(5f); if (distLegend < distReference) { float diff = distReference - distLegend; - legendRight = min + diff; - legendTop = min + diff; } - if (bottomRight.y >= c.y) { + if (bottomRight.y >= c.y && getHeight() - legendWidth > getWidth()) { legendRight = legendWidth; } - mLegendRenderer.getLabelPaint().setTextAlign(Align.LEFT); - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { @@ -148,7 +150,7 @@ protected void calculateOffsets() { legendTop += getRequiredBaseOffset(); } - float min = Utils.convertDpToPixel(11f); + float min = Utils.convertDpToPixel(10f); float offsetLeft = Math.max(min, getRequiredBaseOffset()); float offsetTop = Math.max(min, legendTop); @@ -390,8 +392,7 @@ public float getDiameter() { * @return */ private float getFullLegendWidth() { - return mLegend.getMaximumEntryWidth(mLegendRenderer.getLabelPaint()) - + mLegend.getFormSize() + mLegend.getFormToTextSpace(); + return mLegend.mTextWidthMax + mLegend.getFormSize() + mLegend.getFormToTextSpace(); } /** @@ -468,11 +469,11 @@ public void spin(int durationmillis, float fromangle, float toangle) { mSpinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); mSpinAnimator.setDuration(durationmillis); - + final ViewGroup view = this; - + mSpinAnimator.addUpdateListener(new AnimatorUpdateListener() { - + @Override public void onAnimationUpdate(ValueAnimator animation) { ViewCompat.postInvalidateOnAnimation(view); From ae2b97bb530027224c1da0b6d792cbf67d334486 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 23 Feb 2015 09:49:52 +0100 Subject: [PATCH 0109/1390] Further improved offset calculation. --- .../charting/charts/BarLineChartBase.java | 18 ++--------- .../mikephil/charting/components/YAxis.java | 30 +++++++++++++++++++ .../charting/renderer/YAxisRenderer.java | 22 +------------- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index db4cbba444..f258896e7e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -325,26 +325,14 @@ protected void calculateOffsets() { // offsets for y-labels if (mAxisLeft.isEnabled()) { - String label = mAxisLeft.getLongestLabel(); - - // calculate the maximum y-label width (including eventual - // offsets) - float ylabelwidth = Utils.calcTextWidth(mAxisRendererLeft.getAxisPaint(), - label + (mAxisLeft.mAxisMinimum < 0 ? "---" : "++")); // offsets - offsetLeft += ylabelwidth + mAxisRendererLeft.getXOffset() / 2f; + offsetLeft += mAxisLeft.getRequiredWidthSpace(mAxisRendererLeft.getAxisPaint()); } if (mAxisRight.isEnabled()) { - String label = mAxisRight.getLongestLabel(); - - // calculate the maximum y-label width (including eventual - // offsets) - float ylabelwidth = Utils.calcTextWidth(mAxisRendererRight.getAxisPaint(), - label + (mAxisLeft.mAxisMinimum < 0 ? "---" : "++")); // offsets - offsetRight += ylabelwidth + mAxisRendererRight.getXOffset() / 2f; + offsetRight += mAxisRight.getRequiredWidthSpace(mAxisRendererRight.getAxisPaint()); } - float xlabelheight = Utils.calcTextHeight(mXAxisRenderer.getAxisPaint(), "Q") * 2f; + float xlabelheight = mXAxis.mLabelHeight * 2f; if (mXAxis.isEnabled()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 6a8a2e6f73..1e1f432660 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.components; +import android.graphics.Paint; + import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; @@ -73,6 +75,9 @@ public class YAxis extends AxisBase { /** the total range of values this axis covers */ public float mAxisRange = 0f; + /** the offset in pixels this axis has on the x-axis */ + protected float mXOffset = 5f; + /** the position of the y-labels relative to the chart */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; @@ -91,6 +96,7 @@ public enum AxisDependency { public YAxis(AxisDependency position) { this.mAxisDependency = position; this.mLimitLines = new ArrayList(); + this.mXOffset = Utils.convertDpToPixel(5f); } public AxisDependency getAxisDependency() { @@ -367,6 +373,11 @@ public float getSpaceBottom() { return mSpacePercentBottom; } + public float getRequiredWidthSpace(Paint p) { + String label = getLongestLabel(); + return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + } + /** * Returns the longest formatted label (in terms of characters) the y-labels * contain. @@ -410,4 +421,23 @@ public String getFormattedLabel(int index) { return text; } + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getXOffset() { + return mXOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setXOffset(float xOffset) { + mXOffset = Utils.convertDpToPixel(xOffset); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 555f8ae08c..095346e9a3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -24,8 +24,6 @@ public class YAxisRenderer extends AxisRenderer { protected YAxis mYAxis; - protected float mXOffset = 5f; - public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { super(viewPortHandler, trans); @@ -38,24 +36,6 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mLimitLinePaint.setStyle(Paint.Style.FILL_AND_STROKE); } - /** - * Returns the used offset on the x-axis for drawing the axis labels. - * - * @return - */ - public float getXOffset() { - return Utils.convertDpToPixel(mXOffset); - } - - /** - * Sets the used offset for the labels on the x-axis. - * - * @param xOffset - */ - public void setXOffset(float xOffset) { - mXOffset = xOffset; - } - /** * Computes the axis values. * @@ -183,7 +163,7 @@ public void renderAxis(Canvas c) { mAxisPaint.setTextSize(mYAxis.getTextSize()); mAxisPaint.setColor(mYAxis.getTextColor()); - float xoffset = getXOffset(); + float xoffset = mYAxis.getXOffset(); float yoffset = Utils.calcTextHeight(mAxisPaint, "A") / 2.5f; AxisDependency dependency = mYAxis.getAxisDependency(); From d386512b9c89c4d0ea1a5afeaffc5d98f69b78bd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 23 Feb 2015 11:17:47 +0100 Subject: [PATCH 0110/1390] Worked on HorizontalBarChart value drawing and offset calculation. --- .../charting/charts/HorizontalBarChart.java | 69 +++++++++++++++++++ .../charting/components/AxisBase.java | 56 ++++++++++++++- .../mikephil/charting/components/XAxis.java | 19 +++++ .../mikephil/charting/components/YAxis.java | 36 ++-------- .../charting/renderer/BarChartRenderer.java | 10 ++- .../renderer/HorizontalBarChartRenderer.java | 24 +++++++ .../XAxisRendererHorizontalBarChart.java | 16 ++++- .../mikephil/charting/utils/Transformer.java | 34 +++++++++ 8 files changed, 230 insertions(+), 34 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index e7c7c53b99..a5f30e0d52 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -4,10 +4,14 @@ import android.content.Context; import android.graphics.Matrix; import android.util.AttributeSet; +import android.util.Log; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; +import com.github.mikephil.charting.utils.Utils; /** * BarChart with horizontal bar orientation. In this implementation, x- and @@ -42,6 +46,71 @@ protected void init() { mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); } + + @Override + protected void calculateOffsets() { + + float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; + + // setup offsets for legend + if (mLegend != null && mLegend.isEnabled()) { + + if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART + || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { + + offsetRight += mLegend.mTextWidthMax; + + } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + + offsetBottom += mLegend.mTextHeightMax * 3f; + } + } + + // offsets for y-labels + if (mAxisLeft.isEnabled()) { + offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getAxisPaint()); + } + + if (mAxisRight.isEnabled()) { + offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getAxisPaint()); + } + + float xlabelwidth = mXAxis.mLabelWidth; + + if (mXAxis.isEnabled()) { + + // offsets for x-labels + if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + + offsetLeft += xlabelwidth; + + } else if (mXAxis.getPosition() == XAxisPosition.TOP) { + + offsetRight += xlabelwidth; + + } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + + offsetLeft += xlabelwidth; + offsetRight += xlabelwidth; + } + } + + float min = Utils.convertDpToPixel(10f); + + mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), + Math.max(min, offsetRight), Math.max(min, offsetBottom)); + + if (mLogEnabled) { + Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); + Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); + } + + prepareOffsetMatrix(); + prepareValuePxMatrix(); + } @Override protected void prepareValuePxMatrix() { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 85dbde0d60..bf21b8b621 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -36,10 +36,18 @@ public abstract class AxisBase { /** flag that indicates if the line alongside the axis is drawn or not */ protected boolean mDrawAxisLine = false; + + /** the offset in pixels this axis labels have on the x-axis */ + protected float mXOffset = 5f; + + /** the offset in pixels this axis labels have on the Y-axis */ + protected float mYOffset = 5f; /** default constructor */ public AxisBase() { - mTextSize = Utils.convertDpToPixel(10f); + this.mTextSize = Utils.convertDpToPixel(10f); + this.mXOffset = Utils.convertDpToPixel(5f); + this.mYOffset = Utils.convertDpToPixel(5f); } /** @@ -213,4 +221,50 @@ public void setEnabled(boolean enabled) { public boolean isEnabled() { return mEnabled; } + + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getXOffset() { + return mXOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setXOffset(float xOffset) { + mXOffset = Utils.convertDpToPixel(xOffset); + } + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getYOffset() { + return mYOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setYOffset(float yOffset) { + mYOffset = Utils.convertDpToPixel(yOffset); + } + + /** + * Returns the longest formatted label (in terms of characters), this axis contains. + * + * @return + */ + public abstract String getLongestLabel(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index ed898f09c9..55b3426d8c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -66,6 +66,10 @@ public class XAxis extends AxisBase { public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } + + public XAxis() { + super(); + } /** * if set to true, the x-label entries will adjust themselves when scaling @@ -159,4 +163,19 @@ public void setValues(ArrayList values) { public ArrayList getValues() { return mValues; } + + @Override + public String getLongestLabel() { + + String longest = ""; + + for (int i = 0; i < mValues.size(); i++) { + String text = mValues.get(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 1e1f432660..71d4333dbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -75,9 +75,6 @@ public class YAxis extends AxisBase { /** the total range of values this axis covers */ public float mAxisRange = 0f; - /** the offset in pixels this axis has on the x-axis */ - protected float mXOffset = 5f; - /** the position of the y-labels relative to the chart */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; @@ -94,9 +91,9 @@ public enum AxisDependency { } public YAxis(AxisDependency position) { + super(); this.mAxisDependency = position; this.mLimitLines = new ArrayList(); - this.mXOffset = Utils.convertDpToPixel(5f); } public AxisDependency getAxisDependency() { @@ -377,13 +374,13 @@ public float getRequiredWidthSpace(Paint p) { String label = getLongestLabel(); return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; } + + public float getRequiredHeightSpace(Paint p) { + String label = getLongestLabel(); + return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; + } - /** - * Returns the longest formatted label (in terms of characters) the y-labels - * contain. - * - * @return - */ + @Override public String getLongestLabel() { String longest = ""; @@ -421,23 +418,4 @@ public String getFormattedLabel(int index) { return text; } - - /** - * Returns the used offset on the x-axis for drawing the axis labels. This - * offset is applied before and after the label. - * - * @return - */ - public float getXOffset() { - return mXOffset; - } - - /** - * Sets the used x-axis offset for the labels on this axis. - * - * @param xOffset - */ - public void setXOffset(float xOffset) { - mXOffset = Utils.convertDpToPixel(xOffset); - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index ed84402573..45df2e30d5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -210,9 +210,7 @@ public void drawValues(Canvas c) { ArrayList entries = dataSet.getYVals(); - float[] valuePoints = trans.generateTransformedValuesBarChart(entries, i, - mChart.getBarData(), - mAnimator.getPhaseY()); + float[] valuePoints = getTransformedValues(trans, entries, i); // if only single values are drawn (sum) if (!mChart.isDrawValuesForWholeStackEnabled()) { @@ -362,4 +360,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } } + + public float[] getTransformedValues(Transformer trans, ArrayList entries, int dataSetIndex) { + return trans.generateTransformedValuesBarChart(entries, dataSetIndex, + mChart.getBarData(), + mAnimator.getPhaseY()); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 27839a8075..76c5879eee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -1,9 +1,16 @@ package com.github.mikephil.charting.renderer; +import android.graphics.Canvas; +import android.graphics.Paint.Align; + import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; /** * Renderer for the HorizontalBarChart. @@ -11,10 +18,17 @@ * @author Philipp Jahoda */ public class HorizontalBarChartRenderer extends BarChartRenderer { + + private float xOffset = 0f; + private float yOffset = 0f; public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(chart, animator, viewPortHandler); + + mValuePaint.setTextAlign(Align.LEFT); + yOffset = Utils.calcTextHeight(mValuePaint, "Q"); + xOffset = Utils.convertDpToPixel(4f); } @Override @@ -38,4 +52,14 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { mBarRect.bottom); } } + + @Override + public float[] getTransformedValues(Transformer trans, ArrayList entries, int dataSetIndex) { + return trans.generateTransformedValuesHorizontalBarChart(entries, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); + } + + @Override + protected void drawValue(Canvas c, float val, float xPos, float yPos) { + super.drawValue(c, val, xPos + xOffset, yPos + yOffset); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 636e3f358b..af057ffef8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -11,12 +11,26 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; + public class XAxisRendererHorizontalBarChart extends XAxisRendererBarChart { public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, BarChart chart) { super(viewPortHandler, xAxis, trans, chart); } + + @Override + public void computeAxis(float xValAverageLength, ArrayList xValues) { + + mAxisPaint.setTypeface(mXAxis.getTypeface()); + mAxisPaint.setTextSize(mXAxis.getTextSize()); + mXAxis.setValues(xValues); + + String longest = mXAxis.getLongestLabel(); + mXAxis.mLabelWidth = (int) (Utils.calcTextWidth(mAxisPaint, longest) + mXAxis.getXOffset() * 3.5f); + mXAxis.mLabelHeight = Utils.calcTextHeight(mAxisPaint, longest); + } @Override public void renderAxis(Canvas c) { @@ -24,7 +38,7 @@ public void renderAxis(Canvas c) { if (!mXAxis.isEnabled()) return; - float xoffset = Utils.convertDpToPixel(4f); + float xoffset = mXAxis.getXOffset(); mAxisPaint.setTypeface(mXAxis.getTypeface()); mAxisPaint.setTextSize(mXAxis.getTextSize()); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 9e66e5afb6..192f510aa6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -208,6 +208,40 @@ public float[] generateTransformedValuesBarChart(ArrayList entr return valuePoints; } + + /** + * Transforms an arraylist of Entry into a float array containing the x and + * y values transformed with all matrices for the BARCHART. + * + * @param entries + * @param dataSet the dataset index + * @return + */ + public float[] generateTransformedValuesHorizontalBarChart(ArrayList entries, + int dataSet, BarData bd, float phaseY) { + + float[] valuePoints = new float[entries.size() * 2]; + + int setCount = bd.getDataSetCount(); + float space = bd.getGroupSpace(); + + for (int j = 0; j < valuePoints.length; j += 2) { + + Entry e = entries.get(j / 2); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + space * (j / 2) + + space / 2f ; + float y = e.getVal(); + + valuePoints[j] = y * phaseY; + valuePoints[j + 1] = x; + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } /** * transform a path with all the given matrices VERY IMPORTANT: keep order From 865d5f33ec192359764de433c37a942055017ae6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 23 Feb 2015 12:40:25 +0100 Subject: [PATCH 0111/1390] More improvements concerning offset calculation. --- .../CandleStickChartActivity.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 28 ++++++---- .../listviewitems/BarChartItem.java | 1 + .../listviewitems/LineChartItem.java | 9 +-- .../charting/charts/BarLineChartBase.java | 2 +- .../charting/charts/HorizontalBarChart.java | 2 +- .../charting/charts/ScatterChart.java | 3 + .../charting/components/AxisBase.java | 3 +- .../mikephil/charting/components/Legend.java | 56 ++++++++++++++++--- .../charting/renderer/LegendRenderer.java | 4 +- .../YAxisRendererHorizontalBarChart.java | 2 +- 11 files changed, 83 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 25655fe0e7..0753f983ae 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -64,7 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yLabels = mChart.getAxisLeft(); yLabels.setLabelCount(7); yLabels.setDrawGridLines(false); -// yLabels.setPosition(YLabelPosition.LEFT); + yLabels.setDrawAxisLine(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 99d88b523c..dfa7c33749 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -6,8 +6,9 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.CombinedChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -42,13 +43,19 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setDrawGridLines(false); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTH_SIDED); CombinedData data = new CombinedData(mMonths); data.setData(generateLineData()); data.setData(generateBarData()); // data.setData(generateScatterData()); - data.setData(generateCandleData()); +// data.setData(generateCandleData()); mChart.setData(data); mChart.invalidate(); @@ -61,14 +68,14 @@ private LineData generateLineData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(), index)); + entries.add(new Entry(getRandom(15, 10), index)); LineDataSet set = new LineDataSet(entries, "Line DataSet"); - set.setColor(Color.RED); + set.setColor(Color.rgb(240, 238, 70)); set.setLineWidth(2.5f); - set.setCircleColor(Color.RED); + set.setCircleColor(Color.rgb(240, 238, 70)); set.setCircleSize(5f); - set.setFillColor(Color.RED); + set.setFillColor(Color.rgb(240, 238, 70)); set.setDrawCubic(true); set.setDrawValues(false); d.addDataSet(set); @@ -83,9 +90,10 @@ private BarData generateBarData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(getRandom(), index)); + entries.add(new BarEntry(getRandom(15, 30), index)); BarDataSet set = new BarDataSet(entries, "Bar DataSet"); + set.setColor(Color.rgb(60, 220, 78)); d.addDataSet(set); return d; @@ -98,7 +106,7 @@ private ScatterData generateScatterData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(), index)); + entries.add(new Entry(getRandom(20, 30), index)); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); set.setColor(Color.GREEN); @@ -127,7 +135,7 @@ private CandleData generateCandleData() { return d; } - private float getRandom() { - return (float) (Math.random() * 20f) + 25f; + private float getRandom(float range, float startsfrom) { + return (float) (Math.random() * range) + startsfrom; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index f7e55255ce..da7e3805d3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -57,6 +57,7 @@ public View getView(int position, View convertView, Context c) { xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); + xAxis.setDrawAxisLine(true); YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 1b0f87b207..16346251dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -53,10 +53,11 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDescription(""); holder.chart.setDrawGridBackground(false); - XAxis xl = holder.chart.getXAxis(); - xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(mTf); - xl.setDrawGridLines(false); + XAxis xAxis = holder.chart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setTypeface(mTf); + xAxis.setDrawGridLines(false); + xAxis.setDrawAxisLine(true); YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index f258896e7e..89955730bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -313,7 +313,7 @@ protected void calculateOffsets() { if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - offsetRight += mLegend.mTextWidthMax; + offsetRight += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f; } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index a5f30e0d52..2e69fecdc0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -58,7 +58,7 @@ protected void calculateOffsets() { if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - offsetRight += mLegend.mTextWidthMax; + offsetRight += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f; } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index ec04d59184..0f5140cf9a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -59,6 +59,9 @@ protected void calcMinMax() { if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; + + mXChartMax += 0.5f; + mDeltaX = Math.abs(mXChartMax - mXChartMin); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index bf21b8b621..5a82dd4523 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -35,7 +35,7 @@ public abstract class AxisBase { protected boolean mDrawGridLines = true; /** flag that indicates if the line alongside the axis is drawn or not */ - protected boolean mDrawAxisLine = false; + protected boolean mDrawAxisLine = true; /** the offset in pixels this axis labels have on the x-axis */ protected float mXOffset = 5f; @@ -222,7 +222,6 @@ public boolean isEnabled() { return mEnabled; } - /** * Returns the used offset on the x-axis for drawing the axis labels. This * offset is applied before and after the label. diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 27a52b9f73..280365c980 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -71,7 +71,13 @@ public enum LegendForm { private float mFormToTextSpace = 5f; /** the space that should be left between stacked forms */ - private float mStackSpace = 3f; + private float mStackSpace = 3f; + + /** the offset in pixels this axis labels have on the x-axis */ + protected float mXOffset = 5f; + + /** the offset in pixels this axis labels have on the Y-axis */ + protected float mYOffset = 6f; /** default constructor */ public Legend() { @@ -82,6 +88,8 @@ public Legend() { mFormToTextSpace = Utils.convertDpToPixel(5f); mTextSize = Utils.convertDpToPixel(10f); mStackSpace = Utils.convertDpToPixel(3f); + this.mXOffset = Utils.convertDpToPixel(5f); + this.mYOffset = Utils.convertDpToPixel(6f); } /** @@ -372,12 +380,8 @@ public void apply(Legend l) { mStackSpace = l.mStackSpace; mTextColor = l.mTextColor; mEnabled = l.mEnabled; - // - // // apply offsets - // mLegendOffsetBottom = l.mLegendOffsetBottom; - // mLegendOffsetLeft = l.mLegendOffsetLeft; - // mLegendOffsetRight = l.mLegendOffsetRight; - // mLegendOffsetTop = l.mLegendOffsetTop; + mXOffset = l.mXOffset; + mYOffset = l.mYOffset; } /** @@ -540,4 +544,42 @@ public void setEnabled(boolean enabled) { public boolean isEnabled() { return mEnabled; } + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getXOffset() { + return mXOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setXOffset(float xOffset) { + mXOffset = Utils.convertDpToPixel(xOffset); + } + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getYOffset() { + return mYOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setYOffset(float yOffset) { + mYOffset = Utils.convertDpToPixel(yOffset); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index c3bad69fd7..f80fd0d629 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -177,8 +177,8 @@ public void renderLegend(Canvas c, Legend legend) { boolean wasStacked = false; - float yoffset = Utils.convertDpToPixel(4f); - float xoffset = Utils.convertDpToPixel(3f); + float yoffset = legend.getYOffset(); + float xoffset = legend.getXOffset(); switch (legend.getPosition()) { case BELOW_CHART_LEFT: diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 36cf3fbe58..774ae379c1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -76,7 +76,7 @@ public void renderAxis(Canvas c) { mAxisPaint.setColor(mYAxis.getTextColor()); mAxisPaint.setTextAlign(Align.CENTER); - float yoffset = Utils.calcTextHeight(mAxisPaint, "A") * 1.3f; + float yoffset = Utils.calcTextHeight(mAxisPaint, "A") + mYAxis.getYOffset(); AxisDependency dependency = mYAxis.getAxisDependency(); YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); From 9b5e70fa0110344a4e01a04f30d7770d3c9b211a Mon Sep 17 00:00:00 2001 From: Maragues Date: Mon, 23 Feb 2015 18:12:35 +0100 Subject: [PATCH 0112/1390] Upgraded example build tools to 21.1.1. Now it matches the one used by the library --- MPChartExample/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index de136fa0ff..0e37b5497b 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 19 - buildToolsVersion '19.1.0' + buildToolsVersion '21.1.1' defaultConfig { minSdkVersion 16 targetSdkVersion 19 From 85e9795a751def3f95f4d25564f01cf6addd823e Mon Sep 17 00:00:00 2001 From: Maragues Date: Mon, 23 Feb 2015 18:15:47 +0100 Subject: [PATCH 0113/1390] Change Rendeder's access level modifiers for extra draw methods --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 +- .../github/mikephil/charting/renderer/PieChartRenderer.java | 4 ++-- .../github/mikephil/charting/renderer/RadarChartRenderer.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 12078b6dea..03f7944b22 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -357,7 +357,7 @@ public void drawExtras(Canvas c) { drawCircles(c); } - private void drawCircles(Canvas c) { + protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); ArrayList dataSets = mChart.getLineData().getDataSets(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 2522addfe2..c38d42c489 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -200,7 +200,7 @@ public void drawExtras(Canvas c) { * draws the hole in the center of the chart and the transparent circle / * hole */ - private void drawHole(Canvas c) { + protected void drawHole(Canvas c) { if (mChart.isDrawHoleEnabled()) { @@ -234,7 +234,7 @@ private void drawHole(Canvas c) { * draws the description text in the center of the pie chart makes most * sense when center-hole is enabled */ - private void drawCenterText(Canvas c) { + protected void drawCenterText(Canvas c) { String centerText = mChart.getCenterText(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 0ea66b20e8..f87efe664b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -141,7 +141,7 @@ public void drawExtras(Canvas c) { drawWeb(c); } - private void drawWeb(Canvas c) { + protected void drawWeb(Canvas c) { float sliceangle = mChart.getSliceAngle(); From bbfb6c6648da6385c56d3f2494408bc1bca53262 Mon Sep 17 00:00:00 2001 From: Gabriel Burca Date: Mon, 23 Feb 2015 17:27:38 -0600 Subject: [PATCH 0114/1390] Fixed null pointer exception in design view (issue #370) - In the Android Studio Preview mode, mData is null and throws an exception. --- .../src/com/github/mikephil/charting/charts/RadarChart.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 0f0d467597..a0a9865576 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -114,8 +114,10 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); - mYAxisRenderer.computeAxis(0f, mData.getYMax()); - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + if (mData != null) { + mYAxisRenderer.computeAxis(0f, mData.getYMax()); + mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + } } @Override From 9f1b8f726be83f477227943111ffe576131e59b4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 24 Feb 2015 15:56:48 +0100 Subject: [PATCH 0115/1390] Merged, removed support library. --- MPChartExample/AndroidManifest.xml | 4 ++-- .../HorizontalBarChartActivity.java | 1 + MPChartLib/libs/android-support-v4.jar | Bin 758727 -> 0 bytes .../charting/charts/BarLineChartBase.java | 3 +++ .../github/mikephil/charting/charts/Chart.java | 6 +++--- .../charting/charts/PieRadarChartBase.java | 8 +------- .../charting/renderer/BarChartRenderer.java | 8 ++++++-- .../renderer/HorizontalBarChartRenderer.java | 5 +++++ 8 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 MPChartLib/libs/android-support-v4.jar diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index b57370e86b..b782e93495 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,12 +1,12 @@ + android:targetSdkVersion="21" /> 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%0A<(7v*D)E<@03_8EbidqNKuAHLI_ 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/k+ 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 w+jTz#EWX5_5YyoKR`w$kwP`E(nSTNLWi8KN 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%0AEkcx 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 b-;+{*nGO`iNluswDR-BKTh&qeu1; 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 HrBwYtY{WkL diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 89955730bf..ae5818e5dc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -372,6 +372,9 @@ protected void calculateOffsets() { */ protected void calcModulus() { + if (mXAxis == null) + return; + float[] values = new float[9]; mViewPortHandler.getMatrixTouch().getValues(values); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 6ea96c790f..7c33287202 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -19,7 +19,6 @@ import android.graphics.drawable.Drawable; import android.os.Environment; import android.provider.MediaStore.Images; -import android.support.v4.view.ViewCompat; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -63,7 +62,7 @@ public abstract class Chart dataSets = mChart.getBarData().getDataSets(); @@ -366,4 +365,9 @@ public float[] getTransformedValues(Transformer trans, ArrayList entri mChart.getBarData(), mAnimator.getPhaseY()); } + + protected boolean passesCheck() { + return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleX(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 76c5879eee..7ba6ee767f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -62,4 +62,9 @@ public float[] getTransformedValues(Transformer trans, ArrayList entri protected void drawValue(Canvas c, float val, float xPos, float yPos) { super.drawValue(c, val, xPos + xOffset, yPos + yOffset); } + + protected boolean passesCheck() { + return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() + * mViewPortHandler.getScaleY(); + } } From f941206292366b0328988109517fd64bb407f0ae Mon Sep 17 00:00:00 2001 From: "JitPack.io" Date: Tue, 24 Feb 2015 19:53:55 +0000 Subject: [PATCH 0116/1390] Added gradle dependency information So that MPAndroidChart can be easily added to gradle Android projects --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb8aa21828..25d63d130e 100644 --- a/README.md +++ b/README.md @@ -111,15 +111,28 @@ Features Usage ======= -In order to use the library, there are 2 options: +In order to use the library, there are 3 options: **1. jar file only** - Download the [**latest .jar file**](https://github.com/PhilJay/MPAndroidChart/releases) from the releases section - Copy the **mpandroidchartlibrary-.jar** file into the `libs` folder of your Android application project - Start using the library - -**2. clone whole repository** + +**2. Gradle dependency** + + - Add the following to your `build.gradle`: + ```gradle +repositories { + maven { url "https://jitpack.io" } +} + +dependencies { + compile 'com.github.PhilJay:MPAndroidChart:v2.0.0' +} +``` + +**3. clone whole repository** - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - Import the library folder (`MPChartLib`) into your Eclipse workspace, using `File-->Import-->Android-->Existing Android Code` and then choose the library folder from your file system and press `Finish`. From d2a46e90e4ff0e9feeca200d778f45aa98bb9aa3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 24 Feb 2015 21:54:06 +0100 Subject: [PATCH 0117/1390] Update README.md --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 25d63d130e..d6d0701a9f 100644 --- a/README.md +++ b/README.md @@ -131,8 +131,22 @@ dependencies { compile 'com.github.PhilJay:MPAndroidChart:v2.0.0' } ``` +**3. Maven** +- Add the following to your `pom.xml`: + ```xml + + jitpack.io + https://jitpack.io + + + + com.github.PhilJay + MPAndroidChart + v2.0.0 + +``` -**3. clone whole repository** +**4. clone whole repository** - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - Import the library folder (`MPChartLib`) into your Eclipse workspace, using `File-->Import-->Android-->Existing Android Code` and then choose the library folder from your file system and press `Finish`. From 6c1acd570b95213e0342071641bfef810e1bec0c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 24 Feb 2015 21:55:01 +0100 Subject: [PATCH 0118/1390] Update README.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index d6d0701a9f..5986a9c9ef 100644 --- a/README.md +++ b/README.md @@ -111,15 +111,9 @@ Features Usage ======= -In order to use the library, there are 3 options: +In order to use the library, there are 4 options: - -**1. jar file only** - - Download the [**latest .jar file**](https://github.com/PhilJay/MPAndroidChart/releases) from the releases section - - Copy the **mpandroidchartlibrary-.jar** file into the `libs` folder of your Android application project - - Start using the library - -**2. Gradle dependency** +**1. Gradle dependency** - Add the following to your `build.gradle`: ```gradle @@ -131,7 +125,8 @@ dependencies { compile 'com.github.PhilJay:MPAndroidChart:v2.0.0' } ``` -**3. Maven** + +**2. Maven** - Add the following to your `pom.xml`: ```xml @@ -145,6 +140,11 @@ dependencies { v2.0.0 ``` + +**3. jar file only** + - Download the [**latest .jar file**](https://github.com/PhilJay/MPAndroidChart/releases) from the releases section + - Copy the **mpandroidchartlibrary-.jar** file into the `libs` folder of your Android application project + - Start using the library **4. clone whole repository** - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) From 2229715bead0c5a6fa2b0e01a86b9ba2b25aaa72 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 00:44:31 +0100 Subject: [PATCH 0119/1390] Included PercentFormatter into the library. --- .../mpchartexample/PieChartActivity.java | 2 +- .../custom/PercentFormatter.java | 20 ----------- .../listviewitems/PieChartItem.java | 2 +- .../mikephil/charting/charts/PieChart.java | 33 ------------------- .../charting/utils/PercentFormatter.java | 24 ++++++++++++++ 5 files changed, 26 insertions(+), 55 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 2bf7b11804..9e9a67a572 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -20,7 +20,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.PercentFormatter; +import com.github.mikephil.charting.utils.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java deleted file mode 100644 index 1e3e223f72..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/PercentFormatter.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import com.github.mikephil.charting.utils.ValueFormatter; - -import java.text.DecimalFormat; - -public class PercentFormatter implements ValueFormatter { - - private DecimalFormat mFormat; - - public PercentFormatter() { - mFormat = new DecimalFormat("#,##0.0"); - } - - @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + " %"; - } - -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index d071322e52..a31846391b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.utils.PercentFormatter; import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.PercentFormatter; public class PieChartItem extends ChartItem { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 33561668f6..7978baf4b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -3,14 +3,11 @@ import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; -import android.graphics.Paint.Style; import android.util.AttributeSet; import com.github.mikephil.charting.data.DataSet; @@ -476,34 +473,4 @@ public void setUsePercentValues(boolean enabled) { public boolean isUsePercentValuesEnabled() { return mUsePercentValues; } - - @Override - public void setPaint(Paint p, int which) { - super.setPaint(p, which); - - switch (which) { - case PAINT_HOLE: - // mHolePaint = p; - break; - case PAINT_CENTER_TEXT: - // mCenterTextPaint = p; - break; - } - } - - @Override - public Paint getPaint(int which) { - Paint p = super.getPaint(which); - if (p != null) - return p; - - switch (which) { - case PAINT_HOLE: - // return mHolePaint; - case PAINT_CENTER_TEXT: - // return mCenterTextPaint; - } - - return null; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java new file mode 100644 index 0000000000..b69b3e9ba9 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java @@ -0,0 +1,24 @@ + +package com.github.mikephil.charting.utils; + +import java.text.DecimalFormat; + +/** + * This ValueFormatter is just for convenience and simply puts a "%" sign after + * each value. (Recommeded for PieChart) + * + * @author Philipp Jahoda + */ +public class PercentFormatter implements ValueFormatter { + + protected DecimalFormat mFormat; + + public PercentFormatter() { + mFormat = new DecimalFormat("###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value) { + return mFormat.format(value) + " %"; + } +} From 536b9100dd1659b34d65afc924f311f456f3f088 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 09:06:44 +0100 Subject: [PATCH 0120/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5986a9c9ef..ebec969f06 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [ **android-arsenal.com**] (https://github.com/vbauer/android-arsenal.com) + [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven-version)](https://jitpack.io/#PhilJay/MPAndroidChart) MPAndroidChart ======= From 5bb32e16c93021545601a71a74aabc7f03534337 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 09:36:13 +0100 Subject: [PATCH 0121/1390] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ebec969f06..a894f23fd5 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,8 @@ or create it in code (and then **add it to a layout**): **Gestures & Selecting:** - setTouchEnabled(boolean enabled): If set to ture, touch gestures (such as scaling and dragging) will be possible on the chart. NOTE: If touch-gestures are disabled, highlighting on touch is disabled as well. Default: true. - - setDragScaleEnabled(boolean enabled): Enables/disables dragging and scaling for the chart. + - setDragEnabled(boolean enabled): Enables/disables dragging for the chart. + - setScaleEnabled(boolean enabled): Enables/disables scaling for the chart. - setOnChartValueSelectedListener(OnChartValueSelectedListener l): Sets a selection-listener to the chart that will generate callbacks when values are selected or unselected. The callback contains the selected values and their indices. - setHighlightEnabled(boolean enabled): If set to true, highlighting/selecting values is possible on the chart. Default: true. - public void highlightValues(Highlight[] highs): Highlights the specified entries in the chart. From 4cb9089fe44062486da79403a6c6b495a6f13a5e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 09:52:16 +0100 Subject: [PATCH 0122/1390] Added more documentation, created ComponentBase. --- .../charting/components/AxisBase.java | 120 +--------------- .../charting/components/ComponentBase.java | 130 ++++++++++++++++++ .../mikephil/charting/components/Legend.java | 113 +-------------- .../charting/components/MarkerView.java | 35 ----- .../mikephil/charting/components/YAxis.java | 8 +- .../mikephil/charting/data/DataSet.java | 3 +- 6 files changed, 142 insertions(+), 267 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 5a82dd4523..7a38fcd7e4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -2,7 +2,6 @@ package com.github.mikephil.charting.components; import android.graphics.Color; -import android.graphics.Typeface; import com.github.mikephil.charting.utils.Utils; @@ -11,17 +10,8 @@ * * @author Philipp Jahoda */ -public abstract class AxisBase { - - /** the typeface to use for the labels */ - private Typeface mTypeface; - - /** the size of the label text */ - private float mTextSize = 10f; - - /** the text color to use */ - private int mTextColor = Color.BLACK; - +public abstract class AxisBase extends ComponentBase { + private int mGridColor = Color.GRAY; private int mAxisLineColor = Color.GRAY; @@ -36,12 +26,6 @@ public abstract class AxisBase { /** flag that indicates if the line alongside the axis is drawn or not */ protected boolean mDrawAxisLine = true; - - /** the offset in pixels this axis labels have on the x-axis */ - protected float mXOffset = 5f; - - /** the offset in pixels this axis labels have on the Y-axis */ - protected float mYOffset = 5f; /** default constructor */ public AxisBase() { @@ -50,68 +34,6 @@ public AxisBase() { this.mYOffset = Utils.convertDpToPixel(5f); } - /** - * sets the size of the label text in pixels min = 6f, max = 24f, default - * 10f - * - * @param size - */ - public void setTextSize(float size) { - - if (size > 24f) - size = 24f; - if (size < 6f) - size = 6f; - - mTextSize = Utils.convertDpToPixel(size); - } - - /** - * returns the text size that is currently set for the labels - * - * @return - */ - public float getTextSize() { - return mTextSize; - } - - /** - * sets the typeface that should be used for the labels - * - * @param t - */ - public void setTypeface(Typeface t) { - mTypeface = t; - } - - /** - * returns the typeface that is used for the labels - * - * @return - */ - public Typeface getTypeface() { - return mTypeface; - } - - /** - * Sets the text color to use for the labels. Make sure to use - * getResources().getColor(...) when using a color from the resources. - * - * @param color - */ - public void setTextColor(int color) { - mTextColor = color; - } - - /** - * Returns the text color that is set for the labels. - * - * @return - */ - public int getTextColor() { - return mTextColor; - } - /** * Set this to true to enable drawing the grid lines for this axis. * @@ -221,44 +143,6 @@ public void setEnabled(boolean enabled) { public boolean isEnabled() { return mEnabled; } - - /** - * Returns the used offset on the x-axis for drawing the axis labels. This - * offset is applied before and after the label. - * - * @return - */ - public float getXOffset() { - return mXOffset; - } - - /** - * Sets the used x-axis offset for the labels on this axis. - * - * @param xOffset - */ - public void setXOffset(float xOffset) { - mXOffset = Utils.convertDpToPixel(xOffset); - } - - /** - * Returns the used offset on the x-axis for drawing the axis labels. This - * offset is applied before and after the label. - * - * @return - */ - public float getYOffset() { - return mYOffset; - } - - /** - * Sets the used x-axis offset for the labels on this axis. - * - * @param xOffset - */ - public void setYOffset(float yOffset) { - mYOffset = Utils.convertDpToPixel(yOffset); - } /** * Returns the longest formatted label (in terms of characters), this axis contains. diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java new file mode 100644 index 0000000000..a04f9051e4 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -0,0 +1,130 @@ + +package com.github.mikephil.charting.components; + +import android.graphics.Color; +import android.graphics.Typeface; + +import com.github.mikephil.charting.utils.Utils; + +/** + * This class encapsulates everything both Axis and Legend have in common. + * + * @author Philipp Jahoda + */ +public abstract class ComponentBase { + + /** the offset in pixels this axis labels have on the x-axis */ + protected float mXOffset = 5f; + + /** the offset in pixels this axis labels have on the Y-axis */ + protected float mYOffset = 5f; + + /** the typeface used for the labels */ + protected Typeface mTypeface = null; + + /** the text size of the labels */ + protected float mTextSize = 10f; + + /** the text color to use for the labels */ + protected int mTextColor = Color.BLACK; + + /** + * Returns the used offset on the x-axis for drawing the axis or legend + * labels. This offset is applied before and after the label. + * + * @return + */ + public float getXOffset() { + return mXOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setXOffset(float xOffset) { + mXOffset = Utils.convertDpToPixel(xOffset); + } + + /** + * Returns the used offset on the x-axis for drawing the axis labels. This + * offset is applied before and after the label. + * + * @return + */ + public float getYOffset() { + return mYOffset; + } + + /** + * Sets the used x-axis offset for the labels on this axis. + * + * @param xOffset + */ + public void setYOffset(float yOffset) { + mYOffset = Utils.convertDpToPixel(yOffset); + } + + /** + * returns the Typeface used for the labels, returns null if none is set + * + * @return + */ + public Typeface getTypeface() { + return mTypeface; + } + + /** + * sets a specific Typeface for the labels + * + * @param tf + */ + public void setTypeface(Typeface tf) { + mTypeface = tf; + } + + /** + * sets the size of the label text in pixels min = 6f, max = 24f, default + * 10f + * + * @param size + */ + public void setTextSize(float size) { + + if (size > 24f) + size = 24f; + if (size < 6f) + size = 6f; + + mTextSize = Utils.convertDpToPixel(size); + } + + /** + * returns the text size that is currently set for the labels + * + * @return + */ + public float getTextSize() { + return mTextSize; + } + + /** + * Sets the text color to use for the labels. Make sure to use + * getResources().getColor(...) when using a color from the resources. + * + * @param color + */ + public void setTextColor(int color) { + mTextColor = color; + } + + /** + * Returns the text color that is set for the labels. + * + * @return + */ + public int getTextColor() { + return mTextColor; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 280365c980..dc27a80854 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -1,9 +1,7 @@ package com.github.mikephil.charting.components; -import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Typeface; import com.github.mikephil.charting.utils.Utils; @@ -16,7 +14,7 @@ * * @author Philipp Jahoda */ -public class Legend { +public class Legend extends ComponentBase { public enum LegendPosition { RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, PIECHART_CENTER @@ -41,15 +39,6 @@ public enum LegendForm { /** the shape/form the legend colors are drawn in */ private LegendForm mShape = LegendForm.SQUARE; - /** the typeface used for the legend labels */ - private Typeface mTypeface = null; - - /** the text size of the legend labels */ - private float mTextSize = 10f; - - /** the text color to use */ - private int mTextColor = Color.BLACK; - /** the size of the legend forms/shapes */ private float mFormSize = 8f; @@ -72,12 +61,6 @@ public enum LegendForm { /** the space that should be left between stacked forms */ private float mStackSpace = 3f; - - /** the offset in pixels this axis labels have on the x-axis */ - protected float mXOffset = 5f; - - /** the offset in pixels this axis labels have on the Y-axis */ - protected float mYOffset = 6f; /** default constructor */ public Legend() { @@ -265,25 +248,6 @@ public void setForm(LegendForm shape) { mShape = shape; } - /** - * returns the typeface used for the legend labels, returns null if none is - * set - * - * @return - */ - public Typeface getTypeface() { - return mTypeface; - } - - /** - * sets a specific typeface for the legend labels - * - * @param tf - */ - public void setTypeface(Typeface tf) { - mTypeface = tf; - } - /** * sets the size in pixels of the legend forms, this is internally converted * in dp, default 8f @@ -384,24 +348,6 @@ public void apply(Legend l) { mYOffset = l.mYOffset; } - /** - * sets the text size of the legend labels, default 9f - * - * @param size - */ - public void setTextSize(float size) { - mTextSize = Utils.convertDpToPixel(size); - } - - /** - * returns the text size of the legend labels - * - * @return - */ - public float getTextSize() { - return mTextSize; - } - /** * returns the space that is left out between stacked forms (with no label) * @@ -507,25 +453,6 @@ public void calculateDimensions(Paint labelpaint) { } } - /** - * Sets the text color to use for the legend labels. Make sure to use - * getResources().getColor(...) when using a color from the resources. - * - * @param color - */ - public void setTextColor(int color) { - mTextColor = color; - } - - /** - * Returns the text color that is set for the legend labels. - * - * @return - */ - public int getTextColor() { - return mTextColor; - } - /** * Set this to true if the legend should be enabled (should be drawn), false * if not. Default: true @@ -544,42 +471,4 @@ public void setEnabled(boolean enabled) { public boolean isEnabled() { return mEnabled; } - - /** - * Returns the used offset on the x-axis for drawing the axis labels. This - * offset is applied before and after the label. - * - * @return - */ - public float getXOffset() { - return mXOffset; - } - - /** - * Sets the used x-axis offset for the labels on this axis. - * - * @param xOffset - */ - public void setXOffset(float xOffset) { - mXOffset = Utils.convertDpToPixel(xOffset); - } - - /** - * Returns the used offset on the x-axis for drawing the axis labels. This - * offset is applied before and after the label. - * - * @return - */ - public float getYOffset() { - return mYOffset; - } - - /** - * Sets the used x-axis offset for the labels on this axis. - * - * @param xOffset - */ - public void setYOffset(float yOffset) { - mYOffset = Utils.convertDpToPixel(yOffset); - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index 3c57172fe1..e8f96562ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -93,39 +93,4 @@ public void draw(Canvas canvas, float posx, float posy) { * @return */ public abstract int getYOffset(); - - // /** - // * Set the position offset of the MarkerView. By default, the top left - // edge - // * of the MarkerView is drawn directly where the selected value is at. In - // * order to change that, offsets in pixels can be defined. Default offset - // is - // * zero (0f) on both axes. For offsets dependent on the MarkerViews width - // * and height, use getMeasuredWidth() / getMeasuredHeight(). - // * - // * @param x - // * @param y - // */ - // public void setOffsets(float x, float y) { - // this.mXOffset = x; - // this.mYOffset = y; - // } - // - // /** - // * returns the x-offset that is set for the MarkerView - // * - // * @return - // */ - // public float getXOffset() { - // return mXOffset; - // } - // - // /** - // * returns the y-offset that is set for the MarkerView - // * - // * @return - // */ - // public float getYOffset() { - // return mYOffset; - // } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 71d4333dbf..4b0d1202dc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -86,6 +86,12 @@ public enum YAxisLabelPosition { /** the side this axis object represents */ private AxisDependency mAxisDependency; + /** + * Enum that specifies the axis a DataSet should be plotted against, either + * LEFT or RIGHT. + * + * @author Philipp Jahoda + */ public enum AxisDependency { LEFT, RIGHT } @@ -374,7 +380,7 @@ public float getRequiredWidthSpace(Paint p) { String label = getLongestLabel(); return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; } - + public float getRequiredHeightSpace(Paint p) { String label = getLongestLabel(); return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e894f2b846..4db3554e45 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -43,7 +43,8 @@ public abstract class DataSet { /** if true, y-values are drawn on the chart */ protected boolean mDrawValues = true; - private AxisDependency mAxisDependency = AxisDependency.LEFT; + /** this specifies which axis this DataSet should be plotted against */ + protected AxisDependency mAxisDependency = AxisDependency.LEFT; /** * Creates a new DataSet object with the given values it represents. Also, a From 7b31ec2ea176c972654f248848e01f28de4769f3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 11:01:22 +0100 Subject: [PATCH 0123/1390] Update README.md --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a894f23fd5..49215912af 100644 --- a/README.md +++ b/README.md @@ -149,9 +149,11 @@ dependencies { **4. clone whole repository** - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - - Import the library folder (`MPChartLib`) into your Eclipse workspace, using `File-->Import-->Android-->Existing Android Code` and then choose the library folder from your file system and press `Finish`. - - After importing, add the library to your project by right clicking your project `Properties-->Android`. There, you press the "Add.." button and choose the library project you just imported into eclipse. Then press `apply`. - - Start using the library + - Import the library folder (`MPChartLib`) into your Eclipse workspace + - More information: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) + +Getting Started +======= For getting started, rely on the **"MPChartExample"** folder and check out the examples in that project. The example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 93ff1bb5a4dc365d810f76cd627c7b9203883f11 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 11:03:17 +0100 Subject: [PATCH 0124/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49215912af..91eb06bc42 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ dependencies { - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - Import the library folder (`MPChartLib`) into your Eclipse workspace - - More information: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) + - Add it as a reference to your project: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) Getting Started ======= From c72f76577a6cce5379980c176ae13eabc047c167 Mon Sep 17 00:00:00 2001 From: Maragues Date: Wed, 25 Feb 2015 14:29:57 +0100 Subject: [PATCH 0125/1390] Improved CombinedChart example. DataSets depend on different YAxis. Added a menu to toggle values annd YAxis dependency. --- MPChartExample/res/menu/combined.xml | 21 +++++ .../mpchartexample/CombinedChartActivity.java | 85 +++++++++++++++++-- 2 files changed, 97 insertions(+), 9 deletions(-) create mode 100644 MPChartExample/res/menu/combined.xml diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/res/menu/combined.xml new file mode 100644 index 0000000000..97f4a4aa86 --- /dev/null +++ b/MPChartExample/res/menu/combined.xml @@ -0,0 +1,21 @@ + +

+ + + + + + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index dfa7c33749..ce91b6fe73 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -3,6 +3,8 @@ import android.graphics.Color; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.CombinedChart; @@ -16,6 +18,7 @@ import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -29,6 +32,8 @@ public class CombinedChartActivity extends DemoBase { private CombinedChart mChart; private final int itemcount = 12; + private final int maxYLeft = 40; + private final int maxYRight = 60; @Override protected void onCreate(Bundle savedInstanceState) { @@ -40,13 +45,15 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (CombinedChart) findViewById(R.id.chart1); mChart.setDescription(""); mChart.setDrawGridBackground(false); - + YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - + rightAxis.setAxisMaxValue(maxYRight); + YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setDrawGridLines(false); - + leftAxis.setAxisMaxValue(maxYLeft); + XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); @@ -67,8 +74,9 @@ private LineData generateLineData() { ArrayList entries = new ArrayList(); + int minValue = 5; for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(15, 10), index)); + entries.add(new Entry(getRandom(maxYLeft - minValue, minValue), index)); LineDataSet set = new LineDataSet(entries, "Line DataSet"); set.setColor(Color.rgb(240, 238, 70)); @@ -77,9 +85,12 @@ private LineData generateLineData() { set.setCircleSize(5f); set.setFillColor(Color.rgb(240, 238, 70)); set.setDrawCubic(true); - set.setDrawValues(false); + set.setDrawValues(true); + + set.setAxisDependency(YAxis.AxisDependency.LEFT); + d.addDataSet(set); - + return d; } @@ -89,16 +100,19 @@ private BarData generateBarData() { ArrayList entries = new ArrayList(); + int minValue = 20; for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(getRandom(15, 30), index)); + entries.add(new BarEntry(getRandom(maxYRight - minValue, minValue), index)); BarDataSet set = new BarDataSet(entries, "Bar DataSet"); set.setColor(Color.rgb(60, 220, 78)); d.addDataSet(set); + set.setAxisDependency(YAxis.AxisDependency.RIGHT); + return d; } - + private ScatterData generateScatterData() { ScatterData d = new ScatterData(); @@ -116,7 +130,7 @@ private ScatterData generateScatterData() { return d; } - + private CandleData generateCandleData() { CandleData d = new CandleData(); @@ -138,4 +152,57 @@ private CandleData generateCandleData() { private float getRandom(float range, float startsfrom) { return (float) (Math.random() * range) + startsfrom; } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.combined, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.actionToggleLineValues: { + for (DataSet set : mChart.getData().getDataSets()) { + if(set instanceof LineDataSet) + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleBarValues: { + for (DataSet set : mChart.getData().getDataSets()) { + if(set instanceof BarDataSet) + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleBarYDependency: { + for (DataSet set : mChart.getData().getDataSets()) { + if(set instanceof BarDataSet) { + YAxis.AxisDependency newAxisDependency = set.getAxisDependency().equals(YAxis.AxisDependency.LEFT) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT; + set.setAxisDependency(newAxisDependency); + } + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleLineYDependency: { + for (DataSet set : mChart.getData().getDataSets()) { + if(set instanceof LineDataSet) { + YAxis.AxisDependency newAxisDependency = set.getAxisDependency().equals(YAxis.AxisDependency.LEFT) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT; + set.setAxisDependency(newAxisDependency); + } + } + + mChart.invalidate(); + break; + } + } + return true; + } } From 657567b3d2bac596f70ac522e10e0e7e5ef94ecb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 25 Feb 2015 23:45:59 +0100 Subject: [PATCH 0126/1390] Minor changes. --- MPChartExample/res/menu/combined.xml | 8 ----- .../mpchartexample/CombinedChartActivity.java | 34 ++----------------- .../mikephil/charting/charts/Chart.java | 2 +- 3 files changed, 4 insertions(+), 40 deletions(-) diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/res/menu/combined.xml index 97f4a4aa86..9b034d7f4f 100644 --- a/MPChartExample/res/menu/combined.xml +++ b/MPChartExample/res/menu/combined.xml @@ -9,13 +9,5 @@ android:id="@+id/actionToggleBarValues" android:title="Toggle bar Values"> - - - - \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index ce91b6fe73..267cdde9d7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -32,8 +32,6 @@ public class CombinedChartActivity extends DemoBase { private CombinedChart mChart; private final int itemcount = 12; - private final int maxYLeft = 40; - private final int maxYRight = 60; @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,11 +46,9 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setAxisMaxValue(maxYRight); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setDrawGridLines(false); - leftAxis.setAxisMaxValue(maxYLeft); XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); @@ -74,9 +70,8 @@ private LineData generateLineData() { ArrayList entries = new ArrayList(); - int minValue = 5; for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(maxYLeft - minValue, minValue), index)); + entries.add(new Entry(getRandom(15, 10), index)); LineDataSet set = new LineDataSet(entries, "Line DataSet"); set.setColor(Color.rgb(240, 238, 70)); @@ -100,15 +95,14 @@ private BarData generateBarData() { ArrayList entries = new ArrayList(); - int minValue = 20; for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(getRandom(maxYRight - minValue, minValue), index)); + entries.add(new BarEntry(getRandom(15, 30), index)); BarDataSet set = new BarDataSet(entries, "Bar DataSet"); set.setColor(Color.rgb(60, 220, 78)); d.addDataSet(set); - set.setAxisDependency(YAxis.AxisDependency.RIGHT); + set.setAxisDependency(YAxis.AxisDependency.LEFT); return d; } @@ -177,28 +171,6 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); - break; - } - case R.id.actionToggleBarYDependency: { - for (DataSet set : mChart.getData().getDataSets()) { - if(set instanceof BarDataSet) { - YAxis.AxisDependency newAxisDependency = set.getAxisDependency().equals(YAxis.AxisDependency.LEFT) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT; - set.setAxisDependency(newAxisDependency); - } - } - - mChart.invalidate(); - break; - } - case R.id.actionToggleLineYDependency: { - for (DataSet set : mChart.getData().getDataSets()) { - if(set instanceof LineDataSet) { - YAxis.AxisDependency newAxisDependency = set.getAxisDependency().equals(YAxis.AxisDependency.LEFT) ? YAxis.AxisDependency.RIGHT : YAxis.AxisDependency.LEFT; - set.setAxisDependency(newAxisDependency); - } - } - mChart.invalidate(); break; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3c943b85e1..ff7df888ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -62,7 +62,7 @@ public abstract class Chart Date: Thu, 26 Feb 2015 09:49:29 +0100 Subject: [PATCH 0127/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index fb05b900dd..d6adfc1da6 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -26,3 +26,6 @@ https://play.google.com/store/apps/details?id=com.droidinfinity.healthplus БИТ.Лидер https://play.google.com/store/apps/details?id=com.firstbit.bitlider + +My Expenses +https://play.google.com/store/apps/details?id=org.totschnig.myexpenses From 7b1fb38415570748fba549ce49a4e78a6f581b0d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 26 Feb 2015 09:55:22 +0100 Subject: [PATCH 0128/1390] Added convenience methods for PieChart, issue #380. --- .../BarChartActivityMultiDataset.java | 1 + .../mikephil/charting/charts/PieChart.java | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 4bac43117d..24b67e4dda 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -226,6 +226,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set3); BarData data = new BarData(xVals, dataSets); + data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width data.setGroupSpace(80f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 7978baf4b9..858ac2d984 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -105,7 +105,7 @@ protected void onDraw(Canvas canvas) { mLegendRenderer.renderLegend(mDrawCanvas, mLegend); drawDescription(); - + canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } @@ -127,7 +127,7 @@ protected void calculateOffsets() { mCircleBox.set(c.x - boxSize, c.y - boxSize, c.x + boxSize, c.y + boxSize); } - + @Override protected void calcMinMax() { super.calcMinMax(); @@ -402,13 +402,31 @@ public void setCenterTextTypeface(Typeface t) { } /** - * Sets the size of the center text of the piechart. + * Sets the size of the center text of the PieChart in dp. * * @param size */ - public void setCenterTextSize(float size) { + public void setCenterTextSize(float sizeDp) { ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize( - Utils.convertDpToPixel(size)); + Utils.convertDpToPixel(sizeDp)); + } + + /** + * Sets the size of the center text of the PieChart in pixels. + * + * @param size + */ + public void setCenterTextSizePixels(float sizePixels) { + ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize(sizePixels); + } + + /** + * Sets the color of the center text of the PieChart. + * + * @param color + */ + public void setCenterTextColor(int color) { + ((PieChartRenderer) mRenderer).getPaintCenterText().setColor(color); } /** From 8b932a71abdd28c558ad67847afd6cdea9fc1ce1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 26 Feb 2015 10:54:54 +0100 Subject: [PATCH 0129/1390] Grouped BarChart highlighting now working. --- .../mikephil/charting/charts/BarChart.java | 50 +++++++++---------- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/renderer/BarChartRenderer.java | 6 ++- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index a91a58b9a7..40572767ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -122,44 +122,44 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (xTouchVal < mXChartMin || xTouchVal > mXChartMax) return null; - Log.i(LOG_TAG, "base: " + base); - int setCount = mData.getDataSetCount(); - int valCount = setCount * mData.getXValCount(); + int valCount = mData.getXValCount(); if (setCount <= 1) { return new Highlight((int) Math.round(base), 0); } - // calculate the amount of bar-space between index 0 and touch position - float space = (float) ((((float) valCount / (float) setCount) / (mDeltaX / base))); -// - float border = (float) setCount + mData.getGroupSpace(); - - float steps = 0.5f + (int) (((float) base + 0.5f) / ((float) setCount)); - - float reduction = (float) (steps) * mData.getGroupSpace(); + int steps = (int) ((float) base / ((float) setCount + mData.getGroupSpace())); - Log.i(LOG_TAG, "reduction: " + reduction); + float groupSpaceSum = mData.getGroupSpace() * (float) steps; - float beforeRound = (float) ((base - reduction) / setCount); - Log.i(LOG_TAG, "touch x-index before round: " + beforeRound); - - int xIndex = (int) beforeRound; - Log.i(LOG_TAG, "touch x-index: " + xIndex); + float baseNoSpace = (float) base - groupSpaceSum; - float dataSetBeforeRound = (float) ((base - reduction) % (setCount - 0.5f)); + if (mLogEnabled) + Log.i(LOG_TAG, "base: " + base + ", steps: " + steps + ", groupSpaceSum: " + + groupSpaceSum + + ", baseNoSpace: " + baseNoSpace); - Log.i(LOG_TAG, "datasetindex before round: " + dataSetBeforeRound); + int dataSetIndex = (int) baseNoSpace % setCount; + int xIndex = (int) baseNoSpace / setCount; - int dataSetIndex = (int) Math.round(dataSetBeforeRound); - Log.i(LOG_TAG, "touch dataset-index: " + dataSetIndex); - - if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) - return null; + if (mLogEnabled) + Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - if (xIndex < 0) + // check bounds + if (xIndex < 0) { xIndex = 0; + dataSetIndex = 0; + } else if (xIndex >= valCount) { + xIndex = valCount - 1; + dataSetIndex = setCount - 1; + } + + // check bounds + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; return new Highlight(xIndex, dataSetIndex); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index ff7df888ad..3c943b85e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -62,7 +62,7 @@ public abstract class Chart= 0 ? y : 0; float bottom = y <= 0 ? y : 0; From bd75e6c2a68afc4f78423c89367a9a500a13e09a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 26 Feb 2015 10:56:52 +0100 Subject: [PATCH 0130/1390] Horizontal barchart highlighting working. --- .../HorizontalBarChartActivity.java | 2 +- .../charting/charts/HorizontalBarChart.java | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index b737df460b..8584445641 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -50,7 +50,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (HorizontalBarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setHighlightEnabled(false); +// mChart.setHighlightEnabled(false); mChart.setDrawBarShadow(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 2e69fecdc0..5b9d4b978d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; +import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; /** @@ -131,4 +132,76 @@ protected void calcModulus() { .ceil((mData.getXValCount() * mXAxis.mLabelHeight) / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); } + + /** + * Returns the Highlight object (contains x-index and DataSet index) of the + * selected value at the given touch point inside the BarChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mDataNotSet || mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + pts[1] = y; + + mLeftAxisTransformer.pixelsToValue(pts); + + // for barchart, we only need x-val + double yTouchVal = pts[1]; + double base = yTouchVal; + + if (yTouchVal < mXChartMin || yTouchVal > mXChartMax) + return null; + + int setCount = mData.getDataSetCount(); + int valCount = mData.getXValCount(); + + if (setCount <= 1) { + return new Highlight((int) Math.round(base), 0); + } + + int steps = (int) ((float) base / ((float) setCount + mData.getGroupSpace())); + + float groupSpaceSum = mData.getGroupSpace() * (float) steps; + + float baseNoSpace = (float) base - groupSpaceSum; + + if (mLogEnabled) + Log.i(LOG_TAG, "base: " + base + ", steps: " + steps + ", groupSpaceSum: " + + groupSpaceSum + + ", baseNoSpace: " + baseNoSpace); + + int dataSetIndex = (int) baseNoSpace % setCount; + int xIndex = (int) baseNoSpace / setCount; + + if (mLogEnabled) + Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); + + // check bounds + if (xIndex < 0) { + xIndex = 0; + dataSetIndex = 0; + } else if (xIndex >= valCount) { + xIndex = valCount - 1; + dataSetIndex = setCount - 1; + } + + // check bounds + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; + + return new Highlight(xIndex, dataSetIndex); + } } From b01c5e2b32defdd9364f900c7180083115fe3b5b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 00:16:06 +0100 Subject: [PATCH 0131/1390] Value textsize, textcolor and typeface can now be set via DataSet or ChartData object. --- .../mpchartexample/BarChartActivity.java | 19 +- .../BarChartActivityMultiDataset.java | 9 +- .../CandleStickChartActivity.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 6 + .../CubicLineChartActivity.java | 6 +- .../mpchartexample/DrawChartActivity.java | 6 +- .../DynamicalAddingActivity.java | 38 ++- .../HorizontalBarChartActivity.java | 223 +++++++++--------- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 4 +- .../mpchartexample/LineChartActivity2.java | 4 +- .../LineChartActivityColored.java | 3 +- .../ListViewBarChartActivity.java | 8 +- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PieChartActivity.java | 11 +- .../mpchartexample/RadarChartActivitry.java | 6 +- .../RealtimeLineChartActivity.java | 10 +- .../mpchartexample/ScatterChartActivity.java | 8 +- .../mpchartexample/StackedBarActivity.java | 2 +- .../mpchartexample/custom/MyMarkerView.java | 1 - .../fragments/PieChartFrag.java | 3 - .../fragments/SimpleFragment.java | 23 +- .../listviewitems/BarChartItem.java | 3 +- .../listviewitems/PieChartItem.java | 6 +- .../mikephil/charting/charts/BarChart.java | 21 +- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/Chart.java | 58 ++--- .../charting/charts/HorizontalBarChart.java | 41 +--- .../charting/components/ComponentBase.java | 4 - .../mikephil/charting/data/ChartData.java | 94 ++++---- .../mikephil/charting/data/DataSet.java | 51 +++- .../charting/interfaces/ChartInterface.java | 26 +- .../listener/BarLineChartTouchListener.java | 1 - .../OnChartGestureListener.java | 2 +- .../OnChartValueSelectedListener.java | 2 +- .../OnDrawLineChartTouchListener.java | 2 +- .../OnDrawListener.java | 2 +- .../listener/PieRadarChartTouchListener.java | 1 - .../charting/renderer/BarChartRenderer.java | 3 + .../renderer/CandleStickChartRenderer.java | 6 +- .../charting/renderer/DataRenderer.java | 53 ++++- .../charting/renderer/LineChartRenderer.java | 7 +- .../charting/renderer/PieChartRenderer.java | 7 + .../charting/renderer/RadarChartRenderer.java | 12 +- .../renderer/ScatterChartRenderer.java | 3 + .../XAxisRendererHorizontalBarChart.java | 5 + .../YAxisRendererHorizontalBarChart.java | 4 + 47 files changed, 459 insertions(+), 353 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/{interfaces => listener}/OnChartGestureListener.java (94%) rename MPChartLib/src/com/github/mikephil/charting/{interfaces => listener}/OnChartValueSelectedListener.java (93%) rename MPChartLib/src/com/github/mikephil/charting/{interfaces => listener}/OnDrawLineChartTouchListener.java (87%) rename MPChartLib/src/com/github/mikephil/charting/{interfaces => listener}/OnDrawListener.java (94%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 133d586c70..c5d9f91ceb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -30,7 +30,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -43,6 +43,8 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListene protected BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + + private Typeface mTf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -79,30 +81,25 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); - // sets the text size of the values inside the chart - mChart.setValueTextSize(10f); - - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(tf); + xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); ValueFormatter custom = new MyValueFormatter(); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(tf); + leftAxis.setTypeface(mTf); leftAxis.setLabelCount(8); leftAxis.setValueFormatter(custom); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(tf); + rightAxis.setTypeface(mTf); rightAxis.setLabelCount(8); rightAxis.setValueFormatter(custom); - - mChart.setValueTypeface(tf); setData(12, 50); @@ -265,6 +262,8 @@ private void setData(int count, float range) { BarData data = new BarData(xVals, dataSets); // data.setValueFormatter(new MyValueFormatter()); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 24b67e4dda..0044720833 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -22,7 +22,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.LargeValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -35,6 +35,8 @@ public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarC private BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + + private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -77,7 +79,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); @@ -93,8 +95,6 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setSpaceTop(25f); mChart.getAxisRight().setEnabled(false); - - mChart.setValueTypeface(tf); } @Override @@ -230,6 +230,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // add space between the dataset groups in percent of bar-width data.setGroupSpace(80f); + data.setValueTypeface(tf); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 3bfbb43ac3..420a04d107 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -14,8 +14,8 @@ import com.github.mikephil.charting.charts.CandleStickChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 267cdde9d7..44e06e7bf8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -81,6 +81,8 @@ private LineData generateLineData() { set.setFillColor(Color.rgb(240, 238, 70)); set.setDrawCubic(true); set.setDrawValues(true); + set.setValueTextSize(10f); + set.setValueTextColor(Color.rgb(240, 238, 70)); set.setAxisDependency(YAxis.AxisDependency.LEFT); @@ -100,6 +102,8 @@ private BarData generateBarData() { BarDataSet set = new BarDataSet(entries, "Bar DataSet"); set.setColor(Color.rgb(60, 220, 78)); + set.setValueTextColor(Color.rgb(60, 220, 78)); + set.setValueTextSize(10f); d.addDataSet(set); set.setAxisDependency(YAxis.AxisDependency.LEFT); @@ -120,6 +124,7 @@ private ScatterData generateScatterData() { set.setColor(Color.GREEN); set.setScatterShapeSize(7.5f); set.setDrawValues(false); + set.setValueTextSize(10f); d.addDataSet(set); return d; @@ -137,6 +142,7 @@ private CandleData generateCandleData() { CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); set.setColor(Color.rgb(80, 80, 80)); set.setBodySpace(0.3f); + set.setValueTextSize(10f); set.setDrawValues(false); d.addDataSet(set); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 6b7f9da59c..7d50fe3a60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -30,6 +30,8 @@ public class CubicLineChartActivity extends DemoBase implements OnSeekBarChangeL private LineChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + + private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -71,8 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setValueTypeface(tf); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis x = mChart.getXAxis(); x.setTypeface(tf); @@ -281,6 +282,7 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); + data.setValueTypeface(tf); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 905fbbab82..5cf95aef1a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -16,8 +16,8 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; -import com.github.mikephil.charting.interfaces.OnDrawListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnDrawListener; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -73,8 +73,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setEnabled(false); - mChart.setValueTypeface(tf); - // mChart.setYRange(-40f, 40f, true); // call this to reset the changed y-range // mChart.resetYRange(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index ad67cd33aa..fca67d8ee8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -59,7 +59,11 @@ private void addEntry() { // add a new x-value first data.addXValue(set.getEntryCount() + ""); - data.addEntry(new Entry((float) (Math.random() * 10) + 50f, set.getEntryCount()), 0); + + // choose a random dataSet + int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); + + data.addEntry(new Entry((float) (Math.random() * 10) + 50f, set.getEntryCount()), randomDataSetIndex); // let the chart know it's data has changed mChart.notifyDataSetChanged(); @@ -107,9 +111,17 @@ private void addDataSet() { // create 10 y-vals ArrayList yVals = new ArrayList(); + + if(data.getXValCount() == 0) { + // add 10 x-entries + for (int i = 0; i < 10; i++) { + data.addXValue("" + (i+1)); + } + } - for (int i = 0; i < data.getXValCount(); i++) + for (int i = 0; i < data.getXValCount(); i++) { yVals.add(new Entry((float) (Math.random() * 50f) + 50f * count, i)); + } LineDataSet set = new LineDataSet(yVals, "DataSet " + count); set.setLineWidth(2.5f); @@ -120,6 +132,8 @@ private void addDataSet() { set.setColor(color); set.setCircleColor(color); set.setHighLightColor(color); + set.setValueTextSize(10f); + set.setValueTextColor(color); data.addDataSet(set); mChart.notifyDataSetChanged(); @@ -139,23 +153,6 @@ private void removeDataSet() { mChart.invalidate(); } } - -// private void addEmptyData() { -// -// int size = 1; -// -// // create 30 x-vals -// String[] xVals = new String[size]; -// -// for (int i = 0; i < size; i++) -// xVals[i] = "" + i; -// -// // create a chartdata object that contains only the x-axis labels (no entries or datasets) -// LineData data = new LineData(); -// -// mChart.setData(data); -// mChart.invalidate(); -// } @Override public void onValueSelected(Entry e, int dataSetIndex) { @@ -216,6 +213,7 @@ private LineDataSet createSet() { set.setCircleColor(Color.rgb(240, 99, 99)); set.setHighLightColor(Color.rgb(190, 190, 190)); set.setAxisDependency(AxisDependency.LEFT); + set.setValueTextSize(10f); return set; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 8584445641..1c1ad75209 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -7,10 +7,13 @@ import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.Legend; @@ -22,8 +25,11 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -34,6 +40,8 @@ public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarCha protected HorizontalBarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + + private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -74,10 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawYLabels(false); - // sets the text size of the values inside the chart - mChart.setValueTextSize(10f); - - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xl = mChart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); @@ -95,8 +100,6 @@ protected void onCreate(Bundle savedInstanceState) { yr.setTypeface(tf); yr.setDrawAxisLine(true); yr.setDrawGridLines(true); - - mChart.setValueTypeface(tf); setData(12, 50); mChart.animateY(2500); @@ -116,114 +119,102 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawLegend(false); } -// @Override -// public boolean onCreateOptionsMenu(Menu menu) { -// getMenuInflater().inflate(R.menu.bar, menu); -// return true; -// } -// -// @Override -// public boolean onOptionsItemSelected(MenuItem item) { -// -// switch (item.getItemId()) { -// case R.id.actionToggleValues: { -// if (mChart.isDrawYValuesEnabled()) -// mChart.setDrawYValues(false); -// else -// mChart.setDrawYValues(true); -// mChart.invalidate(); -// break; -// } -// case R.id.actionToggle3D: { -// if (mChart.is3DEnabled()) -// mChart.set3DEnabled(false); -// else -// mChart.set3DEnabled(true); -// mChart.invalidate(); -// break; -// } -// case R.id.actionToggleHighlight: { -// if (mChart.isHighlightEnabled()) -// mChart.setHighlightEnabled(false); -// else -// mChart.setHighlightEnabled(true); -// mChart.invalidate(); -// break; -// } -// case R.id.actionTogglePinch: { -// if (mChart.isPinchZoomEnabled()) -// mChart.setPinchZoom(false); -// else -// mChart.setPinchZoom(true); -// -// mChart.invalidate(); -// break; -// } -// case R.id.actionToggleHighlightArrow: { -// if (mChart.isDrawHighlightArrowEnabled()) -// mChart.setDrawHighlightArrow(false); -// else -// mChart.setDrawHighlightArrow(true); -// mChart.invalidate(); -// break; -// } -// case R.id.actionToggleStartzero: { -// if (mChart.isStartAtZeroEnabled()) -// mChart.setStartAtZero(false); -// else -// mChart.setStartAtZero(true); -// -// mChart.invalidate(); -// break; -// } -// case R.id.animateX: { -// mChart.animateX(3000); -// break; -// } -// case R.id.animateY: { -// mChart.animateY(3000); -// break; -// } -// case R.id.animateXY: { -// -// mChart.animateXY(3000, 3000); -// break; -// } -// case R.id.actionToggleAdjustXLegend: { -// XLabels xLabels = mChart.getXLabels(); -// -// if (xLabels.isAdjustXLabelsEnabled()) -// xLabels.setAdjustXLabels(false); -// else -// xLabels.setAdjustXLabels(true); -// -// mChart.invalidate(); -// break; -// } -// case R.id.actionToggleFilter: { -// -// Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); -// -// if (!mChart.isFilteringEnabled()) { -// mChart.enableFiltering(a); -// } else { -// mChart.disableFiltering(); -// } -// mChart.invalidate(); -// break; -// } -// case R.id.actionSave: { -// if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { -// Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", -// Toast.LENGTH_SHORT).show(); -// } else -// Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) -// .show(); -// break; -// } -// } -// return true; -// } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlightArrow: { + if (mChart.isDrawHighlightArrowEnabled()) + mChart.setDrawHighlightArrow(false); + else + mChart.setDrawHighlightArrow(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleAdjustXLegend: { + XAxis xLabels = mChart.getXAxis(); + + if (xLabels.isAdjustXLabelsEnabled()) + xLabels.setAdjustXLabels(false); + else + xLabels.setAdjustXLabels(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleFilter: { + + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + break; + } + } + return true; + } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @@ -269,6 +260,8 @@ private void setData(int count, float range) { dataSets.add(set1); BarData data = new BarData(xVals, dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tf); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 0d91fd1e7c..95ab66172a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -21,7 +21,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index eeddb0ba86..30a2822ff4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -26,8 +26,8 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartGestureListener; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 38c42ac0cd..98af14b8a3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -26,7 +26,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -59,7 +59,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setValueTextColor(Color.WHITE); // no description text mChart.setDescription(""); @@ -318,6 +317,7 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); + data.setValueTextColor(Color.WHITE); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index b143c23451..d08b584745 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -38,6 +38,7 @@ protected void onCreate(Bundle savedInstanceState) { mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); LineData data = getData(36, 100); + data.setValueTypeface(mTf); for (int i = 0; i < mCharts.length; i++) // add some transparency to the color with "& 0x90FFFFFF" @@ -75,8 +76,6 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setBackgroundColor(color); - chart.setValueTypeface(mTf); - // add data chart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 3b627a0d70..258d509a42 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -66,7 +66,7 @@ public ChartDataAdapter(Context context, List objects) { @Override public View getView(int position, View convertView, ViewGroup parent) { - BarData c = getItem(position); + BarData data = getItem(position); ViewHolder holder = null; @@ -85,10 +85,10 @@ public View getView(int position, View convertView, ViewGroup parent) { } // apply styling - holder.chart.setValueTypeface(mTf); + data.setValueTypeface(mTf); holder.chart.setDescription(""); holder.chart.setDrawGridBackground(false); - holder.chart.setValueTextColor(Color.WHITE); + data.setValueTextColor(Color.WHITE); XAxis xAxis = holder.chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); @@ -106,7 +106,7 @@ public View getView(int position, View convertView, ViewGroup parent) { rightAxis.setSpaceTop(15f); // set data - holder.chart.setData(c); + holder.chart.setData(data); // do not forget to refresh the chart // holder.chart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 95a6986cd5..f3a1836b6c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -20,7 +20,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 13d10d1c7d..5119f88c29 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; @@ -18,7 +19,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -31,6 +32,8 @@ public class PieChartActivity extends DemoBase implements OnSeekBarChangeListene private PieChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + + private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -57,9 +60,8 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setHoleColor(Color.rgb(235, 235, 235)); mChart.setHoleColorTransparent(true); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setValueTypeface(tf); mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); mChart.setHoleRadius(60f); @@ -213,6 +215,9 @@ private void setData(int count, float range) { PieData data = new PieData(xVals, dataSet); data.setValueFormatter(new PercentFormatter()); + data.setValueTextSize(11f); + data.setValueTextColor(Color.WHITE); + data.setValueTypeface(tf); mChart.setData(data); // undo all highlights diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 9c27f32a99..2dc44d3260 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -26,6 +26,7 @@ public class RadarChartActivitry extends DemoBase { private RadarChart mChart; + private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,9 +37,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (RadarChart) findViewById(R.id.chart1); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - mChart.setValueTypeface(tf); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setDescription(""); @@ -192,6 +191,7 @@ public void setData() { sets.add(set2); RadarData data = new RadarData(xVals, sets); + data.setValueTypeface(tf); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 75df73fc48..de6ea80883 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -18,7 +18,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -36,7 +36,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setValueTextColor(Color.WHITE); // no description text mChart.setDescription(""); @@ -59,8 +58,11 @@ protected void onCreate(Bundle savedInstanceState) { // set an alternative background color mChart.setBackgroundColor(Color.LTGRAY); + LineData data = new LineData(); + data.setValueTextColor(Color.WHITE); + // add empty data - mChart.setData(new LineData()); + mChart.setData(data); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -156,6 +158,8 @@ private LineDataSet createSet() { set.setFillAlpha(65); set.setFillColor(ColorTemplate.getHoloBlue()); set.setHighLightColor(Color.rgb(244, 117, 117)); + set.setValueTextColor(Color.WHITE); + set.setValueTextSize(10f); return set; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 03b8ddfd45..bebe9b5110 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -23,7 +23,7 @@ import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -36,6 +36,8 @@ public class ScatterChartActivity extends DemoBase implements OnSeekBarChangeLis private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + private Typeface tf; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -55,8 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (ScatterChart) findViewById(R.id.chart1); mChart.setDescription(""); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setValueTypeface(tf); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setOnChartValueSelectedListener(this); @@ -226,6 +227,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a data object with the datasets ScatterData data = new ScatterData(xVals, dataSets); + data.setValueTypeface(tf); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index d328b0990e..d2482ca66a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -24,7 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 8f316a06ae..0f21a17df9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.R.id; /** * Custom implementation of the MarkerView. diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index 06dbdcd1a1..851351b1c4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -27,9 +27,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart = (PieChart) v.findViewById(R.id.pieChart1); mChart.setDescription(""); - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Regular.ttf"); - - mChart.setValueTypeface(tf); mChart.setCenterTextTypeface(Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf")); mChart.setCenterText("Quarterly\nRevenue"); mChart.setCenterTextSize(22f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index cdc6bc91bc..4f12b62770 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -1,6 +1,11 @@ package com.xxmassdeveloper.mpchartexample.fragments; +import android.graphics.Typeface; +import android.os.Bundle; import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; @@ -17,11 +22,22 @@ import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FileUtils; -import com.xxmassdeveloper.mpchartexample.R; import java.util.ArrayList; public abstract class SimpleFragment extends Fragment { + + private Typeface tf; + + public SimpleFragment() { + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Regular.ttf"); + return super.onCreateView(inflater, container, savedInstanceState); + } protected BarData generateBarData(int dataSets, float range, int count) { @@ -43,6 +59,7 @@ protected BarData generateBarData(int dataSets, float range, int count) { } BarData d = new BarData(ChartData.generateXVals(0, count), sets); + d.setValueTypeface(tf); return d; } @@ -69,6 +86,7 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) } ScatterData d = new ScatterData(ChartData.generateXVals(0, count), sets); + d.setValueTypeface(tf); return d; } @@ -99,6 +117,7 @@ protected PieData generatePieData() { ds1.setSliceSpace(2f); PieData d = new PieData(xVals, ds1); + d.setValueTypeface(tf); return d; } @@ -135,6 +154,7 @@ protected LineData generateLineData() { int max = Math.max(sets.get(0).getEntryCount(), sets.get(1).getEntryCount()); LineData d = new LineData(ChartData.generateXVals(0, max), sets); + d.setValueTypeface(tf); return d; } @@ -174,6 +194,7 @@ protected LineData getComplexity() { sets.add(ds4); LineData d = new LineData(ChartData.generateXVals(0, ds1.getEntryCount()), sets); + d.setValueTypeface(tf); return d; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index da7e3805d3..d886c9d485 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -48,7 +48,6 @@ public View getView(int position, View convertView, Context c) { } // apply styling - holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); holder.chart.setDrawGridBackground(false); holder.chart.setDrawBarShadow(false); @@ -69,6 +68,8 @@ public View getView(int position, View convertView, Context c) { rightAxis.setLabelCount(5); rightAxis.setSpaceTop(20f); + mChartData.setValueTypeface(mTf); + // set data holder.chart.setData((BarData) mChartData); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index a14da357ac..5578c146d4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -2,6 +2,7 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; import android.content.Context; +import android.graphics.Color; import android.graphics.Typeface; import android.view.LayoutInflater; import android.view.View; @@ -49,17 +50,18 @@ public View getView(int position, View convertView, Context c) { } // apply styling - holder.chart.setValueTypeface(mTf); holder.chart.setDescription(""); holder.chart.setHoleRadius(52f); holder.chart.setTransparentCircleRadius(57f); holder.chart.setCenterText("MPChart\nAndroid"); holder.chart.setCenterTextTypeface(mTf); holder.chart.setCenterTextSize(18f); - holder.chart.setValueTextSize(11f); holder.chart.setUsePercentValues(true); mChartData.setValueFormatter(new PercentFormatter()); + mChartData.setValueTypeface(mTf); + mChartData.setValueTextSize(11f); + mChartData.setValueTextColor(Color.WHITE); // set data holder.chart.setData((PieData) mChartData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 40572767ad..ff25a6147a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -122,21 +122,34 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (xTouchVal < mXChartMin || xTouchVal > mXChartMax) return null; + return getHighlight(base); + } + + /** + * Returns the correct Highlight object (including xIndex and dataSet-index) + * for the specified touch position. + * + * @param touchPositionBase + * @return + */ + protected Highlight getHighlight(double touchPositionBase) { + int setCount = mData.getDataSetCount(); int valCount = mData.getXValCount(); if (setCount <= 1) { - return new Highlight((int) Math.round(base), 0); + return new Highlight((int) Math.round(touchPositionBase), 0); } - int steps = (int) ((float) base / ((float) setCount + mData.getGroupSpace())); + // calculate how often the group-space appears + int steps = (int) ((float) touchPositionBase / ((float) setCount + mData.getGroupSpace())); float groupSpaceSum = mData.getGroupSpace() * (float) steps; - float baseNoSpace = (float) base - groupSpaceSum; + float baseNoSpace = (float) touchPositionBase - groupSpaceSum; if (mLogEnabled) - Log.i(LOG_TAG, "base: " + base + ", steps: " + steps + ", groupSpaceSum: " + Log.i(LOG_TAG, "base: " + touchPositionBase + ", steps: " + steps + ", groupSpaceSum: " + groupSpaceSum + ", baseNoSpace: " + baseNoSpace); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 9de80e83bd..caf838f4b1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -27,8 +27,8 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.interfaces.OnDrawListener; import com.github.mikephil.charting.listener.BarLineChartTouchListener; +import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; import com.github.mikephil.charting.utils.FillFormatter; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3c943b85e1..cd0193b761 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -33,8 +33,8 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.interfaces.OnChartGestureListener; -import com.github.mikephil.charting.interfaces.OnChartValueSelectedListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; import com.github.mikephil.charting.renderer.ViewPortHandler; @@ -1088,23 +1088,32 @@ public void setDrawMarkerViews(boolean enabled) { mDrawMarkerViews = enabled; } - /** - * sets the draw color for the value paint object - * - * @param color - */ - public void setValueTextColor(int color) { - mRenderer.getPaintValues().setColor(color); - } - - /** - * Sets the font size of the values that are drawn inside the chart. - * - * @param size - */ - public void setValueTextSize(float size) { - mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); - } +// /** +// * sets the draw color for the value paint object +// * +// * @param color +// */ +// public void setValueTextColor(int color) { +// mRenderer.getPaintValues().setColor(color); +// } +// +// /** +// * Sets the font size of the values that are drawn inside the chart. +// * +// * @param size +// */ +// public void setValueTextSize(float size) { +// mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); +// } +// +// /** +// * sets a typeface for the value-paint +// * +// * @param t +// */ +// public void setValueTypeface(Typeface t) { +// mRenderer.getPaintValues().setTypeface(t); +// } /** * returns the x-value at the given index @@ -1163,16 +1172,7 @@ public T getData() { public float getPercentOfTotal(float val) { return val / mData.getYValueSum() * 100f; } - - /** - * sets a typeface for the value-paint - * - * @param t - */ - public void setValueTypeface(Typeface t) { - mRenderer.getPaintValues().setTypeface(t); - } - + /** * sets the typeface for the description paint * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 5b9d4b978d..e74730c4b2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -163,45 +163,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (yTouchVal < mXChartMin || yTouchVal > mXChartMax) return null; - int setCount = mData.getDataSetCount(); - int valCount = mData.getXValCount(); - - if (setCount <= 1) { - return new Highlight((int) Math.round(base), 0); - } - - int steps = (int) ((float) base / ((float) setCount + mData.getGroupSpace())); - - float groupSpaceSum = mData.getGroupSpace() * (float) steps; - - float baseNoSpace = (float) base - groupSpaceSum; - - if (mLogEnabled) - Log.i(LOG_TAG, "base: " + base + ", steps: " + steps + ", groupSpaceSum: " - + groupSpaceSum - + ", baseNoSpace: " + baseNoSpace); - - int dataSetIndex = (int) baseNoSpace % setCount; - int xIndex = (int) baseNoSpace / setCount; - - if (mLogEnabled) - Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - - // check bounds - if (xIndex < 0) { - xIndex = 0; - dataSetIndex = 0; - } else if (xIndex >= valCount) { - xIndex = valCount - 1; - dataSetIndex = setCount - 1; - } - - // check bounds - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; - - return new Highlight(xIndex, dataSetIndex); + return getHighlight(base); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 540fc0ac94..72653288a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -4,11 +4,7 @@ import android.graphics.Color; import android.graphics.Typeface; -import com.github.mikephil.charting.utils.DefaultValueFormatter; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; - -import java.text.DecimalFormat; /** * This class encapsulates everything both Axis and Legend have in common. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 1b32274eea..b9c69c986f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -1,10 +1,12 @@ package com.github.mikephil.charting.data; +import android.graphics.Typeface; import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; @@ -377,21 +379,6 @@ public int getYValCount() { return mYValCount; } - // /** - // * Checks if the ChartData object contains valid data - // * - // * @return - // */ - // public boolean isValid() { - // if (mXVals == null || mXVals.size() < 1) - // return false; - // - // if (mDataSets == null || mDataSets.size() < 1) - // return false; - // - // return true; - // } - /** * returns the x-values the chart represents * @@ -428,17 +415,6 @@ public ArrayList getDataSets() { return mDataSets; } - // /** - // * returns the Entries array from the DataSet at the given index. If a - // * filter is set, the filtered Entries are returned - // * - // * @param index - // * @return - // */ - // public ArrayList getYVals(int index) { - // return mDataSets.get(index).getYVals(); - // } - /** * Retrieve the index of a DataSet with a specific label from the ChartData. * Search can be case sensitive or not. IMPORTANT: This method does @@ -807,21 +783,6 @@ public int getIndexOfDataSet(T dataSet) { return -1; } - /** - * Sets a custom ValueFormatter for all DataSets this data object contains. - * - * @param f - */ - public void setValueFormatter(ValueFormatter f) { - if (f == null) - return; - else { - for (DataSet set : mDataSets) { - set.setValueFormatter(f); - } - } - } - public T getFirstLeft() { for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) @@ -856,4 +817,55 @@ public static ArrayList generateXVals(int from, int to) { return xvals; } + + /** + * Sets a custom ValueFormatter for all DataSets this data object contains. + * + * @param f + */ + public void setValueFormatter(ValueFormatter f) { + if (f == null) + return; + else { + for (DataSet set : mDataSets) { + set.setValueFormatter(f); + } + } + } + + /** + * Sets the color of the value-text (color in which the value-labels are + * drawn) for all DataSets this data object contains. + * + * @param color + */ + public void setValueTextColor(int color) { + for (DataSet set : mDataSets) { + set.setValueTextColor(color); + } + } + + /** + * Sets the Typeface for all value-labels for all DataSets this data object + * contains. + * + * @param color + */ + public void setValueTypeface(Typeface tf) { + for (DataSet set : mDataSets) { + set.setValueTypeface(tf); + } + } + + /** + * Sets the size (in dp) of the value-text for all DataSets this data object + * contains. + * + * @param color + */ + public void setValueTextSize(float size) { + for (DataSet set : mDataSets) { + set.setValueTextSize(size); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e0d4b90785..60aa646867 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -3,10 +3,12 @@ import android.content.Context; import android.graphics.Color; +import android.graphics.Typeface; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.DefaultValueFormatter; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; @@ -45,6 +47,12 @@ public abstract class DataSet { /** if true, y-values are drawn on the chart */ protected boolean mDrawValues = true; + private int mValueColor = Color.BLACK; + + private float mValueTextSize = 16f; + + private Typeface mValueTypeface; + /** custom formatter that is used instead of the auto-formatter if set */ protected ValueFormatter mValueFormatter; @@ -599,9 +607,11 @@ public void setValueFormatter(ValueFormatter f) { * @return */ public ValueFormatter getValueFormatter() { + if (mValueFormatter == null) + return new DefaultValueFormatter(1); return mValueFormatter; } - + /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. @@ -616,4 +626,43 @@ public boolean needsDefaultFormatter() { return false; } + + /** + * Sets the color the value-labels of this DataSet should have. + * + * @param color + */ + public void setValueTextColor(int color) { + mValueColor = color; + } + + public int getValueTextColor() { + return mValueColor; + } + + /** + * Sets a Typeface for the value-labels of this DataSet. + * + * @param tf + */ + public void setValueTypeface(Typeface tf) { + mValueTypeface = tf; + } + + public Typeface getValueTypeface() { + return mValueTypeface; + } + + /** + * Sets the text-size of the value-labels of this DataSet in dp. + * + * @param size + */ + public void setValueTextSize(float size) { + mValueTextSize = Utils.convertDpToPixel(size); + } + + public float getValueTextSize() { + return mValueTextSize; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index 09369ddbe1..93649d9c5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -15,18 +15,9 @@ */ public interface ChartInterface { -// public float getOffsetBottom(); -// -// public float getOffsetTop(); -// -// public float getOffsetLeft(); -// -// public float getOffsetRight(); - public float getXChartMin(); - public float getXChartMax(); -// public float getDeltaY(); + public float getXChartMax(); public float getYChartMin(); @@ -35,16 +26,15 @@ public interface ChartInterface { public int getWidth(); public int getHeight(); - -// public boolean isStartAtZeroEnabled(); - + public PointF getCenterOfView(); - + public PointF getCenterOffsets(); - + public RectF getContentRect(); - + public View getChartView(); - -// public ValueFormatter getValueFormatter(); + + public ValueFormatter getDefaultValueFormatter(); + } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 3c4b0f663a..dad057e20f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -15,7 +15,6 @@ import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartGestureListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java similarity index 94% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartGestureListener.java rename to MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java index 33ca882b12..6eac55f8fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartGestureListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.listener; import android.view.MotionEvent; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartValueSelectedListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java similarity index 93% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartValueSelectedListener.java rename to MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 359a331082..7972a997c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnChartValueSelectedListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.listener; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java similarity index 87% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawLineChartTouchListener.java rename to MPChartLib/src/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java index 5c71ac6945..ca3a67f677 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.listener; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java similarity index 94% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawListener.java rename to MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java index f86270115a..58ed4bc69a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/OnDrawListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.listener; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 0be00e2d79..0c4fb4871c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.interfaces.OnChartGestureListener; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 1eee657b04..108f7fbcc7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -207,6 +207,9 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); ValueFormatter formatter = dataSet.getValueFormatter(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index ce1b2ed63c..03b367e3f9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -151,10 +151,14 @@ public void drawValues(Canvas c) { for (int i = 0; i < dataSets.size(); i++) { CandleDataSet dataSet = dataSets.get(i); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); if (!dataSet.isDrawValuesEnabled()) continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); ArrayList entries = dataSet.getYVals(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index b4f0ae4ffc..5cbf402976 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,16 +8,17 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; -public abstract class DataRenderer extends Renderer { - +public abstract class DataRenderer extends Renderer { + protected ChartAnimator mAnimator; - + /** main paint object used for rendering */ protected Paint mRenderPaint; - + /** paint used for highlighting values */ protected Paint mHighlightPaint; @@ -25,38 +27,63 @@ public abstract class DataRenderer extends Renderer { * entries) */ protected Paint mValuePaint; - + public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { super(viewPortHandler); this.mAnimator = animator; - + mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRenderPaint.setStyle(Style.FILL); - + mValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mValuePaint.setColor(Color.rgb(63, 63, 63)); mValuePaint.setTextAlign(Align.CENTER); mValuePaint.setTextSize(Utils.convertDpToPixel(9f)); - + mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHighlightPaint.setStyle(Paint.Style.STROKE); mHighlightPaint.setStrokeWidth(2f); mHighlightPaint.setColor(Color.rgb(255, 187, 115)); } - + + /** + * Returns the Paint object this renderer uses for drawing the values + * (value-text). + * + * @return + */ public Paint getPaintValues() { return mValuePaint; } - + + /** + * Returns the Paint object this renderer uses for drawing highlight + * indicators. + * + * @return + */ public Paint getPaintHighlight() { return mHighlightPaint; } + /** + * Applies the required styling (provided by the DataSet) to the value-paint + * object. + * + * @param set + */ + protected void applyValueTextStyle(DataSet set) { + + mValuePaint.setColor(set.getValueTextColor()); + mValuePaint.setTypeface(set.getValueTypeface()); + mValuePaint.setTextSize(set.getValueTextSize()); + } + public abstract void drawData(Canvas c); - + public abstract void drawValues(Canvas c); - + public abstract void drawExtras(Canvas c); - + public abstract void drawHighlighted(Canvas c, Highlight[] indices); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 294198ea58..299deb80d5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -7,7 +7,6 @@ import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -316,11 +315,15 @@ public void drawValues(Canvas c) { for (int i = 0; i < dataSets.size(); i++) { LineDataSet dataSet = dataSets.get(i); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); if (!dataSet.isDrawValuesEnabled()) continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + // make sure the values do not interfear with the circles int valOffset = (int) (dataSet.getCircleSize() * 1.75f); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 16002d22d5..27a934d57d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -140,6 +140,13 @@ public void drawValues(Canvas c) { for (int i = 0; i < dataSets.size(); i++) { PieDataSet dataSet = dataSets.get(i); + + if (!dataSet.isDrawValuesEnabled()) + continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + ArrayList entries = dataSet.getYVals(); for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index f2d63ffc8a..7e43277e84 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -37,7 +37,7 @@ public RadarChartRenderer(RadarChart chart, ChartAnimator animator, mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mWebPaint.setStyle(Paint.Style.STROKE); } - + public Paint getWebPaint() { return mWebPaint; } @@ -121,6 +121,9 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + ArrayList entries = dataSet.getYVals(); for (int j = 0; j < entries.size(); j++) { @@ -140,9 +143,9 @@ public void drawValues(Canvas c) { public void drawExtras(Canvas c) { drawWeb(c); } - + protected void drawWeb(Canvas c) { - + float sliceangle = mChart.getSliceAngle(); // calculate the factor that is needed for transforming the value to @@ -159,7 +162,8 @@ protected void drawWeb(Canvas c) { for (int i = 0; i < mChart.getData().getXValCount(); i++) { - PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor, sliceangle * i + rotationangle); + PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor, sliceangle * i + + rotationangle); c.drawLine(center.x, center.y, p.x, p.y, mWebPaint); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 8dfa4fa6f0..88b353a6a4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -126,6 +126,9 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + ArrayList entries = dataSet.getYVals(); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index af057ffef8..535798d1ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -93,6 +93,11 @@ protected void drawLabels(Canvas c, float pos) { position[1] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; + + // consider groups (center label for each group) + if (step > 1) { + position[1] += ((float) step - 1f) / 2f; + } mTrans.pointValuesToPixel(position); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 774ae379c1..ec8a81f3e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -137,6 +137,10 @@ protected void drawAxisLine(Canvas c) { */ @Override protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { + + mAxisPaint.setTypeface(mYAxis.getTypeface()); + mAxisPaint.setTextSize(mYAxis.getTextSize()); + mAxisPaint.setColor(mYAxis.getTextColor()); for (int i = 0; i < mYAxis.mEntryCount; i++) { From 0a0c22cc7357a2474749d71c5d34774b10f912de Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 00:19:44 +0100 Subject: [PATCH 0132/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91eb06bc42..fc5c8a0865 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven-version)](https://jitpack.io/#PhilJay/MPAndroidChart) + [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) MPAndroidChart ======= From 82f2d5595a9407be64535f7acca295d5a7654ad6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 09:57:10 +0100 Subject: [PATCH 0133/1390] Fixed bug concerning axis rendering. Axes can now be enabled/disabled totally, added possibility to enable / disable drawing axis labels. --- .../charting/charts/BarLineChartBase.java | 7 +++--- .../mikephil/charting/charts/LineChart.java | 2 -- .../mikephil/charting/charts/RadarChart.java | 6 ++--- .../charting/components/AxisBase.java | 24 ++++++++++--------- .../charting/components/ComponentBase.java | 23 ++++++++++++++++++ .../mikephil/charting/components/Legend.java | 22 ----------------- .../charting/components/MarkerView.java | 3 ++- .../mikephil/charting/data/ChartData.java | 13 +++++++++- .../mikephil/charting/data/DataSet.java | 5 +++- .../charting/renderer/AxisRenderer.java | 4 ++-- .../charting/renderer/XAxisRenderer.java | 10 ++++---- .../XAxisRendererHorizontalBarChart.java | 10 ++++---- .../renderer/XAxisRendererRadarChart.java | 4 ++-- .../charting/renderer/YAxisRenderer.java | 10 ++++---- .../YAxisRendererHorizontalBarChart.java | 10 ++++---- .../renderer/YAxisRendererRadarChart.java | 6 ++--- 16 files changed, 83 insertions(+), 76 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index caf838f4b1..d582dc7381 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -198,11 +198,12 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(mDrawCanvas); - mXAxisRenderer.renderAxis(mDrawCanvas); + mXAxisRenderer.renderAxisLabels(mDrawCanvas); + mXAxisRenderer.renderAxisLine(mDrawCanvas); - mAxisRendererLeft.renderAxis(mDrawCanvas); + mAxisRendererLeft.renderAxisLabels(mDrawCanvas); - mAxisRendererRight.renderAxis(mDrawCanvas); + mAxisRendererRight.renderAxisLabels(mDrawCanvas); mRenderer.drawValues(mDrawCanvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index a2532a71f5..ee6b58aeca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -2,11 +2,9 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Paint; import android.util.AttributeSet; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; import com.github.mikephil.charting.utils.FillFormatter; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 08bedd2971..1fa7bedaab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -7,7 +7,6 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; -import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -17,7 +16,6 @@ import com.github.mikephil.charting.renderer.RadarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererRadarChart; import com.github.mikephil.charting.renderer.YAxisRendererRadarChart; -import com.github.mikephil.charting.utils.DefaultValueFormatter; import com.github.mikephil.charting.utils.Utils; /** @@ -151,7 +149,7 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - mXAxisRenderer.renderAxis(mDrawCanvas); + mXAxisRenderer.renderAxisLabels(mDrawCanvas); if (mDrawWeb) mRenderer.drawExtras(mDrawCanvas); @@ -163,7 +161,7 @@ protected void onDraw(Canvas canvas) { if (mHighlightEnabled && valuesToHighlight()) mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); - mYAxisRenderer.renderAxis(mDrawCanvas); + mYAxisRenderer.renderAxisLabels(mDrawCanvas); mRenderer.drawValues(mDrawCanvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 7a38fcd7e4..a7c1adb33d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -11,22 +11,22 @@ * @author Philipp Jahoda */ public abstract class AxisBase extends ComponentBase { - + private int mGridColor = Color.GRAY; private int mAxisLineColor = Color.GRAY; private float mAxisLineWidth = 1f; - /** flag that indicates if this axis is enabled or not */ - protected boolean mEnabled = true; - /** flag indicating if the grid lines for this axis should be drawn */ protected boolean mDrawGridLines = true; /** flag that indicates if the line alongside the axis is drawn or not */ protected boolean mDrawAxisLine = true; + /** flag that indicates of the labels of this axis should be drawn or not */ + protected boolean mDrawLabels = true; + /** default constructor */ public AxisBase() { this.mTextSize = Utils.convertDpToPixel(10f); @@ -127,25 +127,27 @@ public int getAxisLineColor() { } /** - * Set this to true to enable this axis from being drawn to the screen. + * Set this to true to enable drawing the labels of this axis (this will not + * affect drawing the grid lines or axis lines). * * @param enabled */ - public void setEnabled(boolean enabled) { - mEnabled = enabled; + public void setDrawLabels(boolean enabled) { + mDrawLabels = enabled; } /** - * Returns true if the axis is enabled (will be drawn). + * Returns true if drawing the labels is enabled for this axis. * * @return */ - public boolean isEnabled() { - return mEnabled; + public boolean isDrawLabelsEnabled() { + return mDrawLabels; } /** - * Returns the longest formatted label (in terms of characters), this axis contains. + * Returns the longest formatted label (in terms of characters), this axis + * contains. * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 72653288a2..bdcaa4a56e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -13,6 +13,9 @@ */ public abstract class ComponentBase { + /** flag that indicates if this axis / legend is enabled or not */ + protected boolean mEnabled = true; + /** the offset in pixels this axis labels have on the x-axis */ protected float mXOffset = 5f; @@ -131,4 +134,24 @@ public void setTextColor(int color) { public int getTextColor() { return mTextColor; } + + /** + * Set this to true if this component should be enabled (should be drawn), + * false if not. If disabled, nothing of this component will be drawn. + * Default: true + * + * @param enabled + */ + public void setEnabled(boolean enabled) { + mEnabled = enabled; + } + + /** + * Returns true if this comonent is enabled (should be drawn), false if not. + * + * @return + */ + public boolean isEnabled() { + return mEnabled; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index dc27a80854..07d426cb47 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -23,9 +23,6 @@ public enum LegendPosition { public enum LegendForm { SQUARE, CIRCLE, LINE } - - /** flag indicating if the legend should be drawn or not */ - private boolean mEnabled = true; /** the legend colors */ private int[] mColors; @@ -452,23 +449,4 @@ public void calculateDimensions(Paint labelpaint) { mTextHeightMax = mNeededHeight; } } - - /** - * Set this to true if the legend should be enabled (should be drawn), false - * if not. Default: true - * - * @param enabled - */ - public void setEnabled(boolean enabled) { - mEnabled = enabled; - } - - /** - * Returns true if the legend is enabled (should be drawn), false if not. - * - * @return - */ - public boolean isEnabled() { - return mEnabled; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index e8f96562ea..14a0aed6c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -71,7 +71,8 @@ public void draw(Canvas canvas, float posx, float posy) { * everytime the MarkerView is redrawn. * * @param e The Entry the MarkerView belongs to. This can also be any - * subclass of Entry, like BarEntry or CandleEntry. + * subclass of Entry, like BarEntry or CandleEntry, simply cast + * it at runtime. * @param dataSetIndex the index of the DataSet the selected value is in */ public abstract void refreshContent(Entry e, int dataSetIndex); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index b9c69c986f..9de93161ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; @@ -868,4 +867,16 @@ public void setValueTextSize(float size) { set.setValueTextSize(size); } } + + /** + * Enables / disables drawing values (value-text) for all DataSets this data + * object contains. + * + * @param enabled + */ + public void setDrawValues(boolean enabled) { + for (DataSet set : mDataSets) { + set.setDrawValues(enabled); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 60aa646867..1e64a497e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -47,10 +47,13 @@ public abstract class DataSet { /** if true, y-values are drawn on the chart */ protected boolean mDrawValues = true; + /** the color used for the value-text */ private int mValueColor = Color.BLACK; - private float mValueTextSize = 16f; + /** the size of the value-text labels */ + private float mValueTextSize = 17f; + /** the typeface used for the value text */ private Typeface mValueTypeface; /** custom formatter that is used instead of the auto-formatter if set */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index 5e7bd0617e..cc1d7e4763 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -63,7 +63,7 @@ public Transformer getTransformer() { * * @param c */ - public abstract void renderAxis(Canvas c); + public abstract void renderAxisLabels(Canvas c); /** * Draws the grid lines belonging to the axis. @@ -77,5 +77,5 @@ public Transformer getTransformer() { * * @param c */ - protected abstract void drawAxisLine(Canvas c); + public abstract void renderAxisLine(Canvas c); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 60eb0c6df3..07275139c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -43,9 +43,9 @@ public void computeAxis(float xValAverageLength, ArrayList xValues) { } @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mXAxis.isEnabled()) + if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; float yoffset = Utils.convertDpToPixel(4f); @@ -75,14 +75,12 @@ public void renderAxis(Canvas c) { drawLabels(c, mViewPortHandler.offsetTop() - yoffset); drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.6f); } - - drawAxisLine(c); } @Override - protected void drawAxisLine(Canvas c) { + public void renderAxisLine(Canvas c) { - if (!mXAxis.isDrawAxisLineEnabled()) + if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return; mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 535798d1ac..285332dbf9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -33,9 +33,9 @@ public void computeAxis(float xValAverageLength, ArrayList xValues) { } @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mXAxis.isEnabled()) + if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; float xoffset = mXAxis.getXOffset(); @@ -69,8 +69,6 @@ public void renderAxis(Canvas c) { drawLabels(c, mViewPortHandler.contentLeft()); drawLabels(c, mViewPortHandler.contentRight()); } - - drawAxisLine(c); } /** @@ -139,9 +137,9 @@ public void renderGridLines(Canvas c) { } @Override - protected void drawAxisLine(Canvas c) { + public void renderAxisLine(Canvas c) { - if (!mXAxis.isDrawAxisLineEnabled()) + if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return; mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index edbca7caf0..1f14e2c450 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -19,9 +19,9 @@ public XAxisRendererRadarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Rad } @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mXAxis.isEnabled()) + if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; mAxisPaint.setTypeface(mXAxis.getTypeface()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 095346e9a3..d173207f11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -143,9 +143,9 @@ protected void computeAxisValues(float min, float max) { * draws the y-axis labels to the screen */ @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled()) + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; float[] positions = new float[mYAxis.mEntryCount * 2]; @@ -193,14 +193,12 @@ public void renderAxis(Canvas c) { } drawYLabels(c, xPos, positions, yoffset); - - drawAxisLine(c); } @Override - protected void drawAxisLine(Canvas c) { + public void renderAxisLine(Canvas c) { - if (!mYAxis.isDrawAxisLineEnabled()) + if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) return; mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index ec8a81f3e0..7fbf904f28 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -55,9 +55,9 @@ public void computeAxis(float yMin, float yMax) { * draws the y-axis labels to the screen */ @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled()) + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; float[] positions = new float[mYAxis.mEntryCount * 2]; @@ -105,14 +105,12 @@ public void renderAxis(Canvas c) { } drawYLabels(c, yPos, positions, yoffset); - - drawAxisLine(c); } @Override - protected void drawAxisLine(Canvas c) { + public void renderAxisLine(Canvas c) { - if (!mYAxis.isDrawAxisLineEnabled()) + if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) return; mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index fe80cb88a5..aeb0cae482 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -28,11 +28,11 @@ public void computeAxis(float yMin, float yMax) { } @Override - public void renderAxis(Canvas c) { + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled()) + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; - + mAxisPaint.setTypeface(mYAxis.getTypeface()); mAxisPaint.setTextSize(mYAxis.getTextSize()); mAxisPaint.setColor(mYAxis.getTextColor()); From f5e93c6efbc71610cac97ba779e73ccca50971d1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 10:15:01 +0100 Subject: [PATCH 0134/1390] Fixed some issues concerning offset calculation. --- .../mpchartexample/LineChartActivity2.java | 9 ++++++--- .../github/mikephil/charting/components/YAxis.java | 11 +++++++++-- .../mikephil/charting/renderer/XAxisRenderer.java | 3 +++ 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 98af14b8a3..6e0c13cb2e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -95,13 +95,17 @@ protected void onCreate(Bundle savedInstanceState) { // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); l.setTypeface(tf); + l.setTextSize(11f); l.setTextColor(Color.WHITE); l.setPosition(LegendPosition.BELOW_CHART_LEFT); XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); + xAxis.setTextSize(12f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); + xAxis.setDrawAxisLine(false); + xAxis.setSpaceBetweenLabels(1); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -113,10 +117,9 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setTypeface(tf); rightAxis.setTextColor(Color.RED); rightAxis.setAxisMaxValue(900); + rightAxis.setStartAtZero(false); + rightAxis.setAxisMinValue(-200); rightAxis.setDrawGridLines(false); - -// yl.setAxisMaxValue(300f); -// yl.setAxisMinValue(-100f); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 05b73a8a55..731c198627 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -263,7 +263,9 @@ public float getAxisMinValue() { /** * Set a custom minimum value for this axis. If set, this value will not be * calculated automatically depending on the provided data. Use - * resetAxisMinValue() to undo this. + * resetAxisMinValue() to undo this. Do not forget to call + * setStartAtZero(false) if you use this method. Otherwise, the axis-minimum + * value will still be forced to 0. * * @param min */ @@ -339,11 +341,17 @@ public float getSpaceBottom() { } public float getRequiredWidthSpace(Paint p) { + + p.setTextSize(mTextSize); + String label = getLongestLabel(); return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; } public float getRequiredHeightSpace(Paint p) { + + p.setTextSize(mTextSize); + String label = getLongestLabel(); return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; } @@ -377,7 +385,6 @@ public String getFormattedLabel(int index) { else return getValueFormatter().getFormattedValue(mEntries[index]); } - /** * Sets the formatter to be used for drawing the values inside the chart. If diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 07275139c7..527922d8cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -27,6 +27,9 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t } public void computeAxis(float xValAverageLength, ArrayList xValues) { + + mAxisPaint.setTypeface(mXAxis.getTypeface()); + mAxisPaint.setTextSize(mXAxis.getTextSize()); StringBuffer a = new StringBuffer(); From 951c3f1a3f2c9a89c1b6f23dd8041ddafa759b09 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 10:19:00 +0100 Subject: [PATCH 0135/1390] Code cleanup. --- .../charting/charts/BarLineChartBase.java | 2 ++ .../mikephil/charting/charts/Chart.java | 2 +- .../charting/charts/PieRadarChartBase.java | 22 ------------------- 3 files changed, 3 insertions(+), 23 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d582dc7381..98d0d23029 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -202,8 +202,10 @@ protected void onDraw(Canvas canvas) { mXAxisRenderer.renderAxisLine(mDrawCanvas); mAxisRendererLeft.renderAxisLabels(mDrawCanvas); + mAxisRendererLeft.renderAxisLine(mDrawCanvas); mAxisRendererRight.renderAxisLabels(mDrawCanvas); + mAxisRendererRight.renderAxisLine(mDrawCanvas); mRenderer.drawValues(mDrawCanvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index cd0193b761..00e80c3d0c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -62,7 +62,7 @@ public abstract class Chart Date: Fri, 27 Feb 2015 11:20:29 +0100 Subject: [PATCH 0136/1390] Fixed bugs in RadarChart. --- .../mpchartexample/RadarChartActivitry.java | 18 ++--- .../mikephil/charting/charts/RadarChart.java | 17 ++++- .../charting/renderer/RadarChartRenderer.java | 10 +-- .../renderer/XAxisRendererRadarChart.java | 2 +- .../renderer/YAxisRendererRadarChart.java | 75 ++++++++++++++++++- 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 2dc44d3260..8bc64815a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -54,16 +54,15 @@ protected void onCreate(Bundle savedInstanceState) { setData(); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); - xl.setTextSize(9f); + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(tf); + xAxis.setTextSize(9f); - YAxis yl = mChart.getYAxis(); - yl.setTypeface(tf); - yl.setLabelCount(5); - yl.setTextSize(9f); - - // mChart.animateXY(1500, 1500); + YAxis yAxis = mChart.getYAxis(); + yAxis.setTypeface(tf); + yAxis.setLabelCount(5); + yAxis.setTextSize(9f); + yAxis.setStartAtZero(true); Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); @@ -192,6 +191,7 @@ public void setData() { RadarData data = new RadarData(xVals, sets); data.setValueTypeface(tf); + data.setValueTextSize(8f); mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 1fa7bedaab..c2c02c4287 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -7,6 +7,7 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; +import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -88,6 +89,9 @@ protected void calcMinMax() { float minLeft = mData.getYMin(AxisDependency.LEFT); float maxLeft = mData.getYMax(AxisDependency.LEFT); + mXChartMax = mData.getXVals().size() - 1; + mDeltaX = Math.abs(mXChartMax - mXChartMin); + float leftRange = Math.abs(maxLeft - (mYAxis.isStartAtZeroEnabled() ? 0 : minLeft)); float topSpaceLeft = leftRange / 100f * mYAxis.getSpaceTop(); @@ -134,7 +138,7 @@ public void notifyDataSetChanged() { mYAxis.setValueFormatter(mDefaultFormatter); } - mYAxisRenderer.computeAxis(0f, mYAxis.mAxisMaximum); + mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum); mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); mLegend = mLegendRenderer.computeLegend(mData, mLegend); @@ -182,7 +186,7 @@ protected void onDraw(Canvas canvas) { public float getFactor() { RectF content = mViewPortHandler.getContentRect(); return (float) Math.min(content.width() / 2f, content.height() / 2f) - / mYAxis.mAxisMaximum; + / mYAxis.mAxisRange; } /** @@ -344,4 +348,13 @@ public float getYChartMax() { public float getYChartMin() { return mYAxis.mAxisMinimum; } + + /** + * Returns the range of y-values this chart can display. + * + * @return + */ + public float getYRange() { + return mYAxis.mAxisRange; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 7e43277e84..281f553d71 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -74,7 +74,7 @@ protected void drawDataSet(Canvas c, RadarDataSet dataSet) { Entry e = entries.get(j); - PointF p = Utils.getPosition(center, e.getVal() * factor, + PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); if (j == 0) @@ -130,7 +130,7 @@ public void drawValues(Canvas c) { Entry e = entries.get(j); - PointF p = Utils.getPosition(center, e.getVal() * factor, + PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); c.drawText(dataSet.getValueFormatter().getFormattedValue(e.getVal()), @@ -162,7 +162,7 @@ protected void drawWeb(Canvas c) { for (int i = 0; i < mChart.getData().getXValCount(); i++) { - PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor, sliceangle * i + PointF p = Utils.getPosition(center, mChart.getYRange() * factor, sliceangle * i + rotationangle); c.drawLine(center.x, center.y, p.x, p.y, mWebPaint); @@ -179,7 +179,7 @@ protected void drawWeb(Canvas c) { for (int i = 0; i < mChart.getData().getXValCount(); i++) { - float r = mChart.getYAxis().mEntries[j] * factor; + float r = (mChart.getYAxis().mEntries[j] - mChart.getYChartMin()) * factor; PointF p1 = Utils.getPosition(center, r, sliceangle * i + rotationangle); PointF p2 = Utils.getPosition(center, r, sliceangle * (i + 1) + rotationangle); @@ -213,7 +213,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { Entry e = set.getEntryForXIndex(xIndex); int j = set.getEntryPosition(e); - float y = e.getVal(); + float y = (e.getVal() - mChart.getYChartMin()); PointF p = Utils.getPosition(center, y * factor, sliceangle * j + mChart.getRotationAngle()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 1f14e2c450..e3b0572f97 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -42,7 +42,7 @@ public void renderAxisLabels(Canvas c) { float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; - PointF p = Utils.getPosition(center, mChart.getYChartMax() * factor + PointF p = Utils.getPosition(center, mChart.getYRange() * factor + mXAxis.mLabelWidth / 2f, angle); c.drawText(text, p.x, p.y + mXAxis.mLabelHeight / 2f, mAxisPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index aeb0cae482..c19653be17 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -27,12 +27,81 @@ public void computeAxis(float yMin, float yMax) { computeAxisValues(yMin, yMax); } + @Override + protected void computeAxisValues(float min, float max) { + float yMin = min; + float yMax = max; + + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[] {}; + mYAxis.mEntryCount = 0; + return; + } + + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } + + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { + + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; + + } else { + + double first = Math.ceil(yMin / interval) * interval; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } + + if (Float.isNaN(mYAxis.getAxisMaxValue())) + n += 1; + + mYAxis.mEntryCount = n; + + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } + + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + + if (interval < 1) { + mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mYAxis.mDecimals = 0; + } + + mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; + mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); + } + @Override public void renderAxisLabels(Canvas c) { if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; - + mAxisPaint.setTypeface(mYAxis.getTypeface()); mAxisPaint.setTextSize(mYAxis.getTextSize()); mAxisPaint.setColor(mYAxis.getTextColor()); @@ -47,7 +116,7 @@ public void renderAxisLabels(Canvas c) { if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) break; - float r = mYAxis.mEntries[j] * factor; + float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); @@ -81,7 +150,7 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setPathEffect(l.getDashPathEffect()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - float r = l.getLimit() * factor; + float r = (l.getLimit() - mChart.getYChartMin()) * factor; Path limitPath = new Path(); From 408eaeb1279ec41fba35273a6aeb06a25a95c425 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 11:48:56 +0100 Subject: [PATCH 0137/1390] Inverting chart y-axis is now possible avain. --- .../InvertedLineChartActivity.java | 11 ++-- .../charting/charts/BarLineChartBase.java | 28 ++++++++ .../mikephil/charting/components/YAxis.java | 12 ++-- .../listener/BarLineChartTouchListener.java | 64 ++++++++++--------- 4 files changed, 75 insertions(+), 40 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 95ab66172a..97e28e092f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -59,10 +60,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.setDescription(""); - // invert the y-axis - // MAKE THIS RIGHT -// mChart.setInvertYAxisEnabled(true); - // enable value highlighting mChart.setHighlightEnabled(true); @@ -92,6 +89,12 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setInverted(true); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setEnabled(false); // add data setData(25, 50); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 98d0d23029..eb71bd462d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -932,6 +932,21 @@ public Entry getEntryByTouchPoint(float x, float y) { } return null; } + + /** + * returns the DataSet object displayed at the touched position of the chart + * + * @param x + * @param y + * @return + */ + public BarLineScatterCandleDataSet getDataSetByTouchPoint(float x, float y) { + Highlight h = getHighlightByTouchPoint(x, y); + if (h != null) { + return mData.getDataSetByIndex(h.getDataSetIndex()); + } + return null; + } /** * returns the current x-scale factor @@ -1096,6 +1111,19 @@ public float getYChartMin() { return Math.min(mAxisLeft.mAxisMinimum, mAxisRight.mAxisMinimum); } + /** + * Returns true if either the left or the right or both axes are inverted. + * + * @return + */ + public boolean isAnyAxisInverted() { + if (mAxisLeft.isInverted()) + return true; + if (mAxisRight.isInverted()) + return true; + return false; + } + /** * returns the filtered ChartData object depending on approximator settings, * current scale level and x- and y-axis ratio diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 731c198627..5732672cb3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -187,11 +187,11 @@ public boolean isShowOnlyMinMaxEnabled() { /** * If this is set to true, the y-axis is inverted which means that low - * values are on top of the chart, high values on bottom. + * values are on top of the chart, high values on bottom. * * @param enabled */ - public void setInvertAxis(boolean enabled) { + public void setInverted(boolean enabled) { mInverted = enabled; } @@ -341,17 +341,17 @@ public float getSpaceBottom() { } public float getRequiredWidthSpace(Paint p) { - + p.setTextSize(mTextSize); - + String label = getLongestLabel(); return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; } public float getRequiredHeightSpace(Paint p) { - + p.setTextSize(mTextSize); - + String label = getLongestLabel(); return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index dad057e20f..f199619c9b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; @@ -58,6 +59,8 @@ public class BarLineChartTouchListener mClosestDataSetToTouch; + /** the chart the listener represents */ private T mChart; @@ -182,6 +185,8 @@ private void saveTouchStart(MotionEvent event) { mSavedMatrix.set(mMatrix); mTouchStartPoint.set(event.getX(), event.getY()); + + mClosestDataSetToTouch = mChart.getDataSetByTouchPoint(event.getX(), event.getY()); } /** @@ -195,16 +200,16 @@ private void performDrag(MotionEvent event) { PointF dragPoint = new PointF(event.getX(), event.getY()); // check if axis is inverted -// if (mChart.isInvertYAxisEnabled()) { -// -// -// mMatrix.postTranslate(dragPoint.x - mTouchStartPoint.x, -(dragPoint.y -// - mTouchStartPoint.y)); -// } -// else { + if (mChart.isAnyAxisInverted() && mClosestDataSetToTouch != null + && mChart.getAxis(mClosestDataSetToTouch.getAxisDependency()).isInverted()) { + + mMatrix.postTranslate(dragPoint.x - mTouchStartPoint.x, -(dragPoint.y + - mTouchStartPoint.y)); + } + else { mMatrix.postTranslate(dragPoint.x - mTouchStartPoint.x, dragPoint.y - mTouchStartPoint.y); -// } + } } /** @@ -336,20 +341,19 @@ private static float getYDist(MotionEvent e) { * @return */ public PointF getTrans(float x, float y) { - + ViewPortHandler vph = mChart.getViewPortHandler(); float xTrans = x - vph.offsetLeft(); float yTrans = 0f; // check if axis is inverted -// if (mChart.isInvertYAxisEnabled()) { -// yTrans = -(y - vph.offsetTop()); -// } -// else { - + if (mChart.isAnyAxisInverted() && mClosestDataSetToTouch != null + && mChart.getAxis(mClosestDataSetToTouch.getAxisDependency()).isInverted()) { + yTrans = -(y - vph.offsetTop()); + } else { yTrans = -(mChart.getMeasuredHeight() - y - vph.offsetBottom()); -// } + } return new PointF(xTrans, yTrans); } @@ -409,21 +413,21 @@ public void onLongPress(MotionEvent e) { l.onChartLongPressed(e); } -// else if (mTouchMode == NONE) { -// -// mChart.fitScreen(); -// -// Log.i("BarlineChartTouch", -// "Longpress, resetting zoom and drag, adjusting chart bounds to screen."); -// -// // PointF trans = getTrans(e.getX(), e.getY()); -// // -// // mChart.zoomOut(trans.x, trans.y); -// // -// // Log.i("BarlineChartTouch", "Longpress, Zooming Out, x: " + -// // trans.x + -// // ", y: " + trans.y); -// } + // else if (mTouchMode == NONE) { + // + // mChart.fitScreen(); + // + // Log.i("BarlineChartTouch", + // "Longpress, resetting zoom and drag, adjusting chart bounds to screen."); + // + // // PointF trans = getTrans(e.getX(), e.getY()); + // // + // // mChart.zoomOut(trans.x, trans.y); + // // + // // Log.i("BarlineChartTouch", "Longpress, Zooming Out, x: " + + // // trans.x + + // // ", y: " + trans.y); + // } } @Override From 9bd5ce6b9895a93f38296d098aeccf72f964172f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 12:21:24 +0100 Subject: [PATCH 0138/1390] Fixed clipping issues in HorizontalBarChart. --- .../renderer/HorizontalBarChartRenderer.java | 227 +++++++++++++++++- 1 file changed, 220 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 3ea52e3d85..e695ef2945 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Paint.Align; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; @@ -19,19 +20,228 @@ * @author Philipp Jahoda */ public class HorizontalBarChartRenderer extends BarChartRenderer { - + private float xOffset = 0f; private float yOffset = 0f; public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(chart, animator, viewPortHandler); - + mValuePaint.setTextAlign(Align.LEFT); yOffset = Utils.calcTextHeight(mValuePaint, "Q"); xOffset = Utils.convertDpToPixel(4f); } + protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + // the space between bar-groups + float space = mChart.getBarData().getGroupSpace(); + + boolean noStacks = dataSet.getStackSize() == 1 ? true : false; + + ArrayList entries = dataSet.getYVals(); + + // do the drawing + for (int j = 0; j < dataSet.getEntryCount() * mAnimator.getPhaseX(); j++) { + + BarEntry e = entries.get(j); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + j * (mChart.getBarData().getDataSetCount() - 1) + index + + space * j + space / 2f; + float y = e.getVal(); + + // no stacks + if (noStacks) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + + // avoid drawing outofbounds values + if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) + break; + + if (!mViewPortHandler.isInBoundsBottom(mBarRect.top)) + continue; + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + // Set the color for the currently drawn value. If the index + // is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j)); + c.drawRect(mBarRect, mRenderPaint); + + } else { // stacked bars + + float[] vals = e.getVals(); + + // we still draw stacked bars, but there could be one + // non-stacked + // in between + if (vals == null) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + mRenderPaint.setColor(dataSet.getColor(0)); + c.drawRect(mBarRect, mRenderPaint); + + } else { + + float all = e.getVal(); + + // if drawing the bar shadow is enabled + if (mChart.isDrawBarShadowEnabled()) { + + prepareBar(x, y, dataSet.getBarSpace(), trans); + mRenderPaint.setColor(dataSet.getBarShadowColor()); + c.drawRect(mBarShadow, mRenderPaint); + } + + // draw the stack + for (int k = 0; k < vals.length; k++) { + + all -= vals[k]; + + prepareBar(x, vals[k] + all, dataSet.getBarSpace(), trans); + + mRenderPaint.setColor(dataSet.getColor(k)); + c.drawRect(mBarRect, mRenderPaint); + } + } + + // avoid drawing outofbounds values + if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) + break; + } + } + } + + @Override + public void drawValues(Canvas c) { + // if values are drawn + if (passesCheck()) { + + ArrayList dataSets = mChart.getBarData().getDataSets(); + + float posOffset = 0f; + float negOffset = 0f; + boolean drawValueAboveBar = mChart.isDrawValueAboveBarEnabled(); + + // calculate the correct offset depending on the draw position of + // the value + posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( + mValuePaint, + "8") * 1.5f); + negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils + .convertDpToPixel(5)); + + for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { + + BarDataSet dataSet = dataSets.get(i); + + if (!dataSet.isDrawValuesEnabled()) + continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + + ValueFormatter formatter = dataSet.getValueFormatter(); + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + ArrayList entries = dataSet.getYVals(); + + float[] valuePoints = getTransformedValues(trans, entries, i); + + // if only single values are drawn (sum) + if (!mChart.isDrawValuesForWholeStackEnabled()) { + + for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsX(valuePoints[j])) + continue; + + if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) + break; + + if(!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + continue; + + float val = entries.get(j / 2).getVal(); + + drawValue(c, val, valuePoints[j], + valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset), formatter); + } + + // if each value of a potential stack should be drawn + } else { + + for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { + + if (!mViewPortHandler.isInBoundsX(valuePoints[j])) + continue; + + if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) + break; + + if(!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + continue; + + BarEntry e = entries.get(j / 2); + + float[] vals = e.getVals(); + + // we still draw stacked bars, but there is one + // non-stacked + // in between + if (vals == null) { + + drawValue(c, e.getVal(), valuePoints[j], + valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset), + formatter); + + } else { + + float[] transformed = new float[vals.length * 2]; + int cnt = 0; + float add = e.getVal(); + + for (int k = 0; k < transformed.length; k += 2) { + + add -= vals[cnt]; + transformed[k + 1] = (vals[cnt] + add) * mAnimator.getPhaseY(); + cnt++; + } + + trans.pointValuesToPixel(transformed); + + for (int k = 0; k < transformed.length; k += 2) { + + drawValue(c, vals[k / 2], valuePoints[j], + transformed[k + 1] + + (vals[k / 2] >= 0 ? posOffset : negOffset), + formatter); + } + } + } + } + } + } + } + @Override protected void prepareBar(float x, float y, float barspace, Transformer trans) { @@ -53,17 +263,20 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { mBarRect.bottom); } } - + @Override - public float[] getTransformedValues(Transformer trans, ArrayList entries, int dataSetIndex) { - return trans.generateTransformedValuesHorizontalBarChart(entries, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); + public float[] getTransformedValues(Transformer trans, ArrayList entries, + int dataSetIndex) { + return trans.generateTransformedValuesHorizontalBarChart(entries, dataSetIndex, + mChart.getBarData(), mAnimator.getPhaseY()); } - + @Override protected void drawValue(Canvas c, float val, float xPos, float yPos, ValueFormatter formatter) { super.drawValue(c, val, xPos + xOffset, yPos + yOffset, formatter); } - + + @Override protected boolean passesCheck() { return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleY(); From 74c4c166a5483fd18ec4bf25b9f103197a13dc9b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 12:46:50 +0100 Subject: [PATCH 0139/1390] Added method setViewPortOffsets(...) to customly set the chart border offsets. --- .../mpchartexample/LineChartActivity1.java | 1 + .../LineChartActivityColored.java | 15 +-- .../charting/charts/BarLineChartBase.java | 114 ++++++++++++------ .../charting/renderer/LegendRenderer.java | 4 +- .../charting/renderer/ViewPortHandler.java | 8 +- 5 files changed, 89 insertions(+), 53 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 30a2822ff4..a2a5bc1edb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -267,6 +267,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + // redraw mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index d08b584745..b21c385a07 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -75,6 +75,9 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setPinchZoom(false); chart.setBackgroundColor(color); + + // set custom chart offsets (automatic offset calculation is hereby disabled) + chart.setViewPortOffsets(10, 0, 10, 0); // add data chart.setData(data); @@ -89,18 +92,10 @@ private void setupChart(LineChart chart, LineData data, int color) { l.setTextColor(Color.WHITE); l.setTypeface(mTf); - YAxis leftAxis = chart.getAxisLeft(); - leftAxis.setTextColor(Color.WHITE); - leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(4); - leftAxis.setDrawGridLines(false); - + chart.getAxisLeft().setEnabled(false); chart.getAxisRight().setEnabled(false); - XAxis x = chart.getXAxis(); - x.setTextColor(Color.WHITE); - x.setTypeface(mTf); - x.setDrawGridLines(false); + chart.getXAxis().setEnabled(false); // animate calls invalidate()... chart.animateX(2500); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index eb71bd462d..fe9f013e7c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -313,62 +313,65 @@ protected void calcMinMax() { @Override protected void calculateOffsets() { - float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; + if (!mCustomViewPortEnabled) { - // setup offsets for legend - if (mLegend != null && mLegend.isEnabled()) { + float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART - || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { + // setup offsets for legend + if (mLegend != null && mLegend.isEnabled()) { - offsetRight += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f; + if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART + || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + offsetRight += mLegend.mTextWidthMax + mLegend.getXOffset() * 2f; - offsetBottom += mLegend.mTextHeightMax * 3f; + } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + + offsetBottom += mLegend.mTextHeightMax * 3f; + } } - } - // offsets for y-labels - if (mAxisLeft.isEnabled()) { - offsetLeft += mAxisLeft.getRequiredWidthSpace(mAxisRendererLeft.getAxisPaint()); - } + // offsets for y-labels + if (mAxisLeft.isEnabled()) { + offsetLeft += mAxisLeft.getRequiredWidthSpace(mAxisRendererLeft.getAxisPaint()); + } - if (mAxisRight.isEnabled()) { - offsetRight += mAxisRight.getRequiredWidthSpace(mAxisRendererRight.getAxisPaint()); - } + if (mAxisRight.isEnabled()) { + offsetRight += mAxisRight.getRequiredWidthSpace(mAxisRendererRight.getAxisPaint()); + } - float xlabelheight = mXAxis.mLabelHeight * 2f; + float xlabelheight = mXAxis.mLabelHeight * 2f; - if (mXAxis.isEnabled()) { + if (mXAxis.isEnabled()) { - // offsets for x-labels - if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + // offsets for x-labels + if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - offsetBottom += xlabelheight; + offsetBottom += xlabelheight; - } else if (mXAxis.getPosition() == XAxisPosition.TOP) { + } else if (mXAxis.getPosition() == XAxisPosition.TOP) { - offsetTop += xlabelheight; + offsetTop += xlabelheight; - } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { - offsetBottom += xlabelheight; - offsetTop += xlabelheight; + offsetBottom += xlabelheight; + offsetTop += xlabelheight; + } } - } - float min = Utils.convertDpToPixel(10f); + float min = Utils.convertDpToPixel(10f); - mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), - Math.max(min, offsetRight), Math.max(min, offsetBottom)); + mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), + Math.max(min, offsetRight), Math.max(min, offsetBottom)); - if (mLogEnabled) { - Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop - + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); - Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); + if (mLogEnabled) { + Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); + Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); + } } prepareOffsetMatrix(); @@ -589,6 +592,43 @@ public void moveViewTo(int xIndex, float yValue, AxisDependency axis) { mViewPortHandler.centerViewPort(pts, this); } + /** flag that indicates if a custom viewport offset has been set */ + private boolean mCustomViewPortEnabled = false; + + /** + * Sets custom offsets for the current ViewPort (the offsets on the sides of + * the actual chart window). Setting this will prevent the chart from + * automatically calculating it's offsets. Use resetViewPortOffsets() to + * undo this. + * + * @param left + * @param top + * @param right + * @param bottom + */ + public void setViewPortOffsets(final float left, final float top, + final float right, final float bottom) { + + mCustomViewPortEnabled = true; + + post(new Runnable() { + + @Override + public void run() { + mViewPortHandler.restrainViewPort(left, top, right, bottom); + } + }); + } + + /** + * Resets all custom offsets set via setViewPortOffsets(...) method. Allows + * the chart to again calculate all offsets automatically. + */ + public void resetViewPortOffsets() { + mCustomViewPortEnabled = false; + calculateOffsets(); + } + /** * ################ ################ ################ ################ */ @@ -932,7 +972,7 @@ public Entry getEntryByTouchPoint(float x, float y) { } return null; } - + /** * returns the DataSet object displayed at the touched position of the chart * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index f80fd0d629..2889c9b0ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -183,7 +183,7 @@ public void renderLegend(Canvas c, Legend legend) { switch (legend.getPosition()) { case BELOW_CHART_LEFT: - posX = mViewPortHandler.contentLeft(); + posX = mViewPortHandler.contentLeft() + xoffset; posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = 0; i < labels.length; i++) { @@ -208,7 +208,7 @@ public void renderLegend(Canvas c, Legend legend) { break; case BELOW_CHART_RIGHT: - posX = mViewPortHandler.contentRight(); + posX = mViewPortHandler.contentRight() - xoffset;; posY = mViewPortHandler.getChartHeight() - yoffset; for (int i = labels.length - 1; i >= 0; i--) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java index 086214a076..f0970ec379 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java @@ -41,10 +41,10 @@ public ViewPortHandler() { } - public ViewPortHandler(float width, float height) { - mChartHeight = height; - mChartWidth = width; - } +// public ViewPortHandler(float width, float height) { +// mChartHeight = height; +// mChartWidth = width; +// } public void setChartDimens(float width, float height) { mChartHeight = height; From 02e8149f5d40cdabc4692f1dbac93ed9d20309f7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 17:05:28 +0100 Subject: [PATCH 0140/1390] Fixes concerning BarChart. Stacked values can now be highlighted separately, HorizontalBarChart now supports stacked-values. --- .../mpchartexample/BarChartActivity.java | 3 +- .../BarChartActivityMultiDataset.java | 3 +- .../mpchartexample/DrawChartActivity.java | 3 +- .../DynamicalAddingActivity.java | 3 +- .../HorizontalBarChartActivity.java | 3 +- .../InvertedLineChartActivity.java | 3 +- .../mpchartexample/LineChartActivity1.java | 3 +- .../mpchartexample/LineChartActivity2.java | 3 +- .../MultiLineChartActivity.java | 3 +- .../mpchartexample/PieChartActivity.java | 3 +- .../RealtimeLineChartActivity.java | 3 +- .../mpchartexample/ScatterChartActivity.java | 3 +- .../mpchartexample/StackedBarActivity.java | 21 ++-- .../mikephil/charting/charts/BarChart.java | 100 +++++++++++------- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/charts/HorizontalBarChart.java | 8 +- .../mikephil/charting/data/BarData.java | 59 ++++++----- .../mikephil/charting/data/BarDataSet.java | 11 +- .../mikephil/charting/data/BarEntry.java | 37 ++++--- .../OnChartValueSelectedListener.java | 5 +- .../charting/renderer/BarChartRenderer.java | 5 +- .../renderer/HorizontalBarChartRenderer.java | 6 +- .../mikephil/charting/utils/Highlight.java | 38 ++++++- 23 files changed, 217 insertions(+), 111 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index c5d9f91ceb..f614149d4c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -31,6 +31,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.ValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -270,7 +271,7 @@ private void setData(int count, float range) { @SuppressLint("NewApi") @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { if (e == null) return; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 0044720833..7f131a43d5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.LargeValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -249,7 +250,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + dataSetIndex); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 5cf95aef1a..35b8215648 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnDrawListener; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -161,7 +162,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + ", DataSet index: " + dataSetIndex); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index fca67d8ee8..203188bfcb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -155,7 +156,7 @@ private void removeDataSet() { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 1c1ad75209..43232e875b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -30,6 +30,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -268,7 +269,7 @@ private void setData(int count, float range) { @SuppressLint("NewApi") @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { if (e == null) return; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 97e28e092f..a2284d3e5b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -248,7 +249,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + ", DataSet index: " + dataSetIndex); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index a2a5bc1edb..3765902144 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -28,6 +28,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -369,7 +370,7 @@ public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, floa } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 6e0c13cb2e..9b58f437bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -28,6 +28,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -327,7 +328,7 @@ private void setData(int count, float range) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index f3a1836b6c..666bc45006 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -237,7 +238,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + ", DataSet index: " + dataSetIndex); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 5119f88c29..fa8c91483c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -227,7 +228,7 @@ private void setData(int count, float range) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { if (e == null) return; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index de6ea80883..6ae19d6f92 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; public class RealtimeLineChartActivity extends DemoBase implements @@ -164,7 +165,7 @@ private LineDataSet createSet() { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index bebe9b5110..f63c7e99ca 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -25,6 +25,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -234,7 +235,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + ", DataSet index: " + dataSetIndex); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index d2482ca66a..a372a26e1a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -26,6 +26,7 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -62,8 +63,9 @@ protected void onCreate(Bundle savedInstanceState) { // if more than 60 entries are displayed in the chart, no values will be // drawn mChart.setMaxVisibleValueCount(60); - - // if false values are only drawn for the stack sum, else each value is drawn + + // if false values are only drawn for the stack sum, else each value is + // drawn mChart.setDrawValuesForWholeStack(true); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); @@ -72,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis yLabels = mChart.getAxisLeft(); -// yLabels.setPosition(YLabelPosition.BOTH_SIDED); + // yLabels.setPosition(YLabelPosition.BOTH_SIDED); yLabels.setLabelCount(5); yLabels.setValueFormatter(new MyValueFormatter()); @@ -199,20 +201,20 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvY.setText("" + (mSeekBarY.getProgress())); ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress()+1; i++) { + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { xVals.add(mMonths[i % mMonths.length]); } ArrayList yVals1 = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress()+1; i++) { + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { float mult = (mSeekBarY.getProgress() + 1); float val1 = (float) (Math.random() * mult) + mult / 3; float val2 = (float) (Math.random() * mult) + mult / 3; float val3 = (float) (Math.random() * mult) + mult / 3; yVals1.add(new BarEntry(new float[] { - val1, val2, val3 + val1, val2, val3 }, i)); } @@ -245,10 +247,11 @@ public void onStopTrackingTouch(SeekBar seekBar) { } @Override - public void onValueSelected(Entry e, int dataSetIndex) { + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + + BarEntry entry = (BarEntry) e; Log.i("VAL SELECTED", - "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() - + ", DataSet index: " + dataSetIndex); + "Value: " + entry.getVals()[h.getStackIndex()]); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index ff25a6147a..7ee49b81dd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -115,66 +115,94 @@ public Highlight getHighlightByTouchPoint(float x, float y) { mLeftAxisTransformer.pixelsToValue(pts); - // for barchart, we only need x-val - double xTouchVal = pts[0]; - double base = xTouchVal; - - if (xTouchVal < mXChartMin || xTouchVal > mXChartMax) + if (pts[0] < mXChartMin || pts[0] > mXChartMax) return null; - return getHighlight(base); + return getHighlight(pts[0], pts[1]); } /** * Returns the correct Highlight object (including xIndex and dataSet-index) * for the specified touch position. * - * @param touchPositionBase + * @param xPosition * @return */ - protected Highlight getHighlight(double touchPositionBase) { + protected Highlight getHighlight(double xPosition, double yPosition) { int setCount = mData.getDataSetCount(); int valCount = mData.getXValCount(); - if (setCount <= 1) { - return new Highlight((int) Math.round(touchPositionBase), 0); - } + // only one dataset exists + if (!mData.isGrouped()) { + + int dataSet = 0; + int xIndex = (int) Math.round(xPosition); + + if (!mData.getDataSetByIndex(dataSet).isStacked()) + return new Highlight(xIndex, dataSet); + else + return getStackedHighlight(xIndex, dataSet, yPosition); + + // if this bardata is grouped into more datasets + } else { + + // calculate how often the group-space appears + int steps = (int) ((float) xPosition / ((float) setCount + mData.getGroupSpace())); - // calculate how often the group-space appears - int steps = (int) ((float) touchPositionBase / ((float) setCount + mData.getGroupSpace())); + float groupSpaceSum = mData.getGroupSpace() * (float) steps; - float groupSpaceSum = mData.getGroupSpace() * (float) steps; + float baseNoSpace = (float) xPosition - groupSpaceSum; - float baseNoSpace = (float) touchPositionBase - groupSpaceSum; + if (mLogEnabled) + Log.i(LOG_TAG, "base: " + xPosition + ", steps: " + steps + ", groupSpaceSum: " + + groupSpaceSum + + ", baseNoSpace: " + baseNoSpace); - if (mLogEnabled) - Log.i(LOG_TAG, "base: " + touchPositionBase + ", steps: " + steps + ", groupSpaceSum: " - + groupSpaceSum - + ", baseNoSpace: " + baseNoSpace); + int dataSetIndex = (int) baseNoSpace % setCount; + int xIndex = (int) baseNoSpace / setCount; - int dataSetIndex = (int) baseNoSpace % setCount; - int xIndex = (int) baseNoSpace / setCount; + if (mLogEnabled) + Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - if (mLogEnabled) - Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); + // check bounds + if (xIndex < 0) { + xIndex = 0; + dataSetIndex = 0; + } else if (xIndex >= valCount) { + xIndex = valCount - 1; + dataSetIndex = setCount - 1; + } - // check bounds - if (xIndex < 0) { - xIndex = 0; - dataSetIndex = 0; - } else if (xIndex >= valCount) { - xIndex = valCount - 1; - dataSetIndex = setCount - 1; + // check bounds + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; + + if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) + return new Highlight(xIndex, dataSetIndex); + else + return getStackedHighlight(xIndex, dataSetIndex, yPosition); } + } - // check bounds - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; + /** + * This method creates the Highlight object that also indicates which value + * of a stacked BarEntry has been selected. + * + * @param xIndex + * @param dataSet + * @param yValue + * @return + */ + protected Highlight getStackedHighlight(int xIndex, int dataSet, double yValue) { - return new Highlight(xIndex, dataSetIndex); + BarEntry entry = mData.getDataSetByIndex(dataSet).getEntryForXIndex(xIndex); + int stackIndex = entry.getClosestIndexAbove((float) yValue); + Highlight h = new Highlight(xIndex, dataSet, stackIndex); + Log.i(LOG_TAG, h.toString()); + return h; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 00e80c3d0c..665e6e3f91 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -504,7 +504,7 @@ public void highlightTouch(Highlight high) { Entry e = mData.getEntryForHighlight(high); // notify the listener - mSelectionListener.onValueSelected(e, high.getDataSetIndex()); + mSelectionListener.onValueSelected(e, high.getDataSetIndex(), high); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index e74730c4b2..8ce78c4205 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -156,13 +156,9 @@ public Highlight getHighlightByTouchPoint(float x, float y) { mLeftAxisTransformer.pixelsToValue(pts); - // for barchart, we only need x-val - double yTouchVal = pts[1]; - double base = yTouchVal; - - if (yTouchVal < mXChartMin || yTouchVal > mXChartMax) + if (pts[1] < mXChartMin || pts[1] > mXChartMax) return null; - return getHighlight(base); + return getHighlight(pts[1], pts[0]); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 5f810a2b61..d10d6f006d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -13,10 +13,10 @@ public class BarData extends BarLineScatterCandleData { /** the space that is left between groups of bars */ private float mGroupSpace = 0.8f; -// /** -// * The maximum space (in pixels on the screen) a single bar can consume. -// */ -// private float mMaximumBarWidth = 100f; + // /** + // * The maximum space (in pixels on the screen) a single bar can consume. + // */ + // private float mMaximumBarWidth = 100f; public BarData() { super(); @@ -77,24 +77,35 @@ public float getGroupSpace() { public void setGroupSpace(float percent) { mGroupSpace = percent / 100f; } -// -// /** -// * Sets the maximum width (in density pixels) a single bar in the barchart -// * should consume. -// * -// * @param max -// */ -// public void setBarWidthMaximum(float max) { -// mMaximumBarWidth = Utils.convertDpToPixel(max); -// } -// -// /** -// * Returns the maximum width (in density pixels) a single bar in the -// * barchart should consume. -// * -// * @return -// */ -// public float getBarWidthMaximum() { -// return mMaximumBarWidth; -// } + + /** + * Returns true if this BarData object contains grouped DataSets (more than + * 1 DataSet). + * + * @return + */ + public boolean isGrouped() { + return mDataSets.size() > 1 ? true : false; + } + + // + // /** + // * Sets the maximum width (in density pixels) a single bar in the barchart + // * should consume. + // * + // * @param max + // */ + // public void setBarWidthMaximum(float max) { + // mMaximumBarWidth = Utils.convertDpToPixel(max); + // } + // + // /** + // * Returns the maximum width (in density pixels) a single bar in the + // * barchart should consume. + // * + // * @return + // */ + // public float getBarWidthMaximum() { + // return mMaximumBarWidth; + // } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index 4638467050..899f9f0de9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -45,7 +45,7 @@ public BarDataSet(ArrayList yVals, String label) { @Override public DataSet copy() { - + ArrayList yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { @@ -108,6 +108,15 @@ public int getStackSize() { return mStackSize; } + /** + * Returns true if this DataSet is stacked (stacksize > 1) or not. + * + * @return + */ + public boolean isStacked() { + return mStackSize > 1 ? true : false; + } + /** * returns the overall entry count, including counting each stack-value * individually diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index f4a2f1ddca..52de15090a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -98,21 +98,32 @@ public int getClosestIndexAbove(float val) { if (mVals == null) return 0; + + int index = mVals.length - 1; + float remainder = 0f; - float dist = 0f; - int closestIndex = 0; - - for (int i = 0; i < mVals.length; i++) { - - float newDist = Math.abs((getVal() - mVals[i]) - val); - - if (newDist < dist && mVals[i] > val) { - dist = newDist; - closestIndex = i; - } + while(index > 0 && val > mVals[index] + remainder) { + remainder += mVals[index]; + index--; } - - return closestIndex; + + return index; + } + + public float getBelowSum(int stackIndex) { + + if (mVals == null) + return 0; + + float remainder = 0f; + int index = mVals.length - 1; + + while(index > stackIndex) { + remainder += mVals[index]; + index--; + } + + return remainder; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 7972a997c2..798d19f34f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.listener; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.Highlight; /** * Listener for callbacks when selecting values inside the chart by @@ -17,8 +18,10 @@ public interface OnChartValueSelectedListener { * @param e The selected Entry. * @param dataSetIndex The index in the datasets array of the data object * the Entrys DataSet is in. + * @param h the corresponding highlight object that contains information + * about the highlighted position */ - public void onValueSelected(Entry e, int dataSetIndex); + public void onValueSelected(Entry e, int dataSetIndex, Highlight h); /** * Called when nothing has been selected or an "un-select" has been made. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 108f7fbcc7..9451d89696 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -11,7 +11,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -333,7 +332,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (index < mChart.getBarData().getYValCount() && index >= 0 && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { - Entry e = mChart.getBarData().getDataSetByIndex(dataSetIndex) + BarEntry e = mChart.getBarData().getDataSetByIndex(dataSetIndex) .getEntryForXIndex(index); if (e == null) @@ -344,7 +343,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // calculate the correct x-position float x = index * setCount + dataSetIndex + groupspace / 2f + groupspace * index; - float y = e.getVal(); + float y = h.getStackIndex() < 0 ? e.getVal() : e.getVals()[h.getStackIndex()] + e.getBelowSum(h.getStackIndex()); prepareBar(x, y, set.getBarSpace(), trans); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index e695ef2945..993ff11076 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -222,7 +222,7 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { add -= vals[cnt]; - transformed[k + 1] = (vals[cnt] + add) * mAnimator.getPhaseY(); + transformed[k] = (vals[cnt] + add) * mAnimator.getPhaseY(); cnt++; } @@ -230,8 +230,8 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { - drawValue(c, vals[k / 2], valuePoints[j], - transformed[k + 1] + drawValue(c, vals[k / 2], + transformed[k], valuePoints[j+1] + (vals[k / 2] >= 0 ? posOffset : negOffset), formatter); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java b/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java index b7118bab3a..63c4457d34 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java @@ -10,10 +10,13 @@ public class Highlight { /** the x-index of the highlighted value */ private int mXIndex; - + /** the index of the dataset the highlighted value is in */ private int mDataSetIndex; + /** index which value of a stacked bar entry is highlighted, default -1 */ + private int mStackIndex = -1; + /** * constructor * @@ -26,6 +29,20 @@ public Highlight(int x, int dataSet) { this.mDataSetIndex = dataSet; } + /** + * Constructor, only used for stacked-barchart. + * + * @param x the index of the highlighted value on the x-axis + * @param val the value at the position the user touched + * @param dataSet the index of the DataSet the highlighted value belongs to + * @param stackIndex references which value of a stacked-bar entry has been + * selected + */ + public Highlight(int x, int dataSet, int stackIndex) { + this(x, dataSet); + mStackIndex = stackIndex; + } + /** * returns the index of the DataSet the highlighted value is in * @@ -44,6 +61,16 @@ public int getXIndex() { return mXIndex; } + /** + * Only needed if a stacked-barchart entry was highlighted. References the + * selected value within the stacked-entry. + * + * @return + */ + public int getStackIndex() { + return mStackIndex; + } + /** * returns true if this highlight object is equal to the other (compares * xIndex and dataSetIndex) @@ -56,10 +83,17 @@ public boolean equalTo(Highlight h) { if (h == null) return false; else { - if (this.mDataSetIndex == h.mDataSetIndex && this.mXIndex == h.mXIndex) + if (this.mDataSetIndex == h.mDataSetIndex && this.mXIndex == h.mXIndex + && this.mStackIndex == h.mStackIndex) return true; else return false; } } + + @Override + public String toString() { + return "Highlight, xIndex: " + mXIndex + ", dataSetIndex: " + mDataSetIndex + + ", stackIndex (only stacked barentry): " + mStackIndex; + } } From 365ea5fe38c39557d015fa0142cff91030b13a36 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 17:12:30 +0100 Subject: [PATCH 0141/1390] Removed unneccessary logs. --- .../src/com/github/mikephil/charting/charts/BarChart.java | 1 - .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 -- 2 files changed, 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 7ee49b81dd..6c5a25416e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -201,7 +201,6 @@ protected Highlight getStackedHighlight(int xIndex, int dataSet, double yValue) BarEntry entry = mData.getDataSetByIndex(dataSet).getEntryForXIndex(xIndex); int stackIndex = entry.getClosestIndexAbove((float) yValue); Highlight h = new Highlight(xIndex, dataSet, stackIndex); - Log.i(LOG_TAG, h.toString()); return h; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index fe9f013e7c..6bfcf3bf49 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -285,8 +285,6 @@ protected void calcMinMax() { float bottomSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceBottom(); float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); - Log.i(LOG_TAG, "minLeft: " + minLeft + ", maxLeft: " + maxLeft); - mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); From d41be04a3e8541c1c04590c973bae45b54d49c0b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 17:15:11 +0100 Subject: [PATCH 0142/1390] Added jar to example. --- MPChartExample/AndroidManifest.xml | 4 ++-- .../libs/mpandroidchartlibrary-2-0-1.jar | Bin 0 -> 545492 bytes MPChartExample/project.properties | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) create mode 100644 MPChartExample/libs/mpandroidchartlibrary-2-0-1.jar diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 01482fd5c0..19ce5c8176 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="33" + android:versionName="2.0.1" > +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
-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

1>-GiZQceB)p+xoOK*pC|yMXm6{ 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

  • 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

    N?k&{V1m6V20jrLYt==Y^WHI(tu=b!N* zeHmPE4GH`JDT@yXsC8*R|kj$LL?a z6$hzYRY6taFj4s#hnHf%v_M+QKjMaxLK1Y}PPvBGAOSP%?dR7p@vqL(LQD0;39n$Q zbH+sWJil2TEkORDbIuB^-H9vWKL%!x5VIc|v`syR&n@2qCLums@uYaJJeX19uK00+ zl6-EtWeQ<7!%rLvUuRmma=(rmys6kcXlp{d0W7#)=?SRHNnKh=5L2ebDqK2kwmkJF zcIh#!4c*mN0egqn0S|p;Z+y+&#Us`cHjq^`Q4Ze$WDI1Vz-C4dOmD>0%lI11I4+`% zJ&&)zd9CcwvB(>1?q~3P*0Ft9V*5IqGe?FLh6sDpPRZbuqS_Bf=-x$U*%C9xtgl#6 zix%96&HUGex5?0jg5(@t@Kes(nDWP2uV2mU+(Q5+=ky%Cxmv8{&bf+xiE&17(syVzUwn1h4|+Swse8&^<#3py!$QTsuzHlkTSbRmlJ{%n zRKxIMBV3aAyZcx-VTY(4r+B>y8?W{BHJ)#(rAtF@L)S73pz9}ae!@{>%~f|u+!6e$ zg5wx*GT*(B^p~&y-TXc~Ehw`J0t967Z!N6Z_!l_hop0MlA*`$!~t>#UFI3ryQ z8zA1mmF4MV?1hABG%Rj&wI60;1oE|@pqQ)lRMpGtGR4MPPwT19@0@k%E=W+`o6X=V z6D`5ivmjukOmMv4M4dz==!=JO8CP}`RD>dXg;ox2NDK*&c9|YV3Y=^2ua4zUQ1X=z}dh7;Z`IL{}#EN-X813nbUSy zW?A0SI367O_2~)l3fch2^>>|4UI~GX)Ai7_@+AH#4R@#*`^JI}NjLG64%eqWWw=O4 zD0!@yKQPlI#A8n0qIC1Uiq zZB#5Zk}vF83D=Szm?>Fe#@ij@k;SgeFBFP70rCP*YRscTqu%vUPI&J z#K&rbij6p~^9MC_cPpYKPNZS>f2ck^UnrgewXmJ>GlKmm!OaP3AC2rBD@D2bV=2dEXXGA3MT4h0=YAt0H*Ux1A-RTSr^rwwexJ9B%Cz>x zCfQ2)@QsA^Ok--NsldZ%;?eZ?)KJMe09~SLcjl|QI6!(aHpt$|!1eX04I}C18k;OM zEJhh&%%m6j4Hq|WgwYcxVq|Po4DK)Vj;}WO!^KG+eU7;Z~X%CZ_l*SSppzN93hj8u(H}injsP z92Q0gD~TvQeI~ z7hj?_vPmW1Y+=TFBNWj88*ASf+-bLb8*5@a6Wf~Dwr$(iB$?Q@jbCirwr$(E?|c5Z zr|zvfbuOx&FZ;_=wX3?KV zeDUh!`vL=6T80L%`&XJZG76jF>KvDPeDh`~WZkI5=>(h1W9TQ(5`o?w3iU@yehToH zUjpi8D~sO=m=x1!_kBjQZu{%Llw(jCpsy5b7w}S4#G1#pVNTmYmTk_~%cP5E&xN+?iPv8X_CKqQvn5;%34nDkI&=YbC!b!~U$1*U}+t@`b_0(HqQ@a1sOV zL?b?)Xp*}kvEm|5uz!UB9EWw;ZfnXQ5Egf$u(f$(uI^8=`e@sUl}<{)K&L7Ex2Ly# z!OO+M^ki$z^pSwsk=B^{LiM46gKFcuD_-@umi9SiH`xuSJvk`sh9_49IGYW@yzJ@K z2!?dMQM(895L*H!nh}638|BjYtMZlWf(5G1Us>!1FSP1>;T`Y-TBP&w`Th{-_&&us zvS8&Y3zjDtwaPz?W%Y2wtiTR>hxWi~`l&+~W~9*iL)^O>N|H94NJJoZr=VUXduI22 z4e$7n5iMs^M)JnoQWh4jZg3e)7bl#=wmVI3+5qVDijvGWBDn9ssE7bZB}=+5yCoN$ zH=lwNjW2lJAJ$Wnm(Gg%iJn*m>(TQ}Zn_wb7UAt({^4j_C)?7SA}fb2fwuiX;d zC5J~5;pv}?GVBBu0m_zw3J1rQyXqH^dZA6;2BUG1U9~lOJ0^yAgGOzU>dB`s-PLQN z*b;&+{F4X8dSd|1_cJaB-shnqig|$CK7gB7Dw90TocFp1y>6dGSV!F2$s25sV2UUWi>gYG`>wt2gnM*dWW%O+$@-dd~EkdH42 znv3pr*CaX8j#FuY!&cb%@ceee}h&(!vigx40n>^hx*Vt9OviD-p7YYNlQ7 zT#U}j-_?xZ4gS|fv!wQ?W;q9v#6=mWKrVk22@3?JgtLfb??Tyhs*#DIDn$dz81^6-u#DOKg&Cef=|lTH&5GrMGG*WF_BMHsV;fB z8sczFVlt<6oDD5rLj&p#VERT{wZ3#NC4|LJ>FqB5OtpwUhjmWPLxbr$U z`&EUiT7+s^?5x{A#O9DEAGdrS20KUCcLz$k+5OB{hGlK^mi036 zlI@X6e1Pa>z>p=BG{^INLt3`GRpKR%8Jp%A@R=xj<~%4)4=>=hOL%AJi{>IB z0<(@EuO;+9ra=#=`}I4c#E77H#NsITBw_G8v-y%+l-wB~#5jIx%;IeZofMw1>qng^ z?xiy}ZJ|GFN^SJ@k)(b{qd7DrRh1%ll5(yQ?90(Oa^+DnjuAPniX5#GVqGA9vb@=b z)R;6KC+=F+tvkxo*Oz@$epQCnRA`GRT~I5mRPW=6jJUMb4oi_dAHSFayFLwP*wrHRg~+kHqw1^g;l&Wk_JhhlauTWY3b|j zimr>BB%6Jqlak%|!djTavRq><>X`UI6B<{T%I zes0^^a)*1CW!nZ_q#J}q)(acaebbpz2xXF%OC*NfUog_;s(Po*f7GkfbO}1sQ;ian z`DoqMkb0m&4qVTJvP>y6qe8?Kkc3>eifw)Svp&D%CF%5mm_g5*dPwq|(4kJ<9JufD zL_rp~EFQ%+Xi5##)C_BV!?&z^WbvFe@Ui;ExgG9$?O6W2ZSwujw{+p%Ew}J`Hm06Q zJWiXJX>xIldPd7q7o<6L%sB7K?GEt5=#F(Z)@MKb9OVB@)2|Am zhZLWr)CBSc;1be?zG?;ut^ct8`6IDZ)`s3*xKM0rM$o(om!RfC6D189pWRGMW6`v) zVlhv%!p$B~+q#5m4;WojPdrRlwd~7M%g`nj&CoN{^_jogf6{ETmcJV(IGS@<{Io3wg!XC?+eQ9?WN)>*edLc4U9V2OG_TKgbXeRfmLa;^nNq$4{Dkf(4fz)Tu*dS&}bO9ad-+g9Gb0gYt>};Uh|sG?L??=)h*s+kx8*KU5anl zhS4C-Qh?^LZZ!y^ikdLVU%Gq)b?)IoJ^X~S^ui;ntPv?ibYU99jikQQ$stZG#ehSf z7LYo0iL1|lGC9E*tOUO1U_6fWo@N~=e#e3BFlhS@75a7of2$rpR+I6Ka%E>U_3#NC zoj&Fv#h?$>5IbDkSAEAjNEK{N76l|5An_dRY{>Vt_V%X1xp;tUOxG81SIcM~KUKV! zE+WV%k!~2+G)owE;h|31>mI`g#U!Fn8TzZM7aE~PZ1nL88}Mmpt4|r!7b7)EXe&`v zsvk`8ww*W2ZYs`dT zq>sOsA(iv?vr{D1^Sby!0jiTC7*3_)oGUR-(|aY{LyxF%dONv*QoG7VFw_EoIDGO4 z>nDS`DH!t6v@YoIgm5)_aK<#yzA3$pG1bx;0;=NCZdODd`@jsUNS%wp`+c&CZZ+jZ zdI*_>H~JvR7POIqfw|gh`JpYgJBFG0DisS)N!rfdgq{|Rm}8YnN4w?XXBu2fW9Ir# zhi1QPXUfQXT&d^V!DJ=6)hJ-?gTom^)BP>j>45_EA(L9yq6#D40%<3#Yn&G#T+Na4 zn+$nZ_>_Q+#B<>VTD?n79HAUh|e-clE}!j$v9;uvaWA?u#y7qfBymIE+EseK+e3IA}Q@c3vA7JfYSIMSYh zMZqs8ru(x@ApzsG#PcWeV~*6gs00xu%tz3edsDEAncVF+VzpHGr_>`N(^sL?2q0U~ zl(AV({H!(3L(uwYgO@)vQWR#|3b?OPv>}%)TW~Y6Y9v&60bX~yINRC5&!5q|HN>m$ z7~jY_oom+@#qM<@#yjgrS@$f#ie#Khs^1eRCCd9OLgCfO<@W8<$z1=iBl^Z%jD%&* zUJzv0-r;*XepfG4*Wseyh}36jbeGZLwZ?r2Pa8UCHioy3S>w0<2!mndOQKJd+M~+h zyhr$9MgfMay@YaO99HL=DBJ2#BO9-+QKy$E-({LY2XjG(sL$I!0Hd9QF#hlA=*PcY z=JoHX9{nxR@J~Y{%Kx#7_=@dBb*Nn$GanXgh^;iBnqM4skUlDXLLb%0v6;291w)ZD z$*)K+b9Ufw6_IQ&t#q3P2i6Cn>(fh)>HAElE1vG}j~8%#P%RiD*jC5-D!eq;MwPj< zBgp+i%cTa#B(0{^UvpF&N9nd~k>th{p^Vm_>)(vc!s4|PHtRJ{?gfeox3Ga+ru_|W zSoy1qpusD;^@gRPL~#Q^5Lluj8~3W6#_HAXWu^?$CzDLoc=qF{+gGL&Rp}+L;GKS# z>#*}0pQ(Nan&V{EV#$Nk&i4yj=z_>1_ocm;$s#-8dd+xd^+V7t=30NcJEigjKmH){ z^)cMM{$3VeN~DJqD(6b7Pq=qheJ3M{z1STjh>pg}+o$R;jDhS=_j~dut$m{p>^A!D zq{MDgn>Z&5(+GASd=+@y=*IO9?$Emg`EgUFcl|B%SS-%ke?ybYyel7c(2vOTBcdvR zFk^tq5mv}`UZ~{DxIX|~8*%WGBM==qZnw;?xi95rzK8_nOPr!bgnb!OGAQ_uyA7EG zq??8F-CqakCgM$uBBKIn#jQDW?j$!+S~e}!)fM(ZZ!F#tO$TZ}|*ig8$K zuXb0IgFoseKXx(_2<4%Bt9W1f0GeRto%(>RA|A_^L)sm98 zj3IWRe4_B^;SZaMN6GB`okXxKw+(Lj!6ceW9Al9}_Yh5oL9Xv33psf+?lW)+pB0hL z6)7H}g;V~s2k^54@IKNQdky3+H)s{2k7%?U=i}1#Wv*W;F-nhfDsf_Y5lWXQi|Oms zoheqe&3agSnotLlZVqLJYaXkW?W?~^3@*qU*ljkJ?py6v+_S#-4q1pCQch~<6FTP{ z*oH`|S|A)Y&N)4%rnohbHd3q+w3kBs{y{Rd-ZYG#f&c+k|H}dRe{VeVzuf455)Eor zPB><0zN*O$(RIhbxt3TFA-D6&6o0i(1T0lrSZG=(aO!KObvWdv(rcQ4%bd=?MP{crm9=lzJ*+lpGOdBKZLke8LiQkCX#GVmCf3YW^WU21S( z&5S3AIeXphlqrb@*R0KZ5?Y~6T2q;w!jdS-Zc+)3uPyv8%5edpv^pvZOzZ3F63$m;YL;D=BfyR z&EEJH>)^ASYa8xaib}h>ShW~XBKmdC%Ks>ZS z7MwL~Y8JC?rXXKS;2zm9Yr$$I8r1}_0hT5O3kT-{KWNXlRbm(t@Djgaxe}%Wvw+3J zXM@Wt(jJyKMMe6PAAjcNCw{&IPliblDTrYRxvUfuS6aI#<&@C85=yX(cFst>I`;fv zWH!Mftx|Spe+`cX(|Q>i35mUcI$hkV0*~CJxNZ)^ouQ9JHs&CJ&P?iu?ek~1ioijd zVc6hS!il#38qwA8weXiLq6C%?e?M_3)4q~XU$pUgAU3{8`s$d3pLrWAK(|X7SFy$> zsLBv?2ni0-URhu{Jiq}7CKU;8*dbseDeI|M(Nu-XUAliCQ%PPb(thT{qU}Ahn0fa;r806m#ip12*LRW7)Km99G6>47DWY~i(G83wp zs6F@dhqE(EvKkadRue9s4&$?LbBKy0I%%9uCLN2m8%;fKZ*xJZ&k>#GiYgt6oEf^C zbD*unPid71Gk;P3R59x9=X}#ay}`5k5q@=H{!n-@no{<>s-2ol`$MGJSl3m}uYMy@ z+o{5$_mXv|+VUlRu>fnwyO%^1cug ze^=0T=}S|2vcS)EH5p;4NCoZEC%*5ct-???~ulB2R9p> z6AwAk;0+U9*$Zz%O=N5^!A{77lw}Oo;a)>hT!1;k!fZf*Nup90RL0O>csLk?X6-2_ z0LRx0-V90m0H-RuUYBYDa)2j_XQ`s?eC{H#C01mkGk?=2ef`TvwU~o#?+W79+|-&d zo-f4h>Y{dpi?&~2jgcG0>Y@*xjD!h1?dVVwN2MH_ZDv0i$4VybbRLfeb4c_-#tNq^ z-n#G^T*H6^VYJ_n!#zYiyZtt|E1zrBkY!Csw*=%A57;`txz%Y07Oi=|=$F;7=|+T2 zhs`E#2+v8;!6qHzg$TjU#akA?$+PbTvGJ?zd`E&W_e547A^T2ZZ-lX&Y?5@Fx}?IdWQT^Tl_s{XLLgUCO1J&e@o@LL~tc7 ztme|BvG9^>JdqWoN8Do=2luQ`QgpxUOM4d0g?_NBV{^pr@jR04fB9*NLvlqj)KBC$DtxpKe{x(S!riO?C!dVqBbQV>39OB;B~(2psL87 z?GCCR>2^sO(%#xy9?v&2(Hg&)(N$1HDBBT4Jgo7&;oH(YaqQ7GgAIWp9G>YTt_e&G z2WEy2mv5UUV_51jPoz8m);r-#yPJ|+ga41PjpyR%5`IbM;Z32@%%t@Ib7^cW_{=-c zOhr5%d#o8})hmSIR0ItYHn4Jqw{pb`D~gl1mP&19^?+kBRWg&cT6wm2`}V zFCJdS=`T+7EyusCCDX)&M$oF5mqF;+%mZ{v!7KP+5&{{Q(|LZ+} zC*kCwNqB z@g+i%2G5)mz9>00LZ|yh7^WP6AMe@YosCPtYPW9(w7oEqw}M$F!e zldrzO&r3C`-yMo*BgYk>r=?(bR4%&haIy5t;ByMl2c9ZFr*|TJQQqf}iD{D>zN*UO z==TFcb`;2z>^XTn13zj8lQOs5zPY;;!%i>x&1rqjXB<{j(@N-82` z9BR#4oIlfYzv^Ihra5>qa9T4LJax1695>r-cfh9w7zq4I#`uz3ucm8_wVk%_CqBb= zEL)#E?sw#uSMVPJo3rVgapNr&GB)AX+jv)}*~3yYyB-~TlePCqMU-=>ozC~wqxcAd zzh*GLMG~&h;iZq?z5$3UD-}j6 z_6=0T*`dD*blHXStA6J(iMt;91IA3D_d2U!GVHDHG{IEmrYxaW0)bB&NoAtfiRxIlxc55KpjV1-_ChjbkEGDb-{+dFLAnI8Gf^VVYa zIZg-+)?Nwpy`RGJUI7LSnoaDCJbB9LN5h!7N|t5u7wRp$5n^<`-gsD$hN&@&D1jwK z;iu`z)Ze!yu34(0<4P&{BRiU48o>)r6$vAdOI_S>2liP8jkD*xH9=}8YF^D*)ucI0 zz;JFac{z4Pd$&WMa_)RTz3cEdYqXsLNv$H@rm0Iy0vcj+*CX~r8 z6e7+`wvMP28`1yg%(SlqQOs8@VvU z;37$`8Qydisk|&c%DL0Ae!$`e|GJUUuM@{+%I4O5 zvkO}@dMX+b)I*n7I299+^znlA4?WU6Jl`TvARxnksW$QNbydk*{Bzkr)kXH@6R)vM1!vs*1f`&tAw)jdI35ul!UG!>|cFPdv%``6xQ z!?ZHW@G1ox~JFCjZ~I2G`nrihKl#d{R$&lhTZ6%~f20Bd$g z9~J42TZL8%@-5vXj+CEYNjVR>m?Wo4ZV7xur3%(Pmi$s4gn177+01Q7=aFhBX7p8> zwwE35VlCez3CoBrGe{Rq^M|C7fo}$+-)!s(uc%yPA1j3HP%EzogNnDG3cS}@URYB9 zr`2gt$@3%V>g7~z(PM`Kl6s78<#DFnmyCDOo|Q59Td0s=jIa?#Et+?r7~#w=rln8u zp4P=&+pSYzn@71aU@^+&bH==EW_~KesC1aBYhUupg)QzIErffn3Wd5DPP0Y;Jn7}^ z`*92BEg;;6JNIfqXRkxcPq8*=T0*^PsT3o!aMVK4#2iCCy(fW=Ve`4;+9?bx9tr4M zIeoSSNJq%|89ypuDEkHa&9`Kfl)_oX94r_~80^y#1#9*fKQSn5{GiFY?+C=$Oyu*! zP$LQ~vtmymizL^Obs^)hB+=~!j3|`Dg2`?YqZWFnP0<7z{hNEm6m(tYMJO+2ZL#*? zJloN8VXRR8K;tW){UaDNpuCzW(u(cMWq58-rO-0FGXlrhr&#ayq?_`wM62~k(AAMs_-`Fw7a7pPC6C8ATdJKSnZF1gP` z(%EEi{T}M*`wPEkJ#{PD9=$_zSd7O^D(w{wO%4Y}9x_O0u%J3gIu|B+4f7uK@+h&(C!wRM+$oY$qIvC*BP~qK?t-HjPZy9M;<7b63;|C58p+%ZqVX=29(T zcYs+`Hqan{Hk&*O_DyGmZDkbEVV(#2)#W-G>HB|d#>Dt0@UsR30(yo0e^&whPaym6 zXr@tF>u=iRYv`6#w>n`cN(dQ*#D%hJkj|o&Qzm1`0mpvrH%jxajSc-%ahFAB71ZqI@RtG0^Kw3i8s6NMV) z<%eivnTAfn?vp6K_9P$Pw&^?*0<+b3Y=7r$`3cMrL!Ke7FCW-c*-g*6?l)@e_&t^P z4UF_rRIzW#I>qTxm1;SP62&%^)nmRXw&Nw{rt0JgRN>Tb>rxld9w+sMGj2?LO2p@L zO^NF9!V-6=3GV2Fnost0oNpCYWUA)15RmcN6|88u*9|}PZ!>{|esFXXFj{b_7K)0O zx*l~F)x<$B5fN0UI+W+4jycjQB7YK{@;ZzDS-=Xk$aOOOL){=QWi}5n8Tfch<(^0f zRqQX6b6zy)qww$w_bB}aNs#~!IMOHo2QQ()4EKn^6HJ10woclh2PP_22O0fL?Yqyf z)aW5ux6p^ISkDdlTDr#@RyNJYZ?T=5z#?`LQN9Ev_N4_=-P$G}*G>NonQ0X)^qj4Q-|x(^&Ci2RB1Sg`yyX-z8!i zjFLSm%Yy_2C|*bPV)Sk=GxmU$B_QQ!8BeKidG0uFQ3m{9ea74@E`Mg+8lnv}uX-o1 zQHjA`GIlPw`xMi8@?@shhtrl71;+ag zlFiSCPk57eaqqgCtkH#9P~-rgLb(s)q+824^{@|nkTaO9b0CvZD|PGe1+VdVUu<&= z9D{m-qxES~LfzAji?2Mk4~9B|z+cUk`*}Npu;Q9tK)_$i?r7|H4o3A2l$4Y1dAZR} zT>B?`ppF?NBBCgEJAa=2`3vN4Fgf79oxS`kD$@V|puzRu$#J2+s25aN0nD43|BAC-(KtB|Qob0UXqu4Ys-twLwo;Hp>rp9^v zzP>)-^g&}#g)#3Ahr(Qq*A`VJxET4cN>u8LlPWgqCg0*zciEP8?_iprMiddx&wHv~ zkRdUHnR!@p*)D1GNEBFN&Ngf{{^;Jgth=&VWyVG{ ziGXQwIV+bEV4Nwz3hBYSM>)&9%`p_V8*y-b5=={O{{f5V;r{NQb&xq}8DrSp7g)WE z;bkD5{F>jn#?1dE(*IP)L7bmz8mg8_kT^q*A*>Cq2JIG0!34GW5mcbcG@zxtWDDP;{IM=e;B#Lgn3Q*yH zk|-F)Va)xl-Z&}XiVdI^nX=O2g$?_MM9@|sYETYyMo3&1lo3Ov)J`QRKILj=nw}7O zX4;h&a`%T%?KEp%jA8Pc)i35`g z^~a-h&JRPW18B=XqrG&pjxQ$S(0YAFpL$GuUj89q7j|wUvjqYKl=Ck+lz(r)>wm8- z6e(-Tp(r4J!P8o6G&$00ihzTiMxoyZDDv0nlhCEB1M(4$8a5jsn^LTs$sSkv_7bYo z#U)4>dEd|YZv5QS>H&)2LSY#f*&I$?X|G+YtDhgA{bE4%>MAq6h?9vhwV5^di_Vol zo1z?bQ){KOwVEi73^i=;S3t85m#8!(`c-#KQ+YT=F+>Vjqw}l;P=h)L5MfTVKEPvC zY{E5bX>{jB2BX=#?)o25EXY>4jyv*Lb195r zQ)!>f&VyCcuHpa45hH%>`o&t9!?wW>c30`H$HfLd=1*fq=H8c@T&1gtDBnbM1 zxCTtgWV1@)5O@i+#$}OTt=3P z3~7cT@~2P>?IIjyytKLy*t~GCS$+J3099`ZGR8bZpwwS4>R!?Ah?bhfmI<7ieNwNG z=EIOTEO-DUxv-&^F<+Hc3*mbnDl%!ku}UF*l>u-B%U%!{QOfdZQnpgwI4pO;Ajd2gFs)`FThJ zjfdUcgX@5j%mBR|S0Q)fMOP|_e;cI*c@U2xwc;)!tLTU8~?J@UU@W{AMv zZuT#iVfvRl7XCfj@jsU<{BtILse~hf`EBE9Z;#7T)X|`fC`nD|j~}EN_fxXBVS#_K z!nuLjCHWv&JEOT(8}}^IFIewmN6qYG=Ohx;(u~vhsrrV#mbcxlv-QuoxZ(Y-tKIYJ z_W1q9)nT>YmpiaN7J|wECi?wior8J%;E=yUQ;ue1z7Er!$W@E$;S7a+3XW-Zd)1+} zl3q|>&C|A&trNMK8jar}dNrzKvikH)yRDkFTOeU}=C+x9Q#rVl5bh_Z=ghdhY~{LD zA_C1ZFdu~mY=5g|cFI$$QG}bHyhDU*R_}-l317cGW13fA_nv5fQIE{^IYjpPDj4dPcz;G2s;u0LU!5k6%wa5FZdJRn|Yr;&rHyc--d znG4dS1xKT!YVLLN+;MS{SD{w;m=i=M(BJn~ebxcRZhmv@2Y6dRJmK~;Lbkex;yw6g zmWxNGC_L?Rw2{MddAn)cGR^$gTKuzPQ_fjiF>xSL8`^kRK%2h1+%UveiIGJD%atmg z16C02)ysYwu(hGopiNtk-1OPXP)K2+A)bPUm@eU;r1F;jngxq=7USB2eSB3)72}y4 zxDRL*4!ri20w0xwM;^-G+)BE8CcXnbbqf^{o5c$zf)Fw($2nJb>3#}Urj5G?fJ$0j zWWu-eK2V`c*hZUYp9@Pp{opaQke9H&S+m4!s!o9Xc??2uE^z=5W`3v>6EC4ZZ*jKze1>GsP6vN@NG!x5j6chf$g6n18!+*oU)VLFag3A^ zU5Z^3Q4DW`s#(XBjxDrre_~uXBNJy`1J*$V$yX&Zy(x6i^vxv^iZO4?|9KK;?vxpRwOYz7dZEy@&}N1ekqV78~w6;w(;&@G9SIeG651_NH%o zT+h@xydobv2^d;mxOnwnP*yjCj5c&shLTq8y2Y+r>SUM+7`>nGu2*wFSe1}ZAqW98 z(OnX)T|pHCjAGYP>Ir9x&PxM&w)7~B*xhnw;R@a$IU~~2$V(+G#XW_g1_Qc^rTGDa zP`*kR>6rK6jne)sbF=C2cPfv3WoBl$|@pfv|0ikP89yjv~_Uj|3 z-%f)?75rWE7RzDww3>3g?lsN(dcVEx3u%vILZA(T(rU?}Is-7|!J$6a(gc*I7`EnH zs(Th8j#ngOj~^(H&qZ=vF{d8}is_$OS7Ub?>S^~z*ONOpvI)qIhsi2 z&TVs3tUg(4;3rAkQqC!_Z5#Xz-7nuf-)1q0(-%LsgEjs$*xg+xm$?9gs$7K~$^%fe zdvGdzp**QZW5mVlBM2*3m%a>QzaJmKp6iaxnu`MB1H-vDF#bk`d-`+WM7&`WEj&pV@7E& z`&eBne$RUt^qaEZIofkkUnf6;V%$O(I!W$t(*mYVc)bse8j;U@IfUy)IO)aNbZ7CAz=q{5kP z2AMvG)k|&;m0ppb5cjX$@}P1WXiJHI1}%vOf;rE{A{dvu5SP%NxGqM+=Qym=fn?aQ zTv4j6zXpfLmn)y-7N!@QzSX!axoi-nI6J2DRn;eLc5H9jkDmK;rQq&AjS)^Q%E4_B zdtcWTVa!arWT4O4G9cq^_7957O~ZQ<)6aAV=7p{Z+_YXkVCR53!)h1Z|8SlU(S_ZG z3BE-y>W3rOt_FR&f)K@&zp~x43HA!{8jRcM`3vD~etH9u8}`5A;IAh6r- z@fk2+zk;Lm>U2CqUR~_%>qzr{^pXZBwnd~7e7~QQ4v4bUMYQs4XyF!dHwGqZdyR@# z2^A7A|HK+)?F@W4VTQO{Sr|&gLM+bdX@jy#J^uwMhg%?S7^!50i#2cqhBD$%EIEd> zhFmJN8bgma28^sbgiJYDR^KK`2%ydV+ zG_up0m1hNq!b^T?J_f-!BhNkJMGjfCJaviUz1tG8dd(j)F+2@f)zM_X1o?w~j}C1Gj+AADqn!ylM_jGVa_Aglr8FUlQd? z6#E;rDlGjA3w8e`7E1qH zSZHct{TCF{3)tH`+PPcU7&zNGlKk^Q*~8xCzls1>a`W<-zVLYGs#GbIKQZVj&e&pM z!hBZ+MeR@eR$xt}iph>DQC(}SQmTlr^eDZ5o0IrHiD7Ne(=b8%GFr`drQGXgA7?gy zzMh|h|7NW$!!%r}>nL`h2oNo?Wf>G}Uqp;HU~M6QdY)N124;u`bP2g4a+xkC>ir1yqqZ$ z=*1L(!p@h`iD{j$l~|Q6h8R-s_u-bW?P1s&E?kGdD2@(MHx6~$KGqqxa>1JW^d5gC zUWZ`{veE``b+Qa?_U^g)O1F`Oi}nvFj207T5cuk4%a|JJ_$!<+}z-`$ke(7tRP z&4MSi1>L1}<$p4aaQ{wRmIUr1rRMesxgo&sBy@?}{_KV`fMa;`6@GW{?$vg1^$xr?$9 z5_;X3eaO`qIrN!fRmNjN$cVy9IB$Byt&0bT%kI505=su1$;uJ8DRustuF3KO+3tiz zZD*RWP%+2~2GJgGI@GpJQ|Oc_F(SP&hAM3)N>Ect2xsE;Y<>doa(Q;LRddSkw*EHt zgeVYXEuRPd_eThfRwod|i=23JHM66WFjf4+iZwBWn9IUdh|c6yA({iCoS`0MvGg%d zRA_HW-XIrV7mj&v-PQWS`kb?-(`Pt%^72`Yzh4^^-(93_@;Ab~u%>=4h;JM=ESPZl zkRd4HY@Xd_Q)5;+=e&lMl|#+&m|F%9)*EXDvzVn@`fEdEmPF@F4*rt;GWicm;uWke zl~u%;i--AwRDY9DhV@{8po2JKd8slg8Oq>JNqom_ze8A@oay4)WHW5S2_RQD$>(4c zMV7>PDu-%R;@e(g%+sb5J2{9;1sd%K%VzR)#xUo6e^ByBVtvD0($#o+kYV;qj9jbB zq|C3yY}$jE#>%XYS^FD`HX zdeN~~=(xOFy{WQTnd?q`L3NNb(mRr<$N)M6Xwzu#Oh-4a6~BJIvUgVKlR-A63WaN} z*3b9Qarf|;7SpF3NB54>N;H~X!4YlF5;kHD<9b}M)*$HpyyJ}s5oFldy-{&gZFsTg z@1M&so{0HmfP45kx{)`RWh#0bAB$ie)w$;l&c{6yC!+v0K+3-%X40g$X0N$e0BY02 z4-vRwR;(Cs=Eo@FZu~-nEv?m01P52b+*%ndnbD{GK0qE7&YBH8A3xXuQcCDJKYJW^ zbILq(q}7iEDkg9*kStY4yPi_Jq!mP*oRoAVTWDrmJiDsN*B=zu;(QOn$H1+cyvqnN zS>O<#zc;F0NMXlF`RXnj_CeUUr2=fybmV( zb^|tV!F1b{3Ql&Ga$BhU9=O+qt73UM50TxgMxx^tY{H2oF(N=j!htVGtQ38cQpr=i zVXBkRy0!IWT|RE=9L#(KV>UE$bQfq^JU{k?_C^}jWwE2>9=$mtLwt&XVzw6j4eHdC zKp&dmyjAg`DZzI-KNjYYz;iTi1yh`aBA9UT+2yZxLxmC|Sudk_>Y#XRbLoS6H@vPn zdsBV&a;Leq9IQGPXf>uNcIY7O8b(wcdtUpnk|S=GMM(Qt>F@MQE-++LT7k-fIpY%0 z#`0n>AoOXBZ9VCNmhc(YkR;J~eDBzu-J9xq82(zAB>rO}t%y@~L{_wxIHU0nM;){u zq~^?%**sV5P!N3VAXvOi`YPmXay`!zGLt<9J$H=$%85IW%Om2@30;iRa`r_R6>s?B z!~;xBfdGIz*ip(D{(7fAvMQ3vQ{qg!>%>b7ES0Au1>{r;z!q4@#W&as-*Nh|T+wW$ znrK#!{DmH4pEKpwFQy(DG>q7}wKGNu%Vt1$B@cl?#fgm@NJL9cn;x$ko60mcu8sKY z(D)ll*vODq`aa=^Dyf|H;1QpxrAgSQM}@$C5mNgxs%2B5JGnx|IbW)J_Tm^vT>f6P zs8KVjvr4skZV)tdimkP6>_P?R?6Iv$VfhK?qz=iF46F$|3 z)Zx4B&QsP6mu$Vc)ls{~sRm%en!Figh#*RYUVjTybIMVm>DTrFn9Xfku)!Z5uhwi-Kq$PBcMVl`eK&`8mj!{nX zr;a^`k5#(XVZ)7Ws2leTW{pUN4*}UQThU(>o_P{Jp|ile7YdkLS#XRK+Q?SCpUowyQj|?RT_erWEFy`nU2SO-}%m&Vvr?gT)_TgYgWTCHixp9|Ebi$@!6`VX0q62*6R z)fdENLq*h%nKl-5v?w_R8Peh5!0g;A0&lpt);pE0F;hL7QZ8#{Y2^JB)(Q|a#E2!8 zh1c^JN_{`<{$108rP4>9Y5fK4$u52Uq-SCN9}ofAYE@rVOBhEX;NjNQFyitEo>*{k z9RdhNPIOt&uCzOFO^57h)5j-69&?_+PK=UkL#u3bcQ9ViSuGP|uUI;G$E42~m2rB8 zh}~qJ-MvQcatho7Z3S+0gTp%EF{@B&uMIGseyjQ6>2ll z2(@T_gr5X;V!FMuA4z2{A_`p+i--6rcRasD>R3p9k`&Y8vx}5vGqlvHeLc10_PS(8 zg}C5eAUacqhTl8p!*UMNVY7&%?rR#9|xOCokE9v9x;==NSEVlIY0*w0?Lluijq zOV4zaA1lRhRCp@pL{(z0DU^wPQsM{n(XCvt6($QGQ&fn|9eJGPKVz+g?JB}i=Dl|F zQmG%wNWf5!#|vp0!dc(SNF!&Tk9HdUIbH;+R+Y}v26&~A6{y8noqiVI3Y)Y^KZUDe z_)$;&deI6Kyip?#{~xTqW0-DBvn9I9w!O->y~?(2+qU(VZQHi1R@t^~uHxO_?(f{E zPd~T!>GSmcIdjhWXN-u<$dMTl1Oi_hv?FvM9fnW%fNl9#){j*YpLGFR=@L-8bK`-j zluQr~93UHb0dS;cOUWN2+Ww3f`jbGIy8`+kRjxpxc=>uyFA-{f^F( zj?#+U90Gixj{#9QCFs$3sUYeJ2S!LmFQL|YnLrA*92-}(Ss&q6YaR5aZY-#IHfzrz zozZ;qL6(otk+S@PIuDy`={QUaURtIW%I;ojnxn&NiMKXbLcRnt zUW%#Y7WW@3p;Xb_t0q?$N!(5Yyajd3Jb+0^v+Bv9Ol%a zX;DMj>(HO?fs_%=xl@0>)j!zDSdVI?f@doPwc@K7^9|6f4(jE2=GQ|Jq@g8W@>4{i|2>zj&5+v~#sEHu?8XBRRfTcJLSMh))PIPJhys|&<{-Ik4W?cAqkI{)rwz~J9q zTchBr^pXC;ehldU%FX^W_Wz%Ky8km7#flS>LX3#KcP`D#niu2Uf}OMeFzhb*E#V=N zf+F_mB@1kE*E$x*o3~1p^%ZV|9yg70+>-5stOb)>h zAC(&GIe247!2c8*DdmkYYghj1hAOcuPd=uDrdh$k3s9t=>MoHo@>mYah2)}YL!xlY zI;c}2lozj~wSUV^M!tl^{VE53cBJCA@x-g zKx=O7cKf?S^(;LX>0jhX{iAdI`fm{QzoR5ZUJ4#a0MX}&oiBd19T2>S{Tpwih57Gg3GjcR6j1z7bCNa)YG6gQv z3u$c1M6P8+?>tJO_Dc=>cYc3`eUO2K3P}^#-Fg-pa zjsy#)jC`!g*)@8qPUD71?o<%Mt`Jsl3ag;uW&VO4*N*f3)5FClNZ*ewWN6qE+pgW7 zc>%T~m?s)NU^GW|#0b^+8I>ZFeJHgOZ}YY}Ih_GEAuGC+z_7sJgEQ@pjQneU(YgJ2*ps0&t#H4Oj(a_D?}Nj z^%)NQNT@q9e{7`tvtcCLN?sJpl|n=F4GV~T%!moTkMwJz1E97>n{{~zCkuLkc7<9ahB!~cFh#u*=`ToubH%TT-cwk(%q6N;9tKNpU$j z_>%z;cZzzlJjCSFg3kPobFWx6yBqr2AJYyAc|vUsDh5m#52gmtFC;VV4*B1!f@(80H5HWtvOl35-ekhcr7zUJ!YjDRIZV73e5 zox~B?4^9NWBDnz~A18`B9c3hF z@4VFe(Bi0zFu$9YPIY3SNbuC}jLCE5wjWA`-{qU|{s@?52Sd|WZPxei`Qi#-Q_}vg z8Q~vs68W!ivbJz?HnBBv{Es#7?@2@1&c(=F`rmK|RE6FX$? zb2wZLxpoxGY_M2l6xk-0SY)QH^1gi5&WVcyZ;beT`Al@*^mJyuZ?ClSyWg?+n>fZI zU+@g%T9QQvB8u>u4~jDb@6PQPx2r(l>TBe^ znz{Fb#OjDJZ6ZboXp6TD-aF>2U5VDvTB$FK@FYj}!JhU2)8RT8F7FT=ji3+U4s7?O zd30RnKmoOdWNFc1UZ4vV@1?E7L5nO&6fU9TpsHd%bsM&4xm-Pi;^lIRdwBKsESxm0 zSmh)ypk^Hwb}fYxIx9+AYMmlKRRZfXjpl@zFlE@liFI7bt{?zvmoz&SO^^-G+KsI> zHKJN9ma0k>$&|M@Wffapv`a!>N0()lcH%DXoWmMDWXpyyBOKgoN&+zUf5w&N5*H5K zG-Zvv#atNTH_>gaVs9nZX#+`@3g4Qju>d5JO1PUJNr0(%^}y|NNV1?OHazPlB-9wX z@{k279sJ0#a)efqp!5BQ^SJ4Dy1JZ64Lq_I(A4N@i}0a5_f1sk)ugz!S^1J@Ol04{ zwWY$4(wc5MTsZO-7*}-Pu3<6QiQ$+)&JbnmMXa2u$4-KDb<2E63@7T4C>$Sky59r= zQ?VxM8H1QzLxBiulGQD7LDmGz@S{gV?F3f1HBz*%jH2am=rmzetqdRsN$b`IWTuqO z!voe~>y`!pAr*}_$SChNX$B{j&Nqc1E&|I4c!JRqbk|+S5zowQ<7?6@{Lqo;fniGS z&?e>#8W)I(k5zytt6orEhy9R6VW?m~C#J~DX$}r8jp(nqN~&d77nY5?P<^Lh2flhP zbZAlRpu4)3Em^q+-mE+kF@%x_BWj@q9LEMj>G|Ct7+WRq+VzdKUdJPH9Y;JPm4!Ks zs1D4!rn)!WXnezw40R^lDBH7={0a1%;#^l(k;FatPO5c0+2C?@4;E}Ga2Mn$Ci-Dq zX_wSxHy78DE8##*$|UzrG&8UTcCmr{&klB-79Q07Bzq?gWZCD6K`q**04~j%7E!SN zs)4!3g}zNQ1Ad~RC;I{-eCrM5B~nf4{q(!CkTgIn4Eec*#YXn-C=iMF&k|`o3m_N? zXCxS`)+53zR>8`T=zgOhXcn z@e|;VS6=jM6(Jc|a@XL({O9g^b+K{vz!{A;0t9(=v9{srfmBq0dZ<`y;4T6UPZ>Dw zg2kwo(H*=?_A|frUi_o4ieROFt+vYP#5SnYh_d*D|8ym%bt2&zr%ExCK> z1z0B5b&jCylQqx&>IEl^U&Zsd4FZ{^QAa?>@^Y{ZuE*v86dn$Ntg@>JQFjMiXK~F0 zY)+HCWViL&oHO~#t_TeMo{6Xbn^nSP_;BKe`R{OigJncUF_GXlJe&Fh;b6k5p@oIl zPy{`Ustlj>W2)@b;jtOEo_dCNV0XUAn8xVAT^cGtA_3qiVWS$F3*K1};q4&M-wwj`TO`^Z(jn3F}zJ1Z-qXHLny};ltZ@44G`fNq1bci z4>?w`qUOgV=E+RxFlq9on?KE9_y>9!yf?u>>mTr@riq`3sYGaf19RVQYXcKvhs^hO z7AL=)-{}TtXg`3zr_0WxNfY4i^jVOg$ZXg-)ES*L!$HZQQJuaP2I%joAp)n2hi%|u z;{BCUUz%=v-IXo- z2-A4kbg0RsySGZf+@@~RO4jUEKe~4)M_1nP}g1ZnRJ2wsP=BQn^CfwE99YH9u1}sI9nEXu;mC-bA!) z0uM0dhoPa23+XC%)YMtb+lm7@13OeZk7Mr&ZeVN>M}IGpue(nCT~Ct7%1(bAUGh9v zj+9F|oH8lYX=@olTAYEblpgz;h;3*A0X7qQl1jglK0%{FM~z9eGP`^aWGLF&vX zK+kmg`#f=}>l{{j+jE^`y``KQH~*v|0ktbLb#)C zW07PF%8vv_GkJ#cTW$2|>J-h~#oNhQ0w>Q-`f5P4h9Wt4nzBKEfx$9?Xd%^fN#?R& z!)XCff~+b-Tcy!l3!Z1yN}5%ZajWR0FuS2*kmoHvPSmne7ZgAzo6Dz`RILa?-EtLF zJx1GPY{?OBFtR=2Ese1)hmPBi7w?TR_(&-b{n#)^Ptfo^xC6}(6)L3(dh4hW!5NGg zj3Gl>q}0N~=Nc`N4Q?n}1h#l&_&pbZP`%>iJYe;#FFbnYDJfde1#9u>pc6 z;*4bblZu$^bUE5l3)4fG8sJ$sv5$4h<;2a5|4}43CF@BW0aHjl*rV>3g5=YAB~CMh zvzNn?F+8eAa1j}HIbOHizDB(5o@!1OZmqpi_iW_zq2WeIFeb`X??Ytz>FP@Op;a*E zPH*>gymLzMOY~J)%k`Sm^VCd})>cIUIg?nR#Cd?ci;nJ(xt><|{ovzK?Bl2UHOU}n z0~PpR1P-Y)#)fd@rmECxz^e(vt$V6Cq|vmO6PTC2(S0wekX2m8un zjG339rWetMhsBkIwVbS#oB=m~HE;5jg~ipGw`pDVqx2-x&DymW;GHZho!t)XkecC9 zkPpK^p+e`k86$8Jc|$Gaur)U^srtanOq<%LrjN`ni6jWUfyRPF6-Pia$RSmNm3T^a zUk8w*&(8-?Ht;Hx)gpehHzh0zt^k_=!!RE&B?W>CO4k#pOHbL}bR%{@`usJ2N%t~e zI<#C_7YxPWV)Ze<$~yGQ`T(~qXloI)mVERL2Ufa4e8(vlWf7F;^HxtqwX|v~7t-vc zfJ$+>y^VAi7fV&b$1*Rtnj`f%AInoyzI^JRP)%i&OuCNJgt6cNqXPqV?<=b7pzh3} z7QSEv;+1?Z_`wU#k^E_>*W2UT(_Cn}um?SK0&Fe1qj!hWooL#FPA++Ga3lU`8MU89!9!wZ;fJFtJh4 zt`d6gxMEvQz|JJ)?eGai{jmE^0HRc>Bz)se`Om~?E!jMz{V||+4m2(+ZuOr zUqI(jROj$OcUSTzIkSB)%@9ZfaBeD7&%~eYNQkqeFpmZg;hJGWs5{w3z^E}lK%Bf* zXk|~L9bayY_O*d0x)y$@foGjyqUZ~EXHlK(34`Ncq~Yk9qy7UsckDMF{~yDh_tlJ( zyP2unH$E!w1D>qyAYIwztR6J{L||;D%Ed^Z*Oa%gKd%(I@GCt5Mv|eu|JM z5V*%vydW<;pb-sQ6gDKPODUeU4pC5nL}t`i!gcVh*23NR;3u{~==jwXut5`lR^|@9 zSmDNgKM|tL++;ZzijDDo=n#CBBk=PLtrGe%4o<~%sLsoE7_6*sh2>uHMS>Mh%~8%2 z8=7OOs73+$TOpfv2pM_;V%$;S+@o+j6OkTu_6IgtF1T4vH=@IDN)2ZFlaSy$MAHI% z++*kGKTJ)Z-f1DQ%;xq7GdQ#E#mBj35S>w3bg7y0{MDk;UbLX4$8+WBtKD1&R}y_* zV>Q`%rJzwU3o3anL{*q}5^pF8#Uj$b^jIWHC2on;W&2xej_V3Uotxb#3RkcvTi1UK zAkmQST+!(bw|lGhuxH!#^)%D?^&v!z^AqiVr-9v;4xQ^UIPDORe--e$d+X-PjXM?<4Z{p}Zo>NrC5>J!d2J)_*296=*i@JlD3j5JX{67@)&-hI@ZY z(HlF)aK7?CdrP~A0zsT$?Tyk5zfqy(}X6%d*J-nEY=N+hiqEowr zb4a3-&)DuUop)kAU^LY{qtaOGT&cX@OuQU>y|C_hLHG84Vh%qEOKt}cXSBdXGQAI}9q!3J zpcj8izGqT{fEg9SjEbgz%oHavrPD>}OAwZf8%~~F`NdKih$eB6<0;nU)8=U4vq#Dt z{ZkKO?TTDUg<*@1t2);LqFf!D5cP>>s*1<@9m;j6{BZsLVAwUq&7_cBA?O<8_ z`ORLg-=QrcYj2k6mQmNy~SMvOqESo_U=%&i_ zmn@T(o7${pk2D&su#0gw%#3QK%~;GDzOIwf$><*BN89kTB&ICVg{?pQhoMWEnaF0r z8%+RKM~+7LefkrP`ITiG|4jtQ9SAq!2ARn3v^^X~&5oH-$MZ=Hl5jwq%VZM@1}J zuS@8iObkCh;VW=U8uaoSVwKivi;EwNk_;0SBQX8Eg-vR>Wj;!H{gVCNEXK$uKhWx$Vopv=fK~T_ z9P*2Edg@VODsgi%s_AV)ovc>BI%@>{4;R}Qd!34|$%h~F6iBBc&Q|iec}(XV*kSDb zTgr8Sj)m57{@B{R#^kdEMJn?nHK6m!Qc^x?Oi_nBEcErlf+Hz;o^WExK)<_6xo*@0 z!jXi)DV7+lMq$OX)MMtSTSjY{yFt$hn1mIl4uH-#Qu2PWu9h5E&wVlT-X^le7a-fKEuq?u_Sftc!y) z@4^8==o2EeMj8U%v?u?(?&RNjAHBfwm%=5(M6!kML`%MRNsX%ZJT6hyL~VA~O_wxZ z@?^Uln%@*{*K)_I@$9Yojxk$RBpQ*)?f zK#}*pcZH*qgATwOMh9K#NF!d63vJhLeb?EX=16aVjG zs%l{EVxnYXZDQnXV*I}%+Z_okfEaA`q4fm(gfz+G(6=~w01r0zi-8e)#nj9>E52Fn zb_v$o->Ym83vtL8hpW6cvf%6M2H}U1H)$E9w31&!x`EE+;TY~&RZMcZDkn~=gcY4M zz_HzNM`43PYc_+XSo(b!hO7+A8R5L5NQJOz9S<1e)cs`-V-+5~*u`sD@{42IF43dC zQQwH((Ui$%@WHqZ>C~h3u?obOT@@m}X{G14(i>|E=$na_sDr4`PZFeBs5cLY25}HdzYYyO*jLE^no6_JaF;2)km0BLLE*l;?qdJJ;i@%`+8ush zVE54OA8-Q~L(_#QR||&NQ%@LtGA`((<&L_Ui4+U%W`lItnej?y^=v#e?M7N87TSqG zn!zXIlUYlR=J|hUJV)E&@$7k)|! zKJ3~Hn!{a1cbe~OhX1e%j&W>=9rhl-R+nKWdo;`}vo6S@d+1obFQ0}geEm+vM+EM~ zO}u^l*;6;9-~8C`X)~1xhQrVCA)E(ha6v#Nm^mR8oIQbq*df+p57oPLr1@D1?sKm} zi%RHiM}lQaHN%NeC$!o<&N%Q~oWuLmS{GBBhvNkM4YBvoYT{-&jzSiyMhabmB;smx zXYNyVE?>Wts%Ec4zpcw3XEjc|En-UZqr#Fp<9NksyiSo%v!S_x=c!KR4sLV6rXT!T zd5!H_@^Y*^!mEvbYh!hIaQc4~>uvKe=uZ915J*7&$r!l)+s5!e(;p)@0X@KgnDtr_ zOBBeT{}X&DlU%^7!kxlB)~2r9hKP~sD+A(Rr?QDe;TR4Gjh9BIZum1BczvKfVbJ|7 zs$g4Ci8(Dzh+e+pBC-cb7Q}~u<9+kC!;G3E!A7Z9I^IP{Pb_Zc4Cc<3ZBrgL(4GV- zi$|9n5*|WKxPjbrDCX#t;5GXPgWAQl`p$|jEJ#W~xmEOcyq0=+8ztCAJl9zo1knlT zryY#Zi%*b$9yEr^MHv7*i}@xy(|j#rsa{>+QP>(OK9IyrtBywKqQ1i!KuH9GC?(@J&H(Tf`gZuagZg#g=x4h;m7)}CmXnN zP|6E@EUfZ1BU#atmmxw5Xp?!8Eay}=)|Y$E-k;1K-;1tpw%2sT#evOx>`bqDU$&iQ z{$!sVcYpVMk@<6dXoZONkCbIYK4-}4nW`}uT(c(lnDSs=Ehqsjp1==G*BNPu(JmQc zsy(IUn!}UnxKXa6j8m1}(W>UE)yLV4`h6GL=-n&hU708gm+YgAZ9)`384GFjIeQ= zhF_4E)#^JKbGiT4cO@z)&EA;Y?%^O9Z?N>#U;<#tK|H*NpvRP$aLGWkf$|k$FKvN# zgiyUI_(Q`z)c+C?$m`G=CIT~2`f)lcs63emXFJOP(>QFN9@~W zF;HB8+-70D_MT~!EJg4v)`CJbB9IelfvLq9xieZhwTD`kfD*8(z`I>tD$O{9+%21% zu3Bf|`K}`(JdX!mFzpY#|dCG#q+rMW%VlU;d-)Zb$97HYP*i3X>= zL|;MwEr@lsEFUWqb&_>K%SJ49B1N8wj5pFt6G^c@uE&>37Tb2%W+*sxlMW$dD1U?1 zn@Q{%DVPmTYqmxo9BN9zLDLo9bH3#=O?rz*&Sq!d|PDsl~g&TiL+g1&ZOs+^hV^W zs-4)lcxmk}&X!=oJL~0WX?lW1y{i=0P4KCKjNy>34x;pQz5yBjkPsC-h4}}CHwzDJ zhiLs(&G8ee@1=yiM~FI`4~qiYWMj3gQk!XNj`6^nO$qXTphjw3D`|*mtmSJ#Tqy~) zoG+)v5NK1Z#VZs1e7ocIx=AaddqCNv$C-}a+-(~qArj*xfhiennck8;rk+v7`NR^c zhMvV-M<2kdQlut5ck$MRG73_f(Db+LSR^5O7z2j;d#D+=JESz;OTZ05fOhRuDcR?mC4K zkKTd$V1M+aqXapH6AQ=BF}< z1 zTa?H8ss$(GRD$0)O=dvsxKovzxUvOyyp{FibUtsAemsw+j~jbBe=Ih4*Nnwj_Js4JzaSb zGF|YURH+rLa%gIZ$=YEac_n>xo@$!exTd<(Kqog?mCYpa8w0g1E1vgD5?ZFpACeVuAVItkGq*P%A0FDHLK3YY6O69{AbshZ0upJ5DoRUZgf?yO} z4bg;v^R>;jk8;t^K=$>HkQ^=JWF33>(FG2V5p|BmU3y2Bjm70VN~k6k;fv)%R1 zVL6O+!w4L2WZhwPcaU}fu#QN1L9L~a%X5}0QkxSL&@2X+*BbD*qEA5fiB@=XW3R%q z8A5oiXBWXXhNqaEN5QVS^pb|r1 z1=b_ZgsUbr&=_qQ!AO|DxAWnIG}7fwA807I?(!$e^!s4`eiO(#8IoJ}s1Xgaq23Ac zGr6*I?+aS+=#CtdFjot{dThggTY{%tfV*Dnl71+Y3C)UXyJ&pH^@w^ut0u@3Hpx-E z^7RoO0lQFU^nw`; zl~>iJsO1bZB7RLNj@}z~IoHTKrF=@RD14m`Ex0GDp(p647V;?BnPH+uf4CB!rBcva|4}b0q_IY+>TM{sA$SGr)FKC_3IxvgV=KRz1=%svdi3HUx3O=HvfTzhX=J0=r(5Zn zxTEsRfy}+w^%j2HgqLI*=jGep2x9cKC$zg6xhN{{YD~e`8oxvMtw7A~wt};{M4u>} ze?d!-x9kK|$vY0VSmBALbh-et1Q zYtqBClcNJMdV76PdzkIh(q$gZ5R)*L*3~t}3(!Lp|2;>~sd#wm1K@Fdq=ssXCA_zS zYRfJ73?+`A_oM#v4Il$u@W=4mwL9fUpWgjKdqtT#8_c~^oBj^<+ttIF`2M>hOrVW8 zo*dMV9})jpZ}z_|r(|Q`>}cUmulmP`6S^cm_hiCG+K_))UOd zgM*X!nwlh~7Uu8EW)<;Ox;)}Dj|13KCDR>nv+oiQqV?YT>AwPH#l&pzvhN^XGjT_o zXLw)ir3%qZ2iC|>vYMYY-+As&c6vVrge}&s3(;ec+dWy^P1cLEts5-)XslBwC7INi zXf~>BNGn5a(mThJ1*dDY%r<`4DwJ9CFeRXY6h^HvfwRoJ-i_@(VCM41d|a%gqO)RW za)UmT#%SKqPHt~$y9BYatFM&#P^mFmmH3Dd>sdR4p{|_&5sYIwUpk|BGB{7dwTm%f zN}o%HkAAvX6c7LaE*8&(g}BaSA46qzP!~^sXK7H=Tq-w$UDU)^qxy5I&0r;?4KlUU z_rNB^$}%n?*>8|G<}3Vc0m7dqEKo{vx@Cp7C)QU_0V3CA)0eooj#O9!GQBWjUriLC za;5OYtzayX^e?hag+`}{@y;2RK1Iz_1x%kW9t)p1Tb8OaM7CGj)*XXiS{adBX@O%f z9)><}qit-O5|F{C8ic|usJNtLa)Rgu3OpNx^OKo6E630#S(49~9!`moLFi1h#Cvhr zSx+Fp-n+ctqW9nanyz4%&xQ!o_FV1Oq+D#dOjreA(M?v#ww{KH+D!lA5_f8v6@9>V zxgkjN7^FLE5_i)VJwTZ-l`|DJ+m+b1UKOQP6F1s9bo)balg9(EBvx&!5);`@-tz8~ z%_M!WL#^%-1F%_{%GgS)ro~wrh_)c)Z`9@Pa=3{8{8d`%EK|7a=rcNw#zcl8nCdj5 z0VboLfzT?3qj||LjD5p4*AnF#7n^0yZBjYWBGvSnwjv|Oz#p6gg!;w(!fj!dot;fz zc0$fIf~VsOJ`{fK44!S#ahmmt1fz9I^7WEH@coC!Z4PmF2e`iu^JoY_)zN6q+7$2# z1ARk}5E;Sy;|y)W*$g=w9gDdS3#!iF&cl`-WC*24c_3F3RB^__n4nsVV-cdsS05g7 z$k!}c`0!MQq#Wv!FXHnDbuerIFLDH%0NzkEA%~Y>-bk@EhDs@>WnP3iszOxwez_KUV<-aU}hEG!1y3g8z^} z(ycm{s<8nVeKqU?n1x9i9W=GqY4&%V&f_?prwK-;F%$fn#BW)F=OHWOUa3@)3%X^; z^bs_xq7UTS(`)9aYwFDtd%EeM2jCb1ET>#Yd9;_d!((&FwppRnv&cz9CCk*~)GbgB z$2LySkZ0tdrTSkc^1658&l%r247p=pTc-_b_G{FwSQjkOJAQJ00~VvMzs#NYusm!dn9Cr7rJOmiuHA)E#a&D9;?sYRHb zb@u%N%p%NW9-;{I$tRFGb?C;$XG@0E6+|uA6P4S;-HyXR(5?4HzcB-0FQ;VWxE83g zEt27NEz_q-j?MQ+d}P^s|0LV`dC6<`Kis#m+aP=w#X+(UtX7GgYD&Uc?9h)61&b9C+F-+f8oNKppT8q}>g*tLZjkbqFu zU?QW1+K<#j?kqrfx7WCgWXQ?t4F3?n%t?4}-z0#-Y+-uvlim5v?D7#hM300c;T_rP zmh?yqeQR@3%d{I8ST)g-z(%%~Iv9-wUB1$_HiXRaB{_(E`<(!WV z@*eERk14qSs{-bZCbq^Vj{iz&cDHa+{P)AZ3z(~1$o^es>=D?cSRS<<8d6Xz4y-EA zA6nIRodQTP=)2`g62aPS>@4sNoCkm%AdEuLCw6PF$Z3`ur3o2FW@dUa$^I~vp8hym zTe|}kz2||c0&C<^T4ZP6+LpK=tHy zc?~&;NL39rNXHy)JRNe~wn=p{{!&dWS(0WLo`eocPlL1RilxaEs)Gnme~L5k)4Hds z66c8A2@nNfhcvEED94T>vNzNDx*rHTlR6eFG zl#7KyT9?&}NDC%3E%c|Lfwq}>%?Bb9OTGqKr^MQU6n>S85Uu5*N@v%(ei^`vy_F?c zLFv=W&Q4DE#k`F+p4DVQhC7A0s9tUm?{OhB!C?t)I^|CW#%4h@KYig)JS=hltU|iN zPQ`ma6DzD?_U=06KN{a)e> z_9LgvAUn3d%yE?G$I@DdQOxLtdH>{Ki)*^w_dLF_x>qf7VR0@HA>*NS#IarK6jp`u zof94|kDHPG`YgvZ&ezd#aTVUqI=N5Ak?Y;KEvdJX&z5SjiEJ`Snqc}R-^@NMR9#sD z4t^@;mB)guM{4DRrNAVd<1%~NC920iM(3dFc#HTnmhZzt)|+p^YafpDZm#e~xc)qs z{t-B>z5>)yT!5FSHa>&N(Wg_++Qr#-8sQabUB23Ol5@YMl=DtLt`-8tHHsFdYPczT z$u$>E_n3zx!8K~WQ!*FDsabFGXoLsCU|!e~*9Ri#;?;GBnCL%W@;jIE3Q0vnW0 zkOuorNm9(!et)}{`=5lvKfphJ`2J%#vj6fb{{QPlS*_7|zkaTFc}HIO?%tUsAp}C!^zEH=>-D3n|DK}u$+tMOPl)%vX{%PcE{JL6JajMxzrXsNoS5-I1FIsOS892{!w z<|Y$p)^%jfjI}ayE3_0d@)cpPPC*uFB@*} z)gcRQ)b}yBu^-tIJ{2Mh3p(<%3DC`Y&6JB)g7TS61+y`gmz~;;uHya?JXu&>OyUyC!C zu01$*4T;@_7nHCg+Qg9zZWm>twKF$QtI58i@hBY_ty7iXbVB7jX6E)2+@rfRf({RL zn}ZeH*a-qbe}+lPMm?q4jC#ie#2Xt~(}L6!x2v3(WH;kb(X9}D%kCv=7IEieG<5|* zBUly;C=`%Y6lOmYpz;+1nUe7W7!s(@*@m1qolhU&sJ%7SfGS31#nV0Wv2s;jvw9*D zq66Rz$aMIk>D6C(bWSjT=iNf$PaPt3@@R8G*{`V_)?32C$xpo&3>>%*JgX6J(&=M2 ztMQcIqUMl6uIa`vN}+K_fAd$~W~u6qhTYKyS-y3Jq2`QQa;eL)S$N(NeT@yIf}Lbb zPpiC|U4^Y1v^s|*>`j!(i=o$UA#rE7DXrIoMwMO!lgO;+XJbTVij!d&=+=c(M2M%^ zeMuCic6R&`8>lGHuVhRlE9?+lbbi7~V9##7V(!EAyzGbYb&44#Y z4TZU5%9NH9Leq7uIUFj5F=0m$eCM++8s-(`nul?>18oQB%vGg_Kk!4{9*D(Uf_nSu zQ%c`O+e6wwj+@;zU(dT_-vz<1@LIlyxzikVW~J4oHuI&uhXEeHaZu%GSl)c6Otn2| zWfVHO{WC08luJ>kh*b$kXikU4mTFtd+-d^R-DMUtIRSgdxAe9J-ayZeA{~}|#U*5; zb{=c@1=?@+*EP=6rUc%-pWQ;>eS{ot<-E zkD26D6K0fbT>GesJ2+sd*0==JTAt++`!qOTSrP+yLRQ&ywFFmAwRQ=XDxKB|lzC(c z9q-uz^oBDa2Sve1QP`Y>ZC=Q@CPArr?l^`O8?B>>8XpcPd`#mOKfUzOIa}MiaI9FR z(z_(#PlG=o>p``D*$AUlNxD~TO?2a$+g&j7upL< z+L$ArmGl61BCDm9yZGCY)J4&b+uk*w*vZdV^lr%Bs3jFmQgysST5tu4q>L`NEjiVD z(pWZbwUM;O>CxY#?cFB77-h|v!F~`wBc40zQR*5cq~+A1BM(oheF&HN06Rd$zsjHi zDJbPy1hCVCCnCYrE-ta4Fr`#tXp<6^Y(1?imr*8xVp36RYN6WTGEnj7{FiyEjU?R| z`b~!@dvg?EQz}`z#3@?0Z4#9*Q&4pMNYeE;8XJG2v`2HQ3D;Uhxl4m9{PJjr;@Epb zb7DY{H5MHqsZ9ql3#%Ik_RiM)iqVP@xcY#ktA&2L5s1{Zs`I1v*qNroC>mOd?e|Aw zn`FfVwGM?-^=9w)53%_|5;BKRg+!oE+L}R~6PK0o5;fhW3n)^FM*NtewrkDe6DX`t zN!JUmlD1Tu(bAW-MAHoARG`eTBW%)@@$Kl+3y=N;BL&=anZR8Mk!u> zpyw{I_t+?q^rays104e0=)hywSv6Z$by2qM(ai*){g&D2ahzFNBh`I-r*=m><$;ll zp{APsKmtvbE8=jGNZ|wgHD{3LxQ7CH?;~4zAu;I#{6Ix8+BM3+A0x@@$dxT;pn!dH zmb%Ytk@Zc%$t6F!(@25F5tK1003|z2$&tuK*T<>NNnmEgOH~JzTy|0;sfD8LkLHh6 zO_H59M^!~8#;Y0B%!B8JKEH0}K9q%~F8Zgxv|gZYtlbgwq2jp2VGhQ;#tBTvqUkcM z*3n>gcuWc+o2iv51`k4P+kFvJs?w7R4orE0vm3TcR`LQ@EAX4pgBR+(o8JxR#{ zYdb7^Bo78j5JzP(cV=TwAV+|W)!?$gF?;hY=m9d4#xy)HNU6GQb9wuZO9Kt?A-kp* z)zTA7K~pxhTN;a})t0t+JHG!BcIbr0!QRC+*MvqQJI$cLL~iOxGyU#J$A`WzHv9X- z$n3Sfi}O`hrxV5Q^9h_wE7&GjeT!!8HoNl0gV(c>oJk+fZTwzXbFwY*nb;o;cU%Iw zgKLmmSgDKC%})y+{bTesqA%S#f=13SF{W2o9eu)4-_M*8AydtZXLVD;I1S8^+9u#L zE;MC&g9lKslA%>jtewoOAhc)$MZSPfW14K%kU@1M3P>uyy?q^H#M=ymygVD8@?QIb z&3?f<4DhA=AYyu176Ma*V<;Orwi#H5GbxL%+3uTdH+s)S(BkJVdLu?ZwOKe-Bf725 z$eM0Yi~{r++ z7N6)2lBW*@fH%*E)~j3>xXv=%Ze|vB98Mk34v`JvSJXL$rQw55wzrG4t>_(+vO345 zI_-^PuLw?8R9pxS9-x8wxGM;T#@pYbz*cVC z;e0OrRa=TJ{%?WUF zGdB0|4F+aa-8gX9_dg)2j=}fWj^8kz zZfKi89kLzL!z74(Zizm1Y4Hq_rS$0 zjY&((Tcz>9AhdVpJS?JdT18HktRtJroH0;=koF7uF*S5CmQS^#(V-z3J2z4ewqrORP%?-Cehx$60S{B$iO6yLik1a9&Kdik2b0*OD zt=X|{t7F^l*tTsu9ox2(H@0ot=-9U2cz*wTXYSNY-I|%IJ5{GnolmgW-cPN)4(6yo z*BMHmh3z1}=aB}tWqM`^@t&6VdpZ-?oC$@#q0t@b2^w-bGOP_Y`4qSQz^S#s8jHC$ zOt{7a4k@}jDmYq5j}5f%8p@tMMf0`@7jM82SHvxo@oxVT5QMu=D&v!c?14VcZy5N- zOmbg#Fggc7?n{91O*@2YMD0ss2iE9D>`u6M)7Jp`6EBch`aRd91*hn_NIjxNUm|4) z(cAdOP9KdY(#Z|Jpz9F?Wyop-Eub*XrG?<|#rZX*M$8*_~G&u3>s?1J2BPLHXl-vefRv`TR zfSaRTv)575bG0pfnAYevfq64eaLky0z{I<5Rm=2v>AVuT zZ1^Zu`J5-OfwKrXnW||po9TNlE(_zyBA5xY3!rI~osOvTp(|~)v z^nI&vz4yb>G)OiVpyS5y2-%~}(aT@UZ$if2Hs#PT_0Z4*dzV_HUb9H)dHeScLTeBK zK}ADg$=um#-X_m#W1}=1VT3NX>;t})vCT{;+RMF46oJ>ZaIK_Iov)qM?9 zfL5f{e}T+r zZKWvG?l!+Rt6xkYgqA#8wM1sMP=b~zq28%2j~s!XDF%Tl{jEop?QrU1gnil`=Qza{ zZT5YF?ZBaLsTplvDkgrC%pELV%+NI7?&+gkM~>DpEX-tTqmcV#$0EfuYFg|f^~~Z( zvczxlZ5Aq}4mIy1hFZU**vOYwC_BN)7CfY*f3g43z>d6LO=6<-*KGG<%^RkUL9y%C zNd#xI9>=_=O!MKP^|0pNXTdavXQ4U45hGl5KbnjSQ?;l+3Vl+L+%zfX9JE9UB(0*IL3&7+&CWR#$7$Z9 z;EzjwzSrfH1jus5rJW~wmN!~3`)01|Pi_qao#TUQRq4vU5rM+#rW}Y-P<2_tj&0J_4B+F>jNKYBb|g zvP^7u%ko5bbsi_m?UFmkw@qf(mzKnKR%|KWNY7X&?^GO$Qted1H%!XbF0w?~I?fLY zJla+&O&in&&0i4E*6Z`IqAI|jpPOJJSXQ>~J8JYc?)&vHy9J!D1{F=NTsK@e$54@k&8d3YG;@2=Enf*!F6AcL89-Ii#JFX4vb0Nlm7-Cx z?*5?EGHzdZ+sjJtNzW2~@h@#rWi=#^`YIDIX}oJRkzx>8Kc;lwS|v+Cm+!Jv zLR{8>icxl4xr5+sA}Kp23)LRjeOCKo1y6vJEF;nUKzB|R1D#5#1x*DT- zMTT|0lPwJ2;N@C&?v_-N2h6M+9}m9>H;7H|mNX#T zx_;>TsQuZA?T_YdmkMyxeI>3!JG?;zyP$vh20G4U0m>jVeH5g@?Bj?B&G| zDtiAoD@r<7hOwsJQ~M@Q%CE$1HYiEkNgg8g&qObAhi03HTE4ZWxrkT7?4p}_c7icL zLnrG6G0y~4%m0z+3X_~W*tCyDVY(9Y+Wk|5oZV}o!Y7z%qs-!8elGz{J&n%?V1;nR zvv0d63t**UkqmTfP#OI6=40MWcmN7u>h8hV?{Z{~pk zz`@ z{fWcTFg-G)VCk#;^6F-{(|jN1CW4G)=?jar2uN|M+SJr0&(B{4!b@+sLb|M_{`!VR z+5p;wlApS4E&%ZYYxC!?4bdVKudgg?jm}f30de381M)W;tAmh>qR^-2wwNx9kxDeV z&0|eOiIJ+bf_#5w*qG;Ja;fq44NIf_IysUKLB#6dprHBNfS*zzm9#ovDLC68UbE5( zkw>K536cw&T4=Xb#iAX&HdCe&xd(v5<|g*U9i&Yl6vzHKf!xEFTWlGHX$@}xcHXL| zI5An1j*eC<*=ma~GulcUdoLNBYM_J=nIC3k)1QSXh}Md-!yxC8ZF&MEpKC!Z)BLp7yxdFq?4UDv)uz!^iXuMC>U(uY2q7g)%vIQ zo3U(;)dbcuw{r0KJFr_~`mpa2#mQoSi>Q^S8r%d82tSsSXg^fJS_9OS(hNAWX`STW z&M9VBSxue3uf@3kY$%c*L%YEq#@b(9vbGtr45Q(0{I)6*Apg?_KWHFt_Q>+xm05@+A?xTUHeAB;k1ty-bgbl63= zDp%38%&*|?koUKm6KHwb$F;l4$ty=US5D|XcFLjIc^nkAYgcuupeLdz(Jfe8$v3c< zA*V2`RqEFeH#&3Tn0LxDgj#?Au7``|>-e--XZVu+B^tvSuw4%x2nucC>|CM8|9(Z5 zpn&Q{>P_ruMw8{JxtI2}(xH|=s@6C)?qmf@(va(WA;kY%wA1L#UHhd|lYh~2stVU_ zD&IV?I;hh4mI!}*tCRvuy?L@Zx4>J`0<5CNQWuO8GF!n?dg6}br#g9sZ+bDVg(HjD z$e2(9eDE;{!5EgnRcMHJLIZTE7wJOU({4+2&u^Z*;(9*yl-{7D;tX3wJ_g}W%pA>v z-JsJ$YRHI%h$ObdF5uIy!uuMdM0%#{RJj}cXAPlX$H46x5d39^HH8Rtc5i$7^~P6YnRf$U4~xvotAB- zjH-oxWjKHdB4BPC?Cu>q*%vf32iFFf^@@7V$fmrroXzg(8P!Q9j-lApAMg1(f1q4F z6%^Jt^4NyM5s4MC*oNBCD6` z?EZE5l7BGE^zA`<1nP|}h=e(#oLXlN@ys$<P9>R>7}COdhXQ=!QjcsOcWTmNd`l8%KPYJ% z`o72p#j4Yw2@gsedht#g!j_Cz$?)m9qL#U_eVjjaMX!{JqtjAs9L5}ZckMseKjf5J zG0E9?-2?xg$7Q^Gwdqw%z(03ky*ymiy_%NzHJ;qm z-?%*0ONZ3eAm?J4C-B2yB^TYZQd^@faLg|}(0&!Shmj;cv32mCOtnt@7Q&GVx@KM! zWR`^xPpa2xZcmxu8Wi$6LL%1s5wr&)YUVudPQKrEe*2D3cHMaY)itlAbn!+)xB;km z-0^&aG|uF@ev1CN4Ub)t*|K|(XXF4XiBEF(thY1^8d~_mdj@_hn z4tJqFMg|--IG>dR3~w{(cY@EM5L2JwOvtS=UxR#~4fZ5&vL%^1&O@)aoa0Qkk6}tH zA%6jWw*gab@QyvTNnbng=Va1eLbK3eupcx;O77wiFF=04caPD>8P_0}*H|8?+NdnP z@1E&1w#RQL>b_f29RHYxzVK-$Mzr4iR3DW%cb4_HFu#T&CwLGy>su^Fj6TGupM zYbV_qVm!}?04!BzdJILE>AP?-M#L;#pYtidAzT4(XG*OzrUqBMU10{pZ@7E??lGpw z{NC+qX?TsTSo#Z*A&j|)N!P@ESfgOAt*NWZl8#RI_=Va#5nfOSQattznC_ zs_8?0v%_LlNxdAgmsz^T>`2uXUn4C&@z8WFFZk?88CL7s{x!T80WtgvQjsHP4m3Bw zCVx##Wx~xl+{d4IjiIZuu_oZQlEc*9+h_eew#EwVv!6ya06Rkqm{HeNu#Eb0an&jk zIBV}szAbBD&$U$AN^(|>+&T^)p7CrmvWJiqQ{OS>xoXt{rF`Ru*y_Ak4hYZdBu{k~Qopt(jI8O8!TfQ|Rc3 z8;{eDk5AXa5dJ=$w4eKN{C!V5j|hFb%IF+*o!v}Sk}Jg}9AokjoVMl)guL;{SlQcI z>89LMb2yL|eubGfOaGwvqeiSoEvQ_vM(~$8Ta;+fsk5{OBp6Fz>CY^B*i zOPY!@;W3-8tWV3k^InB!5k&ZpQsy^5k*En*HBXN50R=ztF4kD_3@gCHR+7SVZv=d1 z*LL4dT=U-!>kRy%m_p>hEWnN3Nh|=V=^H!s&elsCljYTB7A2PzzWGGW4i{!TLT!EGJN-2>kx&lkABwP`RMYob0^M~ZL^x82I=*Fa zca4~?%6U>Had_Kt`EJ}JL~9xIl;dVphpTNny4)Y_Tm>h63{623!(hlNA0ZE{F|qtP z#V@iHDh{Lt4W?Y38uqb7EtlfWV-V0A1^vp^lSr0YnDIU&Vs%tAY#xM-FT$bM?s$dp z;}YjiwdmkWZdKXZ^j)F9q5}Qez5U_?ugxwW)vEbMKqJ}{4Wu$V8h}&1f&&;&_+N-V_1H;3hd?uM_`H$PiRuiFjwbJH8uMG8E@Eh`N!jv$Y7VM~vKk)${a85TY8 zQo+KBYR~F`3WlaX{t8`6d1{Ts&Cp&{LNmd(;4CT`Kp>>zL6%?wB}PF-cWrs}81pfDCkfvOmF zU2X~plzX<^(l}NHaZowRrzxMdC})~Zdz9%S>OW#!jMK<^F79+Qw)rN)Z((8AhNJ~T z(LF?IDyF2+8i1D-09fU#bQGy+ucblP{aUWai*}Va6PX&K6x_BcT$82GY)D9mZ39m{ z!WyB@=vPhMH>s^tN+O?skyj`s;gV}TXah%G0Jr3FdHR@h@A}lB6vfKfUCo z4d1q_lO_7H>=ewRR|zwIu8qrmrSCIfG$~`uAtMJ{ZFr-lH9l9`Rvmv_I>?-Yp~|E3 zk5F9M_li_x!c3 zc(X!s;fcXv&PQ?89>V-{9D9AOFe3B-@ox zp{)1&6ZL$HY{g7DHu(a!LV$Q>1x?ZIuKJJL=q>~@Ok!o`4IhD+jCR{S*6*~GMw2>dzjiHfe}V1 z8UEkMF5e-85ESDKK7#);>{ifei-&e`%#^XxFX+PHwgM=RS5fTKgsVJZ*E)2$;awnK{xk>KwuBzEMi}rEFaXPIB)w5ooxvDkpdzC`zl+caudfbTMy!JSgFm_OjhCo8&1gzvj3QgS&2+f9d+FmF z1x>KpGf(44*1pZh>G9aZbjoB;4*5fATBD)93N2n|_$=DL;vht3Q$p52RG-m$q8oq{ zcEz`nJZFUPVBOm6Na(s^%Q7buZOgWa-6{;`p;eUvNr0hK`)!iD8PrQ( zdw$W+Wl03V1IoFwfF2qcn(U0~Gd4>6T_Q7)q-LZMme&yG`|Q>8p8Yw@CMQA?Ss8dkpqs8^9>=#3wVX^OYvJ>F zK-t-MLH|Hr1Uh_Cx`ppW5@ltinOXLPG!vrl>!GQgtg>V31xwMeyrrmrYR;x1lJUmK zCe593Fr9iQ$fB@LwuU(url4k9La8@#y9I|fp~^Rg2(KXQI%SSb>>pu@c5HK`r(JbR zRJ(4H2mavTeEl)XrCUIL|6zbBIDCVU_AZX`II(ixmcF`~p9J zyM8vD#4{)*J-M&AAbm{g>2?3y`pIN!&-)r_nFu2Is zH}Lpl*5j7{G|%OR`^RVYZcrjT{#OQNv>bL2K<@tKVO6ry&d0>d$5f}im>!kh!MX{p zLbAGr4<(L09Bu#4Tcszdvk6~XWAW7WpV%z@>^zozOx2v+6csNB^RY~OvwT~R>4o)HPf|d1OgJf53)Ue61Ho)wi zRRC9`kNT2qpTOoIa+!vA75~^Aa0zjf<>|5xg+&LaH9i|gycPtdFLtcML{K>|f-(y8 zd3||(_Hu`t%>hlZtfEXxXvN?lx4zX(tyODL*~CnUCJPRcETON|O^0h0s|9UD>Q-)` z)g|w^V^zX!Q}s6^=22D_C5Ff=H?)Gw!0?`FHMC1PONOcDXxdn2&0-&v@K{X%-J~=U zCn$-v)5V7dRW8k-CJ&S04-CPosYLd2TGe3UD#!bA(bBb+Uf;@1^Hed%FLIXoD#Ue)Bq8ND#0KT>RU6Ste{`xw0f0(C>8TVvh zd935Zn-@iC_gvVcl0FHYPH?K7>u-@N9G`d3-l9vKm2g^aoT~YDhZvXKEk15fQ0OW4 zOU%JZNRR0Gdcng>6pDP+Xq?->2_@93OjMRtWo0+LbMI8z6--Pcf%^iz&AlOGI`)P? zOg?mrbaX?`!ooIOE!DJ1x+ph_FT+{xs6W!ubJf_Cyax@Abg6W^d#4}nQ`CAq3 ztD=sDr1Z{-W3;y0*|$cxi{!N0lRU1=cNFk<~9ORBpm}2o=&Fl&V5G*t5nK zTnko*+s2fmOsYcdCQ0;X7l_SFyFxQ?A9yK?`HxJZTs7N4;IRxONVkkA2Xn~SQkGX& zd|VqUpAxdf*Es8yQ-2{A}fGqdmAR`=lxs?e;lZa%nMc6@C6r z4whkve*YSBu8EKip3`n8@KAIyN57YQ>zc8TyVb-|X%lHe?2(%!@z8FU(K}J^3VwXI zRvvR}3uP={qL(B}H?ND7ID~O~yJ>P{?3EOxSSggi$m)_=%<#w${YZ`fd;R4rfZv}k z`^kRz&UR`z@+0X0Au*ZWH(50jkmC1D z&d7&x)*o4-hRFLoEAF36Bd}Z8z9KVTM@VbhD@pJG7R8u6sw>1+OTetO8rsE~q)|lD zq(0^U41U7KL}=)?r23oY{B@7A*`?(GuoRDPSIkYUPbZC;Nof6ybBsRED_dAdlx|hv zNJWd8YrTX|SkP<&_l5oM3b^3B03E>uUGYBRk(0YYJQ2WT<%)wnNj>ysxO z8%yc8n&tMd`m})!odlm?T-mDJ-zso*RnKU-_-h|@HZdMyEz~@7+cHGpGH-{j+5n#k zB{gk^(QM2eWnZyiV3HLiV9a0J6YpoltE-r-Q$?XFsFkEeh1+wMs;$%AoZ>wv=F`-qB)Uv8BL~G(bn2?pp zCV*=*KMOih0gFSy+|No2OwRR3>|8R-?JQHhaPr6M<4VKj(vM@Wa9=XxOxAz1F!iAj z$I{47qHXt_{@0l`9j-K@?Rh^f1vlSz0-fC+Ft)}+V4+@|D;ez8>Q~oTOb@^O@c= zC*aiQu1K8sQ7V5}kOa!vNC}G=ro0d6QrC*7(K#B`VWmX#JhyM2L}5R=0Hx5Ex@tg0 zM#!U*H2cXuXo^eg^aiAh6LUd@*C(2sUJyh|NjWTC$v=D517!)}H8@p4q=a4N$jXhL z_A9An>~iO-Im&^~3M>tEZ?1(sKjhLbD0_|2^!zo|%-X1G!gH9+z-oP40oX1Y-jwa= zQlVAi9ZV0G%`|GA&fq*D_1D$W0!qqN&2yDY($wz&55dmKpx%Of&|(q~#sgEihq_1R zt@UWV*MUtkJgCv{Ml658*a?@8uXsHXnv{PWsK9Qtk9p!wU9Zo50HJ#4mz;MIEB`{U z0WHLL?If($oY6BA#H@6^&F_vjp0HzhRAm;~Pf1cej1K;Gx(u{N&<+HQ} zDjQ-CV6Tr0c>-Qz9R8J$cl!sElSA74EBa%Lz5Lf-#@-IM-7g}&!ojJUp-UV{1g2yo z#Yy69fS<3)-LzT4^x<{iuQg`dtT)6*f_>geV(Fr&?ITiG6PT_-Ks(aZz1#Ah(eeQk z!&sAMC{beoZ`_I}mPUiFm7!ie2vL2O3cW8%ZStdIPf7!Molr8Jgr<6t+C_sJ2Qdx3 zWjY>ma`pz{ZdA%voIG~~gIC7(icuVYw9XOxRZ_lT?I)y}+%KUuopuO=k1af<#7E<@u6D)kw$ z0$_rQNczwCgw5@eYDdIj*Od1?<40^Z#=Ff|>N)&RWWgZX-Bq|6ko7>`0_lMr z|0_GFc+h`WyXqt=4E~vTQ%k3!zF=%Tm*CDCTvOL9Y+Ap&Q03{1MeHZsyITc7BAjUD zIidcM{&zeh z42rHqaSF}NaAIOyOO}D0riUftus0ITN3(Iz&_t5V3TWXI-LrE`_It|dBfj$4bBi=8jA=kc~Cp-9W1tWZc;Cmq5 zZR4g=Ocyj;K4trs+;~THfiovwSr;^oLH|lSR5tJ%T(~sS5_jn9Y#2cBb-$oWFDtj58>Aq_i#V-Q%LU%Y|{)}V2J#@N1keV1W%AD|^Mw~#!Cwan8 zRr3_D9q=$i%S*Kb<_)h8-VDB)A?c^^-ZySV6HS15iuFcm98>8hTSy8<6HPq=D?X9y z&_w(w>YCPk(HzEoJd-6K)Ak3Q$gmvnK)Ow22j^mqyKSaNe8ds_jH-`bY2rBd${P?~ zal7t(5RAsoF-~kD2PL_YIc5zH6@*xrb|NB>^>v|f=#3Mci`Uob7(mmZbYdzFD2_Z~ zaw*x*GSAZ5MntEY>J{`?3esc2oMpjskdP)=LlRD5j1=x{(U-M!dG#9ELTXCNavFGH z{9wPG&!WrNmX8-7_><&l;$Lo2iPnyn;PehC9Rl&oFkru7V`0kOsSrXAtwLKR=#=9q z7?sdOiuT8v1t5btgPqoJA+KvWL1`lcOLK$*+SkI(#&NoXmW@@oTw`{JWgF4aF`n;f zruYw8((Grujj;b-_wLjl676fQHsD*a3vSh=q`8!VfS&Xn)E>#O)28dY< zl&k=-qQ;(?dq(@2Rr{Ek5LXuQpM9zP@ux|mp9}@yEfj}F5hS_RGOLXotGvDEVsbPA z7T$?RE#UmIsrq6Km9`aZ(d@<;O+wEa<`^HZ1mnJ@RY6o47*CK*!RB>G;alhbr1nkf zV(?U}XJpe&C-gHDYPoXjq%w=7A213!T(?yN@dbV)X9P@-?eVAPc;waj0QxUaRQ zRJ-N*&J0Da3*_1ozJH^MlY2*-$oY5lN@$=LQL8DHJO4!@S*q%a;Xl_N3C=dFtW|r^ z4BQrywN#}4K*i`F`KM4`TODW)H>Mb3$-tZ1dA#s z@mxDUH>LVt#9sA=%DYqduFA;n6(_$&1-UP(Tr`mIOepA!0-|NHsG=CROHwM5p^pV3 zk@XezbnD`@&~<6K0)b39Wriki;MxT@_+t72S2S-7;99`=aGqq34~jaEOXuGH&W@c= z{fk-uFtf0tu~}toiY_)UN*P!#>yP14;%0e-JL0w9|Cgev>p46Ht~0kiqs?s>?5-WD z12Oj?3t28VqQW=*HQU=ryCMBqJ5#ugaelTgA=DR(#&yiJLKinl2B6KLgZnP{Upzob z{)sFH>DRA&lK-V#$N#|tWX&x8^ZdUufE6tSU)BF&0IxeoW)u!dQij-2FcIM6l!XDz zzoA1C#w8_epeM7X^)V|qYv0K0g>1`b-~9e!g%yP->blH>~>#G|hPd9iJo!fDV4V_0=EHATm- zSlX98b-o6?9f;A%ax@MR-bnWY>e|T;%ncnG;#FT|X@**ICSBT-Cg_>+*dnUaXLkmK5$cQKR2Yc;kess`%y|jCl>+^!WeI;)gLkI72VNvcH5$ z3V7`+|2dPeD2NKcLT6Dck0Dc>#`P{UNhU&KP^+UK($bjcX}64OI?UG@VVXBtujFNA zDXA`5xvelPDh5TvR8(gP@MdX`Hg;o74u&4M;!`atGT3I;*2RTz0<*z-H7QAoDUcu5 zUR+z=$>es_2iU79woVXg@5DikZRKeiW`$A|ox{F4_#(K6SvU}1g$74X&pN?7+tP!h&yFa0|9vgishv@?x= z81*K#ecqgv?(%wj{JF(Yb;2>4_P!ObBb*t*NQ`J}qd-2!-xrP@N11|lw%>upyKwA? z@)jA;x)K%z!{rWqtcWx!7HlnF8_KKCtolWn$I2Am5o2P`ou%ejG{t);hO1r_8Xo}A z2n*ha_UVq!wF%k2xYDp`2i3qu)WV1o^QIl*ADr;~AjGhN2`x+S9>-%2-K>Y~{!t%L z^0YIV-fR^<;tRa9x+~5-6dXO(wU6=`H;kt$yStlSh_WC2LT3-FfO>O9Gp&lh0 z`a;~He#~G@Iv#I!NmrNQWuP;~@B*G2xwehBj^3hWvqy47Z#gd>IdEcm^nvi;4qW?X9DSd^%jBIw{!m(W?l zwFHGy4EVI4jcY%!i%hq3b7RP8^kTI*0KH%H*daI6=E#esyrZPz(AKxTIXXe^Q_`F% zbV+{dz`hmekPX4rQR^B~nXJpfGbM1f>WFp2p(eHJikM*?_*EO`gL=bQ?~M#A_hQ|y z!A4XB%uN2dP0VM z!=0-u)S(;W%J(R*EMYTW!e3SYRs00rqmEIGdAfzHj-CHn5fQvb4YCKrT(&>CNoG z?;$O$?H;eTfK(@9MCLOvZZ;z?T_KT5Uf_{0KH()U%pYyhmaYa++rv*&DMz%kaz_+- zo*HR2c*|CD!0+TVp;N=?Z!mOwAJ{N9z-ugav+-g~smsdU_l-hS33M1F_s1YZ_#sQG z$BhGmk~k>p+6k=QQL08{KfqkKBlr)L(Fl;}y2@X7hs`}5p4b@1uvgxRx1 zV(g+N#PVWG^Hw-Xa~S_|k6ok=HW4m2<=|$OSh51|Gbyy6T&9v~ujk(%d?%2nVpb=! z7}TeI?lue?H5dmhc!2^kDeRFU(IW0~bMqr`wnuq5jSg&MDPYkyyOKoK2aRVSaOGC@ zwoF&iZ!izaEK`z^cUh?P@3Kl4T!S@gc5fd)Ady%UihTnYWMjNY035TrWo(E)C>CgA&zm`54oLOT4_I)@fgN27g2qUA@Hv%8h}%_7jns@89PhP znz=z1%u^?UERL`(!_;$2z@i$TVc%HHc@cg46Pma&msq=o?k(|XuG)$urq`UzbxQ^{ zD^F3& z1^{Eo6Z~TTL9n<`H4eC(qY`XZIQ@*T$9OBOD2{;J2ah6P94@+Dw79K|8VAB!p<_~= zIxZ)SXjq}+L=LKKo@wafUV!Hk(__L0(RVAV-Ph(Qn1$I8CD{s$1c^5Lu|Bp4>l*V8Y27no*FVB`3tfG38oV zn7}d!BUUn}?)Gzu@|~D~6o|qp4NN+n6)vhaY7&8A7LN6nM42n#nzLFT)?r;##GC9V#0#Q*UFBYh}sSOtW$X--lW+UB&hbNDI{+l$$z?261gMHebz z=%xdE2n@^K*rBQR19#uY8@%bta*JU0$jYPLyB%&AtNBpCf9;_Ec>0CnS5FlBsXM-- zJ>b`g%^>h0<$JNTXS7zizoAXI5*eSY87JOc2%{9{;Vjq&N8b)rbB z!5Hs)(EVR5fvcc>>ECs!xjnomvaOmBPJ;y(~D` z3edx`vqvvi52W;sj^9!}VHH?ks9Ou;jz=4{!mGOlG3M&UY`d#QJkwel@AAwKZ?!(q z`Npj0u&AZizKAqEL=R7sar^pl@w~sODo)|1mlA&XrUVE1+=(B#bZPiL<003%vS5{! z%8KT4R2#NDYn1NeZHwRpMluxkc;fDP1~9WesYf4&nO7NkS#5qHmgI~FyA1p)YeYN6 z`4u-%aUizS05w3$zdr?RNOW8D*4&q!rPg;>$LqRS*j6MweXVH`lPG`@q?2y9-Y+P_ z#EqM*%TJ^J{M4#&d^BkPk1$cgck5SPXuZXX0-xRUn!}}4mZX=CP-7GO=vy8icV(84 z_62c(bzI*}herFjlf2%_V0dx2eBDSK9W1e95TCrmhs6QiX*mAqWBGdLH2`%mfs@9z zbmx=tGYJX5z^RKy48r~Z{^gr#s+i;}^&Fh0I75)3N>-DwLm+=Wvr?3%gCZ~MfoW{= zN#lhQ)frNv2`?k|(xmEFJ!|F&AZnl$-r2l8)#4R#YoTs>9;3ji_UUDRk}2?D2}4?v zDAMCY3KxE1f!x(rK~iHQD)>mWt&QHKKhx>8|HjWNzA(1y?w6b;k!mDG$5l<~U-xtP zMQy!SqgEL1mTf8*Eg6ELm?LCy=Q~sh5%bG}8rxdclYjBlkPKC>{76vGHbf#5vW%v` zeS`$@YuT1ktfV73EN6uJo?gb^4>S0ORaCsj48rtcI6Vq!b7@n)f8166F{=V#MAhC| zv@pZ_mcQwFGBf$p^mUBusHq-Y+4k=r@Vx8j7o!Q8r4Q}yYW%U`;iA03VS zgY4c!YZqUZr`A|U-dOult3!QI9eD(Mo$eV`YbdoEbuNG35i|;SAJ53TC0X-h_R{8ux@fv9ITPzCuKg>=!P+R8qi*rI-8?x=$_VL$nI)d?|7+ zikXp9WsEo(`rlGDzh(TCOXM3RQKS>S?|Pe4s~2NaD7NLZo_+yj;*&(Zvl>fIt*W0$ zW0T_+y%ueb(sqg-0rAv2JmP2okgVTj3lI;#Clg()Ds_dHj&RuY7y!B*Ig7{EG%5V5 zbakbf&QLQ+U6yg(sSIf!<+8oGlgC|WsBcDDjDnMWlvaVC`1C0T1+Z@zrGIlPk2ozO zKS8|E=atDr)2QVuRT|Hok43CiOBbBYFl!V~7Nr4k>eRHBEsG)=RDPYx=j3(HU@bJ9 zO4*AN0>>N=v|Slvgs@bvN{ZYE5YG=hnw)|BNRJ zZ0HZqc%rjgwM!SD(>h#}%~0&xR2LAZP%oO;=4aB5(OatzzoWb8I@3Oc7!D#CrVaq0 zH0UEKr!fq)OUiYxtSpmsOB=8@j#<`)E6rvSZ zMr%tN*r>US2oz5=gsjBp?tDf<4;SFMpTfrS+yN2@5oWLRbYZqvPIz)>c3T!gi(oL4 zH#l9z={)k#;x^TMO8h2flTfd=(NG)?LZSBP2a0{yGXCobd z=x-$agb|T8UD|K%yH+v`7USvi)+l2$vrKD5B5U{c>X)`9%Wg@tUx>qBNb_$Fb=Lou zpH|kV5em`rN60-P*Op2E5rKcdPSy;sXx>IlEl4Sue;0`_7V?Cd5>%dMC_iD4nrI~i zyLal&Nxf-GAb888zLv9TE(%J7{x<7e+($`@qC%35d3ojiVVC3f@ zNz4loS2%y4VU9?C-}oQr8L#L-665FGEH7soTbO8DVTN9!;L1ke5B;2giB48ue(jM@ zEE%AdNSZain@<@Hj0i~?Ef`Ta{ZGwlViLCNegA*1$9~hb2QcfMu~El6W($=Ryzp~h zVx?ZnnSqf{h7nTL`>rgVa7aJS16Y9)DozxT-hPRhVs-(#*abO~RvKAeI2;+(3!Hw< z{Vx6kl##`wVsoIPf4#6ROt2%F3HDLaS2MFw!c3`f@8oRO){GmUBDz3qPAimm zOUn44@!L9j*Ps8k=}T+$v9*r+>(|NuPn*8~<9nR{1EKvERdlejcm3a;gUWIWgF?uE zb!ec~g;hVlA;n~??~BAmmnnWz{E5ZA0oWQgG?$_mYy2ca86OM~?ZvaqqTBCqU1f7N zbvf+Fe>{FXBkV!*!dQZujooI*VYGU?H5KO_xyW>sE;R-#ddaaS=!-(KFjY+^V`|)n zr*^xY(lW{lVU0ImV{N+Hbvo)e$WWpq*EQ2L?|?Ut(tGEJ2>tD`8;@e`#GMq)}B`~%Buih!Mg5`pn*-OXxY2=8S62#E^TYH8^Ezp?ht zznMVM`tQ`XZQJczO*!RT+qU)AQ%^m$+o^5awr$(iJ?GryCO0`bIr--M!`}bEvy#1^ zCu^-wPcjlE8jh4pScZNvbI`B$E13Y>MGxC%bC`&GBcXRY*f%LG?uTYe9Od8@e z=h!G5HC!>RcNlb*ac#r)ueOKq(>ZaHdPKfZsL(>?Y#XRD-x)0=hG3ln6y3jXY;;+M z&=#6M@yc5YIvFnd$dPTuzaljI0jO+Gr4mtDLw_8^%Q9S14&sUI^M8E)*TV3!AQ{{L z1mqC@kANJ(|MNole=A^88v&GfnB=Fx&hb5Qa14YE(uE>B5dA9y3x~so8VK%;0jp>x zMa`NjHRGmhgrh&s zaq{F$jv657e~b%W)eB*aXts?}mP`6);Nr%qzm2JddDP)qn<_&rAWUfUr&*j}Y-zY3 zQ$2^4qd)U113OwGfddi-e%gPTqZ)BIZ*tePflA$cif6o|Dbr4ENNPMk?i{;uAfZt} z41%TN z03?L3AEGTieW<-NRm(A2=^JyHwQQLEEiL9-AFqMCo4j*rI)&@eHEihlkYD1IR$fr~ z@Y5Z(AI^HbYeTq;Dmd!RoQz?t8k zEx06gQp6>^+q88~aMTEQOTXez$$EqPZY`EN1LoQDV1Lu4TIY%?x?Yvrs^*QYY8s?S z#=Dw>@oeF45i+kQ9`tG5fLP%i(NZ-Pbm5BH@?aQ zR83++R>c=i^SP~AQ)(h4)?mW}tl;F0to;t#qT}97lR`WL=Ujv-P_V?As%qFs5Fi6A zjXgQhxK1XS2)pS=YC7hI$Qg@>=9rK1d$BgXJ7HpSX(8gR85?WmxN5kAF%TwS3-nRX z+%fR$>4HMzvke1iWKZD6yh@7yEzg;@e62z4s$*6T}ltwBb_~n-j1# zzgwbWbe>bD7}>p{<0kq*?Hn%1=?z20_{`hSEOoSB{4*ciFOX8L-~1DSE9}> ze_YLZel{?}an?5=?9#wh4Pq1MES`Vnhp&ojJQlglzVWd&+6ReV=X2ZlLC6Tlp2^seZyQ6+z_EE zd#i0f@VlL4RWFYl>)Ww5H@_d459Q0)1H%QWptCy{2khIFibK=@$g63Vi*q4^Vm#WX zfM{5I=1h0yq^kbD%nR1AM!l@I*Q5##azUzjG9iwaC;Yf7P!j(>qFmrM1YLk z!qkdfvi{M6xi=~cS^St!1#L6aE{lCon`0S=Hw$d@X%7rHFq0iM`Y>Foii*$GL&2kd zkV0QFtGu1qO$k9z-kxVs2F0WtCW#RuM`A~)*7lZQN>P)^W|xf0Qda-%FT;G;LTjh( zX{Eq*rGvFJs;)YP8@Ea0+;sAnb`A6#UI^BC2K!914<03MlMwp6w-jaMBQ!>8_$&0J z7<_w0i1ko4HCzN@6IHPCTgz+Wx~U@bU!!D1EIFa-^%ACjGf0Q#*@2D~Go}nCV+(IC{C?lB-xnGNo$br z2DZOzQw5e!gL*}o8Uv}0Xde%RtDHX5*x5#xUaq=EsUt+0aznaWw~%||{Z%XBq=2V* z$}w{W4W`9t;f5q%deTs!>-g|3Kf87xM8{iZn^vS2aT)5<_7;!VG;txoS|0u}jgUA| zcUbqpL)oli+Qj4%9D15F6q-;=$;WFo{`bX%T;+StCKzDUz0$MCevVW=~y*pOS&33mK z=6sRgZRm98TQT*=%AIUG^N^3Ko-Nr8cPM&5mpow02L)r^Kt; zc<+^fc@IxVj`K;;(MR(@=JmkzdkJfc(6qRr!%Xg_AUKIJb)BkTY40Kvj~RdqXdU~7 z%vt_@#}wS9k;$eF^5(YqOt#*ezWRb#y1L2aSh~4)({2&`)cRjki|n&pR(10=!u>d{ zi^t%}QLLLfP2-oz7pRF3riDx%nR%7oVHxBetIo|E315h2L(J>Ol3XoES+da??&0L; z2~9pSaf`)#^`37DX+CSo?`lY!GQW<`OZMScV~P_++}G;P6Ypp@iflaA@9F4#LmeZNl z6l>78NPe8LIQZt)nB7p14&RwemcR9yq(l28bh8E%5-|yaX7z_Fw}+=eZ!2G($)Zv~ zDEeeFP+{bAZJM4bmNDGOeCr)K)XA!j!`NBUiLNvB*l*k1R z^|nm@#Y2o^TruWKX+j7OHjh8uYOF0mTZCzs^e-_TeU{e64KU!rlB3dUmP27k*Yb}t z({KIo2G(H8~@nZ+6~If1WZ(Oq;^nX8Qtg4T8hf|=|W2=z(RqS$EC0J3a-(O;rKvt&8!7! z9n=?FyL^;7KYx|Y_h)1O#LnoAm&9!IH$m&sJ~U*GqOSma`IZk-NjoV0@|U9pGQFTr zCr`*beFxCQB4k?d$v*E-Y#2jD{)&bNZmjxStTBLqC@Dbs(ODlxM$EG+C8q>2G;o-e z6O%Ur!c8LA5I)Cdc{?b~i8ka|<3w)%`8pWf`ux{n*~Xn=*aRZf9pB~1IIm(_3du%@ z%;immTl3{fvqYzsL)Abe&~5~vaew10~VnNn9=k);4i`Ca6^ZMOO)?J@-rMR=6+Q$QMT%@CaC9?W>y#xG$_t)1N zK22*huy=Jmm}ZF1f+5VUwnLEdtJx%M>+EU2{R$J}mGl3s&ugGOP}qebvYkx{yMYcT zJDBat!3z6WOX<_m>LDg)3@D$4v0=kCf>sF@JZFO=Pzs@*kmSh4-;cu99e!f^V*-QT z0+UgbA?Q6D8nhBvZOGvF`~23#2eX?R@;i`VFfzlG)jk=)u{>(njvZ?Kz}Y7X>cCwq zj3|EK(wXSWl+7_kAhi9kzU5a;?I%6@9mfVscOS%^w*amG0ML`5{Se|}^mg9}gOlz- z<7aVDC=-w6igTc(4shln&f~WFg(n+S^MTh*W!#BN)jfEOV|^ z%UFMC^Fpx<4SL#rLHP(Lb1&8n{~pL$U1KT~*fzk^hAEXr(&647-s^4{OwiwZxa|NM zuw*+naaeinD zbkqiC!Wg!f%>K3=n?K*-klrJe_ZZm9DM?u!=xT{*tz*WHipaImSEgNr#}FTJ--*q( z{fd4g#~)&}Kr7@C=TIF9Er(N^;H5|52}fF$E<3l>X}`@Rv}Ssamr|yx0Oz58;DLaY zCy>Z)*WQSok47Mb=P-dnsIElBk_PATPa-KyK^iDBhHYUsDlzxoScQYN8iFC`LWDLJFiT?4f4*zU$Wz_c3^yqVQSOrce5^y1> zr4qt~-^pF+)QGOK0rxsN++#fYS+2-g%J{c=hoH7>Vq&NOT`TW6jME!9DBb6$|E|_u z?|s8L&I1cnYIwdJKMO09Z#b%NxTbHK{u_PTj*a*oo9%Ep2z9%Fr8}hGr>nQ^1iGkmJegqHw)J*G9gy953MwMx$);Nj zKW?>58O_`3%Dm??{@iFK$-hOpkfl-lr40x`7TJN|3ElcdB1>Pe{SwZ1{qH-3VrRBm z#fouMbuj)wDL$ELQp=EE|F6tr;CyCwylkWl$E=!j(+PlaF-gB|%0~D2@}SL+S43+y zy)?5C3Uosn&X6;VKWY-QC&EIBBws{!bjO$D8!64eaLc{4tEc?xWO9NRvzNwdJ*7%8 zX(d*Fh^ws=lZ#_gGI0ppssNj04djC85* zh_fSMys=z+NaPS7!aRP@^b1@o|7UJw)ao+OJW2D~^<*p`h-1a+lfxcKWZhQ6K^MKd zkDgf+{f?{qnipKZS3elA?HUh20N_2njfyJoYVh9ODZ5FsWc z!X2(;wC;f1LLJlJ1QJV>SA&TH4?vTzP8Fib9qhFr+8A|YC1cFbGNymRk_q@UGFa5( zuFw;56G^gooQs;2E;Y#&Gvcx|hw!#ZP%R;a3wCv|9ygxVj7DkAh~5YEt|RaQ3=CG! zY9M*_eYfNYhfyw&&eEQsknmqBcEvK&U{2fxTbGX{X?zMj=8QkW(t-JWh!w(h6CWH( z90`Y|cNt+JS1zH89R~w6rU`HzIyZDdya>^#?anAMn<4D`U!WLqvQPCRFb4s@;}yn~4`$i!)`=wID; zt-lRKF-j)7vl9n_LyzTJx*kybHtu^$FbxIsf2%Ppv)*V+^TddYM_y@N@=KlQ!R?b& z&^V=#3Pd{CKV?u;ioq^_gLIul{*hXW4wr`7kGVf6M-U8D$ptLnwe!%q^AA4Qc`GDl zE8j?A1Wsr{&B;^`u_d3-6?<6B+_;!B)cOcIbtHATK&X$)n=RME+jJk}{YE{WD!DNc176 z@@TVtjc9vz@_N^IJMw)y6|oRdyfU+QI(ZgRVZaOX^NIy_$D|s+`Hetr48a>1eB=1K zwd&TkOeN6OU@v>h$FitcF;&&yVK2WT_(Yz+y|MSb8rPQ30r2)2xekm}B*r`GRvmb6 z20Ll!>ylPPsclDqp_^iicaKtxF!xolsFC-lp%0d?tPO+m=tN(y<5zwd6)!C8T1pfg4%P@U z;x0nGPYirS?CS7lc+rI>r)`6`E4ExM1H`O5m~uiwt9-k*yeu@d zS4#wN)J=qHx*qHyLB$9ioA=7$D|?Ot(x(a9eWR8Dtk@;Dg8sxP$I|rOw%yHolTlm7 zPR=Gan`&kup6nbwGLRFT`H_{Y9fV&ST8`lUc;L-HMOsX zUi+82y42t5XcCAPjA$^McQfwjkl7=!Jx63}h4A zKAT7j2mP8G5MMy!tUqSf1$cz-98efeY76QS0Y(Q*GnrT~#U7(}8p`q`waqiE^T6z_ zH#!9}Pa09LGFx#o@t4pQhOnR9o6)9rn;=<~m*OLWF~<8(Ti%*rvR0=+lBfV+F$wV` zBEH5zgp9`uG-~N?IasVrwJ@e?pp^kyG^gdS33y|y_dq4J#b3xDbsuX1FUKKyr#H|N zBCc>4bo}JkxGPi}B5(4qo3HCJfRC~jKe{U=3 z0*aN-c~FsZj6;J1k-nBTjIzftAV&?5uV$F+=7cL?V;Ozg6mD9bk)uXcQD~qc{IDfh zJ!0N4d7S}ywRn{{=c-?(g1aWd{OhhFT(&lpRn9sgcH;UktjfEDonEa}@^i<9W)YE( z!q#YHBW#AHnD|b(Me;C*6Vg*&*_oRDkmQ6oKfp4yBaDusu`pyUVna?G-uM(u!3NcJE^j-8w9zf5H#2R@h6%98jN*S;SUmO|TC#v$YrWe=iT16qr<+fr(Czxjv`AFnn-v$qpIMPIQ2N(X@6a zc(<0NXOwG{B06@56VXGYZemld)44MdbKatU4c&!I<*PR>zWc2Y00oSd4lY1|_&<{} zb^_oM%(-zHMdkU#T(?9u=y$HicB>O|r5SWLp9ncEv3@r^w`QN=AV{Z!&ei4ceEli%LvW zW~R8rpQe94E9>%cR+*oDDU_g>gQKNZ!ZzsTp8!6V1?f;)j+OXOt771Z4Y9fr`~66Y zKEWlZW37RR%-;8rew)eE!55;8|C6ce&0mYV2o=n)U2;V^rNUbr3AyYwJ|khf7`Y?M zLtU37-7uA?XXans(A5biM1M3`LCN`CJ~#c3-c&MM@YsH$NG*$ueKc`2)uvriq8&fe zcubW`vkV$0!Zjqyswg-y_Sfu!>^$N~Hmd=YyZ$(bL>gzA52*O=v$ZIbhU3De(#)q+ zjf-ef(vZLqv$HyAy|HNDstj>InP(Y z6oNmCQEENwT_nc|9OmHTL^NFJYGz;$#RwdjnUbt%E7u@_rkaBl2WGF#Mtg6PoU2&OpzPT4JE-s8ns=O^oIqA@6$h&#-xhBC?>&g?WDa{r5*|G19 z($b|~Rq~6}yX;3dvB~LSPlme{m{`+jNN)a#!oVxx4Si{xD*ODCHU*}O+xOPDo_=O# zZW~el`-$XBWl$VSGaDrVGZ!7F@`^L1Uqv= z(_k82mHSkg2`}XhL*Hi#nf-J6`zmW(Q2cqSAMvWn>sY1hPd*3Rc$YPic(rpWzo3$0 zKRVKBrMyi*XQScM-#!y$93c;>UA|Ns1YrqzU0VV=0fDe0oY}g6++iVnj8?8!11JCP zt^QKz53Ge?IBPZ|W#4jLh%fT?J9vM4w>QWxhUYh^Sj-x`I0DiYC%sBzK3!%6MgY-J z=bU@alqF%YdC>xHVAiKt2ZJ2H9NOnPBoflZrB*8S9uM=<`fR^Pssz z&r4>(FY=guSP_IT5OaJZkhQaK@&NS#!A02Xt3M!&PM`mx`^BuEw>a$l?Y~zc^2xnx zCeu=SsJ1el9cEE@1Fvr;@LiAe(jt34_Xi0%EPyE| zKg!wRp!aM;VfDwYp7rYIB$WF5C-wR>nZ?#|)BUzJV-=%xDB}6~rQMB&dU9t%gOLBm zV$~5ngrxWU?{b1o5uV%a6FTb~Y_1pgv8I2+*YlcM>z2@ygj<_2ds)txphbU$&(#%8 ziob&BLYN384F>W~k7{W2IU*5}}PS0|Whb0usCE4QzbBM78fq^-uLm ze52B*cROA_%{`XJpRzsL{r*zPo%4+eAR+-QdKGP7G+J-%fq)_BPSvQ;IPG`nZvO-B zire>QqmaF>Oi*P}L8We}M+iMQ1vu7#gQd89jR30vYhOCiE=!@&z&B}|wdyhD`A@vc zWJvn83pIW=13Tf_>+P7cz>x-)NX(_!r`U}c_`)e882hKOBjwu^d$?p)&8CB(lPYf% z`|S&iZk7`zHdj`5RI%;_*zKQ$`r*6c#;6(z%3YFcUCF_n;i=s*l+Fc{tKtb{NUm;9pV~tGLqp7EvE~2%yG@^vmQr2 z+Ts&lAxn{=?)q&CVSB3^fvdK77yUdihgr-qpw!=+!~L zzrv6&ksU{0D#>?QCp#pIBsm9&m0|MsTRRp=>v6+M7p4c1RALkgJe5}8st!^r^js9{ zAjsX-?!_#>l3W(j4t?A~y1z!gS;k85l9K zptelAcc=)SUKH?#qeCBa@zap{+s8W3*zku#2ZfwagHUzME#X|O^^9HxLJ!RGpQ-z z1|KsA*TZxVAgwUhAX3)Vum!XvnkHX@ZS&GX>VL2Ve0*t~Yz|Wy|g)RD_ zyOK{1$-67`6u5)L8!Qx!Y1Iw3imdlB0{uJ0T2n14RB)+*L;{ zp_9o{*v|%XtCpreBj6Lts*y656C8kP2>KWM92 zcwOk{4lGcaF`=R1{~W;XY958VJ@o1~#kkz3ya(Vd1Fn zq?!c9Ucv~RW29Bbxt1SBfX53lEoA15EvJ5}PQEf^<^IPVP$iUw8&0y`YR%|pcwDA( zD;SLxwA-OjwJ4<>HhJe3UGOOW*GmYLw$G9vPk4WOap;_-i}L7CM?GTxR8gUXke_q$ zcN*VWEW6%KnHHz|8DYW2^78mkT&`Ipxml}{ecg5`*M#AA3+ao+f96C_;;DXJXg_|` zQv6RjkN)#RardnKDCeu*t51YEN@p0HC zFI#SY-KX(*G8M%r8M2M+`p?r7ZQ6VWIwEOYq)$GnAaqz0*FvUzhD$(O-4~%=dy-rC zvRz`R*S5=cf-Q}E=FKX}Qv3CP4NGTVzh=LG%sJ$EBKP1gTIEU^`FdEh&Jj#MA$dqZ z??XH(8VI1BUPTtx-?S)`H@XQn-iX1y5BwXy!6vW*hi1*f>=0^#~M(>IpEBQw%Qf zkC$Vq_Je9|1(Kq0FTL*5WfV-*c>lz-_`W}>0@~B!Xf9m!B*FrV$repul%kZQf0)xE z%46Jrdn1C;PR!l(Ss2Cib&SSx{aHUQ}M$>9(FM86u%lurOPdfQtPeUvXt9|Dh@T(!Th+`wTVL zKfCPFhb_uRp=@%+&=-2Q*|s^h)b#j=B@K#ft4{>V;i}sC@Qd(+r(4X>x?2kiseM#tPr=ib%RVgeNlH4q zKUB|y?9>?qPC+4FAxStI8~8{qO1;KXQ|xG=F8VlvsxC3V5YHIJvC4{?S!E+6P@`8W zW`i>_6Hv7>vdrqnTU`BZ4H(%o3q5@SL})+#OOvxn0VB!!}(crd;P}g)oF~!9)AQTZ!QwkMBC7AZNf^`9_ zI7eOy6WVptc|zyauB2JE^yG-o@B3Lzo_fYPqiEljtOuY~P?qUe^W|m++m8<0Ic2$8 z%zU@_QM70Xa2;WJetzTdsE}2y0=ntUvz6N^yZtr8zTNtQE( zGxM{JkDRzRx5ZgIRd!;y@C-PaB>IW0kHOKkP=j z_^P>>-N{KpIlDrOub4O*m=*U!DC8I8$E+!-lPV|jK5T7Qj=z$Uzv_N$w5j;qy;Zac zNY~z=)YsiR0x4g>`fZEorDEuKLN#!+Opwa+C2$DmmPSsF+OG#pE5TBz)JfO*;u2WE z-b8sHJfxy*n=-(`Q&*OME8cfyB?n*NeSq$$yr0+rQfMe`)k4gkn~JdkJ?Vq3sT zkbEn~pFSigWgzUi$2SRG~!(NLVUs;UTE?3yARdhvXUm1??Yl z`^PUZQ^TR5=oIE{Sr^w^Xc|D5((Ibdpi~3Pju?OEJ)Wz)QcedcXe68Bc3xgi*4Zfe z*PPpG?5_}zI2+9nCp-pB-hn+QDG8Ylr@y? z-?jWy53#!{`nfXAF_$72Jx0}%3D3s6QT8jfxd+6!_eS`rg!Y13r6kM3`^uX7q<1nE zq!K*sN!9ud!ASp*ap{2h3#G}~vv>i6%OkpUq%nH3%A-+wm+6QWy0iv)P>MAc_PEx5 zAG4f((IR-`%w^T%`{7%+7eLO*nKp@X*_3>!fcYP@hAd-aYIAZV`+_xH7gGtVguOdu zRkBs1?k&Qo!$IhD#M4cmPP#imu53)Nc*QudB~85|G%t7Yu0HfMp`XbIeoYWwr>JY| zvh^=IJ#T_f$scXIQZ@KR9Fx+;^m;{W%|BdKRZG^D6Vh7Ye)T8(KlZiH8?;&K!3#E_ zGPEnt78+xs`F<|#+ovp-u|zEsI%8Q7G_>j4x&AaRFyRR~L&#+uR*}Fc*W3K324Q__ zb5k*0^Uqo}gKmDt)I#Q+j9s)j_H84~d%*VM*S*5gNf9zbQyk0rkFS3)<(KRc)=#JxW)zMU_-7 zPyBj*K^mt~l~fH+@cS5w%>F}m`pI2* pk+sy1FzL0WfO*WuEmW2l2n?m~H^3AhM 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 z zBvECP`hj^0>gJO)Yyjz2+2J&%(oN=}7&p4JKb$ zEibtvsZW~Ys}W#;rjSYY1GC?yiEmm$s(D>vJ+aV*KJ6U~-t8PCQi%E`-eucj_egBX z|KYy==;1YaB>%3;CZ$TDDsj{Bs2gXZ;wjO3A+h4krSVCpZEW!q1M2n%X~zv~w>MSN z33+Tq@bBv$gY?(-dqCBptN|x&+IQk>{lhh_m0+BM^as<+2X)Z<7&_9CJcEI8Su%=% zZ3Sh?U*vvXa~hw@TDHXbWIGmyR272YIX_X#D_tMimpQHJf=0p$A^$kvXN$mQd(Ss4 z>Y8c?OJDr3cxSzV6g4aDfjO1ytYBFD6`prumW5T-243GkIYxwJNHQAJ*&!DsH%gh~@HP5yO?6`ieHadY-qf;&2NgH_B4P z;>3sU)QyB%BU-)rnqC-kfIIz|oQZnKN{T_Scbg63?*^f6FyS`T@p=?8oSA^}C@wDpBaEA7WqR&BZ;UL^ z@ww>h0Wk~LGYwB7_2JypCq({z!#~>0F-_qz7M1mjSlPX{$>jx2`xACPhN=~uW{u&y zuqU3Z(XCi9a`n@jg-#Yk(+9)WZQyGFr)1pJoi2Ey{;|ZJ4LoOp%7YKG6n-`aJ{D~b>>*%7J~tRXCjrM2n18JPXGq*SCn8+od4xu!EG~_rm&&H z0ULW~fy*O?Z)#9>kY>e{(R}qQgy8TJ;Z858;Ylx{jw4TB&@Y^?Zs~G|1D5bt!fUTI zm45liOltZ=aSBj=Dw*ddE<}iw`x71}n7uC$LgU3$x%`ppzFgC&+xv#e(V2JFBR)pe zz8krKQ;4ApOh6iL0~o}>@%mg%Zyp!)yWjS%l<~NaMNDYvVBsP&D9kfv8wrsH|5tCw6U_( z<0m7H8L<5a?M;8{S&#+nXYQvLfpG_6>K_pS_;LJgv9BGu69?nSj#%H$MC5IIzO8-i zJP*!8-fD^ZjU%yG^l|>@Qzm!eeDPVjwzrD*#F)?Qsq%^2o>-m(J2lALm-dK~0U?*3 zebtk8x{rdxv;O;@PN}=G@yVexyxGNUIFi-OPQ*OD+{|8jO}%qG{$~BWKax>!4heAC z{6(zsQ*2}%)2*M~$s--nBkSRC+p^CN7Ky#_fLH&PJ>j&yUlDV|kAH-ZPuy#a%lYq_ z5sz7LU0JG(4EpRW3>j>KlKtQyE2WyCRn;|eWzGoSCw!oN-u&oa^y1xY`{+Dvl950B zLw6w=FutMxBX2#%J--)%0|9Bn_}{6&(Ehje7g}DvYNG_-3eTPs=1CyN$+5&m5b_;;{4I9u!IFsoY7SfMX1~pR#J&0T_h)+Xf360FfXreZBL0ER!D>4kbf*I@ z0C8hq&*H_?j-U*k;_ckiF zVIXz^V-+~=zqKmHx|Wp3>9L<9m8A)!b+S~RT*3klgqI%Xa07} zx|lYaF7YqUyiUl7vdS@St6HxTSt$hb&Szu^5s&|P9TMZUs_b}RTq3(k=7#3b>muC9 za3eW2!ZgRLz^LGb6{%HGjO3k0p_W~gD48%o1tu6+wNlk^(%I4$UswG-Pw+6Hc+A%s z@5@**hY_TwKTK(+gH4NY}4q(x_n>z2UBM^kfnV#SWLETbWAm z{I@hRVF-2JAYaF3I&R|l+v5;UOUlIzvIRR-6UIxA$5wH@W$lq0ZnSw)s5WcD)gNbQh6a32*SD67l2DWZ+x zBNvS0Yp!c@{$qpfRRPR~KD#0G)9;n`82 zPrNE~nd*t3ZxLIe zO3hrl!MBN$&c;ERQjQRR;yck%(9&jB^RQxVF#ccp*sm-e(In^;{!#f($t9Cc^9*)Z zG2u&YQ2va}hh{&HgN#-LAA?7jmIc*NiI6W`-yI?PlV08GC|7>AQO56ap)&2aBXyq7 zsExDcZNhJDVn+>x7Dk<}OMC17?HwVyWmO&ALQi zrc1h3BK#)3(`*IDSRyNIT{{ks+jBq-(BysNp~ukrPI=XwRf^u>^~}L}CXKg;V49DLgJ?{A>HLEGBW930LypT{zA5U<6VUpz>v7}wbXu##Q zuWra~>$T3AFlPbkqd71W@N=PLLUqLdl~Vpne8B+jUTMgpQG-xEj8!Vd6v8JNA2Mcy z+Ao&18NCQX+f;|yTwjBeOsQt>I9Y&}uYn^P*0?$7X|Wjy4qk4O z<8HLa-gb{Yu%4r>nbPab=r|RsbVUDB;)k6-7>cXd>0_cxRMo!f{h3E_3)wTebt9UI z>n?D1C9c%&&Enz^h-Tkp^8o(l$L(QL>%cw>|N58NV@uvoONkD=FR-P31^qqxfk>ng zH^t_?pvwPoDtoa#zQB!#3#A zIJI8|^qtlp0^AgQ!#6)tcG~!D+>;GoKfjuQpG=Ux6k9jqomnO6y?Og~7o%B(=;o>| z61~k5IcstrX5LKG!kuS5q_l^@D#HI^bE7q~6RyzE$L8vwt4w z)9|m>&s{CYS9RpO`JI}}ir@(wwN)2lO`Hf!^nO8uCW_$0E_&8k8a={dZjdU+Gq(9! zVxH_-w~?<#R7$B7XH>7ppaUrMWVse?V@J4NFOTchUNf8Ba!yWYleOkFa5$M8*rWbt z{u~bceMqzxsr)&uz8@GEfZ$^;l+1sCO%h-&40&|;uFW?dduJ=GErfOJu3FxpNMGk9 zqrgACQWYh5*>Jx}ur26%@i*7;2Jj$J{=Sc3Zy>PV%MlWf_+mDX+4os)uF>A)g#ISQx!&|>LD1K`t&naodC;`^ zflBj_CiZ)S!!nl6%6lLjNeGkuJq#egCk_9fu5XJJ66WLDv&l)7w7H;B zceO6G6DQ?r<&_2%FK5UIa&TUjy|CD`vc`T?R_F@I9#Ik7Tep04F?>QL1cyd^Jf?y9 zbTGQRSVntQKx*nKZDFWg9gdVZJAg6*eBhV^K54gYHt#=KiP4C7An3L z6Sy97-kuS4g1&emqda0O_<-<%fu{Ds6zGW(io&XRXDx-hw#j)!8u*mK zy!P#({t(HH@;5M=@T9fv21KRsPCFM;CokKz7S2~^ze zj1A?E+IR2jJ8#s(-%dNCdPI`3N^rfL=YKuPmou>*9)<@2QT?}1^11%MG=rO~m8}bt zsDrJ8vxI}Q-M>bd{HIRvi)Dcu`iU-fA}L>#x<}D6FRm-gf{aYhKWN@ej>n~~9RN{p zz7NWulCi$QJ<2?4x^waA3AS#8PeNRiS}kteVaukR-Q1Tl2B$7FS4JZ?HD)k6t9^oY zVlz?W7fNERGm(w1;Xch$-C`o5XZe*Bdh~Jo!kJD#+GiZFTNa(d%+t9_my2Bu+iVD| z;tGQp0`aS8jz@lmS6%}>_*dDw$J4EM-ai{$0{M4G!1@2<2-E;}j<&|Gfd6VJtfnuA zua5r3_|Dcqu-VBV+YMP#S_;(nPiqToRiamF*qUvEiO|LyHO^!dP1k4TldWkS!#0gM zD_$8H$;iSsG5L^grO>!L89j~8dR??IC0c$xo>RS>24;Otx%Km2$YvIgx6a88d=(sa&Tm*C7T{1U|1X?tdu8L?n5u%n?G58zmCjj z^~+;>NKhwFG$!9Eb7WFGs6UrAOUyR>#pd7tO&;RGEL05LfT$Ndq*Q%mKHbBDHkE;U zr^purupLM0GBGd1`Pld5Cydk#BB36J?zg*2AxW)Ch?z`Mrz);8BXDh{FsBm_9S8}$Mh%KT!-l~CstBzfrd}KW|zGczDl_P zrq_D=_aF9ZOH}uRfT71K8&%|T9~|K2*+t^~WWyoT5V)nVDhLaH(!B7>=T;6Y;wj2G zKZbBcsZMyMAE@iTJuDF6L$MQpKPrH*SR{cVn^)Wj)7`VC+~W24`*hTawwjYo6dXl^ zYt}{a4+)fn72bCt=kiO-5|U6Zdh;WCa5j1_&ZDATjlPf|7Unie)Ym)fk}7U{%i~*U z8!@Bob4mD6wnvX&bMwqC_@T%_0|})+(6eoet08?S;+G(WVCW^ZxW;dP1(RCWRay(g zh!x3qUE-x)>%dR?=YhPM59Wk>N8iyqzVZ60^(;9r9)rEtw6D;ML(jNFfjGROC%R~S z2d5qee(6Zs2Ykh?S@mUZORiMqxD)+`E&OzhiBZxUt|Jy`>p0WMLv84)=tH(R2N|ta zFj=0$67D?bLPnRKI{tkT;2*7H&)U$@I~J1ELGC(Qf=NqQoAlue)lzL7mqv|L7ecHv zthhM=n;Zi*+%+ZhlseQ&d*~yyt|_O=7|~$8HLC4;{d6h)gV!KV{SNiU2N~FgFa3YG z^txzQ8se-yt*a&3V3#q6#0R3AC5~55Ou&Hj9T4S<5&Ie}=(wBc2QUAM@{T?3k1331 zGYaYs1HC~8(>y-W7Xc%_g;TNcEZMm1^A~PjwSkJ%o4{v{`gOF7wC;B)$mOuVPW5~Y z`0SAei#vKD{=R4ap-`B49Z*oQ z-2=8TLFm-(#wM0iPxPIYw|;*;WX@B29`8|KyLaU;67V5P&b{&{ph_%QhFwG(RjuP) z{Fr(aS@5ny)A4EqcCaRC{lzpeV;Ln`IES24G;VWogE<#SMJPW?>n4_joa`u5RF7$D z7Wix{eb-d7B(jKSwsBKAlUO35I_^scG*H|{wHE0Me?DY*s>A+a1LIv^^R?WhJT*LG z9K|XmW0zYLV^s)UX$y|xLuZGFl%uX_#aJHb&+8K@w}5bZ`d38U zyUtIlg8%`Ef%(50hW(!rQ4C;i>}Kn#VQlLL_;1{hn+#MyQ$`;DUSa??F=E0U6)QnT zucyg?_9u|iCQ)V-VP)VlwqMZ*G<^PUq7V#h?+f%W@T!hX6GJ8XnLm<_e9|HwoD%BE z;v;B&%=OK4av8t7+Xt>Sl7;lcxKgRQ#Jxn<{*Nj~C)GK?svHh57BxKf5FcFGC!^O3_QI5yr@MkQrr!$gI*6T0 zg>N$1u+z-i(@j)At3&N+jP;EBWzky1Tu?YC##D#eqQzfcoX_lAWjp28ajjFVh8h0h=?6~rIn>|6Wa+Ut}$p84&pOkwmG%gm=+wRt9L1Sun11p^cld381{b!17n}3d8 z0T0Hs3Mru$$g>RrE)$ zY#vHCkJ)=cyg?WBZ<}6qL%Y=qA1;)8sLv2x+v)jFHvJzoF)fi8{0CK~v!V#2tKFff z-bkC&lgKf(I>R&(F=|gk`gobDFmiV&*0ut+gl81F}wgmEA;HsSNULQbBbERx^04*rL% z6F;We5nVoV_jw0k9>$HF>%p-lBkDcCP{h0hqNQyc#?U1xHffpTAqzNkM+jCeO)xy1 z;?)h0YTkRw_d(yG3klfft3#wD13^T4(<%5b+1nc8f=Y4|v* z9btR}%{*?*J0T#z=|y6dh+$#3M7%PTFi3U5yHG>t zC3RaZTVG{l4d>6H5M$fgUMn`!W|?&?HqTtk*mC0nxR;#9RGoAz1k2w&d& zTxLCH-)7%(AN=YAK8C0Rk6uHfNFi4eJq;_yUAcl-WN+3)S#mGa>hvW>l$EyE?|C5EaOa$L2(sTV(B*35b)_ZSbKC{e zSU;$h9krKYpN4+UbQnPPwUz;R*Ob)70o`DVe*D%DN--*kpmNI0wF@mV$7+V@#_ebN zETUS`l8;*5_Sq)6B;Gj&$(v~$29uSiN7Gt*@%9a;Er|$QcY=eeO4?4>k+k|rN+>!O zTYrs;GhHhROI9u$U8w*rhFhc8x<39w#a+d}LN!C&)|Mfepi&{lbqdJHQ^$^%hLI@u2XB+a9&5(b}H~551Snvksn#lQk2aMq;KwmMdRF!R$zB z0^g{yjQeE1XqA|>k_Wfg_4N6;*byA3xTpf zj9{xmp=Dvy_E&Y6@?~&FKSmYSe|zrB2-!6VM?6VR|sojs&aKTI19? zN1R%53#RM1=T5y~{mUYog~EB zY2lTy_-=!CHY$6u=muA^sZNt$Hr6O@mX_jp09)u1h=*->%yX&H;* zX^7w`WcwLTvZCc`2P67-Antqcw1RV&=GDT%^(?cOJE7T;AjOX6@Q{(QWQBaak9;_> zr<|fHS<$?3u2X3Rxc13L^ORN);`(jDJh5RYOz5L#2iB$CG)73V|nJkd!Jq2Z1LlamH^c2SBDDhr``CEXKsW(}pXOboL z;yXHhhocm%Ki^X7&FpHy^3JNw_)Ev{#U$_k1x$z7)hW^m@3izGkvy7p9i>+lR<+lW z2dDh-_dAeJE~p9?nqA~A$ir;hJ_>AAGX6|cc03<3mTJ$6f!Jl^>^ScC_6K|Nbi#pQ zPq9CT%1saUC09ey(03U|LU}F}ojw=aX+C1ZXr4(7a`Ub`W3ELeq}F(>k6kpLxT3Uq z6W&R~E4Ko^`Fl+3r(y32754M?(nPG z0}Q5HoRPG}6Ep2EW&H~r5z^CK6q&=N*1iIV<#+N)8;OQ4wo^I-e=tpGKSHE6BvVmb zE?0!YJl4EZX~SBbo=Kt5OySmPqQ}&?u*>7_4>-+#@Y)!lBx!1)g!s3lr@BbH0>*oB zeOvp&4{&)+B3J)3eG5OiinhL^>=IL+J$mnx<$w^+|1RM*JF2H%gf2UQc(>4rudX$? zo9f$BD}o2Q9#q|k=5{)!L(a1kXLE;qlsDi#ZU_I!kTU9gmuAYKdC>lQxCCc#czL6e`EESvWtvdrxv6VV@6!< z1w==Mn5yX{4IlkDW2_msr1W6oG~e_8(I<%XBFf5Wl_&eSCb+(;;WILhvyIX2bQpNraUpz7#(325{s+ud2o(1$9e+t2Zfc!=MU%0aQCq1+MZ^9%sjt^;w z8ClHY4YC4R4-7ZP(kii9ir5KMt|1AMN@5~>SlJN-DXc*jm%L3&{!Ze-;AR|c0Jj)| zV2JjibW%I&xkRRKQ+H4S5LOvht=BqKr<|3$)W;YbQH%BnlN{ZNcO>`Iy*zp*lzFOF zjQMEt+HZKMj}-spY%Zu7rPu_3H#9hT{KL2SNd#>SdUrJwaVw4a(^+3)1~h11oFDGo z55YtP)gOBJUvkZu>D;R7pS}J7{a;8{rK~J0ZU6cH>o{UG9^aH4$61okO>x@8uz8VMxX2NufNGM$r+-wJIz5mCI~*o60?$j-e$mT%fzX}wC?S-_6}E@ ziMZtd8#%?9r}Hu$}0<{34}6KKRK4ixSQ67)c$7?1!h*R`-Z3a{hhea43iUqUYXtdS^UATctb%ELI0;5w#ytaz&xPf zh1xHbdiH@T6)hs_28M;gD-@Q(Ep!B{+&XG!X#|oS?A?6fMrRQFTHAmo5B zmh>+k%d~{K1zB(J8*09vd)wA>FMkF6O9^7I{}BBAM+pKU|DAL3|IeID&e+)k@c()fqPFXT zrjGt)pKQ)`(N+S_fDVUgBAb*{rY7Ei!C(cxzz*6z5+3|y?jqd={BUeGUj7~o7|~jS>?3WjJKjT-kj@BI}WU(b}lDlm2aOFP)u-0AZZ#Vx=k6LXi(ZgNh>EF zal8{E?t>jeW_7S&-H;D2*6jpWT5_2HL<;K~Zfwui9@RT+8yRUsmF~EhXIyUh9Plx< z($aU&=H^9hF9W6;@!C96NsyzlaDvaw#i_A<$es+)F(h#cOme_3tGE@4>P(Wvv`1-B z4X_c)-Kdq0&h!b4EfFN0-9`WKJvBLUd2XN}NYq(5mH*b)-Fc5M1PGxZg7%aj;!9vm zv*HKHUelT&3@=!^+6fOMpe~xm8S}e$aNiY8Q&t`loQlm?Z`g%Tb$+j@S8Zsid)8lL z7}6b@AN(S-L4WZhAlehPR?5AJ%C5WZxhZ`+2XP^NEPx(oO?^oYl-jK$vcL>WD&dq3e~y@SP-x))n&d9n0q1pml^&eYobkJQ(;0WC z9ZKErTQ)WcA=$o8+3HI&CQX|`qIZE1Col|Z6TPF;>X>7G_qOgm!b^z=2SY_QmWAq} z^I_wb05!Z=ALCNf+_8?72s5{yZz1qLPrfIa|(@7I}T@`b{8T9%%BlBn~H6x5j;M6sD$sD1k>qY&HqO+*Sq>H)0|*g2AJ1v!4KLE7OVVq zQT980Hj2X!!UILeeGr?JBuL7Mdvp@{H*W7a_y?)C2>6b5Nj*{<9C2x}fbHRf`gdlM zUBISC{%PhT@aPOxkn}S_?@e$%{||}u?TAB%V_)>tTS?<1jOv6LRz3usehvSq&Ts9@ zgXj;Y2qDSB6a*979KH(<0)h+uf7PnvKLd#pz}XaF@A}`Pi0YL+sxq>GD2=R>Y!Ie(>k4ffSQ~w- zhCK6^(h!qL_Hx4G30S-11*2@6MQGEO?89&ZXB8Uic-%PtTIp`qWxj9vrzK_NN#q)TeZ{WL7aOVXN#wyNt}MqYT7Kpt zw)Yv>M6#T9%rupm5JX>f4;2o$RHH>!KSEt|$uDKCVMIY#u0}y&{)07A-#SC1!;(jo zjgM{=`v3|57?U#gp;?&J7u8Fxz+`x47vpV+rG9}S&@I?_@NX)if05WYa>NbBKP0vd z{_n8I^gqO&gO$Cj*nc7}Rz==n=_j(^l5gfRd8L(Q5Ev9(D=?5E4#Ei}8axW5QoV$b zz+%PrVm+~2;;J7kvJ6$~1H>QQWVP*Q5wX+y23IrN&CK=X3z1)A=5m*0NZqyxte=m+sJtFq2t#4xU;}9h)EE?B5&^q&p)z zJ0KW3>|gj!7SrsatTPRn-;sTwN3AdQZ>f5x>Pm?8Lim8x@I1j`CKU*xHTn6YbY=(C zg2VI18%yiSeRkn)+vQOZBN9^=-mQ(GO`q|cMQ4~JZXMDO>*5p~a*OfBr~+)I?adwjOE@HTD}V{3hkp+j!PFIz?tN~aR@E%1m==?ekmwkl z{sM$90M_W6CGd79f-|&UK?GCorh~&`7tCk5EM|}L*&goRo{{!oba6^x;;^2#;}(G( zN6*W-JvX$wPhF&ow5J`78veU>QvI0Qp*SV5Z0!fa9esPl)vL9S?1SFOfOjNPr`J`yD z#7E1gS>9nat~a?;vQDB+b$R8QDGZvE_Fb_*%qNc{Y+01CZ+V?yG|xT<8Uq58T$l%j zWK}#O*HG7vvE%5SS5P%+iUT3(o7ZrTO(Cm)oPA@kC{2^*J+^Jzwr$(E$F^!}EFex-L899sN3_5237lf z2V<=7(Bdt_rhCKh`p4nkX6BEdsRfIfk!RZDpSandL2jxH-5QQ_^qp=bha@Z8%)LET ziLBz{TNBl;Vm^bzc2))Z#+oZs2BELwkFmdi+@sj(yybDN@X2OJK;KSgQptskVF&rw~*ws<=td#l$VulKNzYfqkc?vpsPK$iU1z8JJ7 z*QH3pJuyemP~%&0@6+O~ekd5*Uurf~4nv;o!v5S){rUEymEjZLp{iK%0_usqleWMT z?rj;Flh3qXAVZk2fITHP`p^k6*8n+O*_xIng*l6M-g1ZcG=nw@@A74J6&A~ z3(qd&m>M$(Tu`vI_Mlr|8LTNoFwq&+q@cV$NDa!=C2a@`8p-tbF<8GPIrgf5OrX0ag~c?QTx&d`y0O^EGAY?%Gh(Q8IOe33ks{Qq0gSE8(Qo(6 zsx(G#>AovPEr zBEe#cu}gIFFK4RF%eXi{>3nq^5bNI7<=84_##(3*TTx(sRw;VGxWwu}OxcrC-In)N z<`I4Xfkrvuhke5#5%wfz7Zvbxkh`>+kQg$eg)Ga>XkOANt_~ej=1et^ z9r;&Ry?hY)Uud?DdSF2M4);)K1g48zGrWCeNg~$Rsc<97N}&cRYAW?g-pr|c_56XN zt0>NW-`B}C+IIF}lhLJ#l44#k?>Y)r^-OyTfrW%Ynvq_k!w^!a$Lm2_n<9+X9qK!# zv0T*+Lh7Hy=UP6tsOpF?7XU;a^(B$_o1;U^#8$3@-X&PMiClfz(gajhMqRKtXwI|5 z_=!y`x5;KvQdH~pfG!#Du?31+Ey5YAP zO~8SnkJzz|p?|L@G>;Pw%EKAf_d%8-ge)^(eX6b;mXQFB+NLU6=RK7NnAP!t{N@|k z#f;)R)`~Z97EF>m7um7xHceCpgtd{)s6vYNsI~mw9qy)R0xms@P_0M=k@jT(-ND%% zU{JJ7T()BF-n6XoiCzpVRMv#+7@3X*BEV*OdWp_CH5UiRw4Gv@yhCP~H0_lM4?lK9 zLT4Sw)E}TE_-X;ljXd4UI84r;GU_B5>)Mh>&`w)_Jv1;Js4ZO_9cH*>+UUGZ8d#WP zd-J?7&ITt13%~{t*?w6^6K*Q?xe-m>Q0I#}{Jjl1-0;oR=Dlv4RnUA{@8ToBswl$U z!tM3c!%1aj3Y$;H9w1Jh*G*QPOJjJY`YdzCf`ZedX(Wi-0z_2|lv&#$Y{Qu{fnCI9 z%606-!p-D(^V<9i+zjOdX^39L)faIqJ)AmO?2y`rs~z;n=(feeDSj+y)g=i~DQN+Y z1VY-~YV6Omp8ywG(xw~g^sNZ*c~foK2Vn_`_Hebw5!3_hfW~rk(hPX*RGNBP9mtp- z_NoK&D|P(gL!SagEW{?l9o1>iVkT`X9qo8;(~l~;^dgVz<%eT!hK@t$|gXhQ*O zTG$99S}8=OO+0)gl}JAQdx3NuJqN5s?zSs422LBLePx5kw($9-2xmJ8_DIZwnsZB|9hBgGZ_SZatW5fD|pUHP`lL} z&WXWs5gr(D18X}x`Omv`i+i#FsPPYNjedvlolj^eM7Et}_K3{3VRg7k@9xt`1F@&5 zS68b37R*&s^I96tND*7Y4M^ugM2yd^wNaJ>>72Gm`z`72wxK;Gs_OtZ=DK?&ligEV@+4K+z}-jdMGY`_R97zbcP~(w0$&nt z3NO5o6PIEtrDWdsZJ00!&#c?p_#vJQlxzogYDmn=gu<6E#LCA4rTi$q0}vJ0nB`Ie z)UUfQONm??L*L@e_Xk>>upMjC9`elh9YJZJB8VOTP?NVVjof10RB5-ln=M;jX{^o! zk{cwwZy5mpR5s+BIV8PcIwn1Zl8caajNEgaE+xHTAyBp8vS`Al!SC?9!`ZAfIJ(e# zJrN^`T+I;SCM0=6kR~8}hh5eUU%OG>Pg>$@I?@ zMqAS&G(rs(@U!}r zp2$KwQPyy_GC1y@^IiGE%eO1C@g~q1iJVh~C=I1V5TvPnfXqA?Tgm0cfzy=z+*$n& z7Sm^kHe!s^v+>D-pxy|NX06y`;6|GL=_va{$gDq)#S%F`i|g)vN?%{GKkJ!E>C??3 z~>r_NkK~a||XzB5cOpT_-Xb2PHs$h&LEms;p#LsyFW` z?V^?)pjbEI6v|ZYSG=o^62LbUHXbY=){0(w1RSl$T|Ds(dUd6}$(I~`5IsRf)vd$} z5BoYOYJBFky48!3XY*&Q%AXbx*6EcK%eF@ATSASI={YTNBL}9hNnp@nvR3xfIcul= zEYMlWit20)D-Yz|jaFOAHd^?F`S|pg4C5mDnh)&SUlS#ql?~rd+$FQnCCT?9j1whW zK^)gdHqO6ow!B0x3~%1Jb)J*(O@Vv4aZ~4e5D7!vrD6hXfaPS{5V)|?8Mq`L%sKB8 z>4o^BG`4E7f}3<|WlEzfmYOq_@cCySiov)=0(P8Z0Ot{^ z0^$aG99w8}=#~N8x1gBfTjGTv?s#NFsfPh|MDARFaWQ^Am8s<8(h^FiB^|PskZ=V?o=$lFoVy(I1wK}5?yx5UN`%3WruR%l$ZAoP0& zzbAW(_p;tAdGNltUY}&BcC{EAJzJayfon7hhQyenO4hyxH3V)_dZ2 zPI||!jXj>15qRn?cXVj@f$d`%@T1Vxpn)SiY-sEE31GVOpn2r!3T9;T2qgDJVhsgN zzwFZ)tuv}i>(>8$@tgU(qiJehrzS9p`vh|9-5ndgEO);sDhsJT>T~X`fYurt&3Vyn z_G`vXVEgnG+;!@1QK7Ve&`uJaM2?LSb51j|QNKIf-E{TmTXHh~d!g(5vSPxaGz(#?(ddI>9$9}a>2qZ`Rk_5~ z^!$3nx^0E#>L4-3y1Kys6-X+$K>ny#Y;zkAK5p4YRTHwM_!i@r`*gG!ko=Ri<7-GK? zwInDGv}Lj*Yxb-`ILUa#Xv$Y^5e>hQ=QkRXrT6=^251p%QL+b66q$R+!ISBL80n>j zS{+3;AUl>qm%TzzNc_(EJGy#I*j5CQF1sFyY(cTq&A8SAY5=c_vpcJnW%Edk3x8B? zN30!0ZL2Gb%QnUQ(7k3{TK}ce3y%f>R&ThEipz9H2tLK5lbnl8bwi6j&Z!YmPt(1* z3^Fsh=TMmfQzP7~m+E*bFsge4zP7);2UWo{lkOAtHbZ0sNv+VU^Yf$9m|Savrk0&% z!U2C!G2rG2wvi28)2u~aRFv5>h+bxua&h5w4z(>>r#LAZ8?(tpXn=H9d9YG76;Vxg z((AO^#~EdmBd7K>$#;m%Qij3=!TYCN{faZ&O3MwXmJofe1L+h>52pLhoSe)#WTW$6v*q2n zZu>_$OvaN{4lZRy6lEm#T4_Gptr12l8QxcW%XaQ&cH7(_MP@&fU(jS zi!sN@0`f))xh>7J!IsFkA2GHj+Rj=6nk}VT4*H0}b0GxoauIEJS(MY_raCfRWKB#W z=(FXZ)xHvWR|xKWC9!oz{H+9UCYMA3mX(<3pOfQyFc6oP6BMkxaFDS|R1LQq_B5E? zFSE^1zV5Mn27f4rJxxJ|tY4{V#g!nt5ypEb_8(;p4FPhmvr2MF{KJODh}_cwbJUeR z5+PY8m@|3=2AfX+r%(;&J=E}iFUz8(o3RA1OkcUwki#nv&v@;)WWTn_CiAh_wm+^p zx9s@n|0#5-3z>Apv(-f^ zjzEvav1?5DAawS&TPy)ehCZIj>m|J@I}+1P1L+dNY|u#}7K&$@^+q&^h|zK|b`qTeX3?SMqP8BS7x11`W&& zQ$mAWgb*1DCYx8cF1gX=;X-h4C%A1_e^30p1=nyvCdPRqc8^FB^p9z(JB=FnGYTzY zaKH+D@!~C3vsB;Ha=41(KBpcv^QI7osWmaJjxL=+zvdQcm{>sQOeOa>>)~B@g!@7B zeI(^+kYUN_x<39IlE!hA`f_^eRTOx06c9RU>YfV`k+q=aZK=GdUs#U;V;<2|m>VMB z&ayPR1$*FI5}HC!{C@T6cQM$n;|yat1`;WPRh6PTp6{>%O_L~w0!V`d=W?u@-#l~< zJ%`v% zufkM7h9Zy^F&mY{##xm6SYNwVEqW-f*rUSbX}hNm@(t!knXpQ#Q!;%#?van@S5H?y zgvX9EhS5%h;mC*=U%9G4<=3g2HZm=`jBsg0lXiU$gYeVcC`v*LmX)HouwZ!L+kq`w z>|AAD9I}&>h}4womc83n7a7!3-E6f}+QiE2pY6^(C1lO@Ha10^;EuF_E{0xngJ;1m zOD}}PxvwW2rWY8mfH%?hZ7k=IJ=^OI{T_AR-m7R2Bn+}0PB-<*^_O>Od#r9`iubvz z_+OjiEo4#6Ceq1Hv)-c1oAJY2hE{;~T3dKE!(8R)iHk~?8SH{jZBz*~K&FwPZgI15 zBF?nPyvB7hW%9S1-Rjdfc~@tVM;+h^Oyra@rTe%Ae=16D&9D5(BV;a#qTyh(*H*M& z?)mTJJ+gY}EWgc1sUpgsf6Jtc6FCQSd zYYL=rIhUcYQIES zBg}T?O<5h+T7QVQwwg3nF{_ipfKcFgWDtt$BDkmis3 zeeqz#B8W*I*(lWfoyPq4YX~j9exlwZZFCm_6CY_P!$Ucmu5Za+DAu8R)OWpGxS zQKkAy)mxgxx$zSA*vu0=<7ROW>n^x~@Z$J!1xY8Gt4^K;BA0*Q!uEwy&zQ&D?t-EO^+hP#p4r9x`Htrj1{k$T8_X|2#- z@;3doW;*5cWvDg&w>;WS-X(tcEu2g{?_S%dsMx?%6o4wb+TI zyQ%|i(yY33r~~aaECu=#gXpvl5@!?D5FLmVH@QiHA^xjBnv+ydF3Ft{rE$9!<&l@Q zR_p?&(nNbGZ^n?sbjt32$Gu}CoPI(x)^UY#5Z*#C`)@QpxnQ@;kDduRmY(@#8q+_1 zKO#EKt@N*s^=bVhi%T%ujorMBOtV0`HhRsQf+KP3iIycOXH`&e@k-098dHZm>Tlc3 z@tK4P*7E5qdBh!Z!gU$`dq+Rr)V=tK#cbZ)cbzelCtwxeVMaO7HUz_~sn4`|oqD$KR*53!u?s#_NSNOlY?aU3ERrFnd-K^- z4F~hsY$Qj%mGJ5e|ixtrke*34b#H_fqNQ8UU z7m3UZuF!AyL!HyAe56B0kNjk+bZfbqSi0T%3d(_hk*)cyBp$z;aq2@;&A4!h*_E1; zs&=ccOQKgcPpJw?@uKzGh~+grou74}kT#MIlX8vhpQ$B4Ubn6+p&@rqGiyz%DJ+Udl-)$$JYC)Brup*Sc@*&L-bw3e7jKeb z3$dCel<8vvPu8s0=nHPF@GJ$f%Wbk-e#iYX{o7$xCc|43cK%|4RKxyJ*&?LKFz;TL z-zDVE{S1;M7ZLczEc)6@m0EQlNn--mGsA4Yb=(1&-_@nZouxqCYuDp{YSP>8dHe|V zJAw%o3)tFILOlpps7L&4B83LXV(K4b@JCsvUL8t(-Jo?qcGxO?)GHoyNoO>?$3Y!6 z9QvA|OB>GqyClNG8%hLYN?rfuIMG_}=IaMt;p+lnXHEFrmRwCszo<~f$Vnb2A#ABI zTfMDfFSKv(%qu=_Xkvm_Ek?V{YzAUc9O|X0iMUNe70@#Dc>7QD)3~39Ny5VPMCit$ z<5I*UBV!gV$^(<@jbG@bJxLk^zPIOm+tQ|`{gpRmpq%*Ol46F~`i{3!caO2q;8(TU zps#XPPn0fY>$rk3shNmWuDtbqf#^@go9Rdpg}90H&7TPOY6$M)oMZ+MzMpj)BX?z~ z=?FeF>v>D?09bXY=-U2o!rIhe6y{*ohIiDMl1D;#XPkffZ+in&){B zZt~hpaO;eD6IC^0jQR{Y0l3w-hu1Wp-C`@Pi3c7&ghDWR0 zhI127`vvouCP!IJ*YfR}ZTfCo_dmfp#IG57j33xfXRnH_pNCn342$wu3V$KXpDjC< zDJ(_?qC6SDYdeEq11|A&iR84Nxb zC=;u8O4NxV{|rh4-bh|iI#vn@4%`O!b1mOkT$Vn0K*6?DtCTEH&!`l3 z!R_>xeX2MPRc5*}Ek`K##^c8KS{)LeC>&y&|D>h}chJ?rh?O>k40)9}Cu>9=>0FG% zyxDY6yw=`_|81s6rn8HQ0@C;+d zWX%x5K_pI&dSDJW8%o@gvt%XIl%utUS$a@PtO?E3%yfkUR1D?p=uF7A3FiW3VS5ex zg6PK&Xa3FSrSMTkWQM5|yc&HXm+!kdOPe_ft}O}EQ_!4$Ni=WAkt8cYar2wLe@ZNA zx-!JdpH`+dll7VHI%dxAbqv2DE#=EAdi`y`%5=-~U_E$Y)g&}Qh@o1PnViWk$chJj zUrMjnK()y(+Qy1WEA$W{*PZYyIY~09?#_ldwXy8_;kN4{`pBe5Q;?2*F|_NsvA4ma zH-484b16yK_&xV9WDw!S-WOc{$)MrlMg1oe{sI_tL<96NL%uHjMt@VoC7}LM>+el8xKWVX&&cva-f!{dJNDe|V?!;F6Mj$J!S*==TCpYcqs__|wCU8>Ht-`Umth-;p0K ze8A7i0|AUeP?~^sWH(n1tZ{0-juYf6x%Sr-JkB-_?c)#0Wkq%1n?Qyg^Q{+h_OfRm zisASk4>sp(XfxF~?f$o2T*oP(fcase1E@JO{F@tdTHKoF&(PPP< zKthwaV%Sf_a%}|oa_3mJ`;^a}8{-Qz>krC_OzZu?yE6CPF+8bQ^Wy>XR|xy0{~K#ZL$jqOF3 z^}d8o6#_g@k2@3jT?`-ek*TpU#LI%BW3gjm8y6(>JZLn|RE9tHE5&kBJcx*+<^GA4f+Lk z6T_z9TH3b2wfn+0>YvMsK@5-hGrMr$CI}4CZ3G0lH z>g8tF`2{u*`*nmjC6pxUk1N|BfTvlT1t0&z_kc~)6Ff500tP=D2+P+buk$1RSq~XT zQxU$4)4p`v8wtLbEAHI|iT7&BlmqCO$$op0JLTyM&aMhE3eIDI)F(~KFIxzHA?OoE zFFjTL3wQ;Ei_23hHCHQichGi8Css>9aX;w=9;YaT_?D`6tgn|C55}wGVOfOZtV3m>Z($rVhNzub3yaYJ=s5YJE_f+6+OO)q-}PE=~89C+PE+^#EA zi=odTYb(GK69at!`)4NT-;qPNk&V}8$^IalwqVpR(LFv3&f#x_^D*juV^-N&n0~Zh z62BmLl?eR_XGD`qq5_EsA>v-+_goi)4u1SxZqqk=Z(>Q)Jz{O>03AN!eNv!5|Ck`b zlYMb%WmWwVOnXX%|_KpZ6#j~OE@urQJ5&^X6|r`7@s zUk7$~eBgGQ??-4mHd59Co+=E1{#dRgr4w^$2tb$~k~_Hz-2Pmk>kVncMb5*N1qhme z__f-nB!RCuXXvgzrC1Tb6A^&bGvZ3(@I3f1|WY335QpW$@)9`^=HfG_;$-ArewFJ87v^&4>%Er*Q~jT zQ1Z?7;>S3F+0wF`hZj6a5(rRYAZ|$vo}^#zg(KbUM}lYqTU?nQVpk}&4=pG>w6-8C z3JGdFxb0V)xYa8xS91XQH9miiw1Ud_$St_MSupJOBH9Xk@#jm$^tiN3VD?`BBK{mR z*C+Y5kdSEHn&D0=|Wk4n^0-#TEAbX;S_ZQ4R%7^5OOBn z#+?dca84MkjGrDR!YBsI;Xz_aX5OBCk_(xTyx~mpLP>V71vBH!e~T=#W%UgPMImy( zUC)RlxmM46EG%!xKZrDOz$U8Q073bOiukCKJ}t(U!vdOo@pgbPiU%0|F%Fq9a>SKKvNX-{;4_H$9kXFK1%EzEU&gM}UenS2&#K^f^WW(@{yl{7)VP+nbAS>bl( z(OZ5-1`t5bKYM;)cl=L*6(+I#rCRz zav$1ZxU61i_%CxnDbZj5c0m7a8#It z1>UHNrV66=uI@9x7p1aP1#U{jnBoBHDKiL^HCd}eyGhqSKnkdTE!z3U7dgltt9|LK zU{K}rv^@YHo7BD|dbxF=057yH8xk9sunMjcdZT+P8-c{kwCSpx@)%pvu-+tIe3A17 z)HLFxEohXv>A1rb@j3m1VS!AqwB1|3IJ~r zw67kvI!@iSTnwF@?;t?WCHE#H`16N? z$pw7y)X&$3{TKX(O!J?*qjhp~`mH!=^M@XO>x4=alFI4gl8#Ev)ytlbD}QEcBLWp_Q-@^unMRkwDl(I9bkb{n&`)6^Gs=viyPo z$&7iK=n#X-xB^lzp3Nlyrz1cbT8eTVA=4}8H>eR#M2%_ktR~)l93Z7-)jJj$YAA$B z6bg*q@;Q0rf%cz8c8+41#gY;T#(N|{k7=7MyTHqVGL4`;JlzBz#PyLC0;G0k?7bac zo1&HYD%3YulNmb7yrP|nvYBNnHD)=Q2k0n}2uz|VsxpoD@%Qrn7>>JB1 z&NoQ})O`tN6LTF-0l~wcUyd_-+|ZbGr<7vY94It{%2gvqu|%J2S!oaZ9o-IRD=*D_ z1fY3wG;h_9j={ccKiUxF;jxDRqn?p!ZJM;Z&)2}ijzJ(_%drF}rxO@ydKYWd%ht8* ztpkqnH8>FDWJ-W^XjNdU2(9;oH?Jc>Q#8M$L@PLbfO0y&OOCA~K~fQn)=8!s?*pRT zj6E!z?nKc-3flJF%JcO!Q}d%@Lcd?jFZ4S3{^=l|jV6wje>(`we;OO|*FU`>J6!9( z_(0&l#x}CGru)ZB{_iQE{*%Jg+{w(@@P8ou=ezkw)PE9Mn_K?2Gc&jPA2@LS4;)5j z1`bZyq{P&B)>~L9<8IQ&cHaMcVMrnSqiz0Ys65Zr*`p<&s`_nH@veSyrvH)JH1~3yF6B*^8|LKX32@2 z9gS)m5-CsK)eWUs+ zSnxK{Eq}Lln`ckDCjy6?J}tTChChvxI|KoARF#O#NAiZG&EtafkAxfu8!KHw7Dhlg z9X~H=QKY&t`$KjflMnG|T3ujq_@{z)MVEf}@~ov#`I-9<@vQP^*Po0rsg6O&0B{K5 zD3h#}lLTWaO( z<@h1A5~n)BCOtHBzb$9Hs?Q05M-C!u<0t}Nu=XJtFLXd8c`m>pulFkWb2TY(=-M~4 z73}b~sH?8(;+rJKJ?|Q9>Og{jgja*0IK*hK=_*lXnc_tQ&2rsDIU7FMOPqsFPiu~u zZ9u*zJrSC<;`zC0kbreadImvu7~K6GRI4?Y7CI~sjYzYSs^QVs%hF?Xml==!Z7vQu zEHhFL5(sm#dLmc{#lA^{drZFn4EnU!=|17cVSmi_eKdgjZF@f`h8-yIWA>$6&-DA*qffA`*5&7 z+co#K?QSN%f^exAF1IZc%M4vC@v0_q@H z)*6o{Dl!gARGvSp5HE~9&_VUcpuCRPi|{ac6_6yD*>J&wqmP7R7=2?Hr9Q47FW@6m z6aocBH82`i;Za;!RK9{|x>j8?2(e#2B*-o2d`DY0+)NuLszujhqLxazM>}9{=FQJ( zN-43F20bh{Pt0g(^AV-lXp4?5zeUmuRg|frut?O#>(B^#T>U(|TyL!ypHX`qXT5wL zlO^l)u7PQwO3apUS*~o*(g!-fOsJ`M3w*8k#>@PMZtq9qtp&@}^^J<f3p!}`ifqw|Uqlo2I(=H2gctEY+gPZaL4kTNdk`B#hJcta`NX(0o#F$!ho{-SPT zXPq@D+S#fNF97!N7CDpPEmb>@qTmPcA0IwAxu&Q0*F~p5{Ckk2=Bn~vd^pGduN$*4 za530Y({bEqMfN^X+mz6g4nfI0BifK%4YodQhy%!Ak;5^VtjE;4S9d@xN&MNSnq*~V zpw485t2RkMcjAk==6O*+BVOt(Y=!2=NYttsv=TD(8BK^28-g;gXm2A?zD={B9nM?a zvnN!7QGP8y{I-dlV)JE?gL{}|#KC6m%2ybXIkuY z7)E>L)=P66ynv7%WjmnI*7jp+qTe;W&*65Nw+B{B+^HFXGPIhWC7E^#gQ%@{;Fj2R z#gxq5m+f`b5WCEpULB<0Gu@I+uqM3rM^h-KE^0u(bu9&IyS2i<>UR=nu>;Z2CByrX ztmo3WYaTcGOi0?vjJ+BTc2hI4wDD)gXWv2`T0|%Wf+*PUAM!I)k=RSM@RgT~V_T?l zd^NZ2-i;(w?yWc|eKUi`8(n;3Q`eD6sY90wt-J$QeZYZ>@;=fJO9)b~uXt|RRQEC_ zQKaCOe256^=xEBIhvk2Tn9oFMb*70}QQX`dBb-TTu?rjM1n*Vsfk_c)^Ymd)x}R2Ty!r zV2y}tbBu{gWbn2=B1a}(*=u6-XVrNpC{4oUU%^D1{lp?cjB~#Ql`sQyi#bwiu@5L; zPOm!{Fo)H5u$-xGJ1xP2E%;2}a(vrsga@c`{glp|l@EdxROz?nc}R$Z`iwuJ)wSYNo~cwB`oy=2+~mMVT}%H;ToklTV4RLMmz2%=Lr zj1btv-sbhZd=@XpMGg`wD5(>{%BYYVb&F$LRLGCG1KGb`Kej^uY{a}_O|9U5s(vh* zxrAxe?$18^PUW_wj{07++KqTVd1mpM(++78 zbz&U2WcWtz<+PzB~$f0}4&2S!9`+zl&m?Dl&)&0*acpot~ZA zW~JMVXQKH6iA)6RPM7Nr&&lV>X5*IU$AE7RC#XIG$fh_E^#$`_5ANW3wCn4@h)Z|v z3iunRXLH$aVUH|Xm{J zFETP6)mj9iDl^Vjk~fHJ*-_|$Lncjebsv)lrJ%N9&Pp083#TEPZkg2N@r161A}_&^ z5oT7Gb8y72B*%rN(=tkU6(k4^9S_&cW+`sr=u48n7z5oydl@zKAWBaW{0FF!5gG>n{JpD&Ns^=0VVD_fp@FCu>v~?6-mVGNRKK>Mk6U-X z-n^k`HK?wexaranQDMm?kHp+fKXg)r?F4viQWUgdU1Q;vW~t4IJ%3|UN?H4&zWz^p z^%=G`tq$ExTB*GM+x~_?EK*7oqJkA((tT&WpFA69fApU(Q7ifTrPWBCNMux_a2&^D z>xE8^UN6&fL8eVpQTBYJ7(lMoN#qnG5CcJVdSg!XKZNx*OqeOfwCEU$kOaqAg#Gc) z2Fb!1Qsz4vgx;bnvGzDd&GX@x!H|{q2nO12Wvw`Jv^d3kgMhz38a4Ap_xJ7PqjPk* zv;l%S?H`8fc$^b*gAWXYK^aE5rm!CRvPpwYs`k1Gte9d+Y^?xd?1?mq zM=ro;e|C&EePkJM|AZv1hh#;WDS_`Z3hKJ0p^4?f4i2^bx_2MEj0$Cz(%abjyIV(^ znYr3(m`vB5{qPh0jYgzZ7#%hQY~Ru9{)iU%!zgKa9g6KyiNVl0VS~TxTIK?2|AqW1 zud z3?l72-YS|RIMnOV-maGA#WL`PX5$)Hi6EW}yu+XXFN76+N7c4Tb*}4+$DNLJzhG8m zj`!cSQR^;N-G4!p=ID0cSe#`n*@)va&(8w|yA=1V1+m$Z%(MuWTB)>YlyBtEAqs00 z+Ek+^8lx@diq+~=YAPuE0xw8JZ19z%%F{h=X}dTV`X_1qWw9Icr%aDm|n;?16~kG>y;~eh-`$PXiXWcy}h7!fwacchlU4R_h8v< z@CG@rC{@~!5;-;oWi&%^8-UIY%4qK0a+3x=IGRV|K3UD`zpxWDT@Q5Gt_faufTISy z+j2Xdr`PrE{_bfrpV@LI5DW)y>|tje>E$cGCv<;hfC8hnfeGXcpyr%^I5+4v6b*+Y zDLU^>msmO=cB^3SWnx^4+YIO}&^Ua$BIE^1TTXXm=#HFgcW{u^xY3lIL044o)@brX zi9KXwrJx=`Sy;4v>qnn`FbNnO=f&Yu2MtVt)k*CllaO3szX)>|C5 zo@x3)TIoyuV6|Hvms)`|PfR5_BQGP=o>?r_YDW|#p`5--NWP(1cJ593gdo-K2kB^0 z@h7V#x!VRTz9Uvg4_G*|!C4d^|MH+aZ-s8TNK#kpnc1>=x<@^VF49K`iFXeg0nz3G7FH#pE&-mUBokPzm3=EaUy9YnKtB`(1_H0vHjDBGJNA1~3_SGrHzirQvCV zdoS{=M{VPSEUuuaA`uR2?NJt$F%mbcm&&Z!rR2FIchc(D2HIFeFVnOp4zw`?*RG3h zf@f(kQU@ z+C^)S=NJaCxufuTOL1 zw0(_FKx49+9R|_XJ&W_z;GW{1pTzD#wo!#-qY9@gd|*g_>OB1EO~8bGP-<&Qfzj7oTTH93 zueyYXd{g80OBf_S;n)#DiG}iUn3mhhh_=9g{nhJ~un)Z40`-_3uNmad%#bpe(d*OHq(Y1=_X z7N?Y|l-oEk9Kps7CZ!8uwH<0bBkqa)?sHhm+k)4J%-}RgAe=RBcHI&a(-B(FINa#S zS5nIB0+ZZx{;LawR_qgJ+tucx?uk}?pm4j8+UmPMJ7&!i+dr~sIeTl=|<1MlhGQ3W|+F46w?ymU) zfT$Qr&_U8g#BS>Yrq-StSA9_1UX%L{r1=`)1a9U_?X3!5(gD0m$o*&Cd*k}hOec3I zxye)d)!gKF_Z0y3xB_f##3j9ANrc4!`NVferxJ-%Np6|GzZ3~`ZN$Dsr}j@6jg3gi z^6(rvwx!x2vE+kYl!e4#3czoRD-hWB5H}-Du=_B%!=2qy9`;0H{!V1QQL^s6c>Q?b zXpIfOoLQMAfn}54)3~yFm?QM2-gj3cZcv25TOYUr8>|QNc0_Bf>n;;w{Mj{@VJuuY zmHouzVlUNp;_?|RWHw%?ex-?Bh@W2QJ&2E_aZhi);Rn6wMD^WOApIV@XWDZQOik=R zN*eiTvz{8yWV~XRTp*R^jHz5ye{5F%v(?8!dv=*R5%0tv#K%$FdwX&7`Jo2*Q-2Zq zFh)R&Ez7N-;J8}YC+lVp@>1dRd?hPAN?VgnRiAd#I_cg8sRmO{_@j@a;4x8@xkhY` znEbXT#*}#(mQcwppdm}5w9RxVGY8D2a`w5s1v|Rr@DgAh&m(3wLKAAf43TMK-w04+ zFlE^;raKCA>Jjq-qy4pF1mgQq?ZKe}k>6Xo2O(+0Gr42Qtx}nO1lGpH6UNEST(s3vvTjZF zcC{I=P@K)RSf50D*j%)+77wJBbHXmU)sztn>J*=Cr=mPWzFAwaXse0rz^Dm{%gva>;HdT@K3^`THV@lT@?O%rgrsRh!R^vc0rED znT(Z`00$dg8p)Iqca{LQO>`lCaU9k9ey8(=FrTfDc{vK;YWs@kqvvEf;#F@fAYfL= zw*QbZ-GksmP)!Qe?K=T{ydd}u!Bvw6wWckOzaV|r>iCU2fjL1}&AYTg>4*+kK)~lx z2Z2Ie^MDLdjw5v}lQcnhu>-i(G}>Zja*Q?o-GdwbNX^6Y*d;N*BLh1!7+#N z!#xe!zf@5mc;zJEEAW}19|S>X7*}iAKY%&R%2wyxe}R`LnE5Ds^`dc@v9C9f^{be7 zzOr<5l!iUzQroT1x^C*OFA2Pl&FOCi?8~kWu*0}vUm+l-i4)oa5(=~A@_SI84L@)& z`tX|+=L53NS2yYZqU;@;bc>>F&9rgSwr$(CZQHg^+B#|5wr$(Ct8)h0o{(#jTqH`Nk4vARJ}2DvUAd@jm?r85U`P(09$N-GQHWRH1L{ zKF+zYGf;OkZdk7YJ_g4kpva7znZG^)?zPE_;r@7sw`A{WelOr09fOyJi6ELf`_ilc zZh`l2RZ{nP@N||4)?%>if}}2{I)lBaL*4?AX8kjsiQ}ru#5NUxHTyFc26j{r8WTZ; z*8lJ~MA$KakB|PHz8~V+h#XW|-Cfg~K@ZHCw(6C~<4{?oT{Iyt#f#coa zVwyfV^G;%j-8H6K;@F|CztX^*PU|F{$yM8d?j zma3{VEq1p*gv(ezY8NU0RV)s<${;jX^ z2c_W_zKPh;f0_rtdD{7^zvOeWoQ*2Z=y{W)V8Om47 z0Wpd!qzo`p$t;mq4k*6m(jRfjpD}#>qZcp(+hB=FSu9(UX_Ajs0?`7KykY+B%R6OX zk1f_OoT?tdA6L5$F+LY5uX@hiM|avuqNl?q&xgB~6#;M1SCduyOi=w&L{N#WnzugJ zfgwxWTZ*xtFM_*LmNym~<~g4nvwuvJybUJHPx>viIB)~?ZE7EzpD?>lHodZpTvOK*_N5!X}50#e8<8z@Stl4h=DSXwDz{4E(*cH zba9AvSuzdj)73U?I=ckfWKmQ5ty4pd;_J|l0uEVtChi%2W7D**fTI#nbKj%Sn%s2F z>X)4O<_`>xnP>cA7_fWz4wS<*W1X>Oy0|(v)LG)Iu@8nztYt^S98MF4UZ>B|ndeW) z02_|ReUjI8P`6GycHN!F$p>5x{T?XAHL_#j)VF?^t-k4kYhAmmr=~LK(lg zCuVd~DN{lm;Z%e9itEv?YMTzQUjDT_T@uUPb*`3>eor<|*>2)gK)Qw}$(Z-_rOG!_S(t)uq`yuz?)*A=$ltbzh!9fZ2=ebic&Hn-79A0d z{=dDc@r$$b#l^YH?Zm0ZSEeluZ59`J`;qWIF2mqrX2PbXx|A z*IQmQZ{1GaUe^-e-zP160F#Dvp??OR5`F=op{1V)45=Rnq&$TSd9o>o#*-AKM_=qCSry z==mD@TZ-udM#H|CIIomhmw*N{uv+H8IGK|zY$bG_TLra;?giTit$j>})PawLWpqkl zfgN!t=nsx#rY6l1YpJLh&GeY^<}2V$6k@=ED259v#D1iqqhOD*z)(nD!{3H&tB_@X zB3=vr9l=eYB7nJq{%%>3B5-1>RJIAVtmg&`yD_ibSga@7za^i$rxR*iWqymc(M-fj zp{Inp>rHP-HHj3H&R%V(DtXU40AHpb=O3AHMq5T3luaSYVoTW?;z41n0>r2|PZB!BM9c%aGGnii=Y?zbcfo|#24gwpTM_l7 zJP@9N2DTn**#!LW(sCQcBTid$-ma1LyiWNTaoGZxm^>-bjdCG}g+ti*vvsT~;9$Iv zZXfD3BRLAKYh-(R6IO~_>Zu_taT(tu>$}fn|aT_+Y$eGg#~dWad$Uos-Li!Ng+Vdi82lD zIpm1w&)1BCP3_I>_GttYOO1Ff13n8+{Qq^k{(ZUlXZ^ zZ38*r?MqEk6(&UJD-x1+HciW43>*8lNfmhF)`SU173w#OYoMryOCk2B$7R!p9+D9SF!%=>iLcY5Zd-{$eo#Yfm(h}Bb?rD}JMeE&9yb}kQ2 zydU6yjMFumRal9??%&w&Nd14d*ieA~>p0E$|NEWyA5(OZs)pPF{U6_%nlv)ya!SxE zBMQo}KbkZ^G>9D^<_Qvpd)W14H0Ec1J9SRX5>gbJ6=hp@+B@21YJYb{1|bBp-|Gqs zy`Pod0!0Xu@rVTzC-=|wO|!`s2v7zeC)C*cs|F9TwP{fkk&XWtYmcEpQp z9kZYasZM1^jNpfN9|1`M@fQtE`0Egu0F_jEzPpsG(kI z6S$GRnVur4U|OVCcK5IL=ZNa|T+>kC!TcxApSSNW{Z_ ziw978QHM&a86e8P(y~H4)9d+pENM++x_PCiK-!NWF9TTd%Ci?=erybYw5$IZK8o8x z@inlm**{a$U8k0^klDtClC#RkX!of;#gfNg3VOy%$jVp0 zy%IY-^};$#_*BcU=&m&>Y{)qjeP9wPP@ezRSou@@p=?cD%W~fesPtOvW6N5Pb!MqV zC=B3Mvil6FMJ_j%JRaY8a!`v95k2clshbS0*V!Kt_sb4$AD@^Eb>$6PsP6sXx;)~` zu-nnAz3p5NlW1&Rs;czc$p!MkzILWkLJ+=oD6Qgb(c;(2%Zc(Ha5IVA|k;%o< zbdB!A_u+;r%>q@4UO#kfV5^_%CJ#onD9SIE>8LtzoCsZSGq9SSicw%u$TVhS-yj;U zd!#G_79>jMWC{aVi!7LLfEGM5>qHV-xsx22{qez>g;(ftdFMf8DLF8WVM9T*d5^=Y zQ!dwonnPP(q*Vs{Xkxa0HfNgT6Iw=#4*TNEwPOL8P_W^k%$CCsF<%r77H?T0>PbSi2q=5h#O27o`1gFvH3t}7fVsfPs2PZMh zNC8V^G+Q({=TX?KGfQMR5AmFIvqcUQN!5QG9bj!eWq#y1&A8^gO^exi!}bz-4n$)2 z_v;fYuNkam@l+)fSkm+Lm6QUo%61=CzkP z_>XkDkrD7MDsEW~K_tVXgC2d(8ZWM#8E$}X&FrD3Z*G5>j!V-BUD6(KyFY=np8D*xvF>|^(kRlF!_uQ zF^5Q`U23pFlY{IrhHxKxEq5Qmm{GXL-waq!J{iIpC|S zQjOD9)YQ<`pxrZu03l1x)a*KWs!6#MF@y zT}-IsI;-P4I+Oh77zD?{$T&tpl^KCOGJwA_f%tm0{2Gyj#1BPT>6 zr64`PY8Xb(&~ouBTT2tqvkFuv6e?CJ)+e7uKXR9&HaRMKCf5|IYQe0!N=c~ElY@{A zd8!`*eO#YPPmjlQI2*KJ7_qraYXL9kvqPT(u7X(#oaSM4Rd^S7!4TR4$2x zFIg#~MC#DAMDuX3?0Kz+Sp(`-SFP2^``FX16juXG`v=o3*j%v$8ipI;(@b0Y%vm~C z(Ya0D&t3OT>1+*4T6gmtZ|cUej%xa8y`$v&S?hPA)?KzXh_oto8>HC5#(}e&E_%1e ze!Z#De9>_-#5|!x2+GF3B!4ZOX2DPz1dp|lC+pK_RbuV3Hj>lwV4W~QGHOvA%lb)R zEkXq^;0)(f;g%z!C|itRYoLxgwa4iMKBi2_%#&|4vT+eX7i#LtKLRbK%qZ)rQE^6D z23U~glyqtL>r#?Tyq7^V;}-;v@CBU&LzpJnI9Dhfnq0Z^5qG-S*ma{qg#vh<4i$et z?{-2)r&96nZJ?0o<983N(KgLP*f6^gd+pR-gOQARi|om+_d5|0J9hnD_MFz;6OBge zv!+gL1&3~tF;nGVXT!Wut_MmuEL_uEp^e`CAUXi|yoC3@k@XN7;o&L0QQ;kE5894N zg#wQb>+eH(hJ6QQ{O3v?YWpJAut9M9jC8pr(Q`~R_8hqT92iV-7+nY#k46%qa)fv* z*cL03`%A_jPf%ju{x$dWatEDsx~Et%PIXP_x3OZnmh?X$202A9r^R*W-sZ=73b~l3 z+AvGGdP?j?x~J3kMX;MGUa0Ao>ruw^CM zB5arvY*mdLRwrq*b}``kh_5EgR_6>+cLUYZ0-|Qcn2%k=zrjPn(IXR9^c*3dtEyvWG+$kmY3j zV1x3D>~U&ctd~lko4UHvRuh*Q%XZLx>mo4>xdQNd-)Xpjsnh%me+v(VH_oF_llIO> z@rnI2X|{pz>@xvzL0MGYDU0ftcUx1Rh7~m!{HO-ivs?&n^0b5ETcBpN&w{thM?CvY zwxOYcj}H&Me?f_NH&shB`gcOBN{k{`#AMR9r*ADg@QlQ(c(!wTnu!3ruIf3+1rE#A zoVAYiS>>L5Jn=*%J|-)Jkd-bn!p_X71V|)gzY%Gmcx||^eCzbA9yp%d%uj1YM7dBL zAu$%(q#6-bPo2LcbYVJ?I6*Ka0wsBt{TO4xG_HA)WrhAZGr4Rr`NO<3AJP$A1Tp-r zX&1S|hgo9In4u2R*1hVOasE^v587=tE0e^65^0`!*+B!}YIaE@!j!x{iq?z|mL&}b zdr?Vbir&SLu??;`ku%!i+_oU?Rm1-9VbiYvtbK_ z`W%|PT{hEa)AufW^;z68adw%iJ=<2F4$=W;zi_vD!xK2~zBvBXB*7?If3wsa$;LDm zA!>}I49ph&Jw?lA-NDr@aNpQt*Yr*UOT6R5AAdfb5k1V{*n#Dk8n)Z?98dP_F~ z<^|HF)GaLE2ib+PSMy|HmX&GLPw@XnY3Ko_!jlHJ9()zVZFInVf1$?L zC@P!#?yV(l;A&THl~6QMi56ZrEv|0qE1xHi=)yU^VdHBt%Z%MdLF~P4oD`i&gLIeB+(h`wtZT!H?cqwsZ^(L=(8iDxk?8oiL(sYyDMD8u zPZ%zm@a_h(K1XUTJIyG7CLDYxH*dB1(%J!!uzOfsj@cZHx~^`2@xeO}S*WvV?i>Qk zRW3E-SSbG81_p`bRcSofk6ofz-j zMKeH1`%{}u{03#z+?6`=MKj1j>(l57>XvM;uq~b0bRvEFkL=zY4|mSM6_nqQh4fRZ zEM6~+-`Npx+8G@O@lRGC3UFEuFZoOCfDv%%truABu8NN$$xqf)tG`N=D=E>xsbBhB z!?=9k4^6)ywHQkEF-~IUgFWnw;0vk|WC4P*l#Vhy6J@+_QO|z)g1YNj?Q-q8>F;~B zf$`X(21bpcatOu>blFn9Arm;UR<*shuqDus19O)WZC3&86u|*w*Q7+j>-K`@m<1;Tq4QX+&J2|~3ag5-@RYpC{iTj-HvZTD3D1nq_&=EbL( z!ooe~x$MC^p!MP0amvCfr@!bA1@rN+1JQ&%7>#C{ma`eD-TK!4$&>1LQ_gTUV6eNb zUL?$0OZ?j~SZ&UUCz4Y%x0^XYn3CfAns&eix(3fq-%~3LTWuzmMz@SLrj~mnN{c?0 zq50xGC3pi>l~{KY$NgcH(c3CQY23^!agNJ~)~QkWerpM>&tv+NuN(RZumks{#RV3B z&*am?P1!S(yC;BN8Wqr>LnYpJzR~Su{8?}3JY7iE+kuy=yJA72m+E13aG7dEvHKUy zzMNqc7dzO^=2-SJU}yUJ-P0qE-U*Hq=}8m(?iF!0;TcLB(>>QwTu%SSw8PEc1gEBi zmbzGAE_EH6%EK&cQMQKgOF^89W>7HB*$CXmJ>9g^lQ~G|eV7(AgFT+hKKQmT1i@E~ z{#VfUGJuaqlS&8VYh6(a-$*;Ff`1|Kci@{72G?YFIM+vvEho2On-8}VvAeOYsbOyE zmSmkLueMHIx!A77nNET07>9?qr>KV)3Ne+Q3Qn@s92|)QOdK8ca&o&3-{?CoQ(q^S z0J^ptUk;sW2qP~a&-OPnTELq>QrBN;HAxvgy2);+c#YCiTp>9)>6aXgH=`Jz2N<6d z+q*%GFB6Szeg|y}uUF-tooo+UjwQ!TL(8bKjXj&5j263U=j5F^1=oPmVsv7+LYGM` z_2GE?UL2Dxj#yS-waX`9;0E)_8+UrIb~d+HuXx8qbsdmD6;B*lItN5mGgP&>C+1O~Nw${C z)|xgKADtW{7v6o7NKs!~2xMU?5@;wAs$x1lktRB_Br@LIe$h32s)M)^RSuSN;dry@ z&kkUlGx>E~2fthva`49z4VD>4T`$~=TcEIZv^6X}Lzd3TfNS<&4Em+fOdEX79%N^B z3f@Oz^PHScW10$~I%JVME88vV}|4ic|W3+Ky+ z?5ps+yp#(r$HdDcX)2)J5%HJldSAn45Hx)VuRzXX_?y?*g6bJJL{e1AMq;z0m>#AZ z*@`#SRf?2$jIf(R&cq3I!Sq41C)~yTwd=2S+;i%Ax5j_XIKv>F#Wr`aw$);`oo4^B zDHcoUmw)n_h5PSR0_Wqh4etb3ZoBVjy=41n{iFjMbZ3M)^lIdVBf5JA_Z}G5Jlx4# zv1Ms}q?L4#uw8DX4pN;zXW5qx!{ia;StNG36TS`4KvNbjxgO{gV(SJ2oxq=afFK#~ z7xpqQs@fi3sxIh~nH{+hd2lA>#aLBD3#;gmpH_Gv!5XRK0W}0FH<$Xsh_P70KrTJ* z%s8eWiRD)UgWxA;EZ!E*W8m~JNh#s3nHa(DY>D_qgtiliO~x$WN>WHIPWWYA{?X2C z{$^bA=Ux8s#(2KPEN`YrsXh{nyn187SyW0+yL)j~ZCU2)f5p6tGbIN-e>ZvC$p5oQ zD53dZMZ*87G4h|ZjsH*yhcK;_h}iDAdIVF;iH(+FLa7{8)`(lEsZpv|VL`Ql++6Su zG1gSmFl2~f)2y%jdahH3ADUr1TuwAU(VwKYs(dZn9C5cE+VtZk2ih7V4Ka)Fbq}G_ zgXaRRs2bWn40UfVN14^u8MB8p$JnEkO+`!xkUq87SFWDgj`_(M_aJ9*TQwT05sSi7 z>5?Ze*KXgF|9YlCLwm6|t4>%L3^kpOi~T{f)V;Fq!bAozsWm{_#-%f9%CV`t){Q~g z-zXauL5-yLT#pf-q=DZtQRVx!7)G>n`dhB-nI#KDT;0iDU&r}8Ndf0A!nG8rw+!8p2I7B1mhqM5#{vG|t&p2#v?(zwMC*7pBLIz|8p*|J922(?_?(4Kz= z$~BE*!<12l5`o+3i~<0VY1hbw;G7Gf-140(ShHB98kU{reqcn-3mXnc>Q$K-M{72~ zxGdI3=ukLo+YzTrOYEjulx}4lhybA>VBuy>Eubu%<&OtjfC0c`BO!`IPRV5 zsu)2%^nJbly#6MXND@NrW`NAv!l$Utc#$|zl)THkkAgM8FODYKp6YOZs`GKn8FMuR z#HVB=UAj#Lv-_KJ=zzqyDJL&qBDi{D-u|^6s>2tz@hpnxJ&j-@224vCTviTmX#;M_ zW|L%J;!)T1=B<9j;yjYY<-L=z0h*x!-#kKtE)&`dycer;^x)nE4XyR@U|CtX1ALV8 z_^Jlm+Zq}3t;ApEvM%VKqMV4~8;yU@i7Uc=8KkA~vnsO5@|HdjqV63G)GKFms&_2t zbW9%e3aU8vh96|rwu$$@zvzRnTp6`DQY6vsi&f)ih3-7clh12?#*9JdgA2cl6)pw$ zxdo$T^{PcPM2{)PA0X~p2p(0Y} zp#E6KJ!P|5LM-)6jam1S>-gQ&t?J?}T^Yi8T=o16@XOq^b)&s2VuTm@@mC@LUX|^F zU)cM-j>;(u$tyu|kdooJuoCLn2X^vLv`B|7!Qef51cS+rQz77%Il18303`jukq8K{ zp2I|=KrZGhWDTQrJOL4sr+TJL;_k%`N!;4kz^xw`AcNL}f#lkO>Z8sp6da1Axpb-m z-l_6qV2xdK=FHcvYSEKQiBSQgT>QnfS*Xpk7!s=g_Km`%aA`+wpBpt_8>gGA;qr}v znrbq6-e{qx`Cb(_#i@SVtG@*_04&W82v^pbKtOsA!TcwYyah2ydOXj7nx^ZX_X*qQ`P;)##GBcAgG3(4swW zQuj31S*^}V0163joTPAQT+!CG05dspBwo|9P|D__z5Ym(ImP2?Km1dZku6t1>3vmC zbuS_m{TQVP;vGT^-rXHQTN%TtS4>{t(-ru{8r`NuTCjS|9GzSc zMI3!R1+S>jKHOy) zk#=5H*;8JrRTBzo8b=!SY_LIc%73F=;Qjx#meLGptVi~lDQk*@loq&dF#9OVN_*tT(SuJaoboy;B3lH2?05TX? zK43tdu7ks{u9hdMxtcSGPxe0r8dX+uUq+D?Lu$`^X_p#@U`Pp-vMdp%06AVkL=?KhbI4?O%4FslblfoL;Qa2Y$ZF=mNJ^dje zSSwy_W(>316p*=I$3w#-H^t+sLG81bX*!zlGXfx<)(GsdWUl~ zp+Cb;)WsCPO&=WKW*FBri(4ZeTsP@{-?{p|F4tuzt2&X2DHBNQ8F)C8EA^Ffl$al^6_!_e-ffVgnEhZ?*+)xGmQ0d9ZUnmW8armMHC_Bo#s&$@=B>qpH;ha{61CEy_GRXrho#dfiq~ZJgo%@* zL@C`wr!FYj_Dj5d@@dvK=CZbw2M!}!OnV1Oxe2z{kw8<;xicjKhpEFv)u#XjkKUiJ zOvOk$z=<~}3c}4zK^NKp&Ah}I0pZfeIX#|DERSuB=g$)m7Np*kt>p=17SFFqDe;Rb zz}iM>hO&o@&WmTp79)(BCccwWIuEix7?mt4f}oJ9sjsM%tbdg6eiXKWtl&-X&N&zX0fJ<|>(x5m+vf+$LS|$XGK0PK9iKl&~4zclVb&gN%=s#D?rIGDJ zw9ACfj4?uF2RvgS!BQKCyKoy6#S3u7k<(zI0uGY=3WDhISs{15>;WwOCo{;8olL0- zWh1#(7Jv)H;mh0T=bP`-(~ap8UKBE2oP8Lm*%%r@uJbOXadVAI3j;?XHL?op8~-!?IE@zS=JVv&N3U#PkA;jR+d`p z%}XrIEiCw$YTp6$P3y42y6r*N^JlWfy%c2|%0SjzWzy zQ3OPwf)9d*!(K4$snL`J77>^`l%?VA(0Gc+jr8amxRG{Y^#%28E#7(AnJa)6b zeM3I?uCuvli&{Oi9&@=ukBEz?0_8AdoRiJQs5ykWX*qdB&1}NkawugTSNm0SqP}PYf%KDsqv`(st;N#iJCJ4gb2sw;4}u>gEcUU}Y}Y z*5Fnb|5zpt)nGodXi$&qC=Vws)nGlsYS2vUGn{;U(&N#Id(e93Lp;%Z!H4EQGSQ7gIW#ZWGaBG^)^hBj-5ea}9n=CfV;z(ao| zdqe;UmjYdnlQvoACt*#hW`1^YT=lVn;*ZwQQIw92UyK z*E~tp@Lo^gLCw&EjQ10bbYWyI!GEqHAJj0U*^gT?!F_ilr{=O~iyS)SgMFuaw+pr) zwU`qi`hzZmBl^MeRU`WY%sB9_OTLo3Gy6lJT_Eiw2lPa|I|uS%s9J{NEnoL!3MfRa zQ8No-{qGvmja>WrwFQNVH4PH|WE%t8%WIY(ZH=m2)lHZLG27Zc+;~?) z7R*)hHH>>npD$JN#(aS0 z{F=XRq${G5uihiP5A8wG`dUJljG_Z~^zO1kEkoyPSt;07xb=lVWWzHdA3`jhI0DBv zD>XS<(5tAgqOkBdY-0g68i6a)369Gq3U!ro#cFF(7FlGWfK|dy2@iH;Dr&RbchCw( zduzGh(-7x^bT!b5$MZ4~MM48=$-ON+!$mhN@^;J(y;FC-@q*LAV$G+mkB0H!TGf_@ zu^B@fA5x>`CP%u+=uRm7WD3l#E}|#N9fhjAzvN9as0MMJ5Tg;>Ziq(wxQ4+!W5G$k zn}&i+3&EusNK9KLZJKXv%XqN_QGubLg@NBSa=fvZ;Zh~jEWdL+t9qG{uMnC!`_mS@ z#yZ-Sq(6Nd**|1>m32B5v;xP9#V9&_+IR}8jsD(M;sn~BCZ+^HC1q-rNs6%Z| zO&FfY!qlEA6>syoH<8lqWAfe+)~nMj$PRVtjQjz{C}p4eNDHPn)(&kSdU#Z6^fDQ} zi$quO4f89lMH(p_MH}rJRm|1(L_~+u)_qCT9=PWq=diK^7`Z?*o~B9phu%duq zE^ZRAX1iF?1b;yz`DwKlzB98eE2*pKf`W0@x^VxrV4RQXbn4)xvx$|R9DIAWvy$@G zu8zDConhaWwXWI*63y-}jXw)d1jb~BbRoH%j(lfzc7DCJdu_K%84$F2S+BXOu5D`I zBaT9`jbmX#?mpGoH=@kCQ!X8hZ)#?gEmHOR&tA0Gd?AZz)JOh^^{wAst>JG-w||kluc3JjU*(TIoAa z5}XwfnLwR_bRwuiHVzCQWdQJc4W_sH^>wxL@Vhrook*0J5yP9b)@-`u@PMkw0+WQ- zp^eOQG3TVbvTkt

    ($FjI+0g)>FE7wYo1Dfs3XW7Gk$=)PuYGgmDQGf+6v~HdheR*2D;5B#gG5>bm<*Uwqe|hR z(y-H64fX9Jlw;-|0XJ$!Zn`8b!`$6cj#4@Js=$5iD?CQxBq?D@#V$R%@7(iBWJnxx4kuXVOiE_%a});I@u zjx8H;tm-zUHV*Uwu9E_ViI{(~fRlSBNlTN#bMa3r1k}T^+KNKh02H9E)r^|A?IU>3dV1G&jl+82RxQUabkm^oc%<$uX?!|&>_q1n zJxVu`u}?V#cT@9$gPl^Tfc9B%K6i0jzuyAjls$u$c$kb^-8`b;Ax($&^xk+KLjF5^ zd4uMxAbo}X34Zo;vHus7!}CE75*XC44!HV&Omo+PFIGe}a(7}8`fxw}z&z&R;l}4- zf8G_k_WD)u{LXQXK>5uNd9`xr64$MBbZ_N!c=l}7a8#xxb%Z`q0S?l05$4Ol|HB}jV~cqo zT@uGM*l*ho<=_WvjVsFShEJ5HEVk8{(yT-^ZxM`${xo}K9}q?%6RQ*oxBrHCRoH@n zeWSqVBhEG}=1lYzY+J0iK=X*zp5@~Vo;sh!9d><;zcmnfrdyr=;X!hB-1LZl?E-(N z>X}y181`|h(4CGe#MGRsH}n9}`q$5wpJd;>+3)!7;!$f?HTwz)$>hkXFp@2}H6pTm_(NJ|~2QUNAiNco~0Nn_tg-Ta>OmCtlWFIvL02 zO>G-E_BBa=7s#d**O7?6^l`rHr_7!YgiKvI=ZOEYOs)sk_nRzSzJCz;EqTvm;GooyVVV$#lf%O$=qPYjM~cM}I(BcbPImM zK1x=whEC}g$1*`zzPY>};0W_otwZA7hp%_&wgG&Xw3RRrHmO6Sf>1USLVP4J`3_M1 zM`C2=%^8<|#t;oOUXfOKzf=HIBcKsMaMkvJuqccL)ldxnD&}khXF<;YhLDqp2>=A_To%~sbVlsZkgrSvRXl*Gn1}vs%y%&AktJS4ema| z>!uuj8W**i(xaD_mp6y>ZZng%WHdfce2u1Mg2GWzlxE9}sbWZJx$rZ!^O9b^-^oO_ zWFK>>tQFg_qHUVArEmBePF8G#D<3jALR&ivc=^iT#fb+w1A6&N-j2Tr3)b~K4?$lo zhjcZL=!1n-eJpkdZ&xaV66}@nbBlhoiZ0gQ7ei883GNXwBPa}}JCF@7NZ0UgUj3Wk zkDSbRvNTT*iCkvSO5bcKTk^EZ&QOLj@PO7v)ydKokxV_2*!aAHA{+%ZQZVTr)S@dY#%U%KfM-RYN+Vug9eP1Q_nf(+fj(G~XDWG6$?y@Di&5kscsx^bh zK3gwnUQ#~qCtA#%Xz>ooV(uIIh(0eLxxim1GK`%w;rA)W^e}eOj$HipIJgC=!t#<= zN&%*f3E<^94uHn(W=TF-%1_*!s@q^=R55FN1T`7}tBO@TFzvT_F8^)Ne>y7rCpar( zc=fWrGvF!@>U@IXowRJ-3oB2!zVnQkV-yyRTO{W{)Yh9?SRaMjsyUJ zO8K9qTqVW-x*72Q$w2*oIA8x=%BB5Z3j$bHP8+QE9e$wa85i;lA{$qa*O+{?5hiTi zPL)xW-Ml9F2nndTsRF`M{M&zVLL$`0-&!4UTjH1C00?hI%(i5UlF zSGj}<2o5G?THK^{!B5p_oqqYR^5@&z8}1w)_?NS*tnW_Z4L@!@DnjSjN*rzkGw2Ip zSqxpAISNCPLU*zt(8}L50GMD<=rKk_X0nX3VGM~Rru(Ix*c7rS;)%c2{=c;a?1#{Q zZ=!BZc#viwBG0&i0&^)LZl8sn2na=ucu+bPcg=|9piN~$I!QBOi+B{33-`Ij%ou%D z6Hi|FqofT-Rz{1TIYCRPml&f<8lW{wZvf4g$$6*{Q#_A{!m)o|xgB}ym|*g5)wAx)>SEDqN7IO64VTaXf4d3KywN1A1M_=t=^urF_SEwa# zhAl$w>C&%xsGg8Q{jS2{;U(hhbm^+G)wu_kghF5lj%*gCIk~$(=jXT3aytnlz)-k- z6;seGw1q(bsg;TAF}W+2B#;~FypG$)WU`*ql1OmzPd=EGIbo!+=+@2F{Y`@1*@?jB zZx61;9%ijL5OW+8ZYbANdL2>R#a2_Z_hl(3y@#F66=?m7Zzi2G5p|UQBCY4-AVWAD zJ6;%X7+JH-VeirS_%v!2e`0t5GbK!zLvvl2&=|G8J`Sqf*UNN;w%wcF9uTo@TMo5* zcNx{1EK1+?eLZ#gb$I?YlriW0{Jnqg>dIlGuy`Hi8w`o7!x^NQ6wfh%haP$K7g40$ zqiMXclza)Fk$M%sLA$c9AK2vNz?gLVjwZ76peD7sY;r_}V$>DXQUUR6bif;y5Ep$P z_Az#T=O@_q`$zIktVGt@EK$t#Ky`A5Y3BjyMGHUMl*JUoZ^^c$>Jc6R5Dqr*M9il3`u0Y_e*6A^@K*L%GQbloFR-7-sfJZ4B zJ?$HnXoBUJ{Bxz%;GwVEXXzp?V;>D|UWc{|SORUoV+Cd{D5j>W6>}s$J1xN?c%m}) zyAk_fZ0PtKrbZvSu~uF5eP!xlPSOVXRdaP7E%b*%4couxYqg+q8F)(2HLLdPq2Jci_-()P4X?=*YKP?dU)Qv++(IYr z5|F8(gvATlts{2sQjah6fmz|^?mkLek6R_m&-+W{B^HB>x*DLRdM^5_U=E2?<#@9@ zo8yuO+4$|BZ{fI}*z3ea<$FtDvdrbd{RXa2ttz(GM zd@KP;sBR}T%f!mFHUU)5WReg{_+YEN=?Pl1)aia-!>Fvp!kpNL z@I^jl$G)?E#{yCV2r#arfFTFXHtM0Qx)6h%iO(?gxOB0R zrUvZBoZvf=Z&8? zkRQU4D^pJQ9c;JV)9Ig6+v6kxh}<*uqZFk2NttBwCh6`)r4CJ~D!sBr@}%gB0uBBhAz=C}?>7UI8TVaLC?EAq}GvumHMW$AD`EWJ|g? z6?Z6a9P;Mv7}UZZ7EbFMLJ5%8ol>cUfwCf@=kqT5SfLY^PA&OufF;^OU|kJ|x=9$z zcpue`z<^DLs(p$$ce?~*`GtTZ_&8`T(G+SoM@l~ME(pp5o>dXo6W-{iaUvmMN5HJmarb0_cTHbw~Kb}$*zRzi#99kRiH zkOO%`_!5Mu_QYvR6`Ht%E59gk5nbPG0)I_vxP|pxMd~=DwE46;sK{CAQ)5@rfR`4( z6wX?)=TbeVNWp;NUfCw8uM?!+wZ)~Qx@|Zm^3`T&VlKM_Y@ltEP8a-kULa#6hf2-) z8M`r?SD(>#%qGLDd%hZthcaEAsuYs&S8KP}|Fi**&&bDougWiYtXgI&Yi+{9#slC`NLuN$jy9I=*&qDU)C z3Ei`IhfByokV|C=A`f3#*Wz%=SxpnDTFx0A;T6F23`rKrPZ`o&KAZ`$H`!>|9_@g1 zdrqSj%##mn7upasl}*WAs?LWsaSF#|r8P#aiVe~+!b_ytcc4+T`jE%k6u;C1$|6XE z^ps%C-UknkCK-E}xTODM%nP?F^lAccUOeRm z!V);>)zm3NzT4_!g#fe8vobX|^%$J0XN$HQBU_oqa^&cJ-=8fy->URDD6|c$a2b>z*z-N!lU{9&m6;5nL#Is}BZB_G_S&)P6 z{rRHRi$RK*jl_HPIw*b0aeFTXiDTXJ_M9m?y+qjS8e`CF2B@fTAJYE8Y&MR57?nsN zEFH6Y)JXxRR8Ey2R#L1h>G6mSUadzbdBbu9w4DAfeFR=_z5M!_nT8SzeVhO-M^-es zF$n2`eTXroCk{zvGXU6w;SS63{KLu7omo!f;2>p7BPA`P-5IvauQBd?jiTZ$IL=gS z%T4hhEK4w8Lc%k^1JN`>r)aBo;fNOjNELX@C}n@i#L{iHrAJUi?d=m9q&ujnP=D=R zU71olvBrz>D=B@T6=7O;ioU$cEkgOqiIN4PnYU0uUIJs2s4P_Bt&hH?DaCQh=YS{_ zEaQAY4KjKZRODqj@%81eex+&*4~SQ0T{5f+N%Sawol5Ru18_2Ps>Ny7kLt~~fB+JM zSYC`^Y|iRhrVJ}K`EH|F;?KQ&m*1*7)I8(`s_z<60~d-?b399+Zo!X44?o*bif|<{ z%*{E0#F+x7Q`a1c!ji2?`3yWqD&_&IgvJedDBzlYuxxdpp9fHoAUvHVt$2xNJf0%c zU@S1aOVumo!OxH{(@jAufQDaHn7ZP1^aI}uuigXxhnDU`PK=m(NFLgfrgk+qV~_Wy zES)&Qssu%wR;btzdW7YD#qTT4T=9an^Dm7CIm>K8>a=0b(1OcdtY_K~wx2gItF6r86NiUl z*A30@J(jN6W2$_8Z7q;PilPBMORaeuC@(%*c*Nrp>}LQgtMw}pCsby0qi`cBUR8Rc z8ZRM!wJ8x>f9AZctsr?(>k7j?X8dT&bE>KDkrM>*!1PX#8u^DlR02DXTu`4JZv6f+ z;tkR4iF?5U05~%K_Yv=Z?pUz@o7+0Vb~c7T!8peMl8mFJhOCD24F>}3p!_Qmwb}53 z6oiBd%CdYygoUk~HQc?zB@xD$1)VFyU(>6xx?AsC82^0%T&GH0ty6WgtV7jLS*_QJ zDVSu)_=qrr+3fk{YIFVL((mubmmEOYT@gAgP}sq`v;9g_(wjPi%?|5vqA3-I+kgaH(5;Ry`=3M5Wd1PgPE!StyEF?#YG-zi z*rnphO;aj#n!#X@71#{SMLx>9LHq(FYAdq9I~rCq>(Yo>FV}J}$v);x84Nxa!>CXh zbJR7GLl45dSj?4TJSj{dn*?iZIhnIm%H159xEvNIps!||Dpxx5YaH$ z`(NpRiFfGckLbnER%=1sy3WwStBS~8Bhi?=c@2~ImqGZviaxb{4!u>%%J)pVv{PPWAtGqX(TtLC%vnqWbvHKhLFYPA~RR!nI#H35y^ z?fR2Z-Ng3D-B8tbK39&Xv8rj8TqT9EFfo_^s6Xhsj#D&tMjIAAk}REZy*7kJaqi9k zZd;9AiO_3~lF`+mWv0fdZmcqoTe6Z|rk{E;*2E)S`=#yDV)7PmP4vP#Wh7Yht}$m! zodL(e-%dmmKrsW)+7%Z@gAr?T0tYnX4MWamnLo?GJ*l zxW$`IJP$bVtox-9maT^5x%TGfG{Z;3>TR+bvDKx+2nG)NhHd`oovQF_T%*mYsC$lUj!)$ zx%&LctLD(SeGt|HpRB~n-juPo z%CS*8XTIN&p97%x^OnXJbvQk^#;uFeT0p#1j(U961PGD&g2Sg)&F^5lKd$8~UPA$7 zOM~bq!0g|DRHdWU7-L2-0DvjP|6Y|Os+9kQTEh1KRF(c|I;!c|ElMKz%+_M;EKIm~ z>{I$fz(N#gHFs3x*BW`@)T(<`Z#yW`o%{7R#>QNc#CJduDO!#;Ivr1C#1$tY9on@K zh0Ea8pqQzk9G_#SWGonD7nrF0Zeh1&%P8++Nd=4=!b%CQr%Z=}tNnZmFzbAd1T~ql zR#9f8jo=R79g&J>^p0~STwPz}ts$u?t(PT>Qx+T-Z}l58E1qN$HN{FuMpChfWNcTB z*0NfmBIMraO*&pjuo;;JJN?5CH>gNxHvav4Ii>Y;lg9@u)J_E5S6S1Kg{?M1oLM(F zPi_zAn(0qIA5^{Q2|zO&HhA`O5Fuki3T0n$K4}j$fe^LdHXHHo4ZC96*F) z$;eHzKhkbsCW1Mnu-{zouEB6dy*;(HipGH1lysnBdv>x)vC0+$Rxuotbz(QL1+-r3 z`@Wa+W5@2aonY{M@?KP zoL_!!jbv6L7oui^D2>jGnyytK@;uwZaIJCJ-CtJf5bnUBHu{2;s+r)W7RXz@bo7LF zCshud99~MPM9489H4sdL@lPuHFb<*Y!dH-G2i&WM+lRzKQ#L{DEVk7ouMd zTw=0AFxoBPFACAy${r8xSk~F}Xv2wX8qa6ly3L>eSj4TY(9J!ZdlZLrqlA62Sa&sb zb6cT{X*D%j&6FAfYb+*oOKr^8(RCunyIP&4zY4D|+eZ34(K?t!bq~AI2z93Ox_j~W zJs~aIxU1)q{brwfZfn}!1jHv_fL=%z_6M%}fO3T%UJikHSt@v!+v3ju+_-a7xr8VVczz z>C9Ht2xLhOvYv@NPS8lIgm-P3a zNn>-+y1ueMd%9acz2tu-js4F)QuyCgtdfy|v$M&6pgc(a^Fhhnz~1CPc6LjWZIqA{ zP)7f*f}*WVgDXBzPBsCtC`{%GBw<*l%Zt`93_e<}v#B5UYoM8Z!uVtipmVWuc3%s# z=6G#NI9`ejGEH*!I^B3=1M~a(a)Q^z(xL*xWSLeW)^6BVD@Cwh!mk+oM4(P*?zg!% zzH3>Gwp+B-{3!;d_3X16DJU5jWpLKV!My7bd|{rJ4eHOMJK{8RPq?6V44*aWnCY#ElW~nk$(kAtqJG*-a=6KY&0PP>D+!P!O<@D-cKs$o32Z zat>r`zJQRRNdz}&4l~rrb#dd0g(|htPWc>dIo>KmwA+}YMc-m6pFldLgSAs;7#H&? zR%BvQylL0NTzw=m5*&t@*9Wgvr>cNBRwXokpJSwcor}jb{7IHrkF!piJ)wIb8P!R} zB;)M`<};E|^n*^jpBUF_O@Hk)Ca(tj%JrZ!*sqqUI&ee_ceF`&-SD!gyIpli=R9X~ zxpdzZhikXTeu81zASVKnF;6ZzM8O=?~H=@ixqO2J-zD zDg(aP81Xa1>@*)8>HCJ>C`?^AXU5SM0Wq|92R#7AjF({)p^6G;Uy%M!G ztY&g7Wh1G^vNpecjC|~NYi>+8Tzhpbj zc6YwN^zQxzVhA;Z>cFtYl;v$V@K`qG)M(Ak%2KIHWvSeHqVXEUXG!en=bd$CK9CSh z-=8rkG;PmnwN?_Hz7MU)4E;6O3<8jo(X^QichK$z`7Wr{+WEnh$|U@u9bVZAb0+Bq=EnnalD2BS;uxQaB} zZ@gBe2^(7fsh}glND)f!U+_0(17l>Drt7Kj3{h+2LAz?}QFYZ_Kfu@cj(!RRVJ~ao>jHnuvM+;H#U*omP_KfQ}lr(2tn9{b*s4@Gl zJPzSA=FkPe43*q6s|<~)w|}KO=ducYn=qZN29I?YOJ4Z#s5Zayn#PGEGr9E9@$K#9 zCy%YO63g#Ig`46wt~o@@J%pWIlp3j=%jogHUKSQnI!?hK&5Jt2zlDnE${R|Ct@%Y@ z_DEuOp41B9%K$jJVwi&o>kI)^V>yHZ1+lw(qTHT?U=`;~AlWYItpX?k(=l?Al!2bT z0XhR2zWgEj;jRw`e76uay+jTyzdO)ui$ky>?T5_)&?ES1_~ZcxsVI@FLYs87SHAn~ zB^GrLpmbJU3$FG;(K@?>>eYrAC7ffv58M1fN=hUEE8&qLAfg^<^Iuip;fuo!v;A-K zUa!5fi~5iF)89}V`Q<&&;jXPp(#A#{|KJ*jgwp63UG(lVb|XC!O7IJK20#*}7vBLB zWs?Civn1IjB|sU|OmeXO;>yiOIL%1IlvhaRFGv&GR9}|bw@H3fd|~5Tl;YidRs7qY zVxRY0J=PsR$&PcJXv>&l5Q1RTm^+;7O`|*Vd0WSFu|=&2fyyx@!o_1(KxHLme#NZL z^!+dRKN|8w;e>nhpCHkcAJo@>{g$~Ks{Knt&iemQ-v7A-P_4RawxRH$A77mU86A%409HHG#bZ~=qMj? z)TmBK(h;tjc<+gcde5xduB?y1Au~vAv5- zGy@T{{WqjhG47DxyA)^yg)9hSCbVx}&x9lsWKsl3wVjvMqh_hOZkR!xu?`FGz!oIh zHeq8P4j!02gd1mIEn#g6tSV|3a=R?36q%q3eTp=J!oUU~iVj2y8Jv`VMD z$D}r{;%F=21$S;ota-(_qz?u!{qQ5@8Ju+DRk>!gxzgz_IJ5} zxbsnbR}%<{4;&9XYn=i}ul`3rqL_YqLwymW-blXdBmRN$wUmfSU+KRTpQ)2~vQB%S zm!>fzw^uF7(PYvPO6pE=4Zsrnc#cbWazR%P^KO9I0uk`Hib282Ql<)1k{S>Tp?Wv% zm3Hk{z9(?<=3Iubd!r-InyJz5&NyF*HWG4V!W&oLn0LR*i&X<}$tGzMZ34|%-3%_N zWi&>WCX(zX|nie-oyS_sR1jZv=}II-%1w89w#C}$;xb+4gd3?K73>UH5b%A6=HO*6vE|;aE)v|(66g)^S{xO`+rCFF z^hJV)Yc<;7-;%j2sL8t1!k6=bYkgtPj=yfuVcB^u;fQ?R6%2bt`Go$5PJK*(9YucH z@Yx?w^MC2|f41TO?#7O=f$a~}Udh?Q$m+j4y2@Jr=sUjI*b)vSrC?dKkr?KpszH)N zr66QwkimsD!%EXV_Z(<{GM-b1D6Am-!p!hCGK{w@%r^L5#29%y6J^ff$c$MwE;x7H zp1I9l@>+ZULh9qi(L^(D-3sk)CsuCTbo6+W<+hrPK5g(QGOa~|Z`y`{SI3r9pYc|m zqC%emd)C~RlK~raslK+#zhqJYlzjsw>-^EaP6KW9|V(29XD4T><2*tD% z$+u|JljI4sqi+A?&DZzG*96lhh(P77)x{fd)Bt;|J!KJjPG#Zt$5(~m-LSZmJn?8q zSG8=JwyAJOGmwH!Mg{3}eC)hppzYv)>K9doJ7`phvvo=?h47{E%~AT~;|wCodZC=Z zA>zTb!Vfp0Ddj9HC&6T-uKli3)5LEP#X3V_D2A$E7Qt3ZZ?TUk;8AQA2T2x2{E}-G z8y^9|s9Af((PNN)oeX$vhbn?M4Z;@21gjCe_();dQe%UnV9LJ5R_xk>Ab#qLM?N1g zUlME*jxC|NPoJNdV(Oxd2E){tE*ZqVh&MpT){L`a)1I>M_$XXd;Ug%F?Y>cw{3|jW zF4|>#2xiM<{6$VSc*YDw%TsFsXhXQiesnPT?V~us51C_qpi$<#!tl=#c#mgS*qNPiFpb&vM6qa zsL>~a5w+3uklS1CWin2%1`kAN7A7#nC3HQGkQDdafc^fL$~m;F=c}XkqNe=7xg+&n zC3eE}1#q|QVBF2ZsD;9}KtT+hjW!Xb(j$JsP^^+%978iQ3$;-+pQekc=h(Mo5#t)! zm**3SNA`dMmJgcNK1M9CsWVU>Qs~G8sk+rrLg9|1si_wSCk&f}tQm|t9~-v624p&3 z4x2KTD^q|^G>eZwsD7Cj2XnMnu5}qq4e}Z2?f3_qrVf0Qgd zdNzN&-#JHToAlo_UJkFe^P`@f!B6gkY{Cg8uZ&n{Q1sJ`CBQXCX(R#7-TL4{gGX}w zLUsGxYeUA?rLDn2GRj4mIa3H1S9~$Pef{zS-vLIu`+|^-;hd^_7bKfPi`9+oTkHHNRa|A6>{^}I^j{-`?nUsR1Dr|>V;_x~5-`=5Jw|C_4+ z;fPf$%h+u)z;u78-JY66bWY0ZMzv6e8mQOl1BU8iW<*4+H4x5AL>Bz@c~rY1)7k`N z*4J1--t{Vm04L4FwS|;U5YtL+(iG#oDVOGql8%&Jv)zn{3-W(xum>_nR`EUYHu)hE?az+5&Vs}1qS=3aJqo%B|Fv~Gmx;{ zc*GT$Qnx;Bbt?v5{x@oz#2?bzG-`#xbnaIWPcleip}@iIUOx*A^UqRLd2IQv)o&77 z92%9>Nu(Y_O_K645qZ^%XxMa^?l2{vx${a;_}0^&`V!LzG+rMp#cm)O#v*O{VsZ>M z0AEnR)5WuFs^D$hK#Sg+M;_<6T1iI(_@U|VL;iXhgDp`1j$1#Kbl2CvNST2xU?fc% zLa!FlwRBa$qVU0_k z9LdScD!xXXVwBmkeoVNj8`FB32<(QlH(6_-S|&L@;e58aDtE&mFs7ow=th#HDR_Fm+e>w%n5wgvT!|AJsCK?Mv{y#A z*#9U8+o5E43qKdsr$4RR|G6CeyO`A#3N90(wu)nSYEg%wC!6S4 z$u~54BB06-4TD?3a3$N{cMs-zYV)f+N_(kivlCf@EHQQe{@c|Q&7~-HrT4=W*x#=Y zf(_k{fZ)j0PhwhNV$>`@Jx>oU@Li^QG2)rC@yNHvom|~*vJgw!xFxd;a}cWEkw6~8 zjV()UOBQz;_E@+|6p`5rQy_6+Mv)*w{;lZLNTQTZg?2>)Fr1hZtUMddihrR|l|Yy= z$m4+uiJO!|-hFNZQ@^(ys{XhVO5v5Vg@9Vi#5$Dtg1cN>af18aNeL{>y4bHHl+EzA z=tjTY8<)cPLiopIwsMCQjqc8WiAW-&Sg7F<_F~nX88DUk9Dn0Hoei45yFCQ#3@2uR z%~g>;b*Jd*pF>3IL2)|Ck0B!QfBhQe{>>rcfBPDLnV1^5SUZbaSX+zQIokZwLHtjr zL|IA>S>cDy;>B$=d5bV#`HF@zVI;564|M-qL68&!S(~#7y^SGrMCGJhRfkfFve^S8&-5Z8v2#@N#{wnm+lMC*Y_)=|KQkZI79YKhli6a z*h2^=Gd=q7LRZuDW!E3jg$!z-U7VIKhqG`*Qdq4Xb1c+G)qXgpg%;+TwAMfYcPwICO)AtL~5P^-J_7U_Tv?;0Him3gyS5G48q%gj-F@67nRudmO zO?t*#M0WB6{c^T^BVizgC9LqGSi+4$6w8$9b|GI;cl2sZErzAIPL0VPV-Lk~(!?rf zjF}qhME=w)rY#n7Az4a2dml{kRf9G~vh8eC^-?BGQU=mMXVCLA=~C9DK2_`0`j~>E z!YCLPL+~J31vxqO)d8r`8CT4;uZv$?k(*Zf_|MGNB(|rSk7C1#_KpMNx@H*G7PLxY z?7c@^0|lD0)Q6?bcngp$hxxIs${uPiv_Qna|K1++TgzI zEOU@a1%mHNfE6&HX(1=EoR+_w47lmY?Zuy-8HCSwy{e*J6?h$o`IysDWeK|BhZ&pH zn4*3z$AV2QG6PI}Cl&}b@=DSK3MGt~ds;>uGn=1tr6ITorPw;R+Y?AvB7U;L)O3s&lTJ(u?Stu=_;Om1gxy+C zC?QQ#L8*qtDLryM?=#OZ0=T3YJ&X8HYSZ`LWB)ce9$sdmbxm?DE7w%C1lb$o2z(-Lk}F2Qi*RB`0Uc?lGs zV3x?z_TU+WRXOodl5K@wz{WYhyisEkwyVN_S*jw&D8q~N1XPh_!$9+g6TYt?8y;Dw z(_s~~a`2Ve>{JRsz{}l0m=(U?0Qa^ck+0K-$bKKNX04dQP z42c9B;V4v|5P_)QUW_3BfJ|dR$d&!tmSNsg=~k$#5@%%vng=n(y0F}R>BGFaMboRi zxdrd5xwTpGZ8z)fdDD&^TfF$M-K6is^xg4v=k5m?z2C!H5&(lj*BQW!zGKm@*3KoQ zjky)Yizi#V7Q4IV1U7pc5Mf-c27BNiC!GMzxLMw~o#T!`TktiEjbN&avg5 z1>{GTrnZx}P4Bf~OAMG>x~Eqx_TP6O-48x=I93DStT2w;FH8Pq7By84N=^XmHk#-6b2A>zbb3mCHx^WO zaBT<|Bl_)F75WTooqda41!#XmEWKrNMb*ae83N4acTPqENl?mLSCC=aeXaq5Dw;=& zrJ@+?y(4Bj;9g|!R9n0Po3Ee34d3bm_VlZEPo4<_E-VmhTq~C+A)UZnZ!A48;Io&( zvH`JTH&>6~+JLdLC`Ut)7|5)&iKGx$`Y_bNY}a*xB!4i-Y4mM7__s*wWH?@NE%9Zf z>b4pIdrnGON0DZOHN&Y#eqNilK1e!qA{HyiDNo2Cf>l6ljOd%Zio#`VQtLo8$6&<8 zI)FdzZPw}_s;V9asC!@2?H_c_D{5HKaG@&gPQ=l*O>D7yov+=L(} zNU~Qju0C4X?`I$H7aWfXvq|ybZ%gkr!Ts?!{?H%ZN6YnMJpgp2#CrFC9gddC?T;o& zV8RgLUh#s~eWDb8r!tHza~fc4@B2^AM|oEPOSK`@2+3_zy|#pZN%zs%hnCBg3_Tb01)Nc^L!+XF#1KV4KBm-^ntWMzzg~V+=W|< z2<5%|B>Iy`av92N&Rb<=X@v=ML;AhsL~S00FW!dg8!k(G3Wq6cV|-VimXOy5du`u$ z6%n6zVs}Tpd=uO`R|b+fkG2tIWoapCY2NCCbRFvTXlqGSsQFt6u2WB>g3*^6YVptJ zB@~wL1t8?hfX}ZCa8jIn45DQzg;zsAi0*u3ywD&xcM#Y;(N$A5k0|Jjrb6J5aq0r( z0Sq^`7EpOjAs4(_uY|IakOL@ZU+5f&daZ$?TMSWB3OcSHH}*4#zbMIRMo>b?vQgoH zrBH<0+;R~F)wKl9_-VHwJP~k%Rf4e>zyhT5P(n;RA%zIB5lF{Y zxtqrpf;!@%_(o_&a)M?#8hgQI`yPoG=nTcQH8FZ+rynd`B>N`rpqvMmq`P7`8tMy1 z4fT+PPgseyeb~h%`~@Za!%3t-JJb-GZ>7O`{aO?lguQq}w?BtVNZB9I?xTQq#9l@~ z1)6@1!FmIo>B}A%(GqojK+%@re|l4Y5(H>P!^a$_)9(4|xh62dyW)KBHle{i{_aY= zBKXF=A3>_J*$j>Ox>Q&7ZzHh`dM3}Y24CZod?Ly>D=}VMYaiKJT3J9V{v}7^EBOwP z;bj^{feHL3+4tLXny?)IO+OGnyLl{PsIs`1NBTL;bZS{9=ve2MbnEsCZWHPYSR|cu zPKv6gW<~v6671KnCJE@ER$a0J!L1vRbIbZU3MeLT?v+8bkIfM&N_e_)sTwAVXJaJI zG!xu%@ZikQxwRcGc(M0OH9NG@fw$@f0b)qapr~kQ}#$0o4#h^l^-jXmR|uB$dRpun#mQU)1j~L1>pt zWQ_GCL)fEClwk#|RVE?jl1;M)%ZdnlUg^kk@K6?wOj~AKCWwrQ}yV=(xEpOXNyxQcw#^q=qqe-<9kNuHzYAyPRyyK!AEpSpspLo zC72wwB+(N8l1#4L>L2khV?Db22$5>9* zhd4tXux;9aR^VusP$IHf;#^b>o;#*@Y{p^@zg+R}Tt>C02GriDIh-{PMO+^%u>`5m z$p;&ywV|IIG=kpf#@n3&8mNDcIXdYh)BxZq9shrb&WL!%sjqTRXDMHl%pZh$kMG`Al!m|s?Nxv*5JMf z&sECnAvv6ij6_7=M527suNB)wY{*3Dn>zD_1wtx{eExz-VoXF5$}9Nzx%r zKNm%*t0TfxyhF#`xHa{8 zgiAKatK)bL0iY{Y+Vvfw2}EZVNoQu=M>DeYTX5CXTWwi!(Cndpyb8}d~)&&uWOPqJF~QI!+cQf2xf}7ty*K} z%9RzIjeKlRX6aR`HGC&1>1cXrU>-IkuuDHRg1w8pt-9dIt7^0y1{wX^@G|7d-j4Z( zZPKNyEBJXB;_xq;rPxCpa=NLD*5&h7OwrUG(skX$5b4B_7Bsangbf0P6Wj4?gO_vp zW<1b8z4D8S%Ds9G;Dz?hkGvG?fQdcUa`vDaxf63(ZhiQWm}`TV`9TJWDR`^^zaPc_YWqP7? zJU0ay%p|4wHzx8H4gQ+-um!p|8qXyrNN&Ys{EZ|`?iJ8|q)&e!jxv9a)(cJ8HN`M4 zaSwvtiDsp}icq{t;>8P=I9f)KAaeiu!-WCIV%?S;;XAYvW^%=vPDaB~Hib&z67U)M zVH#*HV?LcXjaAjt6$#>QGZ8N?6p?YRcV4c-Jy#v3fO(0h8TS&pmbwR${lrY)NIdg> z2s{{9@ShU4N(e3M&C@Q#L4-%5JQIG5_1pK}WFruafA@Wd7ZyUDUqWB zsdErK9&W_o;e2O2uGA+xUIdlMYMZ`*Buhu9FyM~m_#2<8gep$toPB~Zw;!Ctoh&F4 z8G!grAU8yCd5hG=MGCFJIhR3}GZCIBzR-4D(Q`J5CvPXGZ8*?{+OqOkZJi1_Uc#FK z|9Wo_1LdVZBv-aKF^)hhbNy7UUP8qx$FHJndpmF>EiTy`g?`9p{uBd}Q}f=&yXlBr zK|EPvTo#}mr6QEfG|3BpaaUMP_m~h5SHcwcEi!q zC%`-t1zod__phyXy=}Blq>59LM0Ei^{6NB+ehC4>MP((ms>}d8&t_+%Rto26H7jS;4rWx1?+Be|{{XuF;2QhC{s#PggtHiz{B0L8!llX!v z`;+OL7kt;T>t2Zdf^=81Eg_v|dk?DPB7!MR$``a(@qvo1)P$i7zo#^< zLd6^kOWtMj{W(VXkFdEw5ZAAKZG0sMgzDrn?`c1Rx9ZO@Q9#8s9r7nl*Q;*HKStW)+C&p6mR?#4Tf+f1n1kViJScw zPL5+9;yAB$(ff}#V2np>4u*7uR$kgl4m44Bgw_#n`&(T2loxFYTKFS5nM-`Qd0H|6raGgV3sTEZ_)U zv6W{Pam-J`4htmZ1#bar3}EY~*qm;{C+RyywgfAjkBWVBLV*Ha+X7qFtqr-%XT_1- z?ds#N!>sX0h*wvmkZv89VSy_4kz+KqywegbcP zP#64?-ws3BV)Lwu*5o6k{aC0?ip{gy(`AMUd_@Xs4!87k^*&j0pCaVk zZzrGhNKkKj5&FB=x&Ac@NNIoR-uPen6U?f=^~29~Q`7A{vg9!7Or))8sdUi@BV&?) zMntB-h`DA&m#-ZpeI7XmNA`+AQh$%?2ovF0&7=0ORTaaS;+!mXZwsoB+V_*f_y-)t z8~Rs5kd~Ug-|=|fxarVed1X5n`gWHQ6PwBC5$z(6D;7hLHxOd^s4Rx)ZKd^3_zpRK zK?;TN=yKS&oT4~IDksp1h!)F+5mRxwh66@0QTy= zeK&5si=t`mG6#k(GkGoW_OHcy2hLCC-1C5}PRhsbbc~kVbeT@>AG=a4D?6JpD0qDO z`XI@m4Z}b&&SD@_L3C&_08pEsQa~Wi-GN4Zfes<#K*YEW(EqA9S{>}f@Qtijj4rxm zu1+D6jpm6tI3Fz3j)Y9UA*;5#`v87k?_BchylUJ9f5OLNV^oQ>Fzi^l@T59d6BU}} zVQ!3}zkVn%EJZ;zOzn5N+O4#o`co9|q~b8(LViwMjzcG#VAzsg#5`mvM}R>o5q+`P z9UsoIN!M|DssO|;7fA&~PP|vXB?$gI^+37)#~!z3ZF&v5)*oWQIC|sfGL8|Z;mI`! zN5&~DM{F)XG(=31v0RF&M)663!;JhcfO6>t{KDLTC6!62HL1v|{+y9;$AfViFJko= zyDFjZE8ToRlF3^}kI>tKOe+zM<)Rgq7~jJIY&8E{(NHT^qav!=Q@6?U zFFa=3Mm3brDd*^6txJzmQzXG%ptq`nO3Fe~Y{2H1dR$PUXnSAv9=no_q^F zjHQ>e#ri+jvi#?m&Y1fg2dMD6*gB14=yFfU?dKIGJAMc9rcWZXEUHt)4ECh*DD`GX|!(E=i>*=cFd&&Xi?67M6kkFtBh)cWc(#`{2^#|w@-Rl#V8Z_#HdaYKzml?__DQzGk3fuV`VaM2?acDN8}y>@uMKjw#2F zTy96yOtv_y?3we8P=msN>^FK?0r2U5OzEDh5&mX97s#MJ>AAzA{MW?9L$73yJWR0f0pCrq;%P|bh5me6q1LOf+ zCU*@du;l<{&kBJ_j~U913eJi9rR}dpD_ne$j|0z$DRhni>S^?Vpfn{c%?O7m;u8t_ z1PXTEdI-aHdbH3$SI)^eH7hco6r^|>?UYL z-d4Y^t>=lrqqBDvyt1|m&=a~u{jC-BSF=;!iQHMeb9KMh|C|rMlRn(J^XW2*YhUql zM^R7m%V2E-RLyMw?y>_8v8@2vcIX=$KQwE=9=aKN`@PlqR zkT>G}GZM84_+?nf-jNciy$Tr)mfIU5w-*1+8l5|==(kSY z&2hKP(2W<$-noBTWj?|yPEQLvRF@n0Y7dA=27`YE1peX^{KGq%3rBP#@FvaI3o)eE z;KG}r>Q>9l^@ADeC)c7Nq>v<#zOHKUsK`2+2&=y)&B~7bzs#seVhK+3G4L9RPHVP;kX4Yc# zH`Smun;|3q4=u&e>!RX4jI~5M?bz6)j(quf?#P7~;g?Wk0SViuf;fP!pzDor=&j&q z8@S9^jd`A5IFU0p)#)__UR#0Vc7UJ*x$=-sdF*SyCQ6u#c^B5cfbs+|g*-T-Bzdgs zz7{)9pxD00mk%&rnBGv*otQgTY(Fy%YOc}x9S}AkeS@NVhD?CkI*xlx4j7*S^?uo3 zP`gGn_oy6ryQZkUv@51J)Gj#RA=g1W4fbyImY%Em@P{U`bIEA>XRaZCYQA&$d_hfhV7H#-Oshvau~Kwf8+EP_yjDHk1ST!GLiCgK}$n5 zqu;WZVR=>E;S|~P!6JRlo1uJqa_)&@9g+eX3kcg^wxkO!u+_5xR!@dWY#R(d;l3xY zqY*I%*gRD6iIF?T?AY1mJ4ow5IYR$gwzt29qgh_%_oh?lp!HDPcOEAJI^s;3EYe1> zmxEVd3|;a?kXBDxOH0MnZTFzOKheAo^r=2!&ueb#!#4F&GR)l2vtmYZ=2HnZ6Exs> zGlprDzr`4DIYj2atro(yTOlWc8Jev;e`^=pv2rd8b9~w`ij%|UUV_(Or&nqjJ_RZY zY{Qy6zsr+U2+-U_Gn8U1f$rptXVS#O{S5l=P^qR@&l+O+8F4}yq6d^m3lbqYV%GIZ zn}*0v{G&9Wt^`=uW*7DhQf&!$hK`ODVC>@oGA+J0vu!r^?iv z?XqviTd;30m%JKXzUD^HDOVi4-BL9rzKUxstjITogLi}{`L&!aedZ8yuT5ufLsK(46uUwiS|Hcvj7ALMW*)q0+T+=}6RHWhv-OsPkUXb5#OspunLcdY8a2h(( zdjehErh~wWoYTYe#5kDxlJsyXiUSNz%vt_bgrC9T@KE*1k^I*Kv@wnGT zeOxXUOsK?w7xPCZrt*X}{ZPJjk6$fi!gNSn74mRhyIfy|;%m7+HV2B<8qm2u#2!=& zh`s(-sI3*i)&mFEq;dyU6_(e;yyu1y>>U^|qE-#qYam0DQ)Bk0Is?`;YmMT>1UVya zdh}F#Wztf<2TQ|0CvG-MJ^mXZsMr zt5ji0wmCqZT-gg`cdt=gX^o=Y-&dr}S{dl3rEJf_5qBV3Ix~=;!~_P<3uNTsig%7i zg{%bfQFJ~Ao)4POa^-k%3!M&VT*_@*$NG@o$iO!u?vy-ns-hVyyIrp`y$3xt930bo zz3n~En&X{ua+eKJcfnF;|F4ljFJt6V#lK{w>b2z~r(YNo*CbyubZun3Uy1X#=$ZVHec(+Oj<+Z(GB4>eGW`(3*ukFJDp~YLc$5Eujw7 z-4U^UK~NnqHeXg3%mWLdN4dEJYhs~+mCN~Jw+DJ@jxhX9hQ(A{$Zus?K{&6#;KnNw z+}_fhnp3k&qSe(o2|LWzW?W{n#cp_)MQ_O2Ss^y`qIm53+3=~+6Ps>uEmRNVB+XWv zZBZ2qn(6QFbyS)+W4$*6*4{#N;9Xsb6Hm!7hHXO)Fig`LbQl2hkk|3lhiwHsc7dnX zYw9Dn;mqo}`lICdG&^Xm@hAWBL~5H6K;C7WviY+1JG1s7lExnP)qH(QvVjYb z_C@SgOY$(k%N~o84Vw2#O`JH2A9ST)-w!eLf=Adw?k~e378;THfv7s*{47NqX;Czf zoFWwWFKtuAr%EH>vxmOZDqv!kH-?AFi{go5o(B)mSVNA6K0%Cz4vWrBl#_41vyRSS zM@x?TGr@Ge0Fh?afKz0~B58|EUr}z|TEt&zL}kM=K(hP)K&Xz6uluj*G$heAVs+_8 z>44Im7!h6&RuaEMX1DYfVoTR<=js4FUhAbq3CJ6uL@I?;S>NC#aQ_lWV z?z88c*}UfYWfi+b+0i$5uyDSEZR>eGqxd%Wt9bbHA2QQg8bk26)U{Wnt{sy;g`cj5 zw`EU04R4Dpbxq+))Z~F#eh1N4BF!5t>%G?miCmCCuC)!O5RI>AFnkfT+(L#Qi7j7lRK3PEW8N2&DY%cJCD#L64g$9FvQG)m-{JHZ6|EAt-obJ;-;wK(yQFW_q|7{Tb0Q|#V zQj8Uo+wW63x-F;+@AtBg3+Pu378b)Op?Qg~F>h2#qopc&iq;F^xF!f5Ewt{%9}%}8 z#}7HFMwI-aTK<-lbdaZ2F0Q)m(tr@{IIebo>L;>y$2~S2{XpZ?7 zB=?!DEL?BT!inWbW<)$A1X)XqHnoqEd>0WvLr&aPnm>^XL(ITHIS_A*1V$WuZrmf+ ztUSfXc*e1wZ^W5B%%|dvW1w#*B|mQR#r%&P_>&yLOEK1>z|zvk@NA#O1tnlZtvc3F zsPM8#{n-j8~#5aT!l!^cK5bVQVOyyD_1p)w3L4B!AkcpqK^r?e?- z$T_oqcfeR~=mpc4N$qn&x#**1mm=Xh48v}M9u&L}CgYJOYJY+iKC3F+mX*7sVTTF$ zm3Q#R=&EOFZBtis1(K`K%u$hkH^8iOr7>oEYjmbBAc1jnZ8`~;^l=TiQ~!R>jp#`y zq5wLeKwR)_kSr1AEak13(HTDwmmz?f@u*E>Eq*BoR>BnY#>arY{~Om!!v11Pw|{BR zUlAL%1Z)1NafDM7*Csg8#9-fDvRHBMgWEV3*-V;0iC{r|C^>*1chf=KcqI-Qd32r3 zIU-=bUJRA-cg%@-D<+A@KlKk`avyN~6kK6*kRiZr0A&Z(>79@xhR-13!ZS(q*_2zu zE}DL_bTw<^Kk81a(9gs%;+HzV143#yf68WG?bRE#Qar zuZqF0tk ziCKiC)U0-q*vaHpbCzuYigqvjRlB1pr{K8UE!tz5>5;MiO!zo166^Dyne1pf2hF9o z+%P~mi0Ij2l5x}|LOtm)14FQAl%{;)Y@lO9HfhupdCE%tmUMWl;fg&Z=zNJKe?6LD zR|RPFa8mmab*R-y)Ow|CIJfYWdcEpUp+dY|B&$8v2DBX%vq3RKTyH|{JNS73y-2c= zNm`6JBB{UhE`lZ0(k;5m`x6XrK~PB`$wOL(j5j7h6%bC8tydHQv*9LdlA+N0RZv~o z^~h`y$Kg^`TYzR!oWVo}eA%(-KCxXsAVVop;$id*`9%jpp-4ES%23EiIIu>f#Z>5w zh{m0d6r&z+Dqn(Xgdp$F$<@T^5Wc|2aIWc(fEG@;^dI8au-N31`WQ;XxLK?BA0?~xIX&U*;%Nk{EZNSC^ly(vmrnZcqmbi z2HEWZrjb$lx$PLL2Wwyrq?(GsF{OnzEI^ya<_PP7TYSt5MU#frRi;jy&in*BeMvEu7n46 zV~*Bsd=!Nl8lDRg+2xoFKS(g_NJv5BON3bu-%gfmhOds};s`I6V_nLG{|c1w zLx^`U<`X3TI*NSguH(&cpT;ZL4Y=HCX5C0eM~I~N%EC!8Bli4X|JeyI4(H_6E{s_DB5+r3(pX5Z5n!--mnHwmI?sKC=dyY;?q` z)lj@KFv}~525a0Yjt3h*Z4LvZ_gc!tdTD#34Y2T z!re&r-~X;58CyVPB~b$ac-#JG^mjP?|Hgs;Pisj3U-b9CYe>sH-%gwD4SlC|{m0YI z%0!GaJ+3?591^n;Im14#*$plg+p=UrQpqF2NYCPvskJ>n-`C&(2T>@;M;pA;Im8M5 zh7Ia8XkAewK_*NenOnt%$+L%9)tR-mhaNAiIGN(x&4-l0aPSC;@n7h$7U zOp%Dnm7s#K<5+D4RTm-Kgeiac8-TEE@63sW2}H=sMpHG20Eh~ygx+D4K`)k!+))

    1>-GiZQceB)p+xoOK*pC|yMXm6{ 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 Qd<6d$s({V^dr++Z1IGh^PXGV_ literal 0 HcmV?d00001 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index a8d309b24e..4ab125693c 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,4 +12,3 @@ # Project target. target=android-19 -android.library.reference.1=../MPChartLib From 0a00522d249d9375742275e39beb3592f6d34e97 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 17:23:36 +0100 Subject: [PATCH 0143/1390] Update gradle and maven. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fc5c8a0865..998fdedd75 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.0' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.1' } ``` @@ -137,7 +137,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.0 + v2.0.1 ``` From ebb146856095f141ece5fa5360f6e3c8cf3a49f4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 18:52:47 +0100 Subject: [PATCH 0144/1390] Added feature that allows to set the grid-line width for each axis. --- .../libs/mpandroidchartlibrary-2-0-1.jar | Bin 545492 -> 0 bytes MPChartExample/project.properties | 1 + .../charting/components/AxisBase.java | 22 ++++++++++++++++++ .../charting/renderer/XAxisRenderer.java | 1 + .../renderer/XAxisRendererBarChart.java | 3 +++ .../XAxisRendererHorizontalBarChart.java | 3 +++ .../charting/renderer/YAxisRenderer.java | 1 + .../YAxisRendererHorizontalBarChart.java | 1 + 8 files changed, 32 insertions(+) delete mode 100644 MPChartExample/libs/mpandroidchartlibrary-2-0-1.jar diff --git a/MPChartExample/libs/mpandroidchartlibrary-2-0-1.jar b/MPChartExample/libs/mpandroidchartlibrary-2-0-1.jar deleted file mode 100644 index df1e45545366e1971d989c13b0016a11f5badca5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 545492 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

  • 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

    3oxU8mqdCj0}(Ov4u4j;!Zrr=0~gg3CI0QO)ovc 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

    e36+5RQBpjZDb_nawX! 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%0DJ1WR~;a*t4gZh)G3 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

    en_YJYgcx;1{}5oj`|`9WKI| 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 literal 0 HcmV?d00001 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index a8d309b24e..4ab125693c 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,4 +12,3 @@ # Project target. target=android-19 -android.library.reference.1=../MPChartLib From 4b69d8bb5bd19623319a8a9310e5d495561ea3ae Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 16:38:06 +0100 Subject: [PATCH 0162/1390] Update gradle and maven info. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 75072874eb..0e581b603e 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.1' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.2' } ``` @@ -138,7 +138,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.1 + v2.0.2 ``` From 1b1f639be29aa2b013ce4d2423007b5feb103fc0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 18:05:10 +0100 Subject: [PATCH 0163/1390] Added sources for documentation. --- MPChartLib/build.gradle | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index c3ac477a01..fd3e79432f 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -36,3 +36,12 @@ dependencies { //compile 'com.android.support:support-v4:19.+' //compile 'com.nineoldandroids:library:2.4.+' } + +task sourcesJar(type: Jar) { + from android.sourceSets.main.java.srcDirs + classifier = 'sources' +} + +artifacts { + archives sourcesJar +} From f52c3cedef3ff6e21a8bb2359a6d2befe2901315 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 18:08:30 +0100 Subject: [PATCH 0164/1390] Update example build.gradle --- MPChartExample/build.gradle | 23 +++++++++++++++--- .../libs/mpandroidchartlibrary-2-0-2.jar | Bin 549340 -> 0 bytes MPChartExample/project.properties | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) delete mode 100644 MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 3ac76eec1a..da36f8bae4 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -6,8 +6,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 21 - versionCode 34 - versionName '2.0.2' + versionCode 33 + versionName '2.0.1' sourceSets { main { @@ -31,11 +31,26 @@ android { lintOptions { abortOnError false } +} + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:1.1.0' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} +repositories { + maven { url "https://jitpack.io" } } dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:support-v4:19.+' - compile project(':MPChartLib') + compile 'com.android.support:appcompat-v7:21.0.3' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' } diff --git a/MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar b/MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar deleted file mode 100644 index cc8d47f6a770063eb4b83b06caa7f0ccfbe52a4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 549340 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%0D^e}}G45n{WfuMw^t|kMvR`zF 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 z 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 z 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

    3oxU8mqdCj0}(Ov4u4j;!Zrr=0~gg3CI0QO)ovc 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

    e36+5RQBpjZDb_nawX! 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%0DJ1WR~;a*t4gZh)G3 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

    en_YJYgcx;1{}5oj`|`9WKI| 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 diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index 4ab125693c..a8d309b24e 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-19 +android.library.reference.1=../MPChartLib From 10b8e09a1d6a3c341817bd27e174af0569f1f71f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 18:09:03 +0100 Subject: [PATCH 0165/1390] Update example build.gradle --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 70d72b91d5..e90f5f6fd1 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="35" + android:versionName="2.0.3" > Date: Sat, 28 Feb 2015 19:18:16 +0100 Subject: [PATCH 0166/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e581b603e..0b425e7667 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.2' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' } ``` @@ -138,7 +138,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.2 + v2.0.3 ``` From ef2a10aeec7f0a78814d1893f349169ffeecde73 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 20:50:05 +0100 Subject: [PATCH 0167/1390] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b425e7667..c5a5322942 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) + [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) MPAndroidChart ======= @@ -159,6 +159,9 @@ For a **detailed documentation**, please have a look at the [**Wiki**](https://g Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). +You have a problem that cannot be solved by having a look at the example project and documentation? +No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) + License ======= Copyright 2014 Philipp Jahoda From c35189ad4d4cbf7cceaf21dc7ea744adf1e32090 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 21:14:16 +0100 Subject: [PATCH 0168/1390] Fix gradle issue. --- MPChartExample/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 51f25969c9..b2c40f0042 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -51,6 +51,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) + compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:21.0.3' - compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' + //compile 'com.github.PhilJay:MPAndroidChart:v2.0.4' } From 4a1a8027a47e2ea8e3db38568b77fba51f6912da Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 21:15:26 +0100 Subject: [PATCH 0169/1390] Update gradle and maven. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c5a5322942..9d9ee00624 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.4' } ``` @@ -138,7 +138,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.3 + v2.0.4 ``` From 8c649ed8a9cfeeeb4f3381154f19feddfc3e575b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 01:08:22 +0100 Subject: [PATCH 0170/1390] Update build.gradle --- MPChartExample/AndroidManifest.xml | 3 +- MPChartExample/build.gradle | 4 +- .../layout/activity_performance_linechart.xml | 37 +++ .../mpchartexample/PerformanceLineChart.java | 283 ++++++++++++++++++ .../notimportant/MainActivity.java | 8 + MPChartLib/build.gradle | 8 + .../charting/charts/BarLineChartBase.java | 17 +- 7 files changed, 355 insertions(+), 5 deletions(-) create mode 100644 MPChartExample/res/layout/activity_performance_linechart.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index e90f5f6fd1..395d834f1d 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.0.5" > + diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index b2c40f0042..7686ffdfaa 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,7 +7,7 @@ android { minSdkVersion 16 targetSdkVersion 21 versionCode 35 - versionName '2.0.3' + versionName '2.0.5' sourceSets { main { @@ -53,5 +53,5 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:21.0.3' - //compile 'com.github.PhilJay:MPAndroidChart:v2.0.4' + //compile 'com.github.PhilJay:MPAndroidChart:v2.0.5' } diff --git a/MPChartExample/res/layout/activity_performance_linechart.xml b/MPChartExample/res/layout/activity_performance_linechart.xml new file mode 100644 index 0000000000..b7aedf6dda --- /dev/null +++ b/MPChartExample/res/layout/activity_performance_linechart.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java new file mode 100644 index 0000000000..48d7f246de --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -0,0 +1,283 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Highlight; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class PerformanceLineChart extends DemoBase implements OnSeekBarChangeListener { + + private LineChart mChart; + private SeekBar mSeekBarValues; + private TextView mTvCount; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_performance_linechart); + + mTvCount = (TextView) findViewById(R.id.tvValueCount); + mSeekBarValues = (SeekBar) findViewById(R.id.seekbarValues); + mTvCount.setText("500"); + + mSeekBarValues.setProgress(500); + + mSeekBarValues.setOnSeekBarChangeListener(this); + + mChart = (LineChart) findViewById(R.id.chart1); + mChart.setDrawGridBackground(false); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // disable value highlighting + mChart.setHighlightEnabled(false); + + // enable touch gestures + mChart.setTouchEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(false); + + // enable/disable highlight indicators (the lines that indicate the + // highlighted Entry) + mChart.setHighlightIndicatorEnabled(false); + + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getAxisRight().setEnabled(false); + mChart.getXAxis().setDrawGridLines(false); + mChart.getXAxis().setDrawAxisLine(false); + + // dont forget to refresh the drawing + mChart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.line, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + mChart.resetAverage(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleFilled: { + + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawFilledEnabled()) + set.setDrawFilled(false); + else + set.setDrawFilled(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCircles: { + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawCirclesEnabled()) + set.setDrawCircles(false); + else + set.setDrawCircles(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (LineDataSet set : sets) { + if (set.isDrawCubicEnabled()) + set.setDrawCubic(false); + else + set.setDrawCubic(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleAdjustXLegend: { + XAxis xLabels = mChart.getXAxis(); + + if (xLabels.isAdjustXLabelsEnabled()) + xLabels.setAdjustXLabels(false); + else + xLabels.setAdjustXLabels(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleFilter: { + + // the angle of filtering is 35° + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + + // + // for(int i = 0; i < 10; i++) { + // mChart.addEntry(new Entry((float) (Math.random() * 100), + // i+2), 0); + // mChart.invalidate(); + // } + // + // Toast.makeText(getApplicationContext(), "valcount: " + + // mChart.getDataOriginal().getYValCount() + ", valsum: " + + // mChart.getDataOriginal().getYValueSum(), + // Toast.LENGTH_SHORT).show(); + // + break; + } + case R.id.actionSave: { + if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + + // mChart.saveToGallery("title"+System.currentTimeMillis()) + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + mTvCount.setText("" + (mSeekBarValues.getProgress())); + + setData(mSeekBarValues.getProgress(), 500f); + + // redraw + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + private void setData(int count, float range) { + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add((i) + ""); + } + + ArrayList yVals = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = (range + 1); + float val = (float) (Math.random() * mult) + 3;// + (float) + // ((mult * + // 0.1) / 10); + yVals.add(new Entry(val, i)); + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + + set1.setColor(Color.BLACK); + set1.setLineWidth(1f); + set1.setDrawValues(false); + set1.setDrawCircles(false); + + // create a data object with the datasets + LineData data = new LineData(xVals, set1); + + // set data + mChart.setData(data); + + // get the legend (only possible after setting data) + Legend l = mChart.getLegend(); + l.setEnabled(false); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 4e4aeeb674..d41335f7ff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -35,6 +35,7 @@ import com.xxmassdeveloper.mpchartexample.ListViewBarChartActivity; import com.xxmassdeveloper.mpchartexample.ListViewMultiChartActivity; import com.xxmassdeveloper.mpchartexample.MultiLineChartActivity; +import com.xxmassdeveloper.mpchartexample.PerformanceLineChart; import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; @@ -110,6 +111,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Dynamical data adding", "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); +// objects.add(new ContentItem( +// "Performance Line Chart", +// "Renders up to 3000 objects.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -219,6 +223,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; + case 22: + i = new Intent(this, PerformanceLineChart.class); + startActivity(i); + break; } overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index fd3e79432f..2b10d4db7c 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -37,6 +37,14 @@ dependencies { //compile 'com.nineoldandroids:library:2.4.+' } +android.libraryVariants.all { variant -> + def name = variant.buildType.name + def task = project.tasks.create "jar${name.capitalize()}", Jar + task.dependsOn variant.javaCompile + task.from variant.javaCompile.destinationDir + artifacts.add('archives', task); +} + task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index fdd0a03ae2..b5530d04c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -217,8 +217,21 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (mLogEnabled) - Log.i(LOG_TAG, "DrawTime: " + (System.currentTimeMillis() - starttime) + " ms"); +// if (mLogEnabled) + + long drawtime = (System.currentTimeMillis() - starttime); + draws++; + totaltime+=drawtime; + long average = totaltime / draws; + Log.i(LOG_TAG, "DrawTime: " + drawtime + " ms, average: " + average + " ms"); + } + + long draws = 0; + long totaltime = 0; + + public void resetAverage() { + draws = 0; + totaltime = 0; } protected void prepareValuePxMatrix() { From 68964e86830d951535cdc787ff0efe6b23336999 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 01:14:43 +0100 Subject: [PATCH 0171/1390] Update gradle and maven. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9d9ee00624..4b247652f9 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.4' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.5' } ``` @@ -138,7 +138,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.4 + v2.0.5 ``` From ec7130acb4ac3f9ea9d17820fb431eebf7157a42 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 01:22:44 +0100 Subject: [PATCH 0172/1390] Minor fixes. --- MPChartExample/AndroidManifest.xml | 2 +- MPChartExample/build.gradle | 4 +- .../mpchartexample/PerformanceLineChart.java | 151 ------------------ .../charting/charts/BarLineChartBase.java | 25 +-- .../mikephil/charting/data/LineData.java | 5 + 5 files changed, 15 insertions(+), 172 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 395d834f1d..c152c2e771 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.0.3" > sets = (ArrayList) mChart.getData() - .getDataSets(); - - for (LineDataSet set : sets) { - if (set.isDrawFilledEnabled()) - set.setDrawFilled(false); - else - set.setDrawFilled(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() - .getDataSets(); - - for (LineDataSet set : sets) { - if (set.isDrawCirclesEnabled()) - set.setDrawCircles(false); - else - set.setDrawCircles(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getData() - .getDataSets(); - - for (LineDataSet set : sets) { - if (set.isDrawCubicEnabled()) - set.setDrawCubic(false); - else - set.setDrawCubic(true); - } - mChart.invalidate(); - break; - } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000); - break; - } - case R.id.animateXY: { - mChart.animateXY(3000, 3000); - break; - } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - - // - // for(int i = 0; i < 10; i++) { - // mChart.addEntry(new Entry((float) (Math.random() * 100), - // i+2), 0); - // mChart.invalidate(); - // } - // - // Toast.makeText(getApplicationContext(), "valcount: " + - // mChart.getDataOriginal().getYValCount() + ", valsum: " + - // mChart.getDataOriginal().getYValueSum(), - // Toast.LENGTH_SHORT).show(); - // - break; - } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) - break; - } - } - return true; - } - @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b5530d04c4..4112d449b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -217,21 +217,10 @@ protected void onDraw(Canvas canvas) { canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); -// if (mLogEnabled) - - long drawtime = (System.currentTimeMillis() - starttime); - draws++; - totaltime+=drawtime; - long average = totaltime / draws; - Log.i(LOG_TAG, "DrawTime: " + drawtime + " ms, average: " + average + " ms"); - } - - long draws = 0; - long totaltime = 0; - - public void resetAverage() { - draws = 0; - totaltime = 0; + if (mLogEnabled) { + long drawtime = (System.currentTimeMillis() - starttime); + Log.i(LOG_TAG, "DrawTime: " + drawtime + " ms"); + } } protected void prepareValuePxMatrix() { @@ -620,11 +609,11 @@ public void setViewPortOffsets(final float left, final float top, final float right, final float bottom) { mCustomViewPortEnabled = true; - + post(new Runnable() { - + @Override - public void run() { + public void run() { mViewPortHandler.restrainViewPort(left, top, right, bottom); } }); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 5ee6fc702e..329b0c1cc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -3,6 +3,11 @@ import java.util.ArrayList; +/** + * Data object that encapsulates all data associated with a LineChart. + * + * @author Philipp Jahoda + */ public class LineData extends BarLineScatterCandleData { public LineData() { From b622ea5561f91dcf3bab4aa0bb834884a888f8ed Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 01:24:44 +0100 Subject: [PATCH 0173/1390] Update gradle and maven info. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4b247652f9..c5a5322942 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.5' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' } ``` @@ -138,7 +138,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.5 + v2.0.3 ``` From 33ebc9d19200c96e977db9fb17b1fc33c9ddcfe0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 10:04:57 +0100 Subject: [PATCH 0174/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c5a5322942..14e51c6395 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Questions & Issues If you are having questions or problems, feel free to contact me. Since I would very much like that other users of this library **can also benefit** from your question, I am asking you to contact me via e-mail **only as a last option**. Instead, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) From 6b57fa74d4f2c80d918e47a224155c45d8c1ef93 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 10:30:29 +0100 Subject: [PATCH 0175/1390] Update gradle, fixed issue #284. --- MPChartExample/AndroidManifest.xml | 4 +- MPChartExample/build.gradle | 6 +-- .../CubicLineChartActivity.java | 12 +++--- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/renderer/LineChartRenderer.java | 37 +++++++++++-------- 5 files changed, 34 insertions(+), 27 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index c152c2e771..3ee2b9e0bb 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="36" + android:versionName="2.1.2" > dataSets = new ArrayList(); - dataSets.add(set1); + set1.setFillColor(ColorTemplate.getHoloBlue()); // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(xVals, set1); data.setValueTypeface(tf); data.setValueTextSize(9f); data.setDrawValues(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index eff8b1371f..650916f613 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -62,7 +62,7 @@ public abstract class Chart entries float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - // get the color that is specified for this position from the - // DataSet - mRenderPaint.setColor(dataSet.getColor()); - float intensity = dataSet.getCubicIntensity(); // the path for the cubic-spline @@ -145,20 +141,26 @@ else if (j == points.size() - 1) { } } } - + // if filled is enabled, close the path if (dataSet.isDrawFilledEnabled()) { - drawCubicFill(dataSet, spline); - } else { - mRenderPaint.setStyle(Paint.Style.STROKE); - } - + + // create a new path, this is bad for performance + drawCubicFill(c, dataSet, new Path(spline), trans); + } + + mRenderPaint.setColor(dataSet.getColor()); + + mRenderPaint.setStyle(Paint.Style.STROKE); + trans.pathValueToPixel(spline); c.drawPath(spline, mRenderPaint); + + mRenderPaint.setPathEffect(null); } - protected void drawCubicFill(LineDataSet dataSet, Path spline) { + protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans) { float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), @@ -169,6 +171,15 @@ protected void drawCubicFill(LineDataSet dataSet, Path spline) { spline.close(); mRenderPaint.setStyle(Paint.Style.FILL); + + mRenderPaint.setColor(dataSet.getFillColor()); + // filled is drawn with less alpha + mRenderPaint.setAlpha(dataSet.getFillAlpha()); + + trans.pathValueToPixel(spline); + c.drawPath(spline, mRenderPaint); + + mRenderPaint.setAlpha(255); } protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entries) { @@ -225,10 +236,6 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList entries, Transformer trans) { - // mDrawCanvas.drawVertices(VertexMode.TRIANGLE_STRIP, - // valuePoints.length, valuePoints, 0, - // null, 0, null, 0, null, 0, 0, paint); - mRenderPaint.setStyle(Paint.Style.FILL); mRenderPaint.setColor(dataSet.getFillColor()); From 822e578f9bfda4ec67ff622b85b12efad02f3942 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 10:39:22 +0100 Subject: [PATCH 0176/1390] Removed logcat ouput. --- MPChartExample/AndroidManifest.xml | 2 +- MPChartExample/build.gradle | 4 ++-- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 3ee2b9e0bb..626e85c460 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.0.7" > Date: Sun, 1 Mar 2015 10:56:08 +0100 Subject: [PATCH 0177/1390] Update gradle and maven. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 14e51c6395..61f6db5621 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.3' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.7' } ``` @@ -139,7 +139,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.3 + v2.0.7 ``` From e0ede6054dc3038ebb3a700a8b0e9842cf796ce8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 11:42:46 +0100 Subject: [PATCH 0178/1390] Added horizontal barchart. --- screenshots/horizontal_barchart.jpg | Bin 0 -> 39571 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/horizontal_barchart.jpg diff --git a/screenshots/horizontal_barchart.jpg b/screenshots/horizontal_barchart.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eee2f70afd0d6de406b59daea3a7ded67a2228f8 GIT binary patch literal 39571 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 E0KFNCi2wiq literal 0 HcmV?d00001 From 233c44eb019dc8409baf2ab41787113b95e9c2b2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 11:44:18 +0100 Subject: [PATCH 0179/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 61f6db5621..d19b14fb98 100644 --- a/README.md +++ b/README.md @@ -79,17 +79,17 @@ Features - **LineChart (single DataSet)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/linechart.png) - - **BarChart2D (with legend, simple design)** + - **BarChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) - - **BarChart2D (grouped DataSets)** + - **BarChart (grouped DataSets)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) - - **BarChart2D** + - **Horizontal-BarChart** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/barchart2d_multi_dataset_date1.png) +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.jpg) - **PieChart (with selection, ...)** From edd513208b405006e7144a2a45b28bc02cc7e308 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 13:56:15 +0100 Subject: [PATCH 0180/1390] LineDataSet can now enable/disable the hole in circles. --- .../mpchartexample/LineChartActivity1.java | 5 ++- .../mikephil/charting/data/LineDataSet.java | 17 ++++++++- .../charting/renderer/LineChartRenderer.java | 38 +++++++++++-------- 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 023218ed75..3e4e3a868e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -312,7 +312,9 @@ private void setData(int count, float range) { set1.setColor(Color.BLACK); set1.setCircleColor(Color.BLACK); set1.setLineWidth(1f); - set1.setCircleSize(4f); + set1.setCircleSize(3f); + set1.setDrawCircleHole(false); + set1.setValueTextSize(9f); set1.setFillAlpha(65); set1.setFillColor(Color.BLACK); // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), @@ -323,7 +325,6 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); - data.setValueTextSize(10f); LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 60220a3ac5..82a14b49f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -14,7 +14,7 @@ public class LineDataSet extends LineRadarDataSet { /** arraylist representing all colors that are used for the circles */ private ArrayList mCircleColors = null; - + /** the radius of the circle-shaped value indicators */ private float mCircleSize = 8f; @@ -30,6 +30,8 @@ public class LineDataSet extends LineRadarDataSet { /** if true, cubic lines are drawn instead of linear */ private boolean mDrawCubic = false; + private boolean mDrawCircleHole = true; + public LineDataSet(ArrayList yVals, String label) { super(yVals, label); @@ -269,4 +271,17 @@ public void setCircleColor(int color) { public void resetCircleColors() { mCircleColors = new ArrayList(); } + + /** + * Set this to true to allow drawing a hole in each data circle. + * + * @param enabled + */ + public void setDrawCircleHole(boolean enabled) { + mDrawCircleHole = enabled; + } + + public boolean isDrawCircleHoleEnabled() { + return mDrawCircleHole; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index ab5fb328c7..b4f5c26ecc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -141,32 +141,35 @@ else if (j == points.size() - 1) { } } } - + // if filled is enabled, close the path if (dataSet.isDrawFilledEnabled()) { - + // create a new path, this is bad for performance drawCubicFill(c, dataSet, new Path(spline), trans); - } - + } + mRenderPaint.setColor(dataSet.getColor()); - + mRenderPaint.setStyle(Paint.Style.STROKE); - + trans.pathValueToPixel(spline); c.drawPath(spline, mRenderPaint); - + mRenderPaint.setPathEffect(null); } protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans) { - + float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo(dataSet.getYVals().get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())).getXIndex(), fillMin); + spline.lineTo( + dataSet.getYVals() + .get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())) + .getXIndex(), fillMin); spline.lineTo(mChart.getXChartMin(), fillMin); spline.close(); @@ -178,7 +181,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo trans.pathValueToPixel(spline); c.drawPath(spline, mRenderPaint); - + mRenderPaint.setAlpha(255); } @@ -325,12 +328,12 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; - + // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - + // make sure the values do not interfear with the circles int valOffset = (int) (dataSet.getCircleSize() * 1.75f); @@ -355,7 +358,8 @@ public void drawValues(Canvas c) { float val = entries.get(j / 2).getVal(); - c.drawText(dataSet.getValueFormatter().getFormattedValue(val), x, y - valOffset, + c.drawText(dataSet.getValueFormatter().getFormattedValue(val), x, + y - valOffset, mValuePaint); } } @@ -402,9 +406,11 @@ protected void drawCircles(Canvas c) { c.drawCircle(x, y, dataSet.getCircleSize(), mRenderPaint); - c.drawCircle(x, y, - dataSet.getCircleSize() / 2f, - mCirclePaintInner); + + if (dataSet.isDrawCircleHoleEnabled()) + c.drawCircle(x, y, + dataSet.getCircleSize() / 2f, + mCirclePaintInner); } } // else do nothing } From cbbddd3231c9ff7ff4663c4dfaef592bf5fb9719 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 1 Mar 2015 17:19:20 +0100 Subject: [PATCH 0181/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d19b14fb98..bd8b9df4b5 100644 --- a/README.md +++ b/README.md @@ -165,7 +165,7 @@ No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](ht License ======= -Copyright 2014 Philipp Jahoda +Copyright 2015 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From c739d6271397e9979cf633453df3ea35c6052e2d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Mar 2015 22:34:03 +0100 Subject: [PATCH 0182/1390] Performance improvements concerning LineChart, still bugs. --- MPChartExample/AndroidManifest.xml | 1 + .../layout/activity_performance_linechart.xml | 4 +- .../mpchartexample/PerformanceLineChart.java | 11 +- .../notimportant/MainActivity.java | 6 +- .../charting/buffer/AbstractBuffer.java | 50 +++++++ .../mikephil/charting/buffer/LineBuffer.java | 51 +++++++ .../charting/charts/BarLineChartBase.java | 73 ++++++---- .../mikephil/charting/charts/Chart.java | 45 +++--- .../mikephil/charting/charts/PieChart.java | 14 +- .../mikephil/charting/charts/RadarChart.java | 22 +-- .../mikephil/charting/data/DataSet.java | 8 +- .../mikephil/charting/data/LineDataSet.java | 8 +- .../listener/BarLineChartTouchListener.java | 12 +- .../charting/renderer/BarChartRenderer.java | 6 + .../renderer/CandleStickChartRenderer.java | 6 + .../renderer/CombinedChartRenderer.java | 15 ++ .../charting/renderer/DataRenderer.java | 6 + .../charting/renderer/LineChartRenderer.java | 129 +++++++++++++++--- .../charting/renderer/PieChartRenderer.java | 6 + .../charting/renderer/RadarChartRenderer.java | 6 + .../renderer/ScatterChartRenderer.java | 6 + .../charting/renderer/XAxisRenderer.java | 19 ++- 22 files changed, 396 insertions(+), 108 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 626e85c460..10da8bbc59 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -11,6 +11,7 @@ diff --git a/MPChartExample/res/layout/activity_performance_linechart.xml b/MPChartExample/res/layout/activity_performance_linechart.xml index b7aedf6dda..c107699d5a 100644 --- a/MPChartExample/res/layout/activity_performance_linechart.xml +++ b/MPChartExample/res/layout/activity_performance_linechart.xml @@ -19,12 +19,12 @@ android:layout_marginBottom="35dp" android:layout_toLeftOf="@+id/tvValueCount" android:layout_marginRight="5dp" - android:max="3000" + android:max="29000" android:paddingBottom="12dp" /> + */ +public abstract class AbstractBuffer { + + protected int index = 0; + public final float[] buffer; + + /** + * Initialization with buffer-size. + * + * @param size + */ + public AbstractBuffer(int size) { + index = 0; + buffer = new float[size]; + } + + /** + * Resets the buffer index to 0. + */ + public void reset() { + index = 0; + } + + /** + * Returns the size of the buffer array. + * + * @return + */ + public int size() { + return buffer.length; + } + + /** + * Builds up the buffer with the provided data and resets the buffer-index + * after feed-completion. + * + * @param entries + */ + public abstract void feed(ArrayList entries); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java new file mode 100644 index 0000000000..3bb57157b8 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -0,0 +1,51 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.Entry; + +import java.util.ArrayList; + +public class LineBuffer extends AbstractBuffer { + + public LineBuffer(int size) { + super(size); + } + + public void moveTo(float x, float y) { + + if (index != 0) + return; + + buffer[index++] = x; + buffer[index++] = y; + } + + public void lineTo(float x, float y) { + + if (index == 2) { + buffer[index++] = x; + buffer[index++] = y; + } else { + + float prevX = buffer[index - 2]; + float prevY = buffer[index - 1]; + buffer[index++] = prevX; + buffer[index++] = prevY; + buffer[index++] = x; + buffer[index++] = y; + } + } + + @Override + public void feed(ArrayList entries) { + moveTo(entries.get(0).getXIndex(), entries.get(0).getVal()); + + for (int i = 1; i < entries.size(); i++) { + + Entry e = entries.get(i); + lineTo(e.getXIndex(), e.getVal()); + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 4112d449b9..be09dd5b23 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -143,6 +143,10 @@ protected void init() { mGridBackgroundPaint.setColor(Color.rgb(240, 240, 240)); // light // grey } + + // for performance tracking + private long totalTime = 0; + private long drawCycles = 0; @Override protected void onDraw(Canvas canvas) { @@ -169,59 +173,70 @@ protected void onDraw(Canvas canvas) { calcModulus(); // execute all drawing commands - drawGridBackground(); + drawGridBackground(canvas); mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); // make sure the graph values and grid cannot be drawn outside the // content-rect - int clipRestoreCount = mDrawCanvas.save(); - mDrawCanvas.clipRect(mViewPortHandler.getContentRect()); + int clipRestoreCount = canvas.save(); + canvas.clipRect(mViewPortHandler.getContentRect()); - mXAxisRenderer.renderGridLines(mDrawCanvas); - mAxisRendererLeft.renderGridLines(mDrawCanvas); - mAxisRendererRight.renderGridLines(mDrawCanvas); + mXAxisRenderer.renderGridLines(canvas); + mAxisRendererLeft.renderGridLines(canvas); + mAxisRendererRight.renderGridLines(canvas); - mAxisRendererLeft.renderLimitLines(mDrawCanvas); - mAxisRendererRight.renderLimitLines(mDrawCanvas); - - mRenderer.drawData(mDrawCanvas); + mRenderer.drawData(canvas); + + mAxisRendererLeft.renderLimitLines(canvas); + mAxisRendererRight.renderLimitLines(canvas); // if highlighting is enabled if (mHighlightEnabled && mHighLightIndicatorEnabled && valuesToHighlight()) - mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHightlight); // Removes clipping rectangle - mDrawCanvas.restoreToCount(clipRestoreCount); + canvas.restoreToCount(clipRestoreCount); - mRenderer.drawExtras(mDrawCanvas); + mRenderer.drawExtras(canvas); - mXAxisRenderer.renderAxisLabels(mDrawCanvas); - mXAxisRenderer.renderAxisLine(mDrawCanvas); + mXAxisRenderer.renderAxisLabels(canvas); + mXAxisRenderer.renderAxisLine(canvas); - mAxisRendererLeft.renderAxisLabels(mDrawCanvas); - mAxisRendererLeft.renderAxisLine(mDrawCanvas); + mAxisRendererLeft.renderAxisLabels(canvas); + mAxisRendererLeft.renderAxisLine(canvas); - mAxisRendererRight.renderAxisLabels(mDrawCanvas); - mAxisRendererRight.renderAxisLine(mDrawCanvas); + mAxisRendererRight.renderAxisLabels(canvas); + mAxisRendererRight.renderAxisLine(canvas); - mRenderer.drawValues(mDrawCanvas); + mRenderer.drawValues(canvas); - mLegendRenderer.renderLegend(mDrawCanvas, mLegend); + mLegendRenderer.renderLegend(canvas, mLegend); // drawLegend(); - drawMarkers(); + drawMarkers(canvas); - drawDescription(); + drawDescription(canvas); - canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); +// canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (mLogEnabled) { + if (true) { long drawtime = (System.currentTimeMillis() - starttime); - Log.i(LOG_TAG, "DrawTime: " + drawtime + " ms"); + totalTime += drawtime; + drawCycles += 1; + long average = totalTime / drawCycles; + Log.i(LOG_TAG, "Drawtime: " + drawtime + " ms, average: " + average + " ms, cycles: " + drawCycles); } } + + /** + * RESET PERFORMANCE TRACKING FIELDS + */ + public void resetTracking() { + totalTime = 0; + drawCycles = 0; + } protected void prepareValuePxMatrix() { @@ -252,6 +267,8 @@ public void notifyDataSetChanged() { if (mLogEnabled) Log.i(LOG_TAG, "Preparing..."); } + + mRenderer.initBuffers(); calcMinMax(); @@ -429,13 +446,13 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { /** * draws the grid background */ - protected void drawGridBackground() { + protected void drawGridBackground(Canvas c) { if (!mDrawGridBackground) return; // draw the grid background - mDrawCanvas.drawRect(mViewPortHandler.getContentRect(), mGridBackgroundPaint); + c.drawRect(mViewPortHandler.getContentRect(), mGridBackgroundPaint); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index eff8b1371f..9daa7a9984 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -74,7 +74,7 @@ public abstract class Chart 0 && h > 0 && w < 10000 && h < 10000) { // create a new bitmap with the new dimensions mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); - mDrawCanvas = new Canvas(mDrawBitmap); +// mDrawCanvas = new Canvas(mDrawBitmap); mViewPortHandler.setChartDimens(w, h); if (mLogEnabled) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 858ac2d984..dccc4e6d8d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -94,19 +94,19 @@ protected void onDraw(Canvas canvas) { return; if (mHighlightEnabled && valuesToHighlight()) - mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHightlight); - mRenderer.drawData(mDrawCanvas); + mRenderer.drawData(canvas); - mRenderer.drawExtras(mDrawCanvas); + mRenderer.drawExtras(canvas); - mRenderer.drawValues(mDrawCanvas); + mRenderer.drawValues(canvas); - mLegendRenderer.renderLegend(mDrawCanvas, mLegend); + mLegendRenderer.renderLegend(canvas, mLegend); - drawDescription(); + drawDescription(canvas); - canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); +// canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index c2c02c4287..e35ad60910 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -153,29 +153,29 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - mXAxisRenderer.renderAxisLabels(mDrawCanvas); + mXAxisRenderer.renderAxisLabels(canvas); if (mDrawWeb) - mRenderer.drawExtras(mDrawCanvas); + mRenderer.drawExtras(canvas); - mYAxisRenderer.renderLimitLines(mDrawCanvas); + mYAxisRenderer.renderLimitLines(canvas); - mRenderer.drawData(mDrawCanvas); + mRenderer.drawData(canvas); if (mHighlightEnabled && valuesToHighlight()) - mRenderer.drawHighlighted(mDrawCanvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHightlight); - mYAxisRenderer.renderAxisLabels(mDrawCanvas); + mYAxisRenderer.renderAxisLabels(canvas); - mRenderer.drawValues(mDrawCanvas); + mRenderer.drawValues(canvas); - mLegendRenderer.renderLegend(mDrawCanvas, mLegend); + mLegendRenderer.renderLegend(canvas, mLegend); - drawDescription(); + drawDescription(canvas); - drawMarkers(); + drawMarkers(canvas); - canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); +// canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 1e64a497e0..69c2058187 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -267,13 +267,13 @@ public float getYMax() { } /** - * returns the type of the DataSet, specified via constructor + * Returns the number of entries this DataSet holds. * * @return */ - // public int getType() { - // return mType; - // } + public int getValueCount() { + return mYVals.size(); + } /** * The xIndex of an Entry object is provided. This method returns the actual diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 82a14b49f4..b52a08a4ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -110,10 +110,12 @@ public float getCircleSize() { } /** - * Enables the line to be drawn in dashed mode, e.g. like this "- - - - - -" + * Enables the line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. * * @param lineLength the length of the line pieces - * @param spaceLength the length of space inbetween the pieces + * @param spaceLength the length of space in between the pieces * @param phase offset, in degrees (normally, use 0) */ public void enableDashedLine(float lineLength, float spaceLength, float phase) { @@ -280,7 +282,7 @@ public void resetCircleColors() { public void setDrawCircleHole(boolean enabled) { mDrawCircleHole = enabled; } - + public boolean isDrawCircleHoleEnabled() { return mDrawCircleHole; } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index f199619c9b..a96cc7f826 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -28,6 +28,8 @@ public class BarLineChartTouchListener>>> extends SimpleOnGestureListener implements OnTouchListener { + // private static final long REFRESH_MILLIS = 20; + /** the original touch-matrix from the chart */ private Matrix mMatrix = new Matrix(); @@ -166,11 +168,19 @@ public boolean onTouch(View v, MotionEvent event) { } // Perform the transformation, update the chart - mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); +// if (needsRefresh()) + mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); return true; // indicate event was handled } +// private boolean needsRefresh() { +// if (System.currentTimeMillis() - mChart.getLastDrawMillis() > REFRESH_MILLIS) { +// return true; +// } else +// return false; +// } + /** * ################ ################ ################ ################ */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 8db89a2389..6fd6862e97 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -40,6 +40,12 @@ public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, // set alpha after color mHighlightPaint.setAlpha(120); } + + @Override + public void initBuffers() { + // TODO Auto-generated method stub + + } @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 03b367e3f9..d35379fafe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -24,6 +24,12 @@ public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator super(animator, viewPortHandler); mChart = chart; } + + @Override + public void initBuffers() { + // TODO Auto-generated method stub + + } @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 95cec1f090..e6b6e41387 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -30,6 +30,21 @@ public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, if (chart.getCandleData() != null) mCandleRenderer = new CandleStickChartRenderer(chart, animator, viewPortHandler); } + + @Override + public void initBuffers() { + if (mBarRenderer != null) + mBarRenderer.initBuffers(); + + if (mCandleRenderer != null) + mCandleRenderer.initBuffers(); + + if (mLineRenderer != null) + mLineRenderer.initBuffers(); + + if (mScatterRenderer != null) + mScatterRenderer.initBuffers(); + } @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 5cbf402976..5da2902e47 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -21,6 +21,8 @@ public abstract class DataRenderer extends Renderer { /** paint used for highlighting values */ protected Paint mHighlightPaint; + + protected Paint mDrawPaint; /** * paint object for drawing values (text representing values of chart @@ -34,6 +36,8 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRenderPaint.setStyle(Style.FILL); + + mDrawPaint = new Paint(Paint.DITHER_FLAG); mValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mValuePaint.setColor(Color.rgb(63, 63, 63)); @@ -78,6 +82,8 @@ protected void applyValueTextStyle(DataSet set) { mValuePaint.setTypeface(set.getValueTypeface()); mValuePaint.setTextSize(set.getValueTextSize()); } + + public abstract void initBuffers(); public abstract void drawData(Canvas c); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index b4f5c26ecc..e1bb1f33af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -7,6 +7,7 @@ import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.LineBuffer; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -22,6 +23,21 @@ public class LineChartRenderer extends DataRenderer { /** paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; + // + // /** + // * Bitmap object used for drawing the paths (otherwise they are too long + // if + // * rendered directly on the canvas) + // */ + // protected Bitmap mPathBitmap; + // + // /** + // * on this canvas, the paths are rendered, it is initialized with the + // * pathBitmap + // */ + // protected Canvas mPathCanvas; + + protected LineBuffer[] mLineBuffers; public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -33,9 +49,51 @@ public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, mCirclePaintInner.setColor(Color.WHITE); } + @Override + public void initBuffers() { + + LineData lineData = mChart.getLineData(); + mLineBuffers = new LineBuffer[lineData.getDataSetCount()]; + + for (int i = 0; i < mLineBuffers.length; i++) { + LineDataSet set = lineData.getDataSetByIndex(i); + mLineBuffers[i] = new LineBuffer(getBufferSize(set)); + } + } + + /** + * Returns the correct buffer size depending on the DataSet setup. + * + * @param set + * @return + */ + private int getBufferSize(LineDataSet set) { + if (set.isDrawFilledEnabled()) { + if (set.isDrawCubicEnabled()) { + return 0; + } else { + return set.getValueCount() * 4 - 4; + } + } else { + if (set.isDrawCubicEnabled()) { + return 0; + } else { + return set.getValueCount() * 4 - 4; + } + } + } + @Override public void drawData(Canvas c) { + // if (mPathBitmap == null) { + // mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.mChartWidth, + // (int) mViewPortHandler.mChartHeight, Config.ARGB_4444); + // mPathCanvas = new Canvas(mPathBitmap); + // } + // + // mPathBitmap.eraseColor(Color.TRANSPARENT); + LineData lineData = mChart.getLineData(); for (LineDataSet set : lineData.getDataSets()) { @@ -43,6 +101,8 @@ public void drawData(Canvas c) { if (set.isVisible()) drawDataSet(c, set); } + + // c.drawBitmap(mPathBitmap, 0, 0, mDrawPaint); } /** @@ -93,6 +153,15 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + int minx = (int) + trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + int maxx = (int) + trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + 0).x + 2; + + if (maxx > entries.size()) + maxx = entries.size(); + float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -102,7 +171,9 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Path spline = new Path(); ArrayList points = new ArrayList(); - for (Entry e : entries) { + for (int i = minx; i < maxx; i++) { + + Entry e = entries.get(i); if (e != null) points.add(new CPoint(e.getXIndex(), e.getVal())); } @@ -146,7 +217,7 @@ else if (j == points.size() - 1) { if (dataSet.isDrawFilledEnabled()) { // create a new path, this is bad for performance - drawCubicFill(c, dataSet, new Path(spline), trans); + drawCubicFill(c, dataSet, new Path(spline), trans, minx, maxx); } mRenderPaint.setColor(dataSet.getColor()); @@ -160,17 +231,15 @@ else if (j == points.size() - 1) { mRenderPaint.setPathEffect(null); } - protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans) { + protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans, + int from, int to) { float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo( - dataSet.getYVals() - .get((int) ((dataSet.getYVals().size() - 1) * mAnimator.getPhaseX())) - .getXIndex(), fillMin); - spline.lineTo(mChart.getXChartMin(), fillMin); + spline.lineTo(to, fillMin); + spline.lineTo(from, fillMin); spline.close(); mRenderPaint.setStyle(Paint.Style.FILL); @@ -187,6 +256,8 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entries) { + int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseX = mAnimator.getPhaseX(); @@ -220,12 +291,25 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie } else { // only one color per dataset + int minx = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + int maxx = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; + + int range = (maxx - minx) * 4; + int from = minx * 4; + mRenderPaint.setColor(dataSet.getColor()); - Path line = generateLinePath(entries); - trans.pathValueToPixel(line); + LineBuffer buffer = mLineBuffers[dataSetIndex]; + buffer.feed(entries); + + trans.pointValuesToPixel(buffer.buffer); - c.drawPath(line, mRenderPaint); + c.drawLines(buffer.buffer, from, range, mRenderPaint); + + // Path line = generateLinePath(entries); + // + // trans.pathValueToPixel(line); + // c.drawPath(line, mRenderPaint); } mRenderPaint.setPathEffect(null); @@ -247,10 +331,16 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en // mRenderPaint.setShader(dataSet.getShader()); + int minx = (int) + trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + int maxx = (int) + trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + 0).x + 1; + Path filled = generateFilledPath( entries, mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getLineData(), - mChart.getYChartMax(), mChart.getYChartMin())); + mChart.getYChartMax(), mChart.getYChartMin()), minx, maxx); trans.pathValueToPixel(filled); @@ -267,24 +357,27 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en * @param entries * @return */ - private Path generateFilledPath(ArrayList entries, float fillMin) { + private Path generateFilledPath(ArrayList entries, float fillMin, int from, int to) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); Path filled = new Path(); - filled.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); + filled.moveTo(entries.get(from).getXIndex(), entries.get(from).getVal() * phaseY); + + if (to >= entries.size()) + to = entries.size() - 1; // create a new path - for (int x = 1; x < entries.size() * phaseX; x++) { + for (int x = from + 1; x <= to * phaseX; x++) { Entry e = entries.get(x); filled.lineTo(e.getXIndex(), e.getVal() * phaseY); } // close up - filled.lineTo(entries.get((int) ((entries.size() - 1) * phaseX)).getXIndex(), fillMin); - filled.lineTo(entries.get(0).getXIndex(), fillMin); + filled.lineTo(entries.get((int) (to * phaseX)).getXIndex(), fillMin); + filled.lineTo(entries.get(from).getXIndex(), fillMin); filled.close(); return filled; @@ -406,7 +499,7 @@ protected void drawCircles(Canvas c) { c.drawCircle(x, y, dataSet.getCircleSize(), mRenderPaint); - + if (dataSet.isDrawCircleHoleEnabled()) c.drawCircle(x, y, dataSet.getCircleSize() / 2f, diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 27a934d57d..696d0cd7db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -59,6 +59,12 @@ public Paint getPaintHole() { public Paint getPaintCenterText() { return mCenterTextPaint; } + + @Override + public void initBuffers() { + // TODO Auto-generated method stub + + } @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 281f553d71..9107fc5e99 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -42,6 +42,12 @@ public Paint getWebPaint() { return mWebPaint; } + @Override + public void initBuffers() { + // TODO Auto-generated method stub + + } + @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 88b353a6a4..43a5aa738b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -24,6 +24,12 @@ public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, super(animator, viewPortHandler); mChart = chart; } + + @Override + public void initBuffers() { + // TODO Auto-generated method stub + + } @Override public void drawData(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index a559a298f0..b800e7353e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Align; +import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -27,7 +28,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t } public void computeAxis(float xValAverageLength, ArrayList xValues) { - + mAxisPaint.setTypeface(mXAxis.getTypeface()); mAxisPaint.setTextSize(mXAxis.getTextSize()); @@ -118,7 +119,13 @@ protected void drawLabels(Canvas c, float pos) { 0f, 0f }; - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + int minx = (int) + mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + int maxx = (int) + mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + 0).x; + + for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { position[0] = i; @@ -162,11 +169,17 @@ public void renderGridLines(Canvas c) { float[] position = new float[] { 0f, 0f }; + + int minx = (int) + mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + int maxx = (int) + mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + 0).x; mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { position[0] = i; From 4d223ba624049df95024eddb8b74c2bc937b874f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 5 Mar 2015 17:49:35 +0100 Subject: [PATCH 0183/1390] Performance improvements concerning bar- and linechart. --- .../res/layout/activity_barchart.xml | 2 +- .../mpchartexample/LineChartActivity2.java | 1 + .../charting/charts/BarLineChartBase.java | 16 ++++---- .../charting/charts/CombinedChart.java | 1 + .../mikephil/charting/components/YAxis.java | 5 ++- .../charting/renderer/BarChartRenderer.java | 31 +++++++--------- .../charting/renderer/DataRenderer.java | 22 +++++++++-- .../charting/renderer/LineChartRenderer.java | 37 ++++--------------- .../mikephil/charting/renderer/Renderer.java | 17 +++++++++ .../charting/renderer/XAxisRenderer.java | 10 +++-- .../renderer/XAxisRendererBarChart.java | 14 ++++++- 11 files changed, 90 insertions(+), 66 deletions(-) diff --git a/MPChartExample/res/layout/activity_barchart.xml b/MPChartExample/res/layout/activity_barchart.xml index f140d6e78c..7cd77962d6 100644 --- a/MPChartExample/res/layout/activity_barchart.xml +++ b/MPChartExample/res/layout/activity_barchart.xml @@ -30,7 +30,7 @@ android:layout_marginBottom="35dp" android:layout_toLeftOf="@+id/tvXMax" android:layout_marginRight="5dp" - android:max="500" + android:max="2000" android:paddingBottom="12dp" /> entries = dataSet.getYVals(); // do the drawing - for (int j = 0; j < dataSet.getEntryCount() * mAnimator.getPhaseX(); j++) { + for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { BarEntry e = entries.get(j); + // check bounds + if (!fitsBounds(((float) e.getXIndex()) * multi, mMinX - multi, mMaxX + multi)) + continue; + // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + j * (mChart.getBarData().getDataSetCount() - 1) + index + float x = e.getXIndex() + j * (step - 1) + index + space * j + space / 2f; float y = e.getVal(); @@ -88,13 +95,6 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { prepareBar(x, y, dataSet.getBarSpace(), trans); - // avoid drawing outofbounds values - if (!mViewPortHandler.isInBoundsRight(mBarRect.left)) - break; - - if (!mViewPortHandler.isInBoundsLeft(mBarRect.right)) - continue; - // if drawing the bar shadow is enabled if (mChart.isDrawBarShadowEnabled()) { mRenderPaint.setColor(dataSet.getBarShadowColor()); @@ -150,10 +150,6 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { c.drawRect(mBarRect, mRenderPaint); } } - - // avoid drawing outofbounds values - if (!mViewPortHandler.isInBoundsRight(mBarRect.left)) - break; } } } @@ -196,7 +192,8 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { * @param from * @param trans */ - protected void prepareBarHighlight(float x, float y, float barspace, float from, Transformer trans) { + protected void prepareBarHighlight(float x, float y, float barspace, float from, + Transformer trans) { float barWidth = 0.5f; @@ -386,7 +383,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { + groupspace * index; float y = isStack ? e.getVals()[h.getStackIndex()] + e.getBelowSum(h.getStackIndex()) : e.getVal(); - + // this is where the bar starts float from = isStack ? e.getBelowSum(h.getStackIndex()) : 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 5da2902e47..0f556c0d2f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; public abstract class DataRenderer extends Renderer { @@ -21,9 +22,13 @@ public abstract class DataRenderer extends Renderer { /** paint used for highlighting values */ protected Paint mHighlightPaint; - + protected Paint mDrawPaint; + protected int mMinX = 0; + + protected int mMaxX = 0; + /** * paint object for drawing values (text representing values of chart * entries) @@ -36,7 +41,7 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { mRenderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mRenderPaint.setStyle(Style.FILL); - + mDrawPaint = new Paint(Paint.DITHER_FLAG); mValuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -82,7 +87,18 @@ protected void applyValueTextStyle(DataSet set) { mValuePaint.setTypeface(set.getValueTypeface()); mValuePaint.setTextSize(set.getValueTextSize()); } - + + /** + * Calculates the minimum and maximum x-value the chart can currently + * display (with the given zoom level). + * + * @param trans + */ + protected void calcXBounds(Transformer trans) { + mMinX = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + mMaxX = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; + } + public abstract void initBuffers(); public abstract void drawData(Canvas c); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index e1bb1f33af..cf957a8d2b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -86,14 +86,6 @@ private int getBufferSize(LineDataSet set) { @Override public void drawData(Canvas c) { - // if (mPathBitmap == null) { - // mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.mChartWidth, - // (int) mViewPortHandler.mChartHeight, Config.ARGB_4444); - // mPathCanvas = new Canvas(mPathBitmap); - // } - // - // mPathBitmap.eraseColor(Color.TRANSPARENT); - LineData lineData = mChart.getLineData(); for (LineDataSet set : lineData.getDataSets()) { @@ -101,8 +93,6 @@ public void drawData(Canvas c) { if (set.isVisible()) drawDataSet(c, set); } - - // c.drawBitmap(mPathBitmap, 0, 0, mDrawPaint); } /** @@ -133,6 +123,8 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { if (entries.size() < 1) return; + + calcXBounds(mChart.getTransformer(dataSet.getAxisDependency())); mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); @@ -153,11 +145,8 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - int minx = (int) - trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - int maxx = (int) - trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x + 2; + int minx = mMinX; + int maxx = mMaxX + 2; if (maxx > entries.size()) maxx = entries.size(); @@ -291,11 +280,8 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie } else { // only one color per dataset - int minx = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - int maxx = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; - - int range = (maxx - minx) * 4; - int from = minx * 4; + int range = (mMaxX - mMinX) * 4; + int from = mMinX * 4; mRenderPaint.setColor(dataSet.getColor()); @@ -329,18 +315,10 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en // filled is drawn with less alpha mRenderPaint.setAlpha(dataSet.getFillAlpha()); - // mRenderPaint.setShader(dataSet.getShader()); - - int minx = (int) - trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - int maxx = (int) - trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x + 1; - Path filled = generateFilledPath( entries, mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getLineData(), - mChart.getYChartMax(), mChart.getYChartMin()), minx, maxx); + mChart.getYChartMax(), mChart.getYChartMin()), mMinX, mMaxX + 1); trans.pathValueToPixel(filled); @@ -348,7 +326,6 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en // restore alpha mRenderPaint.setAlpha(255); - // mRenderPaint.setShader(null); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index a76bea0811..c42268a4cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -16,4 +16,21 @@ public abstract class Renderer { public Renderer(ViewPortHandler viewPortHandler) { this.mViewPortHandler = viewPortHandler; } + + /** + * Returns true if the specified value fits in between the provided min + * and max bounds, false if not. + * + * @param val + * @param min + * @param max + * @return + */ + protected boolean fitsBounds(float val, float min, float max) { + + if (val < min || val > max) + return false; + else + return true; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index b800e7353e..1c0fab5855 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -4,7 +4,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Align; -import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -123,10 +122,13 @@ protected void drawLabels(Canvas c, float pos) { mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; int maxx = (int) mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x; + 0).x + 1; for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { + if (!fitsBounds(i, minx, maxx)) + continue; + position[0] = i; mTrans.pointValuesToPixel(position); @@ -169,12 +171,12 @@ public void renderGridLines(Canvas c) { float[] position = new float[] { 0f, 0f }; - + int minx = (int) mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; int maxx = (int) mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x; + 0).x + 1; mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 8960ab3eb2..915f48064b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.util.Log; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; @@ -35,8 +36,17 @@ protected void drawLabels(Canvas c, float pos) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); + float div = (float) step + (step > 1 ? bd.getGroupSpace() : 0f); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + float min = (float) (mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x) + / div; + float max = (float) (mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x) + / div; + + for (int i = (int) min; i < max; i += mXAxis.mAxisLabelModulus) { + + if (!fitsBounds(i, min - 1f, max + 0.5f)) + continue; position[0] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; @@ -86,7 +96,7 @@ public void renderGridLines(Canvas c) { float[] position = new float[] { 0f, 0f }; - + mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); From 6020ed39eeb8dd2950c3df98e6de0478d2dd632b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 5 Mar 2015 17:50:52 +0100 Subject: [PATCH 0184/1390] Log fix. --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 10d860422c..860f086758 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -221,7 +221,7 @@ protected void onDraw(Canvas canvas) { // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (true) { + if (mLogEnabled) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; drawCycles += 1; From 80ebcb7ab6b02dd0f1efc8edd077a21eed9a4227 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 5 Mar 2015 23:06:23 +0100 Subject: [PATCH 0185/1390] Improved CandleStickChart performance. --- .../res/layout/activity_barchart.xml | 2 +- .../res/layout/activity_candlechart.xml | 2 +- .../BarChartActivityMultiDataset.java | 8 +- .../CandleStickChartActivity.java | 6 +- .../charting/buffer/CandleBodyBuffer.java | 39 +++++ .../charting/buffer/CandleShadowBuffer.java | 33 ++++ .../charting/charts/BarLineChartBase.java | 2 +- .../renderer/CandleStickChartRenderer.java | 159 ++++++++++-------- .../charting/renderer/XAxisRenderer.java | 3 + 9 files changed, 171 insertions(+), 83 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java diff --git a/MPChartExample/res/layout/activity_barchart.xml b/MPChartExample/res/layout/activity_barchart.xml index 7cd77962d6..83c812d93e 100644 --- a/MPChartExample/res/layout/activity_barchart.xml +++ b/MPChartExample/res/layout/activity_barchart.xml @@ -30,7 +30,7 @@ android:layout_marginBottom="35dp" android:layout_toLeftOf="@+id/tvXMax" android:layout_marginRight="5dp" - android:max="2000" + android:max="1500" android:paddingBottom="12dp" /> xVals = new ArrayList(); @@ -194,7 +194,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); - float mult = mSeekBarY.getProgress() * 10000000f; + float mult = mSeekBarY.getProgress() * 1000f; for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mult) + 3; @@ -227,8 +227,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set3); BarData data = new BarData(xVals, dataSets); - data.setValueFormatter(new LargeValueFormatter()); - +// data.setValueFormatter(new LargeValueFormatter()); + // add space between the dataset groups in percent of bar-width data.setGroupSpace(80f); data.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 420a04d107..c7f1def9e3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -74,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { // rightAxis.setStartAtZero(false); // setting data - mSeekBarX.setProgress(15); + mSeekBarX.setProgress(40); mSeekBarY.setProgress(100); mChart.getLegend().setEnabled(false); @@ -161,10 +161,12 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - int prog = (mSeekBarX.getProgress() + 1) * 2; + int prog = (mSeekBarX.getProgress() + 1); tvX.setText("" + prog); tvY.setText("" + (mSeekBarY.getProgress())); + + mChart.resetTracking(); ArrayList yVals1 = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java new file mode 100644 index 0000000000..0ffb08fed5 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java @@ -0,0 +1,39 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.CandleEntry; + +import java.util.ArrayList; + +public class CandleBodyBuffer extends AbstractBuffer { + + private float mBodySpace = 0f; + + public CandleBodyBuffer(int size) { + super(size); + } + + public void setBodySpace(float bodySpace) { + this.mBodySpace = bodySpace; + } + + public void addBody(float left, float top, float right, float bottom) { + + buffer[index++] = left; + buffer[index++] = top; + buffer[index++] = right; + buffer[index++] = bottom; + } + + @Override + public void feed(ArrayList entries) { + + for (int i = 0; i < entries.size(); i++) { + + CandleEntry e = entries.get(i); + addBody(e.getXIndex() - 0.5f + mBodySpace, e.getClose(), e.getXIndex() + 0.5f - mBodySpace, e.getOpen()); + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java new file mode 100644 index 0000000000..52e6011771 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java @@ -0,0 +1,33 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.CandleEntry; + +import java.util.ArrayList; + +public class CandleShadowBuffer extends AbstractBuffer { + + public CandleShadowBuffer(int size) { + super(size); + } + + public void addShadow(float x1, float y1, float x2, float y2) { + + buffer[index++] = x1; + buffer[index++] = y1; + buffer[index++] = x2; + buffer[index++] = y2; + } + + @Override + public void feed(ArrayList entries) { + + for (int i = 0; i < entries.size(); i++) { + + CandleEntry e = entries.get(i); + addShadow(e.getXIndex(), e.getHigh(), e.getXIndex(), e.getLow()); + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 860f086758..10d860422c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -221,7 +221,7 @@ protected void onDraw(Canvas canvas) { // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (mLogEnabled) { + if (true) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; drawCycles += 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index d35379fafe..eaac26aaf2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -5,6 +5,8 @@ import android.graphics.Paint; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.CandleBodyBuffer; +import com.github.mikephil.charting.buffer.CandleShadowBuffer; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; @@ -18,6 +20,9 @@ public class CandleStickChartRenderer extends DataRenderer { protected CandleDataProvider mChart; + + private CandleShadowBuffer[] mShadowBuffers; + private CandleBodyBuffer[] mBodyBuffers; public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -27,8 +32,15 @@ public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator @Override public void initBuffers() { - // TODO Auto-generated method stub - + CandleData candleData = mChart.getCandleData(); + mShadowBuffers = new CandleShadowBuffer[candleData.getDataSetCount()]; + mBodyBuffers = new CandleBodyBuffer[candleData.getDataSetCount()]; + + for (int i = 0; i < mShadowBuffers.length; i++) { + CandleDataSet set = candleData.getDataSetByIndex(i); + mShadowBuffers[i] = new CandleShadowBuffer(set.getValueCount() * 4); + mBodyBuffers[i] = new CandleBodyBuffer(set.getValueCount() * 4); + } } @Override @@ -44,53 +56,52 @@ public void drawData(Canvas c) { } protected void drawDataSet(Canvas c, CandleDataSet dataSet) { - - // pre allocate - float[] shadowPoints = new float[4]; - float[] bodyPoints = new float[4]; + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + calcXBounds(trans); + + int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet); ArrayList entries = dataSet.getYVals(); + + // draw the shadow + int range = (mMaxX - mMinX) * 4; + int from = mMinX * 4; + + CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex]; + shadowBuffer.feed(entries); + trans.pointValuesToPixel(shadowBuffer.buffer); + + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setColor(dataSet.getColor()); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); - for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { + c.drawLines(shadowBuffer.buffer, from, range, mRenderPaint); + + CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; + bodyBuffer.setBodySpace(dataSet.getBodySpace()); + bodyBuffer.feed(entries); + + trans.pointValuesToPixel(bodyBuffer.buffer); + + for (int j = 0; j < bodyBuffer.size(); j+=4) { + + // get the entry + CandleEntry e = entries.get(j / 4); + + if (!fitsBounds(e.getXIndex(), mMinX, mMaxX)) + continue; // get the color that is specified for this position from // the DataSet, this will reuse colors, if the index is out // of bounds mRenderPaint.setColor(dataSet.getColor(j)); - // get the entry - CandleEntry e = entries.get(j); - - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - - // transform the entries values for shadow and body - transformShadow(shadowPoints, e, trans); - transformBody(bodyPoints, e, dataSet.getBodySpace(), trans); - - float xShadow = shadowPoints[0]; - float leftBody = bodyPoints[0]; - float rightBody = bodyPoints[2]; - - float high = shadowPoints[1]; - float low = shadowPoints[3]; - - float open = bodyPoints[1]; - float close = bodyPoints[3]; - - if (!mViewPortHandler.isInBoundsRight(leftBody)) - break; - - // make sure the lines don't do shitty things outside - // bounds - if (j != 0 && !mViewPortHandler.isInBoundsLeft(rightBody) - && !mViewPortHandler.isInBoundsTop(low) - && !mViewPortHandler.isInBoundsBottom(high)) - continue; - - // draw the shadow - c.drawLine(xShadow, low, xShadow, high, mRenderPaint); + float leftBody = bodyBuffer.buffer[j]; + float open = bodyBuffer.buffer[j + 1]; + float rightBody = bodyBuffer.buffer[j + 2]; + float close = bodyBuffer.buffer[j + 3]; // decide weather the body is hollow or filled if (open > close) { @@ -108,42 +119,42 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { } } - /** - * Transforms the values of an entry in order to draw the candle-body. - * - * @param bodyPoints - * @param e - * @param bodySpace - */ - private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace, Transformer trans) { - - float phase = mAnimator.getPhaseY(); - - bodyPoints[0] = e.getXIndex() - 0.5f + bodySpace; - bodyPoints[1] = e.getClose() * phase; - bodyPoints[2] = e.getXIndex() + 0.5f - bodySpace; - bodyPoints[3] = e.getOpen() * phase; - - trans.pointValuesToPixel(bodyPoints); - } - - /** - * Transforms the values of an entry in order to draw the candle-shadow. - * - * @param shadowPoints - * @param e - */ - private void transformShadow(float[] shadowPoints, CandleEntry e, Transformer trans) { - - float phase = mAnimator.getPhaseY(); - - shadowPoints[0] = e.getXIndex(); - shadowPoints[1] = e.getHigh() * phase; - shadowPoints[2] = e.getXIndex(); - shadowPoints[3] = e.getLow() * phase; - - trans.pointValuesToPixel(shadowPoints); - } +// /** +// * Transforms the values of an entry in order to draw the candle-body. +// * +// * @param bodyPoints +// * @param e +// * @param bodySpace +// */ +// private void transformBody(float[] bodyPoints, CandleEntry e, float bodySpace, Transformer trans) { +// +// float phase = mAnimator.getPhaseY(); +// +// bodyPoints[0] = e.getXIndex() - 0.5f + bodySpace; +// bodyPoints[1] = e.getClose() * phase; +// bodyPoints[2] = e.getXIndex() + 0.5f - bodySpace; +// bodyPoints[3] = e.getOpen() * phase; +// +// trans.pointValuesToPixel(bodyPoints); +// } +// +// /** +// * Transforms the values of an entry in order to draw the candle-shadow. +// * +// * @param shadowPoints +// * @param e +// */ +// private void transformShadow(float[] shadowPoints, CandleEntry e, Transformer trans) { +// +// float phase = mAnimator.getPhaseY(); +// +// shadowPoints[0] = e.getXIndex(); +// shadowPoints[1] = e.getHigh() * phase; +// shadowPoints[2] = e.getXIndex(); +// shadowPoints[3] = e.getLow() * phase; +// +// trans.pointValuesToPixel(shadowPoints); +// } @Override public void drawValues(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 1c0fab5855..43b408e13e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -183,6 +183,9 @@ public void renderGridLines(Canvas c) { for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { + if (!fitsBounds(i, minx, maxx)) + continue; + position[0] = i; mTrans.pointValuesToPixel(position); From fa97f6143ae234da09a7698bf3895997a8dbaac7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Mar 2015 15:34:29 +0100 Subject: [PATCH 0186/1390] Performance improvements concerning BarChart. --- .../CubicLineChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 2 + .../mpchartexample/StackedBarActivity.java | 17 ++- .../charting/buffer/AbstractBuffer.java | 31 ++++- .../mikephil/charting/buffer/BarBuffer.java | 102 ++++++++++++++++ .../charting/buffer/CandleBodyBuffer.java | 8 +- .../charting/buffer/CandleShadowBuffer.java | 8 +- .../mikephil/charting/buffer/LineBuffer.java | 10 +- .../charting/charts/BarLineChartBase.java | 3 + .../charting/charts/HorizontalBarChart.java | 3 + .../mikephil/charting/data/BarEntry.java | 4 +- .../mikephil/charting/data/ChartData.java | 2 +- .../mikephil/charting/data/DataSet.java | 12 +- .../charting/renderer/BarChartRenderer.java | 114 ++++++------------ .../renderer/CandleStickChartRenderer.java | 5 + .../charting/renderer/DataRenderer.java | 15 --- .../charting/renderer/LineChartRenderer.java | 26 ++-- .../mikephil/charting/renderer/Renderer.java | 25 ++++ .../charting/renderer/XAxisRenderer.java | 33 ++--- .../renderer/XAxisRendererBarChart.java | 5 +- 20 files changed, 278 insertions(+), 149 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 026d45512d..dbe3b422fc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -260,7 +260,7 @@ private void setData(int count, float range) { ArrayList vals1 = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 5; i < count / 2; i+=2) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 203188bfcb..446306f345 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -38,6 +38,8 @@ protected void onCreate(Bundle savedInstanceState) { // add an empty data object mChart.setData(new LineData()); +// mChart.getXAxis().setDrawLabels(false); +// mChart.getXAxis().setDrawGridLines(false); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 2019c32c22..e3b9474ffd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -81,6 +81,7 @@ protected void onCreate(Bundle savedInstanceState) { yLabels.setValueFormatter(new MyValueFormatter()); mChart.getAxisRight().setValueFormatter(new MyValueFormatter()); + mChart.getAxisRight().setDrawGridLines(false); XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XAxisPosition.TOP); @@ -223,7 +224,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setColors(ColorTemplate.VORDIPLOM_COLORS); + set1.setColors(getColors()); set1.setStackLabels(new String[] { "Births", "Divorces", "Marriages" }); @@ -263,4 +264,18 @@ public void onNothingSelected() { // TODO Auto-generated method stub } + + private int[] getColors() { + + int stacksize = 3; + + // have as many colors as stack-values per entry + int []colors = new int[stacksize]; + + for(int i = 0; i < stacksize; i++) { + colors[i] = ColorTemplate.VORDIPLOM_COLORS[i]; + } + + return colors; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java index 66988f5326..192fb3ef46 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -4,16 +4,26 @@ import java.util.ArrayList; /** - * Buffer class to boost performance while drawing. + * Buffer class to boost performance while drawing. Concept: Replace instead of + * recreate. * * @author Philipp Jahoda - * @param + * @param The data the buffer accepts to be fed with. */ public abstract class AbstractBuffer { + /** index in the buffer */ protected int index = 0; + + /** float-buffer that holds the data points to draw, order: x,y,x,y,... */ public final float[] buffer; + /** animation phase x-axis */ + protected float phaseX = 1f; + + /** animation phase y-axis */ + protected float phaseY = 1f; + /** * Initialization with buffer-size. * @@ -25,14 +35,14 @@ public AbstractBuffer(int size) { } /** - * Resets the buffer index to 0. + * Resets the buffer index to 0 and makes the buffer reusable. */ public void reset() { index = 0; } /** - * Returns the size of the buffer array. + * Returns the size (length) of the buffer array. * * @return */ @@ -40,9 +50,20 @@ public int size() { return buffer.length; } + /** + * Set the phases used for animations. + * + * @param phaseX + * @param phaseY + */ + public void setPhases(float phaseX, float phaseY) { + this.phaseX = phaseX; + this.phaseY = phaseY; + } + /** * Builds up the buffer with the provided data and resets the buffer-index - * after feed-completion. + * after feed-completion. This needs to run FAST. * * @param entries */ diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java new file mode 100644 index 0000000000..dadab13310 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -0,0 +1,102 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.BarEntry; + +import java.util.ArrayList; + +public class BarBuffer extends AbstractBuffer { + + private float mBarSpace = 0f; + private float mGroupSpace = 0f; + private int mDataSetIndex = 0; + private int mDataSetCount = 1; + private boolean mContainsStacks = false; + + public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { + super(size); + this.mGroupSpace = groupspace; + this.mDataSetCount = dataSetCount; + this.mContainsStacks = containsStacks; + } + + public void setBarSpace(float barspace) { + this.mBarSpace = barspace; + } + + public void setDataSet(int index) { + this.mDataSetIndex = index; + } + + private void addBar(float left, float top, float right, float bottom) { + + buffer[index++] = left; + buffer[index++] = top; + buffer[index++] = right; + buffer[index++] = bottom; + } + + @Override + public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; + + int dataSetOffset = (mDataSetCount - 1); + float barSpaceHalf = mBarSpace / 2f; + float groupSpaceHalf = mGroupSpace / 2f; + float barWidth = 0.5f; + + for (int i = 0; i < size; i++) { + + BarEntry e = entries.get(i); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + i * dataSetOffset + mDataSetIndex + + mGroupSpace * i + groupSpaceHalf; + float y = e.getVal(); + float [] vals = e.getVals(); + + if(!mContainsStacks || vals == null) { + + float left = x - barWidth + barSpaceHalf; + float right = x + barWidth - barSpaceHalf; + float top = y >= 0 ? y : 0; + float bottom = y <= 0 ? y : 0; + + // multiply the height of the rect with the phase + if (top >= 0) + top *= phaseY; + else + bottom *= phaseY; + + addBar(left, top, right, bottom); + + } else { + + float all = e.getVal(); + + // fill the stack + for (int k = 0; k < vals.length; k++) { + + all -= vals[k]; + y = vals[k] + all; + + float left = x - barWidth + barSpaceHalf; + float right = x + barWidth - barSpaceHalf; + float top = y >= 0 ? y : 0; + float bottom = y <= 0 ? y : 0; + + // multiply the height of the rect with the phase + if (top >= 0) + top *= phaseY; + else + bottom *= phaseY; + + addBar(left, top, right, bottom); + } + } + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java index 0ffb08fed5..58446e98a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java @@ -17,7 +17,7 @@ public void setBodySpace(float bodySpace) { this.mBodySpace = bodySpace; } - public void addBody(float left, float top, float right, float bottom) { + private void addBody(float left, float top, float right, float bottom) { buffer[index++] = left; buffer[index++] = top; @@ -27,11 +27,13 @@ public void addBody(float left, float top, float right, float bottom) { @Override public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; - for (int i = 0; i < entries.size(); i++) { + for (int i = 0; i < size; i++) { CandleEntry e = entries.get(i); - addBody(e.getXIndex() - 0.5f + mBodySpace, e.getClose(), e.getXIndex() + 0.5f - mBodySpace, e.getOpen()); + addBody(e.getXIndex() - 0.5f + mBodySpace, e.getClose() * phaseY, e.getXIndex() + 0.5f - mBodySpace, e.getOpen() * phaseY); } reset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java index 52e6011771..d532c68757 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java @@ -11,7 +11,7 @@ public CandleShadowBuffer(int size) { super(size); } - public void addShadow(float x1, float y1, float x2, float y2) { + private void addShadow(float x1, float y1, float x2, float y2) { buffer[index++] = x1; buffer[index++] = y1; @@ -21,11 +21,13 @@ public void addShadow(float x1, float y1, float x2, float y2) { @Override public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; - for (int i = 0; i < entries.size(); i++) { + for (int i = 0; i < size; i++) { CandleEntry e = entries.get(i); - addShadow(e.getXIndex(), e.getHigh(), e.getXIndex(), e.getLow()); + addShadow(e.getXIndex(), e.getHigh() * phaseY, e.getXIndex(), e.getLow() * phaseY); } reset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java index 3bb57157b8..134aec5a40 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -18,6 +18,10 @@ public void moveTo(float x, float y) { buffer[index++] = x; buffer[index++] = y; + + // in case just one entry, this is overwritten when lineTo is called + buffer[index] = x; + buffer[index + 1] = y; } public void lineTo(float x, float y) { @@ -39,11 +43,13 @@ public void lineTo(float x, float y) { @Override public void feed(ArrayList entries) { moveTo(entries.get(0).getXIndex(), entries.get(0).getVal()); + + float size = entries.size() * phaseX; - for (int i = 1; i < entries.size(); i++) { + for (int i = 1; i < size; i++) { Entry e = entries.get(i); - lineTo(e.getXIndex(), e.getVal()); + lineTo(e.getXIndex(), e.getVal() * phaseY); } reset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 10d860422c..f7e4089dba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -414,6 +414,9 @@ protected void calcModulus() { if (mLogEnabled) Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + ", x-axis label width: " + mXAxis.mLabelWidth + ", content width: " + mViewPortHandler.contentWidth()); + + if (mXAxis.mAxisLabelModulus < 1) + mXAxis.mAxisLabelModulus = 1; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index ce4c1904ce..364de1918c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -137,6 +137,9 @@ protected void calcModulus() { mXAxis.mAxisLabelModulus = (int) Math .ceil((mData.getXValCount() * mXAxis.mLabelHeight) / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); + + if (mXAxis.mAxisLabelModulus < 1) + mXAxis.mAxisLabelModulus = 1; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index b472e41ee5..cd1a63c68d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -14,7 +14,7 @@ public class BarEntry extends Entry { /** * Constructor for stacked bar entries. * - * @param vals + * @param vals - the stack values * @param xIndex */ public BarEntry(float[] vals, int xIndex) { @@ -36,7 +36,7 @@ public BarEntry(float val, int xIndex) { /** * Constructor for stacked bar entries. * - * @param vals + * @param vals - the stack values * @param xIndex * @param label Additional description label. */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9de93161ac..06ae6e2b58 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -145,7 +145,7 @@ protected void init(ArrayList> dataSets) { */ private void calcXValAverageLength() { - if (mXVals.size() == 0) { + if (mXVals.size() <= 0) { mXValAverageLength = 1; return; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 69c2058187..69a410679b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -171,9 +171,10 @@ public float getYValForXIndex(int xIndex) { /** * Returns the first Entry object found at the given xIndex with binary - * search. Returns null if no Entry object at that index. INFORMATION: This - * method does calculations at runtime. Do not over-use in performance - * critical situations. + * search. If the no Entry at the specifed x-index is found, this method + * returns the Entry at the closest x-index. Returns null if no Entry object + * at that index. INFORMATION: This method does calculations at runtime. Do + * not over-use in performance critical situations. * * @param xIndex * @return @@ -182,6 +183,7 @@ public T getEntryForXIndex(int x) { int low = 0; int high = mYVals.size() - 1; + T closest = null; while (low <= high) { int m = (high + low) / 2; @@ -194,9 +196,11 @@ public T getEntryForXIndex(int x) { low = m + 1; else high = m - 1; + + closest = mYVals.get(m); } - return null; + return closest; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index efb1b60318..15b2388989 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -8,6 +8,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -29,6 +30,8 @@ public class BarChartRenderer extends DataRenderer { /** the rect object that is used for drawing the bars */ protected RectF mBarRect = new RectF(); + protected BarBuffer[] mBarBuffers; + public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); @@ -43,8 +46,16 @@ public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, @Override public void initBuffers() { - // TODO Auto-generated method stub + BarData barData = mChart.getBarData(); + mBarBuffers = new BarBuffer[barData.getDataSetCount()]; + + for (int i = 0; i < mBarBuffers.length; i++) { + BarDataSet set = barData.getDataSetByIndex(i); + mBarBuffers[i] = new BarBuffer(set.getValueCount() * 4 * set.getStackSize(), + barData.getGroupSpace(), + barData.getDataSetCount(), set.isStacked()); + } } @Override @@ -67,90 +78,35 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); calcXBounds(trans); - // the space between bar-groups - float space = mChart.getBarData().getGroupSpace(); - int step = mChart.getBarData().getDataSetCount(); - float multi = (float) step + space; - - boolean noStacks = dataSet.getStackSize() == 1 ? true : false; + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); ArrayList entries = dataSet.getYVals(); - // do the drawing - for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { - - BarEntry e = entries.get(j); - - // check bounds - if (!fitsBounds(((float) e.getXIndex()) * multi, mMinX - multi, mMaxX + multi)) - continue; - - // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + j * (step - 1) + index - + space * j + space / 2f; - float y = e.getVal(); - - // no stacks - if (noStacks) { - - prepareBar(x, y, dataSet.getBarSpace(), trans); - - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } - - // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j)); - c.drawRect(mBarRect, mRenderPaint); - - } else { // stacked bars + // initialize the buffer + BarBuffer buffer = mBarBuffers[index]; + buffer.setPhases(phaseX, phaseY); + buffer.setBarSpace(dataSet.getBarSpace()); + buffer.setDataSet(index); - float[] vals = e.getVals(); + buffer.feed(entries); - // we still draw stacked bars, but there could be one - // non-stacked - // in between - if (vals == null) { + trans.pointValuesToPixel(buffer.buffer); - prepareBar(x, y, dataSet.getBarSpace(), trans); + for (int j = 0; j < buffer.size(); j += 4) { - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } - - mRenderPaint.setColor(dataSet.getColor(0)); - c.drawRect(mBarRect, mRenderPaint); - - } else { - - float all = e.getVal(); - - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { - - prepareBar(x, y, dataSet.getBarSpace(), trans); - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } - - // draw the stack - for (int k = 0; k < vals.length; k++) { - - all -= vals[k]; + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + continue; - prepareBar(x, vals[k] + all, dataSet.getBarSpace(), trans); + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + break; - mRenderPaint.setColor(dataSet.getColor(k)); - c.drawRect(mBarRect, mRenderPaint); - } - } - } + // Set the color for the currently drawn value. If the index + // is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j / 4)); + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } } @@ -223,8 +179,8 @@ public void drawValues(Canvas c) { // the value posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( mValuePaint, - "8") * 1.5f); - negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils + "8") * 1.8f); + negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.8f : -Utils .convertDpToPixel(5)); for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { @@ -233,7 +189,7 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; - + // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index eaac26aaf2..cb2d31322d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -60,6 +60,9 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); calcXBounds(trans); + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet); ArrayList entries = dataSet.getYVals(); @@ -69,6 +72,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { int from = mMinX * 4; CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex]; + shadowBuffer.setPhases(phaseX, phaseY); shadowBuffer.feed(entries); trans.pointValuesToPixel(shadowBuffer.buffer); @@ -81,6 +85,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; bodyBuffer.setBodySpace(dataSet.getBodySpace()); + bodyBuffer.setPhases(phaseX, phaseY); bodyBuffer.feed(entries); trans.pointValuesToPixel(bodyBuffer.buffer); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 0f556c0d2f..dd3f917fb9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -25,10 +25,6 @@ public abstract class DataRenderer extends Renderer { protected Paint mDrawPaint; - protected int mMinX = 0; - - protected int mMaxX = 0; - /** * paint object for drawing values (text representing values of chart * entries) @@ -88,17 +84,6 @@ protected void applyValueTextStyle(DataSet set) { mValuePaint.setTextSize(set.getValueTextSize()); } - /** - * Calculates the minimum and maximum x-value the chart can currently - * display (with the given zoom level). - * - * @param trans - */ - protected void calcXBounds(Transformer trans) { - mMinX = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - mMaxX = (int) trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; - } - public abstract void initBuffers(); public abstract void drawData(Canvas c); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index cf957a8d2b..55942c99c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.LineBuffer; @@ -57,7 +58,9 @@ public void initBuffers() { for (int i = 0; i < mLineBuffers.length; i++) { LineDataSet set = lineData.getDataSetByIndex(i); - mLineBuffers[i] = new LineBuffer(getBufferSize(set)); + int size = lineData.getXValCount() * 4 - 4; + if(size < 4) size = 4; + mLineBuffers[i] = new LineBuffer(size); } } @@ -67,18 +70,18 @@ public void initBuffers() { * @param set * @return */ - private int getBufferSize(LineDataSet set) { + private int getBufferSize(LineDataSet set, int xValCount) { if (set.isDrawFilledEnabled()) { if (set.isDrawCubicEnabled()) { return 0; } else { - return set.getValueCount() * 4 - 4; + return xValCount * 4 - 4; } } else { if (set.isDrawCubicEnabled()) { return 0; } else { - return set.getValueCount() * 4 - 4; + return xValCount * 4 - 4; } } } @@ -226,9 +229,12 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - spline.lineTo(to, fillMin); - spline.lineTo(from, fillMin); + spline.lineTo(entryTo.getXIndex(), fillMin); + spline.lineTo(entryFrom.getXIndex(), fillMin); spline.close(); mRenderPaint.setStyle(Paint.Style.FILL); @@ -255,7 +261,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie mRenderPaint.setStyle(Paint.Style.STROKE); // more than 1 color - if (dataSet.getColors() == null || dataSet.getColors().size() > 1) { + if (dataSet.getColors().size() > 1) { float[] positions = trans.generateTransformedValuesLine( entries, phaseY); @@ -280,17 +286,19 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie } else { // only one color per dataset - int range = (mMaxX - mMinX) * 4; int from = mMinX * 4; + int range = (mMaxX * 4 - mMinX) + 4; + int to = range + from; mRenderPaint.setColor(dataSet.getColor()); LineBuffer buffer = mLineBuffers[dataSetIndex]; + buffer.setPhases(phaseX, phaseY); buffer.feed(entries); trans.pointValuesToPixel(buffer.buffer); - c.drawLines(buffer.buffer, from, range, mRenderPaint); + c.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, mRenderPaint); // Path line = generateLinePath(entries); // diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index c42268a4cf..f5c38f0f74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -1,6 +1,10 @@ package com.github.mikephil.charting.renderer; +import android.util.Log; + +import com.github.mikephil.charting.utils.Transformer; + /** * Abstract baseclass of all Renderers. * @@ -13,6 +17,10 @@ public abstract class Renderer { */ protected ViewPortHandler mViewPortHandler; + protected int mMinX = 0; + + protected int mMaxX = 0; + public Renderer(ViewPortHandler viewPortHandler) { this.mViewPortHandler = viewPortHandler; } @@ -33,4 +41,21 @@ protected boolean fitsBounds(float val, float min, float max) { else return true; } + + /** + * Calculates the minimum and maximum x-value the chart can currently + * display (with the given zoom level). + * + * @param trans + */ + protected void calcXBounds(Transformer trans) { + + double minx = trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; + double maxx = trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; + + if (!Double.isInfinite(minx)) + mMinX = (int) minx; + if (!Double.isInfinite(maxx)) + mMaxX = (int) maxx; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 43b408e13e..c52b0b11d8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Align; +import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -117,18 +118,15 @@ protected void drawLabels(Canvas c, float pos) { float[] position = new float[] { 0f, 0f }; + + int maxx = mMaxX + 1; + + if(maxx > mXAxis.getValues().size()) { + maxx = mXAxis.getValues().size(); + } - int minx = (int) - mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - int maxx = (int) - mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x + 1; - - for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { - - if (!fitsBounds(i, minx, maxx)) - continue; - + for (int i = mMinX; i < maxx; i += mXAxis.mAxisLabelModulus) { + position[0] = i; mTrans.pointValuesToPixel(position); @@ -165,6 +163,8 @@ protected void drawLabels(Canvas c, float pos) { @Override public void renderGridLines(Canvas c) { + calcXBounds(mTrans); + if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; @@ -172,20 +172,11 @@ public void renderGridLines(Canvas c) { 0f, 0f }; - int minx = (int) - mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - int maxx = (int) - mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), - 0).x + 1; - mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { - if (!fitsBounds(i, minx, maxx)) - continue; - position[0] = i; mTrans.pointValuesToPixel(position); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 915f48064b..97480f7507 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -2,7 +2,6 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.util.Log; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; @@ -38,9 +37,9 @@ protected void drawLabels(Canvas c, float pos) { int step = bd.getDataSetCount(); float div = (float) step + (step > 1 ? bd.getGroupSpace() : 0f); - float min = (float) (mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x) + float min = (float) mMinX / div; - float max = (float) (mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x) + float max = (float) mMaxX / div; for (int i = (int) min; i < max; i += mXAxis.mAxisLabelModulus) { From 5e2fb7bf9b007d1ad59e9fdbd79ceb0c42192082 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Mar 2015 17:31:15 +0100 Subject: [PATCH 0187/1390] Bugfixes and performance boost concerning BarChart. --- MPChartExample/AndroidManifest.xml | 1 + .../res/layout/activity_barchart_sinus.xml | 37 +++ .../mpchartexample/BarChartActivitySinus.java | 255 ++++++++++++++++++ .../mpchartexample/StackedBarActivity.java | 2 +- .../notimportant/MainActivity.java | 8 + .../mikephil/charting/buffer/BarBuffer.java | 12 +- .../charting/buffer/HorizontalBarBuffer.java | 77 ++++++ .../charting/renderer/BarChartRenderer.java | 51 ++-- .../charting/renderer/DataRenderer.java | 1 - .../renderer/HorizontalBarChartRenderer.java | 147 ++++------ .../renderer/XAxisRendererBarChart.java | 7 +- .../mikephil/charting/utils/FileUtils.java | 100 ++++++- 12 files changed, 537 insertions(+), 161 deletions(-) create mode 100644 MPChartExample/res/layout/activity_barchart_sinus.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 10da8bbc59..8f9228ebde 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -48,6 +48,7 @@ + diff --git a/MPChartExample/res/layout/activity_barchart_sinus.xml b/MPChartExample/res/layout/activity_barchart_sinus.xml new file mode 100644 index 0000000000..a4bb6201b7 --- /dev/null +++ b/MPChartExample/res/layout/activity_barchart_sinus.xml @@ -0,0 +1,37 @@ + + + + + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java new file mode 100644 index 0000000000..f5af670b8b --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -0,0 +1,255 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.utils.FileUtils; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeListener { + + protected BarChart mChart; + private SeekBar mSeekBarX; + private TextView tvX; + + private Typeface mTf; + + private ArrayList mSinusData; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart_sinus); + + mSinusData = FileUtils.loadBarEntriesFromAssets(getAssets(),"sine.txt"); + + tvX = (TextView) findViewById(R.id.tvValueCount); + + mSeekBarX = (SeekBar) findViewById(R.id.seekbarValues); + + mChart = (BarChart) findViewById(R.id.chart1); + + mChart.setDrawBarShadow(false); + mChart.setDrawValueAboveBar(true); + + mChart.setDescription(""); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + mChart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + // draw shadows for each bar that show the maximum value + // mChart.setDrawBarShadow(true); + + // mChart.setDrawXLabels(false); + + mChart.setDrawGridBackground(false); + // mChart.setDrawYLabels(false); + + mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setTypeface(mTf); + xAxis.setDrawGridLines(false); + xAxis.setEnabled(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(mTf); + leftAxis.setLabelCount(8); + leftAxis.setStartAtZero(false); + leftAxis.setAxisMinValue(-1.2f); + leftAxis.setAxisMaxValue(1.2f); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setDrawGridLines(false); + rightAxis.setTypeface(mTf); + rightAxis.setLabelCount(8); + rightAxis.setStartAtZero(false); + rightAxis.setAxisMinValue(-1.2f); + rightAxis.setAxisMaxValue(1.2f); + + mSeekBarX.setOnSeekBarChangeListener(this); + mSeekBarX.setProgress(750); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setForm(LegendForm.SQUARE); + l.setFormSize(9f); + l.setTextSize(11f); + l.setXEntrySpace(4f); + + // mChart.setDrawLegend(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlightArrow: { + if (mChart.isDrawHighlightArrowEnabled()) + mChart.setDrawHighlightArrow(false); + else + mChart.setDrawHighlightArrow(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.notifyDataSetChanged(); + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleAdjustXLegend: { + XAxis xLabels = mChart.getXAxis(); + + if (xLabels.isAdjustXLabelsEnabled()) + xLabels.setAdjustXLabels(false); + else + xLabels.setAdjustXLabels(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleFilter: { + + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + + setData(mSeekBarX.getProgress()); + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + private void setData(int count) { + + ArrayList xVals = new ArrayList(); + + ArrayList entries = new ArrayList(); + + for (int i = 0; i < count; i++) { + xVals.add(i+""); + entries.add(mSinusData.get(i)); + } + + BarDataSet set = new BarDataSet(entries, "Sinus Function"); + set.setBarSpacePercent(35f); + set.setColor(Color.rgb(233, 101, 105)); + + BarData data = new BarData(xVals, set); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); + data.setDrawValues(false); + + mChart.setData(data); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index e3b9474ffd..b8f22ca098 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -77,7 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis yLabels = mChart.getAxisLeft(); // yLabels.setPosition(YLabelPosition.BOTH_SIDED); - yLabels.setLabelCount(5); +// yLabels.setLabelCount(5); yLabels.setValueFormatter(new MyValueFormatter()); mChart.getAxisRight().setValueFormatter(new MyValueFormatter()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 76b0b20266..adaf7ef92b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -23,6 +23,7 @@ import com.xxmassdeveloper.mpchartexample.AnotherBarActivity; import com.xxmassdeveloper.mpchartexample.BarChartActivity; import com.xxmassdeveloper.mpchartexample.BarChartActivityMultiDataset; +import com.xxmassdeveloper.mpchartexample.BarChartActivitySinus; import com.xxmassdeveloper.mpchartexample.CandleStickChartActivity; import com.xxmassdeveloper.mpchartexample.CombinedChartActivity; import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; @@ -114,6 +115,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Performance Line Chart", "Renders up to 30.000 objects smoothly.")); + objects.add(new ContentItem( + "Sinus Bar Chart", + "A BarChart plotting the sinus function (~750 values).")); MyAdapter adapter = new MyAdapter(this, objects); @@ -227,6 +231,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, PerformanceLineChart.class); startActivity(i); break; + case 23: + i = new Intent(this, BarChartActivitySinus.class); + startActivity(i); + break; } overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index dadab13310..b7f40a7d39 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -7,11 +7,11 @@ public class BarBuffer extends AbstractBuffer { - private float mBarSpace = 0f; - private float mGroupSpace = 0f; - private int mDataSetIndex = 0; - private int mDataSetCount = 1; - private boolean mContainsStacks = false; + protected float mBarSpace = 0f; + protected float mGroupSpace = 0f; + protected int mDataSetIndex = 0; + protected int mDataSetCount = 1; + protected boolean mContainsStacks = false; public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { super(size); @@ -28,7 +28,7 @@ public void setDataSet(int index) { this.mDataSetIndex = index; } - private void addBar(float left, float top, float right, float bottom) { + protected void addBar(float left, float top, float right, float bottom) { buffer[index++] = left; buffer[index++] = top; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java new file mode 100644 index 0000000000..0a1d5b5bbf --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -0,0 +1,77 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.BarEntry; + +import java.util.ArrayList; + +public class HorizontalBarBuffer extends BarBuffer { + + public HorizontalBarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { + super(size, groupspace, dataSetCount, containsStacks); + } + + @Override + public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; + + int dataSetOffset = (mDataSetCount - 1); + float barSpaceHalf = mBarSpace / 2f; + float groupSpaceHalf = mGroupSpace / 2f; + float barWidth = 0.5f; + + for (int i = 0; i < size; i++) { + + BarEntry e = entries.get(i); + + // calculate the x-position, depending on datasetcount + float x = e.getXIndex() + i * dataSetOffset + mDataSetIndex + + mGroupSpace * i + groupSpaceHalf; + float y = e.getVal(); + float[] vals = e.getVals(); + + if (!mContainsStacks || vals == null) { + + float bottom = x - barWidth + barSpaceHalf; + float top = x + barWidth - barSpaceHalf; + float right = y >= 0 ? y : 0; + float left = y <= 0 ? y : 0; + + // multiply the height of the rect with the phase + if (right >= 0) + right *= phaseY; + else + left *= phaseY; + + addBar(left, top, right, bottom); + + } else { + + float all = e.getVal(); + + // fill the stack + for (int k = 0; k < vals.length; k++) { + + all -= vals[k]; + y = vals[k] + all; + + float bottom = x - barWidth + barSpaceHalf; + float top = x + barWidth - barSpaceHalf; + float right = y >= 0 ? y : 0; + float left = y <= 0 ? y : 0; + + // multiply the height of the rect with the phase + if (right >= 0) + right *= phaseY; + else + left *= phaseY; + + addBar(left, top, right, bottom); + } + } + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 15b2388989..dede9f1062 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -24,13 +24,12 @@ public class BarChartRenderer extends DataRenderer { protected BarDataProvider mChart; - /** the rect object that is used for drawing the bar shadow */ - protected RectF mBarShadow = new RectF(); - /** the rect object that is used for drawing the bars */ protected RectF mBarRect = new RectF(); protected BarBuffer[] mBarBuffers; + + protected Paint mShadowPaint; public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -42,6 +41,9 @@ public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, mHighlightPaint.setColor(Color.rgb(0, 0, 0)); // set alpha after color mHighlightPaint.setAlpha(120); + + mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mShadowPaint.setStyle(Paint.Style.FILL); } @Override @@ -77,6 +79,8 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); calcXBounds(trans); + + mShadowPaint.setColor(dataSet.getBarShadowColor()); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -100,6 +104,12 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; + + if (mChart.isDrawBarShadowEnabled()) { + c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), + buffer.buffer[j+2], + mViewPortHandler.contentBottom(), mShadowPaint); + } // Set the color for the currently drawn value. If the index // is @@ -110,35 +120,6 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { } } - /** - * Prepares a bar for drawing on the specified x-index and y-position. Also - * prepares the shadow-bar if enabled. - * - * @param x the x-position - * @param y the y-position - * @param barspace the space between bars - */ - protected void prepareBar(float x, float y, float barspace, Transformer trans) { - - float barWidth = 0.5f; - - float spaceHalf = barspace / 2f; - float left = x - barWidth + spaceHalf; - float right = x + barWidth - spaceHalf; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - - mBarRect.set(left, top, right, bottom); - - trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); - - // if a shadow is drawn, prepare it too - if (mChart.isDrawBarShadowEnabled()) { - mBarShadow.set(mBarRect.left, mViewPortHandler.offsetTop(), mBarRect.right, - mViewPortHandler.contentBottom()); - } - } - /** * Prepares a bar for being highlighted. * @@ -177,10 +158,12 @@ public void drawValues(Canvas c) { // calculate the correct offset depending on the draw position of // the value + float plus = Utils.convertDpToPixel(6f); + posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( mValuePaint, - "8") * 1.8f); - negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.8f : -Utils + "8") + plus); + negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") + plus : -Utils .convertDpToPixel(5)); for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index dd3f917fb9..d876cee599 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; public abstract class DataRenderer extends Renderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 7dffac0787..07c4492e3c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -5,6 +5,9 @@ import android.graphics.Paint.Align; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.BarBuffer; +import com.github.mikephil.charting.buffer.HorizontalBarBuffer; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; @@ -30,99 +33,62 @@ public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, mValuePaint.setTextAlign(Align.LEFT); } - protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { - - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - - // the space between bar-groups - float space = mChart.getBarData().getGroupSpace(); - - boolean noStacks = dataSet.getStackSize() == 1 ? true : false; - - ArrayList entries = dataSet.getYVals(); - - // do the drawing - for (int j = 0; j < dataSet.getEntryCount() * mAnimator.getPhaseX(); j++) { - - BarEntry e = entries.get(j); - - // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + j * (mChart.getBarData().getDataSetCount() - 1) + index - + space * j + space / 2f; - float y = e.getVal(); - - // no stacks - if (noStacks) { - - prepareBar(x, y, dataSet.getBarSpace(), trans); - - // avoid drawing outofbounds values - if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) - break; - - if (!mViewPortHandler.isInBoundsBottom(mBarRect.top)) - continue; - - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } - - // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j)); - c.drawRect(mBarRect, mRenderPaint); - - } else { // stacked bars + @Override + public void initBuffers() { - float[] vals = e.getVals(); + BarData barData = mChart.getBarData(); + mBarBuffers = new HorizontalBarBuffer[barData.getDataSetCount()]; - // we still draw stacked bars, but there could be one - // non-stacked - // in between - if (vals == null) { + for (int i = 0; i < mBarBuffers.length; i++) { + BarDataSet set = barData.getDataSetByIndex(i); + mBarBuffers[i] = new HorizontalBarBuffer(set.getValueCount() * 4 * set.getStackSize(), + barData.getGroupSpace(), + barData.getDataSetCount(), set.isStacked()); + } + } - prepareBar(x, y, dataSet.getBarSpace(), trans); + protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + calcXBounds(trans); - mRenderPaint.setColor(dataSet.getColor(0)); - c.drawRect(mBarRect, mRenderPaint); + mShadowPaint.setColor(dataSet.getBarShadowColor()); - } else { + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); - float all = e.getVal(); + ArrayList entries = dataSet.getYVals(); - // if drawing the bar shadow is enabled - if (mChart.isDrawBarShadowEnabled()) { + // initialize the buffer + BarBuffer buffer = mBarBuffers[index]; + buffer.setPhases(phaseX, phaseY); + buffer.setBarSpace(dataSet.getBarSpace()); + buffer.setDataSet(index); - prepareBar(x, y, dataSet.getBarSpace(), trans); - mRenderPaint.setColor(dataSet.getBarShadowColor()); - c.drawRect(mBarShadow, mRenderPaint); - } + buffer.feed(entries); - // draw the stack - for (int k = 0; k < vals.length; k++) { + trans.pointValuesToPixel(buffer.buffer); - all -= vals[k]; + for (int j = 0; j < buffer.size(); j += 4) { - prepareBar(x, vals[k] + all, dataSet.getBarSpace(), trans); + if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) + break; - mRenderPaint.setColor(dataSet.getColor(k)); - c.drawRect(mBarRect, mRenderPaint); - } - } + if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) + continue; - // avoid drawing outofbounds values - if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) - break; + if (mChart.isDrawBarShadowEnabled()) { + c.drawRect(mViewPortHandler.contentLeft(), buffer.buffer[j + 1], + mViewPortHandler.contentRight(), + buffer.buffer[j + 3], mShadowPaint); } + + // Set the color for the currently drawn value. If the index + // is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j / 4)); + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } } @@ -255,29 +221,8 @@ public void drawValues(Canvas c) { } @Override - protected void prepareBar(float x, float y, float barspace, Transformer trans) { - - float spaceHalf = barspace / 2f; - - float top = x - 0.5f + spaceHalf; - float bottom = x + 0.5f - spaceHalf; - float left = y >= 0 ? y : 0; - float right = y <= 0 ? y : 0; - - mBarRect.set(left, top, right, bottom); - - trans.rectValueToPixelHorizontal(mBarRect, mAnimator.getPhaseY()); - - // if a shadow is drawn, prepare it too - if (mChart.isDrawBarShadowEnabled()) { - mBarShadow.set(mViewPortHandler.contentLeft(), mBarRect.top, - mViewPortHandler.contentRight(), - mBarRect.bottom); - } - } - - @Override - protected void prepareBarHighlight(float x, float y, float barspace, float from, Transformer trans) { + protected void prepareBarHighlight(float x, float y, float barspace, float from, + Transformer trans) { float spaceHalf = barspace / 2f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 97480f7507..e1c5cc460b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -42,10 +42,7 @@ protected void drawLabels(Canvas c, float pos) { float max = (float) mMaxX / div; - for (int i = (int) min; i < max; i += mXAxis.mAxisLabelModulus) { - - if (!fitsBounds(i, min - 1f, max + 0.5f)) - continue; + for (int i = (int) min; i <= max; i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; @@ -88,6 +85,8 @@ protected void drawLabels(Canvas c, float pos) { @Override public void renderGridLines(Canvas c) { + + calcXBounds(mTrans); if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java index d5958b0d5c..22c442239b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java @@ -49,17 +49,17 @@ public static ArrayList loadEntriesFromFile(String path) { while ((line = br.readLine()) != null) { String[] split = line.split("#"); - - if(split.length <= 2) { + + if (split.length <= 2) { entries.add(new Entry(Float.parseFloat(split[0]), Integer.parseInt(split[1]))); } else { - + float[] vals = new float[split.length - 1]; - - for(int i = 0; i < vals.length; i++) { + + for (int i = 0; i < vals.length; i++) { vals[i] = Float.parseFloat(split[i]); - } - + } + entries.add(new BarEntry(vals, Integer.parseInt(split[split.length - 1]))); } } @@ -119,17 +119,17 @@ public static ArrayList loadEntriesFromAssets(AssetManager am, String pat while (line != null) { // process line String[] split = line.split("#"); - - if(split.length <= 2) { + + if (split.length <= 2) { entries.add(new Entry(Float.parseFloat(split[0]), Integer.parseInt(split[1]))); } else { - + float[] vals = new float[split.length - 1]; - - for(int i = 0; i < vals.length; i++) { + + for (int i = 0; i < vals.length; i++) { vals[i] = Float.parseFloat(split[i]); - } - + } + entries.add(new BarEntry(vals, Integer.parseInt(split[split.length - 1]))); } line = reader.readLine(); @@ -225,4 +225,76 @@ public static void saveToSdCard(ArrayList entries, String path) { Log.e(LOG, e.toString()); } } + + public static ArrayList loadBarEntriesFromAssets(AssetManager am, String path) { + + ArrayList entries = new ArrayList(); + + BufferedReader reader = null; + try { + reader = new BufferedReader( + new InputStreamReader(am.open(path), "UTF-8")); + + String line = reader.readLine(); + + while (line != null) { + // process line + String[] split = line.split("#"); + + entries.add(new BarEntry(Float.parseFloat(split[0]), Integer.parseInt(split[1]))); + + line = reader.readLine(); + } + } catch (IOException e) { + Log.e(LOG, e.toString()); + + } finally { + + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + Log.e(LOG, e.toString()); + } + } + } + + return entries; + + // String label = null; + // ArrayList entries = new ArrayList(); + // + // BufferedReader reader = null; + // try { + // reader = new BufferedReader( + // new InputStreamReader(am.open(path), "UTF-8")); + // + // // do reading, usually loop until end of file reading + // label = reader.readLine(); + // String line = reader.readLine(); + // + // while (line != null) { + // // process line + // String[] split = line.split("#"); + // entries.add(new Entry(Float.parseFloat(split[0]), + // Integer.parseInt(split[1]))); + // line = reader.readLine(); + // } + // } catch (IOException e) { + // Log.e(LOG, e.toString()); + // + // } finally { + // + // if (reader != null) { + // try { + // reader.close(); + // } catch (IOException e) { + // Log.e(LOG, e.toString()); + // } + // } + // } + // + // DataSet ds = new DataSet(entries, label); + // return ds; + } } From aca66bb6d46c4aa951467480c265546e15b6d8bc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Mar 2015 18:59:20 +0100 Subject: [PATCH 0188/1390] Minor bugfixes and new BarChart example. --- MPChartExample/assets/othersine.txt | 8000 +++++++++++++++++ .../res/layout/activity_barchart_sinus.xml | 2 +- .../mpchartexample/BarChartActivitySinus.java | 30 +- .../notimportant/MainActivity.java | 2 +- .../mikephil/charting/buffer/BarBuffer.java | 4 +- .../charting/buffer/HorizontalBarBuffer.java | 4 +- 6 files changed, 8021 insertions(+), 21 deletions(-) create mode 100644 MPChartExample/assets/othersine.txt diff --git a/MPChartExample/assets/othersine.txt b/MPChartExample/assets/othersine.txt new file mode 100644 index 0000000000..142857b056 --- /dev/null +++ b/MPChartExample/assets/othersine.txt @@ -0,0 +1,8000 @@ +0.0#0 +0.09983341664682815#1 +0.19866933079506122#2 +0.2955202066613396#3 +0.3894183423086505#4 +0.479425538604203#5 +0.5646424733950354#6 +0.644217687237691#7 +0.7173560908995227#8 +0.7833269096274833#9 +0.8414709848078964#10 +0.8912073600614353#11 +0.9320390859672263#12 +0.963558185417193#13 +0.9854497299884603#14 +0.9974949866040544#15 +0.9995736030415051#16 +0.9916648104524686#17 +0.973847630878195#18 +0.9463000876874144#19 +0.9092974268256815#20 +0.8632093666488735#21 +0.8084964038195899#22 +0.7457052121767197#23 +0.6754631805511504#24 +0.5984721441039558#25 +0.5155013718214634#26 +0.42737988023382895#27 +0.33498815015590383#28 +0.23924932921398112#29 +0.1411200080598659#30 +0.04158066243328916#31 +-0.05837414342758142#32 +-0.15774569414324996#33 +-0.25554110202683294#34 +-0.3507832276896215#35 +-0.44252044329485407#36 +-0.5298361409084948#37 +-0.6118578909427207#38 +-0.6877661591839753#39 +-0.7568024953079294#40 +-0.8182771110644114#41 +-0.8715757724135886#42 +-0.9161659367494552#43 +-0.9516020738895161#44 +-0.977530117665097#45 +-0.9936910036334644#46 +-0.9999232575641008#47 +-0.9961646088358408#48 +-0.9824526126243328#49 +-0.958924274663139#50 +-0.9258146823277331#51 +-0.8834546557201545#52 +-0.8322674422239027#53 +-0.7727644875559894#54 +-0.7055403255703945#55 +-0.6312666378723244#56 +-0.5506855425976414#57 +-0.4646021794137613#58 +-0.37387666483024096#59 +-0.27941549819893097#60 +-0.18216250427210112#61 +-0.0830894028175026#62 +0.016813900484343496#63 +0.11654920485048659#64 +0.21511998808780858#65 +0.3115413635133711#66 +0.40484992061659103#67 +0.4941133511386012#68 +0.5784397643881929#69 +0.6569865987187824#70 +0.7289690401258698#71 +0.7936678638491472#72 +0.8504366206285593#73 +0.8987080958116223#74 +0.9379999767747351#75 +0.9679196720314837#76 +0.9881682338769986#77 +0.9985433453746043#78 +0.9989413418397726#79 +0.9893582466233836#80 +0.9698898108450894#81 +0.9407305566797773#82 +0.9021718337562995#83 +0.8545989080882879#84 +0.7984871126234988#85 +0.734397097874123#86 +0.662969230082194#87 +0.5849171928917747#88 +0.5010208564578985#89 +0.41211848524177114#90 +0.3190983623493673#91 +0.22288991410026324#92 +0.12445442350707933#93 +0.024775425453375525#94 +-0.07515112046179159#95 +-0.17432678122296213#96 +-0.27176062641092535#97 +-0.36647912925191023#98 +-0.457535893775304#99 +-0.5440211108893535#100 +-0.6250706488928668#101 +-0.6998746875935284#102 +-0.7676858097635688#103 +-0.8278264690856417#104 +-0.8796957599716599#105 +-0.9227754216127984#106 +-0.9566350162701817#107 +-0.980936230066487#108 +-0.9954362533063752#109 +-0.9999902065507036#110 +-0.9945525882039916#111 +-0.9791777291513221#112 +-0.9540192499020964#113 +-0.9193285256646855#114 +-0.8754521746884406#115 +-0.822828594968723#116 +-0.7619835839190494#117 +-0.6935250847771416#118 +-0.6181371122370543#119 +-0.5365729180004575#120 +-0.4496474645346253#121 +-0.3582292822368536#122 +-0.26323179136582836#123 +-0.16560417544833742#124 +-0.06632189735122905#125 +0.03362304722110829#126 +0.13323204141991404#127 +0.23150982510150958#128 +0.3274744391376645#129 +0.4201670368266135#130 +0.5086614643723477#131 +0.5920735147071987#132 +0.6695697621965786#133 +0.7403758899524271#134 +0.8037844265516019#135 +0.8591618148564795#136 +0.9059547423084483#137 +0.9436956694440937#138 +0.972007501394968#139 +0.9906073556948657#140 +0.9993093887479164#141 +0.9980266527163638#142 +0.9867719642746191#143 +0.9656577765492868#144 +0.9348950555246957#145 +0.8947911721405201#146 +0.8457468311429532#147 +0.7882520673753391#148 +0.7228813495120019#149 +0.6502878401571452#150 +0.5711968696600193#151 +0.4863986888538323#152 +0.3967405731306479#153 +0.3031183567457395#154 +0.20646748193783482#155 +0.10775365229948292#156 +0.007963183785976422#157 +-0.09190685022764096#158 +-0.19085858137414927#159 +-0.28790331666502617#160 +-0.3820714171839697#161 +-0.4724219863984317#162 +-0.558052271286747#163 +-0.6381066823479201#164 +-0.7117853423690981#165 +-0.7783520785342762#166 +-0.8371417780197293#167 +-0.8875670335814898#168 +-0.9291240127343579#169 +-0.961397491879549#170 +-0.9840650050816383#171 +-0.9969000660415941#172 +-0.9997744310730117#173 +-0.9926593804706357#174 +-0.9756260054681622#175 +-0.9488444979181307#176 +-0.9125824497911917#177 +-0.8672021794855902#178 +-0.8131571116614967#179 +-0.7509872467716855#180 +-0.6813137655555104#181 +-0.6048328224062927#182 +-0.5223085896267406#183 +-0.43456562207190313#184 +-0.34248061846961925#185 +-0.24697366173662777#186 +-0.14899902581420232#187 +-0.049535640878370965#188 +0.05042268780681122#189 +0.14987720966295234#190 +0.24783420798295983#191 +0.3433149288198987#192 +0.4353653603728964#193 +0.5230657651577025#194 +0.6055398697196067#195 +0.6819636200681407#196 +0.7515734153521554#197 +0.8136737375071116#198 +0.8676441006416744#199 +0.9129452507276334#200 +0.949124553647899#201 +0.9758205177669794#202 +0.9927664058359092#203 +0.9997929001426696#204 +0.9968297942787976#205 +0.9839066946186122#206 +0.9611527245021096#207 +0.9287952340772312#208 +0.887157528692338#209 +0.8366556385360404#210 +0.777794161801075#211 +0.71116122290596#212 +0.6374225961502142#213 +0.5573150535176319#214 +0.47163900309416484#215 +0.3812504916549073#216 +0.28705265132769103#217 +0.18998667579539935#218 +0.09102241619980542#219 +-0.008851309290446507#220 +-0.10863659542412214#221 +-0.20733642060680393#222 +-0.30396460881109105#223 +-0.39755568312147854#224 +-0.487174512460553#225 +-0.5719256551096047#226 +-0.6509623056662873#227 +-0.7234947560442817#228 +-0.7887982859754514#229 +-0.846220404175201#230 +-0.8951873678197072#231 +-0.9352099151945603#232 +-0.9658881542360861#233 +-0.986915558120659#234 +-0.9980820279794003#235 +-0.9992759921366252#236 +-0.9904855208971471#237 +-0.9717984457438473#238 +-0.9434014817545319#239 +-0.9055783620065937#240 +-0.8587070026098931#241 +-0.8032557266939103#242 +-0.7397785850778432#243 +-0.6689098203779662#244 +-0.5913575298650613#245 +-0.5078965903905548#246 +-0.4193609160731571#247 +-0.326635126104645#248 +-0.2306457059273127#249 +-0.13235175009768851#250 +-0.0327353793307601#251 +0.06720807252556354#252 +0.16648000353724682#253 +0.2640885213845585#254 +0.3590583540222545#255 +0.4504405942754718#256 +0.5373221810065527#257 +0.6188350221201147#258 +0.6941646682523136#259 +0.7625584504796671#260 +0.823333000738138#261 +0.875881079810939#262 +0.9196776446620603#263 +0.9542850944927288#264 +0.9793576431039386#265 +0.9946447738778491#266 +0.999993742857021#267 +0.9953511049115485#268 +0.9807632477451307#269 +0.9563759284044698#270 +0.9224328169230419#271 +0.8792730616506684#272 +0.8273279005953128#273 +0.7671163526354526#274 +0.6992400316550114#275 +0.624377135416297#276 +0.5432756692321434#277 +0.45674597214408225#278 +0.3656526202825023#279 +0.2709057883077459#280 +0.17345215524576615#281 +0.07426544558423022#282 +-0.025663299860690898#283 +-0.12533562609656307#284 +-0.223755640186928#285 +-0.31993996188432605#286 +-0.4129275492406663#287 +-0.501789301020694#288 +-0.5856373399744128#289 +-0.6636338842130738#290 +-0.734999618048874#291 +-0.7990214786597013#292 +-0.8550597807771457#293 +-0.9025546082102497#294 +-0.941031408343004#295 +-0.9701057337072216#296 +-0.9894870832545573#297 +-0.9989818049469563#298 +-0.9984950306638061#299 +-0.9880316240928376#300 +-0.9676961321337658#301 +-0.9376917403002256#302 +-0.8983182425572844#303 +-0.8499690458792419#304 +-0.7931272394571857#305 +-0.7283607678314815#306 +-0.6563167561776644#307 +-0.5777150444455955#308 +-0.49334099495663#309 +-0.40403764532290903#310 +-0.3106972850942102#311 +-0.21425254029571766#312 +-0.11566705493706401#313 +-0.015925862599924186#314 +0.08397445569192384#315 +0.18303572898076265#316 +0.28026816976919344#317 +0.37470026364963#318 +0.465388476355119#319 +0.5514266812418447#320 +0.6319552130070282#321 +0.7061694571804652#322 +0.7733278895663422#323 +0.8327594853078859#324 +0.8838704235459204#325 +0.9261500206806009#326 +0.9591758329531347#327 +0.9826178773641765#328 +0.9962419287548808#329 +0.9999118601072645#330 +0.9935910026803725#331 +0.9773425123922165#332 +0.9513287387867192#333 +0.9158096028907363#334 +0.8711400001690751#335 +0.8177662545263231#336 +0.7562216587859281#337 +0.6871211462045894#338 +0.6111551462624274#339 +0.529082686119843#340 +0.44172380666903255#341 +0.34995136895646245#342 +0.2546823328438221#343 +0.15686859504819245#344 +0.05748747810470466#345 +-0.04246803471717159#346 +-0.14199922097421971#347 +-0.24011159795399523#348 +-0.33582485921735605#349 +-0.42818266949635647#350 +-0.5162622200801217#351 +-0.5991834492144473#352 +-0.676117835387937#353 +-0.7462966756450723#354 +-0.8090187662120443#355 +-0.8636574086930742#356 +-0.9096666718336256#357 +-0.9465868462850383#358 +-0.974049037868381#359 +-0.9917788534431466#360 +-0.9995991425528098#361 +-0.9974317674536307#362 +-0.9852983838411613#363 +-0.9633202244736941#364 +-0.9317168878546153#365 +-0.8908041440767483#366 +-0.840990779751967#367 +-0.7827745135504952#368 +-0.7167370231604792#369 +-0.6435381333568037#370 +-0.5639092232500512#371 +-0.4786459185881904#372 +-0.38860014212710114#373 +-0.2946716015000064#374 +-0.19779879963620456#375 +-0.09894965755002794#376 +8.881568059804928E-4#377 +0.10071709699276916#378 +0.19953970523905196#379 +0.29636857870964317#380 +0.39023623530819473#381 +0.48020478043849585#382 +0.5653752781372515#383 +0.6448967329450791#384 +0.7179745927718371#385 +0.783878687798465#386 +0.8419505260924545#387 +0.8916098730415694#388 +0.9323605488662917#389 +0.9637953862841635#390 +0.9856002987906811#391 +0.997557418907825#392 +0.9995472750438832#393 +0.9915499852141032#394 +0.9736454556949117#395 +0.9460125826268136#396 +0.9089274645432923#397 +0.862760643685528#398 +0.8079734036668093#399 +0.7451131604791498#400 +0.6748079928936466#401 +0.5977603669050155#402 +0.5147401169235761#403 +0.42657675384429683#404 +0.33415117684813256#405 +0.23838687174859532#406 +0.1402406838267691#407 +0.040693257349552474#408 +-0.059260762703698414#409 +-0.15862266880501766#410 +-0.2563996696333202#411 +-0.35161480971710896#412 +-0.4433167308506074#413 +-0.5305891777504746#414 +-0.6125601529757225#415 +-0.6884106296379023#416 +-0.7573827348470396#417 +-0.8187873221270313#418 +-0.8720108571394337#419 +-0.9165215479157646#420 +-0.9518746583470648#421 +-0.9777169518400896#422 +-0.9937902207405829#423 +-0.9999338662588075#424 +-0.9960865031195645#425 +-0.9822865729035719#426 +-0.9586719599518976#427 +-0.9254786136712014#428 +-0.8830381910052587#429 +-0.831774742628409#430 +-0.7722004759713906#431 +-0.7049106374140062#432 +-0.6305775647800578#433 +-0.549943969560057#434 +-0.46381551598351894#435 +-0.3730527710882991#436 +-0.2785626062192159#437 +-0.18128913586934542#438 +-0.08220428440008934#439 +0.017701925105768793#440 +0.11743126282744855#441 +0.21598726618857098#442 +0.312385196181835#443 +0.4056618765556671#444 +0.49488531755294296#445 +0.5791640280445662#446 +0.6576559230141424#447 +0.7295767373931061#448 +0.7942078621780435#449 +0.8509035245343125#450 +0.8990972401447438#451 +0.9383074733336821#452 +0.9681424484122837#453 +0.9883040641716944#454 +0.9985908724117905#455 +0.9989000907450034#456 +0.989228629563962#457 +0.969673122911827#458 +0.9404289629468755#459 +0.9017883476486434#460 +0.8541373612723012#461 +0.7979521167223996#462 +0.7337939983901085#463 +0.6623040529859501#464 +0.5841965844129685#465 +0.5002520166782486#466 +0.4113090961542109#467 +0.318256511102111#468 +0.2220240121926944#469 +0.12357312274482915#470 +0.023887531502341068#471 +-0.07603673605875032#472 +-0.1752012696875459#473 +-0.2726152501434634#474 +-0.367305349134568#475 +-0.4583254544921258#476 +-0.5447661234106508#477 +-0.6257636692997951#478 +-0.7005087914552633#479 +-0.7682546613239306#480 +-0.8283243845678764#481 +-0.8801177643688576#482 +-0.923117298396518#483 +-0.9568933495206096#484 +-0.9811084386031781#485 +-0.995520616478555#486 +-0.9999858814294422#487 +-0.9944596180044706#488 +-0.9789970428010428#489 +-0.9537526527593436#490 +-0.918978681479984#491 +-0.8750225789892403#492 +-0.8223235401332446#493 +-0.7614081162882599#494 +-0.6928849542333831#495 +-0.6174387147531208#496 +-0.5358232317331488#497 +-0.4488539801013109#498 +-0.3573999278716999#499 +-0.26237485370350366#500 +-0.16472821672669768#501 +-0.06543566986026736#502 +0.03451068858925011#503 +0.13411222764610073#504 +0.2323737616559199#505 +0.32831349385182623#506 +0.42097282614317716#507 +0.5094259371108206#508 +0.5927890325086789#509 +0.6702291758437122#510 +0.740972610802025#511 +0.8043124923661843#512 +0.859615949376982#513 +0.9063304079728589#514 +0.9439891127252716#515 +0.9722157903046471#516 +0.9907284090791111#517 +0.9993419970813273#518 +0.9979704901872514#519 +0.9866275920404088#520 +0.9654266371296195#521 +0.9345794583882479#522 +0.8943942706295563#523 +0.8452725909661725#524 +0.7877052269838246#525 +0.7222673727541837#526 +0.6496128616858338#527 +0.5704676336369813#528 +0.48562248156435645#529 +0.3959251501813905#530 +0.3022718655732663#531 +0.20559838040212833#532 +0.10687062417580104#533 +0.007075051999440675#534 +-0.09279121175779685#535 +-0.19173033639984702#536 +-0.2887537548982128#537 +-0.38289204132693666#538 +-0.47320459704600304#539 +-0.5587890488520287#540 +-0.6387902651930264#541 +-0.712408900360203#542 +-0.7789093812860535#543 +-0.8376272571473031#544 +-0.8879758383378954#545 +-0.929452058477602#546 +-0.9616415008850029#547 +-0.984222539291978#548 +-0.9969695514270638#549 +-0.9997551733586085#550 +-0.9925515720730763#551 +-0.9754307235733183#552 +-0.948563693718144#553 +-0.9122189289888067#554 +-0.8667595742605005#555 +-0.8126398443788057#556 +-0.7504004857950958#557 +-0.6806633736067427#558 +-0.6041252979867081#559 +-0.5215510020864632#560 +-0.43376554097521025#561 +-0.3416460379623573#562 +-0.2461129206713498#563 +-0.14812072443110932#564 +-0.04864855487455499#565 +0.0513096949612317#566 +0.1507552752856959#567 +0.24869455873257396#568 +0.34414896835608744#569 +0.4361647552483109#570 +0.5238225280829925#571 +0.6062464393697752#572 +0.6826129366328042#573 +0.7521589910748351#574 +0.8141897215087521#575 +0.8680853373806932#576 +0.9133073315123875#577 +0.9494038606868752#578 +0.9760142603165708#579 +0.9928726480846032#580 +0.9998105805530361#581 +0.9967587361940206#582 +0.9837476080275863#583 +0.9609071989454651#584 +0.9284657227651701#585 +0.8867473239929686#586 +0.8361688390791232#587 +0.7772356315258688#588 +0.7105365424623492#589 +0.6367380071386995#590 +0.5565773961253213#591 +0.4708556477498852#592 +0.38042926538631583#593 +0.28620175955620214#594 +0.18911462035032636#595 +0.09013791037089226#596 +-0.009739427813336072#597 +-0.10951945285428034#598 +-0.20820519572462254#599 +-0.30481062110277163#600 +-0.3983704795118571#601 +-0.48794995177343276#602 +-0.5726539894116975#603 +-0.6516362576820022#604 +-0.7241075918678563#605 +-0.7893438823539132#606 +-0.8466933096898865#607 +-0.8955828573550356#608 +-0.935524037149826#609 +-0.966117770008547#610 +-0.9870583734654177#611 +-0.9981366159327402#612 +-0.999241807273761#613 +-0.9903629047819286#614 +-0.9715886235159662#615 +-0.9431065498883311#616 +-0.9052012673637889#617 +-0.8582515129955042#618 +-0.8027263932095995#619 +-0.7391806966488114#620 +-0.6682493509077604#621 +-0.5906410785463059#622 +-0.5071313157679993#623 +-0.418554464517864#624 +-0.3257955554139773#625 +-0.2297814048140864#626 +-0.131471354372927#627 +-0.03184768561752508#628 +0.06809419468512197#629 +0.1673557003034234#630 +0.26494504308473243#631 +0.3598871425747261#632 +0.4512333686989858#633 +0.5380710201611258#634 +0.6195324438524475#635 +0.6948037041549939#636 +0.7631327155171924#637 +0.8238367570440802#638 +0.8763092940188087#639 +0.9200260381970413#640 +0.9545501863217811#641 +0.9795367845171353#642 +0.9947361749534073#643 +0.9999964903456082#644 +0.9952651713611683#645 +0.9805894917754141#646 +0.9561160861276317#647 +0.9220894845972212#648 +0.8788496697389755#649 +0.8268286794897758#650 +0.7665462903883387#651 +0.6986048241398573#652 +0.6236831294166234#653 +0.542529799026492#654 +0.4559556902209967#655 +0.3648258228777264#656 +0.27005073650764577#657 +0.17257739244528622#658 +0.07337971212411498#659 +-0.026551154024492412#660 +-0.12621672981873175#661 +-0.2246211897703263#662 +-0.3207813090436296#663 +-0.41373628751317226#664 +-0.5025573497609173#665 +-0.5863570250932251#666 +-0.664298014854665#667 +-0.7356015584394067#668 +-0.7995552144097693#669 +-0.8555199789755651#670 +-0.9029366707087443#671 +-0.9413315176993833#672 +-0.9703208913280009#673 +-0.9896151393559127#674 +-0.9990214800346544#675 +-0.9984459283174868#676 +-0.9878942349269157#677 +-0.9674718288953736#678 +-0.9373827641531779#679 +-0.8979276806891099#680 +-0.849500800655026#681 +-0.7925859894284285#682 +-0.7277519209895582#683 +-0.6556463959189626#684 +-0.5769898687882292#685 +-0.4925682496160574#686 +-0.40322505131513814#687 +-0.30985296158995934#688 +-0.21338492349634555#689 +-0.1147848137828343#690 +-0.015037812152819907#691 +0.08485944232538563#692 +0.18390880930667822#693 +0.2811206202575485#694 +0.37552356689692795#695 +0.46617440618746125#696 +0.552167384908141#697 +0.6326432896410897#698 +0.7067980317480133#699 +0.773890681558078#700 +0.8332508714922635#701 +0.8842854941546171#702 +0.9264846284653002#703 +0.9594266346234597#704 +0.9827823669927427#705 +0.9963184628156941#706 +0.9998996738972894#707 +0.9934902179601922#708 +0.9771541361694416#709 +0.9510546532542999#710 +0.9154525466207135#711 +0.870703540749673#712 +0.8172547529157873#713 +0.7556402257392723#714 +0.6864755912086206#715 +0.610451919489274#716 +0.5283288139789675#717 +0.44092682160167046#718 +0.3491192341739591#719 +0.2538233627618576#720 +0.1559913722118884#721 +0.056600767434670324#722 +-0.04335537350102874#723 +-0.14287832187608665#724 +-0.2409736772882528#725 +-0.3366613033722623#726 +-0.42898512099840763#727 +-0.5170226610991652#728 +-0.5998942816751899#729 +-0.6767719568874018#730 +-0.7468875504174615#731 +-0.8095404904319502#732 +-0.8641047694645521#733 +-0.9100351992757256#734 +-0.9468728581933795#735 +-0.9742496765065195#736 +-0.9918921140961338#737 +-0.9996238935576413#738 +-0.9973677615064493#739 +-0.9851462604682352#740 +-0.9630815036414816#741 +-0.9313939547827625#742 +-0.8904002254057634#743 +-0.8405099113036936#744 +-0.7822215000035158#745 +-0.7161173900433542#746 +-0.6428580718388172#747 +-0.5631755282810933#748 +-0.47786592100586434#749 +-0.38778163540941735#750 +-0.29382276389552614#751 +-0.19692811244968383#752 +-0.09806582040002382#753 +0.001776312910822753#754 +0.10160069789023536#755 +0.2004099222810544#756 +0.29721671697515395#757 +0.3910538204800225#758 +0.480983643475862#759 +0.5661076368981451#760 +0.645575269942848#761 +0.7185925282890948#762 +0.7844298476277866#763 +0.8424294032270155#764 +0.8920116826993384#765 +0.9326812762979901#766 +0.9640318268873135#767 +0.9857500901289341#768 +0.9976190643156452#769 +0.9995201585807343#770 +0.9914343778187229#771 +0.9734425124781813#772 +0.945724331330272#773 +0.9085567852786125#774 +0.8623112401573938#775 +0.807449766166722#776 +0.7445205210199198#777 +0.6741522729328512#778 +0.5970481181797517#779 +0.5139784559876693#780 +0.4257732909620477#781 +0.33331393995507175#782 +0.23752422623900496#783 +0.1393612489694287#784 +0.03980582016685425#785 +-0.06014733523277261#786 +-0.15949951834081932#787 +-0.2572580349851358#788 +-0.3524461143820813#789 +-0.44411266870731736#790 +-0.5313417960509607#791 +-0.6132619318067095#792 +-0.6890545570572891#793 +-0.7579623769449068#794 +-0.8192968873111423#795 +-0.8724452540029098#796 +-0.9168764361087397#797 +-0.9521464919440266#798 +-0.9779030147695946#799 +-0.9938886539233454#800 +-0.9999436861830043#801 +-0.9960076116677604#802 +-0.9821197583330767#803 +-0.9584188890187596#804 +-0.9251418149765318#805 +-0.882621029730285#806 +-0.8312813869106968#807 +-0.7716358552581907#808 +-0.7042803932088473#809 +-0.6298879942747078#810 +-0.5492019627150644#811 +-0.463028486686005#812 +-0.37222858307484785#813 +-0.277709494504018#814 +-0.18041562446265824#815 +-0.0813191011391443#816 +0.018589935762430915#817 +0.1183132281708837#818 +0.2168543739126067#819 +0.3132287824327208#820 +0.406473512498437#821 +0.4956568935895487#822 +0.5798878348422998#823 +0.6583247285347402#824 +0.7301838591528853#825 +0.7947472340170689#826 +0.8513697572274626#827 +0.8994856752490656#828 +0.9386142297340143#829 +0.9683644611000755#830 +0.9884391148695585#831 +0.998637611737797#832 +0.9988580516952584#833 +0.9890982321787556#834 +0.9694556700787299#835 +0.9401266273827171#836 +0.9014041501904432#837 +0.853675140694064#838 +0.7974164913793547#839 +0.7331903200736304#840 +0.6616383534502285#841 +0.5834755151077143#842 +0.4994827822896071#843 +0.41049938261791885#844 +0.31741440880816796#845 +0.22115793514885987#846 +0.12269172450663844#847 +0.022999618709638837#848 +-0.07692229167484431#849 +-0.17607561994804152#850 +-0.2734696588295798#851 +-0.36813127927714384#852 +-0.4591146536701932#853 +-0.5455107062068977#854 +-0.6264561960890486#855 +-0.701142342738765#856 +-0.7688229068666809#857 +-0.8288216466482501#858 +-0.880539074508522#859 +-0.9234584470038253#860 +-0.9571509279514455#861 +-0.9812798732190074#862 +-0.9956041943613665#863 +-0.9999807674966593#864 +-0.9943658633528207#865 +-0.9788155841960154#866 +-0.9534853032753393#867 +-0.9186281123846742#868 +-0.8745922930531441#869 +-0.8218178366312031#870 +-0.7608320480425032#871 +-0.6922442771274011#872 +-0.6167398302207777#873 +-0.5350731227976723#874 +-0.4480601416032317#875 +-0.35657029158288345#876 +-0.2615177090755071#877 +-0.16385212806530994#878 +-0.06454939075379683#879 +0.035398302732936385#880 +0.13499230807988533#881 +0.23323751490702455#882 +0.3291522895832851#883 +0.4217782833853109#884 +0.5101900080011152#885 +0.5935040827033676#886 +0.6708880607976146#887 +0.7415687471544812#888 +0.8048399237198179#889 +0.8600694058120545#890 +0.9067053587025647#891 +0.9442818113658633#892 +0.9724233123080624#893 +0.990848680954091#894 +0.999373817111055#895 +0.9979135404365095#896 +0.9864824415322831#897 +0.9651947361600082#898 +0.9342631240349845#899 +0.8939966636009335#900 +0.8447976840201904#901 +0.7871577652337052#902 +0.7216528262567685#903 +0.6489373707865839#904 +0.5697379476176754#905 +0.4848458912064981#906 +0.3951094149191295#907 +0.30142513596369747#908 +0.20472911668761928#909 +0.1059875117520471#910 +0.006186914633861963#911 +-0.09367550009022263#912 +-0.19260194018240928#913 +-0.2896039653540304#914 +-0.3837123634341776#915 +-0.47398683441733475#916 +-0.5595253856302109#917 +-0.6394733441443728#918 +-0.7130318963856286#919 +-0.7794660696152083#920 +-0.8381120755344199#921 +-0.888383942637911#922 +-0.9297793710472535#923 +-0.9618847513252905#924 +-0.9843792971249118#925 +-0.9970382503801957#926 +-0.9997351270147091#927 +-0.9924429807285888#928 +-0.9752346722370627#929 +-0.9482821412702676#930 +-0.9118546886083012#931 +-0.8663162853168473#932 +-0.8121219360685991#933 +-0.7498131328869748#934 +-0.6800124447368134#935 +-0.6034172970210714#936 +-0.5207930031367345#937 +-0.4329651177163347#938 +-0.3408111879589536#939 +-0.2452519854686876#940 +-0.1472423062091467#941 +-0.047761430497799545#942 +0.05219666163925169#943 +0.15163322198712595#944 +0.2495547133041842#945 +0.3449827364177279#946 +0.43696380606511737#947 +0.524578877803335#948 +0.6069525307972649#949 +0.6832617147353013#950 +0.7527439734759979#951 +0.8147050632577988#952 +0.8685258893532176#953 +0.9136686918587087#954 +0.9496824188138638#955 +0.9762072329635024#956 +0.9929781071325793#957 +0.9998274722901109#958 +0.9966868918435423#959 +0.9835877454345576#960 +0.9606609154040736#961 +0.9281354790591521#962 +0.8863364198082719#963 +0.8356813800345357#964 +0.7766764881510327#965 +0.7099113015330387#966 +0.6360529158556042#967 +0.5558392996940816#968 +0.4700719209860606#969 +0.3796077390286655#970 +0.28535064202453175#971 +0.1882424157296708#972 +0.08925333344150882#973 +-0.010627538651171125#974 +-0.11040222389064579#975 +-0.20907380660312846#976 +-0.3056563929506449#977 +-0.3991849616563692#978 +-0.4887250061782283#979 +-0.5733818719893634#980 +-0.6523096956704291#981 +-0.7247198564972739#982 +-0.7898888560785331#983 +-0.8471655473123978#984 +-0.8959776404332164#985 +-0.9358374211416584#986 +-0.9663466236847766#987 +-0.9872004101957622#988 +-0.9981904165331424#989 +-0.9992068341864074#990 +-0.9902395074463488#991 +-0.9713780348775489#992 +-0.9428108740791415#993 +-0.9048234586787762#994 +-0.8577953463741634#995 +-0.8021964265180238#996 +-0.7385822251390002#997 +-0.6675883543092127#998 +-0.5899241613185386#999 +-0.5063656411109719#1000 +-0.41774768279965196#1001 +-0.3249557277308229#1002 +-0.22891692244659007#1003 +-0.1305908549431452#1004 +-0.03095996678470595#1005 +0.06898026312784167#1006 +0.16823126505305938#1007 +0.26580135578772984#1008 +0.3607156472376163#1009 +0.45202578717704495#1010 +0.5388194348708605#1011 +0.6202293768814718#1012 +0.6954421919788581#1013 +0.7637063785766175#1014 +0.8243398634874052#1015 +0.8767368169727581#1016 +0.9203737059935807#1017 +0.9548145251792146#1018 +0.9797151532489783#1019 +0.9948267913582519#1020 +0.9999984490142912#1021 +0.9951784527233196#1022 +0.9804149622949977#1023 +0.955855489645524#1024 +0.9217454249073299#1025 +0.8784255845719909#1026 +0.8263288061645024#1027 +0.7659756234738067#1028 +0.697969065551239#1029 +0.6229886314435827#1030 +0.5417835008632049#1031 +0.4551650486320175#1032 +0.3639987376924607#1033 +0.2691954716878667#1034 +0.17170249351436012#1035 +0.07249392078295652#1036 +-0.02743898724160609#1037 +-0.1270977339757739#1038 +-0.225486562164981#1039 +-0.3216224031609835#1040 +-0.41454469941883354#1041 +-0.5033250020703501#1042 +-0.5870762476783056#1043 +-0.6649616214810665#1044 +-0.7362029185690774#1045 +-0.8000883194510767#1046 +-0.8559795023191575#1047 +-0.9033180209492709#1048 +-0.9416308845112984#1049 +-0.9705352835370772#1050 +-0.989742414826066#1051 +-0.9990603670714583#1052 +-0.9983960383745241#1053 +-0.987756066488005#1054 +-0.9672467624938841#1055 +-0.9370730485781962#1056 +-0.8975364105162827#1057 +-0.8490318853265837#1058 +-0.79204411419133#1059 +-0.7271425000820525#1060 +-0.6549755184733097#1061 +-0.5762642379901035#1062 +-0.4917951157285321#1063 +-0.40241213923645325#1064 +-0.3090083936688921#1065 +-0.21251713837638628#1066 +-0.11390248208604994#1067 +-0.014149749845864671#1068 +0.08574436201749502#1069 +0.18478174455889376#1070 +0.28197284898938413#1071 +0.37634657392060444#1072 +0.466959968288848#1073 +0.5529076530103934#1074 +0.63333086723003#1075 +0.7074260487756557#1076 +0.7744528630858774#1077 +0.8337416003882263#1078 +0.8846998672178285#1079 +0.926818505417086#1080 +0.9596766794756827#1081 +0.9829460813798933#1082 +0.9963942109577327#1083 +0.9998866989438198#1084 +0.9933886495526604#1085 +0.9769649891458017#1086 +0.9507798175090885#1087 +0.915094768221848#1088 +0.8702663945006491#1089 +0.8167426066374239#1090 +0.7550581966278896#1091 +0.6858294947067065#1092 +0.6097482111795045#1093 +0.5275745250821587#1094 +0.4401294887231446#1095 +0.3482868240002752#1096 +0.2529641924603128#1097 +0.15511402632813187#1098 +0.05571401211876051#1099 +-0.04424267808309759#1100 +-0.1437573100702344#1101 +-0.24183556653499838#1102 +-0.33749748195915497#1103 +-0.42978723410541103#1104 +-0.5177826942772574#1105 +-0.600604640924089#1106 +-0.6774255445323065#1107 +-0.7474778360266712#1108 +-0.8100615760667802#1109 +-0.864551448609587#1110 +-0.910403008860601#1111 +-0.9471581231863048#1112 +-0.9744495466339814#1113 +-0.9920045923218871#1114 +-0.9996478560364346#1115 +-0.9973029688131155#1116 +-0.9849933599899484#1117 +-0.9628420231092787#1118 +-0.9310702870069596#1119 +-0.8899956043677858#1120 +-0.840028379843203#1121 +-0.7816678694236923#1122 +-0.7154971920379454#1123 +-0.6421775032212828#1124 +-0.5624413890680937#1125 +-0.4770855464737418#1126 +-0.3869628228025392#1127 +-0.29297369451879685#1128 +-0.19605726992365072#1129 +-0.0971819058953447#1130 +0.0026644676126004055#1131 +0.1024842186409163#1132 +0.20127998123335095#1133 +0.29806462078761803#1134 +0.3918710971780397#1135 +0.48176212710082145#1136 +0.5668395490989988#1137 +0.6462532976948229#1138 +0.7192098969630194#1139 +0.7849803886799459#1140 +0.8429076158332012#1141 +0.8924127887172654#1142 +0.9330012680089154#1143 +0.9642675070398367#1144 +0.9858991038848767#1145 +0.9976799227788151#1146 +0.9994922536734847#1147 +0.9913179883576629#1148 +0.9732388013883325#1149 +0.9454353340255065#1150 +0.9081853893244696#1151 +0.8618611564194799#1152 +0.8069254917329687#1153 +0.743927294267167#1154 +0.6734960211867176#1155 +0.5963353984907568#1156 +0.5132163896153517#1157 +0.42496949222169395#1158 +0.3324764401379949#1159 +0.2366613933665366#1160 +0.13848170418241593#1161 +0.038918351586070044#1162 +-0.06103386031462717#1163 +-0.16037624205817258#1164 +-0.2581161974044102#1165 +-0.35327714102805435#1166 +-0.4449082562364434#1167 +-0.5320939952156349#1168 +-0.6139632268815225#1169 +-0.6896979409336707#1170 +-0.7585414211438385#1171 +-0.819805806214395#1172 +-0.8728789626610285#1173 +-0.9172306010481774#1174 +-0.9524175744657799#1175 +-0.9780883063067141#1176 +-0.9939863031040413#1177 +-0.9999527173289418#1178 +-0.9959279345427144#1179 +-0.9819521690445431#1180 +-0.9581650620635117#1181 +-0.9248042865096023#1182 +-0.8822031722245435#1183 +-0.8307873754602152#1184 +-0.771070625862084#1185 +-0.7036495934524011#1186 +-0.629197926900574#1187 +-0.5484595226483394#1188 +-0.46224109214241743#1189 +-0.37140410144039926#1190 +-0.27685616372666233#1191 +-0.1795419707414492#1192 +-0.08043385373327268#1193 +0.019477931753509533#1194 +0.1191951001847589#1195 +0.217721310575624#1196 +0.31407212160031445#1197 +0.40728482780441533#1198 +0.49642807863955946#1199 +0.5806111842102433#1200 +0.6589930147528394#1201 +0.730790404926155#1202 +0.7952859789406399#1203 +0.851835318340144#1204 +0.8998734008181136#1205 +0.938920245733708#1206 +0.9685857099197014#1207 +0.988573385864046#1208 +0.9986835633157533#1209 +0.9988152247237061#1210 +0.9889670545706377#1211 +0.9692374525173453#1212 +0.9398235502258059#1213 +0.9010192416847732#1214 +0.8532122467181903#1215 +0.7968802370168715#1216 +0.7325860634008656#1217 +0.6609721320001158#1218 +0.5827539855447597#1219 +0.4987131538986974#1220 +0.409689345271531#1221 +0.3165720561317042#1222 +0.22029168365181864#1223 +0.12181022948763352#1224 +0.022111687775516597#1225 +-0.07780778661170105#1226 +-0.17694983131492942#1227 +-0.27432385179549673#1228 +-0.36895691902833305#1229 +-0.45990349068718106#1230 +-0.5462548586909652#1231 +-0.6271482287145591#1232 +-0.70177534094448#1233 +-0.7693905459437702#1234 +-0.8293182549346921#1235 +-0.8809596900584754#1236 +-0.9237988671657521#1237 +-0.9574077513596155#1238 +-0.9814505337788207#1239 +-0.9956869868889223#1240 +-0.9999748647563899#1241 +-0.9942713243229557#1242 +-0.9786333534792907#1243 +-0.953217201660839#1244 +-0.9182768186551078#1245 +-0.8741613172193351#1246 +-0.8213114848612212#1247 +-0.7602553796358565#1248 +-0.6916030539641876#1249 +-0.616040459190884#1250 +-0.5343225917852477#1251 +-0.4472659496660599#1252 +-0.35574037402427566#1253 +-0.2606603581573747#1254 +-0.1629759101546243#1255 +-0.06366306073028243#1256 +0.03628588895266636#1257 +0.1358722820277203#1258 +0.2341010841741585#1259 +0.3299908256710588#1260 +0.42258340791831867#1261 +0.510953676441162#1262 +0.5942186647278355#1263 +0.6715464165391247#1264 +0.7421642985400877#1265 +0.805366720196939#1266 +0.8605221838044265#1267 +0.9070795942021564#1268 +0.9445737651352686#1269 +0.9726300672417244#1270 +0.9909681712250566#1271 +0.9994048488120352#1272 +0.9978558035090056#1273 +0.9863365128645896#1274 +0.9649620738231349#1275 +0.9339460527140935#1276 +0.8935983513678535#1277 +0.8443221106790897#1278 +0.7866096825562044#1279 +0.7210377105038093#1280 +0.6482613679914285#1281 +0.5690078121768063#1282 +0.48406891839188965#1283 +0.3942933679863122#1284 +0.3005781685838748#1285 +0.20385969147888025#1286 +0.10510431572368364#1287 +0.005298772388643717#1288 +-0.09455971452856225#1289 +-0.1934733920354848#1290 +-0.2904539473629896#1291 +-0.38453238285975366#1292 +-0.4747686978964897#1293 +-0.5602612810415106#1294 +-0.6401559186641225#1295 +-0.7136543299548559#1296 +-0.7800221430834386#1297 +-0.8385962327993722#1298 +-0.8887913461602351#1299 +-0.9301059501856239#1300 +-0.9621272430089094#1301 +-0.9845352784570335#1302 +-0.9971061628469102#1303 +-0.9997142920570979#1304 +-0.9923336065226613#1305 +-0.9750378516137301#1306 +-0.9479998407961381#1307 +-0.9114897289363962#1308 +-0.8658723130035688#1309 +-0.8116033871385435#1310 +-0.749225188509642#1311 +-0.6793609794580729#1312 +-0.6027088200666426#1313 +-0.5200345933741548#1314 +-0.43216435292525485#1315 +-0.3399760691164684#1316 +-0.24439085680621755#1317 +-0.14636377183963595#1318 +-0.04687426844626337#1319 +0.05308358714285112#1320 +0.15251104907633528#1321 +0.25041467102089904#1322 +0.3458162323487072#1323 +0.43776251219453577#1324 +0.5253348137235645#1325 +0.6076581434464698#1326 +0.6839099538651353#1327 +0.753328362095355#1328 +0.8152197623487677#1329 +0.8689657562126182#1330 +0.9140293314822825#1331 +0.9499602278097037#1332 +0.9763994355559533#1333 +0.9930827828968712#1334 +0.9998435753406082#1335 +0.9966142612838874#1336 +0.9834271069652942#1337 +0.9604138740716864#1338 +0.9278045032189735#1339 +0.8859248164614908#1340 +0.8351932617857352#1341 +0.7761167321164042#1342 +0.7092855006098496#1343 +0.6353673228398167#1344 +0.5551007648044826#1345 +0.4692878234191396#1346 +0.37878591322812316#1347 +0.28449929940210755#1348 +0.1873700626194315#1349 +0.08836868610737038#1350 +-0.011515641105471527#1351 +-0.11128490783895244#1352 +-0.2099422525592064#1353 +-0.306501923689571#1354 +-0.3999991289144955#1355 +-0.4894996750654395#1356 +-0.57410930227021#1357 +-0.6529826191020013#1358 +-0.7253315494510825#1359 +-0.7904332067207822#1360 +-0.8476371166714086#1361 +-0.8963717167438338#1362 +-0.9361500669236509#1363 +-0.9665747150848376#1364 +-0.9873416682000192#1365 +-0.9982434297383107#1366 +-0.9991710729020646#1367 +-0.9901153289874269#1368 +-0.9711666799941617#1369 +-0.9425144545594192#1370 +-0.9044449362485765#1371 +-0.857338503104486#1372 +-0.8016658270358069#1373 +-0.7379831710188773#1374 +-0.6669268311019312#1375 +-0.5892067787453151#1376 +-0.5055995670213429#1377 +-0.41694057155269054#1378 +-0.3241156437153132#1379 +-0.2280522595043203#1380 +-0.12971025250041487#1381 +-0.03007222353003439#1382 +0.06986627715730269#1383 +0.1691066970980048#1384 +0.2666574588205459#1385 +0.36154386735978916#1386 +0.45281784908688705#1387 +0.5395674245475895#1388 +0.6209258206594904#1389 +0.6960801312221501#1390 +0.7642794392071385#1391 +0.8248423196727637#1392 +0.8771636483368399#1393 +0.9207206477784876#1394 +0.9550781108573155#1395 +0.9798927491593076#1396 +0.9949166230211789#1397 +0.9999996188615343#1398 +0.9950909490661519#1399 +0.9802396594410367#1400 +0.9555941391629392#1401 +0.9214006381237522#1402 +0.8780008064829905#1403 +0.8258282810123316#1404 +0.7654043523403342#1405 +0.6973327563887936#1406 +0.6222936420429795#1407 +0.5410367753288019#1408 +0.4543740479985197#1409 +0.36317136537672806#1410 +0.2683399945205851#1411 +0.1708274591406018#1412 +0.07160807225693622#1413 +-0.028326798814238986#1414 +-0.1279786378752571#1415 +-0.226351756690739#1416 +-0.32246324357531025#1417 +-0.415352784322254#1418 +-0.5040922573456266#1419 +-0.5877950071643484#1420 +-0.6656247035706814#1421 +-0.7368036979652107#1422 +-0.8006207933645937#1423 +-0.8564383504467267#1424 +-0.9036986586320765#1425 +-0.941929508543436#1426 +-0.9707489101659298#1427 +-0.9898689095649735#1428 +-0.9990984660268033#1429 +-0.9983453608741385#1430 +-0.987617118884721#1431 +-0.9670209331062237#1432 +-0.9367625938187515#1433 +-0.8971444323463876#1434 +-0.848562300262541#1435 +-0.7915016141718754#1436 +-0.7265325055880536#1437 +-0.6543041243681132#1438 +-0.5755381526216753#1439 +-0.4910215939018614#1440 +-0.40159890972594#1441 +-0.30816358199498733#1442 +-0.211649185618078#1443 +-0.1130200605403922#1444 +-0.013261676377251867#1445 +0.08662921407252257#1446 +0.1856545340510954#1447 +0.2828248552946596#1448 +0.37716928407358735#1449 +0.46774516204164157#1450 +0.5536474849665701#1451 +0.6340179452332398#1452 +0.7080535077696084#1453 +0.7750144337077156#1454 +0.8342316716099273#1455 +0.8851135424097409#1456 +0.9271516512734351#1457 +0.9599259673131953#1458 +0.9831090203969006#1459 +0.9964691731214373#1460 +0.999872935257061#1461 +0.9932862975376467#1462 +0.9767750714700341#1463 +0.9505042317672048#1464 +0.9147362679754845#1465 +0.8698285617657631#1466 +0.816229816093974#1467 +0.7544755719094801#1468 +0.6851828572069336#1469 +0.609044021886516#1470 +0.5268198200225961#1471 +0.43933180866049054#1472 +0.34745413909003786#1473 +0.2521048226148663#1474 +0.15423655808690193#1475 +0.05482721285436108#1476 +-0.04512994776555348#1477 +-0.14463618486537203#1478 +-0.24269726501638209#1479 +-0.3383333943203984#1480 +-0.4305890081865166#1481 +-0.518542319016638#1482 +-0.6013145264024473#1483 +-0.6780785978085996#1484 +-0.748067532008433#1485 +-0.8105820227066887#1486 +-0.8649974457768529#1487 +-0.910770100298956#1488 +-0.9474426410394413#1489 +-0.97464864809356#1490 +-0.9921162880319376#1491 +-0.9996710299703442#1492 +-0.9972373894245966#1493 +-0.9848396825265736#1494 +-0.962601783065463#1495 +-0.930745884781808#1496 +-0.8895902812810987#1497 +-0.8395461857492807#1498 +-0.7811136222465291#1499 +-0.7148764296321258#1500 +-0.6414964280395691#1501 +-0.5617068061885679#1502 +-0.4763047956057153#1503 +-0.38614370495060346#1504 +-0.292124394037764#1505 +-0.19518627274318584#1506 +-0.09629791473136161#1507 +0.0035526202125998304#1508 +0.10336765854973708#1509 +0.20214988141145054#1510 +0.2989122894799676#1511 +0.3926880647592674#1512 +0.4825402307009092#1513 +0.5675710141639814#1514 +0.6469308156675612#1515 +0.7198266983078874#1516 +0.7855303105217932#1517 +0.843385163534764#1518 +0.892813190779766#1519 +0.9333205237473006#1520 +0.9645024265563005#1521 +0.9860473399412646#1522 +0.9977399942494521#1523 +0.9994635603440932#1524 +0.9912008169225054#1525 +0.9730343225856573#1526 +0.9451455909399181#1527 +0.9078132769731031#1528 +0.8614103928259461#1529 +0.8064005807780915#1530 +0.7433334806876951#1531 +0.6728392381716484#1532 +0.5956222083988731#1533 +0.5124539184063026#1534 +0.42416535825576057#1535 +0.3316386780559536#1536 +0.23579837381018381#1537 +0.13760205015788235#1538 +0.03803085230559389#1539 +-0.06192033725160367#1540 +-0.16125283926712547#1541 +-0.2589741562157922#1542 +-0.35410788900102547#1543 +-0.44570349281186655#1544 +-0.5328457746525187#1545 +-0.6146640376482388#1546 +-0.6903407807606958#1547 +-0.7591198669881154#1548 +-0.8203140784362564#1549 +-0.8733119827724461#1550 +-0.9175840424553352#1551 +-0.9526879056989698#1552 +-0.9782728263056137#1553 +-0.9940831682058159#1554 +-0.9999609596895136#1555 +-0.9958474718071414#1556 +-0.9817838051698816#1557 +-0.9579104792859435#1558 +-0.9244660285360871#1559 +-0.8817846188169394#1560 +-0.8302927086658156#1561 +-0.7705047882279834#1562 +-0.7030182386411985#1563 +-0.6285073632008448#1564 +-0.5477166499443011#1565 +-0.4614533329725679#1566 +-0.370579326833965#1567 +-0.2760026145588766#1568 +-0.17866817539345065#1569 +-0.07954854287934016#1570 +0.02036591237996836#1571 +0.12007687817485184#1572 +0.21858807549515108#1573 +0.3149152130207141#1574 +0.408095821834904#1575 +0.49719887209586344#1576 +0.5813340755789376#1577 +0.6596607811423243#1578 +0.7313963742354008#1579 +0.7958240965246156#1580 +0.8523002075058284#1581 +0.9002604165466352#1582 +0.9392255210918378#1583 +0.9688061946969714#1584 +0.9887068770494445#1585 +0.998728727109482#1586 +0.9987716098640673#1587 +0.9888350968428918#1588 +0.9690184703994884#1589 +0.9395197317147739#1590 +0.9006336224346992#1591 +0.8527486797091522#1592 +0.7963433540571888#1593 +0.7319812288476018#1594 +0.6603053891601949#1595 +0.5820319962922426#1596 +0.49794313211153723#1597 +0.4088789847528897#1598 +0.31572945373601446#1599 +0.21942525838369095#1600 +0.12092863838194484#1601 +0.021223739399179705#1602 +-0.07869322017202651#1603 +-0.1778239030997941#1604 +-0.275177828368556#1605 +-0.369782267737956#1606 +-0.46069196492188513#1607 +-0.5469985802768322#1608 +-0.6278397666313447#1609 +-0.7024077855739117#1610 +-0.7699575781081692#1611 +-0.8298142090361076#1612 +-0.8813796106874666#1613 +-0.9241385586142015#1614 +-0.9576638195428573#1615 +-0.9816204201482128#1616 +-0.9957689939960187#1617 +-0.9999681732132844#1618 +-0.994176000989335#1619 +-0.9784503507943949#1620 +-0.9529483481270028#1621 +-0.91792480056797#1622 +-0.8737296518272608#1623 +-0.8208044852221184#1624 +-0.7596781115225273#1625 +-0.6909612852488008#1626 +-0.6153406022143034#1627 +-0.5335716392870412#1628 +-0.4464714049153578#1629 +-0.35491017584958534#1630 +-0.2598028016244306#1631 +-0.16209956368483314#1632 +-0.06277668048788872#1633 +0.03717344654927897#1634 +0.13675214879643402#1635 +0.2349644687770656#1636 +0.33082910145460404#1637 +0.42338819910797#1638 +0.511716941829381#1639 +0.5949327780191651#1640 +0.6722042425496124#1641 +0.742759264489685#1642 +0.8058928813825473#1643 +0.8609742829974049#1644 +0.9074531141768128#1645 +0.9448649738034854#1646 +0.9728360549427497#1647 +0.9910868797978722#1648 +0.9994350921598212#1649 +0.9977972794502282#1650 +0.9861898061522987#1651 +0.9647286503023048#1652 +0.9336282446753849#1653 +0.8931993342441357#1654 +0.8438458713175653#1655 +0.78606097938315#1656 +0.7204220259799529#1657 +0.6475848538330251#1658 +0.5682772278896909#1659 +0.48329156373276017#1660 +0.3934770100259633#1661 +0.2997309641011942#1662 +0.20299010546101035#1663 +0.10422103678666807#1664 +0.0044106259636479345#1665 +-0.09544385437604187#1666 +-0.19434469127235002#1667 +-0.29130370025527885#1668 +-0.3853520989574582#1669 +-0.47555018686732337#1670 +-0.5609967345060028#1671 +-0.6408379882143644#1672 +-0.714276200577364#1673 +-0.7805776012525157#1674 +-0.8390797285606031#1675 +-0.8891980485837959#1676 +-0.9304317956353363#1677 +-0.9623689757447501#1678 +-0.9846904831654123#1679 +-0.9971732887736847#1680 +-0.9996926685021967#1681 +-0.9922234495414972#1682 +-0.9748402618584459#1683 +-0.9477167925182539#1684 +-0.9111240502607415#1685 +-0.8654276576705933#1686 +-0.8110841979973509#1687 +-0.7486366531265098#1688 +-0.6787089782840057#1689 +-0.6019998676818485#1690 +-0.5192757733965142#1691 +-0.43136324723315195#1692 +-0.3391406820931682#1693 +-0.24352953536271474#1694 +-0.14548512201507893#1695 +-0.04598706941925612#1696 +0.053970470772899765#1697 +0.1533887558613586#1698 +0.25127443120483245#1699 +0.34664945549199166#1700 +0.4385608730069506#1701 +0.5260903352477752#1702 +0.6083632767611484#1703 +0.6845576535112877#1704 +0.753912156472218#1705 +0.8157338183759043#1706 +0.8694049376121297#1707 +0.9143892500987989#1708 +0.9502372874553822#1709 +0.976590867942398#1710 +0.9931866752949559#1711 +0.9998588896918333#1712 +0.996540844572318#1713 +0.9832656927464438#1714 +0.9601660751430733#1715 +0.9274727955055809#1716 +0.8855125142771431#1717 +0.8347044847175692#1718 +0.775556363863317#1719 +0.7086591401861929#1720 +0.6346812286318964#1721 +0.5543617920388316#1722 +0.4685033556673605#1723 +0.3779637886326811#1724 +0.2836477323602019#1725 +0.18649756170745438#1726 +0.08748396906602378#1727 +-0.012403734475959032#1728 +-0.11216750400318758#1729 +-0.21081053290806362#1730 +-0.30734721265281995#1731 +-0.40081298064423065#1732 +-0.49027395782420097#1733 +-0.5748362796806161#1734 +-0.6536550274460741#1735 +-0.7259426702469165#1736 +-0.7909769338513953#1737 +-0.848108017395044#1738 +-0.8967650859761198#1739 +-0.9364619742492493#1740 +-0.966802044028854#1741 +-0.9874821473667896#1742 +-0.9982956555064372#1743 +-0.9991345234489356#1744 +-0.9899903695030964#1745 +-0.970954559032491#1746 +-0.9422172915629393#1747 +-0.9040657003717193#1748 +-0.8568809835467744#1749 +-0.8011345951814257#1750 +-0.7373835347609137#1751 +-0.666264781807661#1752 +-0.5884889313924426#1753 +-0.5048330941033291#1754 +-0.41613313141356995#1755 +-0.32327530403005167#1756 +-0.2271874166692736#1757 +-0.12882954773931182#1758 +-0.029184456553725577#1759 +0.07075223607464673#1760 +0.16998199574774103#1761 +0.26751335150790145#1762 +0.3623718022879524#1763 +0.45360955380373474#1764 +0.5403149886012937#1765 +0.6216217746371384#1766 +0.6967175213816488#1767 +0.7648518969567075#1768 +0.8253441252037987#1769 +0.8775897877743497#1770 +0.9210668632780755#1771 +0.9553409431481533#1772 +0.9800695721080259#1773 +0.9950056698713242#1774 +0.9999999998864149#1775 +0.995002660458693#1776 +0.9800635833518199#1777 +0.9553320348860447#1778 +0.9210551245184746#1779 +0.8775753358070623#1780 +0.8253271044281046#1781 +0.7648324774385712#1782 +0.6966958971544762#1783 +0.6215981617630594#1784 +0.5402896230123407#1785 +0.4535826889444879#1786 +0.36234370658320497#1787 +0.26748430568064796#1788 +0.1699522900142862#1789 +0.0707221672448598#1790 +-0.029214588042036787#1791 +-0.12885944082227627#1792 +-0.22721677266508764#1793 +-0.32330382962330895#1794 +-0.4161605415859719#1795 +-0.5048591149814937#1796 +-0.5885133029843566#1797 +-0.6662872606004342#1798 +-0.7374038961538791#1799 +-0.8011526357302755#1800 +-0.8568965229963079#1801 +-0.9040785834568934#1802 +-0.9422273895602254#1803 +-0.9709617710460383#1804 +-0.9899946234728495#1805 +-0.9991357768706348#1806 +-0.9982938958563073#1807 +-0.9874773922266732#1808 +-0.966794340910539#1809 +-0.9364514001197477#1810 +-0.8967517464886383#1811 +-0.848092045833332#1812 +-0.790958489798018#1813 +-0.7259219379887585#1814 +-0.6536322141330055#1815 +-0.5748116132557202#1816 +-0.49024768474624164#1817 +-0.4007853634251181#1818 +-0.30731852723467856#1819 +-0.21078106590610934#1820 +-0.11213754984196339#1821 +-0.012373592447542393#1822 +0.08751399779244858#1823 +0.18652717709477906#1824 +0.2836766385012659#1825 +0.37799169670687793#1826 +0.46852998682643804#1827 +0.5543868801930514#1828 +0.6347045231087146#1829 +0.7086804082348972#1830 +0.7755753929805951#1831 +0.8347210847707713#1832 +0.8855265194040249#1833 +0.9274840657715442#1834 +0.960174497939346#1835 +0.9832711839152297#1836 +0.9965433492476736#1837 +0.9998583828478708#1838 +0.9931831619958922#1839 +0.9765843832919562#1840 +0.9502278962460459#1841 +0.9143770461644276#1842 +0.8693900428904013#1843 +0.8157163816899551#1844 +0.7538923520436499#1845 +0.6845356792194047#1846 +0.6083393521658111#1847 +0.5260646993956318#1848 +0.43853378204296184#1849 +0.3466211801001145#1850 +0.25124525390343583#1851 +0.1533589681803935#1852 +0.05394037034102778#1853 +-0.04601718184846958#1854 +-0.145514945568195#1855 +-0.24355877205264906#1856 +-0.3391690397965793#1857 +-0.4313904426092411#1858 +-0.5193015347180733#1859 +-0.6020239375502678#1860 +-0.6787311162011166#1861 +-0.7486566378975624#1862 +-0.8111018299411188#1863 +-0.8654427606145227#1864 +-0.9111364733012091#1865 +-0.9477264115283458#1866 +-0.9748469807281929#1867 +-0.9922272011381739#1868 +-0.9996934153410891#1869 +-0.9971710233926254#1870 +-0.98468522819934#1871 +-0.9623607836995489#1872 +-0.9304207483632138#1873 +-0.8891842564654433#1874 +-0.8390633294023081#1875 +-0.7805587589092471#1876 +-0.7142551033155872#1877 +-0.6408148468309454#1878 +-0.5609717802219951#1879 +-0.47552366901768395#1880 +-0.3853242824997751#1881 +-0.29127486312240225#1882 +-0.1943151215953794#1883 +-0.09541384760541509#1884 +0.0044407700101977065#1885 +0.10425101691979201#1886 +0.20301962212912839#1887 +0.2997597223835154#1888 +0.39350472257923697#1889 +0.48331795366231456#1890 +0.5683020315160732#1891 +0.6476078233265996#1892 +0.7204429318371323#1893 +0.7860796127195201#1894 +0.8438620459549884#1895 +0.8932128885709812#1896 +0.9336390432612995#1897 +0.9647365852513876#1898 +0.9861947981811614#1899 +0.9977992786801687#1900 +0.9994340786151946#1901 +0.9910828636056814#1902 +0.9728290762314595#1903 +0.9448551023020723#1904 +0.9074404485180556#1905 +0.8609589497323792#1906 +0.8058750337161689#1907 +0.7427390807499367#1908 +0.6721819244057498#1909 +0.5949085484667043#1910 +0.5116910429620009#1911 +0.42336088969859254#1912 +0.3308006543698204#1913 +0.23493516825074362#1914 +0.1367222875897472#1915 +0.03714332302553373#1916 +-0.06280676534440063#1917 +-0.16212930927617017#1918 +-0.25983191074247675#1919 +-0.35493835764565523#1920 +-0.4464983778062608#1921 +-0.5335971337685674#1922 +-0.6153643635540208#1923 +-0.6909830760312574#1924 +-0.7596977140214278#1925 +-0.8208217035757736#1926 +-0.8737443139955725#1927 +-0.9179367600513992#1928 +-0.9529574854303443#1929 +-0.9784565746207341#1930 +-0.9941792491522566#1931 +-0.999968413258218#1932 +-0.9957662235245147#1933 +-0.9816146668419067#1934 +-0.9576551408868839#1935 +-0.9241270413228225#1936 +-0.8813653698376505#1937 +-0.8297973869177182#1938 +-0.7699383428022528#1939 +-0.7023863292732867#1940 +-0.6278163037202744#1941 +-0.5469733451889683#1942 +-0.4606652097978839#1943 +-0.36975425990617233#1944 +-0.27514884767398695#1945 +-0.1777942391079601#1946 +-0.07866316927572836#1947 +0.021253876941319732#1948 +0.12095856144556782#1949 +0.21945466798743643#1950 +0.3157580560288433#1951 +0.40890649395014667#1952 +0.49796927335041663#1953 +0.5820565083781266#1954 +0.6603280271764242#1955 +0.7320017666026011#1956 +0.7963615863444993#1957 +0.8527644243577857#1958 +0.9006467221293312#1959 +0.9395300555675856#1960 +0.9690259152579552#1961 +0.9888395883204489#1962 +0.9987731030833557#1963 +0.998727207150748#1964 +0.9887023590996133#1965 +0.9687987238979044#1966 +0.9392151720892897#1967 +0.9002472927444187#1968 +0.8522844400326369#1969 +0.7958058429238293#1970 +0.731375816890965#1971 +0.6596381254564291#1972 +0.5813095479197075#1973 +0.49717271753556175#1974 +0.40806830170125163#1975 +0.3148866022857897#1976 +0.2185586600279604#1977 +0.12004695188501968#1978 +0.020335774281090385#1979 +-0.07957859165734228#1980 +-0.17869783461311994#1981 +-0.27603158787509413#1982 +-0.37060732475493247#1983 +-0.46148007575231387#1984 +-0.5477418703778104#1985 +-0.6285308092938824#1986 +-0.7030396761281532#1987 +-0.7705240029125717#1988 +-0.8303095085612607#1989 +-0.8817988360642393#1990 +-0.9244775210812064#1991 +-0.9579191322991703#1992 +-0.9817895321931679#1993 +-0.9958502156179638#1994 +-0.9999606928726213#1995 +-0.9940798934271551#1996 +-0.9782665762856902#1997 +-0.9526787428859168#1998 +-0.9175720584009519#1999 +-0.8732972972174424#2000 +-0.8202968381138436#2001 +-0.759100244157896#2002 +-0.6903189714875031#2003 +-0.6146402598431213#2004 +-0.5328202658954452#2005 +-0.44567650797790564#2006 +-0.3540796977137181#2007 +-0.25894504015316233#2008 +-0.16122308934724644#2009 +-0.0618902507258409#2010 +0.03806097482262027#2011 +0.13763190769193942#2012 +0.23582766803466082#2013 +0.33166711627264295#2014 +0.4241926563194016#2015 +0.5124798035636668#2016 +0.5956464220140248#2017 +0.6728615383101487#2018 +0.7433536445339318#2019 +0.8064184068615782#2020 +0.8614257030343491#2021 +0.9078259183318809#2022 +0.9451554371407925#2023 +0.9730412752486439#2024 +0.9912048065788938#2025 +0.9994645471305557#2026 +0.9977379683063444#2027 +0.9860423215111407#2028 +0.9644944657816552#2029 +0.9333097001695628#2030 +0.8927996125445465#2031 +0.8433689663113009#2032 +0.7855116561473892#2033 +0.7198057731708851#2034 +0.6469078288450127#2035 +0.5675461953326192#2036 +0.48251382784229224#2037 +0.3926603416820314#2038 +0.29888352318393624#2039 +0.20212035931994485#2040 +0.1033376756377367#2041 +0.003522476059450432#2042 +-0.09632791893524607#2043 +-0.19521583720571825#2044 +-0.29215322336060745#2045 +-0.38617151108069375#2046 +-0.47633130071339214#2047 +-0.5617317454435568#2048 +-0.6415195522570779#2049 +-0.7148975077626172#2050 +-0.7811324436842906#2051 +-0.8395625624367278#2052 +-0.8896040495877838#2053 +-0.9307569071393618#2054 +-0.9626099493421324#2055 +-0.9848449111276216#2056 +-0.9972396281075698#2057 +-0.9996702563670624#2058 +-0.9921125098719891#2059 +-0.97464190312707#2060 +-0.9474329966598855#2061 +-0.9107576528697868#2062 +-0.864982319668668#2063 +-0.8105643690545611#2064 +-0.7480475272018192#2065 +-0.6780564417289145#2066 +-0.6012904404259155#2067 +-0.5185165438023752#2068 +-0.4305618012719435#2069 +-0.338305027548012#2070 +-0.24266802181759525#2071 +-0.1446063574285605#2072 +-0.04509983411660629#2073 +0.054857311829817915#2074 +0.15426634164985503#2075 +0.2521339931777998#2076 +0.34748240519032947#2077 +0.43935888787260957#2078 +0.5268454417800063#2079 +0.6090679301850868#2080 +0.6852048131628486#2081 +0.7544953561460856#2082 +0.8162472309337178#2083 +0.8698434332053228#2084 +0.9147484474243518#2085 +0.9505135975323528#2086 +0.9767815299718332#2087 +0.993289784244882#2088 +0.9998734153317062#2089 +0.9964666417667453#2090 +0.9831035029053308#2091 +0.9599175188136995#2092 +0.9271403561806276#2093 +0.8850995135804554#2094 +0.8342150492155885#2095 +0.7749953838337934#2096 +0.7080322207561459#2097 +0.633994633773039#2098 +0.5536223819800354#2099 +0.4677185183495166#2100 +0.37714136589083663#2101 +0.2827959415705366#2102 +0.18562491368197392#2103 +0.08659918301533971#2104 +-0.013291818062099673#2105 +-0.11305001168715346#2106 +-0.21167864696479485#2107 +-0.308192259173622#2108 +-0.4016265162036029#2109 +-0.49104785384375327#2110 +-0.5755628036471371#2111 +-0.6543269201722473#2112 +-0.7265532184027201#2113 +-0.7915200370414769#2114 +-0.8485782491118543#2115 +-0.8971577478197825#2116 +-0.9367731428724192#2117 +-0.967028610337507#2118 +-0.9876218475852627#2119 +-0.9983470937963259#2120 +-0.9990971858558507#2121 +-0.9898646290919259#2122 +-0.970741672159859#2123 +-0.9419193853241061#2124 +-0.9036857513473486#2125 +-0.8564227880619233#2126 +-0.8006027313739196#2127 +-0.7367833168381062#2128 +-0.6656022069486314#2129 +-0.5877706198261639#2130 +-0.5040662229615295#2131 +-0.4153253630192043#2132 +-0.32243470933790386#2133 +-0.22632239462364384#2134 +-0.1279487413545418#2135 +-0.02829666655605602#2136 +0.07163813918102345#2137 +0.17085716031182666#2138 +0.26836903317466254#2139 +0.3631994513690255#2140 +0.45440090070308614#2141 +0.5410621264422896#2142 +0.6223172382654424#2143 +0.6973543619545768#2144 +0.7654237513737662#2145 +0.8258452796846828#2146 +0.8780152349491458#2147 +0.9214123522192472#2148 +0.9556030218444039#2149 +0.9802456219556541#2150 +0.995093931838447#2151 +0.9999995920886321#2152 +0.9949135869705855#2153 +0.9798867341662368#2154 +0.9550691770215901#2155 +0.9207088843640407#2156 +0.8771491728798204#2157 +0.824825276807153#2158 +0.7642599992196163#2159 +0.6960584883506457#2160 +0.6209021911524217#2161 +0.5395420445031802#2162 +0.4527909720941514#2163 +0.3615157619647542#2164 +0.2666284058430285#2165 +0.16907698682575256#2166 +0.06983620644553508#2167 +-0.030102354224705447#2168 +-0.1297401421220481#2169 +-0.22808160940569652#2170 +-0.3241441606419197#2171 +-0.41696797057282303#2172 +-0.5056255743730492#2173 +-0.5892311345717338#2174 +-0.6669492920476956#2175 +-0.7380035126616422#2176 +-0.8016838461286017#2177 +-0.8573540196064917#2178 +-0.9044577951240342#2179 +-0.9425245273266959#2180 +-0.9711738660094966#2181 +-0.99011955645053#2182 +-0.9991722995735218#2183 +-0.9982416433616265#2184 +-0.9873368866240788#2185 +-0.9665669860855675#2186 +-0.9361394677266565#2187 +-0.896358353252788#2188 +-0.8476211224098967#2189 +-0.7904147414981781#2190 +-0.7253107977657867#2191 +-0.6529597882979938#2192 +-0.5740846204653375#2193 +-0.48947338887213754#2194 +-0.3999715009757185#2195 +-0.3064732300545506#2196 +-0.2099127799252589#2197 +-0.11125495068689388#2198 +-0.01148549875726277#2199 +0.08839871247934979#2200 +0.18739967300159813#2201 +0.28452819793731066#2202 +0.3788138111717516#2203 +0.4693144420241625#2204 +0.5551258381065974#2205 +0.6353906003148769#2206 +0.709306749677019#2207 +0.7761357404620275#2208 +0.8352098394847063#2209 +0.8859387978749215#2210 +0.9278157486492024#2211 +0.9604222711580919#2212 +0.9834325718069646#2213 +0.9966167392779312#2214 +0.999843041727728#2215 +0.9930792430087505#2216 +0.9763929247619841#2217 +0.9499508111635871#2218 +0.9140171030720339#2219 +0.8689508382204706#2220 +0.8152023038303673#2221 +0.7533085374904468#2222 +0.6838879612546183#2223 +0.6076342025732385#2224 +0.5253091637969104#2225 +0.43773540950004725#2226 +0.34578794768754867#2227 +0.2503854870040551#2228 +0.15248125730085532#2229 +0.05305348527830788#2230 +-0.046904379631989734#2231 +-0.1463935914855311#2232 +-0.24442008696423675#2233 +-0.3400044177285349#2234 +-0.43219153674140776#2235 +-0.5200603407826888#2236 +-0.6027328738079627#2237 +-0.6793830991951469#2238 +-0.7492451532293688#2239 +-0.8116209973600432#2240 +-0.8658873927713292#2241 +-0.9115021275783626#2242 +-0.9480094344291783#2243 +-0.9750445443814343#2244 +-0.9923373315531067#2245 +-0.9997150121310117#2246 +-0.9971038707695518#2247 +-0.9845299971300822#2248 +-0.9621190252016383#2249 +-0.9300948780076469#2250 +-0.8887775302410945#2251 +-0.8385798111831653#2252 +-0.780003279849526#2253 +-0.7136332135784356#2254 +-0.6401327601330475#2255 +-0.5602363117481685#2256 +-0.4747421673258055#2257 +-0.3845045560964199#2258 +-0.2904251024428272#2259 +-0.19344381716740122#2260 +-0.09452970521486317#2261 +0.005328916304815557#2262 +0.10513429305428211#2263 +0.2038892027003272#2264 +0.3006069188298006#2265 +0.3943210699937632#2266 +0.4840952953715645#2267 +0.569032600578643#2268 +0.64828432013791#2269 +0.7210585970646649#2270 +0.7866282948398333#2271 +0.8443382627177061#2272 +0.8936118817756269#2273 +0.9339568262996617#2274 +0.9649699829403923#2275 +0.9863414784882509#2276 +0.9978577760242008#2277 +0.9994038085100443#2278 +0.9909641285002334#2279 +0.9726230624876389#2280 +0.9445638683411081#2281 +0.9070669042534167#2282 +0.8605068274948806#2283 +0.8053488509617559#2284 +0.7421440949227586#2285 +0.6715240804075154#2286 +0.5941944192571897#2287 +0.5109277638842079#2288 +0.42255608718475995#2289 +0.3299623697406341#2290 +0.23407177736911827#2291 +0.135842417171973#2292 +0.03625576444597857#2293 +-0.0636931438937977#2294 +-0.16300565139394135#2295 +-0.26068946030786144#2296 +-0.3557685463068644#2297 +-0.44729291059261544#2298 +-0.534348071971104#2299 +-0.6160642040464467#2300 +-0.6916248262387088#2301 +-0.7602749617879662#2302 +-0.8213286812325286#2303 +-0.8741759559893822#2304 +-0.9182887535581434#2305 +-0.9532263134472572#2306 +-0.9786395511071335#2307 +-0.9942745458675742#2308 +-0.9999750780291754#2309 +-0.9956841897589236#2310 +-0.9814447541940361#2311 +-0.9573990470677456#2312 +-0.9237873251372041#2313 +-0.8809454256173832#2314 +-0.8293014106066361#2315 +-0.7693712900317081#2316 +-0.7017538658471201#2317 +-0.6271247490039753#2318 +-0.5462296089686645#2319 +-0.45987672324004214#2320 +-0.3689289013078397#2321 +-0.2742948637454506#2322 +-0.17692016257434437#2323 +-0.07777773362082588#2324 +0.022141824737131294#2325 +0.12184014930142922#2326 +0.2203210873689061#2327 +0.3166006499598618#2328 +0.4097168435106797#2329 +0.4987392817955214#2330 +0.5827784820379505#2331 +0.6609947523288111#2332 +0.7326065815502183#2333 +0.7968984479763155#2334 +0.8532279685298386#2335 +0.901032317261481#2336 +0.9398338489207327#2337 +0.9692448714293358#2338 +0.9889715195723757#2339 +0.9988166912023702#2340 +0.9986820166187732#2341 +0.9885688414455068#2342 +0.968578213185931#2343 +0.9389098715895922#2344 +0.8998602529186711#2345 +0.8518195280548398#2346 +0.7952677040407854#2347 +0.7307698280085084#2348 +0.6589703414151602#2349 +0.5805866409970266#2350 +0.49640191077847906#2351 +0.407257296756089#2352 +0.31404350244587664#2353 +0.21769188926820557#2354 +0.1191651706923382#2355 +0.019447793121681437#2356 +-0.08046390036926145#2357 +-0.17957162516554395#2358 +-0.27688512964165996#2359 +-0.37143208942845196#2360 +-0.4622678225568002#2361 +-0.5484847284075876#2362 +-0.6292213561570731#2363 +-0.7036710121087649#2364 +-0.7710898199101781#2365 +-0.8308041531194559#2366 +-0.8822173658581055#2367 +-0.9248157542993909#2368 +-0.9581736894271621#2369 +-0.9819578697802895#2370 +-0.9959306516906896#2371 +-0.9999524237403014#2372 +-0.993983001712226#2373 +-0.9780820300981395#2374 +-0.9524083861502476#2375 +-0.917218592432299#2376 +-0.8728642537309242#2377 +-0.8197885439368322#2378 +-0.7585217779977886#2379 +-0.6896761131869558#2380 +-0.6139394326297725#2381 +-0.532068472203148#2382 +-0.44488125948072355#2383 +-0.35324894027176074#2384 +-0.2580870744201778#2385 +-0.16034648783323305#2386 +-0.061003772143360675#2387 +0.03894847307260204#2388 +0.13851155802027681#2389 +0.23669068126604687#2390 +0.33250486946414387#2391 +0.4249967789180523#2392 +0.5132422610422692#2393 +0.5963595961494876#2394 +0.6735183033022544#2395 +0.7439474382039768#2396 +0.8069432962194937#2397 +0.861876443559176#2398 +0.9081980063732902#2399 +0.9454451549180705#2400 +0.9732457279975278#2401 +0.9913219514750999#2402 +0.9994932137010042#2403 +0.9976778701241392#2404 +0.9858940590574525#2405 +0.9642595204459123#2406 +0.9329904194478973#2407 +0.8923991865843892#2408 +0.8428913960364823#2409 +0.7849617132822316#2410 +0.7191889525627104#2411 +0.6462302935614438#2412 +0.5668147150822461#2413 +0.4817357113339816#2414 +0.39184336359872296#2415 +0.2980358465005815#2416 +0.20125045374175918#2417 +0.1024542329737048#2418 +0.0026343233766439834#2419 +-0.09721190750880472#2420 +-0.19608682914840989#2421 +-0.29300251600885235#2422 +-0.3869906185830895#2423 +-0.47711203881853564#2424 +-0.5624663132743792#2425 +-0.6422006102546296#2426 +-0.7155182510205144#2427 +-0.7816866699410908#2428 +-0.840044734046876#2429 +-0.890009348851936#2430 +-0.9310812844412447#2431 +-0.9628501636109706#2432 +-0.9849985622218451#2433 +-0.9973051807962356#2434 +-0.999647055669374#2435 +-0.9920007876016487#2436 +-0.9744427755760723#2437 +-0.9471484534448972#2438 +-0.9103905370525548#2439 +-0.8645362993490856#2440 +-0.8100439007202268#2441 +-0.7474578112002859#2442 +-0.6774033703075353#2443 +-0.6005805388584559#2444 +-0.5177569051906351#2445 +-0.42976001567382827#2446 +-0.33746910614018294#2447 +-0.2418063168504405#2448 +-0.14372747877327008#2449 +-0.0442125632381852#2450 +0.05574410961404525#2451 +0.155143805749565#2452 +0.2529933562617591#2453 +0.34831508078667095#2454 +0.44015655616202054#2455 +0.5276001327246129#2456 +0.6097721031624384#2457 +0.6858514323093241#2458 +0.7550779606569172#2459 +0.8167599996172166#2460 +0.8702812426463021#2461 +0.9151069231755982#2462 +0.9507891578226558#2463 +0.9769714214938605#2464 +0.9933921096653152#2465 +0.9998871522487686#2466 +0.9963916529257024#2467 +0.9829405375698944#2468 +0.959668205279632#2469 +0.9268071855063493#2470 +0.8846858146972121#2471 +0.8337249556658711#2472 +0.774433792470347#2473 +0.7074047428142367#2474 +0.633307538804846#2475 +0.5528825352113574#2476 +0.4669333120847054#2477 +0.3763186456513355#2478 +0.28194392770502347#2479 +0.18475211923135468#2480 +0.08571432865325745#2481 +-0.014179891163352991#2482 +-0.11393243019470806#2483 +-0.212546594044612#2484 +-0.3090370625853853#2485 +-0.402439734950877#2486 +-0.49182136251362973#2487 +-0.5762888735966745#2488 +-0.6549982967505166#2489 +-0.7271631934368789#2490 +-0.7920625158626148#2491 +-0.8490478114509101#2492 +-0.8975497019650812#2493 +-0.9370835725477036#2494 +-0.9672544138320761#2495 +-0.9877607687452395#2496 +-0.9983977445674013#2497 +-0.9990590601522629#2498 +-0.9897381078531023#2499 +-0.9705280195441958#2500 +-0.9416207360779147#2501 +-0.9033050894751768#2502 +-0.8559639170113676#2503 +-0.8000702360328346#2504 +-0.7361825177239204#2505 +-0.664939107047496#2506 +-0.5870518446130994#2507 +-0.5032989542008693#2508 +-0.4145172670067797#2509 +-0.32159386030194986#2510 +-0.22545719404978#2511 +-0.12706783404090483#2512 +-0.027408854237334586#2513 +0.07252398577761245#2514 +0.17173219009991203#2515 +0.26922450314584817#2516 +0.36402681395014#2517 +0.4551918891607088#2518 +0.5418088374812179#2519 +0.6230122109958052#2520 +0.6979906524385796#2521 +0.7659950020072227#2522 +0.8263457827200938#2523 +0.8784399895256259#2524 +0.9217571143294733#2525 +0.9558643467393337#2526 +0.9804208985633203#2527 +0.9951814088529242#2528 +0.9999983954685079#2529 +0.9948237286720926#2530 +0.9797091120237905#2531 +0.9548055657769237#2532 +0.9203619179335726#2533 +0.8767223180374318#2534 +0.8243227985453299#2535 +0.7636869181350534#2536 +0.6954205304801045#2537 +0.620205730760064#2538 +0.5387940403910272#2539 +0.45199889807203436#2540 +0.3606875321744773#2541 +0.26577229568287974#2542 +0.16820155026545985#2543 +0.068950190557828#2544 +-0.03099009666195487#2545 +-0.13062074107985552#2546 +-0.2289462662303628#2547 +-0.32498423596827036#2548 +-0.41777507064588915#2549 +-0.5063916349156925#2550 +-0.5899485013602381#2551 +-0.6676107973902402#2552 +-0.738602547015509#2553 +-0.8022144241405411#2554 +-0.8578108399163944#2555 +-0.9048362933343682#2556 +-0.9428209216084585#2557 +-0.9713851948889993#2558 +-0.9902437083994649#2559 +-0.9992080341066545#2560 +-0.9981886034313139#2561 +-0.9871956021877676#2562 +-0.966338868810637#2563 +-0.9358267968855071#2564 +-0.8959642529491038#2565 +-0.8471495303636348#2566 +-0.7898703697011723#2567 +-0.7246990854010827#2568 +-0.6522868473933305#2569 +-0.5733571748237859#2570 +-0.48869870689008327#2571 +-0.39915732301944756#2572 +-0.30562769112106847#2573 +-0.20904432836008902#2574 +-0.11037226377100239#2575 +-0.010597396006535125#2576 +0.0892833574357961#2577 +0.18827202108378255#2578 +0.2853795329315549#2579 +0.37963562682020546#2580 +0.4700985270165206#2581 +0.5558643581247975#2582 +0.6360761763110162#2583 +0.7099325316023618#2584 +0.7766954757104277#2585 +0.8356979353665813#2586 +0.8863503774975581#2587 +0.9281466996450561#2588 +0.9606692867742049#2589 +0.9835931839449478#2590 +0.9966893431543875#2591 +0.9998269119087179#2592 +0.992974540658088#2593 +0.9762006960309414#2594 +0.9496729767380968#2595 +0.9136564389818304#2596 +0.8685109481019182#2597 +0.8146875829201173#2598 +0.7527241287096857#2599 +0.6832397038226994#2600 +0.6069285736641322#2601 +0.5245532138214233#2602 +0.43693669166044735#2603 +0.34495444250846585#2604 +0.2495255225937167#2605 +0.15160342613938146#2606 +0.052166558364490814#2607 +-0.047791540417606526#2608 +-0.14727212192563383#2609 +-0.24528120907307063#2610 +-0.3408395274586362#2611 +-0.4329922899524019#2612 +-0.520818736613183#2613 +-0.6034413346175079#2614 +-0.6800345462775168#2615 +-0.7498330775406523#2616 +-0.8121395245548596#2617 +-0.8663313418973455#2618 +-0.911867062842657#2619 +-0.9482917095192162#2620 +-0.9752413388978184#2621 +-0.9924466791900753#2622 +-0.9997358203231163#2623 +-0.9970359316082094#2624 +-0.9843739894409296#2625 +-0.9618765077619307#2626 +-0.9297682739714707#2627 +-0.888370102928013#2628 +-0.8380956314722081#2629 +-0.7794471855043118#2630 +-0.713010760909837#2631 +-0.6394501684823696#2632 +-0.5595004013455463#2633 +-0.4739602911447193#2634 +-0.38368452638521455#2635 +-0.28957511266730906#2636 +-0.19257236014443638#2637 +-0.0936454882549586#2638 +0.006217058398080305#2639 +0.10601748625869184#2640 +0.2047586224413277#2641 +0.3014538781527306#2642 +0.3951371063610338#2643 +0.48487225521753735#2644 +0.5697627207773633#2645 +0.6489603055696946#2646 +0.7216736935065267#2647 +0.7871763564514449#2648 +0.8448138134486051#2649 +0.8940101700801013#2650 +0.934273872612625#2651 +0.9652026194398814#2652 +0.986487380747257#2653 +0.9979154862355749#2654 +0.9993727500524254#2655 +0.9908446116994578#2656 +0.9724162815160672#2657 +0.9442718892858502#2658 +0.9066926444726718#2659 +0.860054026468659#2660 +0.8048220329282305#2661 +0.7415485236735729#2662 +0.6708657066937176#2663 +0.5934798213312947#2664 +0.5101640817724733#2665 +0.42175095134640345#2666 +0.32912382482680763#2667 +0.23320820184341287#2668 +0.13496243959558005#2669 +0.035368177263958724#2670 +-0.06457947220371922#2671 +-0.16388186493227264#2672 +-0.26154680423856425#2673 +-0.3565984543327818#2674 +-0.4480870905470817#2675 +-0.5350985886705324#2676 +-0.6167635585760615#2677 +-0.6922660308792223#2678 +-0.7608516098345607#2679 +-0.8218350110085325#2680 +-0.8746069084150397#2681 +-0.918640022699266#2682 +-0.9534943895386959#2683 +-0.9788217556211913#2684 +-0.9943690582769701#2685 +-0.9999809539971505#2686 +-0.9956013705747425#2687 +-0.9812740673596052#2688 +-0.9571421980294875#2689 +-0.9234468802458005#2690 +-0.8805247864856478#2691 +-0.8288047801217232#2692 +-0.7688036303612542#2693 +-0.7011208488589045#2694 +-0.6264326995944929#2695 +-0.54548544186685#2696 +-0.4590878739175849#2697 +-0.3681032516864081#2698 +-0.2734406634431365#2699 +-0.17604594647820584#2700 +-0.07689223660911715#2701 +0.023029755070976092#2702 +0.12272164105102494#2703 +0.22118733296007248#2704 +0.31744299415299343#2705 +0.4105268698810389#2706 +0.4995088968273724#2707 +0.5834999959922931#2708 +0.6616609560767109#2709 +0.7332108186040404#2710 +0.797434680999148#2711 +0.8536908396585681#2712 +0.9014172016407891#2713 +0.9401369009131222#2714 +0.9694630630394689#2715 +0.9891026707018031#2716 +0.9988594914323538#2717 +0.9986360383035573#2718 +0.988434543985213#2719 +0.9683569384363839#2720 +0.9386038304549402#2721 +0.8994725032607627#2722 +0.8513539441400785#2723 +0.7947289378297411#2724 +0.730163262675065#2725 +0.6583020375596216#2726 +0.5798632760906015#2727 +0.4956307124441966#2728 +0.4064459705527783#2729 +0.31320015487677#2730 +0.2168249467834381#2731 +0.11828329549464342#2732 +0.018559796616524828#2733 +-0.08134914561433308#2734 +-0.18044527407266456#2735 +-0.2777384529997385#2736 +-0.37225656111256417#2737 +-0.4630552047184104#2738 +-0.5492271537844082#2739 +-0.6299114066801492#2740 +-0.7043017930213666#2741 +-0.7716550286579311#2742 +-0.8312981423233815#2743 +-0.8826351997413644#2744 +-0.9251532580039342#2745 +-0.9584274907275325#2746 +-0.9821254327777841#2747 +-0.9960103021512207#2748 +-0.9999433658227904#2749 +-0.9938853259203851#2750 +-0.9778967123761879#2751 +-0.9521372781315993#2752 +-0.9168644029386548#2753 +-0.8724305217066197#2754 +-0.8192796030888767#2755 +-0.7579427134948966#2756 +-0.6890327108502228#2757 +-0.6132381211226626#2758 +-0.531316258798414#2759 +-0.4440856600460539#2760 +-0.3524179041737139#2761 +-0.2572289050967394#2762 +-0.15946975982860834#2763 +-0.06011724543396326#2764 +0.039835940604938974#2765 +0.13939109909332772#2766 +0.23755350779614662#2767 +0.3333423603738149#2768 +0.425800566274961#2769 +0.5140043136688397#2770 +0.5970722998677733#2771 +0.6741745370122875#2772 +0.7445406450354447#2773 +0.8074675490458203#2774 +0.862326504219411#2775 +0.908569378010082#2776 +0.9457341269087781#2777 +0.9734494130295364#2778 +0.9914383143948933#2779 +0.9995210918487465#2780 +0.997616984950588#2781 +0.9857450189071303#2782 +0.9640238144787292#2783 +0.932670402759958#2784 +0.8919980566766509#2785 +0.8424131608663822#2786 +0.7844111512175009#2787 +0.7185715646375037#2788 +0.6455522485118246#2789 +0.5660827877102146#2790 +0.4809572148158928#2791 +0.39102607641444626#2792 +0.29718793471350063#2793 +0.20038038940616668#2794 +0.10157070948483571#2795 +0.001746168609144461#2796 +-0.09809581940608277#2797 +-0.1969576664199707#2798 +-0.2938515775365379#2799 +-0.38780942082477593#2800 +-0.4778924005728819#2801 +-0.5632004374246865#2802 +-0.6428811616750538#2803 +-0.7161384298662196#2804 +-0.7822402795900505#2805 +-0.8405262430144722#2806 +-0.8904139460597256#2807 +-0.9314049272876644#2808 +-0.9630896183636759#2809 +-0.9851514363280947#2810 +-0.9973699467884874#2811 +-0.9996230664272368#2812 +-0.9918882828176945#2813 +-0.9742428793609076#2814 +-0.9468631630954215#2815 +-0.9100227030956302#2816 +-0.8640895970600148#2817 +-0.8095227934006172#2818 +-0.746867505582215#2819 +-0.6767497645296058#2820 +-0.5998701635335436#2821 +-0.5169968581541643#2822 +-0.4289578910645463#2823 +-0.33663291852203614#2824 +-0.24094442113370063#2825 +-0.14284848673503256#2826 +-0.04332525747633915#2827 +0.056630863433631995#2828 +0.15602114747584864#2829 +0.25385251978622037#2830 +0.34914748163137366#2831 +0.44095387725287755#2832 +0.5283544074928413#2833 +0.610475795143881#2834 +0.6864975104463086#2835 +0.7556599695502599#2836 +0.8172721240264376#2837 +0.8707183655935856#2838 +0.9154646770729435#2839 +0.9510639681113735#2840 +0.9771605423603803#2841 +0.9934936514764484#2842 +0.9999001004322978#2843 +0.9963158781076524#2844 +0.9827767968671937#2845 +0.9594181347352508#2846 +0.9264732837424994#2847 +0.8842714179499392#2848 +0.8332342044504877#2849 +0.7738715902107717#2850 +0.7067767068496035#2851 +0.6326199442629082#2852 +0.5521422523094861#2853 +0.4661477374849479#2854 +0.3754956285554135#2855 +0.281091691427704#2856 +0.1838791790358073#2857 +0.08482940666935936#2858 +-0.015067953087655503#2859 +-0.11481475883822152#2860 +-0.21341437347118883#2861 +-0.3098816222298437#2862 +-0.4032526362524221#2863 +-0.4925944832311636#2864 +-0.5770144889635445#2865 +-0.6556691566578302#2866 +-0.7277725948741954#2867 +-0.7926043698922097#2868 +-0.8495167040464284#2869 +-0.8979409481066987#2870 +-0.9373932630332972#2871 +-0.9674794543366784#2872 +-0.9878989107385114#2873 +-0.9984476077802041#2874 +-0.9990201463678514#2875 +-0.9896108058851415#2876 +-0.9703136013518633#2877 +-0.9413213440569057#2878 +-0.902923715051594#2879 +-0.8555043707523807#2880 +-0.7995371095727526#2881 +-0.7355811378860999#2882 +-0.6642754826204825#2883 +-0.5863326063127988#2884 +-0.5025312884186264#2885 +-0.41370884400533103#2886 +-0.3207527575766946#2887 +-0.22459181562111544#2888 +-0.12618682648403282#2889 +-0.026521020288540302#2890 +0.07340977517499168#2891 +0.17260708443102024#2892 +0.27007976075572954#2893 +0.3648538893874657#2894 +0.4559825185611017#2895 +0.5425551211370541#2896 +0.623706692287481#2897 +0.6986263923385901#2898 +0.7665656484126308#2899 +0.8268456339206427#2900 +0.878864051173344#2901 +0.9221011493405477#2902 +0.9561249176296516#2903 +0.9805954017946731#2904 +0.995268100846702#2905 +0.9999964100269597#2906 +0.9947330856330885#2907 +0.979530717062608#2908 +0.9545412013570396#2909 +0.920014225496878#2910 +0.876294771611817#2911 +0.8238196700333464#2912 +0.7631132346304763#2913 +0.6947820240388727#2914 +0.6195087811274721#2915 +0.5380456112574195#2916 +0.45120646749391313#2917 +0.35985901785623386#2918 +0.26491597586570953#2919 +0.16732598101391277#2920 +0.06806412027043987#2921 +-0.03187781466376874#2922 +-0.13150123701126137#2923 +-0.22981074246706656#2924 +-0.3258240549494714#2925 +-0.41858184117793273#2926 +-0.507157296014103#2927 +-0.5906654027924112#2928 +-0.6682717761140383#2929 +-0.7392009987500107#2930 +-0.8027443693538329#2931 +-0.8582669835710771#2932 +-0.9052140777938206#2933 +-0.9431165721752354#2934 +-0.9715957575203611#2935 +-0.9903670792231963#2936 +-0.9992429804422601#2937 +-0.9981347761065544#2938 +-0.987053539027478#2939 +-0.9661099892629551#2940 +-0.9355133878392158#2941 +-0.8955694458837944#2942 +-0.8466772700609979#2943 +-0.7893253748300435#2944 +-0.724086801370063#2945 +-0.6516133919420634#2946 +-0.5726292768965259#2947 +-0.4879236394023083#2948 +-0.3983428301892924#2949 +-0.3047819110916564#2950 +-0.2081757118858963#2951 +-0.1094894897807127#2952 +-0.009709284886053158#2953 +0.090167931973725#2954 +0.18914422066277686#2955 +0.28623064282173216#2956 +0.38045714301288247#2957 +0.47088224119345734#2958 +0.5566024396729995#2959 +0.6367612505636312#2960 +0.7105577535239129#2961 +0.7772545982901459#2962 +0.8361853720364713#2963 +0.8867612579515394#2964 +0.9284769185014516#2965 +0.9609155445953574#2966 +0.9837530202041103#2967 +0.9967611608204933#2968 +0.9998099934033869#2969 +0.9928690550254331#2970 +0.9760076972485352#2971 +0.9493943931859762#2972 +0.9132950541747605#2973 +0.8680703728774336#2974 +0.8141722193602262#2975 +0.7521391261567218#2976 +0.6825909074287959#2977 +0.6062224659883935#2978 +0.523796850058337#2979 +0.4361376291467138#2980 +0.3441206652125872#2981 +0.24866536134282327#2982 +0.1507254753803607#2983 +0.05127959029111491#2984 +-0.04867866351354105#2985 +-0.1481505362033963#2986 +-0.2461421377075628#2987 +-0.3416743683355274#2988 +-0.43379270161761196#2989 +-0.521576721617934#2990 +-0.6041493194261889#2991 +-0.6806854569399482#2992 +-0.7504204103726574#2993 +-0.8126574111209275#2994 +-0.8667746076460986#2995 +-0.9122312788092578#2996 +-0.9485732365781204#2997 +-0.9754373641237138#2998 +-0.9925552439637022#2999 +-0.9997558399011433#3000 +-0.9969672059616304#3001 +-0.9842172052536875#3002 +-0.9616332315697985#3003 +-0.9294409365097438#3004 +-0.8879619748444056#3005 +-0.8376107906476223#3006 +-0.778890476308#3007 +-0.712387745796065#3008 +-0.6387670724122129#3009 +-0.5587640495891363#3010 +-0.4731780410854005#3011 +-0.38286419400700217#3012 +-0.2887248944601604#3013 +-0.1917007512076325#3014 +-0.09276119741688045#3015 +0.007105195595686342#3016 +0.10690059584252641#3017 +0.20562788067234633#3018 +0.30230059969002754#3019 +0.39595283104289725#3020 +0.48564883259258895#3021 +0.5704923915411738#3022 +0.649635779093189#3023 +0.7222882206815403#3024 +0.7877237971255806#3025 +0.8452886977756067#3026 +0.8944077531727492#3027 +0.9345901819520811#3028 +0.9654344945677839#3029 +0.9866325048439754#3030 +0.9979724092691066#3031 +0.9993409032666355#3032 +0.9907243132969028#3033 +0.9722087334786201#3034 +0.9439791653648948#3035 +0.9063176694688648#3036 +0.8596005470082881#3037 +0.8042945800281633#3038 +0.7409523674688342#3039 +0.670206803780042#3040 +0.5927647552487915#3041 +0.5093999972250692#3042 +0.42094548281432353#3043 +0.32828502028537193#3044 +0.23234444235032745#3045 +0.13408235555017892#3046 +0.0344805621751064#3047 +-0.06546574957946144#3048 +-0.16475794920433068#3049 +-0.26240394186248667#3050 +-0.3574280810727624#3051 +-0.4488809170469727#3052 +-0.5358486832783511#3053 +-0.6174624265944348#3054 +-0.6929066894499258#3055 +-0.7614276577089293#3056 +-0.8223406925066218#3057 +-0.8750371709344767#3058 +-0.9189905671991826#3059 +-0.9537617134943233#3060 +-0.9790031880199306#3061 +-0.9944627863062665#3062 +-0.9999860411575177#3063 +-0.9955177660369557#3064 +-0.9811026064725701#3065 +-0.9568845939737097#3066 +-0.9231057069158529#3067 +-0.8801034527726663#3068 +-0.8283074958528935#3069 +-0.7682353642366102#3070 +-0.7004872788057198#3071 +-0.6257401560353084#3072 +-0.5447408444679848#3073 +-0.45829866245011713#3074 +-0.36727731169044214#3075 +-0.27258624743809257#3076 +-0.17517159150637399#3077 +-0.07600667893635255#3078 +0.0239176672451336#3079 +0.12360303600163591#3080 +0.22205340408014085#3081 +0.3182850879461725#3082 +0.41133657242450644#3083 +0.5002781178409661#3084 +0.5842210496739159#3085 +0.6623266378963246#3086 +0.7338144772889486#3087 +0.7979702849913142#3088 +0.8541530373799495#3089 +0.901801374964536#3090 +0.9404392113063745#3091 +0.969680489916708#3092 +0.9892330416055432#3093 +0.9989015037396196#3094 +0.9985892722412621#3095 +0.9882994668243924#3096 +0.9681348998233783#3097 +0.9382970489261745#3098 +0.8990840440758637#3099 +0.8508876886548145#3100 +0.7941895447147971#3101 +0.7295561213681458#3102 +0.6576332144159718#3103 +0.5791394537699889#3104 +0.49485912313998487#3105 +0.40563432373024166#3106 +0.31235656024266445#3107 +0.21595783325649234#3108 +0.11740132698658906#3109 +0.017671785465154324#3110 +-0.08223432669513268#3111 +-0.18131878064613588#3112 +-0.2785915572769423#3113 +-0.37308073915756135#3114 +-0.4638422216166124#3115 +-0.5499691459231215#3116 +-0.6306009603191937#3117 +-0.704932018368717#3118 +-0.7722196287102416#3119 +-0.8317914757835613#3120 +-0.8830523373845538#3121 +-0.9254900319286898#3122 +-0.9586805360001208#3123 +-0.9822922210534869#3124 +-0.9960891669367201#3125 +-0.9999335191272192#3126 +-0.9937868661286703#3127 +-0.9777106232660219#3128 +-0.951865419043858#3129 +-0.9165094901994781#3130 +-0.8719961014867792#3131 +-0.8187700159716086#3132 +-0.7573630511062297#3133 +-0.6883887649851336#3134 +-0.6125363258753749#3135 +-0.530563626275056#3136 +-0.4432897103020118#3137 +-0.3515865900757242#3138 +-0.2563705328604733#3139 +-0.1585929060257105#3140 +-0.05923067129778288#3141 +0.040723376718695616#3142 +0.14027053021635935#3143 +0.23841614694337318#3144 +0.3341795883400279#3145 +0.4266040177550728#3146 +0.5147659608412467#3147 +0.597784532605696#3148 +0.6748302389216413#3149 +0.7451332645594977#3150 +0.807991164926182#3151 +0.8627758846592893#3152 +0.908940032948667#3153 +0.9460223528844458#3154 +0.9736523301836125#3155 +0.99155389524625#3156 +0.9995481815517231#3157 +0.9975553128338268#3158 +0.985595201178036#3159 +0.9637873480665278#3160 +0.9323496503588747#3161 +0.8915962231386506#3162 +0.8419342611793482#3163 +0.783859970388803#3164 +0.7179536098837859#3165 +0.6448736942327173#3166 +0.5653504137957747#3167 +0.4801783389041825#3168 +0.3902084807761133#3169 +0.29633978849390213#3170 +0.19951016700196894#3171 +0.10068710587064418#3172 +8.58012460191664E-4#3173 +-0.09897965392714189#3174 +-0.19782834833075857#3175 +-0.2947004072712111#3176 +-0.3886279171572114#3177 +-0.4786723853582849#3178 +-0.5639341173129099#3179 +-0.6435612059791769#3180 +-0.7167580438083482#3181 +-0.7827932721924921#3182 +-0.8410070889579382#3183 +-0.8908178408904955#3184 +-0.931727835422099#3185 +-0.9633283134104351#3186 +-0.9853035333251733#3187 +-0.9974339260329675#3188 +-0.9995982886596559#3189 +-0.991774995609316#3190 +-0.9740422146400699#3191 +-0.9465771258376843#3192 +-0.9096541512907214#3193 +-0.8636422131557419#3194 +-0.8090010475090663#3195 +-0.7462766108158684#3196 +-0.6760956249136447#3197 +-0.5991593150147811#3198 +-0.5162364032960245#3199 +-0.4281554280805988#3200 +-0.33579646535715757#3201 +-0.24008233535141982#3202 +-0.14196938201151837#3203 +-0.04243791753539556#3204 +0.057517572584630666#3205 +0.1568983661321727#3206 +0.25471148306902575#3207 +0.34997960706347403#3208 +0.44175085051201957#3209 +0.5291082654856638#3210 +0.6111790055705121#3211 +0.6871430470606158#3212 +0.7562413823637792#3213 +0.8177836037545257#3214 +0.8711548016998724#3215 +0.9158217088321214#3216 +0.9513380281801238#3217 +0.9773488924210882#3218 +0.9935944095975676#3219 +0.9999122598719884#3220 +0.9962393173728123#3221 +0.9826122809273776#3222 +0.959167307379348#3223 +0.9261386511545373#3224 +0.8838563236681221#3225 +0.8327427959596674#3226 +0.7733087775021505#3227 +0.7061481133617248#3228 +0.6319318506941176#3229 +0.5514015338632693#3230 +0.4653617951751706#3231 +0.374672315257837#3232 +0.2802392334166466#3233 +0.18300609378993019#3234 +0.08394441776783579#3235 +-0.015956003128259934#3236 +-0.1156969969154514#3237 +-0.21428198455380562#3238 +-0.310725937434704#3239 +-0.40406521946109236#3240 +-0.4933672153808272#3241 +-0.5777396491699932#3242 +-0.6563394993599873#3243 +-0.7283814222293667#3244 +-0.7931455986987139#3245 +-0.8499849265249375#3246 +-0.8983314859329812#3247 +-0.9377022140824873#3248 +-0.9677037316720184#3249 +-0.9880362734550029#3250 +-0.9984966833949899#3251 +-0.9989804445336107#3252 +-0.9894827232894784#3253 +-0.9700984177537353#3254 +-0.941021209499695#3255 +-0.9025416283805849#3256 +-0.8550441496512888#3257 +-0.7990033524186914#3258 +-0.7349791778041159#3259 +-0.6636113341967335#3260 +-0.5856129054987965#3261 +-0.5017632262270028#3262 +-0.4129000946596174#3263 +-0.3199114018330162#3264 +-0.22372626002794793#3265 +-0.12530571938674848#3266 +-0.025633165417999926#3267 +0.07429550666640745#3268 +0.1734818426070331#3269 +0.27093480532180136#3270 +0.36568067702093243#3271 +0.4567727882732294#3272 +0.5433009768141075#3273 +0.6244006815860823#3274 +0.69926158114707#3275 +0.7671356901343803#3276 +0.8273448328872091#3277 +0.8792874195536663#3278 +0.9224444569777169#3279 +0.9563847343072394#3280 +0.9807691315103211#3281 +0.9953540077505189#3282 +0.9999936357655596#3283 +0.994641657925974#3284 +0.9793515494252069#3285 +0.9542760839731598#3286 +0.9196658073317829#3287 +0.8758665339446406#3288 +0.8233158916733028#3289 +0.7625389491644119#3290 +0.6941429695373308#3291 +0.6188113428117887#3292 +0.5372967577007027#3293 +0.4504136809933635#3294 +0.3590302196725045#3295 +0.264059447076288#3296 +0.16645027977133223#3297 +0.0671779962920478#3298 +-0.03276550752009386#3299 +-0.1323816292119314#3300 +-0.23067503742423134#3301 +-0.3266636169136169#3302 +-0.4193882815234355#3303 +-0.5079225570556044#3304 +-0.5913818382945464#3305 +-0.668932227690092#3306 +-0.7397988673861511#3307 +-0.8032736813442769#3308 +-0.8587224502053834#3309 +-0.9055911481999364#3310 +-0.9434114787903057#3311 +-0.9718055537349715#3312 +-0.9904896688229197#3313 +-0.9992771385523388#3314 +-0.9980801614304436#3315 +-0.9869106972569683#3316 +-0.9658803476258001#3317 +-0.9351992408387446#3318 +-0.8951739323729925#3319 +-0.8462043418801258#3320 +-0.7887797573211552#3321 +-0.7234739461629501#3322 +-0.6509394224833727#3323 +-0.5719009272663036#3324 +-0.4871481870292994#3325 +-0.3975280231372775#3326 +-0.30393589064335974#3327 +-0.20730693119798013#3328 +-0.10860662942263#3329 +-0.008821166106667043#3330 +0.09105243538514393#3331 +0.19001627104051966#3332 +0.2870815269266859#3333 +0.3812783590923355#3334 +0.47166558392780156#3335 +0.557340082160572#3336 +0.6374458225245284#3337 +0.711182414941391#3338 +0.777813107753807#3339 +0.836672149104373#3340 +0.8871714389081266#3341 +0.9288064049541939#3342 +0.9611610444245324#3343 +0.9839120804565766#3344 +0.9968321922187865#3345 +0.9997922862252552#3346 +0.9927627861951471#3347 +0.9758139285691194#3348 +0.9491150607300238#3349 +0.9129329489398365#3350 +0.867629112899349#3351 +0.813656213562821#3352 +0.751553530299355#3353 +0.6819415725917019#3354 +0.605515880110623#3355 +0.5230400731124144#3356 +0.4353382225977257#3357 +0.34328661646652237#3358 +0.24780500393905253#3359 +0.14984740572566616#3360 +0.05039258176723505#3361 +-0.04956574821064165#3362 +-0.14902883361665542#3363 +-0.2470028721795537#3364 +-0.34250893969192686#3365 +-0.4345927710972995#3366 +-0.5223342951911364#3367 +-0.6048568276681833#3368 +-0.6813358306622516#3369 +-0.7510071512560216#3370 +-0.8131746566443966#3371 +-0.8672171896633807#3372 +-0.9125947751871345#3373 +-0.9488540153809398#3374 +-0.9756326199024913#3375 +-0.9926630257872393#3376 +-0.9997750708490869#3377 +-0.9968976938847057#3378 +-0.9840596446935896#3379 +-0.9613891968195613#3380 +-0.9291128658839244#3381 +-0.8875531463162514#3382 +-0.8371252890966461#3383 +-0.7783331527052134#3384 +-0.7117641687346805#3385 +-0.6380834724681006#3386 +-0.5580272570669699#3387 +-0.4723954177725101#3388 +-0.38204355961682934#3389 +-0.28787444850026606#3390 +-0.19082899105292786#3391 +-0.09187683340666573#3392 +0.00799332718855293#3393 +0.10778362110074621#3394 +0.20649697669942857#3395 +0.3031470827657546#3396 +0.39676824338818645#3397 +0.48642502687682576#3398 +0.5712216122876458#3399 +0.6503107401692458#3400 +0.7229021780992223#3401 +0.7882706164253177#3402 +0.8457629153197103#3403 +0.8948046307362744#3404 +0.9349057540656031#3405 +0.9656656081390587#3406 +0.9867768506625949#3407 +0.9980285450793656#3408 +0.9993082681780738#3409 +0.9906032333885376#3410 +0.972000418540872#3411 +0.9436856968117622#3412 +0.9059419795411228#3413 +0.8591463894755079#3414 +0.8037664926822882#3415 +0.7403556267840615#3416 +0.6695473721920379#3417 +0.592049221580004#3418 +0.508635510851393#3419 +0.4201396822308988#3420 +0.32744595678526595#3421 +0.23148049957867578#3422 +0.1332021657375744#3423 +0.03359291988720454#3424 +-0.06635197531433547#3425 +-0.1656339035115813#3426 +-0.2632608724962278#3427 +-0.35825742586536535#3428 +-0.4496743894594147#3429 +-0.5365983551965742#3430 +-0.6181608075444406#3431 +-0.6935468014401158#3432 +-0.7620031049518906#3433 +-0.8228457253237202#3434 +-0.8754667432047455#3435 +-0.9193403867784948#3436 +-0.9540282851010776#3437 +-0.9791838481587489#3438 +-0.9945557298807602#3439 +-0.9999903395062136#3440 +-0.9954333762121745#3441 +-0.9809303716695452#3442 +-0.9566262351056599#3443 +-0.9227638054191856#3444 +-0.8796814248141186#3445 +-0.8278095581963233#3446 +-0.7676664921104855#3447 +-0.6998531561922808#3448 +-0.6250471188780957#3449 +-0.5439958173651854#3450 +-0.45750908946626917#3451 +-0.366451081977802#3452 +-0.27173161641083377#3453 +-0.17429709835521742#3454 +-0.07512106130779558#3455 +0.02480556055249268#3456 +0.12448433345136849#3457 +0.22291930003944738#3458 +0.3191269306688547#3459 +0.4121459504963556#3460 +0.5010469442238331#3461 +0.5849416425087233#3462 +0.6629917972576633#3463 +0.7344175571243525#3464 +0.7985052595264196#3465 +0.854614561326041#3466 +0.9021848369269034#3467 +0.9407407798598458#3468 +0.969897151887982#3469 +0.9893626321798219#3470 +0.9989427280907218#3471 +0.9985417184690987#3472 +0.9881636100705354#3473 +0.9679120975236041#3474 +0.9379895272474138#3475 +0.8986948756730775#3476 +0.8504207619700415#3477 +0.793649525125126#3478 +0.7289484045708101#3479 +0.6569638725163257#3480 +0.5784151746110389#3481 +0.49408714347967225#3482 +0.40482235693414975#3483 +0.3115127192146192#3484 +0.21509054937710928#3485 +0.11651926586970504#3486 +0.016783760373878607#3487 +-0.08311944290763014#3488 +-0.1821921441912403#3489 +-0.2794444417948066#3490 +-0.3739046229080092#3491 +-0.4646288726255491#3492 +-0.550710704233698#3493 +-0.6312900165258971#3494 +-0.7055616876497018#3495 +-0.7727836196181932#3496 +-0.8322841531077579#3497 +-0.8834687784560297#3498 +-0.9258260758059158#3499 +-0.9589328250437571#3500 +-0.9824582344748051#3501 +-0.9961672459844911#3502 +-0.9999228836614071#3503 +-0.9936876224153341#3504 +-0.9775237629155394#3505 +-0.9515928091030836#3506 +-0.9161538544968271#3507 +-0.8715609934166348#3508 +-0.8182597829899804#3509 +-0.7567827912924092#3510 +-0.6877442761033722#3511 +-0.6118340474455396#3512 +-0.5298105752310752#3513 +-0.4424934108809914#3514 +-0.35075499863825743#3515 +-0.2555119583933158#3516 +-0.15771592712113114#3517 +-0.05834405043910549#3518 +0.041610780708929006#3519 +0.14114985069081507#3520 +0.23927859802253518#3521 +0.3350165526978016#3522 +0.427407132720259#3523 +0.5155272019545877#3524 +0.5984962937976203#3525 +0.6754854085095959#3526 +0.7457252963055302#3527 +0.8085141434447857#3528 +0.8632245845219801#3529 +0.9093099708947372#3530 +0.9463098326162236#3531 +0.9738544792986461#3532 +0.9916686939374035#3533 +0.999574482788422#3534 +0.9974928538228081#3535 +0.9854446059890913#3536 +0.9635501213970051#3537 +0.9320281624992393#3538 +0.8911936862893262#3539 +0.841454697355472#3540 +0.7833081712335805#3541 +0.7173350887919758#3542 +0.6441946312626129#3543 +0.5646175939201048#3544 +0.4793990842169069#3545 +0.38939057733247995#3546 +0.2954914085147568#3547 +0.19863978721962608#3548 +0.09980342283217974#3549 +-3.01443655808235E-5#3550 +-0.0998634103708049#3551 +-0.19869887419005808#3552 +-0.2955490045395186#3553 +-0.38944610693113085#3554 +-0.47945199255605286#3555 +-0.5646673523571102#3556 +-0.6442407426276232#3557 +-0.7173770923554741#3558 +-0.783345647309845#3559 +-0.8414872714959365#3560 +-0.8912210330239467#3561 +-0.9320500085884833#3562 +-0.9635662485619702#3563 +-0.9854548530924759#3564 +-0.9974971184789425#3565 +-0.9995727223862718#3566 +-0.9916609260663253#3567 +-0.9738407815726398#3568 +-0.9462903418984395#3569 +-0.9092848819299848#3570 +-0.8631941479909019#3571 +-0.8084786634591391#3572 +-0.7456851273696038#3573 +-0.6754409519781194#3574 +-0.5984479938655606#3575 +-0.5154755412189004#3576 +-0.42735262735793816#3577 +-0.33495974730841055#3578 +-0.23922006018674727#3579 +-0.14109016529933546#3580 +-0.04155054411846003#3581 +0.05840423636446346#3582 +0.15777546102350673#3583 +0.2555702454296358#3584 +0.350811456423722#3585 +0.4425474753080707#3586 +0.5298617061058852#3587 +0.6118817338852807#3588 +0.6877880416409017#3589 +0.7568221986369429#3590 +0.8182944383963581#3591 +0.8715905506194918#3592 +0.9161780181703624#3593 +0.9516113378118588#3594 +0.9775364715268212#3595 +0.9936943839488795#3596 +0.9999236305582081#3597 +0.9961619707818016#3598 +0.9824469898807066#3599 +0.9589157234105169#3600 +0.9258032880074003#3601 +0.8834405321803889#3602 +0.8322507305824411#3603 +0.7727453547900252#3604 +0.7055189628481972#3605 +0.6312432586431493#3606 +0.5506603804590156#3607 +0.4645754857774538#3608 +0.3738487064102398#3609 +0.2793865543465253#3610 +0.1821328641846953#3611 +0.08305936264905144#3612 +-0.016844040582407176#3613 +-0.11657914372826583#3614 +-0.2151494266059326#3615 +-0.31157000753189684#3616 +-0.4048774839339524#3617 +-0.4941395583512405#3618 +-0.5784643536423021#3619 +-0.6570093243266599#3620 +-0.7289896750207507#3621 +-0.7936862018539796#3622 +-0.8504524785160569#3623 +-0.8987213151350112#3624 +-0.9380104254509017#3625 +-0.9679272456607052#3626 +-0.9881728567860709#3627 +-0.9985449713729435#3628 +-0.9989399546809362#3629 +-0.9893538601673995#3630 +-0.9698824689199713#3631 +-0.9407203326436097#3632 +-0.9021588297642675#3633 +-0.8545832540719774#3634 +-0.7984689649926625#3635 +-0.7343766379538854#3636 +-0.6629466623013117#3637 +-0.5848927427400513#3638 +-0.5009947682331652#3639 +-0.41209101960894357#3640 +-0.3190697937359677#3641 +-0.22286052795443187#3642 +-0.12442451344547048#3643 +-0.024745290327437247#3644 +0.07518117955184238#3645 +0.1743564639366335#3646 +0.27178963616835333#3647 +0.36650717619718665#3648 +0.45756269767262103#3649 +0.5440464039230273#3650 +0.6250941783432632#3651 +0.6998962183621539#3652 +0.7677051267220971#3653 +0.8278433792254051#3654 +0.8797100943321279#3655 +0.9227870369697753#3656 +0.9566437965668558#3657 +0.9809420875730321#3658 +0.9954391294965175#3659 +0.9999900726864973#3660 +0.9945494456229591#3661 +0.9791716092530895#3662 +0.9540102138346597#3663 +0.9193166637134389#3664 +0.8754376053740758#3665 +0.8228114638630091#3666 +0.7619640621903281#3667 +0.6935033674800697#3668 +0.6181134163636822#3669 +0.5365474803121163#3670 +0.44962053919628586#3671 +0.35820113827759426#3672 +0.26320270999078516#3673 +0.1655744472289955#3674 +0.0662918193221285#3675 +-0.033653174530243454#3676 +-0.13326191698696957#3677 +-0.2315391504196944#3678 +-0.3275029211980919#3679 +-0.4201943910459491#3680 +-0.508687417436272#3681 +-0.5920978073012736#3682 +-0.6695921515972314#3683 +-0.7403961524521645#3684 +-0.8038023596942209#3685 +-0.8591772394599432#3686 +-0.9059675042552137#3687 +-0.943705641221003#3688 +-0.9720145833673183#3689 +-0.9906114771019258#3690 +-0.9993105084099446#3691 +-0.9980247594460628#3692 +-0.9867670769889152#3693 +-0.9656499440803186#3694 +-0.9348843561318997#3695 +-0.894777712728688#3696 +-0.845730746194075#3697 +-0.788233517604903#3698 +-0.7228605202631786#3699 +-0.6502649395489006#3700 +-0.5711721265076578#3701 +-0.4863723503827509#3702 +-0.396712902506141#3703 +-0.3030896304435386#3704 +-0.20643798698165444#3705 +-0.10772368339317456#3706 +-0.00793304036894502#3707 +0.09193686697233655#3708 +0.19088817152911786#3709 +0.28793218457521963#3710 +0.3820992744107705#3711 +0.4724485546016347#3712 +0.558077285005646#3713 +0.6381298916537022#3714 +0.7118065153620489#3715 +0.778371003660846#3716 +0.837158266186306#3717 +0.8875809200437595#3718 +0.9291351587433763#3719 +0.9614057860680744#3720 +0.9840703645768764#3721 +0.996902437293236#3722 +0.9997737903882905#3723 +0.9926557342510572#3724 +0.9756193901455429#3725 +0.9488349795905833#3726 +0.9125701235626947#3727 +0.8671871685157403#3728 +0.8131395659349391#3729 +0.7509673415995165#3730 +0.6812916998236274#3731 +0.6048088165881917#3732 +0.5222828835806185#3733 +0.43453847264407314#3734 +0.3424522969281879#3735 +0.24694445106107385#3736 +0.1489692178679391#3737 +0.04950553349254367#3738 +-0.0504527938091558#3739 +-0.14990701347259025#3740 +-0.2478634118100764#3741 +-0.34334324086950585#3742 +-0.43539249776035166#3743 +-0.523091456735199#3744 +-0.6055638587853923#3745 +-0.6819856669313974#3746 +-0.7515932997279102#3747 +-0.8136912607172517#3748 +-0.8676590876000732#3749 +-0.9129575516895527#3750 +-0.9491340457061896#3751 +-0.9758271060801286#3752 +-0.9927700245756657#3753 +-0.9997935131517774#3754 +-0.9968273954322683#3755 +-0.9839013078849232#3756 +-0.961144403703719#3757 +-0.9287840623528019#3758 +-0.8871436176660437#3759 +-0.8366391272022538#3760 +-0.7777752151355816#3761 +-0.7111400302175752#3762 +-0.6373993691892722#3763 +-0.5572900243602457#3764 +-0.47161242182339913#3765 +-0.38122262386203104#3766 +-0.28702377545847707#3767 +-0.18995708036798664#3768 +-0.09099239692192086#3769 +0.008881452476101726#3770 +0.10866656133680092#3771 +0.20736590983701175#3772 +0.3039933267121866#3773 +0.3975833427536857#3774 +0.48720083745796805#3775 +0.5719503824415534#3776 +0.6509851882654402#3777 +0.7235155652752691#3778 +0.7888168139193128#3779 +0.8462364657068425#3780 +0.8952008024576104#3781 +0.9352205887042604#3782 +0.9658959599713982#3783 +0.9869204180892522#3784 +0.9980838936220705#3785 +0.9992748448124834#3786 +0.9904813720698726#3787 +0.9717913368671467#3788 +0.943391483857947#3789 +0.9055655749857984#3790 +0.8586915542285684#3791 +0.8032377713071723#3792 +0.7397583020899774#3793 +0.6688874124498796#3794 +0.5913332208893615#3795 +0.5078706232544888#3796 +0.41933355023176294#3797 +0.326606634988362#3798 +0.23061637420995554#3799 +0.13232187085208025#3800 +0.032705251100445504#3801 +-0.06723814870926637#3802 +-0.1665097271630519#3803 +-0.2641175954638214#3804 +-0.3590864880563847#3805 +-0.45046750715849865#3806 +-0.5373476038338433#3807 +-0.61885870087518#3808 +-0.6941863663448576#3809 +-0.7625779511095188#3810 +-0.8233501090614465#3811 +-0.8758956248869896#3812 +-0.9196894811612573#3813 +-0.954294104148681#3814 +-0.9793637358951378#3815 +-0.9946478889271355#3816 +-0.9999938490398477#3817 +-0.9953482011669674#3818 +-0.9807573630863935#3819 +-0.9563671216291374#3820 +-0.9224211760254981#3821 +-0.8792587029429098#3822 +-0.8273109675447968#3823 +-0.7670970144316195#3824 +-0.6992184815187981#3825 +-0.624353588669538#3826 +-0.5432503611461462#3827 +-0.45671915558887405#3828 +-0.3656245632002365#3829 +-0.27087677103551244#3830 +-0.17342246771455624#3831 +-0.07423538442204156#3832 +0.025693434292662947#3833 +0.12536553270503523#3834 +0.22378502015495372#3835 +0.31996852165697554#3836 +0.4129550034581306#3837 +0.5018153753695055#3838 +0.5856617739282951#3839 +0.663656433636034#3840 +0.7350200576345289#3841 +0.7990396041824644#3842 +0.8550754111327816#3843 +0.902567587225408#3844 +0.9410416063356517#3845 +0.970113048782383#3846 +0.9894914423224154#3847 +0.9989831644531418#3848 +0.9984933770245784#3849 +0.988026973830809#3850 +0.9676885317128129#3851 +0.9376812656612382#3852 +0.8983049983593889#3853 +0.8499531644540819#3854 +0.7931088794867078#3855 +0.7283401127624386#3856 +0.6562940123886756#3857 +0.5776904391850793#3858 +0.4933147740722138#3859 +0.40401007080500034#3860 +0.31066863245827525#3861 +0.21422309582942212#3862 +0.11563711283978116#3863 +0.01589572204319201#3864 +-0.08400449355362567#3865 +-0.18306536401904885#3866 +-0.2802971058805568#3867 +-0.37472821171400944#3868 +-0.4654151571246921#3869 +-0.5514518281311794#3870 +-0.6319785747567164#3871 +-0.7061908003676237#3872 +-0.7733470009368971#3873 +-0.8327761739073366#3874 +-0.8838845226272941#3875 +-0.9261613893705334#3876 +-0.9591843576594301#3877 +-0.9826234729107834#3878 +-0.9962445392329431#3879 +-0.9999114594337439#3880 +-0.9935875948586621#3881 +-0.9773361314721403#3882 +-0.951319448524317#3883 +-0.9157974961112352#3884 +-0.8711251978394099#3885 +-0.8177489045464752#3886 +-0.7562019345111574#3887 +-0.6870992447133262#3888 +-0.6111312863871298#3889 +-0.5290571062604954#3890 +-0.44169676241113176#3891 +-0.34992313051729185#3892 +-0.25465318237253#3893 +-0.15683882380665107#3894 +-0.05745738355731774#3895 +0.042498151875634736#3896 +0.14202905982306696#3897 +0.24014086035331167#3898 +0.33585325278691963#3899 +0.42820991053700425#3900 +0.5162880364083785#3901 +0.5992075828820926#3902 +0.6761400452593388#3903 +0.7463167398065342#3904 +0.809036484189094#3905 +0.8636726034535386#3906 +0.909679191556477#3907 +0.9465965658773408#3908 +0.9740558602151771#3909 +0.991782710377798#3910 +0.9995999955380961#3911 +0.9974296079668007#3912 +0.9852932334590895#3913 +0.9633121346572913#3914 +0.9317059394346487#3915 +0.8907904464462075#3916 +0.8409744697730445#3917 +0.7827557541871054#3918 +0.7167160018499767#3919 +0.6435150601371714#3920 +0.56388432866127#3921 +0.47861945136875983#3922 +0.38857236672872686#3923 +0.29464279544528593#3924 +0.19776925074571347#3925 +0.0989196610665116#3926 +-9.183011675747517E-4#3927 +-0.10074708803994468#3928 +-0.19956924331117867#3929 +-0.2963973686720675#3930 +-0.3902639895011276#3931 +-0.48023122155121406#3932 +-0.5654001419788951#3933 +-0.6449197710843588#3934 +-0.7179955750192778#3935 +-0.7838974045063832#3936 +-0.8419667902496881#3937 +-0.891623522142032#3938 +-0.9323714465326797#3939 +-0.9638034236305925#3940 +-0.9856053955106381#3941 +-0.9975595240765649#3942 +-0.9995463676272517#3943 +-0.9915460742787029#3944 +-0.9736385803175122#3945 +-0.9460028115039091#3946 +-0.9089148953047087#3947 +-0.8627454019189386#3948 +-0.8079556416629041#3949 +-0.7450930557099968#3950 +-0.6747857462394504#3951 +-0.5977362006469884#3952 +-0.5147142725229772#3953 +-0.4265494895298316#3954 +-0.3341227650358171#3955 +-0.23835759631986517#3956 +-0.14021083729202993#3957 +-0.04066313792551283#3958 +0.059290854073709855#3959 +0.1586524314579784#3960 +0.25642880619063935#3961 +0.351643029055936#3962 +0.44334375101263535#3963 +0.5306147287591743#3964 +0.6125839795338587#3965 +0.6884324936783796#3966 +0.7574024179115897#3967 +0.8188046275489766#3968 +0.8720256120087151#3969 +0.9165336048066015#3970 +0.9518838967909858#3971 +0.9777232795296128#3972 +0.993793574451522#3973 +0.9999342124819873#3974 +0.9960838383956331#3975 +0.9822809238575657#3976 +0.9586633830272128#3977 +0.9254671945656303#3978 +0.8830240438147254#3979 +0.8317580087069611#3980 +0.7721813225188363#3981 +0.7048892558053088#3982 +0.6305541686531807#3983 +0.5499187926813633#3984 +0.4637888099120561#3985 +0.37302480266230326#3986 +0.27853365488995285#3987 +0.18125949090892593#3988 +0.08217424201115783#3989 +-0.017732064749593147#3990 +-0.11746119858080742#3991 +-0.21601669894331174#3992 +-0.31241383185560057#3993 +-0.40568942903026955#3994 +-0.49491151153316204#3995 +-0.579188601808808#3996 +-0.6576786310294751#3997 +-0.7295973527685441#3998 +-0.7942261789315666#3999 +-0.850919359650971#4000 +-0.8991104354052828#4001 +-0.9383178968954163#4002 +-0.9681499961264257#4003 +-0.9883086606239754#4004 +-0.9985924716759744#4005 +-0.9988986768417671#4006 +-0.9892242166205548#4007 +-0.9696657550209166#4008 +-0.9404187137259883#4009 +-0.9017753195046023#4010 +-0.8541216843780113#4011 +-0.7979339477162029#4012 +-0.7337735188107056#4013 +-0.6622814674585256#4014 +-0.5841721186046438#4015 +-0.5002259150432908#4016 +-0.41128161949152625#4017 +-0.3182279339494287#4018 +-0.2219946200834764#4019 +-0.12354320935531402#4020 +-0.023857395717228277#4021 +0.07606679313265759#4022 +0.1752309477299004#4023 +0.2726442526210754#4024 +0.36733338626426704#4025 +0.4583522461361782#4026 +0.5447914018758033#4027 +0.6257871820119776#4028 +0.7005303034832253#4029 +0.7682739577265967#4030 +0.8283412725419662#4031 +0.8801320751753131#4032 +0.9231288890464878#4033 +0.9569021042041466#4034 +0.9811142698463743#4035 +0.9955234660175518#4036 +0.9999857207925835#4037 +0.9944564487967827#4038 +0.978990896688197#4039 +0.9537435911512637#4040 +0.9189667949172583#4041 +0.8750079862384708#4042 +0.8223063870003694#4043 +0.761388574161709#4044 +0.6928632183716221#4045 +0.6174150023336926#4046 +0.5357977796827074#4047 +0.4488270427283285#4048 +0.35737177432550127#4049 +0.26234576528501463#4050 +0.1646984840777792#4051 +0.06540559005971848#4052 +-0.034540814994005645#4053 +-0.13414209964198492#4054 +-0.2324030807718237#4055 +-0.3283419671408341#4056 +-0.421000169109596#4057 +-0.5094518765527665#4058 +-0.5928133092478203#4059 +-0.6702515473148938#4060 +-0.7409928534768989#4061 +-0.8043304039866315#4062 +-0.8596313509760083#4063 +-0.9063431456627741#4064 +-0.9439990592352849#4065 +-0.9722228462525142#4066 +-0.9907325039641293#4067 +-0.9993430899887548#4068 +-0.9979685701971142#4069 +-0.9866226783366094#4070 +-0.9654187788082579#4071 +-0.9345687339670693#4072 +-0.8943807872634282#4073 +-0.8452564833764284#4074 +-0.7876866561121733#4075 +-0.7222465241546325#4076 +-0.6495899436706947#4077 +-0.5704428751954832#4078 +-0.48559613007466035#4079 +-0.3958974689388687#4080 +-0.30224313115974216#4081 +-0.20556887992236214#4082 +-0.10684065238883424#4083 +-0.0070449083734608125#4084 +0.09282122603764317#4085 +0.19175992144079657#4086 +0.28878261509631514#4087 +0.382919888320631#4088 +0.47323115259733173#4089 +0.5588140476266991#4090 +0.6388134574115429#4091 +0.712430054293582#4092 +0.7789282855711821#4093 +0.8376437228988098#4094 +0.8879897010354305#4095 +0.9294631796096705#4096 +0.9616497693329252#4097 +0.9842278724401516#4098 +0.996971895988431#4099 +0.9997545059070827#4100 +0.9925478992776083#4101 +0.9754240821312622#4102 +0.9485541499885891#4103 +0.9122065783295403#4104 +0.8667445400752233#4105 +0.8126222768841236#4106 +0.7503805605196052#4107 +0.6806412896372068#4108 +0.6041012759788476#4109 +0.5215252820602374#4110 +0.433738379916617#4111 +0.34161770725571405#4112 +0.24608370338771093#4113 +0.148090912499914#4114 +0.04861844616676457#4115 +-0.0513397996093618#4116 +-0.15078507507847264#4117 +-0.24872375592031773#4118 +-0.34417727121014857#4119 +-0.43619188097592587#4120 +-0.5238482056528556#4121 +-0.606270412220094#4122 +-0.6826349652347802#4123 +-0.7521788553259561#4124 +-0.8142072229319841#4125 +-0.8681003011075967#4126 +-0.9133196080303462#4127 +-0.9494133273329757#4128 +-0.9760208225032105#4129 +-0.9928762402445782#4130 +-0.9998111667946672#4131 +-0.9967563106597709#4132 +-0.983742194952588#4133 +-0.9608988524153701#4134 +-0.928454526175744#4135 +-0.8867333892168279#4136 +-0.836152305347941#4137 +-0.7772166640392184#4138 +-0.710515330737084#4139 +-0.6367147631153636#4140 +-0.5565523520505097#4141 +-0.47082905385571255#4142 +-0.38040138739018#4143 +-0.28617287600582364#4144 +-0.18908501984059176#4145 +-0.09010788866030936#4146 +0.009769570757759355#4147 +0.10954941585420723#4148 +0.20823467939966173#4149 +0.30483933086178727#4150 +0.39839812849642603#4151 +0.48797626372403896#4152 +0.572678701428026#4153 +0.651659122849752#4154 +0.7241283817258269#4155 +0.7893623891767129#4156 +0.8467093485634559#4157 +0.8955962680242483#4158 +0.9355346856197043#4159 +0.9661255498830958#4160 +0.987063207010698#4161 +0.9981384548535612#4162 +0.9992406331962297#4163 +0.9903587294370351#4164 +0.9715814886223723#4165 +0.943096526735531#4166 +0.905188456099808#4167 +0.8582360416262537#4168 +0.8027084163198831#4169 +0.7391603938577652#4170 +0.6682269250741585#4171 +0.5906167537416616#4172 +0.5071053350377174#4173 +0.41852708745281125#4174 +0.32576705555673624#4175 +0.22975206692580843#4176 +0.13144147158809297#4177 +0.03181755651504257#4178 +-0.06812426906522044#4179 +-0.16738541946787286#4180 +-0.26497411008946486#4181 +-0.35991526699183735#4182 +-0.45126026951859527#4183 +-0.5380964285991342#4184 +-0.619556106036139#4185 +-0.694825383659648#4186 +-0.7631521957283619#4187 +-0.8238538433219311#4188 +-0.8763238156428974#4189 +-0.9200378500720962#4190 +-0.9545591704274494#4191 +-0.9795428510871975#4192 +-0.9947392633726951#4193 +-0.9999965697556514#4194 +-0.9952622409685223#4195 +-0.9805835808595879#4196 +-0.9561072537485367#4197 +-0.9220778190050644#4198 +-0.8788352874924923#4199 +-0.8268117242916139#4200 +-0.7665269316492288#4201 +-0.6985832552859171#4202 +-0.6236595659567079#4203 +-0.5425044763989001#4204 +-0.4559288614410496#4205 +-0.3647977560097223#4206 +-0.27002171198645003#4207 +-0.17254770027431887#4208 +-0.07334964897773245#4209 +0.026581287765269457#4210 +0.1262466330675262#4211 +0.2246505637437602#4212 +0.32080986024666885#4213 +0.413763730671632#4214 +0.5025834106718274#4215 +0.5863814433645755#4216 +0.6643205465071567#4217 +0.7356219783442121#4218 +0.7995733185379454#4219 +0.8555355864366431#4220 +0.9029496255581272#4221 +0.9413416904964934#4222 +0.9703281804296068#4223 +0.9896194719317152#4224 +0.9990228127949825#4225 +0.9984442479458342#4226 +0.9878895582129948#4227 +0.9674642025673584#4228 +0.9373722644108115#4229 +0.8979144124423419#4230 +0.8494848964757872#4231 +0.7925676082260158#4232 +0.7277312464228656#4233 +0.6556236345614223#4234 +0.576965248063798#4235 +0.49254201552687205#4236 +0.4031974659835432#4237 +0.3098243006394673#4238 +0.21335547329769788#4239 +0.11475486859267976#4240 +0.015007671173599317#4241 +-0.08488947793497129#4242 +-0.1839384394407459#4243 +-0.28114954886159205#4244 +-0.3755515049258966#4245 +-0.46620107449380255#4246 +-0.5521925170309506#4247 +-0.6326666344685011#4248 +-0.7068193560262241#4249 +-0.7739097722219453#4250 +-0.83326753779418#4251 +-0.8842995695703985#4252 +-0.9264959723580396#4253 +-0.9594351336487255#4254 +-0.9827879362310783#4255 +-0.9963210466211054#4256 +-0.9998992464532412#4257 +-0.9934867835375585#4258 +-0.9771477290838324#4259 +-0.9510453375231913#4260 +-0.9154404153238058#4261 +-0.8706887150988698#4262 +-0.8172373810440856#4263 +-0.7556204812206672#4264 +-0.686453671323811#4265 +-0.6104280432544994#4266 +-0.5283032199576698#4267 +-0.4408997655208472#4268 +-0.34909098636902386#4269 +-0.2537942054755377#4270 +-0.15596159677414934#4271 +-0.05657067135184257#4272 +0.043385489518834315#4273 +0.14290815691957492#4274 +0.24100293325553057#4275 +0.33668968794737386#4276 +0.42901235057205933#4277 +0.5170484636024555#4278 +0.5999183992980321#4279 +0.6767941486544775#4280 +0.7469075945959657#4281 +0.8095581867470729#4282 +0.8641199411005575#4283 +0.910047694642637#4284 +0.9468825524416159#4285 +0.9742564727743516#4286 +0.9918959444774944#4287 +0.9996247197806206#4288 +0.9973655753156946#4289 +0.9851410837074361#4290 +0.9630733880351154#4291 +0.9313829814192799#4292 +0.8903865039273795#4293 +0.8404935788108798#4294 +0.7822027196851367#4295 +0.7160963495461387#4296 +0.6428349813924542#4297 +0.5631506185976866#4298 +0.4778394409747333#4299 +0.38775384961027715#4300 +0.2937939499548949#4301 +0.19689855826693#4302 +0.09803582127077107#4303 +-0.0018064572451918896#4304 +-0.10163068623749626#4305 +-0.20043945500755345#4306 +-0.2972454989996491#4307 +-0.3910815642220373#4308 +-0.48101007172909493#4309 +-0.5661324856002233#4310 +-0.6455982908137508#4311 +-0.7186134913118861#4312 +-0.7844485433468682#4313 +-0.8424456448409379#4314 +-0.8920253079272591#4315 +-0.9326921490011307#4316 +-0.9640398384292128#4317 +-0.9857551604609085#4318 +-0.9976211427766078#4319 +-0.9995192244033847#4320 +-0.9914304403370466#4321 +-0.973435611034188#4322 +-0.9457145348809033#4323 +-0.9085441917067469#4324 +-0.8622959752938333#4325 +-0.8074319825329326#4326 +-0.7445003963040872#4327 +-0.6741300082144792#4328 +-0.5970239359205429#4329 +-0.5139525978087609#4330 +-0.42574601522981265#4331 +-0.33328551919960797#4332 +-0.23749494443110458#4333 +-0.1393313986832356#4334 +-0.0397756996565601#4335 +0.06017742501298571#4336 +0.15952927674381348#4337 +0.2572871646747842#4338 +0.35247432430415254#4339 +0.4441396769975931#4340 +0.5313673328515297#4341 +0.6132857419622988#4342 +0.6890764026646912#4343 +0.7579820397300296#4344 +0.8193141708099325#4345 +0.872459985524356#4346 +0.9168884684603441#4347 +0.9521557049025041#4348 +0.9779093162821043#4349 +0.9938919810272516#4350 +0.9999440056349789#4351 +0.9960049202759392#4352 +0.9821140829889516#4353 +0.9584102864284875#4354 +0.9251303710943455#4355 +0.8826068588996672#4356 +0.8312646307218977#4357 +0.7716166811335055#4358 +0.7042589927297871#4359 +0.6298645812677813#4360 +0.5491767711152941#4361 +0.4630017681995254#4362 +0.3722006046639412#4363 +0.27768053571971557#4364 +0.18038597465155876#4365 +0.08128905655235824#4366 +-0.018620074929324236#4367 +-0.11834316077729126#4368 +-0.21688380088181902#4369 +-0.3132574097401875#4370 +-0.4065010541095631#4371 +-0.49568307431765746#4372 +-0.5799123930982074#4373 +-0.6583474189404683#4374 +-0.7302044549933965#4375 +-0.7947655295055287#4376 +-0.8513855695613934#4377 +-0.8994988464368491#4378 +-0.9386246281734907#4379 +-0.9683719828934694#4380 +-0.9884436848615913#4381 +-0.9986391842666134#4382 +-0.9988566110486644#4383 +-0.9890937927512102#4384 +-0.9694482762275201#4385 +-0.9401163529847545#4386 +-0.9013910979041106#4387 +-0.8536594409334871#4388 +-0.7973983010113463#4389 +-0.7331698208503304#4390 +-0.6616157501930958#4391 +-0.5834510336610189#4392 +-0.4994566672638683#4393 +-0.4104718949458387#4394 +-0.31738582313747726#4395 +-0.2211285370981292#4396 +-0.12266180781147178#4397 +-0.022969482287764426#4398 +0.07695234671026101#4399 +0.17610529329702104#4400 +0.27349865400582685#4401 +0.3681593065704404#4402 +0.45914143304108707#4403 +0.5455359700847644#4404 +0.6264796920455684#4405 +0.7011638360101038#4406 +0.768842182699172#4407 +0.8288385124441429#4408 +0.880553361750354#4409 +0.9234700129381941#4410 +0.9571596570153528#4411 +0.9812856781945266#4412 +0.9956070172470954#4413 +0.9999805800872513#4414 +0.9943626675208029#4415 +0.9788094118730793#4416 +0.9534762161332899#4417 +0.9186162012192256#4418 +0.874577676876719#4419 +0.8218006614837998#4420 +0.7608124855325126#4421 +0.6922225227169522#4422 +0.6167161012727448#4423 +0.5350476564038567#4424 +0.44803319221541943#4425 +0.35654212847044664#4426 +0.2614886136349538#4427 +0.16382239100866292#4428 +0.06451930920389547#4429 +-0.03542842821118951#4430 +-0.13502217648266945#4431 +-0.2332668277991315#4432 +-0.3291807540799851#4433 +-0.4218056150787603#4434 +-0.5102159338020652#4435 +-0.5935283435697821#4436 +-0.6709104143229327#4437 +-0.7415889699896632#4438 +-0.8048578138049752#4439 +-0.8600847843953653#4440 +-0.9067180721263033#4441 +-0.944291732601697#4442 +-0.9724303422262768#4443 +-0.9908527493140615#4444 +-0.9993748832630681#4445 +-0.997911593727921#4446 +-0.9864775014139562#4447 +-0.9651868519919665#4448 +-0.9342523745932234#4449 +-0.8939831562903168#4450 +-0.8447815538012954#4451 +-0.7871391732743425#4452 +-0.721631958321646#4453 +-0.6489144353812071#4454 +-0.5697131739050296#4455 +-0.4848195267173279#4456 +-0.39508172307869294#4457 +-0.30139639345970826#4458 +-0.20469961070567458#4459 +-0.10595753710616392#4460 +-0.006156770820793085#4461 +0.09370551188346128#4462 +0.1926315200878997#4463 +0.28963281781913364#4464 +0.3837402001745981#4465 +0.47401337729756166#4466 +0.5595503694425562#4467 +0.6394965192588389#4468 +0.7130530312441288#4469 +0.7794849530452186#4470 +0.8381285188589453#4471 +0.8883977815606836#4472 +0.9297904672943264#4473 +0.9618929940266256#4474 +0.9843846039221565#4475 +0.9970405682495806#4476 +0.9997344327968439#4477 +0.9924392813598633#4478 +0.9752280046803405#4479 +0.948272572145566#4480 +0.911842313527146#4481 +0.8663012279269533#4482 +0.8121043468184239#4483 +0.7497931875224875#4484 +0.6799903425454984#4485 +0.6033932588407144#4486 +0.5207672691488844#4487 +0.4329379450464886#4488 +0.340782848107444#4489 +0.245222761597941#4490 +0.14721249031441808#4491 +0.04773132048965235#4492 +-0.052226764911569364#4493 +-0.15166301774166763#4494 +-0.2495839038316188#4495 +-0.345011030055953#4496 +-0.4369909201134505#4497 +-0.5246045413471654#4498 +-0.6069764874149429#4499 +-0.6832837250602186#4500 +-0.7527638175882598#4501 +-0.8147225428815908#4502 +-0.8685408298379123#4503 +-0.9136809439239166#4504 +-0.9496918600409943#4505 +-0.9762137690189293#4506 +-0.9929816727101918#4507 +-0.9998280317638305#4508 +-0.9966844396232869#4509 +-0.9835823060220958#4510 +-0.9606525431482109#4511 +-0.9281242576126963#4512 +-0.8863224612922014#4513 +-0.835664823917724#4514 +-0.7766574998567214#4515 +-0.7098900707859835#4516 +-0.6360296547864077#4517 +-0.5558142407196545#4518 +-0.47004531448738884#4519 +-0.37957985084908624#4520 +-0.2853217508135146#4521 +-0.18821281015864433#4522 +-0.08922330931955144#4523 +0.010657681332957976#4524 +0.11043218395654948#4525 +0.20910328470207334#4526 +0.30568509454720927#4527 +0.39921259997368597#4528 +0.4887513050633646#4529 +0.5734065686725494#4530 +0.6523325433905668#4531 +0.7247406269674924#4532 +0.7899073417671557#4533 +0.84718156351653#4534 +0.8959910271242357#4535 +0.9358480445641681#4536 +0.9663543776930457#4537 +0.9872052173142973#4538 +0.9981922287307987#4539 +0.9992056333562993#4540 +0.990235305586768#4541 +0.9713708739720819#4542 +0.942800825677183#4543 +0.9048106231806318#4544 +0.8577798520278825#4545 +0.8021784281379878#4546 +0.7385619025590685#4547 +0.6675659105858819#4548 +0.5898998207020697#4549 +0.5063396468047552#4550 +0.41772029453019976#4551 +0.32492721915266787#4552 +0.2288875784080196#4553 +0.13056096864009153#4554 +0.03092983683122936#4555 +-0.06901033568320586#4556 +-0.16826097973527826#4557 +-0.2658304156975201#4558 +-0.36074376201796365#4559 +-0.45205267591435566#4560 +-0.538844828901757#4561 +-0.6202530224771886#4562 +-0.6954638528804155#4563 +-0.7637258383554432#4564 +-0.8243569277078173#4565 +-0.8767513151347024#4566 +-0.9203854932362104#4567 +-0.9548234837282926#4568 +-0.9797211935936381#4569 +-0.9948298531453608#4570 +-0.9999985016514786#4571 +-0.9951754956846467#4572 +-0.9804090251262118#4573 +-0.9558466316688474#4574 +-0.9217337346287321#4575 +-0.8784111787968661#4576 +-0.8263118288305887#4577 +-0.7659562442130079#4578 +-0.6979474779947189#4579 +-0.622965051287066#4580 +-0.5417581637118176#4581 +-0.45513820764619767#4582 +-0.36397066105846365#4583 +-0.2691664399381365#4584 +-0.17167279672454178#4585 +-0.07246385567355651#4586 +0.02746912026995325#4587 +0.12712763384380946#4588 +0.2255159301231064#4589 +0.32165094577426767#4590 +0.41457213149891764#4591 +0.5033510495249554#4592 +0.5871006502498729#4593 +0.6649841353471638#4594 +0.736223318778593#4595 +0.8001064021718566#4596 +0.8559950868746282#4597 +0.9033309516237009#4598 +0.941641032105658#4599 +0.9705425466599525#4600 +0.9897467209067285#4601 +0.9990616730849682#4602 +0.9983943312716201#4603 +0.9877513633254895#4604 +0.9672391102641967#4605 +0.9370625237398807#4606 +0.8975231182300396#4607 +0.849015958404538#4608 +0.7920257117700172#4609 +0.7271218060323789#4610 +0.6549527395633749#4611 +0.5762396018192422#4612 +0.49176886845321643#4613 +0.4023845431107794#4614 +0.30897972442422345#4615 +0.21248768246633692#4616 +0.11387253382433511#4617 +0.014119608465615191#4618 +-0.0857743953535712#4619 +-0.18481136976762977#4620 +-0.282001770065486#4621 +-0.37637450189423827#4622 +-0.46698662411293085#4623 +-0.5529327703487394#4624 +-0.6333541951184943#4625 +-0.7074473541296843#4626 +-0.7744719330294112#4627 +-0.833758244380689#4628 +-0.8847139189579444#4629 +-0.9268298245045077#4630 +-0.9596851528138249#4631 +-0.9829516243059571#4632 +-0.9963967680886273#4633 +-0.9998862447295328#4634 +-0.9933851885315454#4635 +-0.9769585558992319#4636 +-0.9507704763159315#4637 +-0.9150826124162126#4638 +-0.8702515455393219#4639 +-0.8167252128863131#4640 +-0.7550384318796021#4641 +-0.6858075564440695#4642 +-0.6097243186023826#4643 +-0.5275489169172812#4644 +-0.44010242083882695#4645 +-0.3482585668498676#4646 +-0.25293502837991955#4647 +-0.1550842467156025#4648 +-0.05568391452213869#4649 +0.044272792938575674#4650 +0.14378714128688722#4651 +0.2418648160491692#4652 +0.33752585751936537#4653 +0.4298144521924413#4654 +0.5178084829369766#4655 +0.6006287424847309#4656 +0.6774477181790405#4657 +0.7474978602077449#4658 +0.8100792507071913#4659 +0.8645665971101664#4660 +0.9104154798625334#4661 +0.947167792083456#4662 +0.9744563168179221#4663 +0.9920083961471714#4664 +0.9996486554964923#4665 +0.9973007559200001#4666 +0.9849881568541509#4667 +0.9628338817188064#4668 +0.9310592887078893#4669 +0.8899818590514812#4670 +0.8400120248483158#4671 +0.7816490681639204#4672 +0.7154761323692573#4673 +0.6421543955649226#4674 +0.5624164643081216#4675 +0.4770590536501172#4676 +0.3869350266227958#4677 +0.29294487271317216#4678 +0.19602771047009768#4679 +0.09715190414215104#4680 +-0.002694611897834578#4681 +-0.10251420426645728#4682 +-0.2013095085927397#4683 +-0.2980933948532388#4684 +-0.3918988304489386#4685 +-0.4817885424753208#4686 +-0.5668643826434057#4687 +-0.6462763012805672#4688 +-0.7192308407458727#4689 +-0.784999063396549#4690 +-0.8429238348919543#4691 +-0.89242639006269#4692 +-0.933012115740859#4693 +-0.9642754927713421#4694 +-0.985904147825149#4695 +-0.9976819745304649#4696 +-0.9994912927360821#4697 +-0.991314024332571#4698 +-0.9732318738827741#4699 +-0.9454255122568215#4700 +-0.9081727714285188#4701 +-0.8618458684701038#4702 +-0.8069076864822988#4703 +-0.7439071496193778#4704 +-0.6734737384204668#4705 +-0.596311200248075#4706 +-0.5131905176770778#4707 +-0.42494220509167996#4708 +-0.3324480104602216#4709 +-0.2366321052009449#4710 +-0.13845185016667366#4711 +-0.03888823001163328#4712 +0.06106394848294375#4713 +0.16040599618933662#4714 +0.25814532020497766#4715 +0.35330534151262716#4716 +0.44493525263509953#4717 +0.5321195177892803#4718 +0.6139870206170349#4719 +0.6897197680919065#4720 +0.7585610636350439#4721 +0.8198230677772865#4722 +0.872893670823771#4723 +0.9172426088516656#4724 +0.9524267619320054#4725 +0.9780945816375459#4726 +0.9939896035984427#4727 +0.9999530100094578#4728 +0.9959252164849727#4729 +0.9819464674064724#4730 +0.9581564338139892#4731 +0.9247928178592397#4732 +0.882188977764299#4733 +0.8307705970164385#4734 +0.7710514310794344#4735 +0.7036281741187975#4736 +0.6291744970309135#4737 +0.5484343163461312#4738 +0.4622143612606979#4739 +0.37137611306529994#4740 +0.2768271975087733#4741 +0.17951231610164317#4742 +0.080403806970907#4743 +-0.019508070421117876#4744 +-0.1192250296220056#4745 +-0.21775073173746473#4746 +-0.31410074052022424#4747 +-0.40731235853160475#4748 +-0.49645424609610067#4749 +-0.5806357269395575#4750 +-0.6590156875320847#4751 +-0.7308109812164121#4752 +-0.7953042531504141#4753 +-0.8518511078795672#4754 +-0.8998865479233226#4755 +-0.938930619043168#4756 +-0.968593205786728#4757 +-0.9885779293924083#4758 +-0.9986851091080121#4759 +-0.9988137573348106#4760 +-0.9889625886622468#4761 +-0.9692300327113339#4762 +-0.9398132506584176#4763 +-0.9010061652658754#4764 +-0.8531965241030328#4765 +-0.7968620253006231#4766 +-0.7325655445489706#4767 +-0.6609495110301554#4768 +-0.5827294884779846#4769 +-0.49868702550169774#4770 +-0.4096618466106099#4771 +-0.3165434619643894#4772 +-0.22026227968157627#4773 +-0.12178030950921329#4774 +-0.022081550739451946#4775 +0.07783783958610788#4776 +0.17697949994829187#4777 +0.27435283964863644#4778 +0.36898493646420194#4779 +0.4599302577648192#4780 +0.5462801079625782#4781 +0.6271717078977682#4782 +0.7017968154430443#4783 +0.7694098011915946#4784 +0.8293350985397009#4785 +0.8809739537249303#4786 +0.9238104083758077#4787 +0.957416454797311#4788 +0.981456312482278#4789 +0.9956897831192412#4790 +0.9999746505745556#4791 +0.9942681018689966#4792 +0.978627154950896#4793 +0.9532080889916499#4794 +0.918264882895897#4795 +0.8741466776282583#4796 +0.8212942877122281#4797 +0.7602357967571705#4798 +0.691581281021455#4799 +0.6160167137321476#4800 +0.5342971110672784#4801 +0.44723898828376585#4802 +0.3557122013668739#4803 +0.2606312557167434#4804 +0.16294616871272874#4805 +0.0636329774537779#4806 +-0.036316013481625595#4807 +-0.13590214681479854#4808 +-0.23413039082027445#4809 +-0.33001928135389064#4810 +-0.4226107283180879#4811 +-0.5109795885814625#4812 +-0.5942429097031241#4813 +-0.6715687521016191#4814 +-0.7421845015202269#4815 +-0.8053845887332195#4816 +-0.8605375393603357#4817 +-0.9070922833500508#4818 +-0.9445836610893715#4819 +-0.9726370711249284#4820 +-0.9909722130568702#4821 +-0.9994058882078054#4822 +-0.9978538300834279#4823 +-0.9863315463354743#4824 +-0.9649541638143936#4825 +-0.9339352782599134#4826 +-0.893584820123014#4827 +-0.8443059578433111#4828 +-0.7865910695232777#4829 +-0.7210168232490024#4830 +-0.6482384152132938#4831 +-0.5689830232119021#4832 +-0.484042540923356#4833 +-0.3942656655690927#4834 +-0.30054941801136287#4835 +-0.203830180017291#4836 +-0.10507433824178496#4837 +-0.005268628411524885#4838 +0.09458972381224616#4839 +0.19350296678289045#4840 +0.29048279207301586#4841 +0.38456020932559115#4842 +0.4747952280852878#4843 +0.56028624987239#4844 +0.6401790766567751#4845 +0.7136754457222707#4846 +0.7800410056438436#4847 +0.8386126536842945#4848 +0.8888051612976158#4849 +0.9301170215391718#4850 +0.9621354599573143#4851 +0.9845405588992577#4852 +0.997108454022515#4853 +0.9997135710734083#4854 +0.9923298805835022#4855 +0.9750311579474484#4856 +0.947990246283629#4857 +0.9114773294428521#4858 +0.865857232420625#4859 +0.811585776146395#4860 +0.7492052230714963#4861 +0.6793388590619841#4862 +0.6026847657322923#4863 +0.5200088454444972#4864 +0.4321371686650891#4865 +0.33994772014193364#4866 +0.24436162637089454#4867 +0.1463339520043707#4868 +0.04684415716099188#4869 +-0.053113689016120146#4870 +-0.15254084076963417#4871 +-0.2504438548654753#4872 +-0.34584451674923133#4873 +-0.4377896145426254#4874 +-0.5253604632215139#4875 +-0.607682083812971#4876 +-0.6839319458959563#4877 +-0.7533481860533897#4878 +-0.815237220159576#4879 +-0.8689806734435207#4880 +-0.9140415590852341#4881 +-0.9499696436105324#4882 +-0.9764059454750843#4883 +-0.9930863218893389#4884 +-0.999844108045964#4885 +-0.9966117823795099#4886 +-0.9834216412195708#4887 +-0.960405476096536#4888 +-0.9277932569241824#4889 +-0.8859108342163137#4890 +-0.8351766832961389#4891 +-0.7760977230291721#4892 +-0.7092642508574933#4893 +-0.6353440447428335#4894 +-0.555075690949919#4895 +-0.4692612043366593#4896 +-0.37875801488679633#4897 +-0.28447040055293665#4898 +-0.18734045201016314#4899 +-0.08833865959742333#4900 +0.011545783501135819#4901 +0.11131486494748018#4902 +0.20997172505907102#4903 +0.3065306171012951#4904 +0.400026756542992#4905 +0.4895259608645748#4906 +0.5741339836009652#4907 +0.6530054493566748#4908 +0.7253523005173126#4909 +0.7904516712607705#4910 +0.8476531101935705#4911 +0.8963850794461777#4912 +0.9361606652904673#4913 +0.9665824432207433#4914 +0.9873464488880291#4915 +0.9982452152113649#4916 +0.9991698453203011#4917 +0.990111100616431#4918 +0.9711594930824132#4919 +0.942504380916159#4920 +0.9044320765263129#4921 +0.8573229857933078#4922 +0.8016478071795532#4923 +0.7379628286659907#4924 +0.6669043695064731#4925 +0.589182422336119#4926 +0.5055735591595948#4927 +0.4169131721003451#4928 +0.3240871264386389#4929 +0.2280229093385172#4930 +0.12968036270263658#4931 +0.030042092749259296#4932 +-0.06989634786427318#4933 +-0.16913640727460627#4934 +-0.2666865116125137#4935 +-0.36157197248122797#4936 +-0.4528447257207117#4937 +-0.5395928041513566#4938 +-0.6209494496485853#4939 +-0.696101773503521#4940 +-0.76429887853826#4941 +-0.8248593618222606#4942 +-0.8771781230251833#4943 +-0.9207324103793711#4944 +-0.9550870438427141#4945 +-0.9798987632737787#4946 +-0.9949196581736731#4947 +-0.9999996447258055#4948 +-0.9950879653837672#4949 +-0.9802336960239586#4950 +-0.9555852555956543#4951 +-0.9213889231679229#4952 +-0.8779863771905777#4953 +-0.8258112815560504#4954 +-0.7653849525731279#4955 +-0.6973111501467191#4956 +-0.6222700452084615#4957 +-0.5410114236736072#4958 +-0.45434719482800395#4959 +-0.3631432789988919#4960 +-0.26831095556522977#4961 +-0.17079775775536865#4962 +-0.07157800520824754#4963 +0.028356931106371913#4964 +0.12800853433893156#4965 +0.2263811186103717#4966 +0.32249177757630465#4967 +0.4153802053023024#4968 +0.5041182913233582#4969 +0.5878193940168606#4970 +0.6656471996326018#4971 +0.7368240784633209#4972 +0.8006388546636893#4973 +0.856453912084273#4974 +0.9037115651213302#4975 +0.9419396309270177#4976 +0.9707561473043234#4977 +0.9898731891470789#4978 +0.9990997452924452#4979 +0.9983436270413116#4980 +0.9876123892773043#4981 +0.9670132549808855#4982 +0.9367520438927767#4983 +0.8971311160311438#4984 +0.8485463506102431#4985 +0.7914831905461722#4986 +0.7265117920717187#4987 +0.6542813279237506#4988 +0.5755135010238178#4989 +0.49099533346112295#4990 +0.40157130282796105#4991 +0.3081349044787646#4992 +0.2116197240198723#4993 +0.1129901092307529#4994 +0.013231534619763643#4995 +-0.08665924511138251#4996 +-0.1856841543111132#4997 +-0.2828537688199873#4998 +-0.3771972019698358#4999 +-0.46777180536241775#5000 +-0.5536725875006172#5001 +-0.6340412561643325#5002 +-0.7080747941826249#5003 +-0.7750334829158495#5004 +-0.8342482932797833#5005 +-0.8851275704630837#5006 +-0.9271629455465875#5007 +-0.9599344149575082#5008 +-0.9831145370062989#5009 +-0.9964717035757779#5010 +-0.9998724542728749#5011 +-0.9932828099207633#5012 +-0.9767686120675627#5013 +-0.9504948651193542#5014 +-0.9147240876706985#5015 +-0.8698136895056156#5016 +-0.8162124004771674#5017 +-0.754455786947096#5018 +-0.6851609005837718#5019 +-0.6090201129858933#5020 +-0.5267941977343409#5021 +-0.4393047289940346#5022 +-0.34742587261645447#5023 +-0.25207565176341384#5024 +-0.1542067743230842#5025 +-0.05479711376769998#5026 +0.04516006143493376#5027 +0.14466601223164102#5028 +0.24272650805435486#5029 +0.3383617608433046#5030 +0.43061621476543416#5031 +0.5185680938124212#5032 +0.6013386118818538#5033 +0.6781007533174772#5034 +0.748087536176257#5035 +0.8105996756584224#5036 +0.8650125711300333#5037 +0.910782546926049#5038 +0.9474522845778579#5039 +0.9746553921882468#5040 +0.9921200652981245#5041 +0.9996718026668301#5042 +0.9972351498308482#5043 +0.9848344530198655#5044 +0.9625936158972921#5045 +0.9307348615558133#5046 +0.8895765121377056#5047 +0.8395298082652133#5048 +0.7810948000601897#5049 +0.7148553508085741#5050 +0.6414733031914381#5051 +0.5616818663716927#5052 +0.4762782900104988#5053 +0.38611589841218874#5054 +0.2920955643898892#5055 +0.19515670804216095#5056 +0.0962679103779054#5057 +-0.003582764424906281#5058 +-0.10339764142988875#5059 +-0.20217940338041937#5060 +-0.2989410555639972#5061 +-0.3927157875371532#5062 +-0.48256663317581633#5063 +-0.5675958325311052#5064 +-0.6469538019499782#5065 +-0.7198476228342582#5066 +-0.785548964221163#5067 +-0.8434013600255303#5068 +-0.8928267682319421#5069 +-0.9333313464994675#5070 +-0.9645103864710906#5071 +-0.9860523574858352#5072 +-0.9977420192901507#5073 +-0.9994625726473769#5074 +-0.9911968263571076#5075 +-0.9730273690239829#5076 +-0.9451357438596512#5077 +-0.9078006347630092#5078 +-0.8613950818028046#5079 +-0.8063827539245794#5080 +-0.7433133161238353#5081 +-0.6728169373750934#5082 +-0.5955979941918066#5083 +-0.5124280327290739#5084 +-0.4241380597494972#5085 +-0.33161023947830387#5086 +-0.23576907931001329#5087 +-0.13757219243615187#5088 +-0.03800072969078855#5089 +0.06195042378427414#5090 +0.16128258910297158#5091 +0.2590032721042872#5092 +0.3541360800258346#5093 +0.4457304772975865#5094 +0.5328712829790856#5095 +0.6146878149448826#5096 +0.6903625894525244#5097 +0.7591394891698853#5098 +0.8203313180496092#5099 +0.8733266675648592#5100 +0.9175960257012121#5101 +0.9526970676656734#5102 +0.9782790754497961#5103 +0.9940864420880884#5104 +0.9999612255983212#5105 +0.9958447270856055#5106 +0.9817780772423467#5107 +0.9579018253839627#5108 +0.9244545351265829#5109 +0.8817704007382551#5110 +0.8302759079802887#5111 +0.7704855728025053#5112 +0.7029968004699444#5113 +0.6284839164869312#5114 +0.5476914289595397#5115 +0.46142658971669825#5116 +0.37055132851675693#5117 +0.2759736409302586#5118 +0.17863851594834093#5119 +0.07951849396516575#5120 +-0.02039605052444625#5121 +-0.12010680441925582#5122 +-0.21861749082633866#5123 +-0.31494382353041833#5124 +-0.4081233416563674#5125 +-0.4972250262601245#5126 +-0.5813586027622296#5127 +-0.6596834362771361#5128 +-0.7314169309591104#5129 +-0.7958423494412308#5130 +-0.8523159742382354#5131 +-0.9002735395588507#5132 +-0.9392358692630565#5133 +-0.968813664631682#5134 +-0.9887113941105229#5135 +-0.9987302461639416#5136 +-0.9987701157340123#5137 +-0.9888306044571701#5138 +-0.9690110246445276#5139 +-0.9395094069860908#5140 +-0.9006205218935647#5141 +-0.8527329342518376#5142 +-0.796325121007094#5143 +-0.7319606903833317#5144 +-0.6602827504952915#5145 +-0.5820074836247582#5146 +-0.49791699036393944#5147 +-0.4088514751248763#5148 +-0.3157008510946928#5149 +-0.2193958485171965#5150 +-0.12089871514394081#5151 +-0.02119360177276821#5152 +0.07872327106164467#5153 +0.17785356699406288#5154 +0.27520680887564847#5155 +0.36981027529422345#5156 +0.4607187196850812#5157 +0.5470238149222044#5158 +0.6278632290226549#5159 +0.702429241282698#5160 +0.7699768127560778#5161 +0.8298310304368901#5162 +0.8813938507672423#5163 +0.9241500750907953#5164 +0.9576724973474368#5165 +0.9816261725750176#5166 +0.9957717635686961#5167 +0.9999679322591741#5168 +0.9941727519159652#5169 +0.978444126065427#5170 +0.9529392099378654#5171 +0.917912840224423#5172 +0.8737149888330982#5173 +0.8207872660851259#5174 +0.7596585082906251#5175 +0.6909394937909978#5176 +0.6153168402636389#5177 +0.533546144265068#5178 +0.44644443155990476#5179 +0.3548819936695015#5180 +0.2597736922067416#5181 +0.16206981788121674#5182 +0.06274659550858111#5183 +-0.03720357010510971#5184 +-0.13678200994417533#5185 +-0.23499376915399928#5186 +-0.33085754830104785#5187 +-0.4234155081924356#5188 +-0.5117428402885212#5189 +-0.5949570070841342#5190 +-0.6722265601315991#5191 +-0.7427794475987832#5192 +-0.8059107283557985#5193 +-0.8609896155137471#5194 +-0.9074657790388062#5195 +-0.9448748444680102#5196 +-0.9728430327853834#5197 +-0.9910908950983123#5198 +-0.9994361047985073#5199 +-0.9977952793092036#5200 +-0.9861848132163057#5201 +-0.9647207144591039#5202 +-0.9336174452172925#5203 +-0.893185779075762#5204 +-0.8438296958776669#5205 +-0.7860423452913707#5206 +-0.7204011194219737#5207 +-0.6475618837002585#5208 +-0.5682524236921068#5209 +-0.4832651733056984#5210 +-0.39344929705384485#5211 +-0.2997022054828736#5212 +-0.20296058854309376#5213 +-0.1041910564924412#5214 +-0.004380481846299932#5215 +0.0954738611264548#5216 +0.19437426083829612#5217 +0.2913325371874285#5218 +0.38537991512671593#5219 +0.47557670434371857#5220 +0.5610216883356741#5221 +0.6408611290668913#5222 +0.7142972972369935#5223 +0.7805964429283947#5224 +0.8390961269929299#5225 +0.8892118399248504#5226 +0.9304428420865926#5227 +0.9623771669337133#5228 +0.9846957372484245#5229 +0.9971755532536798#5230 +0.9996919207532333#5231 +0.9922196970348302#5232 +0.9748335420878756#5233 +0.9477071726255013#5234 +0.9111116263645896#5235 +0.8654125539065005#5236 +0.8110665652771305#5237 +0.7486166676304692#5238 +0.6786868397006105#5239 +0.6019757972125022#5240 +0.5192500115453864#5241 +0.4313360514041404#5242 +0.3391123240180043#5243 +0.2435002983859096#5244 +0.14545529826283898#5245 +0.04595695688065448#5246 +-0.054000571223331524#5247 +-0.15341854346986936#5248 +-0.25130360834348353#5249 +-0.346677730632457#5250 +-0.4385879636333711#5251 +-0.5261159706795642#5252 +-0.6083872008575425#5253 +-0.6845796272306204#5254 +-0.7539319602603454#5255 +-0.8157512543599176#5256 +-0.8694198315774354#5257 +-0.9144014532298141#5258 +-0.9502466778224503#5259 +-0.9765973517200701#5260 +-0.993190187699463#5261 +-0.9998593956283852#5262 +-0.996538338985758#5263 +-0.9832602006717591#5264 +-0.9601576514552531#5265 +-0.927461524371324#5266 +-0.8854985083138918#5267 +-0.8346878838682738#5268 +-0.7755373339981713#5269 +-0.7086378714453144#5270 +-0.6346579335255096#5271 +-0.5543367033239355#5272 +-0.46847672402209806#5273 +-0.3779358801516458#5274 +-0.28361882589570886#5275 +-0.18646794608333994#5276 +-0.08745394019181343#5277 +0.012433876561680912#5278 +0.11219745813066402#5279 +0.2108399997855538#5280 +0.3073758978570232#5281 +0.4008405975620669#5282 +0.4903002305165539#5283 +0.5748609456394255#5284 +0.6536778402172297#5285 +0.7259634018927463#5286 +0.7909953772281428#5287 +0.848123988222581#5288 +0.896778424679212#5289 +0.9364725475519793#5290 +0.9668097462862708#5291 +0.9874869016204777#5292 +0.9982974142534595#5293 +0.9991332691164677#5294 +0.989986114624008#5295 +0.9709473461201218#5296 +0.94220719268632#5297 +0.9040528164354815#5298 +0.856865443282945#5299 +0.8011165538631789#5300 +0.7373631726511333#5301 +0.6662423023578131#5302 +0.5884645592097554#5303 +0.5048070727065923#5304 +0.41610572079997543#5305 +0.32324677807738733#5306 +0.2271580603994272#5307 +0.12879965447042646#5308 +0.029154324969461867#5309 +-0.07078230490945918#5310 +-0.17001170139524382#5311 +-0.2675423971590831#5312 +-0.36239989772826614#5313 +-0.45363641831282586#5314 +-0.540340353757865#5315 +-0.6216453870009271#5316 +-0.6967391450257175#5317 +-0.7648713158247487#5318 +-0.8253611452688975#5319 +-0.877604238977637#5320 +-0.9210786012279#5321 +-0.9553498505627952#5322 +-0.9800755599875371#5323 +-0.9950086783867864#5324 +-0.9999999989777303#5325 +-0.9949996501349354#5326 +-0.9800575936911434#5327 +-0.9553231257351534#5328 +-0.9210433848946539#5329 +-0.8775608830087473#5330 +-0.825310082862874#5331 +-0.7648130571802731#5332 +-0.696674272243908#5333 +-0.6215745482691752#5334 +-0.5402642568733623#5335 +-0.45355582361048796#5336 +-0.36231561048371774#5337 +-0.2674552595426102#5338 +-0.16992258405710617#5339 +-0.07069209828064123#5340 +0.0292447195741433#5341 +0.1288893338579619#5342 +0.22724612852302042#5343 +0.3233323549894589#5344 +0.4161879514443078#5345 +0.5048851354617692#5346 +0.5885376740985312#5347 +0.6663097388403877#5348 +0.7374242569244644#5349 +0.8011706755933992#5350 +0.8569120617036162#5351 +0.9040914657507545#5352 +0.9422374867250122#5353 +0.9709689821942126#5354 +0.9899988765529969#5355 +0.9991370293873787#5356 +0.9982921352949088#5357 +0.9874726361780741#5358 +0.9667866368955992#5359 +0.9364408251144325#5360 +0.8967384061548997#5361 +0.84807607346337#5362 +0.7909400449824686#5363 +0.7259012050221171#5364 +0.6536094001722174#5365 +0.5747869462503366#5366 +0.4902214111608231#5367 +0.4007577457766425#5368 +0.307289841469558#5369 +0.21075159864302492#5370 +0.11210759550806611#5371 +0.012343450336634304#5372 +-0.087544026510359#5373 +-0.18655679238266815#5374 +-0.28370554445296553#5375 +-0.3780196045036721#5376 +-0.4685566176228442#5377 +-0.5544119679029521#5378 +-0.6347278170640023#5379 +-0.708701675690067#5380 +-0.775594421438261#5381 +-0.8347376841048699#5382 +-0.8855405237594921#5383 +-0.9274953352214845#5384 +-0.9601829198831353#5385 +-0.9832766742035843#5386 +-0.9965458530234417#5387 +-0.9998578750941465#5388 +-0.9931796477859774#5389 +-0.9765778977386692#5390 +-0.9502185041508856#5391 +-0.9143648413700989#5392 +-0.8693751473431697#5393 +-0.8156989442211995#5394 +-0.7538725468827897#5395 +-0.684513704253056#5396 +-0.6083154269605701#5397 +-0.5260390630042369#5398 +-0.43850669061575864#5399 +-0.34659290432568596#5400 +-0.2512160763039714#5401 +-0.15332918028882067#5402 +-0.05391026978811178#5403 +0.046047294307954255#5404 +0.14554476906050678#5405 +0.24358800859131027#5406 +0.33919739725975856#5407 +0.4314176376585382#5408 +0.5193272956295426#5409 +0.6020480069293945#5410 +0.6787532535546172#5411 +0.7486766220363146#5412 +0.8111194611902097#5413 +0.865457862808335#5414 +0.9111488955436093#5415 +0.9477360297003892#5416 +0.9748536987282782#5417 +0.9922309518422593#5418 +0.9996941612733737#5419 +0.9971687570999949#5420 +0.9846799723258353#5421 +0.9623525907601151#5422 +0.9304097002189882#5423 +0.8891704635058256#5424 +0.8390469294419863#5425 +0.7805399158111991#5426 +0.7142340053538154#5427 +0.6407917048093058#5428 +0.5609468253679145#5429 +0.47549715067181214#5430 +0.3852964656246555#5431 +0.291246025655054#5432 +0.19428555167024208#5433 +0.09538384067540505#5434 +-0.004470914125755297#5435 +-0.1042809970308588#5436 +-0.20304913868434413#5437 +-0.2997884804632161#5438 +-0.3935324348421947#5439 +-0.483344343216756#5440 +-0.568326834686291#5441 +-0.6476307922875124#5442 +-0.7204638370904717#5443 +-0.7860982453869009#5444 +-0.8438782198649527#5445 +-0.8932264421191625#5446 +-0.9336498410251193#5447 +-0.9647445193431539#5448 +-0.9861997893260463#5449 +-0.9978012770082968#5450 +-0.9994330641599263#5451 +-0.9910788465031126#5452 +-0.9728220966191456#5453 +-0.9448452299179868#5454 +-0.9074277820037917#5455 +-0.8609436156475553#5456 +-0.8058571852738867#5457 +-0.742718896285927#5458 +-0.6721596055965009#5459 +-0.5948843183143766#5460 +-0.5116651435662637#5461 +-0.42333357983764397#5462 +-0.3307722069147612#5463 +-0.23490586743913935#5464 +-0.13669242618562055#5465 +-0.0371131993941631#5466 +0.06283685021764836#5467 +0.16215905479318588#5468 +0.25986101969588604#5469 +0.3549665391884163#5470 +0.44652535035771196#5471 +0.533622627827888#5472 +0.6153881243929944#5473 +0.6910048662394316#5474 +0.7597173158782414#5475 +0.8208389212259487#5476 +0.8737589754060353#5477 +0.9179487187301777#5478 +0.952966621890268#5479 +0.9784627975733101#5480 +0.9941824964197943#5481 +0.9999686523950879#5482 +0.9957634521413347#5483 +0.9816089126294156#5484 +0.9576464613392653#5485 +0.9241155231632417#5486 +0.8813511281517454#5487 +0.8297805640037017#5488 +0.7699191067491161#5489 +0.7023648722813098#5490 +0.6277928401806244#5491 +0.5469481095415738#5492 +0.4606384541889888#5493 +0.3697262516689739#5494 +0.27511986665753085#5495 +0.1777645748809813#5496 +0.07863311823337614#5497 +-0.02128401453896417#5498 +-0.12098848447359085#5499 +-0.2194840774648326#5500 +-0.3157866581058347#5501 +-0.40893400284423276#5502 +-0.4979954142018187#5503 +-0.5820810199960956#5504 +-0.6603506646489725#5505 +-0.7320223037435822#5506 +-0.796379817953585#5507 +-0.8527801682707603#5508 +-0.9006598210382154#5509 +-0.9395403785924068#5510 +-0.9690333592544564#5511 +-0.988844078910672#5512 +-0.9987745953988022#5513 +-0.9987256862806896#5514 +-0.9886978402400751#5515 +-0.9687912521998316#5516 +-0.9392048222074141#5517 +-0.9002341680913335#5518 +-0.8522686717455321#5519 +-0.7957875885542126#5520 +-0.7313552588304589#5521 +-0.6596154691143745#5522 +-0.5812850196707813#5523 +-0.497146562457916#5524 +-0.4080407811277736#5525 +-0.3148579911929501#5526 +-0.2185292442883396#5527 +-0.12001702541096315#5528 +-0.02030563608803385#5529 +0.0796086404385363#5530 +0.17872749374496208#5531 +0.27606056101334203#5532 +0.3706353224095644#5533 +0.4615068181800175#5534 +0.5477670903770854#5535 +0.6285542548748294#5536 +0.703061113030274#5537 +0.7705432169454224#5538 +0.830326307744572#5539 +0.8818130525461197#5540 +0.9244890128152635#5541 +0.9579277844637908#5542 +0.9817952583387776#5543 +0.9958529585308029#5544 +0.9999604251464057#5545 +0.994076617736911#5546 +0.9782603253610263#5547 +0.9526695791840002#5548 +0.9175600734824577#5549 +0.8732826108317093#5550 +0.8202795970023783#5551 +0.7590806205881805#5552 +0.6902971615317548#5553 +0.6146164814192049#5554 +0.5327947565895087#5555 +0.44564952267049884#5556 +0.35405150603310986#5557 +0.2589159237813043#5558 +0.16119333920530024#5559 +0.06186016406738981#5560 +-0.03809109738163067#5561 +-0.13766176517685647#5562 +-0.23585696211936405#5563 +-0.33169555426032#5564 +-0.424219954067078#5565 +-0.5125056883212689#5566 +-0.595670635149608#5567 +-0.6728838378940628#5568 +-0.7433738077561016#5569 +-0.8064362322577487#5570 +-0.8614410124990496#5571 +-0.9078385588979957#5572 +-0.9451652825079584#5573 +-0.973048227045201#5574 +-0.9912087953447836#5575 +-0.9994655330113421#5576 +-0.9977359414514271#5577 +-0.9860373021721781#5578 +-0.9644865041102175#5579 +-0.9332988757160339#5580 +-0.8927860334632826#5581 +-0.8433527682799882#5582 +-0.7854930010113974#5583 +-0.7197848473261622#5584 +-0.6468848413756778#5585 +-0.5675213759218636#5586 +-0.48248742447746074#5587 +-0.3926326181768149#5588 +-0.2988547565424325#5589 +-0.20209083696892502#5590 +-0.10330769255477226#5591 +-0.0034923318255946968#5592 +0.09635792312877281#5593 +0.19524540156693176#5594 +0.2921820524921821#5595 +0.3861993169314748#5596 +0.4763578054565078#5597 +0.5617566842523725#5598 +0.6415426759512564#5599 +0.7149185852978462#5600 +0.7811512644608015#5601 +0.8395789384035385#5602 +0.8896178171216423#5603 +0.9307679286796158#5604 +0.9626181147651897#5605 +0.9848501388472685#5606 +0.9972418658901542#5607 +0.9996694818533945#5608 +0.9921087308007481#5609 +0.9746351572574807#5610 +0.9474233513944414#5611 +0.9107452045807868#5612 +0.8649671927352955#5613 +0.8105467146201293#5614 +0.7480275216635965#5615 +0.6780342849756218#5616 +0.6012663538405035#5617 +0.5184907680500401#5618 +0.4305345938954794#5619 +0.3382766603945284#5620 +0.24263877832231104#5621 +0.14457652978281252#5622 +0.045069720348370305#5623 +-0.05488741083372423#5624 +-0.15429612515013374#5625 +-0.2521631635875603#5626 +-0.34751067104847855#5627 +-0.4393859667560341#5628 +-0.5268710631254516#5629 +-0.6090918379925355#5630 +-0.6852267685533883#5631 +-0.7545151397487074#5632 +-0.8162646450771994#5633 +-0.8698583038932945#5634 +-0.9147606260738101#5635 +-0.9505229624582529#5636 +-0.9767879876029256#5637 +-0.993293270058646#5638 +-0.9998738944990372#5639 +-0.996464109499956#5640 +-0.9830979845059883#5641 +-0.9599090694198203#5642 +-0.927129060215757#5643 +-0.885085483910135#5644 +-0.8341984260196418#5645 +-0.7749763332056944#5646 +-0.7080109330434688#5647 +-0.6339713216755684#5648 +-0.5535972784245394#5649 +-0.4676918741624206#5650 +-0.37711344729204793#5651 +-0.28276702751346355#5652 +-0.1855952930663155#5653 +-0.08656915180049524#5654 +0.013321959814158985#5655 +0.1130799628100045#5656 +0.21170810819671795#5657 +0.30822093614772517#5658 +0.4016541223890385#5659 +0.4910741134086396#5660 +0.5755874542145792#5661 +0.6543497154419204#5662 +0.7265739306118212#5663 +0.791538459240455#5664 +0.8485941972321822#5665 +0.897171062513109#5666 +0.9367836911027245#5667 +0.9670362867103555#5668 +0.9876265754008688#5669 +0.9983488258159133#5670 +0.9990959047736466#5671 +0.9898603477080745#5672 +0.970734433252527#5673 +0.941909261222057#5674 +0.9036728432072584#5675 +0.8564072248576555#5676 +0.8005846686078619#5677 +0.7367629349874418#5678 +0.6655797096620707#5679 +0.5877462318891539#5680 +0.5040401880502716#5681 +0.41529794126592323#5682 +0.3224061747316915#5683 +0.22629303227285133#5684 +0.12791884463807107#5685 +0.028266534192014796#5686 +-0.07166820612001427#5687 +-0.17088686140685108#5688 +-0.26839807166219604#5689 +-0.3632275371060979#5690 +-0.45442775306629446#5691 +-0.5410874771316942#5692 +-0.6223408339853317#5693 +-0.6973759669443137#5694 +-0.7654431497634311#5695 +-0.825862277651974#5696 +-0.8780296626559881#5697 +-0.9214240655087582#5698 +-0.9556119036812614#5699 +-0.9802515835954748#5700 +-0.9950969137144907#5701 +-0.9999995644069737#5702 +-0.9949105500078052#5703 +-0.9798807182666571#5704 +-0.9550602422940854#5705 +-0.9206971200814494#5706 +-0.8771346965869603#5707 +-0.8248082331463521#5708 +-0.7642405584854947#5709 +-0.6960368447885882#5710 +-0.620878561017742#5711 +-0.5395166639003695#5712 +-0.4527640946178#5713 +-0.3614876561657189#5714 +-0.26659935254516054#5715 +-0.1690472763199991#5716 +-0.06980613558944763#5717 +0.030132484973073366#5718 +0.12977003170621854#5719 +0.22811095917882387#5720 +0.3241726773507713#5721 +0.4169953692878687#5722 +0.5056515813353825#5723 +0.5892554899283811#5724 +0.6669717524479807#5725 +0.738023853688666#5726 +0.8017018645415418#5727 +0.8573695353713178#5728 +0.904470653212348#5729 +0.942534599264724#5730 +0.9711810511617585#5731 +0.9901237830253536#5732 +0.9991735253403632#5733 +0.9982398560730228#5734 +0.9873321041380214#5735 +0.9665592561870703#5736 +0.936128867650305#5737 +0.8963449889110358#5738 +0.8476051273348236#5739 +0.7903962755072824#5740 +0.7252900453651407#5741 +0.6529369568387209#5742 +0.574059938071828#5743 +0.48944710216270515#5744 +0.3999438725984719#5745 +0.3064445360631003#5746 +0.20988330702048066#5747 +0.11122499335230866#5748 +0.011455356316654522#5749 +-0.08842873885267832#5750 +-0.18742928329404956#5751 +-0.28455709629262965#5752 +-0.37884170884712265#5753 +-0.4693410602752329#5754 +-0.5551509109725986#5755 +-0.6354138772760167#5756 +-0.7093279981575924#5757 +-0.7761547481542365#5758 +-0.8352264164699689#5759 +-0.8859527785214759#5760 +-0.9278269932670445#5761 +-0.9604306673947122#5762 +-0.9834380357699366#5763 +-0.9966192163731373#5764 +-0.9998425072048462#5765 +-0.9930757022085512#5766 +-0.9763864130629667#5767 +-0.9499413936284902#5768 +-0.9140048737977496#5769 +-0.8689359193978601#5770 +-0.8151848445233696#5771 +-0.7532887121466815#5772 +-0.6838659679623627#5773 +-0.6076102610821948#5774 +-0.5252835133225399#5775 +-0.43770830633340774#5776 +-0.3457596626345197#5777 +-0.2503563026795348#5778 +-0.15245146530496573#5779 +-0.053023383282823196#5780 +0.04693449085788134#5781 +0.14642341108041368#5782 +0.24444931698057448#5783 +0.3400327661096653#5784 +0.43221872023967534#5785 +0.5200860877895621#5786 +0.602756927067857#5787 +0.6794052183758368#5788 +0.7492651173233087#5789 +0.8116386068926013#5790 +0.8659024717938725#5791 +0.9115145254262775#5792 +0.9480190272272615#5793 +0.9750512362816127#5794 +0.9923410556921204#5795 +0.9997157312984891#5796 +0.9971015777798035#5797 +0.984524714893898#5798 +0.9621108064973708#5799 +0.9300838049538668#5800 +0.8887637134760895#5801 +0.8385633887594791#5802 +0.779984415854583#5803 +0.713612096495033#5804 +0.6401096009560984#5805 +0.5602113418765098#5806 +0.4747156362501377#5807 +0.3844767289064784#5808 +0.2903962571786933#5809 +0.19341424204141744#5810 +0.09449969573191108#5811 +-0.005359060299902684#5812 +-0.10516427037266961#5813 +-0.2039187138185583#5814 +-0.30063566888253596#5815 +-0.39434877171997756#5816 +-0.48412167198476425#5817 +-0.5690573885324254#5818 +-0.6483072717592313#5819 +-0.7210794830285081#5820 +-0.7866469064605475#5821 +-0.8443544140341247#5822 +-0.8936254114091304#5823 +-0.9339675990666196#5824 +-0.9649778912028727#5825 +-0.9863464432295038#5826 +-0.997859747638167#5827 +-0.9994027672970033#5828 +-0.990960084863636#5829 +-0.9726160568301596#5830 +-0.9445539706609553#5831 +-0.9070542134449333#5832 +-0.8604914703604248#5833 +-0.8053309809447339#5834 +-0.7421238905744688#5835 +-0.6715017436031232#5836 +-0.5941701731786572#5837 +-0.5109018507903337#5838 +-0.4225287659906093#5839 +-0.32993391343054546#5840 +-0.23404247026913375#5841 +-0.13581255210894666#5842 +-0.036225639821747355#5843 +0.06372322708394657#5844 +0.16303539256871574#5845 +0.26071856230327317#5846 +0.35579671834539367#5847 +0.4473198711885637#5848 +0.534373551743106#5849 +0.61608794840904#5850 +0.6916465979460678#5851 +0.7602945433043837#5852 +0.8213458769059611#5853 +0.8741905940063404#5854 +0.9183006876603954#5855 +0.953235424393193#5856 +0.9786457478631875#5857 +0.9942777665178029#5858 +0.9999752903939005#5859 +0.9956813917162614#5860 +0.9814389737010982#5861 +0.9573903418813012#5862 +0.9237757822365931#5863 +0.8809311603354478#5864 +0.8292845654773529#5865 +0.7693520333660359#5866 +0.7017323900512924#5867 +0.6271012686570413#5868 +0.5462043586784855#5869 +0.4598499552991679#5870 +0.3689008831726845#5871 +0.27426587536395725#5872 +0.17689049358883693#5873 +0.07774768047399928#5874 +-0.022171961764168652#5875 +-0.12187006908946504#5876 +-0.22035049096930778#5877 +-0.31662924358157246#5878 +-0.40974434145568117#5879 +-0.4987654093134345#5880 +-0.5828029780712501#5881 +-0.6610173721212264#5882 +-0.7326270990922569#5883 +-0.7969166582634752#5884 +-0.8532436896109454#5885 +-0.9010453920566842#5886 +-0.9398441467909955#5887 +-0.9692522894817371#5888 +-0.9889759836881826#5889 +-0.9988181567776074#5890 +-0.998680469009892#5891 +-0.9885642961156978#5892 +-0.9685707155506215#5893 +-0.9388994965626704#5894 +-0.8998471041639711#5895 +-0.851803736950367#5896 +-0.7952494283660311#5897 +-0.7307492503679691#5898 +-0.6589476674138139#5899 +-0.580562097185996#5900 +-0.4963757423914076#5901 +-0.4072297652588474#5902 +-0.31401488292408225#5903 +-0.21766246767865804#5904 +-0.11913524100583359#5905 +-0.01941765438575316#5906 +0.08049394701832663#5907 +0.17960127951156024#5908 +0.27691409538820333#5909 +0.3714600771593562#5910 +0.46229455262790753#5911 +0.5485099337408607#5912 +0.6292447849091506#5913 +0.7036924301872969#5914 +0.7711090133127998#5915 +0.8308209300720284#5916 +0.8822315587308598#5917 +0.9248272212818289#5918 +0.9581823159449805#5919 +0.9819635696401684#5920 +0.9959333679415077#5921 +0.9999521292421726#5922 +0.9939796994076727#5923 +0.9780757529826917#5924 +0.9523991969427621#5925 +0.917206582948294#5926 +0.8728495439651891#5927 +0.8197712808644788#5928 +0.7585021341057248#5929 +0.6896542847504532#5930 +0.6139156377513494#5931 +0.5320429486333605#5932 +0.4448542622426411#5933 +0.3532207391128595#5934 +0.2580579511171135#5935 +0.1603167333764215#5936 +0.060973683829497964#5937 +-0.038978594611030024#5938 +-0.13854141181881474#5939 +-0.23671996903540732#5940 +-0.3325332985706153#5941 +-0.42502406530739834#5942 +-0.5132681320779048#5943 +-0.5963837933365737#5944 +-0.6735405848704926#5945 +-0.7439675815232989#5946 +-0.806961100024507#5947 +-0.8618917299601419#5948 +-0.908210622633538#5949 +-0.9454549749800931#5950 +-0.9732526537425062#5951 +-0.9913259137032742#5952 +-0.9994941728230944#5953 +-0.997675816556909#5954 +-0.985889013319461#5955 +-0.9642515329525#5956 +-0.9329795700074526#5957 +-0.8923855836009295#5958 +-0.8428751754265166#5959 +-0.7849430371167282#5960 +-0.7191680074477368#5961 +-0.6462072887736614#5962 +-0.5667898804778864#5963 +-0.4817092950521987#5964 +-0.3918156295822699#5965 +-0.29800707185858066#5966 +-0.20122092598092017#5967 +-0.10242424712565217#5968 +-0.0026041790500589026#5969 +0.09724190912177542#5970 +0.19611638828156605#5971 +0.29303133731710534#5972 +0.3870184140934526#5973 +0.47713853080745516#5974 +0.5624912370426562#5975 +0.6422237167722069#5976 +0.7155393094147028#5977 +0.7817054698033725#5978 +0.8400610875352369#5979 +0.8900230925677216#5980 +0.9310922810617849#5981 +0.9628583032616626#5982 +0.9850037635739842#5983 +0.997307391879625#5984 +0.9996462543915937#5985 +0.9919969819687958#5986 +0.9744360036127667#5987 +0.9471387828143523#5988 +0.9103780643805088#5989 +0.8645211492583496#5990 +0.8100262245854944#5991 +0.7474377856356479#5992 +0.6773811954018097#5993 +0.6005564361759669#5994 +0.5177311155574154#5995 +0.42973279677136517#5996 +0.33744072993074997#5997 +0.2417770668597405#5998 +0.14369764725754003#5999 +0.04418244826406843#6000 +-0.055774207147682296#6001 +-0.15517358511811483#6002 +-0.25302251991961405#6003 +-0.34834333734020045#6004 +-0.4401836232810802#6005 +-0.5276257399634938#6006 +-0.6097959946620711#6007 +-0.6858733693537384#6008 +-0.7550977240584129#6009 +-0.8167773919064145#6010 +-0.8702960900451931#6011 +-0.9151190773338755#6012 +-0.9507984972999824#6013 +-0.9769778529732608#6014 +-0.9933955688855672#6015 +-0.9998876046464816#6016 +-0.9963890939806623#6017 +-0.9829349928502283#6018 +-0.9596597301863407#6019 +-0.926795864719758#6020 +-0.8846717613308728#6021 +-0.8337083101363698#6022 +-0.7744147210943076#6023 +-0.70738343614654#6024 +-0.6332842097346686#6025 +-0.5528574168350533#6026 +-0.46690665537678444#6027 +-0.37629071695680905#6028 +-0.28191500607817316#6029 +-0.18472249364751417#6030 +-0.0856842951214665#6031 +0.014210032557972981#6032 +0.11396237828930539#6033 +0.21257604960772433#6034 +0.3090657313067615#6035 +0.40246733038212795#6036 +0.491847608930326#6037 +0.5763135087532935#6038 +0.6550210745007133#6039 +0.7271838861928992#6040 +0.7920809168692764#6041 +0.8490637368514327#6042 +0.8975629926381219#6043 +0.9370940956972457#6044 +0.9672620643142826#6045 +0.9877654701190156#6046 +0.9983994498581685#6047 +0.9990577523213141#6048 +0.9897337999678465#6049 +0.9705207546475926#6050 +0.9416105867584041#6051 +0.903292157141399#6052 +0.8559483308789219#6053 +0.8000521518331991#6054 +0.7361621161484359#6055 +0.6649165919419564#6056 +0.5870274409409932#6057 +0.5032729057956179#6058 +0.4144898341354351#6059 +0.3215653170646921#6060 +0.22542782564119876#6061 +0.1270379339004295#6062 +0.027378721117284403#6063 +-0.07255405079706279#6064 +-0.17176188661902594#6065 +-0.26925353444682204#6066 +-0.3640548899618095#6067 +-0.4552187293568439#6068 +-0.5418341736834483#6069 +-0.6230357900531704#6070 +-0.6980122387569291#6071 +-0.7660143799031949#6072 +-0.8263627585761534#6073 +-0.8784543937246257#6074 +-0.9217688029494135#6075 +-0.9558732029913825#6076 +-0.980426833958729#6077 +-0.9951843640871785#6078 +-0.9999983410138783#6079 +-0.994820665072666#6080 +-0.9797030698900342#6081 +-0.9547966054798351#6082 +-0.9203501290014732#6083 +-0.876707818261429#6084 +-0.8243057328023874#6085 +-0.7636674569404289#6086 +-0.6953988682836173#6087 +-0.620182084003217#6088 +-0.5387686453443945#6089 +-0.45197200847452446#6090 +-0.36065941669805746#6091 +-0.26574323524809457#6092 +-0.1681718352345661#6093 +-0.06892011783359091#6094 +0.031020226602815813#6095 +0.1306506271889307#6096 +0.22897560989552862#6097 +0.3250127439973229#6098 +0.4178024581960238#6099 +0.5064176283395591#6100 +0.5899728409401348#6101 +0.6676332399331268#6102 +0.7386228682829117#6103 +0.8022324210890692#6104 +0.8578263327264827#6105 +0.9048491272069747#6106 +0.9428309683117653#6107 +0.9713923540396625#6108 +0.9902479084656121#6109 +0.9992092331226073#6110 +0.9981867894168958#6111 +0.98719079326801#6112 +0.9663311130346763#6113 +0.935816171746493#6114 +0.8959508646099132#6115 +0.8471335125961273#6116 +0.789851882549586#6117 +0.7246783135829253#6118 +0.6522639984537427#6119 +0.5733324770618192#6120 +0.4886724070776113#6121 +0.39912968393550297#6122 +0.3055989889262417#6123 +0.20901484983722315#6124 +0.1103423034597536#6125 +0.010567253260429845#6126 +-0.08931338144040267#6127 +-0.188301626356961#6128 +-0.2854084236672018#6129 +-0.37966351435164025#6130 +-0.47012513270074757#6131 +-0.5558894161266145#6132 +-0.6360994362591523#6133 +-0.7099537610911038#6134 +-0.7767144626217417#6135 +-0.8357144899895256#6136 +-0.8863643344238125#6137 +-0.9281579194216271#6138 +-0.9606776572967937#6139 +-0.9835986215780596#6140 +-0.9966917935669896#6141 +-0.9998263506170976#6142 +-0.9929709732704858#6143 +-0.9761941581915149#6144 +-0.9496635337707765#6145 +-0.9136441852376241#6146 +-0.8684960060161877#6147 +-0.8146701017892441#6148 +-0.7527042831993508#6149 +-0.683217692222682#6150 +-0.6069046159070638#6151 +-0.5245275492852929#6152 +-0.4369095767768165#6153 +-0.34492614820028883#6154 +-0.24949633156836795#6155 +-0.151573630063937#6156 +-0.052136454951487186#6157 +0.04782165038481744#6158 +0.14730193759821267#6159 +0.2453104325426728#6160 +0.34086786673401337#6161 +0.4330194618768823#6162 +0.520844469693879#6163 +0.6034653717379834#6164 +0.6800566472668097#6165 +0.7498530215729831#6166 +0.8121571123560498#6167 +0.8663463977358996#6168 +0.9118794362856127#6169 +0.9483012769352218#6170 +0.9752480046924157#6171 +0.9924503767608481#6172 +0.9997365127251596#6173 +0.997033611923271#6174 +0.9843686808465345#6175 +0.9618682632997994#6176 +0.9297571760175435#6177 +0.888356262369377#6178 +0.8380791865991503#6179 +0.7794283006285677#6180 +0.7129896247228424#6181 +0.6394269921699185#6182 +0.5594754164776916#6183 +0.47393374736200167#6184 +0.38365668890433663#6185 +0.28954625963117797#6186 +0.1925427798430516#6187 +0.09361547624491363#6188 +-0.00624720224670175#6189 +-0.10604746075851858#6190 +-0.2047881280970657#6191 +-0.30148262015362104#6192 +-0.3951647975265046#6193 +-0.4848986188666166#6194 +-0.5697874934931841#6195 +-0.6489832398314691#6196 +-0.7216945601626925#6197 +-0.7871949470092712#6198 +-0.844829942157383#6199 +-0.8940236757871044#6200 +-0.9342846203732933#6201 +-0.9652105018661431#6202 +-0.9864923190805144#6203 +-0.9979174311336345#6204 +-0.9993716820825086#6205 +-0.9908405415323671#6206 +-0.9724092498195667#6207 +-0.9442619663183269#6208 +-0.9066799293811373#6209 +-0.8600386462981047#6210 +-0.8048041413522367#6211 +-0.7415282994588526#6212 +-0.6708433519139391#6213 +-0.593455559348028#6214 +-0.5101381550034353#6215 +-0.4217236188433001#6216 +-0.32909535968697506#6217 +-0.23317888848111895#6218 +-0.13493257090025113#6219 +-0.03533805167372523#6220 +0.06460955368391785#6221 +0.16391160173822988#6222 +0.2615758992499447#6223 +0.35662661684184926#6224 +0.4481140391633548#6225 +0.5351240541323454#6226 +0.6167872864409377#6227 +0.6922877840661794#6228 +0.7608711709929451#6229 +0.8218521846897158#6230 +0.8746215230252763#6231 +0.9186519322142014#6232 +0.9535034749623935#6233 +0.978827926175101#6234 +0.9943722523069567#6235 +0.9999811395895223#6236 +0.9955985458751219#6237 +0.9812682605914571#6238 +0.9571334672121197#6239 +0.9234353126146541#6240 +0.8805104976206695#6241 +0.8287879127925286#6242 +0.768784353100621#6243 +0.7010993542788487#6244 +0.6264092024617534#6245 +0.5454601769570099#6246 +0.45906109366927184#6247 +0.36807522367901085#6248 +0.27341166772324016#6249 +0.17601627276145895#6250 +0.07686218138548857#6251 +-0.02305989149962678#6252 +-0.12275155757146444#6253 +-0.22121673065631767#6254 +-0.317471579292981#6255 +-0.4105543568514991#6256 +-0.4995350109875823#6257 +-0.5835244764181962#6258 +-0.6616835581679836#6259 +-0.7332313165280581#6260 +-0.7974528699474296#6261 +-0.8537065378931546#6262 +-0.9014302523101099#6263 +-0.9401471736192033#6264 +-0.969470455140827#6265 +-0.9891071083390048#6266 +-0.9988609302659951#6267 +-0.9986344639572882#6268 +-0.9884299721893809#6269 +-0.9683494148708616#6270 +-0.9385934302927073#6271 +-0.8994593304168023#6272 +-0.8513381302330933#6273 +-0.7947106408670623#6274 +-0.7301426654738955#6275 +-0.6582793459203868#6276 +-0.57983871674066#6277 +-0.49560453077245464#6278 +-0.40641842815784546#6279 +-0.31317152695315215#6280 +-0.21679551937188488#6281 +-0.11825336262412364#6282 +-0.018529657366386256#6283 +0.08137919010266577#6284 +0.18047492360459536#6285 +0.27776741132694516#6286 +0.37228453889301355#6287 +0.46308192240736856#6288 +0.5492523444275588#6289 +0.6299348185809126#6290 +0.7043231922557696#6291 +0.7716742014118969#6292 +0.8313148970290903#6293 +0.8826493689913352#6294 +0.9251647002237049#6295 +0.9584360915902255#6296 +0.9821311063464223#6297 +0.9960129917373818#6298 +0.9999430445530186#6299 +0.9938819970047018#6300 +0.9778904090760181#6301 +0.9521280634274347#6302 +0.9168523689007734#6303 +0.8724157885751502#6304 +0.8192623180723986#6305 +0.7579230492995809#6306 +0.6890108639542089#6307 +0.6132143098129139#6308 +0.5312907209896665#6309 +0.4440586509036509#6310 +0.3523896935640783#6311 +0.25719977489095747#6312 +0.15944000108606712#6313 +0.06008715549418129#6314 +-0.03986606109322982#6315 +-0.13942094917616493#6316 +-0.23758278922136963#6317 +-0.3333707805711021#6318 +-0.42582784127909545#6319 +-0.514030170956996#6320 +-0.5970964810824756#6321 +-0.6741968005428316#6322 +-0.7445607684319929#6323 +-0.807485331242046#6324 +-0.8623417675414878#6325 +-0.9085819699519408#6326 +-0.9457439216558984#6327 +-0.9734563127160425#6328 +-0.9914422500813985#6329 +-0.9995220242111722#6330 +-0.9976149046730771#6331 +-0.9857399467751279#6332 +-0.9640158011713017#6333 +-0.9326595283434245#6334 +-0.8919844298045866#6335 +-0.8423969176939883#6336 +-0.7843924540411868#6337 +-0.7185506002732748#6338 +-0.645529226428678#6339 +-0.5660579379371954#6340 +-0.4809307856437185#6341 +-0.390998331914669#6342 +-0.2971591520999911#6343 +-0.20035085626528476#6344 +-0.10154072090196273#6345 +-0.0017160242202876055#6346 +0.09812581840815446#6347 +0.19698722029514487#6348 +0.29388039099226304#6349 +0.3878372059665269#6350 +0.47791887978070685#6351 +0.5632253461270936#6352 +0.6429042509925226#6353 +0.7161594690979219#6354 +0.7822590585189381#6355 +0.840542574007695#6356 +0.8904276659433977#6357 +0.9314158989772433#6358 +0.963097732233666#6359 +0.9851566113073892#6360 +0.9973721311704039#6361 +0.9996222383861532#6362 +0.9918844506271235#6363 +0.9742360813108307#6364 +0.946853467109708#6365 +0.9100102060533641#6366 +0.8640744238275117#6367 +0.8095050955838005#6368 +0.7468474600118203#6369 +0.6767275714943461#6370 +0.5998460447788914#6371 +0.5169710546667434#6372 +0.4289306606642735#6373 +0.33660453328606976#6374 +0.2409151646779356#6375 +0.142818651380304#6376 +0.04329514132764921#6377 +-0.05666095946568067#6378 +-0.15605092268165224#6379 +-0.25388167666176487#6380 +-0.3491757288507966#6381 +-0.4409809325792998#6382 +-0.5283800005983845#6383 +-0.6104996703106945#6384 +-0.6865194291216177#6385 +-0.7556797127299064#6386 +-0.8172894944430965#6387 +-0.8707331896877957#6388 +-0.9154768067272556#6389 +-0.9510732821302911#6390 +-0.9771669476813053#6391 +-0.9934970840995313#6392 +-0.9999005260599038#6393 +-0.9963132924870508#6394 +-0.9827712258330508#6395 +-0.9594096339514985#6396 +-0.9264619381461588#6397 +-0.8842573409024587#6398 +-0.8332175366050724#6399 +-0.7738524981070234#6400 +-0.7067553812495116#6401 +-0.6325965982448198#6402 +-0.5521171191390967#6403 +-0.466121068284588#6404 +-0.3754676897949175#6405 +-0.2810627622619315#6406 +-0.1838495485154199#6407 +-0.08479937085272225#6408 +0.015098094092590981#6409 +0.11484470387249736#6410 +0.21344382333392106#6411 +0.30991028266773873#6412 +0.4032802208998583#6413 +0.49262071647146216#6414 +0.5770391086828398#6415 +0.6556919168640254#6416 +0.7277932681548336#6417 +0.7926227496867044#6418 +0.8495326067099487#6419 +0.8979542147450874#6420 +0.9374037610906888#6421 +0.9674870789199537#6422 +0.9879035856653547#6423 +0.9984492863402916#6424 +0.9990188117895656#6425 +0.9896064715031475#6426 +0.9703063104738733#6427 +0.9413111695309624#6428 +0.9029107585381975#6429 +0.8554887617087299#6430 +0.799519003959252#6431 +0.7355607166080547#6432 +0.6642529497205526#6433 +0.5863081869322719#6434 +0.5025052265478807#6435 +0.41368140004596415#6436 +0.32072420573967675#6437 +0.2245624411869641#6438 +0.12615692295238418#6439 +0.026490886445597783#6440 +-0.07343983824183033#6441 +-0.17263677634152869#6442 +-0.2701087848381528#6443 +-0.3648819556427663#6444 +-0.4560093465605342#6445 +-0.5425804428241162#6446 +-0.623730254656246#6447 +-0.698647959961658#6448 +-0.7665850057934409#6449 +-0.8268625876466449#6450 +-0.8788784318485121#6451 +-0.9221128132779292#6452 +-0.9561337482870396#6453 +-0.9806013109390582#6454 +-0.9952710294358666#6455 +-0.9999963287994093#6456 +-0.9947299954004215#6457 +-0.9795246487014079#6458 +-0.9545322155003655#6459 +-0.9200024119284395#6460 +-0.876280248368885#6461 +-0.8238025822273635#6462 +-0.7630937529971512#6463 +-0.694760343232246#6464 +-0.6194851177749968#6465 +-0.5380202017954916#6466 +-0.45117956580547686#6467 +-0.35983089273406754#6468 +-0.264886908326737#6469 +-0.16729626149137494#6470 +-0.06803404571198197#6471 +0.031907943763099904#6472 +0.13153111961146466#6473 +0.2298400799910786#6474 +0.32585255426645#6475 +0.4186092175321232#6476 +0.5071832758700237#6477 +0.5906897265679296#6478 +0.6682942007740298#6479 +0.7392213002346851#6480 +0.8027623448174664#6481 +0.8582824534087788#6482 +0.9052268874360858#6483 +0.943126593632353#6484 +0.9716028906612442#6485 +0.9903712527758591#6486 +0.999244152705944#6487 +0.9981329353683882#6488 +0.9870487036795089#6489 +0.9661022076183817#6490 +0.9355027376496583#6491 +0.8955560335624265#6492 +0.8466612296193012#6493 +0.7893068665388091#6494 +0.7240660101580189#6495 +0.6515905255481277#6496 +0.572604563794148#6497 +0.4878973265166385#6498 +0.39831518042998615#6499 +0.3047532007259689#6500 +0.20814622777831115#6501 +0.10945952652668677#6502 +0.009679141868516105#6503 +-0.0901979535757059#6504 +-0.18917382088327842#6505 +-0.28625952590513565#6506 +-0.3804850203689661#6507 +-0.47090883428089403#6508 +-0.5566274827824501#6509 +-0.6367844934726242#6510 +-0.7105789639969848#6511 +-0.7772735643992611#6512 +-0.8362019042785367#6513 +-0.8867751911418572#6514 +-0.9284881134241899#6515 +-0.9609238893945486#6516 +-0.9837584315012794#6517 +-0.9967635845477477#6518 +-0.9998094053436452#6519 +-0.9928654610543938#6520 +-0.9760011332759688#6521 +-0.9493849247969268#6522 +-0.9132827759742418#6523 +-0.8680554075451663#6524 +-0.8141547164248637#6525 +-0.7521192605018084#6526 +-0.6825688775453889#6527 +-0.6061984919918056#6528 +-0.5237711714888175#6529 +-0.43611050257604106#6530 +-0.3440923616804886#6531 +-0.24863616364883562#6532 +-0.15069567525819083#6533 +-0.051249485493732934#6534 +0.04870877218895102#6535 +0.14818034792090215#6536 +0.2461713545983377#6537 +0.3417026984740565#6538 +0.4338198619385158#6539 +0.5216024407442641#6540 +0.6041733403809366#6541 +0.6807075397136739#6542 +0.7504403343215857#6543 +0.8126749771715466#6544 +0.8667896402842373#6545 +0.912243627833765#6546 +0.9485827786016253#6547 +0.9754440038054716#6548 +0.9925589149622076#6549 +0.9997565055369927#6550 +0.9969648595840104#6551 +0.9842118703068278#6552 +0.9616249613587246#6553 +0.9294298136676707#6554 +0.8879481105070949#6555 +0.8375943233429495#6556 +0.7788715705718298#6557 +0.7123665905282638#6558 +0.6387438789892236#6559 +0.5587390497519747#6560 +0.47315148462417583#6561 +0.3828363462650965#6562 +0.28869603368300556#6563 +0.1916711657625737#6564 +0.09273118291190512#6565 +-0.0071353392655659825#6566 +-0.10693056749172508#6567 +-0.20565738083405258#6568 +-0.30232933360837705#6569 +-0.395980511618076#6570 +-0.48567518324943976#6571 +-0.5705171489926438#6572 +-0.6496586959710069#6573 +-0.7223090680078381#6574 +-0.7877423666007652#6575 +-0.8453048038596203#6576 +-0.8944212349389244#6577 +-0.9346009046950666#6578 +-0.9654423511494763#6579 +-0.9866374167640076#6580 +-0.9979743274491972#6581 +-0.9993398085409632#6582 +-0.9907202166036044#6583 +-0.9722016757505011#6584 +-0.9439692171204415#6585 +-0.9063049301076473#6586 +-0.8595851438177926#6587 +-0.8042766669119777#6588 +-0.7409321234088941#6589 +-0.6701844310483026#6590 +-0.5927404773861927#6591 +-0.5093740568079891#6592 +-0.4209181390308347#6593 +-0.3282565463455203#6594 +-0.2323151227563079#6595 +-0.13405248325368307#6596 +-0.0344504356502464#6597 +0.06549582931840771#6598 +0.1647876816105547#6599 +0.2624330298596137#6600 +0.35745623402314036#6601 +0.44890785365562746#6602 +0.5358741344035932#6603 +0.6174861379370337#6604 +0.6929284240939841#6605 +0.7614471984890684#6606 +0.8223578441778256#6607 +0.8750517621229162#6608 +0.9190024521145261#6609 +0.9537707733864255#6610 +0.9790093323653442#6611 +0.9944659537127232#6612 +0.9999861999773392#6613 +0.995514914683267#6614 +0.9810967734351546#6615 +0.9568758375343491#6616 +0.9230941145659948#6617 +0.8800891403392386#6618 +0.8282906063409999#6619 +0.7682160664006705#6620 +0.7004657654633318#6621 +0.625716642140678#6622 +0.5447155649641743#6623 +0.4582718699215725#6624 +0.36724927383925204#6625 +0.272557244409198#6626 +0.17514191308845256#6627 +0.07597662166634576#6628 +-0.023947803044919447#6629 +-0.12363294922425093#6630 +-0.22208279584255267#6631 +-0.3183136645756067#6632 +-0.411364048392728#6633 +-0.5003042186171828#6634 +-0.5842455144677996#6635 +-0.6623492222637417#6636 +-0.7338349555743653#6637 +-0.7979884525824719#6638 +-0.8541687127522828#6639 +-0.9018144014949061#6640 +-0.9404494588379959#6641 +-0.969687856059632#6642 +-0.9892374527597048#6643 +-0.9989029158302245#6644 +-0.9985876711591678#6645 +-0.9882948685670818#6646 +-0.9681273503351187#6647 +-0.9382866236389569#6648 +-0.8990708471557118#6649 +-0.8508718519609921#6650 +-0.7941712264823142#6651 +-0.7295355046267261#6652 +-0.6576105051612804#6653 +-0.5791148789053921#6654 +-0.4948329282094064#6655 +-0.4056067704647689#6656 +-0.3123279239454181#6657 +-0.2159284000518886#6658 +-0.117371390961479#6659 +-0.017641645730405324#6660 +0.08226436899325389#6661 +0.18134842533491713#6662 +0.2786205081564525#6663 +0.3731087069601824#6664 +0.46386892689730536#6665 +0.5499943218515493#6666 +0.6306243553458014#6667 +0.7049533987381323#6668 +0.7722387807968807#6669 +0.8318082082261052#6670 +0.8830664829979679#6671 +0.9255014493746805#6672 +0.958689111199342#6673 +0.9822978683253825#6674 +0.9960918298556162#6675 +0.9999331710861101#6676 +0.9937835106050681#6677 +0.977704293787209#6678 +0.9518561788518946#6679 +0.9164974316193079#6680 +0.871981345003749#6681 +0.8187527090276192#6682 +0.7573433666265443#6683 +0.6883668996505666#6684 +0.6125124981571216#6685 +0.5305380742518008#6686 +0.4432626892811246#6687 +0.3515583700423137#6688 +0.25634139577978515#6689 +0.15856314302582344#6690 +0.05920057976075344#6691 +-0.04075349612817637#6692 +-0.14030037655510802#6693 +-0.2384454219966389#6694 +-0.3342079996011555#6695 +-0.42663128134813255#6696 +-0.514791804357429#6697 +-0.5978086978251298#6698 +-0.674852484393442#6699 +-0.7451533680142645#6700 +-0.8080089254968401#6701 +-0.8627911248880876#6702 +-0.908952600560277#6703 +-0.9460321223074467#6704 +-0.973659203805159#6705 +-0.9915578043873877#6706 +-0.9995490871536059#6707 +-0.9975532058479801#6708 +-0.9855901026567658#6709 +-0.9637793089525735#6710 +-0.9323387509764054#6711 +-0.8915825723906932#6712 +-0.8419179954596638#6713 +-0.783841252219086#6714 +-0.7179326262898007#6715 +-0.6448506548755989#6716 +-0.5653255488771634#6717 +-0.4801518968661259#6718 +-0.39018072581871516#6719 +-0.2963109979355221#6720 +-0.1994806285083495#6721 +-0.10065711458064946#6722 +-8.278680368774796E-4#6723 +0.0990096502906622#6724 +0.1978578969207362#6725 +0.2947292128479025#6726 +0.388655691904816#6727 +0.4786988517607058#6728 +0.5639590109266028#6729 +0.6435842780753824#6730 +0.7167790638583078#6731 +0.7828120301708148#6732 +0.8410233974411052#6733 +0.8908315369295339#6734 +0.9317387821707139#6735 +0.963336401492333#6736 +0.9853086819269133#6737 +0.997436083711423#6738 +0.9995974338560171#6739 +0.9917711368644981#6740 +0.9740353905093757#6741 +0.9465674045055719#6742 +0.9096416298895278#6743 +0.863627016795169#6744 +0.8089833280261255#6745 +0.746256545257776#6746 +0.6760734137688245#6747 +0.59913518020965#6748 +0.5162105859775773#6749 +0.42812818620694754#6750 +0.33576807112009877#6751 +0.24005307245678428#6752 +0.14193954284447627#6753 +0.04240780023904047#6754 +-0.05754766708822902#6755 +-0.15692813714868228#6756 +-0.2547406331362906#6757 +-0.3500078449236578#6758 +-0.4417778940217574#6759 +-0.5291338444351459#6760 +-0.6112028643833304#6761 +-0.6871649473473994#6762 +-0.7562611053041018#6763 +-0.8178009522832872#6764 +-0.8711696024763078#6765 +-0.9158338139717653#6766 +-0.9513473167324222#6767 +-0.977355271577897#6768 +-0.9935978156204607#6769 +-0.9999126587291108#6770 +-0.9962367050789155#6771 +-0.9826066835836388#6772 +-0.9591587809125754#6773 +-0.9261272807583686#6774 +-0.8838422229517972#6775 +-0.8327261058128828#6776 +-0.7732896646873357#6777 +-0.7061267688478077#6778 +-0.6319084877484257#6779 +-0.5513763859206331#6780 +-0.4653351135055202#6781 +-0.37464436645559573#6782 +-0.28021029673700776#6783 +-0.18297645835863166#6784 +-0.08391437969231084#6785 +0.0159861437174899#6786 +0.11572693886358196#6787 +0.21431142869078854#6788 +0.31075458956445545#6789 +0.40409279330100306#6790 +0.4933934354222034#6791 +0.5777642534308487#6792 +0.6563622420026807#6793 +0.72840207601693#6794 +0.793163957265329#6795 +0.8500008064378751#6796 +0.8983447285254006#6797 +0.9377126870387825#6798 +0.967711330349872#6799 +0.9880409219309375#6800 +0.9984983352229706#6801 +0.9989790832091183#6802 +0.9894783624144172#6803 +0.9700911009005274#6804 +0.9410110097759191#6805 +0.9025286476985094#6806 +0.8550285177095982#6807 +0.7989852254065796#6808 +0.7349587368406961#6809 +0.6635887835213552#6810 +0.585588470430354#6811 +0.5017371509126227#6812 +0.41287263963522164#6813 +0.3198828414201331#6814 +0.22369687959278223#6815 +0.1252758124888965#6816 +0.02560303087729906#6817 +-0.07432556775558767#6818 +-0.17351152988422644#6819 +-0.27096382216154746#6820 +-0.3657087334965602#6821 +-0.4567996040537086#6822 +-0.5433262839650238#6823 +-0.6244242272467491#6824 +-0.699283130057029#6825 +-0.7671550269840464#6826 +-0.8273617644691722#6827 +-0.8793017766931565#6828 +-0.9224560962229421#6829 +-0.9563935393627088#6830 +-0.980775014398831#6831 +-0.9953569096921918#6832 +-0.9999935277651537#6833 +-0.9946385410625938#6834 +-0.9793454548415207#6835 +-0.9542670725642333#6836 +-0.9196539691366354#6837 +-0.8758519872466048#6838 +-0.823298781818177#6839 +-0.7625194471082125#6840 +-0.6941212701381572#6841 +-0.6187876628828645#6842 +-0.5372713338440499#6843 +-0.45038676723575394#6844 +-0.3590020849273077#6845 +-0.26403037245657784#6846 +-0.16642055578109807#6847 +-0.06714791992357462#6848 +0.03279563575367421#6849 +0.13241150827926804#6850 +0.23070436878356018#6851 +0.32669210749569116#6852 +0.4194156466597768#6853 +0.5079485233228161#6854 +0.59140614624627#6855 +0.6689546344493088#6856 +0.7398191490719298#6857 +0.8032916353087174#6858 +0.858737897058408#6859 +0.9056039336016954#6860 +0.9434214749932913#6861 +0.9718126608604276#6862 +0.9904938158587981#6863 +0.9992782840628278#6864 +0.9980782939699812#6865 +0.986905835484602#6866 +0.9658725401187522#6867 +0.9351885656070448#6868 +0.8951604960800272#6869 +0.846188278776893#6870 +0.7887612279048725#6871 +0.72345313557342#6872 +0.6509165386531266#6873 +0.571876198843009#6874 +0.4871218610911878#6875 +0.3975003627244203#6876 +0.3039071721294589#6877 +0.20727744152893346#6878 +0.1085766632494626#6879 +0.008791022841475713#6880 +-0.09108245456081744#6881 +-0.19004586618499503#6882 +-0.2871104023350624#6883 +-0.3813062262510775#6884 +-0.4716921643974707#6885 +-0.5573651103579016#6886 +-0.637469048376044#6887 +-0.7112036063820617#6888 +-0.7778320530457624#6889 +-0.8366886589525186#6890 +-0.8871853483515171#6891 +-0.9288175750142688#6892 +-0.9611693634937438#6893 +-0.9839174654135346#6894 +-0.9968345892587814#6895 +-0.9997916713978559#6896 +-0.9927591656435055#6897 +-0.9758073384685907#6898 +-0.9491055669267142#6899 +-0.9129206462926903#6900 +-0.86761412433235#6901 +-0.813638688836776#6902 +-0.7515336445155336#6903 +-0.6819195244422828#6904 +-0.605491889893427#6905 +-0.5230143805297617#6906 +-0.43531108436140914#6907 +-0.3432583037328287#6908 +-0.24777579959945775#6909 +-0.1498176015802779#6910 +-0.050362475609222065#6911 +0.04959585557050026#6912 +0.14905864135557212#6913 +0.24703208246845434#6914 +0.34253726067126045#6915 +0.43461991979320214#6916 +0.5223600003428128#6917 +0.6048808324382549#6918 +0.6813578952029908#6919 +0.7510270551058309#6920 +0.813192200930588#6921 +0.867232199089246#6922 +0.9126070997834519#6923 +0.9488635320044169#6924 +0.975639233466172#6925 +0.9926666702105814#6926 +0.9997757097182173#6927 +0.9968953208162551#6928 +0.9840542833984735#6929 +0.9613809008660682#6930 +0.9291017181624794#6931 +0.8875392582112024#6932 +0.8371087993733477#6933 +0.7783142261235303#6934 +0.7117429944027603#6935 +0.6380602619528687#6936 +0.558002242280222#6937 +0.47236884865372675#6938 +0.38201570163586274#6939 +0.28784558000485344#6940 +0.19079940048753272#6941 +0.09184681643043616#6942 +-0.008023470655912756#6943 +-0.10781358987567453#6944 +-0.20652647134383265#6945 +-0.30317580857889714#6946 +-0.39679591335123815#6947 +-0.4864513645206622#6948 +-0.5712463544552357#6949 +-0.6503336396450295#6950 +-0.7229230060792073#6951 +-0.7882891648032128#6952 +-0.8457789987662547#6953 +-0.8948180885509868#6954 +-0.9349164517824474#6955 +-0.9656734388699845#6956 +-0.9867817361655272#6957 +-0.998030436539974#6958 +-0.9993071466975093#6959 +-0.9905991101722632#6960 +-0.9719933347867018#6961 +-0.9436757232982262#6962 +-0.9059292159202714#6963 +-0.8591309632772218#6964 +-0.8037485580400412#6965 +-0.7403353628948707#6966 +-0.6695249815259856#6967 +-0.592024927857224#6968 +-0.508609556806733#6969 +-0.42011232718859376#6970 +-0.3274174740678562#6971 +-0.23145117377605856#6972 +-0.1331722898634756#6973 +-0.03356279245148251#6974 +0.0663820532883018#6975 +0.16566363149461852#6976 +0.2632899534561562#6977 +0.3582855692348461#6978 +0.449701314039203#6979 +0.5366237919651687#6980 +0.618184502346058#6981 +0.6935685175241308#6982 +0.7620226253383701#6983 +0.8228628549714151#6984 +0.8754813109598781#6985 +0.9193522470848716#6986 +0.9540373194544375#6987 +0.9791899662908198#6988 +0.9945588706611886#6989 +0.9999904715533596#6990 +0.9954304982066668#6991 +0.9809245123674635#6992 +0.9566174530512137#6993 +0.92275218835976#6994 +0.8796670888235313#6995 +0.8277926465150534#6996 +0.767647173714462#6997 +0.699831624104531#6998 +0.6250235882401227#6999 +0.5439705232873457#7000 +0.45748228467862745#7001 +0.3664230343049359#7002 +0.2717026060958192#7003 +0.17426741525953252#7004 +0.07509100201512046#7005 +-0.024835695699641874#7006 +-0.12451424335256278#7007 +-0.22294868584484095#7008 +-0.3191554987651938#7009 +-0.4121734154406648#7010 +-0.5010730315954676#7011 +-0.5849660916512891#7012 +-0.6630143638834097#7013 +-0.7344380157550146#7014 +-0.7985234057461226#7015 +-0.8546302138237558#7016 +-0.9021978393080471#7017 +-0.9407510022089238#7018 +-0.9699044920666614#7019 +-0.9893670168474638#7020 +-0.9989441134371765#7021 +-0.9985400906524421#7022 +-0.9881589853553737#7023 +-0.9679045221185625#7024 +-0.9379790768434352#7025 +-0.8986816546871441#7026 +-0.8504049025018744#7027 +-0.7936311856372888#7028 +-0.7289277683054031#7029 +-0.6569411456640912#7030 +-0.5783905842511721#7031 +-0.4940609353109204#7032 +-0.40479479281987163#7033 +-0.3114840745663333#7034 +-0.21506111040267262#7035 +-0.11648932671361892#7036 +-0.016753620178294085#7037 +0.0831494829918418#7038 +0.1822217840134876#7039 +0.27947338520378323#7040 +0.37393258071074015#7041 +0.46465556547691106#7042 +0.5507358654275436#7043 +0.6313133946598948#7044 +0.7055830491372643#7045 +0.7728027510223979#7046 +0.8323008632739383#7047 +0.8834829004217286#7048 +0.9258374684691203#7049 +0.9589413745727422#7050 +0.9824638554455033#7051 +0.9961698822340214#7052 +0.9999225088492355#7053 +0.9936842402864599#7054 +0.9775174072630763#7055 +0.9515835434306101#7056 +0.9161417713838799#7057 +0.8715462135936842#7058 +0.8182424541321317#7059 +0.756763086543882#7060 +0.6877223923475002#7061 +0.6118102033375776#7062 +0.5297850090134684#7063 +0.44246637800293476#7064 +0.35072676920333273#7065 +0.2554828144607054#7066 +0.15768615988737594#7067 +0.05831395732856547#7068 +-0.041640899015840796#7069 +-0.14117969326193175#7070 +-0.2393078666807508#7071 +-0.33504495500035825#7072 +-0.427434384880738#7073 +-0.5155530316784099#7074 +-0.5985204430027234#7075 +-0.6755076359051054#7076 +-0.7457453798026574#7077 +-0.8085318823758662#7078 +-0.863239801645478#7079 +-0.9093225141661847#7080 +-0.9463195767073986#7081 +-0.9738613268498107#7082 +-0.99167257653009#7083 +-0.9995753616290475#7084 +-0.9974907201302877#7085 +-0.9854394810825754#7086 +-0.9635420564828655#7087 +-0.932017238159432#7088 +-0.8911800116762435#7089 +-0.8414384091013278#7090 +-0.783289432085226#7091 +-0.7173140859847869#7092 +-0.6441715746496963#7093 +-0.5645927138755155#7094 +-0.47937262933382613#7095 +-0.38936281193935457#7096 +-0.2954626100342169#7097 +-0.1986102433965698#7098 +-0.09977342885872108#7099 +6.0288799573731514E-5#7100 +0.09989340407211203#7101 +0.19872841747153056#7102 +0.2955778022144536#7103 +0.3894738712626798#7104 +0.47947844613219254#7105 +0.5646922308624522#7106 +0.6442637974843658#7107 +0.7173980932071098#7108 +0.7833643843228061#7109 +0.8415035574561832#7110 +0.8912347052075476#7111 +0.9320609303874993#7112 +0.9635743108493957#7113 +0.9854599753126002#7114 +0.9974992494522351#7115 +0.9995718408207521#7116 +0.9916570407703045#7117 +0.9738339313667114#7118 +0.9462805952275968#7119 +0.909272336179741#7120 +0.8631789285142464#7121 +0.8084609223240518#7122 +0.745665041839642#7123 +0.675418722741259#7124 +0.5984238430289884#7125 +0.5154497100897922#7126 +0.4273253740323974#7127 +0.3349313440926573#7128 +0.23919079087632442#7129 +0.14106032234351765#7130 +0.041520425698197#7131 +-0.05843432931587226#7132 +-0.15780522782723821#7133 +-0.2555993886656267#7134 +-0.3508396849023918#7135 +-0.4425745069797916#7136 +-0.5298872708791288#7137 +-0.6119055763252834#7138 +-0.6878099235218842#7139 +-0.7568419013223837#7140 +-0.8183117650235371#7141 +-0.8716053280664775#7142 +-0.9161900987857895#7143 +-0.9516206008902112#7144 +-0.9775428245144819#7145 +-0.9936977633688959#7146 +-0.9999240026445323#7147 +-0.9961593318166703#7148 +-0.9824413662317869#7149 +-0.95890717126745#7150 +-0.9257918928203727#7151 +-0.8834264078063425#7152 +-0.8322340181474527#7153 +-0.7727262212792206#7154 +-0.7054975994372918#7155 +-0.6312198787882831#7156 +-0.55063521776397#7157 +-0.46454879165956#7158 +-0.3738207475882999#7159 +-0.27935761017584615#7160 +-0.1821032238658627#7161 +-0.08302932233833335#7162 +0.01687418073215605#7163 +0.11660908256663223#7164 +0.21517886499393998#7165 +0.3115986513309033#7166 +0.4049050469445867#7167 +0.4941657651730115#7168 +0.5784889424253095#7169 +0.6570320493879117#7170 +0.7290103092989471#7171 +0.7937045391782332#7172 +0.8504683356658855#7173 +0.8987345336710154#7174 +0.9380208732978393#7175 +0.967934818427143#7176 +0.98817747880743#7177 +0.9985465964675143#7178 +0.998938566611311#7179 +0.989349472802711#7180 +0.9698751260973173#7181 +0.9407101077300469#7182 +0.9021458249237525#7183 +0.8545675992445777#7184 +0.7984508165962385#7185 +0.7343561773212153#7186 +0.6629240938682737#7187 +0.5848682920029681#7188 +0.5009686794957195#7189 +0.4120635535411761#7190 +0.31904122476974855#7191 +0.22283114154142777#7192 +0.12439460320500637#7193 +0.02471515511274884#7194 +-0.0752112386396513#7195 +-0.17438614655709378#7196 +-0.271818645742533#7197 +-0.3665352228710099#7198 +-0.4575895012129941#7199 +-0.5440716965178346#7200 +-0.6251177072772582#7201 +-0.6999177485420057#7202 +-0.7677244430253657#7203 +-0.8278602886499732#7204 +-0.8797244279246147#7205 +-0.9227986515136628#7206 +-0.9566525760134608#7207 +-0.9809479442010262#7208 +-0.9954420047884096#7209 +-0.9999899379133214#7210 +-0.9945463021313241#7211 +-0.9791654884517249#7212 +-0.9540011768805893#7213 +-0.9193048009009206#7214 +-0.8754230352324109#7215 +-0.822794331972237#7216 +-0.7619445397266382#7217 +-0.6934816495054661#7218 +-0.618089719876988#7219 +-0.5365220420807936#7220 +-0.44959361339073317#7221 +-0.3581729939315602#7222 +-0.26317362831327207#7223 +-0.16554471879451196#7224 +-0.06626174116736495#7225 +0.03368330187430715#7226 +0.1332917924978703#7227 +0.23156847559120272#7228 +0.32753140302278777#7229 +0.42022174494285497#7230 +0.5087133700942921#7231 +0.5921220994100276#7232 +0.6696145404379987#7233 +0.7404164143230488#7234 +0.803820292145306#7235 +0.8591926633161057#7236 +0.9059802654063811#7237 +0.9437156121619712#7238 +0.9720216644717411#7239 +0.9906155976177484#7240 +0.9993116271663351#7241 +0.9980228652647771#7242 +0.9867621887959865#7243 +0.9656421107169549#7244 +0.9348736558664785#7245 +0.8947642524747242#7246 +0.8457146604419769#7247 +0.7882149670781883#7248 +0.7228396903125782#7249 +0.6502420383003954#7250 +0.5711473827829529#7251 +0.48634601141296413#7252 +0.39668523146155205#7253 +0.3030609038040782#7254 +0.20640849177440834#7255 +0.1076937143245037#7256 +0.007902896879877103#7257 +-0.09196688369802286#7258 +-0.19091776157422172#7259 +-0.2879610522857915#7260 +-0.38212713135018883#7261 +-0.472475122432569#7262 +-0.5581022982711118#7263 +-0.6381531004294191#7264 +-0.711827687753602#7265 +-0.7783899281206974#7266 +-0.8371747536275085#7267 +-0.8875948057292506#7268 +-0.9291463039319765#7269 +-0.9614140794007434#7270 +-0.9840757231893756#7271 +-0.9969048076440806#7272 +-0.9997731487937185#7273 +-0.9926520871216694#7274 +-0.9756127739222505#7275 +-0.9488254603805024#7276 +-0.9125577964786259#7277 +-0.8671721567258328#7278 +-0.8131220194320353#7279 +-0.7509474357024735#7280 +-0.6812696334255883#7281 +-0.6047848101693116#7282 +-0.5222571770050993#7283 +-0.43451132276352#7284 +-0.3424239750152328#7285 +-0.24691524009890903#7286 +-0.14893940972284261#7287 +-0.0494754259976481#7288 +0.050482899829713684#7289 +0.14993681720940477#7290 +0.24789261547406108#7291 +0.3433715526673036#7292 +0.4354196348098376#7293 +0.5231171478919449#7294 +0.6055878473518524#7295 +0.6820077132217451#7296 +0.7516131834628998#7297 +0.8137087832251761#7298 +0.8676740738018253#7299 +0.9129698518479584#7300 +0.949143536922132#7301 +0.9758336935205153#7302 +0.9927736424209699#7303 +0.9997941252536848#7304 +0.9968249956748588#7305 +0.9838959202457798#7306 +0.961136082014351#7307 +0.9287728897607787#7308 +0.8871297058042116#7309 +0.8366226150733376#7310 +0.7777562677233152#7311 +0.7111188368382388#7312 +0.6373761416001066#7313 +0.5572649946436438#7314 +0.4715858400680154#7315 +0.3811947556639786#7316 +0.2869948992675788#7317 +0.18992748470559684#7318 +0.0909623774981151#7319 +-0.008911595717163887#7320 +-0.10869652721381882#7321 +-0.20739539894084763#7322 +-0.3040220443974627#7323 +-0.3976110020827836#7324 +-0.48722716206801436#7325 +-0.5719751093057461#7326 +-0.6510080703211262#7327 +-0.7235363738925117#7328 +-0.7888353411852869#7329 +-0.8462525265032307#7330 +-0.8952142363102442#7331 +-0.935231261386525#7332 +-0.9659037648453803#7333 +-0.9869252771712309#7334 +-0.9980857583617049#7335 +-0.9992736965779115#7336 +-0.9904772223338747#7337 +-0.971784227092513#7338 +-0.9433814850831956#7339 +-0.9055527871153815#7340 +-0.85867610503466#7341 +-0.8032198151530112#7342 +-0.7397380183875204#7343 +-0.6688650038671767#7344 +-0.5913089113255638#7345 +-0.5078446556027223#7346 +-0.4193061839522201#7347 +-0.32657814351586195#7348 +-0.23058704222187348#7349 +-0.13229199142394524#7350 +-0.03267512277762666#7351 +0.06726822489452655#7352 +0.16653945069945214#7353 +0.2641466693636113#7354 +0.35911462182276815#7355 +0.45049441968818166#7356 +0.5373730262257255#7357 +0.6188823791171251#7358 +0.6942080638516992#7359 +0.7625974510869405#7360 +0.82336721667212#7361 +0.875910169197324#7362 +0.9197013168493114#7363 +0.9543031129561722#7364 +0.9793698278090396#7365 +0.994651003079058#7366 +0.999993954314214#7367 +0.995345296511911#7368 +0.9807514775242675#7369 +0.9563583139665331#7370 +0.9224095342656689#7371 +0.8792443434064714#7372 +0.827294033707491#7373 +0.7670776754907508#7374 +0.6991969307026712#7375 +0.624330041306784#7376 +0.5432250525142298#7377 +0.4566923385632795#7378 +0.36559650572781904#7379 +0.27084775345726186#7380 +0.1733927799645225#7381 +0.07420532313040953#7382 +-0.025723568763404207#7383 +-0.1253954392612152#7384 +-0.22381439998014888#7385 +-0.3199970811976842#7386 +-0.4129824573568625#7387 +-0.5018414493159796#7388 +-0.5856862074002571#7389 +-0.6636789825023087#7390 +-0.7350404965942983#7391 +-0.7990577290163985#7392 +-0.855091040743531#7393 +-0.9025805654470686#7394 +-0.9410518034941227#7395 +-0.9701203629910278#7396 +-0.9894958005000788#7397 +-0.9989845230543534#7398 +-0.9984917224746438#7399 +-0.9880223226614443#7400 +-0.9676809303969649#7401 +-0.9376707901487422#7402 +-0.8982917533181031#7403 +-0.8499372822240805#7404 +-0.793090518757983#7405 +-0.7283194569893225#7406 +-0.6562712679568256#7407 +-0.57766583334934#7408 +-0.4932885526859621#7409 +-0.40398249586366014#7410 +-0.31063997948154537#7411 +-0.21419365110837466#7412 +-0.11560717057633567#7413 +-0.015865581410547242#7414 +0.0840345314002315#7415 +0.18309499895138165#7416 +0.28032604179616866#7417 +0.3747561594947966#7418 +0.4654418375256672#7419 +0.5514769745705953#7420 +0.6320019359796627#7421 +0.7062121429564829#7422 +0.7733661116435763#7423 +0.8327928617839718#7424 +0.8838986209341382#7425 +0.9261727572419648#7426 +0.9591928815114351#7427 +0.9826290675758504#7428 +0.996247148811028#7429 +0.9999110578508053#7430 +0.9935841861271838#7431 +0.9773297496510405#7432 +0.9513101573786427#7433 +0.9157853884750424#7434 +0.8711103946881975#7435 +0.8177315537884366#7436 +0.7561822095093318#7437 +0.6870773425534116#7438 +0.6111074259082679#7439 +0.529031525868704#7440 +0.44166971769722985#7441 +0.34989489170312094#7442 +0.2546240316109867#7443 +0.15680905236250883#7444 +0.05742728889700527#7445 +-0.04252826905621956#7446 +-0.14205889860301116#7447 +-0.2401701225933894#7448 +-0.33588164610850085#7449 +-0.42823715124340533#7450 +-0.5163138523194657#7451 +-0.5992317160538159#7452 +-0.6761622545610236#7453 +-0.7463368033301797#7454 +-0.809054201466604#7455 +-0.8636877974597326#7456 +-0.9096917104778677#7457 +-0.9466062846290039#7458 +-0.9740626816905584#7459 +-0.9917865664189706#7460 +-0.9996008476167711#7461 +-0.9974274475692897#7462 +-0.9852880821713702#7463 +-0.963304043949328#7464 +-0.9316949901461209#7465 +-0.8907767479787866#7466 +-0.840958158997289#7467 +-0.782736994074895#7468 +-0.7166949798461515#7469 +-0.6434919862866445#7470 +-0.5638594335103286#7471 +-0.47859298366152303#7472 +-0.38854459092177623#7473 +-0.2946139890653031#7474 +-0.19773970161652513#7475 +-0.09888966443324891#7476 +9.484455884677701E-4#7477 +0.10077707905537892#7478 +0.19959878126084157#7479 +0.29642615842253006#7480 +0.3902917433947197#7481 +0.4802576622802053#7482 +0.5654250053562614#7483 +0.6449428086834523#7484 +0.7180165566560236#7485 +0.7839161205392026#7486 +0.8419830536741678#7487 +0.8916371704594106#7488 +0.9323823433734814#7489 +0.963811460117186#7490 +0.985610491345106#7491 +0.9975616283430137#7492 +0.9995454593005464#7493 +0.9915421624345439#7494 +0.973631704041753#7495 +0.9459930395020244#7496 +0.908902325215311#7497 +0.8627301593382061#7498 +0.8079378788896648#7499 +0.7450729502240094#7500 +0.6747634989280851#7501 +0.597712033798026#7502 +0.5146884276035842#7503 +0.4265222247738995#7504 +0.33409435286377454#7505 +0.23832832061674333#7506 +0.1401809905709772#7507 +0.040633018405099953#7508 +-0.0593209454491911#7509 +-0.15868219402545106#7510 +-0.25645794257236754#7511 +-0.35167124813082457#7512 +-0.4433707708250161#7513 +-0.5306402793360133#7514 +-0.6126078055822383#7515 +-0.6884543571363001#7516 +-0.7574221003266068#7517 +-0.8188219322609055#7518 +-0.8720403661145942#7519 +-0.9165456608882823#7520 +-0.9518931343880851#7521 +-0.9777296063431139#7522 +-0.993796927265996#7523 +-0.99993455779722#7524 +-0.9960811727613489#7525 +-0.9822752739079014#7526 +-0.9586548052145977#7527 +-0.9254557745967325#7528 +-0.8830098957940993#7529 +-0.8317412739969522#7530 +-0.772162168327135#7531 +-0.7048678735142673#7532 +-0.6305307719075828#7533 +-0.5498936152537572#7534 +-0.4637621033669758#7535 +-0.37299683384271926#7536 +-0.2785047032510652#7537 +-0.18122984572594025#7538 +-0.0821441994889431#7539 +0.017762204436085696#7540 +0.1174911342857932#7541 +0.21604613155912197#7542 +0.31244246730126723#7543 +0.4057169811898851#7544 +0.4949377051146552#7545 +0.5792131750945708#7546 +0.6577013384913591#7547 +0.7296179675210964#7548 +0.794244494998994#7549 +0.8509351940251821#7550 +0.8991236298744447#7551 +0.9383283196247547#7552 +0.9681575429754743#7553 +0.9883132561871131#7554 +0.9985940700358535#7555 +0.998897262028104#7556 +0.9892198027697#7557 +0.9696583862346088#7558 +0.9404084636307043#7559 +0.9017622905159063#7560 +0.8541060066772513#7561 +0.7979157779497825#7562 +0.7337530385249249#7563 +0.6622588812856302#7564 +0.5841476522182073#7565 +0.5001998129033588#7566 +0.4112541424020529#7567 +0.3181993564524092#7568 +0.22196522771581453#7569 +0.12351329579583167#7570 +0.023827259852323673#7571 +-0.07609685019538392#7572 +-0.17526062567021322#7573 +-0.2726732549068054#7574 +-0.367361423114162#7575 +-0.4583790374153017#7576 +-0.5448166798945504#7577 +-0.6258106942007409#7578 +-0.7005518149159866#7579 +-0.7682932534682305#7580 +-0.8283581597958007#7581 +-0.8801463852094901#7582 +-0.923140478879876#7583 +-0.9569108580349618#7584 +-0.9811201002092328#7585 +-0.995526314657395#7586 +-0.9999855592467439#7587 +-0.9944532786793728#7588 +-0.9789847496739821#7589 +-0.953734528659178#7590 +-0.9189549074967269#7591 +-0.8749933926646701#7592 +-0.822289233087465#7593 +-0.7613690313059284#7594 +-0.6928414818387202#7595 +-0.6173912893079209#7596 +-0.5357723270967809#7597 +-0.44880010489607236#7598 +-0.3573436204008309#7599 +-0.2623166765726389#7600 +-0.16466875122249675#7601 +-0.06537551014239087#7602 +0.03457094142478756#7603 +0.13417197157288324#7604 +0.23243239973237922#7605 +0.3283704401856845#7606 +0.42102751174548914#7607 +0.5094778155811228#7608 +0.5928375854944425#7609 +0.6702739182195506#7610 +0.7410130955169058#7611 +0.8043483149102156#7612 +0.859646751823142#7613 +0.9063558825532837#7614 +0.9440090049063705#7615 +0.9722299013303181#7616 +0.9907365979566459#7617 +0.9993441819901644#7618 +0.9979666492964995#7619 +0.9866177637269746#7620 +0.9654109195947578#7621 +0.9345580086763673#7622 +0.8943673030590836#7623 +0.8452403749881539#7624 +0.7876680844896596#7625 +0.722225674859393#7626 +0.6495670250219955#7627 +0.5704181161888862#7628 +0.48556977809397517#7629 +0.39586978728437555#7630 +0.30221439641738246#7631 +0.2055393792001831#7632 +0.10681068044830018#7633 +0.007014764684294179#7634 +-0.0928512402896644#7635 +-0.19178950636318762#7636 +-0.28881147508631094#7637 +-0.38294773501875135#7638 +-0.4732577077685739#7639 +-0.55883904594057#7640 +-0.6388366490931539#7641 +-0.7124512076193162#7642 +-0.7789471891840013#7643 +-0.8376601879200635#7644 +-0.8880035629520688#7645 +-0.9294742999180047#7646 +-0.9616580369225101#7647 +-0.984233204703965#7648 +-0.9969742396482555#7649 +-0.9997538375458441#7650 +-0.9925442255733512#7651 +-0.9754174397904251#7652 +-0.948544605379246#7653 +-0.9121942268182728#7654 +-0.866729505074249#7655 +-0.8126047086182022#7656 +-0.7503606345250428#7657 +-0.6806192050079543#7658 +-0.6040772533772201#7659 +-0.5214995615121297#7660 +-0.4337112184132438#7661 +-0.3415893761858385#7662 +-0.2460544858260183#7663 +-0.14806110037862266#7664 +-0.048588337358735884#7665 +0.05136990426687065#7666 +0.15081487478967512#7667 +0.24875295293634997#7668 +0.3442055738040776#7669 +0.43621900635758876#7670 +0.5238738827944053#7671 +0.6062943845640199#7672 +0.6826569932573459#7673 +0.7521987189304415#7674 +0.8142247236478194#7675 +0.8681152640734142#7676 +0.9133318837411375#7677 +0.9494227931338964#7678 +0.976027383815107#7679 +0.9928798315089906#7680 +0.9998117521288687#7681 +0.9967538842152956#7682 +0.9837367809736671#7683 +0.9608905049966914#7684 +0.9284433287219556#7685 +0.8867194536091866#7686 +0.836135770826432#7687 +0.7771976958113149#7688 +0.7104941183270491#7689 +0.6366915184705867#7690 +0.5565273074237976#7691 +0.4708024594846968#7692 +0.3803735089970247#7693 +0.286143992142218#7694 +0.18905541910455304#7695 +0.09007786681260743#7696 +-0.009799713748746178#7697 +-0.10957937880967696#7698 +-0.2082641629396677#7699 +-0.30486804039654375#7700 +-0.3984257771697518#7701 +-0.48800257527952967#7702 +-0.5727034129693166#7703 +-0.6516819874672904#7704 +-0.7241491709639128#7705 +-0.7893808953161512#7706 +-0.8467253866970188#7707 +-0.8956096779042066#7708 +-0.9355453332589703#7709 +-0.9661333288939775#7710 +-0.9870680396678903#7711 +-0.9981402928707507#7712 +-0.9992394582085561#7713 +-0.9903545531845869#7714 +-0.9715743528328836#7715 +-0.9430865027074515#7716 +-0.9051756439899129#7717 +-0.8582205694489098#7718 +-0.8026904386679721#7719 +-0.7391400903580423#7720 +-0.6682044985924814#7721 +-0.5905924283560221#7722 +-0.507079353799328#7723 +-0.4184997099576176#7724 +-0.32573855535162055#7725 +-0.22972272877539926#7726 +-0.13141158862949134#7727 +-0.03178742732889281#7728 +0.0681543434380497#7729 +0.16741513853418957#7730 +0.26500317690618225#7731 +0.3599433911329309#7732 +0.45128716997694385#7733 +0.5381218365942502#7734 +0.6195797676997338#7735 +0.6948470625722005#7736 +0.763171675281344#7737 +0.8238709288820886#7738 +0.8763383364969607#7739 +0.9200496611324916#7740 +0.9545681536819657#7741 +0.979548916778125#7742 +0.994742350893655#7743 +0.999996648257155#7744 +0.9952593096662085#7745 +0.9805776690420603#7746 +0.956098420484722#7747 +0.9220661525540147#7748 +0.8788209044215302#7749 +0.8267947683116299#7750 +0.7665075721787701#7751 +0.6985616857584132#7752 +0.6236360018877475#7753 +0.542479153232871#7754 +0.4559020321986561#7755 +0.3647696887598858#7756 +0.2699926871678532#7757 +0.1725180078933547#7758 +0.07331958571085657#7759 +-0.026611421535832028#7760 +-0.1262765362551009#7761 +-0.22467993756558144#7762 +-0.3208384112092187#7763 +-0.4137911735031304#7764 +-0.5026094711725734#7765 +-0.58640586114666#7766 +-0.6643430775961726#7767 +-0.7356423976169658#7768 +-0.7995914219718132#7769 +-0.855551193148098#7770 +-0.9029625796100673#7771 +-0.9413518624563137#7772 +-0.9703354686624472#7773 +-0.9896238036159622#7774 +-0.9990241446498792#7775 +-0.9984425666639266#7776 +-0.987884880593096#7777 +-0.9674565753467003#7778 +-0.9373617637980615#7779 +-0.8979011433561516#7780 +-0.8494689914964797#7781 +-0.7925492262708868#7782 +-0.7277105711583345#7783 +-0.6556008725678979#7784 +-0.5769406267715956#7785 +-0.4925157809438046#7786 +-0.40316988023689265#7787 +-0.3097956393568956#7788 +-0.2133260228532663#7789 +-0.11472492324549403#7790 +-0.014977530127669912#7791 +0.08491951352027674#7792 +0.1839680694597875#7793 +0.28117847726101386#7794 +0.3755794426626941#7795 +0.46622774242334464#7796 +0.5522176486961006#7797 +0.6326899787619682#7798 +0.7068406796995446#7799 +0.773928862216024#7800 +0.8332842033681063#7801 +0.8843136442072667#7802 +0.9265073154287307#7803 +0.9594436318170264#7804 +0.9827935045861007#7805 +0.9963236295256865#7806 +0.9998988180998523#7807 +0.993483348206165#7808 +0.97714132109913#7809 +0.951036020911645#7810 +0.9154282831739184#7811 +0.8706738886310726#7812 +0.817220008399544#7813 +0.7556007359811027#7814 +0.6864317507771306#7815 +0.6104041664235594#7816 +0.5282776254118724#7817 +0.44087270899243347#7818 +0.3490627381978821#7819 +0.2537650479080564#7820 +0.15593182114310442#7821 +0.056540575165497#7822 +-0.04341560554933505#7823 +-0.1429379918848091#7824 +-0.2410321890543877#7825 +-0.3367180722655825#7826 +-0.4290395798028944#7827 +-0.5170742656804435#7828 +-0.5999425164173386#7829 +-0.6768163398448185#7830 +-0.7469276381303027#7831 +-0.8095758823570365#7832 +-0.8641351119774621#7833 +-0.9100601892040956#7834 +-0.9468922458461004#7835 +-0.9742632681685688#7836 +-0.9918997739641114#7837 +-0.9996255450966729#7838 +-0.9973633882148972#7839 +-0.9851359060425772#7840 +-0.9630652715397107#7841 +-0.9313720071906685#7842 +-0.8903727816164261#7843 +-0.8404772455263794#7844 +-0.782183938623869#7845 +-0.7160753083622596#7846 +-0.642811890322518#7847 +-0.5631257083600311#7848 +-0.47781296046421884#7849 +-0.3877260634114115#7850 +-0.2937651356981923#7851 +-0.19686900385491865#7852 +-0.0980058220013664#7853 +0.0018366016292064157#7854 +0.10166067454339997#7855 +0.2004689876021066#7856 +0.29727428080292906#7857 +0.3911093076557798#7858 +0.4810364995900806#7859 +0.5661573338300011#7860 +0.6456213111370226#7861 +0.7186344537171913#7862 +0.7844672383847822#7863 +0.8424618857168215#7864 +0.8920389323676491#7865 +0.9327030208751224#7866 +0.9640478491086351#7867 +0.9857602299057003#7868 +0.9976232203345528#7869 +0.9995182893162105#7870 +0.9914265019478351#7871 +0.9734287086940224#7872 +0.9457047375556851#7873 +0.908531597288111#7874 +0.8622807096210473#7875 +0.807414198135553#7876 +0.7444802708779339#7877 +0.6741077428461579#7878 +0.5969997530782538#7879 +0.5139267391194702#7880 +0.42571873906499613#7881 +0.3332570980936882#7882 +0.2374656623583771#7883 +0.13930154822049173#7884 +0.03974557905975634#7885 +-0.06020751478880264#7886 +-0.15955903505155#7887 +-0.25731629417926616#7888 +-0.3525025339530001#7889 +-0.4441666849293199#7890 +-0.5313928692118094#7891 +-0.6133095516002608#7892 +-0.6890982476823034#7893 +-0.7580017018590971#7894 +-0.819331453592961#7895 +-0.8724747162774904#7896 +-0.9169004999987684#7897 +-0.9521649170110635#7898 +-0.9779156169164552#7899 +-0.9938953072335382#7900 +-0.9999443241788476#7901 +-0.996002227974605#7902 +-0.9821084067429994#7903 +-0.9584016829530904#7904 +-0.9251189263525859#7905 +-0.8825926872436216#7906 +-0.8312478737500688#7907 +-0.7715975062760166#7908 +-0.7042375915754759#7909 +-0.6298411676499076#7910 +-0.5491515789749879#7911 +-0.46297504924832533#7912 +-0.37217262586877564#7913 +-0.27765157663545714#7914 +-0.18035632462780476#7915 +-0.08125901184234507#7916 +0.018650214128785595#7917 +0.1183730933252825#7918 +0.21691322770221497#7919 +0.313286036809926#7920 +0.40652859539642616#7921 +0.4957092546382107#7922 +0.5799369508673419#7923 +0.6583701087850726#7924 +0.7302250502040435#7925 +0.7947838243016816#7926 +0.8514013811474965#7927 +0.8995120168287606#7928 +0.9386350257770081#7929 +0.9683795038191755#7930 +0.9884482539628825#7931 +0.9986407558905398#7932 +0.9988551694920795#7933 +0.9890893524176707#7934 +0.9694408814833709#7935 +0.940106077715835#7936 +0.9013780447775112#7937 +0.8536437403717337#7938 +0.7973801098892623#7939 +0.7331493209275945#7940 +0.6615931462981596#7941 +0.5834265516445285#7942 +0.49943055174204004#7943 +0.410444406856334#7944 +0.31735723713220004#7945 +0.221099138798995#7946 +0.1226318909565677#7947 +0.022939345796415475#7948 +-0.07698240172419506#7949 +-0.17613496653377583#7950 +-0.2735276489802294#7951 +-0.3681873335742909#7952 +-0.45916821203782765#7953 +-0.5455612335075115#7954 +-0.626503187470553#7955 +-0.7011853286788058#7956 +-0.7688614578639504#7957 +-0.8288553775139227#7958 +-0.8805676482149329#7959 +-0.9234815780519405#7960 +-0.957168385223473#7961 +-0.9812914822876503#7962 +-0.9956098392326427#7963 +-0.9999803917688753#7964 +-0.9943594707801187#7965 +-0.9788032386508632#7966 +-0.9534671281103374#7967 +-0.9186042892000581#7968 +-0.8745630598822943#7969 +-0.8217834855622946#7970 +-0.7607929223000569#7971 +-0.6922007676428981#7972 +-0.6166923717266009#7973 +-0.535022189483404#7974 +-0.44800624237770903#7975 +-0.35651396498934845#7976 +-0.2614595179106613#7977 +-0.1637926537560355#7978 +-0.06448922754773154#7979 +0.03545855370492522#7980 +0.13505204481000171#7981 +0.23329614052560674#7982 +0.32920921832252986#7983 +0.42183294643207214#7984 +0.5102418591802964#7985 +0.5935526039351231#7986 +0.6709327672738326#7987 +0.7416091921828252#7988 +0.80487570318693#7989 +0.8601001622213218#7990 +0.9067307847461078#7991 +0.9443016529950545#7992 +0.9724373712718963#7993 +0.9908568167800427#7994 +0.9993759485086353#7995 +0.9979096461094927#7996 +0.9864725603914919#7997 +0.9651789669345293#7998 +0.9342416242857009#7999 \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_barchart_sinus.xml b/MPChartExample/res/layout/activity_barchart_sinus.xml index a4bb6201b7..78b849081f 100644 --- a/MPChartExample/res/layout/activity_barchart_sinus.xml +++ b/MPChartExample/res/layout/activity_barchart_sinus.xml @@ -19,7 +19,7 @@ android:layout_marginBottom="35dp" android:layout_toLeftOf="@+id/tvValueCount" android:layout_marginRight="5dp" - android:max="750" + android:max="8000" android:paddingBottom="12dp" /> entries) { float bottom = y <= 0 ? y : 0; // multiply the height of the rect with the phase - if (top >= 0) + if (top > 0) top *= phaseY; else bottom *= phaseY; @@ -87,7 +87,7 @@ public void feed(ArrayList entries) { float bottom = y <= 0 ? y : 0; // multiply the height of the rect with the phase - if (top >= 0) + if (top > 0) top *= phaseY; else bottom *= phaseY; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 0a1d5b5bbf..31602be204 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -39,7 +39,7 @@ public void feed(ArrayList entries) { float left = y <= 0 ? y : 0; // multiply the height of the rect with the phase - if (right >= 0) + if (right > 0) right *= phaseY; else left *= phaseY; @@ -62,7 +62,7 @@ public void feed(ArrayList entries) { float left = y <= 0 ? y : 0; // multiply the height of the rect with the phase - if (right >= 0) + if (right > 0) right *= phaseY; else left *= phaseY; From 7735226b90e4c57cd30ab31f460b48104c192d26 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 01:01:04 +0100 Subject: [PATCH 0189/1390] Worked on LineChart Performance. --- .../MultiLineChartActivity.java | 2 + .../charting/buffer/CircleBuffer.java | 32 ++++ .../charting/renderer/LineChartRenderer.java | 157 ++++++++++-------- 3 files changed, 119 insertions(+), 72 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 666bc45006..fafc9506eb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -197,6 +197,8 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + mChart.resetTracking(); tvX.setText("" + (mSeekBarX.getProgress())); tvY.setText("" + (mSeekBarY.getProgress())); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java new file mode 100644 index 0000000000..614ecf4bf9 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java @@ -0,0 +1,32 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.Entry; + +import java.util.ArrayList; + +public class CircleBuffer extends AbstractBuffer { + + public CircleBuffer(int size) { + super(size); + } + + protected void addCircle(float x, float y) { + buffer[index++] = x; + buffer[index++] = y; + } + + @Override + public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; + + for (int i = 0; i < size; i++) { + + Entry e = entries.get(i); + addCircle(e.getXIndex(), e.getVal() * phaseY); + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 55942c99c7..d112a64b11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -5,9 +5,9 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; -import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.CircleBuffer; import com.github.mikephil.charting.buffer.LineBuffer; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -40,6 +40,8 @@ public class LineChartRenderer extends DataRenderer { protected LineBuffer[] mLineBuffers; + protected CircleBuffer[] mCircleBuffers; + public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); @@ -59,9 +61,17 @@ public void initBuffers() { for (int i = 0; i < mLineBuffers.length; i++) { LineDataSet set = lineData.getDataSetByIndex(i); int size = lineData.getXValCount() * 4 - 4; - if(size < 4) size = 4; + if (size < 4) + size = 4; mLineBuffers[i] = new LineBuffer(size); } + + mCircleBuffers = new CircleBuffer[lineData.getDataSetCount()]; + + for (int i = 0; i < mCircleBuffers.length; i++) { + LineDataSet set = lineData.getDataSetByIndex(i); + mCircleBuffers[i] = new CircleBuffer(set.getEntryCount() * 2); + } } /** @@ -98,35 +108,13 @@ public void drawData(Canvas c) { } } - /** - * Class needed for saving the points when drawing cubic-lines. - * - * @author Philipp Jahoda - */ - protected class CPoint { - - public float x = 0f; - public float y = 0f; - - /** x-axis distance */ - public float dx = 0f; - - /** y-axis distance */ - public float dy = 0f; - - public CPoint(float x, float y) { - this.x = x; - this.y = y; - } - } - protected void drawDataSet(Canvas c, LineDataSet dataSet) { ArrayList entries = dataSet.getYVals(); if (entries.size() < 1) return; - + calcXBounds(mChart.getTransformer(dataSet.getAxisDependency())); mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); @@ -229,7 +217,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo float fillMin = mChart.getFillFormatter() .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); @@ -260,28 +248,34 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie mRenderPaint.setStyle(Paint.Style.STROKE); + LineBuffer buffer = mLineBuffers[dataSetIndex]; + buffer.setPhases(phaseX, phaseY); + buffer.feed(entries); + + trans.pointValuesToPixel(buffer.buffer); + // more than 1 color if (dataSet.getColors().size() > 1) { - float[] positions = trans.generateTransformedValuesLine( - entries, phaseY); + for (int j = 0; j < buffer.size() - 3; j += 2) { - for (int j = 0; j < (positions.length - 2) * phaseX; j += 2) { - - if (!mViewPortHandler.isInBoundsRight(positions[j])) + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; // make sure the lines don't do shitty things outside // bounds - if (j != 0 && !mViewPortHandler.isInBoundsLeft(positions[j - 1]) - && !mViewPortHandler.isInBoundsY(positions[j + 1])) + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]) + || (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 1]) && !mViewPortHandler + .isInBoundsBottom(buffer.buffer[j + 3])) + || (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 1]) && !mViewPortHandler + .isInBoundsBottom(buffer.buffer[j + 3]))) continue; // get the color that is set for this line-segment mRenderPaint.setColor(dataSet.getColor(j / 2)); - c.drawLine(positions[j], positions[j + 1], - positions[j + 2], positions[j + 3], mRenderPaint); + c.drawLine(buffer.buffer[j], buffer.buffer[j + 1], + buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); } } else { // only one color per dataset @@ -292,18 +286,8 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie mRenderPaint.setColor(dataSet.getColor()); - LineBuffer buffer = mLineBuffers[dataSetIndex]; - buffer.setPhases(phaseX, phaseY); - buffer.feed(entries); - - trans.pointValuesToPixel(buffer.buffer); - - c.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, mRenderPaint); - - // Path line = generateLinePath(entries); - // - // trans.pathValueToPixel(line); - // c.drawPath(line, mRenderPaint); + c.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, + mRenderPaint); } mRenderPaint.setPathEffect(null); @@ -452,45 +436,52 @@ public void drawExtras(Canvas c) { protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + ArrayList dataSets = mChart.getLineData().getDataSets(); - for (int i = 0; i < mChart.getLineData().getDataSetCount(); i++) { + for (int i = 0; i < dataSets.size(); i++) { LineDataSet dataSet = dataSets.get(i); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - // if drawing circles is enabled for this dataset - if (dataSet.isDrawCirclesEnabled()) { + if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled()) + continue; - ArrayList entries = dataSet.getYVals(); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + ArrayList entries = dataSet.getYVals(); - float[] positions = trans.generateTransformedValuesLine( - entries, mAnimator.getPhaseY()); + CircleBuffer buffer = mCircleBuffers[i]; + buffer.setPhases(phaseX, phaseY); + buffer.feed(entries); - for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + trans.pointValuesToPixel(buffer.buffer); + + float halfsize = dataSet.getCircleSize() / 2f; - mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); + for (int j = 0; j < buffer.size(); j += 2) { - float x = positions[j]; - float y = positions[j + 1]; + mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); - if (!mViewPortHandler.isInBoundsRight(x)) - break; + float x = buffer.buffer[j]; + float y = buffer.buffer[j + 1]; - // make sure the circles don't do shitty things outside - // bounds - if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) - continue; + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + // make sure the circles don't do shitty things outside + // bounds + if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) + continue; - c.drawCircle(x, y, dataSet.getCircleSize(), - mRenderPaint); + c.drawCircle(x, y, dataSet.getCircleSize(), + mRenderPaint); - if (dataSet.isDrawCircleHoleEnabled()) - c.drawCircle(x, y, - dataSet.getCircleSize() / 2f, - mCirclePaintInner); - } - } // else do nothing + if (dataSet.isDrawCircleHoleEnabled()) + c.drawCircle(x, y, + halfsize, + mCirclePaintInner); + } } } @@ -527,4 +518,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { c.drawLines(pts, mHighlightPaint); } } + + /** + * Class needed for saving the points when drawing cubic-lines. + * + * @author Philipp Jahoda + */ + protected class CPoint { + + public float x = 0f; + public float y = 0f; + + /** x-axis distance */ + public float dx = 0f; + + /** y-axis distance */ + public float dy = 0f; + + public CPoint(float x, float y) { + this.x = x; + this.y = y; + } + } } From e58b9f7951039a9eac2cf6afad52fd0be103114f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 10:46:17 +0100 Subject: [PATCH 0190/1390] Worked on ScatterChart performance. --- .../mpchartexample/ScatterChartActivity.java | 2 +- .../fragments/ScatterChartFrag.java | 2 +- .../charting/buffer/ScatterBuffer.java | 32 ++++ .../charting/charts/ScatterChart.java | 39 ++-- .../renderer/ScatterChartRenderer.java | 172 +++++++++++++----- 5 files changed, 182 insertions(+), 65 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index f63c7e99ca..0ccee7446c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -214,7 +214,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set2.setScatterShape(ScatterShape.CIRCLE); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); - set3.setScatterShape(ScatterShape.TRIANGLE); + set3.setScatterShape(ScatterShape.CROSS); set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); set1.setScatterShapeSize(8f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 41a44d4104..74253f750a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -38,7 +38,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setHighlightIndicatorEnabled(false); // mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT }); mChart.setDrawGridBackground(false); - mChart.setData(generateScatterData(3, 10000, 150)); + mChart.setData(generateScatterData(2, 10000, 400)); XAxis xAxis = mChart.getXAxis(); xAxis.setEnabled(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java new file mode 100644 index 0000000000..9a2e1941f7 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java @@ -0,0 +1,32 @@ + +package com.github.mikephil.charting.buffer; + +import com.github.mikephil.charting.data.Entry; + +import java.util.ArrayList; + +public class ScatterBuffer extends AbstractBuffer { + + public ScatterBuffer(int size) { + super(size); + } + + protected void addTwo(float x, float y) { + buffer[index++] = x; + buffer[index++] = y; + } + + @Override + public void feed(ArrayList entries) { + + float size = entries.size() * phaseX; + + for (int i = 0; i < size; i++) { + + Entry e = entries.get(i); + addTwo(e.getXIndex(), e.getVal() * phaseY); + } + + reset(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 0f5140cf9a..4011fa0608 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -10,15 +10,20 @@ /** * The ScatterChart. Draws dots, triangles, squares and custom shapes into the - * chartview. + * Chart-View. CIRCLE and SCQUARE offer the best performance, TRIANGLE has the + * worst performance. * * @author Philipp Jahoda */ public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { - /** enum that defines the shape that is drawn where the values are */ + /** + * enum that defines the shape that is drawn where the values are, CIRCLE + * and SCQUARE offer the best performance, TRIANGLE has the worst + * performance. + */ public enum ScatterShape { - CROSS, TRIANGLE, CIRCLE, SQUARE, CUSTOM + CROSS, TRIANGLE, CIRCLE, SQUARE } public ScatterChart(Context context) { @@ -41,17 +46,17 @@ protected void init() { mXChartMin = -0.5f; } -// @Override -// protected void calculateOffsets() { -// super.calculateOffsets(); -// -// float offset = mData.getGreatestShapeSize() / 2f; -// mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, -// mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, -// mViewPortHandler.offsetBottom()); -// -// prepareOffsetMatrix(); -// } + // @Override + // protected void calculateOffsets() { + // super.calculateOffsets(); + // + // float offset = mData.getGreatestShapeSize() / 2f; + // mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, + // mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, + // mViewPortHandler.offsetBottom()); + // + // prepareOffsetMatrix(); + // } @Override protected void calcMinMax() { @@ -59,13 +64,13 @@ protected void calcMinMax() { if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; - + mXChartMax += 0.5f; mDeltaX = Math.abs(mXChartMax - mXChartMin); } /** - * Returns all possible predefined ScatterShapes (excluding CUSTOM). + * Returns all possible predefined ScatterShapes. * * @return */ @@ -74,7 +79,7 @@ public static ScatterShape[] getAllPossibleShapes() { ScatterShape.SQUARE, ScatterShape.CIRCLE, ScatterShape.TRIANGLE, ScatterShape.CROSS }; } - + public ScatterData getScatterData() { return mData; }; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 43a5aa738b..f80f55798a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -2,9 +2,11 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Paint.Style; import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; @@ -12,6 +14,7 @@ import com.github.mikephil.charting.interfaces.ScatterDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -19,16 +22,27 @@ public class ScatterChartRenderer extends DataRenderer { protected ScatterDataProvider mChart; + protected ScatterBuffer[] mScatterBuffers; + public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; + + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); } - + @Override public void initBuffers() { - // TODO Auto-generated method stub - + + ScatterData scatterData = mChart.getScatterData(); + + mScatterBuffers = new ScatterBuffer[scatterData.getDataSetCount()]; + + for (int i = 0; i < mScatterBuffers.length; i++) { + ScatterDataSet set = scatterData.getDataSetByIndex(i); + mScatterBuffers[i] = new ScatterBuffer(set.getEntryCount() * 2); + } } @Override @@ -45,75 +59,141 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + calcXBounds(trans); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + ArrayList entries = dataSet.getYVals(); float shapeHalf = dataSet.getScatterShapeSize() / 2f; - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + ScatterShape shape = dataSet.getScatterShape(); - float[] valuePoints = trans.generateTransformedValuesScatter(entries, - mAnimator.getPhaseY()); + ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet( + dataSet)]; + buffer.setPhases(phaseX, phaseY); + buffer.feed(entries); - ScatterShape shape = dataSet.getScatterShape(); + trans.pointValuesToPixel(buffer.buffer); - for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + switch (shape) { + case SQUARE: - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) - break; + mRenderPaint.setStyle(Style.FILL); - // make sure the lines don't do shitty things outside bounds - if (j != 0 && !mViewPortHandler.isInBoundsLeft(valuePoints[j - 1]) - && !mViewPortHandler.isInBoundsY(valuePoints[j + 1])) - continue; + for (int i = 0; i < buffer.size(); i += 2) { - // Set the color for the currently drawn value. If the index is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j)); + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; - if (shape == ScatterShape.SQUARE) { + mRenderPaint.setColor(dataSet.getColor(i)); + c.drawRect(buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] + + shapeHalf, buffer.buffer[i + 1] + + shapeHalf, mRenderPaint); + } + break; + case CIRCLE: - c.drawRect(valuePoints[j] - shapeHalf, - valuePoints[j + 1] - shapeHalf, valuePoints[j] - + shapeHalf, valuePoints[j + 1] - + shapeHalf, mRenderPaint); + mRenderPaint.setStyle(Style.FILL); - } else if (shape == ScatterShape.CIRCLE) { + for (int i = 0; i < buffer.size(); i += 2) { - c.drawCircle(valuePoints[j], valuePoints[j + 1], shapeHalf, - mRenderPaint); + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; - } else if (shape == ScatterShape.CROSS) { + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; - c.drawLine(valuePoints[j] - shapeHalf, valuePoints[j + 1], - valuePoints[j] + shapeHalf, - valuePoints[j + 1], mRenderPaint); - c.drawLine(valuePoints[j], valuePoints[j + 1] - shapeHalf, - valuePoints[j], valuePoints[j + 1] - + shapeHalf, mRenderPaint); + mRenderPaint.setColor(dataSet.getColor(i)); + c.drawCircle(buffer.buffer[i], buffer.buffer[i + 1], shapeHalf, + mRenderPaint); + } + break; + case TRIANGLE: - } else if (shape == ScatterShape.TRIANGLE) { + mRenderPaint.setStyle(Style.FILL); // create a triangle path Path tri = new Path(); - tri.moveTo(valuePoints[j], valuePoints[j + 1] - shapeHalf); - tri.lineTo(valuePoints[j] + shapeHalf, valuePoints[j + 1] + shapeHalf); - tri.lineTo(valuePoints[j] - shapeHalf, valuePoints[j + 1] + shapeHalf); - tri.close(); - c.drawPath(tri, mRenderPaint); + for (int i = 0; i < buffer.size(); i += 2) { - } else if (shape == ScatterShape.CUSTOM) { + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; - Path customShape = dataSet.getCustomScatterShape(); + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; - if (customShape == null) - return; + mRenderPaint.setColor(dataSet.getColor(i)); + tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); + tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); + tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); + tri.close(); - // transform the provided custom path - trans.pathValueToPixel(customShape); - c.drawPath(customShape, mRenderPaint); - } + c.drawPath(tri, mRenderPaint); + tri.reset(); + } + break; + case CROSS: + + mRenderPaint.setStyle(Style.STROKE); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i)); + + c.drawLine(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1], + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1], mRenderPaint); + c.drawLine(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i], buffer.buffer[i + 1] + + shapeHalf, mRenderPaint); + } + break; + default: + break; } + + // else { // draw the custom-shape + // + // Path customShape = dataSet.getCustomScatterShape(); + // + // for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j += 2) { + // + // Entry e = entries.get(j / 2); + // + // if (!fitsBounds(e.getXIndex(), mMinX, mMaxX)) + // continue; + // + // if (customShape == null) + // return; + // + // mRenderPaint.setColor(dataSet.getColor(j)); + // + // Path newPath = new Path(customShape); + // newPath.offset(e.getXIndex(), e.getVal()); + // + // // transform the provided custom path + // trans.pathValueToPixel(newPath); + // c.drawPath(newPath, mRenderPaint); + // } + // } } @Override From 32efcf18fb4d26ef72eb7043d64c1a982a8a71ef Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 11:43:51 +0100 Subject: [PATCH 0191/1390] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bd8b9df4b5..f0f9847d19 100644 --- a/README.md +++ b/README.md @@ -18,13 +18,16 @@ If you would like to support this project's further development, the creator of PayPal -[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS) + - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffe (or some beer) for you! + - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! + - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! + - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! + - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! + - [**Donate 100$**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! + - Of course, you can also donate any other amount: [**Choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS) -Gittip - - Support via Gittip - +Gittip [![Gratipay](http://img.shields.io/gratipay/PhilJay.svg)](https://gratipay.com/PhilJay) From 1be67516157c6c896fa6c634c8b93b8e1bd0da24 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 14:33:48 +0100 Subject: [PATCH 0192/1390] Update README.md --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f0f9847d19..757a510cf0 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,21 @@ Forks, pull-requests or any other forms of contribution are **always welcome**. Donations ----- -If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated. +If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffe and beer). -PayPal +**PayPal** - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffe (or some beer) for you! - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - - [**Donate 100$**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - - Of course, you can also donate any other amount: [**Choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS) + - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! + - [**Donate 300 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PGW8CXUHZS2T2): I can afford it and want to assure the further development and maintenance of this project. Furthermore, I also want to show my gratitude to it's creator. + - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS). -Gittip +**Gittip** [![Gratipay](http://img.shields.io/gratipay/PhilJay.svg)](https://gratipay.com/PhilJay) From af1ed0fb15a28d07fe2b2ba80d6fc9c4160940b1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 14:36:06 +0100 Subject: [PATCH 0193/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 757a510cf0..29a34d6d92 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,11 @@ Forks, pull-requests or any other forms of contribution are **always welcome**. Donations ----- -If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffe and beer). +If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). **PayPal** - - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffe (or some beer) for you! + - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! From a493362de7c707e98dfe6d45a203ea7713aa16d2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 14:41:51 +0100 Subject: [PATCH 0194/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 29a34d6d92..ffb516d721 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ MPAndroidChart ======= -A simple charting library for Android, supporting line-, bar-, scatter-, candlestick-, pie- and radarcharts (spider web), as well as scaling, dragging, selecting and animations. **Supporting Android 2.2 (API level 8)** and upwards. +A simple and powerful charting library for Android, supporting line-, bar-, scatter-, candlestick-, pie- and radarcharts (spider web), as well as scaling, dragging, selecting and animations. **Supporting Android 2.2 (API level 8)** and upwards. Remember: *It's all about the looks.* @@ -25,7 +25,7 @@ If you would like to support this project's further development, the creator of - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - [**Donate 300 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PGW8CXUHZS2T2): I can afford it and want to assure the further development and maintenance of this project. Furthermore, I also want to show my gratitude to it's creator. - - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS). + - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! **Gittip** From f4e58ba5996634b31dc178cb2dac0fb1403a5085 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 15:09:27 +0100 Subject: [PATCH 0195/1390] Worked on CandleStick chart. --- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../mpchartexample/CandleStickChartActivity.java | 1 + .../renderer/CandleStickChartRenderer.java | 7 +++++-- .../charting/renderer/XAxisRenderer.java | 16 +++++++++------- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 1d22d7243c..fee4f56de9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -108,7 +108,7 @@ protected void onCreate(Bundle savedInstanceState) { l.setTextSize(11f); l.setXEntrySpace(4f); - mChart.animateY(1500); + mChart.animateXY(2000, 2000); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index c7f1def9e3..991b7c5c35 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -61,6 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setSpaceBetweenLabels(2); + xAxis.setDrawGridLines(false); YAxis leftAxis = mChart.getAxisLeft(); // leftAxis.setEnabled(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index cb2d31322d..bf5d7d8f03 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -68,8 +68,9 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { ArrayList entries = dataSet.getYVals(); // draw the shadow - int range = (mMaxX - mMinX) * 4; + int range = (mMaxX - mMinX + 1) * 4; int from = mMinX * 4; + int to = mMaxX + 1; CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex]; shadowBuffer.setPhases(phaseX, phaseY); @@ -81,6 +82,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor()); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); + // draw the shadow c.drawLines(shadowBuffer.buffer, from, range, mRenderPaint); CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; @@ -90,12 +92,13 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { trans.pointValuesToPixel(bodyBuffer.buffer); + // draw the body for (int j = 0; j < bodyBuffer.size(); j+=4) { // get the entry CandleEntry e = entries.get(j / 4); - if (!fitsBounds(e.getXIndex(), mMinX, mMaxX)) + if (!fitsBounds(e.getXIndex(), mMinX, to)) continue; // get the color that is specified for this position from diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index c52b0b11d8..baa82b0524 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -4,7 +4,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Align; -import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -118,15 +117,18 @@ protected void drawLabels(Canvas c, float pos) { float[] position = new float[] { 0f, 0f }; - + int maxx = mMaxX + 1; - - if(maxx > mXAxis.getValues().size()) { + int minx = mMinX - 1; + + if (maxx > mXAxis.getValues().size()) maxx = mXAxis.getValues().size(); - } - for (int i = mMinX; i < maxx; i += mXAxis.mAxisLabelModulus) { - + if (minx < 0) + minx = 0; + + for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { + position[0] = i; mTrans.pointValuesToPixel(position); From bd6b1223036c168bcf2484263a4898a120de2027 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Mar 2015 15:21:34 +0100 Subject: [PATCH 0196/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ffb516d721..d3e6d6b75d 100644 --- a/README.md +++ b/README.md @@ -183,4 +183,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -**Special thanks** to [mikegr](https://github.com/mikegr) and [ph1lb4](https://github.com/ph1lb4) for their contributions to this project. +**Special thanks** to [mikegr](https://github.com/mikegr), [ph1lb4](https://github.com/ph1lb4) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. From f2945ec0ef5932981d4464468d19292f4f0c0b5e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 9 Mar 2015 13:26:18 +0100 Subject: [PATCH 0197/1390] Improved performance of cubic-lines. --- .../CubicLineChartActivity.java | 2 +- .../mikephil/charting/buffer/LineBuffer.java | 7 +- .../charting/renderer/LineChartRenderer.java | 95 ++++++++++++------- 3 files changed, 64 insertions(+), 40 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index dbe3b422fc..026d45512d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -260,7 +260,7 @@ private void setData(int count, float range) { ArrayList vals1 = new ArrayList(); - for (int i = 5; i < count / 2; i+=2) { + for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java index 134aec5a40..7c0ab6731c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -18,7 +18,7 @@ public void moveTo(float x, float y) { buffer[index++] = x; buffer[index++] = y; - + // in case just one entry, this is overwritten when lineTo is called buffer[index] = x; buffer[index + 1] = y; @@ -42,8 +42,9 @@ public void lineTo(float x, float y) { @Override public void feed(ArrayList entries) { + moveTo(entries.get(0).getXIndex(), entries.get(0).getVal()); - + float size = entries.size() * phaseX; for (int i = 1; i < size; i++) { @@ -51,7 +52,7 @@ public void feed(ArrayList entries) { Entry e = entries.get(i); lineTo(e.getXIndex(), e.getVal() * phaseY); } - + reset(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index d112a64b11..a1d301eed8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -150,46 +150,69 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries // the path for the cubic-spline Path spline = new Path(); - ArrayList points = new ArrayList(); - for (int i = minx; i < maxx; i++) { + float size = entries.size() * phaseX; - Entry e = entries.get(i); - if (e != null) - points.add(new CPoint(e.getXIndex(), e.getVal())); - } + if (entries.size() > 2) { - if (points.size() > 1) { - for (int j = 0; j < points.size() * phaseX; j++) { + float prevDx = 0f; + float prevDy = 0f; + float curDx = 0f; + float curDy = 0f; - CPoint point = points.get(j); + Entry cur = entries.get(0); + Entry next = entries.get(1); + Entry prev = entries.get(0); + Entry prevPrev = entries.get(0); - if (j == 0) { - CPoint next = points.get(j + 1); - point.dx = ((next.x - point.x) * intensity); - point.dy = ((next.y - point.y) * intensity); - } - else if (j == points.size() - 1) { - CPoint prev = points.get(j - 1); - point.dx = ((point.x - prev.x) * intensity); - point.dy = ((point.y - prev.y) * intensity); - } - else { - CPoint next = points.get(j + 1); - CPoint prev = points.get(j - 1); - point.dx = ((next.x - prev.x) * intensity); - point.dy = ((next.y - prev.y) * intensity); - } + // let the spline start + spline.moveTo(cur.getXIndex(), cur.getVal() * phaseY); - // create the cubic-spline path - if (j == 0) { - spline.moveTo(point.x, point.y * phaseY); - } - else { - CPoint prev = points.get(j - 1); - spline.cubicTo(prev.x + prev.dx, (prev.y + prev.dy) * phaseY, point.x - - point.dx, - (point.y - point.dy) * phaseY, point.x, point.y * phaseY); - } + prevDx = (next.getXIndex() - cur.getXIndex()) * intensity; + prevDy = (next.getVal() - cur.getVal()) * intensity; + + cur = entries.get(1); + next = entries.get(2); + curDx = (next.getXIndex() - prev.getXIndex()) * intensity; + curDy = (next.getVal() - prev.getVal()) * intensity; + + // the first cubic + spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cur.getXIndex() - curDx, + (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); + + for (int j = 2; j < size - 1; j++) { + + prevPrev = entries.get(j - 2); + prev = entries.get(j - 1); + cur = entries.get(j); + next = entries.get(j + 1); + + prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; + prevDy = (cur.getVal() - prevPrev.getVal()) * intensity; + curDx = (next.getXIndex() - prev.getXIndex()) * intensity; + curDy = (next.getVal() - prev.getVal()) * intensity; + + spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cur.getXIndex() - curDx, + (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); + } + + if (size > entries.size() - 1) { + + cur = entries.get(entries.size() - 1); + prev = entries.get(entries.size() - 2); + prevPrev = entries.get(entries.size() - 3); + next = cur; + + prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; + prevDy = (cur.getVal() - prevPrev.getVal()) * intensity; + curDx = (next.getXIndex() - prev.getXIndex()) * intensity; + curDy = (next.getVal() - prev.getVal()) * intensity; + + // the last cubic + spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cur.getXIndex() - curDx, + (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); } } @@ -456,7 +479,7 @@ protected void drawCircles(Canvas c) { buffer.feed(entries); trans.pointValuesToPixel(buffer.buffer); - + float halfsize = dataSet.getCircleSize() / 2f; for (int j = 0; j < buffer.size(); j += 2) { From 4dff747b02a718a5ffd501d9d5762bb42ea63a6e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 10 Mar 2015 11:32:42 +0100 Subject: [PATCH 0198/1390] Worked on Cubic-LineChart. --- .../CubicLineChartActivity.java | 2 + .../charting/charts/BarLineChartBase.java | 28 +++-- .../mikephil/charting/charts/Chart.java | 67 ++++++---- .../charting/renderer/LineChartRenderer.java | 116 +++++++----------- 4 files changed, 104 insertions(+), 109 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 026d45512d..9690061cac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -78,10 +78,12 @@ protected void onCreate(Bundle savedInstanceState) { XAxis x = mChart.getXAxis(); x.setTypeface(tf); + x.setEnabled(false); YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); y.setLabelCount(5); + y.setEnabled(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index f7e4089dba..26c6698596 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -157,17 +157,17 @@ protected void onDraw(Canvas canvas) { long starttime = System.currentTimeMillis(); - // if data filtering is enabled - if (mFilterData) { - mData = getFilteredData(); - - Log.i(LOG_TAG, "FilterTime: " + (System.currentTimeMillis() - - starttime) + " ms"); - starttime = System.currentTimeMillis(); - } else { - mData = getData(); - // Log.i(LOG_TAG, "Filtering disabled."); - } +// // if data filtering is enabled +// if (mFilterData) { +// mData = getFilteredData(); +// +// Log.i(LOG_TAG, "FilterTime: " + (System.currentTimeMillis() - +// starttime) + " ms"); +// starttime = System.currentTimeMillis(); +// } else { +// mData = getData(); +// // Log.i(LOG_TAG, "Filtering disabled."); +// } if (mXAxis.isAdjustXLabelsEnabled()) calcModulus(); @@ -175,8 +175,10 @@ protected void onDraw(Canvas canvas) { // execute all drawing commands drawGridBackground(canvas); - mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); - mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + if (mAxisLeft.isEnabled()) + mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); + if (mAxisRight.isEnabled()) + mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); // make sure the graph values and grid cannot be drawn outside the // content-rect diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 9daa7a9984..d666f82415 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -74,7 +74,7 @@ public abstract class Chart 0 && h > 0 && w < 10000 && h < 10000) { // create a new bitmap with the new dimensions mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); -// mDrawCanvas = new Canvas(mDrawBitmap); + // mDrawCanvas = new Canvas(mDrawBitmap); mViewPortHandler.setChartDimens(w, h); if (mLogEnabled) @@ -1365,4 +1365,17 @@ public View getChartView() { public PointF getCenterOfView() { return getCenter(); } + + /** + * Setting this to true will set the layer-type HARDWARE for the view, false + * will set layer-type SOFTWARE. + * + * @param enabled + */ + public void setHardwareAccelerationEnabled(boolean enabled) { + if (enabled) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index a1d301eed8..d2a775bdea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -1,10 +1,12 @@ package com.github.mikephil.charting.renderer; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.CircleBuffer; @@ -24,19 +26,21 @@ public class LineChartRenderer extends DataRenderer { /** paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; - // - // /** - // * Bitmap object used for drawing the paths (otherwise they are too long - // if - // * rendered directly on the canvas) - // */ - // protected Bitmap mPathBitmap; - // - // /** - // * on this canvas, the paths are rendered, it is initialized with the - // * pathBitmap - // */ - // protected Canvas mPathCanvas; + + /** + * Bitmap object used for drawing the paths (otherwise they are too long if + * rendered directly on the canvas) + */ + protected Bitmap mPathBitmap; + + /** + * on this canvas, the paths are rendered, it is initialized with the + * pathBitmap + */ + protected Canvas mPathCanvas; + + protected Path cubicPath = new Path(); + protected Path cubicFillPath = new Path(); protected LineBuffer[] mLineBuffers; @@ -99,6 +103,14 @@ private int getBufferSize(LineDataSet set, int xValCount) { @Override public void drawData(Canvas c) { + if (mPathBitmap == null) { + mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), + (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); + mPathCanvas = new Canvas(mPathBitmap); + } + + mPathBitmap.eraseColor(Color.TRANSPARENT); + LineData lineData = mChart.getLineData(); for (LineDataSet set : lineData.getDataSets()) { @@ -122,6 +134,7 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { // if drawing cubic lines is enabled if (dataSet.isDrawCubicEnabled()) { + drawCubic(c, dataSet, entries); // draw normal (straight) lines @@ -147,8 +160,9 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries float intensity = dataSet.getCubicIntensity(); - // the path for the cubic-spline - Path spline = new Path(); + long start = System.currentTimeMillis(); + + cubicPath.reset(); float size = entries.size() * phaseX; @@ -165,7 +179,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Entry prevPrev = entries.get(0); // let the spline start - spline.moveTo(cur.getXIndex(), cur.getVal() * phaseY); + cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); prevDx = (next.getXIndex() - cur.getXIndex()) * intensity; prevDy = (next.getVal() - cur.getVal()) * intensity; @@ -176,7 +190,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries curDy = (next.getVal() - prev.getVal()) * intensity; // the first cubic - spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); @@ -192,7 +206,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries curDx = (next.getXIndex() - prev.getXIndex()) * intensity; curDy = (next.getVal() - prev.getVal()) * intensity; - spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); } @@ -210,7 +224,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries curDy = (next.getVal() - prev.getVal()) * intensity; // the last cubic - spline.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, + cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); } @@ -219,17 +233,27 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries // if filled is enabled, close the path if (dataSet.isDrawFilledEnabled()) { + cubicFillPath.reset(); + cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(c, dataSet, new Path(spline), trans, minx, maxx); + drawCubicFill(mPathCanvas, dataSet, cubicFillPath, trans, minx, maxx); } + Log.i("", "perpare: " + (System.currentTimeMillis() - start)); + mRenderPaint.setColor(dataSet.getColor()); mRenderPaint.setStyle(Paint.Style.STROKE); - trans.pathValueToPixel(spline); + start = System.currentTimeMillis(); + trans.pathValueToPixel(cubicPath); + + Log.i("", "transform: " + (System.currentTimeMillis() - start)); + start = System.currentTimeMillis(); - c.drawPath(spline, mRenderPaint); + mPathCanvas.drawPath(cubicPath, mRenderPaint); + Log.i("", "draw: " + (System.currentTimeMillis() - start)); + c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); mRenderPaint.setPathEffect(null); } @@ -255,7 +279,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo mRenderPaint.setAlpha(dataSet.getFillAlpha()); trans.pathValueToPixel(spline); - c.drawPath(spline, mRenderPaint); + mPathCanvas.drawPath(spline, mRenderPaint); mRenderPaint.setAlpha(255); } @@ -375,30 +399,6 @@ private Path generateFilledPath(ArrayList entries, float fillMin, int fro return filled; } - /** - * Generates the path that is used for drawing a single line. - * - * @param entries - * @return - */ - private Path generateLinePath(ArrayList entries) { - - float phaseX = mAnimator.getPhaseX(); - float phaseY = mAnimator.getPhaseY(); - - Path line = new Path(); - line.moveTo(entries.get(0).getXIndex(), entries.get(0).getVal() * phaseY); - - // create a new path - for (int x = 1; x < entries.size() * phaseX; x++) { - - Entry e = entries.get(x); - line.lineTo(e.getXIndex(), e.getVal() * phaseY); - } - - return line; - } - @Override public void drawValues(Canvas c) { @@ -541,26 +541,4 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { c.drawLines(pts, mHighlightPaint); } } - - /** - * Class needed for saving the points when drawing cubic-lines. - * - * @author Philipp Jahoda - */ - protected class CPoint { - - public float x = 0f; - public float y = 0f; - - /** x-axis distance */ - public float dx = 0f; - - /** y-axis distance */ - public float dy = 0f; - - public CPoint(float x, float y) { - this.x = x; - this.y = y; - } - } } From bdac172d2eef66ee90d740842b9ac582a79ea9e0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 00:00:12 +0100 Subject: [PATCH 0199/1390] Fixed some issues with barchart and piechart. --- .../CubicLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mikephil/charting/charts/PieChart.java | 4 +- .../charting/renderer/BarChartRenderer.java | 67 +++++++++++++------ .../charting/renderer/LineChartRenderer.java | 12 ++-- .../charting/renderer/PieChartRenderer.java | 26 +++++-- 6 files changed, 77 insertions(+), 36 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 9690061cac..a59000d393 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -262,7 +262,7 @@ private void setData(int count, float range) { ArrayList vals1 = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 5; i < count-5; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3e4e3a868e..4f084c4b98 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -294,7 +294,7 @@ private void setData(int count, float range) { ArrayList yVals = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 10; i < count-10; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index dccc4e6d8d..bcd420fcc4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -93,11 +93,11 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; + mRenderer.drawData(canvas); + if (mHighlightEnabled && valuesToHighlight()) mRenderer.drawHighlighted(canvas, mIndicesToHightlight); - mRenderer.drawData(canvas); - mRenderer.drawExtras(canvas); mRenderer.drawValues(canvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index dede9f1062..42cef0f73d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -28,7 +28,7 @@ public class BarChartRenderer extends DataRenderer { protected RectF mBarRect = new RectF(); protected BarBuffer[] mBarBuffers; - + protected Paint mShadowPaint; public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, @@ -41,7 +41,7 @@ public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, mHighlightPaint.setColor(Color.rgb(0, 0, 0)); // set alpha after color mHighlightPaint.setAlpha(120); - + mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mShadowPaint.setStyle(Paint.Style.FILL); } @@ -79,7 +79,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); calcXBounds(trans); - + mShadowPaint.setColor(dataSet.getBarShadowColor()); float phaseX = mAnimator.getPhaseX(); @@ -97,26 +97,51 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - for (int j = 0; j < buffer.size(); j += 4) { + // if multiple colors + if (dataSet.getColors().size() > 1) { - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) - continue; + for (int j = 0; j < buffer.size(); j += 4) { + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + continue; + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + break; - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) - break; - - if (mChart.isDrawBarShadowEnabled()) { - c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), - buffer.buffer[j+2], - mViewPortHandler.contentBottom(), mShadowPaint); + if (mChart.isDrawBarShadowEnabled()) { + c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), + buffer.buffer[j + 2], + mViewPortHandler.contentBottom(), mShadowPaint); + } + + // Set the color for the currently drawn value. If the index + // is + // out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j / 4)); + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } + } else { + + mRenderPaint.setColor(dataSet.getColor()); - // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j / 4)); - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); + for (int j = 0; j < buffer.size(); j += 4) { + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + continue; + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + break; + + if (mChart.isDrawBarShadowEnabled()) { + c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), + buffer.buffer[j + 2], + mViewPortHandler.contentBottom(), mShadowPaint); + } + + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); + } } } @@ -159,7 +184,7 @@ public void drawValues(Canvas c) { // calculate the correct offset depending on the draw position of // the value float plus = Utils.convertDpToPixel(6f); - + posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( mValuePaint, "8") + plus); @@ -172,7 +197,7 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; - + // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index d2a775bdea..492eaf5784 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -37,7 +37,7 @@ public class LineChartRenderer extends DataRenderer { * on this canvas, the paths are rendered, it is initialized with the * pathBitmap */ - protected Canvas mPathCanvas; + protected Canvas mBitmapCanvas; protected Path cubicPath = new Path(); protected Path cubicFillPath = new Path(); @@ -106,7 +106,7 @@ public void drawData(Canvas c) { if (mPathBitmap == null) { mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); - mPathCanvas = new Canvas(mPathBitmap); + mBitmapCanvas = new Canvas(mPathBitmap); } mPathBitmap.eraseColor(Color.TRANSPARENT); @@ -236,7 +236,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mPathCanvas, dataSet, cubicFillPath, trans, minx, maxx); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, minx, maxx); } Log.i("", "perpare: " + (System.currentTimeMillis() - start)); @@ -251,7 +251,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries Log.i("", "transform: " + (System.currentTimeMillis() - start)); start = System.currentTimeMillis(); - mPathCanvas.drawPath(cubicPath, mRenderPaint); + mBitmapCanvas.drawPath(cubicPath, mRenderPaint); Log.i("", "draw: " + (System.currentTimeMillis() - start)); c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); @@ -266,7 +266,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo mChart.getYChartMin()); Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX+1); spline.lineTo(entryTo.getXIndex(), fillMin); spline.lineTo(entryFrom.getXIndex(), fillMin); @@ -279,7 +279,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo mRenderPaint.setAlpha(dataSet.getFillAlpha()); trans.pathValueToPixel(spline); - mPathCanvas.drawPath(spline, mRenderPaint); + mBitmapCanvas.drawPath(spline, mRenderPaint); mRenderPaint.setAlpha(255); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 696d0cd7db..afa5bed93a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.renderer; +import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; @@ -33,6 +34,11 @@ public class PieChartRenderer extends DataRenderer { * chart */ private Paint mCenterTextPaint; + + /** Bitmap for drawing the center hole */ + protected Bitmap mDrawBitmap; + + protected Canvas mBitmapCanvas; public PieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -68,6 +74,14 @@ public void initBuffers() { @Override public void drawData(Canvas c) { + + if (mDrawBitmap == null) { + mDrawBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), + (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); + mBitmapCanvas = new Canvas(mDrawBitmap); + } + + mDrawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -76,6 +90,8 @@ public void drawData(Canvas c) { if (set.isVisible()) drawDataSet(c, set); } + + c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, PieDataSet dataSet) { @@ -101,7 +117,7 @@ protected void drawDataSet(Canvas c, PieDataSet dataSet) { mChart.getData().getIndexOfDataSet(dataSet))) { mRenderPaint.setColor(dataSet.getColor(j)); - c.drawArc(mChart.getCircleBox(), angle + sliceSpace / 2f, + mBitmapCanvas.drawArc(mChart.getCircleBox(), angle + sliceSpace / 2f, newangle * mAnimator.getPhaseY() - sliceSpace / 2f, true, mRenderPaint); } @@ -130,7 +146,7 @@ public void drawValues(Canvas c) { float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); - float off = r / 2f; + float off = r / 3f; if (mChart.isDrawHoleEnabled()) { off = (r - (r / 100f * mChart.getHoleRadius())) / 2f; @@ -226,7 +242,7 @@ protected void drawHole(Canvas c) { int color = mHolePaint.getColor(); // draw the hole-circle - c.drawCircle(center.x, center.y, + mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * holeRadius, mHolePaint); if (transparentCircleRadius > holeRadius) { @@ -235,7 +251,7 @@ protected void drawHole(Canvas c) { mHolePaint.setColor(color & 0x60FFFFFF); // draw the transparent-circle - c.drawCircle(center.x, center.y, + mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * transparentCircleRadius, mHolePaint); mHolePaint.setColor(color); @@ -331,7 +347,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // redefine the rect that contains the arc so that the // highlighted pie is not cut off - c.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceDegrees + mBitmapCanvas.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceDegrees - set.getSliceSpace() / 2f, true, mRenderPaint); } } From 191ec27d2c4de969810cd5fb662b8764b33df37c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 11:35:00 +0100 Subject: [PATCH 0200/1390] Bugfixes in LineChart. --- .../mpchartexample/LineChartActivity1.java | 23 ++++++------ .../mpchartexample/PerformanceLineChart.java | 2 +- .../charting/charts/BarLineChartBase.java | 33 +++++++++++------- .../mikephil/charting/charts/Chart.java | 15 +++++--- .../mikephil/charting/data/LineDataSet.java | 2 +- .../charting/data/LineRadarDataSet.java | 26 +++++--------- .../listener/BarLineChartTouchListener.java | 30 ++++++++-------- .../charting/renderer/LineChartRenderer.java | 27 ++++++++++---- screenshots/combined_chart.png | Bin 0 -> 97128 bytes 9 files changed, 91 insertions(+), 67 deletions(-) create mode 100644 screenshots/combined_chart.png diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 4f084c4b98..b045e11eac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -77,6 +77,8 @@ protected void onCreate(Bundle savedInstanceState) { // enable scaling and dragging mChart.setDragEnabled(true); mChart.setScaleEnabled(true); + // mChart.setScaleXEnabled(true); + // mChart.setScaleYEnabled(true); // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); @@ -94,17 +96,17 @@ protected void onCreate(Bundle savedInstanceState) { // enable/disable highlight indicators (the lines that indicate the // highlighted Entry) mChart.setHighlightIndicatorEnabled(false); - + // add data setData(45, 100); mChart.animateX(2500); -// mChart.setVisibleYRange(30, AxisDependency.LEFT); + // mChart.setVisibleYRange(30, AxisDependency.LEFT); -// // restrain the maximum scale-out factor -// mChart.setScaleMinima(3f, 3f); -// -// // center the view to a specific position inside the chart -// mChart.centerViewPort(10, 50, AxisDependency.LEFT); + // // restrain the maximum scale-out factor + // mChart.setScaleMinima(3f, 3f); + // + // // center the view to a specific position inside the chart + // mChart.centerViewPort(10, 50, AxisDependency.LEFT); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); @@ -268,7 +270,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - + // redraw mChart.invalidate(); } @@ -294,7 +296,8 @@ private void setData(int count, float range) { ArrayList yVals = new ArrayList(); - for (int i = 10; i < count-10; i++) { + for (int i = 0; i < count; i++) { + float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * @@ -337,7 +340,7 @@ private void setData(int count, float range) { ll2.enableDashedLine(10f, 10f, 0f); ll2.setLabelPosition(LimitLabelPosition.POS_RIGHT); ll2.setTextSize(10f); - + YAxis leftAxis = mChart.getAxisLeft(); leftAxis.addLimitLine(ll1); leftAxis.addLimitLine(ll2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index fd0ab2d354..fc1bce3567 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -122,7 +122,7 @@ private void setData(int count, float range) { set1.setDrawValues(false); set1.setDrawCircles(false); set1.setDrawCubic(false); - set1.setDrawFilled(false); + set1.setDrawFilled(true); // create a data object with the datasets LineData data = new LineData(xVals, set1); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 26c6698596..d73faf2525 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -64,8 +64,8 @@ public abstract class BarLineChartBase= 11) { + + if (enabled) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } else { + Log.e(LOG_TAG, + "Cannot enable/disable hardware acceleration for devices below API level 11."); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index b52a08a4ec..2cd8d2efc4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -170,7 +170,7 @@ public boolean isDrawCirclesEnabled() { /** * If set to true, the linechart lines are drawn in cubic-style instead of - * linear. Default: false + * linear. This affects performance! Default: false * * @param enabled */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 048b481828..8dd3ef3bac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -19,15 +19,15 @@ public abstract class LineRadarDataSet extends BarLineScatterCa /** transparency used for filling line surface */ private int mFillAlpha = 85; - + /** the width of the drawn data lines */ private float mLineWidth = 2.5f; - + /** if true, the data will also be drawn filled */ private boolean mDrawFilled = false; - -// private Shader mShader; - + + // private Shader mShader; + public LineRadarDataSet(ArrayList yVals, String label) { super(yVals, label); } @@ -69,7 +69,7 @@ public int getFillAlpha() { public void setFillAlpha(int alpha) { mFillAlpha = alpha; } - + /** * set the line width of the chart (min = 0.2f, max = 10f); default 1f NOTE: * thinner line == better performance, thicker line == worse performance @@ -93,11 +93,11 @@ public void setLineWidth(float width) { public float getLineWidth() { return mLineWidth; } - + /** * Set to true if the DataSet should be drawn filled (surface), and not just - * as a line, disabling this will give up to 20% performance boost on large - * datasets, default: false + * as a line, disabling this will give great performance boost! default: + * false * * @param filled */ @@ -113,12 +113,4 @@ public void setDrawFilled(boolean filled) { public boolean isDrawFilledEnabled() { return mDrawFilled; } - -// public void setShader(Shader s) { -// mShader = s; -// } -// -// public Shader getShader() { -// return mShader; -// } } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index a96cc7f826..64b93f1226 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -28,7 +28,7 @@ public class BarLineChartTouchListener>>> extends SimpleOnGestureListener implements OnTouchListener { - // private static final long REFRESH_MILLIS = 20; + // private static final long REFRESH_MILLIS = 20; /** the original touch-matrix from the chart */ private Matrix mMatrix = new Matrix(); @@ -84,7 +84,7 @@ public boolean onTouch(View v, MotionEvent event) { mGestureDetector.onTouchEvent(event); } - if (!mChart.isDragEnabled() && !mChart.isScaleEnabled()) + if (!mChart.isDragEnabled() && (!mChart.isScaleXEnabled() && !mChart.isScaleYEnabled())) return true; // Handle touch events here... @@ -140,7 +140,7 @@ public boolean onTouch(View v, MotionEvent event) { mChart.disableScroll(); - if (mChart.isScaleEnabled()) + if (mChart.isScaleXEnabled() || mChart.isScaleYEnabled()) performZoom(event); } else if (mTouchMode == NONE @@ -168,18 +168,19 @@ public boolean onTouch(View v, MotionEvent event) { } // Perform the transformation, update the chart -// if (needsRefresh()) - mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); + // if (needsRefresh()) + mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); return true; // indicate event was handled } -// private boolean needsRefresh() { -// if (System.currentTimeMillis() - mChart.getLastDrawMillis() > REFRESH_MILLIS) { -// return true; -// } else -// return false; -// } + // private boolean needsRefresh() { + // if (System.currentTimeMillis() - mChart.getLastDrawMillis() > + // REFRESH_MILLIS) { + // return true; + // } else + // return false; + // } /** * ################ ################ ################ ################ @@ -248,9 +249,10 @@ private void performZoom(MotionEvent event) { // scale mMatrix.set(mSavedMatrix); - mMatrix.postScale(scale, scale, t.x, t.y); + mMatrix.postScale((mChart.isScaleXEnabled()) ? scale : 1f, + (mChart.isScaleYEnabled()) ? scale : 1f, t.x, t.y); - } else if (mTouchMode == X_ZOOM) { + } else if (mTouchMode == X_ZOOM && mChart.isScaleXEnabled()) { float xDist = getXDist(event); float scaleX = xDist / mSavedXDist; // x-axis @@ -259,7 +261,7 @@ private void performZoom(MotionEvent event) { mMatrix.set(mSavedMatrix); mMatrix.postScale(scaleX, 1f, t.x, t.y); - } else if (mTouchMode == Y_ZOOM) { + } else if (mTouchMode == Y_ZOOM && mChart.isScaleYEnabled()) { float yDist = getYDist(event); float scaleY = yDist / mSavedYDist; // y-axis diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 492eaf5784..fac704c222 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -304,7 +304,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie // more than 1 color if (dataSet.getColors().size() > 1) { - for (int j = 0; j < buffer.size() - 3; j += 2) { + for (int j = 0; j < buffer.size(); j += 4) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; @@ -319,20 +319,27 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie continue; // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 2)); + mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawLine(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); } } else { // only one color per dataset - - int from = mMinX * 4; - int range = (mMaxX * 4 - mMinX) + 4; + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + + int minx = dataSet.getEntryPosition(entryFrom); + int maxx = dataSet.getEntryPosition(entryTo); + + int from = minx * 4; + int range = (maxx * 4 - from) + 4; int to = range + from; mRenderPaint.setColor(dataSet.getColor()); - + +// c.drawLines(buffer.buffer, mRenderPaint); c.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, mRenderPaint); } @@ -347,6 +354,12 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList entries, Transformer trans) { + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX-2); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX+2); + + int minx = dataSet.getEntryPosition(entryFrom); + int maxx = dataSet.getEntryPosition(entryTo); mRenderPaint.setStyle(Paint.Style.FILL); @@ -357,7 +370,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en Path filled = generateFilledPath( entries, mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getLineData(), - mChart.getYChartMax(), mChart.getYChartMin()), mMinX, mMaxX + 1); + mChart.getYChartMax(), mChart.getYChartMin()), minx, maxx); trans.pathValueToPixel(filled); diff --git a/screenshots/combined_chart.png b/screenshots/combined_chart.png new file mode 100644 index 0000000000000000000000000000000000000000..0e251c11bbfb204539ff0984977b79d64b897ec1 GIT binary patch literal 97128 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 R`2_wup>*=da|ILs{{cvHZqNV# literal 0 HcmV?d00001 From 4484809ff778063e638aa446a3e950f5d3ea4c3c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 11:50:17 +0100 Subject: [PATCH 0201/1390] More bugfixes. --- .../mpchartexample/LineChartActivity1.java | 1 + .../mikephil/charting/charts/BarLineChartBase.java | 2 +- .../github/mikephil/charting/components/YAxis.java | 14 +++++++++++++- .../mikephil/charting/renderer/YAxisRenderer.java | 13 ++++++++++--- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index b045e11eac..cea967a3a7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -342,6 +342,7 @@ private void setData(int count, float range) { ll2.setTextSize(10f); YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines leftAxis.addLimitLine(ll1); leftAxis.addLimitLine(ll2); leftAxis.setAxisMaxValue(220f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d73faf2525..a3f0295471 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -223,7 +223,7 @@ protected void onDraw(Canvas canvas) { // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (true) { + if (mLogEnabled) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; drawCycles += 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 9d821f1e38..4b42765cc0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.components; import android.graphics.Paint; +import android.util.Log; import com.github.mikephil.charting.utils.DefaultValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -95,6 +96,12 @@ public enum AxisDependency { LEFT, RIGHT } + public YAxis() { + super(); + this.mAxisDependency = AxisDependency.LEFT; + this.mLimitLines = new ArrayList(); + } + public YAxis(AxisDependency position) { super(); this.mAxisDependency = position; @@ -230,6 +237,11 @@ public boolean isStartAtZeroEnabled() { */ public void addLimitLine(LimitLine l) { mLimitLines.add(l); + + if (mLimitLines.size() > 6) { + Log.e("MPAndroiChart", + "Warning! You have more than 6 LimitLines on your axis, do you really want that?"); + } } /** @@ -245,7 +257,7 @@ public void removeLimitLine(LimitLine l) { * Removes all LimitLines from the axis. */ public void removeAllLimitLines() { - mLimitLines = new ArrayList(); + mLimitLines.clear(); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index a0038787f1..a9e89e6243 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; @@ -272,11 +273,12 @@ public void renderLimitLines(Canvas c) { return; float[] pts = new float[4]; - + Path limitLinePath = new Path(); + for (int i = 0; i < limitLines.size(); i++) { LimitLine l = limitLines.get(i); - + pts[1] = l.getLimit(); pts[3] = l.getLimit(); @@ -284,12 +286,17 @@ public void renderLimitLines(Canvas c) { pts[0] = mViewPortHandler.contentLeft(); pts[2] = mViewPortHandler.contentRight(); + + limitLinePath.moveTo(pts[0], pts[1]); + limitLinePath.lineTo(pts[2], pts[3]); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setPathEffect(l.getDashPathEffect()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - c.drawLines(pts, mLimitLinePaint); + c.drawPath(limitLinePath, mLimitLinePaint); + limitLinePath.reset(); +// c.drawLines(pts, mLimitLinePaint); String label = l.getLabel(); From 26f8f655fba964e4e2acf4485cfe8800a3ce078f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 12:25:46 +0100 Subject: [PATCH 0202/1390] Introducing the clearValues() method that only removes entries but not x-values. --- MPChartExample/res/menu/realtime.xml | 4 +++ .../RealtimeLineChartActivity.java | 32 ++++++++++++------- .../mikephil/charting/charts/Chart.java | 13 ++++++-- .../mikephil/charting/data/ChartData.java | 8 +++++ 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/res/menu/realtime.xml index 03f4e7c8a9..a90337fd3c 100644 --- a/MPChartExample/res/menu/realtime.xml +++ b/MPChartExample/res/menu/realtime.xml @@ -5,4 +5,8 @@ android:id="@+id/actionAdd" android:title="Feed new Entry"> + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 6ae19d6f92..3c0bf9cf6c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -8,6 +8,7 @@ import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; +import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -61,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { LineData data = new LineData(); data.setValueTextColor(Color.WHITE); - + // add empty data mChart.setData(data); @@ -87,7 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setTextColor(Color.WHITE); leftAxis.setAxisMaxValue(120f); leftAxis.setDrawGridLines(true); - + YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); } @@ -106,12 +107,17 @@ public boolean onOptionsItemSelected(MenuItem item) { addEntry(); break; } + case R.id.actionClear: { + mChart.clearValues(); + Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); + break; + } } return true; } private int year = 15; - + private void addEntry() { LineData data = mChart.getData(); @@ -127,24 +133,26 @@ private void addEntry() { } // add a new x-value first - data.addXValue(mMonths[data.getXValCount() % 12] + " " + (year + data.getXValCount() / 12)); + data.addXValue(mMonths[data.getXValCount() % 12] + " " + + (year + data.getXValCount() / 12)); data.addEntry(new Entry((float) (Math.random() * 40) + 40f, set.getEntryCount()), 0); // let the chart know it's data has changed mChart.notifyDataSetChanged(); // limit the number of visible entries - mChart.setVisibleXRange(6); + mChart.setVisibleXRange(6); // mChart.setVisibleYRange(30, AxisDependency.LEFT); - - // move to the latest entry - mChart.moveViewToX(data.getXValCount()-7); - - // this automatically refreshes the chart (calls invalidate()) -// mChart.moveViewTo(data.getXValCount()-7, 55f, AxisDependency.LEFT); + + // move to the latest entry + mChart.moveViewToX(data.getXValCount() - 7); + + // this automatically refreshes the chart (calls invalidate()) + // mChart.moveViewTo(data.getXValCount()-7, 55f, + // AxisDependency.LEFT); // redraw the chart -// mChart.invalidate(); + // mChart.invalidate(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 6716f6b6b1..9e43515aee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -278,8 +278,8 @@ public void setData(T data) { } /** - * Clears the chart from all data and refreshes it (by calling - * invalidate()). + * Clears the chart from all data (sets it to null) and refreshes it (by + * calling invalidate()). */ public void clear() { mData = null; @@ -287,6 +287,15 @@ public void clear() { invalidate(); } + /** + * Removes all DataSets (and thereby Entries) from the chart. Does not + * remove the x-values. + */ + public void clearValues() { + mData.clearValues(); + invalidate(); + } + /** * Returns true if the chart is empty (meaning it's data object is either * null or contains no entries). diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 06ae6e2b58..508d6fbefb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -879,4 +879,12 @@ public void setDrawValues(boolean enabled) { set.setDrawValues(enabled); } } + + /** + * Clears this data object from all DataSets and removes all Entries. + */ + public void clearValues() { + mDataSets.clear(); + notifyDataChanged(); + } } From cf10bf9c6dbaac8ac85672f50b5da66fd47194cd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 14:41:44 +0100 Subject: [PATCH 0203/1390] General bugfixes. --- .../mpchartexample/BarChartActivity.java | 3 + .../BarChartActivityMultiDataset.java | 2 + .../HorizontalBarChartActivity.java | 1 + .../mpchartexample/PerformanceLineChart.java | 4 +- .../charting/charts/BarLineChartBase.java | 95 +++++++++++++++---- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/charts/HorizontalBarChart.java | 4 +- .../mikephil/charting/components/YAxis.java | 14 +++ .../charting/renderer/XAxisRenderer.java | 6 +- .../renderer/XAxisRendererBarChart.java | 9 +- 10 files changed, 109 insertions(+), 31 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 352db3a3e7..5ff9bb6174 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -89,6 +90,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); + xAxis.setSpaceBetweenLabels(2); ValueFormatter custom = new MyValueFormatter(); @@ -96,6 +98,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setTypeface(mTf); leftAxis.setLabelCount(8); leftAxis.setValueFormatter(custom); + leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 3a72219d2e..f56978a7e8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -59,6 +59,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setDescription(""); +// mChart.setDrawBorders(true); + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index db15dfc0db..de5df39654 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index fc1bce3567..ed91daf4f4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -64,7 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisLeft().setDrawGridLines(false); mChart.getAxisRight().setEnabled(false); - mChart.getXAxis().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(true); mChart.getXAxis().setDrawAxisLine(false); // dont forget to refresh the drawing @@ -122,7 +122,7 @@ private void setData(int count, float range) { set1.setDrawValues(false); set1.setDrawCircles(false); set1.setDrawCubic(false); - set1.setDrawFilled(true); + set1.setDrawFilled(false); // create a data object with the datasets LineData data = new LineData(xVals, set1); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a3f0295471..adea3ce6bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; @@ -73,6 +74,8 @@ public abstract class BarLineChartBase mXAxis.getValues().size()) maxx = mXAxis.getValues().size(); @@ -127,7 +127,7 @@ protected void drawLabels(Canvas c, float pos) { if (minx < 0) minx = 0; - for (int i = minx; i < maxx; i += mXAxis.mAxisLabelModulus) { + for (int i = minx; i <= maxx; i += mXAxis.mAxisLabelModulus) { position[0] = i; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index e1c5cc460b..02b39fdf0a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -99,10 +99,15 @@ public void renderGridLines(Canvas c) { mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); BarData bd = mChart.getData(); - // take into consideration that multiple DataSets increase mDeltaX int step = bd.getDataSetCount(); + float div = (float) step + (step > 1 ? bd.getGroupSpace() : 0f); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + float min = (float) mMinX + / div; + float max = (float) mMaxX + / div; + + for (int i = (int) min; i <= max; i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() - 0.5f; From 173c7e10de01934075f73184501b16dd2e94339a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 22:12:00 +0100 Subject: [PATCH 0204/1390] Bugfixes. --- .../CubicLineChartActivity.java | 4 +- .../mpchartexample/LineChartActivity2.java | 12 +- .../mikephil/charting/buffer/LineBuffer.java | 2 +- .../mikephil/charting/charts/Chart.java | 11 ++ .../mikephil/charting/data/LineDataSet.java | 21 ++++ .../charting/renderer/LineChartRenderer.java | 103 ++++++++---------- .../charting/renderer/XAxisRenderer.java | 4 +- 7 files changed, 89 insertions(+), 68 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index a59000d393..2572150690 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -262,7 +262,7 @@ private void setData(int count, float range) { ArrayList vals1 = new ArrayList(); - for (int i = 5; i < count-5; i++) { + for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * @@ -281,7 +281,7 @@ private void setData(int count, float range) { set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setColor(Color.rgb(104, 241, 175)); set1.setFillColor(ColorTemplate.getHoloBlue()); - + // create a data object with the datasets LineData data = new LineData(xVals, set1); data.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 881b4a0636..c9ce0d89a6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -20,7 +20,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -288,12 +287,14 @@ private void setData(int count, float range) { LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); set1.setAxisDependency(AxisDependency.LEFT); set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(Color.WHITE); set1.setLineWidth(2f); - set1.setCircleSize(4f); + set1.setCircleSize(3f); set1.setFillAlpha(65); set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); +// set1.setCircleHoleColor(Color.WHITE); ArrayList yVals2 = new ArrayList(); @@ -309,11 +310,12 @@ private void setData(int count, float range) { LineDataSet set2 = new LineDataSet(yVals2, "DataSet 2"); set2.setAxisDependency(AxisDependency.RIGHT); set2.setColor(Color.RED); - set2.setCircleColor(Color.RED); + set2.setCircleColor(Color.WHITE); set2.setLineWidth(2f); - set2.setCircleSize(4f); + set2.setCircleSize(3f); set2.setFillAlpha(65); set2.setFillColor(Color.RED); + set2.setDrawCircleHole(false); set2.setHighLightColor(Color.rgb(244, 117, 117)); ArrayList dataSets = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java index 7c0ab6731c..62805dc916 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -8,7 +8,7 @@ public class LineBuffer extends AbstractBuffer { public LineBuffer(int size) { - super(size); + super((size < 4) ? 4 : size); } public void moveTo(float x, float y) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 438d96b2c8..e77cba9714 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1208,6 +1208,17 @@ public DataRenderer getRenderer() { return mRenderer; } + /** + * Sets a new DataRenderer object for the chart. + * + * @param renderer + */ + public void setRenderer(DataRenderer renderer) { + + if (renderer != null) + mRenderer = renderer; + } + /** * Returns the bitmap that represents the chart. * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 2cd8d2efc4..e94f8c495a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -15,6 +15,9 @@ public class LineDataSet extends LineRadarDataSet { /** arraylist representing all colors that are used for the circles */ private ArrayList mCircleColors = null; + /** the color of the inner circles */ + private int mCircleColorHole = Color.WHITE; + /** the radius of the circle-shaped value indicators */ private float mCircleSize = 8f; @@ -274,6 +277,24 @@ public void resetCircleColors() { mCircleColors = new ArrayList(); } + /** + * Sets the color of the inner circle of the line-circles. + * + * @param color + */ + public void setCircleColorHole(int color) { + mCircleColorHole = color; + } + + /** + * Returns the color of the inner circle. + * + * @return + */ + public int getCircleHoleColor() { + return mCircleColorHole; + } + /** * Set this to true to allow drawing a hole in each data circle. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index fac704c222..5024b5c47b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -6,7 +6,6 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; -import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.CircleBuffer; @@ -38,7 +37,7 @@ public class LineChartRenderer extends DataRenderer { * pathBitmap */ protected Canvas mBitmapCanvas; - + protected Path cubicPath = new Path(); protected Path cubicFillPath = new Path(); @@ -61,45 +60,15 @@ public void initBuffers() { LineData lineData = mChart.getLineData(); mLineBuffers = new LineBuffer[lineData.getDataSetCount()]; - - for (int i = 0; i < mLineBuffers.length; i++) { - LineDataSet set = lineData.getDataSetByIndex(i); - int size = lineData.getXValCount() * 4 - 4; - if (size < 4) - size = 4; - mLineBuffers[i] = new LineBuffer(size); - } - mCircleBuffers = new CircleBuffer[lineData.getDataSetCount()]; - for (int i = 0; i < mCircleBuffers.length; i++) { + for (int i = 0; i < mLineBuffers.length; i++) { LineDataSet set = lineData.getDataSetByIndex(i); + mLineBuffers[i] = new LineBuffer(set.getEntryCount() * 4 - 4); mCircleBuffers[i] = new CircleBuffer(set.getEntryCount() * 2); } } - /** - * Returns the correct buffer size depending on the DataSet setup. - * - * @param set - * @return - */ - private int getBufferSize(LineDataSet set, int xValCount) { - if (set.isDrawFilledEnabled()) { - if (set.isDrawCubicEnabled()) { - return 0; - } else { - return xValCount * 4 - 4; - } - } else { - if (set.isDrawCubicEnabled()) { - return 0; - } else { - return xValCount * 4 - 4; - } - } - } - @Override public void drawData(Canvas c) { @@ -118,6 +87,8 @@ public void drawData(Canvas c) { if (set.isVisible()) drawDataSet(c, set); } + + c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, LineDataSet dataSet) { @@ -145,6 +116,13 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { mRenderPaint.setPathEffect(null); } + /** + * Draws a cubic line. + * + * @param c + * @param dataSet + * @param entries + */ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -160,8 +138,6 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries float intensity = dataSet.getCubicIntensity(); - long start = System.currentTimeMillis(); - cubicPath.reset(); float size = entries.size() * phaseX; @@ -239,21 +215,13 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, minx, maxx); } - Log.i("", "perpare: " + (System.currentTimeMillis() - start)); - mRenderPaint.setColor(dataSet.getColor()); mRenderPaint.setStyle(Paint.Style.STROKE); - start = System.currentTimeMillis(); trans.pathValueToPixel(cubicPath); - Log.i("", "transform: " + (System.currentTimeMillis() - start)); - start = System.currentTimeMillis(); - mBitmapCanvas.drawPath(cubicPath, mRenderPaint); - Log.i("", "draw: " + (System.currentTimeMillis() - start)); - c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); mRenderPaint.setPathEffect(null); } @@ -266,7 +234,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo mChart.getYChartMin()); Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX+1); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX + 1); spline.lineTo(entryTo.getXIndex(), fillMin); spline.lineTo(entryFrom.getXIndex(), fillMin); @@ -284,6 +252,13 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo mRenderPaint.setAlpha(255); } + /** + * Draws a normal line. + * + * @param c + * @param dataSet + * @param entries + */ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entries) { int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); @@ -294,6 +269,15 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie float phaseY = mAnimator.getPhaseY(); mRenderPaint.setStyle(Paint.Style.STROKE); + + Canvas canvas = null; + + // if the data-set is dashed, draw on bitmap-canvas + if(dataSet.isDashedLineEnabled()) { + canvas = mBitmapCanvas; + } else { + canvas = c; + } LineBuffer buffer = mLineBuffers[dataSetIndex]; buffer.setPhases(phaseX, phaseY); @@ -321,15 +305,15 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie // get the color that is set for this line-segment mRenderPaint.setColor(dataSet.getColor(j / 4)); - c.drawLine(buffer.buffer[j], buffer.buffer[j + 1], + canvas.drawLine(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); } } else { // only one color per dataset - + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - + int minx = dataSet.getEntryPosition(entryFrom); int maxx = dataSet.getEntryPosition(entryTo); @@ -338,9 +322,9 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie int to = range + from; mRenderPaint.setColor(dataSet.getColor()); - -// c.drawLines(buffer.buffer, mRenderPaint); - c.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, + + // c.drawLines(buffer.buffer, mRenderPaint); + canvas.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, mRenderPaint); } @@ -354,10 +338,10 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList entries, Transformer trans) { - - Entry entryFrom = dataSet.getEntryForXIndex(mMinX-2); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX+2); - + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX - 2); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX + 2); + int minx = dataSet.getEntryPosition(entryFrom); int maxx = dataSet.getEntryPosition(entryTo); @@ -470,6 +454,7 @@ public void drawExtras(Canvas c) { } protected void drawCircles(Canvas c) { + mRenderPaint.setStyle(Paint.Style.FILL); float phaseX = mAnimator.getPhaseX(); @@ -483,6 +468,8 @@ protected void drawCircles(Canvas c) { if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled()) continue; + + mCirclePaintInner.setColor(dataSet.getCircleHoleColor()); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); ArrayList entries = dataSet.getYVals(); @@ -496,9 +483,7 @@ protected void drawCircles(Canvas c) { float halfsize = dataSet.getCircleSize() / 2f; for (int j = 0; j < buffer.size(); j += 2) { - - mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); - + float x = buffer.buffer[j]; float y = buffer.buffer[j + 1]; @@ -509,6 +494,8 @@ protected void drawCircles(Canvas c) { // bounds if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; + + mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); c.drawCircle(x, y, dataSet.getCircleSize(), mRenderPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 87bcae5765..c010cd30af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -121,8 +121,8 @@ protected void drawLabels(Canvas c, float pos) { int maxx = mMaxX; int minx = mMinX; - if (maxx > mXAxis.getValues().size()) - maxx = mXAxis.getValues().size(); + if (maxx >= mXAxis.getValues().size()) + maxx = mXAxis.getValues().size()-1; if (minx < 0) minx = 0; From 94ee5e8d79c1d5766d3558a026971cc405548213 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 11 Mar 2015 22:14:08 +0100 Subject: [PATCH 0205/1390] Update manifest and build.gradle. --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 8f9228ebde..959a91a438 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="37" + android:versionName="2.0.8" > Date: Wed, 11 Mar 2015 22:28:10 +0100 Subject: [PATCH 0206/1390] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d3e6d6b75d..c20d0768e2 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,9 @@ Features - **LineChart (single DataSet)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/linechart.png) + - **Combined-Chart (bar- and linechart in this case)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) + - **BarChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) From f5d6a477de531f69d4ce7630bd3cb3ab2516e277 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Mar 2015 16:37:41 +0100 Subject: [PATCH 0207/1390] Added convenience methods. Code cleanup. --- .../charting/buffer/ScatterBuffer.java | 4 +- .../charting/charts/BarLineChartBase.java | 41 +------------------ .../mikephil/charting/charts/RadarChart.java | 1 - .../mikephil/charting/data/ChartData.java | 37 ++++++++++++++++- .../mikephil/charting/data/DataSet.java | 36 ++++++++++++---- .../github/mikephil/charting/data/Entry.java | 26 ++---------- .../charting/listener/OnDrawListener.java | 2 +- .../listener/PieRadarChartTouchListener.java | 8 ++-- 8 files changed, 75 insertions(+), 80 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java index 9a2e1941f7..ff1691cc5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java @@ -11,7 +11,7 @@ public ScatterBuffer(int size) { super(size); } - protected void addTwo(float x, float y) { + protected void addForm(float x, float y) { buffer[index++] = x; buffer[index++] = y; } @@ -24,7 +24,7 @@ public void feed(ArrayList entries) { for (int i = 0; i < size; i++) { Entry e = entries.get(i); - addTwo(e.getXIndex(), e.getVal() * phaseY); + addForm(e.getXIndex(), e.getVal() * phaseY); } reset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index adea3ce6bf..400fc339ae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -18,7 +18,6 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; @@ -140,7 +139,8 @@ protected void init() { mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); - mListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); + mListener = new BarLineChartTouchListener>>>( + this, mViewPortHandler.getMatrixTouch()); mGridBackgroundPaint = new Paint(); mGridBackgroundPaint.setStyle(Style.FILL); @@ -1240,43 +1240,6 @@ public boolean isAnyAxisInverted() { return false; } - /** - * returns the filtered ChartData object depending on approximator settings, - * current scale level and x- and y-axis ratio - * - * @return - */ - private T getFilteredData() { - // - // float deltaRatio = mDeltaY / mDeltaX; - // float scaleRatio = mScaleY / mScaleX; - // - // // set the determined ratios - // mApproximator.setRatios(deltaRatio, scaleRatio); - // - // // Log.i("Approximator", "DeltaRatio: " + deltaRatio + - // ", ScaleRatio: " - // // + scaleRatio); - // - // ArrayList dataSets = new ArrayList(); - // - // for (int j = 0; j < mOriginalData.getDataSetCount(); j++) { - // - // DataSet old = mOriginalData.getDataSetByIndex(j); - // - // // do the filtering - // ArrayList approximated = mApproximator.filter(old.getYVals()); - // - // DataSet set = new DataSet(approximated, old.getLabel()); - // dataSets.add(set); - // } - // - // ChartData d = new ChartData(mOriginalData.getXVals(), dataSets); - // return d; - - return null; - } - @Override public void setPaint(Paint p, int which) { super.setPaint(p, which); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index e35ad60910..5a007b864c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -7,7 +7,6 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; -import android.util.Log; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 508d6fbefb..f5e566dc9d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -609,7 +609,7 @@ public boolean removeDataSet(int index) { * Adds an Entry to the DataSet at the specified index. Entries are added to * the end of the list. * - * @param e + * @param entry * @param dataSetIndex */ public void addEntry(Entry e, int dataSetIndex) { @@ -887,4 +887,39 @@ public void clearValues() { mDataSets.clear(); notifyDataChanged(); } + + /** + * Checks if this data object contains the specified Entry. Returns true if + * so, false if not. NOTE: Performance is pretty bad on this one, do not + * over-use in performance critical situations. + * + * @param e + * @return + */ + public boolean contains(Entry e) { + + for (T set : mDataSets) { + if (set.contains(e)) + return true; + } + + return false; + } + + /** + * Checks if this data object contains the specified DataSet. Returns true + * if so, false if not. + * + * @param dataSet + * @return + */ + public boolean contains(T dataSet) { + + for (T set : mDataSets) { + if (set.equals(dataSet)) + return true; + } + + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 69a410679b..e788fde716 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -77,16 +77,10 @@ public DataSet(ArrayList yVals, String label) { if (mYVals == null) mYVals = new ArrayList(); - - // if (yVals.size() <= 0) { - // return; - // } - + mColors = new ArrayList(); - // default colors - // mColors.add(Color.rgb(192, 255, 140)); - // mColors.add(Color.rgb(255, 247, 140)); + // default color mColors.add(Color.rgb(140, 234, 255)); calcMinMax(); @@ -401,6 +395,7 @@ public boolean isDrawValuesEnabled() { * * @param d */ + @SuppressWarnings("unchecked") public void addEntry(Entry e) { if (e == null) @@ -576,7 +571,7 @@ public void resetColors() { /** * Returns the position of the provided entry in the DataSets Entry array. - * Returns -1 if doesnt exist. + * Returns -1 if doesn't exist. * * @param e * @return @@ -669,7 +664,30 @@ public void setValueTextSize(float size) { mValueTextSize = Utils.convertDpToPixel(size); } + /** + * Returns the text-size of the labels that are displayed above the values. + * + * @return + */ public float getValueTextSize() { return mValueTextSize; } + + /** + * Checks if this DataSet contains the specified Entry. Returns true if so, + * false if not. NOTE: Performance is pretty bad on this one, do not + * over-use in performance critical situations. + * + * @param e + * @return + */ + public boolean contains(Entry e) { + + for (Entry entry : mYVals) { + if (entry.equals(e)) + return true; + } + + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/com/github/mikephil/charting/data/Entry.java index 59e6fd80e3..e57852ea33 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/Entry.java @@ -93,7 +93,7 @@ public Object getData() { } /** - * Sets additional data this Entry should represents. + * Sets additional data this Entry should represent. * * @param data */ @@ -101,27 +101,6 @@ public void setData(Object data) { this.mData = data; } - // /** - // * If this Enry represents mulitple values (e.g. Stacked BarChart), it - // will - // * return the sum of them, otherwise just the one value it represents. - // * - // * @return - // */ - // public float getSum() { - // if (mVals == null) - // return mVal; - // else { - // - // float sum = 0f; - // - // for (int i = 0; i < mVals.length; i++) - // sum += mVals[i]; - // - // return sum; - // } - // } - /** * returns an exact copy of the entry * @@ -134,7 +113,8 @@ public Entry copy() { /** * Compares value, xIndex and data of the entries. Returns true if entries - * are equal, false if not. + * are equal in those points, false if not. Does not check by hash-code like + * it's done by the "equals" method. * * @param e * @return diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java index 58ed4bc69a..940d0ed18a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java @@ -33,6 +33,6 @@ public interface OnDrawListener { * @param dataSet * the last drawn DataSet */ - public void onDrawFinished(DataSet dataSet); + public void onDrawFinished(DataSet dataSet); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 0c4fb4871c..283dc6b0e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -1,19 +1,18 @@ package com.github.mikephil.charting.listener; +import android.annotation.SuppressLint; import android.graphics.PointF; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; - import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; - import java.util.ArrayList; /** @@ -28,18 +27,19 @@ public class PieRadarChartTouchListener extends SimpleOnGestureListener implemen private PointF mTouchStartPoint = new PointF(); - private PieRadarChartBase mChart; + private PieRadarChartBase mChart; private int mTouchMode = NONE; private GestureDetector mGestureDetector; - public PieRadarChartTouchListener(PieRadarChartBase ctx) { + public PieRadarChartTouchListener(PieRadarChartBase ctx) { this.mChart = ctx; mGestureDetector = new GestureDetector(ctx.getContext(), this); } + @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent e) { From 67f08897230bdfc621902d59e047eae6a6d29018 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 12 Mar 2015 16:41:34 +0100 Subject: [PATCH 0208/1390] Example cleanup. --- .../xxmassdeveloper/mpchartexample/CombinedChartActivity.java | 4 ++-- .../com/xxmassdeveloper/mpchartexample/DrawChartActivity.java | 2 +- .../mpchartexample/HorizontalBarChartActivity.java | 1 - .../mpchartexample/InvertedLineChartActivity.java | 1 + .../mpchartexample/LineChartActivityColored.java | 2 -- 5 files changed, 4 insertions(+), 6 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 44e06e7bf8..5e50b4a57b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -111,7 +111,7 @@ private BarData generateBarData() { return d; } - private ScatterData generateScatterData() { + protected ScatterData generateScatterData() { ScatterData d = new ScatterData(); @@ -130,7 +130,7 @@ private ScatterData generateScatterData() { return d; } - private CandleData generateCandleData() { + protected CandleData generateCandleData() { CandleData d = new CandleData(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 35b8215648..93971fd7cd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -180,7 +180,7 @@ public void onEntryAdded(Entry entry) { /** callback when a DataSet has been drawn (when lifting the finger) */ @Override - public void onDrawFinished(DataSet dataSet) { + public void onDrawFinished(DataSet dataSet) { Log.i(Chart.LOG_TAG, "DataSet drawn. " + dataSet.toSimpleString()); // prepare the legend again diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index de5df39654..db15dfc0db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -20,7 +20,6 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index a2284d3e5b..3b9a98b375 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); + mChart.setDrawGridBackground(false); // no description text mChart.setDescription(""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index b21c385a07..9b12209b64 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -9,8 +9,6 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; From a543bb2b362e7222dfc48c9bea500ace45829d2b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 13 Mar 2015 11:47:04 +0100 Subject: [PATCH 0209/1390] Improved CombinedChart. --- .../mpchartexample/CombinedChartActivity.java | 65 +++++---- .../charting/charts/CombinedChart.java | 112 +++++++++++++-- .../renderer/CombinedChartRenderer.java | 130 ++++++++++-------- 3 files changed, 207 insertions(+), 100 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 5e50b4a57b..09d52fc84e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -8,6 +8,7 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.CombinedChart; +import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -43,6 +44,12 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (CombinedChart) findViewById(R.id.chart1); mChart.setDescription(""); mChart.setDrawGridBackground(false); + mChart.setDrawBarShadow(false); + + // draw bars behind lines + mChart.setDrawOrder(new DrawOrder[] { + DrawOrder.BAR, DrawOrder.LINE, DrawOrder.CANDLE + }); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); @@ -57,8 +64,8 @@ protected void onCreate(Bundle savedInstanceState) { data.setData(generateLineData()); data.setData(generateBarData()); -// data.setData(generateScatterData()); -// data.setData(generateCandleData()); +// data.setData(generateScatterData()); +// data.setData(generateCandleData()); mChart.setData(data); mChart.invalidate(); @@ -153,34 +160,34 @@ private float getRandom(float range, float startsfrom) { return (float) (Math.random() * range) + startsfrom; } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.combined, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.actionToggleLineValues: { - for (DataSet set : mChart.getData().getDataSets()) { - if(set instanceof LineDataSet) - set.setDrawValues(!set.isDrawValuesEnabled()); - } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.combined, menu); + return true; + } - mChart.invalidate(); - break; - } - case R.id.actionToggleBarValues: { - for (DataSet set : mChart.getData().getDataSets()) { - if(set instanceof BarDataSet) - set.setDrawValues(!set.isDrawValuesEnabled()); + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.actionToggleLineValues: { + for (DataSet set : mChart.getData().getDataSets()) { + if (set instanceof LineDataSet) + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleBarValues: { + for (DataSet set : mChart.getData().getDataSets()) { + if (set instanceof BarDataSet) + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } } - - mChart.invalidate(); - break; - } + return true; } - return true; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 33ff13a752..db0fbe12f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -25,7 +25,41 @@ public class CombinedChart extends BarLineChartBase implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider { - private FillFormatter mFillFormatter; + /** the fill-formatter used for determining the position of the fill-line */ + protected FillFormatter mFillFormatter; + + /** flag that enables or disables the highlighting arrow */ + private boolean mDrawHighlightArrow = false; + + /** + * if set to true, all values are drawn above their bars, instead of below + * their top + */ + private boolean mDrawValueAboveBar = true; + + /** + * if set to true, all values of a stack are drawn individually, and not + * just their sum + */ + private boolean mDrawValuesForWholeStack = true; + + /** + * if set to true, a grey area is darawn behind each bar that indicates the + * maximum value + */ + private boolean mDrawBarShadow = true; + + protected DrawOrder[] mDrawOrder = new DrawOrder[] { + DrawOrder.BAR, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER + }; + + /** + * enum that allows to specify the order in which the different data objects + * for the combined-chart are drawn + */ + public enum DrawOrder { + BAR, LINE, CANDLE, SCATTER + } public CombinedChart(Context context) { super(context); @@ -52,7 +86,7 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - if (getBarData() != null) { + if (getBarData() != null || getCandleData() != null) { mXChartMin = -0.5f; mXChartMax = mData.getXVals().size() - 0.5f; mDeltaX = Math.abs(mXChartMax - mXChartMin); @@ -109,25 +143,83 @@ public CandleData getCandleData() { @Override public boolean isDrawBarShadowEnabled() { - // TODO Auto-generated method stub - return false; + return mDrawBarShadow; } @Override public boolean isDrawValueAboveBarEnabled() { - // TODO Auto-generated method stub - return true; + return mDrawValueAboveBar; } @Override public boolean isDrawHighlightArrowEnabled() { - // TODO Auto-generated method stub - return false; + return mDrawHighlightArrow; } @Override public boolean isDrawValuesForWholeStackEnabled() { - // TODO Auto-generated method stub - return false; + return mDrawValuesForWholeStack; + } + + /** + * set this to true to draw the highlightning arrow + * + * @param enabled + */ + public void setDrawHighlightArrow(boolean enabled) { + mDrawHighlightArrow = enabled; + } + + /** + * If set to true, all values are drawn above their bars, instead of below + * their top. + * + * @param enabled + */ + public void setDrawValueAboveBar(boolean enabled) { + mDrawValueAboveBar = enabled; + } + + /** + * if set to true, all values of a stack are drawn individually, and not + * just their sum + * + * @param enabled + */ + public void setDrawValuesForWholeStack(boolean enabled) { + mDrawValuesForWholeStack = enabled; + } + + /** + * If set to true, a grey area is drawn behind each bar that indicates the + * maximum value. Enabling his will reduce performance by about 50%. + * + * @param enabled + */ + public void setDrawBarShadow(boolean enabled) { + mDrawBarShadow = enabled; + } + + /** + * Returns the currently set draw order. + * + * @return + */ + public DrawOrder[] getDrawOrder() { + return mDrawOrder; + } + + /** + * Sets the order in which the provided data objects should be drawn. The + * earlier you place them in the provided array, the further they will be in + * the background. e.g. if you provide new DrawOrer[] { DrawOrder.BAR, + * DrawOrder.LINE }, the bars will be drawn behind the lines. + * + * @param order + */ + public void setDrawOrder(DrawOrder[] order) { + if (order == null || order.length <= 0) + return; + mDrawOrder = order; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index e6b6e41387..5d736abcf2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -5,101 +5,109 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.CombinedChart; +import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; import com.github.mikephil.charting.utils.Highlight; +import java.util.ArrayList; + public class CombinedChartRenderer extends DataRenderer { - private LineChartRenderer mLineRenderer; - private BarChartRenderer mBarRenderer; - private CandleStickChartRenderer mCandleRenderer; - private ScatterChartRenderer mScatterRenderer; + /** + * all rederers for the different kinds of data this combined-renderer can + * draw + */ + protected ArrayList mRenderers; public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); - - if (chart.getLineData() != null) - mLineRenderer = new LineChartRenderer(chart, animator, viewPortHandler); - if (chart.getBarData() != null) - mBarRenderer = new BarChartRenderer(chart, animator, viewPortHandler); + createRenderers(chart, animator, viewPortHandler); + } - if (chart.getScatterData() != null) - mScatterRenderer = new ScatterChartRenderer(chart, animator, viewPortHandler); + /** + * Creates the renderers needed for this combined-renderer in the required + * order. Also takes the DrawOrder into consideration. + * + * @param chart + * @param animator + * @param viewPortHandler + */ + protected void createRenderers(CombinedChart chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { - if (chart.getCandleData() != null) - mCandleRenderer = new CandleStickChartRenderer(chart, animator, viewPortHandler); + mRenderers = new ArrayList(); + + DrawOrder[] orders = chart.getDrawOrder(); + + for (DrawOrder order : orders) { + + switch (order) { + case BAR: + if (chart.getBarData() != null) + mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); + break; + case LINE: + if (chart.getLineData() != null) + mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); + break; + case CANDLE: + if (chart.getCandleData() != null) + mRenderers.add(new CandleStickChartRenderer(chart, animator, + viewPortHandler)); + break; + case SCATTER: + if (chart.getScatterData() != null) + mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); + break; + } + } } - + @Override public void initBuffers() { - if (mBarRenderer != null) - mBarRenderer.initBuffers(); - if (mCandleRenderer != null) - mCandleRenderer.initBuffers(); - - if (mLineRenderer != null) - mLineRenderer.initBuffers(); - - if (mScatterRenderer != null) - mScatterRenderer.initBuffers(); + for (DataRenderer renderer : mRenderers) + renderer.initBuffers(); } @Override public void drawData(Canvas c) { - if (mBarRenderer != null) - mBarRenderer.drawData(c); - - if (mCandleRenderer != null) - mCandleRenderer.drawData(c); - - if (mLineRenderer != null) - mLineRenderer.drawData(c); - - if (mScatterRenderer != null) - mScatterRenderer.drawData(c); + for (DataRenderer renderer : mRenderers) + renderer.drawData(c); } @Override public void drawValues(Canvas c) { - if (mBarRenderer != null) - mBarRenderer.drawValues(c); - - if (mCandleRenderer != null) - mCandleRenderer.drawValues(c); - - if (mLineRenderer != null) - mLineRenderer.drawValues(c); - - if (mScatterRenderer != null) - mScatterRenderer.drawValues(c); + for (DataRenderer renderer : mRenderers) + renderer.drawValues(c); } @Override public void drawExtras(Canvas c) { - if (mBarRenderer != null) - mBarRenderer.drawExtras(c); - - if (mCandleRenderer != null) - mCandleRenderer.drawExtras(c); - - if (mLineRenderer != null) - mLineRenderer.drawExtras(c); - - if (mScatterRenderer != null) - mScatterRenderer.drawExtras(c); + for (DataRenderer renderer : mRenderers) + renderer.drawExtras(c); } @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - // mBarRenderer.drawHighlighted(c, indices); - // mCandleRenderer.drawHighlighted(c, indices); - // mLineRenderer.drawHighlighted(c, indices); - // mScatterRenderer.drawHighlighted(c, indices); + for (DataRenderer renderer : mRenderers) + renderer.drawHighlighted(c, indices); } + /** + * Returns the sub-renderer object at the specified index. + * + * @param index + * @return + */ + public DataRenderer getSubRenderer(int index) { + if (index >= mRenderers.size() || index < 0) + return null; + else + return mRenderers.get(index); + } } From ddf205f57b9c51a603f4f37c5549889ba8086bc8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 13 Mar 2015 20:52:36 +0100 Subject: [PATCH 0210/1390] Minor bugfix. --- .../mpchartexample/CombinedChartActivity.java | 2 +- .../charting/renderer/LineChartRenderer.java | 28 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 09d52fc84e..2ea81d1745 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -48,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { // draw bars behind lines mChart.setDrawOrder(new DrawOrder[] { - DrawOrder.BAR, DrawOrder.LINE, DrawOrder.CANDLE + DrawOrder.BAR, DrawOrder.LINE }); YAxis rightAxis = mChart.getAxisRight(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5024b5c47b..dccd7a49cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -89,6 +89,8 @@ public void drawData(Canvas c) { } c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); + + drawCircles(c); } protected void drawDataSet(Canvas c, LineDataSet dataSet) { @@ -269,11 +271,11 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie float phaseY = mAnimator.getPhaseY(); mRenderPaint.setStyle(Paint.Style.STROKE); - + Canvas canvas = null; - + // if the data-set is dashed, draw on bitmap-canvas - if(dataSet.isDashedLineEnabled()) { + if (dataSet.isDashedLineEnabled()) { canvas = mBitmapCanvas; } else { canvas = c; @@ -324,7 +326,8 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie mRenderPaint.setColor(dataSet.getColor()); // c.drawLines(buffer.buffer, mRenderPaint); - canvas.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from : range, + canvas.drawLines(buffer.buffer, from, to >= buffer.size() ? buffer.size() - from + : range, mRenderPaint); } @@ -450,11 +453,11 @@ public void drawValues(Canvas c) { @Override public void drawExtras(Canvas c) { - drawCircles(c); + } protected void drawCircles(Canvas c) { - + mRenderPaint.setStyle(Paint.Style.FILL); float phaseX = mAnimator.getPhaseX(); @@ -468,7 +471,7 @@ protected void drawCircles(Canvas c) { if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled()) continue; - + mCirclePaintInner.setColor(dataSet.getCircleHoleColor()); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -483,7 +486,7 @@ protected void drawCircles(Canvas c) { float halfsize = dataSet.getCircleSize() / 2f; for (int j = 0; j < buffer.size(); j += 2) { - + float x = buffer.buffer[j]; float y = buffer.buffer[j + 1]; @@ -494,13 +497,16 @@ protected void drawCircles(Canvas c) { // bounds if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - - mRenderPaint.setColor(dataSet.getCircleColor(j / 2)); + + int circleColor = dataSet.getCircleColor(j / 2); + + mRenderPaint.setColor(circleColor); c.drawCircle(x, y, dataSet.getCircleSize(), mRenderPaint); - if (dataSet.isDrawCircleHoleEnabled()) + if (dataSet.isDrawCircleHoleEnabled() + && circleColor != mCirclePaintInner.getColor()) c.drawCircle(x, y, halfsize, mCirclePaintInner); From 0b153157de387f26d1e49b0a167b0e565faa413e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 13 Mar 2015 22:12:51 +0100 Subject: [PATCH 0211/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c20d0768e2..e467d94737 100644 --- a/README.md +++ b/README.md @@ -131,7 +131,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.7' + compile 'com.github.PhilJay:MPAndroidChart:v2.0.8' } ``` @@ -146,7 +146,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.7 + v2.0.8 ``` From d57a86e8f286fc4c46738be0f6292185c71f9fba Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 14 Mar 2015 10:37:12 +0100 Subject: [PATCH 0212/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e467d94737..6f7e9be1b6 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Features - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) + - Dual (separate) Y-Axis - Finger drawing (draw values into the chart with touch-gesture) - Highlighting values (with customizeable popup-views) - Multiple / Separate Axes @@ -69,6 +70,7 @@ Features - Animations (build up animations, on both x- and y-axis) - Limit lines (providing additional information, maximums, ...) - Fully customizeable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) + - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart **Chart types:** From 08e5f5f3eaebbb4acf6f11d9051e07b86afff2db Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 15 Mar 2015 18:38:42 +0100 Subject: [PATCH 0213/1390] Fixed LimitLine issue in HorizontalBarChart (issue #439). --- .../YAxisRendererHorizontalBarChart.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index a960cb7553..e4886aedcd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -2,20 +2,27 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Path; import android.graphics.Paint.Align; +import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; + public class YAxisRendererHorizontalBarChart extends YAxisRenderer { public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { super(viewPortHandler, yAxis, trans); + + mLimitLinePaint.setTextAlign(Align.LEFT); } /** @@ -174,4 +181,67 @@ public void renderGridLines(Canvas c) { mGridPaint); } } + + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + @Override + public void renderLimitLines(Canvas c) { + + ArrayList limitLines = mYAxis.getLimitLines(); + + if (limitLines == null || limitLines.size() <= 0) + return; + + float[] pts = new float[4]; + Path limitLinePath = new Path(); + + for (int i = 0; i < limitLines.size(); i++) { + + LimitLine l = limitLines.get(i); + + pts[0] = l.getLimit(); + pts[2] = l.getLimit(); + + mTrans.pointValuesToPixel(pts); + + pts[1] = mViewPortHandler.contentTop(); + pts[3] = mViewPortHandler.contentBottom(); + + limitLinePath.moveTo(pts[0], pts[1]); + limitLinePath.lineTo(pts[2], pts[3]); + + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + + c.drawPath(limitLinePath, mLimitLinePaint); + limitLinePath.reset(); + + String label = l.getLabel(); + + // if drawing the limit-value label is enabled + if (label != null && !label.equals("")) { + + float xOffset = l.getLineWidth(); + float add = Utils.convertDpToPixel(4f); + + mLimitLinePaint.setPathEffect(null); + mLimitLinePaint.setColor(l.getTextColor()); + mLimitLinePaint.setStrokeWidth(0.5f); + mLimitLinePaint.setTextSize(l.getTextSize()); + + float yOffset = Utils.calcTextHeight(mLimitLinePaint, label) + add / 2f; + + if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); + + } else { + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset, mLimitLinePaint); + } + } + } + } } From 0cb2272f38c0214951892dd094b59a9506e245e5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Mar 2015 11:55:53 +0100 Subject: [PATCH 0214/1390] Fixed min-max issue (#396). --- .../fragments/BarChartFrag.java | 25 ++++++++- .../charting/charts/BarLineChartBase.java | 9 ++- .../mikephil/charting/charts/Chart.java | 9 +++ .../mikephil/charting/charts/PieChart.java | 11 +++- .../charting/charts/PieRadarChartBase.java | 8 +-- .../mikephil/charting/data/ChartData.java | 50 ++++++++++------- .../listener/BarLineChartTouchListener.java | 55 +++++++++++++------ .../charting/renderer/LineChartRenderer.java | 4 +- .../charting/renderer/XAxisRenderer.java | 4 +- 9 files changed, 120 insertions(+), 55 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 91c8316e5f..b6d8b8beb9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -2,7 +2,9 @@ import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.util.Log; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; @@ -11,11 +13,12 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.listener.OnChartGestureListener; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; -public class BarChartFrag extends SimpleFragment { +public class BarChartFrag extends SimpleFragment implements OnChartGestureListener { public static Fragment newInstance() { return new BarChartFrag(); @@ -61,4 +64,24 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa return v; } + + @Override + public void onChartLongPressed(MotionEvent me) { + Log.i("LongPress", "Chart longpressed."); + } + + @Override + public void onChartDoubleTapped(MotionEvent me) { + Log.i("DoubleTap", "Chart double-tapped."); + } + + @Override + public void onChartSingleTapped(MotionEvent me) { + Log.i("SingleTap", "Chart single-tapped."); + } + + @Override + public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { + Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 400fc339ae..9a604edaba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -189,6 +189,10 @@ protected void onDraw(Canvas canvas) { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); if (mAxisRight.isEnabled()) mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + + mXAxisRenderer.renderAxisLine(canvas); + mAxisRendererLeft.renderAxisLine(canvas); + mAxisRendererRight.renderAxisLine(canvas); // make sure the graph values and grid cannot be drawn outside the // content-rect @@ -214,13 +218,8 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(canvas); mXAxisRenderer.renderAxisLabels(canvas); - mXAxisRenderer.renderAxisLine(canvas); - mAxisRendererLeft.renderAxisLabels(canvas); - mAxisRendererLeft.renderAxisLine(canvas); - mAxisRendererRight.renderAxisLabels(canvas); - mAxisRendererRight.renderAxisLine(canvas); mRenderer.drawValues(canvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index e77cba9714..bfb2a2cf66 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -870,6 +870,15 @@ public void setLogEnabled(boolean enabled) { mLogEnabled = enabled; } + /** + * Returns true if log-output is enabled for the chart, fals if not. + * + * @return + */ + public boolean isLogEnabled() { + return mLogEnabled; + } + /** * set a description text that appears in the bottom right corner of the * chart, size = Y-legend text size diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index bcd420fcc4..c14b90cd0e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -33,7 +33,7 @@ public class PieChart extends PieRadarChartBase { private RectF mCircleBox = new RectF(); /** flag indicating if the x-labels should be drawn or not */ - protected boolean mDrawXLabels = true; + private boolean mDrawXLabels = true; /** array that holds the width of each pie-slice in degrees */ private float[] mDrawAngles; @@ -94,7 +94,7 @@ protected void onDraw(Canvas canvas) { return; mRenderer.drawData(canvas); - + if (mHighlightEnabled && valuesToHighlight()) mRenderer.drawHighlighted(canvas, mIndicesToHightlight); @@ -106,7 +106,7 @@ protected void onDraw(Canvas canvas) { drawDescription(canvas); -// canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); + // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } @Override @@ -488,6 +488,11 @@ public void setUsePercentValues(boolean enabled) { mUsePercentValues = enabled; } + /** + * Returns true if using percentage values is enabled for the chart. + * + * @return + */ public boolean isUsePercentValuesEnabled() { return mUsePercentValues; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 0cc0284810..34820538a4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -32,12 +32,15 @@ public abstract class PieRadarChartBase(); - mDataSets.add(d); + + if (d == null) + return; mYValCount += d.getEntryCount(); mYValueSum += d.getYValueSum(); - if (mYMax < d.getYMax()) + if (mDataSets.size() <= 0) { + mYMax = d.getYMax(); - if (mYMin > d.getYMin()) mYMin = d.getYMin(); - if (d.getAxisDependency() == AxisDependency.LEFT) { + if (d.getAxisDependency() == AxisDependency.LEFT) { - if (mLeftAxisMax < d.getYMax()) mLeftAxisMax = d.getYMax(); - if (mLeftAxisMin > d.getYMin()) mLeftAxisMin = d.getYMin(); - } else { - if (mRightAxisMax < d.getYMax()) + } else { mRightAxisMax = d.getYMax(); - if (mRightAxisMin > d.getYMin()) mRightAxisMin = d.getYMin(); + } + } else { + + if (mYMax < d.getYMax()) + mYMax = d.getYMax(); + if (mYMin > d.getYMin()) + mYMin = d.getYMin(); + + if (d.getAxisDependency() == AxisDependency.LEFT) { + + if (mLeftAxisMax < d.getYMax()) + mLeftAxisMax = d.getYMax(); + if (mLeftAxisMin > d.getYMin()) + mLeftAxisMin = d.getYMin(); + } else { + if (mRightAxisMax < d.getYMax()) + mRightAxisMax = d.getYMax(); + if (mRightAxisMin > d.getYMin()) + mRightAxisMin = d.getYMin(); + } } + mDataSets.add(d); + handleEmptyAxis(getFirstLeft(), getFirstRight()); } @@ -572,7 +590,7 @@ private void handleEmptyAxis(T firstLeft, T firstRight) { */ public boolean removeDataSet(T d) { - if (mDataSets == null || d == null) + if (d == null) return false; boolean removed = mDataSets.remove(d); @@ -598,7 +616,7 @@ public boolean removeDataSet(T d) { */ public boolean removeDataSet(int index) { - if (mDataSets == null || index >= mDataSets.size() || index < 0) + if (index >= mDataSets.size() || index < 0) return false; T set = mDataSets.get(index); @@ -614,9 +632,6 @@ public boolean removeDataSet(int index) { */ public void addEntry(Entry e, int dataSetIndex) { - if (mDataSets == null) - mDataSets = new ArrayList(); - if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { float val = e.getVal(); @@ -629,9 +644,6 @@ public void addEntry(Entry e, int dataSetIndex) { if (mYMin > val) mYMin = val; - if (mDataSets == null) - mDataSets = new ArrayList(); - T set = mDataSets.get(dataSetIndex); if (set != null) { diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 64b93f1226..4321adbf74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -174,14 +174,6 @@ public boolean onTouch(View v, MotionEvent event) { return true; // indicate event was handled } - // private boolean needsRefresh() { - // if (System.currentTimeMillis() - mChart.getLastDrawMillis() > - // REFRESH_MILLIS) { - // return true; - // } else - // return false; - // } - /** * ################ ################ ################ ################ */ @@ -277,6 +269,39 @@ private void performZoom(MotionEvent event) { } } + /** + * Perform a highlight operation. + * + * @param e + */ + private void performHighlight(MotionEvent e) { + + Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); + + if (h == null || h.equalTo(mLastHighlighted)) { + mChart.highlightTouch(null); + mLastHighlighted = null; + } else { + mLastHighlighted = h; + mChart.highlightTouch(h); + } + } + + /** + * Highlights upon dragging. + * + * @param e + */ + private void performHighlightDrag(MotionEvent e) { + + Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); + + if (h != null && !h.equalTo(mLastHighlighted)) { + mLastHighlighted = h; + mChart.highlightTouch(h); + } + } + /** * ################ ################ ################ ################ */ @@ -410,7 +435,9 @@ public boolean onDoubleTap(MotionEvent e) { mChart.zoom(1.4f, 1.4f, trans.x, trans.y); - Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); + if (mChart.isLogEnabled()) + Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + + trans.y); } return super.onDoubleTap(e); @@ -451,15 +478,7 @@ public boolean onSingleTapUp(MotionEvent e) { l.onChartSingleTapped(e); } - Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); - - if (h == null || h.equalTo(mLastHighlighted)) { - mChart.highlightTouch(null); - mLastHighlighted = null; - } else { - mLastHighlighted = h; - mChart.highlightTouch(h); - } + performHighlight(e); return super.onSingleTapUp(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index dccd7a49cf..df52e1c95a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -89,8 +89,6 @@ public void drawData(Canvas c) { } c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); - - drawCircles(c); } protected void drawDataSet(Canvas c, LineDataSet dataSet) { @@ -453,7 +451,7 @@ public void drawValues(Canvas c) { @Override public void drawExtras(Canvas c) { - + drawCircles(c); } protected void drawCircles(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index c010cd30af..86427e62e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -82,6 +82,8 @@ public void renderAxisLabels(Canvas c) { @Override public void renderAxisLine(Canvas c) { + + calcXBounds(mTrans); if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return; @@ -165,8 +167,6 @@ protected void drawLabels(Canvas c, float pos) { @Override public void renderGridLines(Canvas c) { - calcXBounds(mTrans); - if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; From 0fb67f31ec6c06486b3dbadbaa61d7f9b39cf15f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Mar 2015 12:02:29 +0100 Subject: [PATCH 0215/1390] Fixed issue concerning gestures. --- .../mpchartexample/fragments/BarChartFrag.java | 1 + .../listener/BarLineChartTouchListener.java | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index b6d8b8beb9..ec048ae40a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -33,6 +33,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa // create a new chart object mChart = new BarChart(getActivity()); mChart.setDescription(""); + mChart.setOnChartGestureListener(this); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 4321adbf74..369693db8c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -472,12 +472,6 @@ public void onLongPress(MotionEvent e) { @Override public boolean onSingleTapUp(MotionEvent e) { - OnChartGestureListener l = mChart.getOnChartGestureListener(); - - if (l != null) { - l.onChartSingleTapped(e); - } - performHighlight(e); return super.onSingleTapUp(e); @@ -485,6 +479,13 @@ public boolean onSingleTapUp(MotionEvent e) { @Override public boolean onSingleTapConfirmed(MotionEvent e) { + + OnChartGestureListener l = mChart.getOnChartGestureListener(); + + if (l != null) { + l.onChartSingleTapped(e); + } + return super.onSingleTapConfirmed(e); } From 084b7e0f664359be5e903d43bcfd118265058a79 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Mar 2015 12:31:14 +0100 Subject: [PATCH 0216/1390] Changes to address issue #403. --- .../mpchartexample/BarChartActivity.java | 1 + .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/Chart.java | 2 +- .../listener/BarLineChartTouchListener.java | 6 +- .../charting/renderer/AxisRenderer.java | 1 + .../charting/renderer/BarChartRenderer.java | 1 + .../renderer/CandleStickChartRenderer.java | 1 + .../renderer/CombinedChartRenderer.java | 1 + .../charting/renderer/DataRenderer.java | 1 + .../renderer/HorizontalBarChartRenderer.java | 1 + .../charting/renderer/LegendRenderer.java | 1 + .../charting/renderer/LineChartRenderer.java | 1 + .../charting/renderer/PieChartRenderer.java | 1 + .../charting/renderer/RadarChartRenderer.java | 1 + .../mikephil/charting/renderer/Renderer.java | 1 + .../renderer/ScatterChartRenderer.java | 1 + .../charting/renderer/XAxisRenderer.java | 1 + .../renderer/XAxisRendererBarChart.java | 8 +- .../XAxisRendererHorizontalBarChart.java | 1 + .../renderer/XAxisRendererRadarChart.java | 1 + .../charting/renderer/YAxisRenderer.java | 1 + .../YAxisRendererHorizontalBarChart.java | 1 + .../renderer/YAxisRendererRadarChart.java | 1 + .../mikephil/charting/utils/Transformer.java | 1 - .../{renderer => utils}/ViewPortHandler.java | 146 ++++++++---------- 25 files changed, 95 insertions(+), 89 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/{renderer => utils}/ViewPortHandler.java (85%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 5ff9bb6174..b30551c1e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -9,6 +9,7 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 9a604edaba..efb7fed162 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -657,11 +657,11 @@ public void setViewPortOffsets(final float left, final float top, final float right, final float bottom) { mCustomViewPortEnabled = true; - post(new Runnable() { @Override public void run() { + mViewPortHandler.restrainViewPort(left, top, right, bottom); } }); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index bfb2a2cf66..630ae8fa92 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -37,11 +37,11 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; -import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.DefaultValueFormatter; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.io.File; import java.io.FileOutputStream; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 369693db8c..20ef3369e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -16,8 +16,8 @@ import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.renderer.ViewPortHandler; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.ViewPortHandler; /** * TouchListener for Bar-, Line-, Scatter- and CandleStickChart with handles all @@ -479,13 +479,13 @@ public boolean onSingleTapUp(MotionEvent e) { @Override public boolean onSingleTapConfirmed(MotionEvent e) { - + OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { l.onChartSingleTapped(e); } - + return super.onSingleTapConfirmed(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index cc1d7e4763..a9f6c22745 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -7,6 +7,7 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; public abstract class AxisRenderer extends Renderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 42cef0f73d..aaad419472 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index bf5d7d8f03..d45e2a0b8c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 5d736abcf2..2ad16f6f22 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index d876cee599..59f2a1a95f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; public abstract class DataRenderer extends Renderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 07c4492e3c..c8852e3004 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 2889c9b0ca..7b90e40f85 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index df52e1c95a..a77d306f97 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index afa5bed93a..24fb50814f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 9107fc5e99..953dd09052 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index 91dc6b3d3c..29aaa1b346 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; /** * Abstract baseclass of all Renderers. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index f80f55798a..5d618eb9a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 86427e62e5..2a65c5292a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 02b39fdf0a..99b2d80110 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; public class XAxisRendererBarChart extends XAxisRenderer { @@ -41,7 +42,7 @@ protected void drawLabels(Canvas c, float pos) { / div; float max = (float) mMaxX / div; - + for (int i = (int) min; i <= max; i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() @@ -54,7 +55,8 @@ protected void drawLabels(Canvas c, float pos) { mTrans.pointValuesToPixel(position); - if (mViewPortHandler.isInBoundsX(position[0])) { + if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 + && i < mXAxis.getValues().size()) { String label = mXAxis.getValues().get(i); @@ -85,7 +87,7 @@ protected void drawLabels(Canvas c, float pos) { @Override public void renderGridLines(Canvas c) { - + calcXBounds(mTrans); if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 119f2fcebc..9b162d0192 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index e3b0572f97..d3e277c7c9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; public class XAxisRendererRadarChart extends XAxisRenderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index a9e89e6243..d6249bcd87 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index e4886aedcd..5f4a350d83 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index c19653be17..e1f8dd77aa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 192f510aa6..cd2f7d7ba9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.renderer.ViewPortHandler; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java similarity index 85% rename from MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java rename to MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index f0970ec379..a3626315b3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -1,14 +1,13 @@ -package com.github.mikephil.charting.renderer; +package com.github.mikephil.charting.utils; import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import com.github.mikephil.charting.interfaces.ChartInterface; -import com.github.mikephil.charting.utils.Utils; -public class ViewPortHandler { +public class ViewPortHandler { /** matrix used for touch events */ protected final Matrix mMatrixTouch = new Matrix(); @@ -18,7 +17,7 @@ public class ViewPortHandler { protected float mChartWidth = 0f; protected float mChartHeight = 0f; - + /** minimum scale value on the y-axis */ private float mMinScaleY = 1f; @@ -36,61 +35,67 @@ public class ViewPortHandler { /** offset that allows the chart to be dragged over its bounds on the x-axis */ private float mTransOffsetY = 0f; - + public ViewPortHandler() { - - } -// public ViewPortHandler(float width, float height) { -// mChartHeight = height; -// mChartWidth = width; -// } + } + /** + * Sets the width and height of the chart. + * + * @param width + * @param height + */ public void setChartDimens(float width, float height) { mChartHeight = height; - mChartWidth = width; + mChartWidth = width; + + if (mContentRect.width() <= 0 || mContentRect.height() <= 0) + mContentRect.set(0, 0, width, height); } - - public void restrainViewPort(float offsetLeft, float offsetTop, float offsetRight, float offsetBottom) { - mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight - offsetBottom); + + public void restrainViewPort(float offsetLeft, float offsetTop, float offsetRight, + float offsetBottom) { + mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight + - offsetBottom); } - + public float offsetLeft() { return mContentRect.left; } - + public float offsetRight() { return mChartWidth - mContentRect.right; } - + public float offsetTop() { return mContentRect.top; } - + public float offsetBottom() { return mChartHeight - mContentRect.bottom; } - + public float contentTop() { return mContentRect.top; } - + public float contentLeft() { return mContentRect.left; } - + public float contentRight() { return mContentRect.right; } - + public float contentBottom() { return mContentRect.bottom; } - + public float contentWidth() { return mContentRect.width(); } - + public float contentHeight() { return mContentRect.height(); } @@ -98,19 +103,19 @@ public float contentHeight() { public RectF getContentRect() { return mContentRect; } - + public PointF getContentCenter() { return new PointF(mContentRect.centerX(), mContentRect.centerY()); } - + public float getChartHeight() { return mChartHeight; } - + public float getChartWidth() { return mChartWidth; } - + /** * ################ ################ ################ ################ */ @@ -206,31 +211,31 @@ public synchronized void centerViewPort(final float[] transformedPts, final Char Matrix save = new Matrix(); save.set(mMatrixTouch); - + final float x = transformedPts[0] - offsetLeft(); final float y = transformedPts[1] - offsetTop(); save.postTranslate(-x, -y); refresh(save, chart, false); - -// final View v = chart.getChartView(); -// -// v.post(new Runnable() { -// -// @Override -// public void run() { -// Matrix save = new Matrix(); -// save.set(mMatrixTouch); -// -// final float x = transformedPts[0] - offsetLeft(); -// final float y = transformedPts[1] - offsetTop(); -// -// save.postTranslate(-x, -y); -// -// refresh(save, chart, false); -// } -// }); + + // final View v = chart.getChartView(); + // + // v.post(new Runnable() { + // + // @Override + // public void run() { + // Matrix save = new Matrix(); + // save.set(mMatrixTouch); + // + // final float x = transformedPts[0] - offsetLeft(); + // final float y = transformedPts[1] - offsetTop(); + // + // save.postTranslate(-x, -y); + // + // refresh(save, chart, false); + // } + // }); } /** @@ -250,7 +255,7 @@ public Matrix refresh(Matrix newMatrix, ChartInterface chart, boolean invalidate newMatrix.set(mMatrixTouch); return newMatrix; - } + } /** * limits the maximum scale and X translation of the given matrix @@ -304,54 +309,36 @@ public void limitTransAndScale(Matrix matrix, RectF content) { matrix.setValues(vals); } - + public void setMinimumScaleX(float xScale) { - + if (xScale < 1f) xScale = 1f; mMinScaleX = xScale; - + limitTransAndScale(mMatrixTouch, mContentRect); } - + public void setMinimumScaleY(float yScale) { - + if (yScale < 1f) yScale = 1f; mMinScaleY = yScale; - + limitTransAndScale(mMatrixTouch, mContentRect); } -// /** -// * Sets the minimum scale values for both axes. This limits the extent to -// * which the user can zoom-out. -// * -// * @param scaleXmin -// * @param scaleYmin -// */ -// public void setScaleMinima(float scaleXmin, float scaleYmin, ChartInterface chart) { -// -// if (scaleXmin < 1f) -// scaleXmin = 1f; -// if (scaleYmin < 1f) -// scaleYmin = 1f; -// -// mMinScaleX = scaleXmin; -// mMinScaleY = scaleYmin; -//// -//// Matrix save = zoom(mMinScaleX, mMinScaleY, 0f, 0f); -//// refresh(mMatrixTouch, chart); -// -// limitTransAndScale(mMatrixTouch, mContentRect); -// } - + /** + * Returns the charts-touch matrix used for translation and scale on touch. + * + * @return + */ public Matrix getMatrixTouch() { return mMatrixTouch; } - + /** * ################ ################ ################ ################ */ @@ -393,7 +380,6 @@ public boolean isInBoundsTop(float y) { public boolean isInBoundsBottom(float y) { return mContentRect.bottom >= y ? true : false; } - /** * returns the current x-scale factor From d7455422c42b38918bec3ebf361df99ea30d0ddd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Mar 2015 16:28:17 +0100 Subject: [PATCH 0217/1390] Minor changes in line-renderer. --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index efb7fed162..a76387604e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -232,7 +232,7 @@ protected void onDraw(Canvas canvas) { // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (mLogEnabled) { + if (true) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; drawCycles += 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index a77d306f97..52a3661f14 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -360,7 +360,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en trans.pathValueToPixel(filled); - c.drawPath(filled, mRenderPaint); + mBitmapCanvas.drawPath(filled, mRenderPaint); // restore alpha mRenderPaint.setAlpha(255); From 0ee1299c4dad48f216533752c28c37d12cdedb16 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Mar 2015 16:40:43 +0100 Subject: [PATCH 0218/1390] Merged. --- .../mpchartexample/BarChartActivitySinus.java | 3 +- .../charting/buffer/AbstractBuffer.java | 4 +- .../mikephil/charting/buffer/BarBuffer.java | 3 +- .../charting/buffer/CandleBodyBuffer.java | 3 +- .../charting/buffer/CandleShadowBuffer.java | 3 +- .../charting/buffer/CircleBuffer.java | 3 +- .../charting/buffer/HorizontalBarBuffer.java | 3 +- .../mikephil/charting/buffer/LineBuffer.java | 5 +- .../charting/buffer/ScatterBuffer.java | 3 +- .../charting/charts/BarLineChartBase.java | 7 +-- .../mikephil/charting/charts/Chart.java | 5 +- .../mikephil/charting/charts/PieChart.java | 8 +-- .../charting/charts/PieRadarChartBase.java | 5 +- .../mikephil/charting/components/Legend.java | 4 +- .../mikephil/charting/components/XAxis.java | 7 +-- .../mikephil/charting/components/YAxis.java | 5 +- .../mikephil/charting/data/BarData.java | 17 +++--- .../mikephil/charting/data/BarDataSet.java | 9 ++-- .../data/BarLineScatterCandleData.java | 8 +-- .../data/BarLineScatterCandleDataSet.java | 4 +- .../mikephil/charting/data/CandleData.java | 17 +++--- .../mikephil/charting/data/CandleDataSet.java | 7 +-- .../mikephil/charting/data/ChartData.java | 53 +++++++++---------- .../mikephil/charting/data/CombinedData.java | 4 +- .../mikephil/charting/data/DataSet.java | 21 ++++---- .../mikephil/charting/data/LineData.java | 17 +++--- .../mikephil/charting/data/LineDataSet.java | 15 +++--- .../charting/data/LineRadarDataSet.java | 10 ++-- .../mikephil/charting/data/PieData.java | 13 ++--- .../mikephil/charting/data/PieDataSet.java | 5 +- .../mikephil/charting/data/RadarData.java | 17 +++--- .../mikephil/charting/data/RadarDataSet.java | 5 +- .../mikephil/charting/data/ScatterData.java | 17 +++--- .../charting/data/ScatterDataSet.java | 5 +- .../charting/data/filter/Approximator.java | 15 +++--- .../listener/PieRadarChartTouchListener.java | 5 +- .../charting/renderer/BarChartRenderer.java | 10 ++-- .../renderer/CandleStickChartRenderer.java | 8 +-- .../renderer/CombinedChartRenderer.java | 3 +- .../renderer/HorizontalBarChartRenderer.java | 10 ++-- .../charting/renderer/LegendRenderer.java | 9 ++-- .../charting/renderer/LineChartRenderer.java | 19 +++---- .../charting/renderer/PieChartRenderer.java | 8 +-- .../charting/renderer/RadarChartRenderer.java | 6 +-- .../renderer/ScatterChartRenderer.java | 8 +-- .../charting/renderer/XAxisRenderer.java | 4 +- .../XAxisRendererHorizontalBarChart.java | 4 +- .../charting/renderer/YAxisRenderer.java | 4 +- .../YAxisRendererHorizontalBarChart.java | 3 +- .../renderer/YAxisRendererRadarChart.java | 4 +- .../charting/utils/ColorTemplate.java | 9 ++-- .../mikephil/charting/utils/FileUtils.java | 19 +++---- .../mikephil/charting/utils/Transformer.java | 30 +++++------ .../github/mikephil/charting/utils/Utils.java | 15 +++--- 54 files changed, 269 insertions(+), 239 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index fee4f56de9..7e77bb94dc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -29,6 +29,7 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeListener { @@ -38,7 +39,7 @@ public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeLi private Typeface mTf; - private ArrayList mSinusData; + private List mSinusData; @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java index 192fb3ef46..68e05da79b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.buffer; -import java.util.ArrayList; +import java.util.List; /** * Buffer class to boost performance while drawing. Concept: Replace instead of @@ -67,5 +67,5 @@ public void setPhases(float phaseX, float phaseY) { * * @param entries */ - public abstract void feed(ArrayList entries); + public abstract void feed(List entries); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 49e0ef3a2c..6dd30d3d7a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.BarEntry; import java.util.ArrayList; +import java.util.List; public class BarBuffer extends AbstractBuffer { @@ -37,7 +38,7 @@ protected void addBar(float left, float top, float right, float bottom) { } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java index 58446e98a1..068225a882 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.CandleEntry; import java.util.ArrayList; +import java.util.List; public class CandleBodyBuffer extends AbstractBuffer { @@ -26,7 +27,7 @@ private void addBody(float left, float top, float right, float bottom) { } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java index d532c68757..a4e61d149a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.CandleEntry; import java.util.ArrayList; +import java.util.List; public class CandleShadowBuffer extends AbstractBuffer { @@ -20,7 +21,7 @@ private void addShadow(float x1, float y1, float x2, float y2) { } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java index 614ecf4bf9..f2cd64ccfc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.Entry; import java.util.ArrayList; +import java.util.List; public class CircleBuffer extends AbstractBuffer { @@ -17,7 +18,7 @@ protected void addCircle(float x, float y) { } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 31602be204..d19a2ac77c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.BarEntry; import java.util.ArrayList; +import java.util.List; public class HorizontalBarBuffer extends BarBuffer { @@ -12,7 +13,7 @@ public HorizontalBarBuffer(int size, float groupspace, int dataSetCount, boolean } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java index 62805dc916..60406e0215 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -3,7 +3,7 @@ import com.github.mikephil.charting.data.Entry; -import java.util.ArrayList; +import java.util.List; public class LineBuffer extends AbstractBuffer { @@ -41,8 +41,7 @@ public void lineTo(float x, float y) { } @Override - public void feed(ArrayList entries) { - + public void feed(List entries) { moveTo(entries.get(0).getXIndex(), entries.get(0).getVal()); float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java index ff1691cc5a..bd150559bc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.Entry; import java.util.ArrayList; +import java.util.List; public class ScatterBuffer extends AbstractBuffer { @@ -17,7 +18,7 @@ protected void addForm(float x, float y) { } @Override - public void feed(ArrayList entries) { + public void feed(List entries) { float size = entries.size() * phaseX; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a76387604e..a490b00b5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -38,6 +38,7 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; /** * Base-class of LineChart, BarChart, ScatterChart and CandleStickChart. @@ -925,7 +926,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { xIndex = (int) base + 1; } - ArrayList valsAtIndex = getYValsAtIndex(xIndex); + List valsAtIndex = getYValsAtIndex(xIndex); float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); @@ -953,9 +954,9 @@ public Highlight getHighlightByTouchPoint(float x, float y) { * * @return */ - public ArrayList getYValsAtIndex(int xIndex) { + public List getYValsAtIndex(int xIndex) { - ArrayList vals = new ArrayList(); + List vals = new ArrayList(); float[] pts = new float[2]; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 630ae8fa92..0dc5405b2a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -48,6 +48,7 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.List; /** * Baseclass of all Chart-Views. @@ -1152,9 +1153,9 @@ public String getXValue(int index) { * @param xIndex * @return */ - public ArrayList getEntriesAtIndex(int xIndex) { + public List getEntriesAtIndex(int xIndex) { - ArrayList vals = new ArrayList(); + List vals = new ArrayList(); for (int i = 0; i < mData.getDataSetCount(); i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index c14b90cd0e..338d295ae6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -17,7 +17,7 @@ import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; +import java.util.List; /** * View that represents a pie chart. Draws cake like slices. @@ -149,14 +149,14 @@ private void calcAngles() { mDrawAngles = new float[mData.getYValCount()]; mAbsoluteAngles = new float[mData.getYValCount()]; - ArrayList dataSets = mData.getDataSets(); + List dataSets = mData.getDataSets(); int cnt = 0; for (int i = 0; i < mData.getDataSetCount(); i++) { PieDataSet set = dataSets.get(i); - ArrayList entries = set.getYVals(); + List entries = set.getYVals(); for (int j = 0; j < entries.size(); j++) { @@ -230,7 +230,7 @@ public int getIndexForAngle(float angle) { */ public int getDataSetIndexForIndex(int xIndex) { - ArrayList> dataSets = mData.getDataSets(); + List> dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { if (dataSets.get(i).getEntryForXIndex(xIndex) != null) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 34820538a4..867a58bf59 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; /** * Baseclass of PieChart and RadarChart. @@ -393,9 +394,9 @@ public float getYChartMin() { * * @return */ - public ArrayList getYValsAtIndex(int xIndex) { + public List getYValsAtIndex(int xIndex) { - ArrayList vals = new ArrayList(); + List vals = new ArrayList(); for (int i = 0; i < mData.getDataSetCount(); i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 07d426cb47..cf0be959b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; +import java.util.List; /** * Class representing the legend of the chart. The legend will contain one entry @@ -100,7 +100,7 @@ public Legend(int[] colors, String[] labels) { * @param colors * @param labels */ - public Legend(ArrayList colors, ArrayList labels) { + public Legend(List colors, List labels) { this(); if (colors == null || labels == null) { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 55b3426d8c..0abb2df683 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.components; import java.util.ArrayList; +import java.util.List; /** * Class representing the x-axis labels settings. Only use the setter methods to @@ -13,7 +14,7 @@ public class XAxis extends AxisBase { /** the arraylist containing all the x-axis labels */ - protected ArrayList mValues = new ArrayList(); + protected List mValues = new ArrayList(); /** * width of the x-axis labels in pixels - this is calculated by the @@ -151,7 +152,7 @@ public boolean isAvoidFirstLastClippingEnabled() { * * @param values */ - public void setValues(ArrayList values) { + public void setValues(List values) { mValues = values; } @@ -160,7 +161,7 @@ public void setValues(ArrayList values) { * * @return */ - public ArrayList getValues() { + public List getValues() { return mValues; } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 61a39852fc..8cc965dee5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; +import java.util.List; /** * Class representing the y-axis labels settings and its entries. Only use the @@ -49,7 +50,7 @@ public class YAxis extends AxisBase { protected boolean mStartAtZero = true; /** array of limitlines that can be set for the axis */ - private ArrayList mLimitLines; + private List mLimitLines; /** custom minimum value this axis represents */ protected float mCustomAxisMin = Float.NaN; @@ -265,7 +266,7 @@ public void removeAllLimitLines() { * * @return */ - public ArrayList getLimitLines() { + public List getLimitLines() { return mLimitLines; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index d10d6f006d..3cbd1b1e9f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; /** * Data object that represents all data for the BarChart. @@ -22,7 +23,7 @@ public BarData() { super(); } - public BarData(ArrayList xVals) { + public BarData(List xVals) { super(xVals); } @@ -30,24 +31,24 @@ public BarData(String[] xVals) { super(xVals); } - public BarData(ArrayList xVals, ArrayList dataSets) { + public BarData(List xVals, List dataSets) { super(xVals, dataSets); } - public BarData(String[] xVals, ArrayList dataSets) { + public BarData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public BarData(ArrayList xVals, BarDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public BarData(List xVals, BarDataSet dataSet) { + super(xVals, toList(dataSet)); } public BarData(String[] xVals, BarDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(BarDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(BarDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index 899f9f0de9..e03557cef0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -4,6 +4,7 @@ import android.graphics.Color; import java.util.ArrayList; +import java.util.List; public class BarDataSet extends BarLineScatterCandleDataSet { @@ -34,7 +35,7 @@ public class BarDataSet extends BarLineScatterCandleDataSet { "Stack" }; - public BarDataSet(ArrayList yVals, String label) { + public BarDataSet(List yVals, String label) { super(yVals, label); mHighLightColor = Color.rgb(0, 0, 0); @@ -46,7 +47,7 @@ public BarDataSet(ArrayList yVals, String label) { @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(((BarEntry) mYVals.get(i)).copy()); @@ -68,7 +69,7 @@ public DataSet copy() { * Calculates the total number of entries this DataSet represents, including * stacks. All values belonging to a stack are calculated separately. */ - private void calcEntryCountIncludingStacks(ArrayList yVals) { + private void calcEntryCountIncludingStacks(List yVals) { mEntryCountStacks = 0; @@ -87,7 +88,7 @@ private void calcEntryCountIncludingStacks(ArrayList yVals) { * calculates the maximum stacksize that occurs in the Entries array of this * DataSet */ - private void calcStackSize(ArrayList yVals) { + private void calcStackSize(List yVals) { for (int i = 0; i < yVals.size(); i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java index 2b5e13bf5d..b9dbda531d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import java.util.ArrayList; +import java.util.List; /** * Baseclass for all Line, Bar and ScatterData. @@ -15,7 +15,7 @@ public BarLineScatterCandleData() { super(); } - public BarLineScatterCandleData(ArrayList xVals) { + public BarLineScatterCandleData(List xVals) { super(xVals); } @@ -23,11 +23,11 @@ public BarLineScatterCandleData(String[] xVals) { super(xVals); } - public BarLineScatterCandleData(ArrayList xVals, ArrayList sets) { + public BarLineScatterCandleData(List xVals, List sets) { super(xVals, sets); } - public BarLineScatterCandleData(String[] xVals, ArrayList sets) { + public BarLineScatterCandleData(String[] xVals, List sets) { super(xVals, sets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java index 43c6173ddd..b0578704a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java @@ -3,7 +3,7 @@ import android.graphics.Color; -import java.util.ArrayList; +import java.util.List; /** * Baseclass of all DataSets for Bar-, Line-, Scatter- and CandleStickChart. @@ -15,7 +15,7 @@ public abstract class BarLineScatterCandleDataSet extends DataS /** default highlight color */ protected int mHighLightColor = Color.rgb(255, 187, 115); - public BarLineScatterCandleDataSet(ArrayList yVals, String label) { + public BarLineScatterCandleDataSet(List yVals, String label) { super(yVals, label); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index 96d8c6cff1..1b25d5075c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; public class CandleData extends BarLineScatterCandleData { @@ -8,7 +9,7 @@ public CandleData() { super(); } - public CandleData(ArrayList xVals) { + public CandleData(List xVals) { super(xVals); } @@ -16,24 +17,24 @@ public CandleData(String[] xVals) { super(xVals); } - public CandleData(ArrayList xVals, ArrayList dataSets) { + public CandleData(List xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(String[] xVals, ArrayList dataSets) { + public CandleData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(ArrayList xVals, CandleDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public CandleData(List xVals, CandleDataSet dataSet) { + super(xVals, toList(dataSet)); } public CandleData(String[] xVals, CandleDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(CandleDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(CandleDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 9acd447cee..ea245aafc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; /** * DataSet for the CandleStickChart. @@ -18,14 +19,14 @@ public class CandleDataSet extends BarLineScatterCandleDataSet { /** the space between the candle entries, default 0.1f (10%) */ private float mBodySpace = 0.1f; - public CandleDataSet(ArrayList yVals, String label) { + public CandleDataSet(List yVals, String label) { super(yVals, label); } @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(((CandleEntry) mYVals.get(i)).copy()); @@ -48,7 +49,7 @@ protected void calcMinMax() { return; } - ArrayList entries = (ArrayList) mYVals; + List entries = mYVals; mYMin = entries.get(0).getLow(); mYMax = entries.get(0).getHigh(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 53d4e53be4..1ed57449cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -9,6 +9,9 @@ import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.List; /** * Class that holds all relevant data that represents the chart. That involves @@ -45,10 +48,10 @@ public abstract class ChartData> { private float mXValAverageLength = 0; /** holds all x-values the chart represents */ - protected ArrayList mXVals; + protected List mXVals; /** array that holds all DataSets the ChartData object represents */ - protected ArrayList mDataSets; + protected List mDataSets; public ChartData() { mXVals = new ArrayList(); @@ -61,7 +64,7 @@ public ChartData() { * * @param xVals */ - public ChartData(ArrayList xVals) { + public ChartData(List xVals) { this.mXVals = xVals; this.mDataSets = new ArrayList(); init(mDataSets); @@ -74,7 +77,7 @@ public ChartData(ArrayList xVals) { * @param xVals */ public ChartData(String[] xVals) { - this.mXVals = arrayToArrayList(xVals); + this.mXVals = arrayToList(xVals); this.mDataSets = new ArrayList(); init(mDataSets); } @@ -87,7 +90,7 @@ public ChartData(String[] xVals) { * DataSets. * @param sets the dataset array */ - public ChartData(ArrayList xVals, ArrayList sets) { + public ChartData(List xVals, List sets) { this.mXVals = xVals; this.mDataSets = sets; @@ -95,41 +98,35 @@ public ChartData(ArrayList xVals, ArrayList sets) { } /** - * constructor that takes string array instead of arraylist string + * constructor that takes string array instead of List string * * @param xVals The values describing the x-axis. Must be at least as long * as the highest xIndex in the Entry objects across all * DataSets. * @param sets the dataset array */ - public ChartData(String[] xVals, ArrayList sets) { - this.mXVals = arrayToArrayList(xVals); + public ChartData(String[] xVals, List sets) { + this.mXVals = arrayToList(xVals); this.mDataSets = sets; init(mDataSets); } /** - * Turns an array of strings into an arraylist of strings. + * Turns an array of strings into an List of strings. * * @param array * @return */ - private ArrayList arrayToArrayList(String[] array) { - - ArrayList arraylist = new ArrayList(); - for (int i = 0; i < array.length; i++) { - arraylist.add(array[i]); - } - - return arraylist; + private List arrayToList(String[] array) { + return Arrays.asList(array); } /** * performs all kinds of initialization calculations, such as min-max and * value count and sum */ - protected void init(ArrayList> dataSets) { + protected void init(List> dataSets) { isLegal(dataSets); @@ -165,7 +162,7 @@ private void calcXValAverageLength() { * * @param dataSets */ - private void isLegal(ArrayList> dataSets) { + private void isLegal(List> dataSets) { if (dataSets == null) return; @@ -191,7 +188,7 @@ public void notifyDataChanged() { /** * calc minimum and maximum y value over all datasets */ - protected void calcMinMax(ArrayList> dataSets) { + protected void calcMinMax(List> dataSets) { if (dataSets == null || dataSets.size() < 1) { @@ -257,7 +254,7 @@ protected void calcMinMax(ArrayList> dataSets) { /** * calculates the sum of all y-values in all datasets */ - protected void calcYValueSum(ArrayList> dataSets) { + protected void calcYValueSum(List> dataSets) { mYValueSum = 0; @@ -275,7 +272,7 @@ protected void calcYValueSum(ArrayList> dataSets) { * * @return */ - protected void calcYValueCount(ArrayList> dataSets) { + protected void calcYValueCount(List> dataSets) { mYValCount = 0; @@ -383,7 +380,7 @@ public int getYValCount() { * * @return */ - public ArrayList getXVals() { + public List getXVals() { return mXVals; } @@ -410,7 +407,7 @@ public void removeXValue(int index) { * * @return */ - public ArrayList getDataSets() { + public List getDataSets() { return mDataSets; } @@ -425,7 +422,7 @@ public ArrayList getDataSets() { * @param ignorecase if true, the search is not case-sensitive * @return */ - protected int getDataSetIndexByLabel(ArrayList dataSets, String label, + protected int getDataSetIndexByLabel(List dataSets, String label, boolean ignorecase) { if (ignorecase) { @@ -766,7 +763,7 @@ public int[] getColors() { for (int i = 0; i < mDataSets.size(); i++) { - ArrayList clrs = mDataSets.get(i).getColors(); + List clrs = mDataSets.get(i).getColors(); for (Integer clr : clrs) { colors[cnt] = clr; @@ -818,9 +815,9 @@ public T getFirstRight() { * * @return */ - public static ArrayList generateXVals(int from, int to) { + public static List generateXVals(int from, int to) { - ArrayList xvals = new ArrayList(); + List xvals = new ArrayList(); for (int i = from; i < to; i++) { xvals.add("" + i); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 369988d861..90fcb04a13 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import java.util.ArrayList; +import java.util.List; /** * Data object that allows the combination of Line-, Bar-, Scatter- and @@ -20,7 +20,7 @@ public CombinedData() { super(); } - public CombinedData(ArrayList xVals) { + public CombinedData(List xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e788fde716..47f304b82d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; +import java.util.List; /** * The DataSet class represents one group or type of entries (Entry) in the @@ -23,11 +24,11 @@ */ public abstract class DataSet { - /** arraylist representing all colors that are used for this DataSet */ - protected ArrayList mColors = null; + /** List representing all colors that are used for this DataSet */ + protected List mColors = null; /** the entries that this dataset represents / holds together */ - protected ArrayList mYVals = null; + protected List mYVals = null; /** maximum y-value in the y-value array */ protected float mYMax = 0.0f; @@ -70,7 +71,7 @@ public abstract class DataSet { * @param yVals * @param label */ - public DataSet(ArrayList yVals, String label) { + public DataSet(List yVals, String label) { this.mLabel = label; this.mYVals = yVals; @@ -205,9 +206,9 @@ public T getEntryForXIndex(int x) { * @param xIndex * @return */ - public ArrayList getEntriesForXIndex(int x) { + public List getEntriesForXIndex(int x) { - ArrayList entries = new ArrayList(); + List entries = new ArrayList(); int low = 0; int high = mYVals.size(); @@ -233,7 +234,7 @@ public ArrayList getEntriesForXIndex(int x) { * * @return */ - public ArrayList getYVals() { + public List getYVals() { return mYVals; } @@ -472,7 +473,7 @@ public boolean removeEntry(int xIndex) { * * @param colors */ - public void setColors(ArrayList colors) { + public void setColors(List colors) { this.mColors = colors; } @@ -501,7 +502,7 @@ public void setColors(int[] colors) { */ public void setColors(int[] colors, Context c) { - ArrayList clrs = new ArrayList(); + List clrs = new ArrayList(); for (int color : colors) { clrs.add(c.getResources().getColor(color)); @@ -537,7 +538,7 @@ public void setColor(int color) { * * @return */ - public ArrayList getColors() { + public List getColors() { return mColors; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 329b0c1cc1..c653072475 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; /** * Data object that encapsulates all data associated with a LineChart. @@ -14,7 +15,7 @@ public LineData() { super(); } - public LineData(ArrayList xVals) { + public LineData(List xVals) { super(xVals); } @@ -22,24 +23,24 @@ public LineData(String[] xVals) { super(xVals); } - public LineData(ArrayList xVals, ArrayList dataSets) { + public LineData(List xVals, List dataSets) { super(xVals, dataSets); } - public LineData(String[] xVals, ArrayList dataSets) { + public LineData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public LineData(ArrayList xVals, LineDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public LineData(List xVals, LineDataSet dataSet) { + super(xVals, toList(dataSet)); } public LineData(String[] xVals, LineDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(LineDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(LineDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index e94f8c495a..bd3abf544d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -9,11 +9,12 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; public class LineDataSet extends LineRadarDataSet { - /** arraylist representing all colors that are used for the circles */ - private ArrayList mCircleColors = null; + /** List representing all colors that are used for the circles */ + private List mCircleColors = null; /** the color of the inner circles */ private int mCircleColorHole = Color.WHITE; @@ -35,7 +36,7 @@ public class LineDataSet extends LineRadarDataSet { private boolean mDrawCircleHole = true; - public LineDataSet(ArrayList yVals, String label) { + public LineDataSet(List yVals, String label) { super(yVals, label); // mCircleSize = Utils.convertDpToPixel(4f); @@ -52,7 +53,7 @@ public LineDataSet(ArrayList yVals, String label) { @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(mYVals.get(i).copy()); @@ -197,7 +198,7 @@ public boolean isDrawCubicEnabled() { * * @return */ - public ArrayList getCircleColors() { + public List getCircleColors() { return mCircleColors; } @@ -221,7 +222,7 @@ public int getCircleColor(int index) { * * @param colors */ - public void setCircleColors(ArrayList colors) { + public void setCircleColors(List colors) { mCircleColors = colors; } @@ -250,7 +251,7 @@ public void setCircleColors(int[] colors) { */ public void setCircleColors(int[] colors, Context c) { - ArrayList clrs = new ArrayList(); + List clrs = new ArrayList(); for (int color : colors) { clrs.add(c.getResources().getColor(color)); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 8dd3ef3bac..64e0762d30 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; +import java.util.List; /** * Base dataset for line and radar DataSets. @@ -25,10 +25,10 @@ public abstract class LineRadarDataSet extends BarLineScatterCa /** if true, the data will also be drawn filled */ private boolean mDrawFilled = false; - - // private Shader mShader; - - public LineRadarDataSet(ArrayList yVals, String label) { + +// private Shader mShader; + + public LineRadarDataSet(List yVals, String label) { super(yVals, label); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index feb6348adb..cb4f886b2c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; /** * A PieData object can only represent one DataSet. Unlike all other charts, the @@ -17,7 +18,7 @@ public PieData() { super(); } - public PieData(ArrayList xVals) { + public PieData(List xVals) { super(xVals); } @@ -25,16 +26,16 @@ public PieData(String[] xVals) { super(xVals); } - public PieData(ArrayList xVals, PieDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public PieData(List xVals, PieDataSet dataSet) { + super(xVals, toList(dataSet)); } public PieData(String[] xVals, PieDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(PieDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(PieDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index cc866b2a93..eb1d979307 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; public class PieDataSet extends DataSet { @@ -13,7 +14,7 @@ public class PieDataSet extends DataSet { /** indicates the selection distance of a pie slice */ private float mShift = 18f; - public PieDataSet(ArrayList yVals, String label) { + public PieDataSet(List yVals, String label) { super(yVals, label); // mShift = Utils.convertDpToPixel(12f); } @@ -21,7 +22,7 @@ public PieDataSet(ArrayList yVals, String label) { @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(mYVals.get(i).copy()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index aca96e00a2..444c13fb05 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; /** * Data container for the RadarChart. @@ -14,7 +15,7 @@ public RadarData() { super(); } - public RadarData(ArrayList xVals) { + public RadarData(List xVals) { super(xVals); } @@ -22,24 +23,24 @@ public RadarData(String[] xVals) { super(xVals); } - public RadarData(ArrayList xVals, ArrayList dataSets) { + public RadarData(List xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(String[] xVals, ArrayList dataSets) { + public RadarData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(ArrayList xVals, RadarDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public RadarData(List xVals, RadarDataSet dataSet) { + super(xVals, toList(dataSet)); } public RadarData(String[] xVals, RadarDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(RadarDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(RadarDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java index 9015797e4d..83cf2907c9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java @@ -2,17 +2,18 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; public class RadarDataSet extends LineRadarDataSet { - public RadarDataSet(ArrayList yVals, String label) { + public RadarDataSet(List yVals, String label) { super(yVals, label); } @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(mYVals.get(i).copy()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index 815b7249a5..22adb5e55d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import java.util.ArrayList; +import java.util.List; public class ScatterData extends BarLineScatterCandleData { @@ -9,7 +10,7 @@ public ScatterData() { super(); } - public ScatterData(ArrayList xVals) { + public ScatterData(List xVals) { super(xVals); } @@ -17,24 +18,24 @@ public ScatterData(String[] xVals) { super(xVals); } - public ScatterData(ArrayList xVals, ArrayList dataSets) { + public ScatterData(List xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(String[] xVals, ArrayList dataSets) { + public ScatterData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(ArrayList xVals, ScatterDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + public ScatterData(List xVals, ScatterDataSet dataSet) { + super(xVals, toList(dataSet)); } public ScatterData(String[] xVals, ScatterDataSet dataSet) { - super(xVals, toArrayList(dataSet)); + super(xVals, toList(dataSet)); } - private static ArrayList toArrayList(ScatterDataSet dataSet) { - ArrayList sets = new ArrayList(); + private static List toList(ScatterDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 13adf227ae..9efca9b760 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; +import java.util.List; public class ScatterDataSet extends BarLineScatterCandleDataSet { @@ -25,7 +26,7 @@ public class ScatterDataSet extends BarLineScatterCandleDataSet { */ private Path mCustomScatterPath = null; - public ScatterDataSet(ArrayList yVals, String label) { + public ScatterDataSet(List yVals, String label) { super(yVals, label); // mShapeSize = Utils.convertDpToPixel(8f); @@ -34,7 +35,7 @@ public ScatterDataSet(ArrayList yVals, String label) { @Override public DataSet copy() { - ArrayList yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mYVals.size(); i++) { yVals.add(mYVals.get(i).copy()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java index a4e963e2ba..75e57edabd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.Entry; import java.util.ArrayList; +import java.util.List; /** * Implemented according to Wiki-Pseudocode {@link} @@ -97,7 +98,7 @@ public void setRatios(float deltaRatio, float scaleRatio) { * @param points the points to filter * @return */ - public ArrayList filter(ArrayList points) { + public List filter(List points) { return filter(points, mTolerance); } @@ -108,7 +109,7 @@ public ArrayList filter(ArrayList points) { * @param tolerance the angle in degrees that will trigger the filtering * @return */ - public ArrayList filter(ArrayList points, double tolerance) { + public List filter(List points, double tolerance) { if (tolerance <= 0) return points; @@ -126,14 +127,14 @@ public ArrayList filter(ArrayList points, double tolerance) { } /** - * uses the douglas peuker algorithm to reduce the given arraylist of + * uses the douglas peuker algorithm to reduce the given List of * entries * * @param entries * @param epsilon * @return */ - private ArrayList reduceWithDouglasPeuker(ArrayList entries, double epsilon) { + private List reduceWithDouglasPeuker(List entries, double epsilon) { // if a shape has 2 or less points it cannot be reduced if (epsilon <= 0 || entries.size() < 3) { return entries; @@ -147,7 +148,7 @@ private ArrayList reduceWithDouglasPeuker(ArrayList entries, doubl algorithmDouglasPeucker(entries, epsilon, 0, entries.size() - 1); // create a new array with series, only take the kept ones - ArrayList reducedEntries = new ArrayList(); + List reducedEntries = new ArrayList(); for (int i = 0; i < entries.size(); i++) { if (keep[i]) { Entry curEntry = entries.get(i); @@ -158,7 +159,7 @@ private ArrayList reduceWithDouglasPeuker(ArrayList entries, doubl } /** - * apply the Douglas-Peucker-Reduction to an ArrayList of Entry with a given + * apply the Douglas-Peucker-Reduction to an List of Entry with a given * epsilon (tolerance) * * @param entries @@ -166,7 +167,7 @@ private ArrayList reduceWithDouglasPeuker(ArrayList entries, doubl * @param start * @param end */ - private void algorithmDouglasPeucker(ArrayList entries, double epsilon, int start, + private void algorithmDouglasPeucker(List entries, double epsilon, int start, int end) { if (end <= start + 1) { // recursion finished diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 283dc6b0e7..6d7e484910 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -13,7 +13,8 @@ import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; + +import java.util.List; /** * Touchlistener for the PieChart. @@ -129,7 +130,7 @@ public boolean onSingleTapUp(MotionEvent e) { } else { - ArrayList valsAtIndex = mChart.getYValsAtIndex(index); + List valsAtIndex = mChart.getYValsAtIndex(index); int dataSetIndex = 0; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index aaad419472..afbd35520f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -19,7 +19,7 @@ import com.github.mikephil.charting.utils.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class BarChartRenderer extends DataRenderer { @@ -86,7 +86,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); // initialize the buffer BarBuffer buffer = mBarBuffers[index]; @@ -176,7 +176,7 @@ public void drawValues(Canvas c) { // if values are drawn if (passesCheck()) { - ArrayList dataSets = mChart.getBarData().getDataSets(); + List dataSets = mChart.getBarData().getDataSets(); float posOffset = 0f; float negOffset = 0f; @@ -206,7 +206,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] valuePoints = getTransformedValues(trans, entries, i); @@ -375,7 +375,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - public float[] getTransformedValues(Transformer trans, ArrayList entries, + public float[] getTransformedValues(Transformer trans, List entries, int dataSetIndex) { return trans.generateTransformedValuesBarChart(entries, dataSetIndex, mChart.getBarData(), diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index d45e2a0b8c..af1265ba41 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -16,7 +16,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class CandleStickChartRenderer extends DataRenderer { @@ -66,7 +66,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); // draw the shadow int range = (mMaxX - mMinX + 1) * 4; @@ -172,7 +172,7 @@ public void drawValues(Canvas c) { if (mChart.getCandleData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getCandleData().getDataSets(); + List dataSets = mChart.getCandleData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { @@ -186,7 +186,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] positions = trans.generateTransformedValuesCandle( entries, mAnimator.getPhaseY()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 2ad16f6f22..71a526b747 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; +import java.util.List; public class CombinedChartRenderer extends DataRenderer { @@ -17,7 +18,7 @@ public class CombinedChartRenderer extends DataRenderer { * all rederers for the different kinds of data this combined-renderer can * draw */ - protected ArrayList mRenderers; + protected List mRenderers; public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index c8852e3004..ab8a543e22 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -16,7 +16,7 @@ import com.github.mikephil.charting.utils.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; /** * Renderer for the HorizontalBarChart. @@ -58,7 +58,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); // initialize the buffer BarBuffer buffer = mBarBuffers[index]; @@ -98,7 +98,7 @@ public void drawValues(Canvas c) { // if values are drawn if (passesCheck()) { - ArrayList dataSets = mChart.getBarData().getDataSets(); + List dataSets = mChart.getBarData().getDataSets(); float posOffset = 0f; float negOffset = 0f; @@ -130,7 +130,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] valuePoints = getTransformedValues(trans, entries, i); @@ -238,7 +238,7 @@ protected void prepareBarHighlight(float x, float y, float barspace, float from, } @Override - public float[] getTransformedValues(Transformer trans, ArrayList entries, + public float[] getTransformedValues(Transformer trans, List entries, int dataSetIndex) { return trans.generateTransformedValuesHorizontalBarChart(entries, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 7b90e40f85..7bd7bb80b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; +import java.util.List; public class LegendRenderer extends Renderer { @@ -62,15 +63,15 @@ public Paint getFormPaint() { */ public Legend computeLegend(ChartData data, Legend legend) { - ArrayList labels = new ArrayList(); - ArrayList colors = new ArrayList(); + List labels = new ArrayList(); + List colors = new ArrayList(); // loop for building up the colors and labels used in the legend for (int i = 0; i < data.getDataSetCount(); i++) { DataSet dataSet = data.getDataSetByIndex(i); - ArrayList clrs = dataSet.getColors(); + List clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); // if we have a barchart with stacked bars @@ -91,7 +92,7 @@ public Legend computeLegend(ChartData data, Legend legend) { } else if (dataSet instanceof PieDataSet) { - ArrayList xVals = data.getXVals(); + List xVals = data.getXVals(); PieDataSet pds = (PieDataSet) dataSet; for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 52a3661f14..1017f78d9b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; +import java.util.List; public class LineChartRenderer extends DataRenderer { @@ -94,7 +95,7 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, LineDataSet dataSet) { - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); if (entries.size() < 1) return; @@ -124,7 +125,7 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { * @param dataSet * @param entries */ - protected void drawCubic(Canvas c, LineDataSet dataSet, ArrayList entries) { + protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -260,7 +261,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo * @param dataSet * @param entries */ - protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entries) { + protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); @@ -338,7 +339,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, ArrayList entrie } } - protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList entries, + protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries, Transformer trans) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX - 2); @@ -372,7 +373,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, ArrayList en * @param entries * @return */ - private Path generateFilledPath(ArrayList entries, float fillMin, int from, int to) { + private Path generateFilledPath(List entries, float fillMin, int from, int to) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -404,7 +405,7 @@ public void drawValues(Canvas c) { if (mChart.getLineData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getLineData().getDataSets(); + List dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { @@ -424,7 +425,7 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] positions = trans.generateTransformedValuesLine( entries, mAnimator.getPhaseY()); @@ -462,7 +463,7 @@ protected void drawCircles(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - ArrayList dataSets = mChart.getLineData().getDataSets(); + List dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { @@ -474,7 +475,7 @@ protected void drawCircles(Canvas c) { mCirclePaintInner.setColor(dataSet.getCircleHoleColor()); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); CircleBuffer buffer = mCircleBuffers[i]; buffer.setPhases(phaseX, phaseY); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 24fb50814f..1102bdbffa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -18,7 +18,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class PieChartRenderer extends DataRenderer { @@ -101,7 +101,7 @@ protected void drawDataSet(Canvas c, PieDataSet dataSet) { int cnt = 0; - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] drawAngles = mChart.getDrawAngles(); for (int j = 0; j < entries.size(); j++) { @@ -156,7 +156,7 @@ public void drawValues(Canvas c) { r -= off; // offset to keep things inside the chart PieData data = mChart.getData(); - ArrayList dataSets = data.getDataSets(); + List dataSets = data.getDataSets(); int cnt = 0; @@ -170,7 +170,7 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 953dd09052..7496c6a451 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -16,7 +16,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class RadarChartRenderer extends DataRenderer { @@ -71,7 +71,7 @@ protected void drawDataSet(Canvas c, RadarDataSet dataSet) { PointF center = mChart.getCenterOffsets(); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); Path surface = new Path(); @@ -131,7 +131,7 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); for (int j = 0; j < entries.size(); j++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 5d618eb9a7..070bb77857 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -17,7 +17,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class ScatterChartRenderer extends DataRenderer { @@ -66,7 +66,7 @@ protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float shapeHalf = dataSet.getScatterShapeSize() / 2f; @@ -204,7 +204,7 @@ public void drawValues(Canvas c) { if (mChart.getScatterData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - ArrayList dataSets = mChart.getScatterData().getDataSets(); + List dataSets = mChart.getScatterData().getDataSets(); for (int i = 0; i < mChart.getScatterData().getDataSetCount(); i++) { @@ -216,7 +216,7 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - ArrayList entries = dataSet.getYVals(); + List entries = dataSet.getYVals(); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesScatter(entries, diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 2a65c5292a..93fa06711b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class XAxisRenderer extends AxisRenderer { @@ -27,7 +27,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisPaint.setTextSize(Utils.convertDpToPixel(10f)); } - public void computeAxis(float xValAverageLength, ArrayList xValues) { + public void computeAxis(float xValAverageLength, List xValues) { mAxisPaint.setTypeface(mXAxis.getTypeface()); mAxisPaint.setTextSize(mXAxis.getTextSize()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9b162d0192..aa3495813d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class XAxisRendererHorizontalBarChart extends XAxisRendererBarChart { @@ -22,7 +22,7 @@ public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xA } @Override - public void computeAxis(float xValAverageLength, ArrayList xValues) { + public void computeAxis(float xValAverageLength, List xValues) { mAxisPaint.setTypeface(mXAxis.getTypeface()); mAxisPaint.setTextSize(mXAxis.getTextSize()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index d6249bcd87..aec666badb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -17,7 +17,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class YAxisRenderer extends AxisRenderer { @@ -268,7 +268,7 @@ public void renderGridLines(Canvas c) { */ public void renderLimitLines(Canvas c) { - ArrayList limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); if (limitLines == null || limitLines.size() <= 0) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 5f4a350d83..ac57f79a2a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; +import java.util.List; public class YAxisRendererHorizontalBarChart extends YAxisRenderer { @@ -191,7 +192,7 @@ public void renderGridLines(Canvas c) { @Override public void renderLimitLines(Canvas c) { - ArrayList limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); if (limitLines == null || limitLines.size() <= 0) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index e1f8dd77aa..974a305223 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; +import java.util.List; public class YAxisRendererRadarChart extends YAxisRenderer { @@ -130,7 +130,7 @@ public void renderAxisLabels(Canvas c) { @Override public void renderLimitLines(Canvas c) { - ArrayList limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); if (limitLines == null) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java index 4ddec02668..4c2615f983 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java @@ -5,6 +5,7 @@ import android.graphics.Color; import java.util.ArrayList; +import java.util.List; /** * Class that holds predefined color integer arrays (e.g. @@ -70,9 +71,9 @@ public static int getHoloBlue() { * @param colors an integer array of resource id's of colors * @return */ - public static ArrayList createColors(Resources r, int[] colors) { + public static List createColors(Resources r, int[] colors) { - ArrayList result = new ArrayList(); + List result = new ArrayList(); for (int i : colors) { result.add(r.getColor(i)); @@ -88,9 +89,9 @@ public static ArrayList createColors(Resources r, int[] colors) { * @param colors * @return */ - public static ArrayList createColors(int[] colors) { + public static List createColors(int[] colors) { - ArrayList result = new ArrayList(); + List result = new ArrayList(); for (int i : colors) { result.add(i); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java index 22c442239b..ebbf76a918 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.List; /** * Utilities class for interacting with the assets and the devices storage to @@ -33,14 +34,14 @@ public class FileUtils { * @param path the name of the file on the sd-card (+ path if needed) * @return */ - public static ArrayList loadEntriesFromFile(String path) { + public static List loadEntriesFromFile(String path) { File sdcard = Environment.getExternalStorageDirectory(); // Get the text file File file = new File(sdcard, path); - ArrayList entries = new ArrayList(); + List entries = new ArrayList(); try { @SuppressWarnings("resource") @@ -74,7 +75,7 @@ public static ArrayList loadEntriesFromFile(String path) { // // Get the text file // File file = new File(sdcard, path); // - // ArrayList entries = new ArrayList(); + // List entries = new ArrayList(); // String label = ""; // // try { @@ -105,9 +106,9 @@ public static ArrayList loadEntriesFromFile(String path) { * @param path the name of the file in the assets folder (+ path if needed) * @return */ - public static ArrayList loadEntriesFromAssets(AssetManager am, String path) { + public static List loadEntriesFromAssets(AssetManager am, String path) { - ArrayList entries = new ArrayList(); + List entries = new ArrayList(); BufferedReader reader = null; try { @@ -151,7 +152,7 @@ public static ArrayList loadEntriesFromAssets(AssetManager am, String pat return entries; // String label = null; - // ArrayList entries = new ArrayList(); + // List entries = new ArrayList(); // // BufferedReader reader = null; // try { @@ -193,7 +194,7 @@ public static ArrayList loadEntriesFromAssets(AssetManager am, String pat * @param ds * @param path */ - public static void saveToSdCard(ArrayList entries, String path) { + public static void saveToSdCard(List entries, String path) { File sdcard = Environment.getExternalStorageDirectory(); @@ -226,9 +227,9 @@ public static void saveToSdCard(ArrayList entries, String path) { } } - public static ArrayList loadBarEntriesFromAssets(AssetManager am, String path) { + public static List loadBarEntriesFromAssets(AssetManager am, String path) { - ArrayList entries = new ArrayList(); + List entries = new ArrayList(); BufferedReader reader = null; try { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index cd2f7d7ba9..ad19d87fb9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import java.util.ArrayList; +import java.util.List; /** * Transformer class that contains all matrices and is responsible for @@ -94,13 +94,13 @@ public void prepareMatrixOffset(boolean inverted) { } /** - * Transforms an arraylist of Entry into a float array containing the x and + * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the SCATTERCHART. * * @param entries * @return */ - public float[] generateTransformedValuesScatter(ArrayList entries, + public float[] generateTransformedValuesScatter(List entries, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -121,13 +121,13 @@ public float[] generateTransformedValuesScatter(ArrayList entri } /** - * Transforms an arraylist of Entry into a float array containing the x and + * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the LINECHART. * * @param entries * @return */ - public float[] generateTransformedValuesLine(ArrayList entries, + public float[] generateTransformedValuesLine(List entries, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -148,13 +148,13 @@ public float[] generateTransformedValuesLine(ArrayList entries, } /** - * Transforms an arraylist of Entry into a float array containing the x and + * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the CANDLESTICKCHART. * * @param entries * @return */ - public float[] generateTransformedValuesCandle(ArrayList entries, + public float[] generateTransformedValuesCandle(List entries, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -175,14 +175,14 @@ public float[] generateTransformedValuesCandle(ArrayList entries, } /** - * Transforms an arraylist of Entry into a float array containing the x and + * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. * * @param entries * @param dataSet the dataset index * @return */ - public float[] generateTransformedValuesBarChart(ArrayList entries, + public float[] generateTransformedValuesBarChart(List entries, int dataSet, BarData bd, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -209,14 +209,14 @@ public float[] generateTransformedValuesBarChart(ArrayList entr } /** - * Transforms an arraylist of Entry into a float array containing the x and + * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. * * @param entries * @param dataSet the dataset index * @return */ - public float[] generateTransformedValuesHorizontalBarChart(ArrayList entries, + public float[] generateTransformedValuesHorizontalBarChart(List entries, int dataSet, BarData bd, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -260,7 +260,7 @@ public void pathValueToPixel(Path path) { * * @param paths */ - public void pathValuesToPixel(ArrayList paths) { + public void pathValuesToPixel(List paths) { for (int i = 0; i < paths.size(); i++) { pathValueToPixel(paths.get(i)); @@ -335,7 +335,7 @@ public void rectValueToPixelHorizontal(RectF r, float phaseY) { * * @param rects */ - public void rectValuesToPixel(ArrayList rects) { + public void rectValuesToPixel(List rects) { for (int i = 0; i < rects.size(); i++) rectValueToPixel(rects.get(i)); @@ -392,7 +392,7 @@ public PointD getValuesByTouchPoint(float x, float y) { // * // * @param paths // */ - // public void transformRectsTouch(ArrayList rects) { + // public void transformRectsTouch(List rects) { // for (int i = 0; i < rects.size(); i++) { // mMatrixTouch.mapRect(rects.get(i)); // } @@ -403,7 +403,7 @@ public PointD getValuesByTouchPoint(float x, float y) { // * // * @param paths // */ - // public void transformPathsTouch(ArrayList paths) { + // public void transformPathsTouch(List paths) { // for (int i = 0; i < paths.size(); i++) { // paths.get(i).transform(mMatrixTouch); // } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 0513dfb91d..952caf8dc3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -11,7 +11,8 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import java.text.DecimalFormat; -import java.util.ArrayList; +import java.util.List; +import java.util.List; /** * Utilities class that has some helper methods. Needs to be initialized by @@ -304,12 +305,12 @@ public static int getDecimals(float number) { } /** - * Converts the provided Integer ArrayList to an int array. + * Converts the provided Integer List to an int array. * * @param integers * @return */ - public static int[] convertIntegers(ArrayList integers) { + public static int[] convertIntegers(List integers) { int[] ret = new int[integers.size()]; @@ -321,12 +322,12 @@ public static int[] convertIntegers(ArrayList integers) { } /** - * Converts the provided String ArrayList to a String array. + * Converts the provided String List to a String array. * * @param labels * @return */ - public static String[] convertStrings(ArrayList strings) { + public static String[] convertStrings(List strings) { String[] ret = new String[strings.size()]; @@ -361,7 +362,7 @@ public static double nextUp(double d) { * @param valsAtIndex all the values at a specific index * @return */ - public static int getClosestDataSetIndex(ArrayList valsAtIndex, float val, + public static int getClosestDataSetIndex(List valsAtIndex, float val, AxisDependency axis) { int index = -1; @@ -395,7 +396,7 @@ public static int getClosestDataSetIndex(ArrayList valsAtIndex, float v * @param axis * @return */ - public static float getMinimumDistance(ArrayList valsAtIndex, float val, + public static float getMinimumDistance(List valsAtIndex, float val, AxisDependency axis) { float distance = Float.MAX_VALUE; From 2b932395d57c5ff6f35b59b002ff322fc881bc0b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Mar 2015 16:45:48 +0100 Subject: [PATCH 0219/1390] Code cleanup. --- .../com/xxmassdeveloper/mpchartexample/BarChartActivity.java | 1 - .../xxmassdeveloper/mpchartexample/LineChartActivity2.java | 4 ++-- .../src/com/github/mikephil/charting/buffer/BarBuffer.java | 1 - .../github/mikephil/charting/buffer/CandleBodyBuffer.java | 1 - .../github/mikephil/charting/buffer/CandleShadowBuffer.java | 1 - .../com/github/mikephil/charting/buffer/CircleBuffer.java | 1 - .../github/mikephil/charting/buffer/HorizontalBarBuffer.java | 1 - .../com/github/mikephil/charting/buffer/ScatterBuffer.java | 1 - .../src/com/github/mikephil/charting/data/ChartData.java | 1 - .../github/mikephil/charting/renderer/LineChartRenderer.java | 1 - .../charting/renderer/YAxisRendererHorizontalBarChart.java | 5 ++--- MPChartLib/src/com/github/mikephil/charting/utils/Utils.java | 1 - 12 files changed, 4 insertions(+), 15 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index b30551c1e0..5ff9bb6174 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -9,7 +9,6 @@ import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index c9ce0d89a6..7d77dee103 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -319,8 +319,8 @@ private void setData(int count, float range) { set2.setHighLightColor(Color.rgb(244, 117, 117)); ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - dataSets.add(set2); // add the datasets + dataSets.add(set2); + dataSets.add(set1); // add the datasets // create a data object with the datasets LineData data = new LineData(xVals, dataSets); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 6dd30d3d7a..e469a5d6e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.BarEntry; -import java.util.ArrayList; import java.util.List; public class BarBuffer extends AbstractBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java index 068225a882..3f62ff63bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.CandleEntry; -import java.util.ArrayList; import java.util.List; public class CandleBodyBuffer extends AbstractBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java index a4e61d149a..214d2a5a78 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.CandleEntry; -import java.util.ArrayList; import java.util.List; public class CandleShadowBuffer extends AbstractBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java index f2cd64ccfc..26c99b85b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.Entry; -import java.util.ArrayList; import java.util.List; public class CircleBuffer extends AbstractBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index d19a2ac77c..079a099de2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.BarEntry; -import java.util.ArrayList; import java.util.List; public class HorizontalBarBuffer extends BarBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java index bd150559bc..11dcb66779 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.data.Entry; -import java.util.ArrayList; import java.util.List; public class ScatterBuffer extends AbstractBuffer { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 1ed57449cc..e309f04a1a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -11,7 +11,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.List; /** * Class that holds all relevant data that represents the chart. That involves diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1017f78d9b..a21464b904 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -18,7 +18,6 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; import java.util.List; public class LineChartRenderer extends DataRenderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index ac57f79a2a..7018e721d6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -2,12 +2,12 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.graphics.Path; import android.graphics.Paint.Align; +import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; import com.github.mikephil.charting.utils.PointD; @@ -15,7 +15,6 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; import java.util.List; public class YAxisRendererHorizontalBarChart extends YAxisRenderer { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 952caf8dc3..8f4da46332 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -12,7 +12,6 @@ import java.text.DecimalFormat; import java.util.List; -import java.util.List; /** * Utilities class that has some helper methods. Needs to be initialized by From 38fdac761db186a48397614c1f8ad6dbcdae1858 Mon Sep 17 00:00:00 2001 From: Maragues Date: Thu, 19 Mar 2015 17:02:19 +0100 Subject: [PATCH 0220/1390] drawBarShadow is false by default. Set variable accessor in BarChart to private --- .../src/com/github/mikephil/charting/charts/BarChart.java | 4 ++-- .../com/github/mikephil/charting/charts/CombinedChart.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index f00ea9c26f..8c580b9665 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -39,10 +39,10 @@ public class BarChart extends BarLineChartBase implements BarDataProvid private boolean mDrawValuesForWholeStack = true; /** - * if set to true, a grey area is darawn behind each bar that indicates the + * if set to true, a grey area is drawn behind each bar that indicates the * maximum value */ - protected boolean mDrawBarShadow = true; + private boolean mDrawBarShadow = false; public BarChart(Context context) { super(context); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index db0fbe12f6..0eebb3a520 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -44,10 +44,10 @@ public class CombinedChart extends BarLineChartBase implements Lin private boolean mDrawValuesForWholeStack = true; /** - * if set to true, a grey area is darawn behind each bar that indicates the + * if set to true, a grey area is drawn behind each bar that indicates the * maximum value */ - private boolean mDrawBarShadow = true; + private boolean mDrawBarShadow = false; protected DrawOrder[] mDrawOrder = new DrawOrder[] { DrawOrder.BAR, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER From 5de0244a6ae6990c12545742921c17ced823c103 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Mar 2015 18:07:55 +0100 Subject: [PATCH 0221/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6f7e9be1b6..1296109586 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/PhilJay/mpandroidchart/trend.png)](https://bitdeli.com/free "Bitdeli Badge") MPAndroidChart ======= From 052c550c2986066d03b8ea7203840d582f702e6f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 19 Mar 2015 18:59:12 +0100 Subject: [PATCH 0222/1390] Created new feature-graphic. --- design/feature_graphic.png | Bin 0 -> 36518 bytes design/feature_graphic.psd | Bin 0 -> 401402 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 design/feature_graphic.png create mode 100644 design/feature_graphic.psd diff --git a/design/feature_graphic.png b/design/feature_graphic.png new file mode 100644 index 0000000000000000000000000000000000000000..d1aabb48c811d20826637e63511e3dbe659e5f1f GIT binary patch literal 36518 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 diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index a940fe72f8..b0ce2f78af 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -13,6 +13,7 @@ import android.widget.TextView; import android.widget.Toast; +import com.github.mikephil.charting.animation.EasingFunction; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; @@ -140,7 +141,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setVisibleYRange(20f, AxisDependency.LEFT); // mChart.centerViewTo(20, 50, AxisDependency.LEFT); - mChart.animateX(2500); + mChart.animateX(2500, EasingFunction.EaseInOutQuart); // mChart.invalidate(); // get the legend (only possible after setting data) @@ -360,6 +361,7 @@ private void setData(int count, float range) { set1.setValueTextSize(9f); set1.setFillAlpha(65); set1.setFillColor(Color.BLACK); + set1.setDrawFilled(true); // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); @@ -372,7 +374,7 @@ private void setData(int count, float range) { // set data mChart.setData(data); } - + @Override public void onChartLongPressed(MotionEvent me) { Log.i("LongPress", "Chart longpressed."); diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java index f6f318a595..7eb42fd457 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java @@ -131,298 +131,493 @@ public float getInterpolation(float input) { } }; - // public static final EasingFunction EaseInQuart = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position * position * position; - // } - // }; - // - // public static final EasingFunction EaseOutQuart = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return -(position * position * position * position - 1.f); - // } - // }; - // - // public static final EasingFunction EaseInOutQuart = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position * position * position; - // } - // position -= 2.f; - // return -0.5f * (position * position * position * position - 2.f); - // } - // }; - // - - // public static final EasingFunction EaseInSine = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; - // } - // }; - // - // public static final EasingFunction EaseOutSine = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return (float) Math.sin(position * (Math.PI / 2.f)); - // } - // }; - // - // public static final EasingFunction EaseInOutSine = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); - // } - // }; - // - // public static final EasingFunction EaseInExpo = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed - // / (float) duration - 1.f)); - // } - // }; - // - // public static final EasingFunction EaseOutExpo = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * - // elapsed - // / (float) duration) + 1.f); - // } - // }; - // - // public static final EasingFunction EaseInOutExpo = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // if (elapsed == duration) - // { - // return 1.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - // } - // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); - // } - // }; - // - // public static final EasingFunction EaseInCirc = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -((float) Math.sqrt(1.f - position * position) - 1.f); - // } - // }; - // - // public static final EasingFunction EaseOutCirc = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (float) Math.sqrt(1.f - position * position); - // } - // }; - // - // public static final EasingFunction EaseInOutCirc = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); - // } - // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) - // + 1.f); - // } - // }; - // - // public static final EasingFunction EaseInElastic = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - // }; - // - // public static final EasingFunction EaseOutElastic = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - // return (float) Math.pow(2, -10 * position) - // * (float) Math.sin((position * duration - s) * (2.f * Math.PI) / p) + - // 1.f; - // } - // }; - // - // public static final EasingFunction EaseInOutElastic = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position == 2) - // { - // return 1.f; - // } - // - // float p = duration * (.3f * 1.5f); - // float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - // if (position < 1.f) - // { - // return -.5f - // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - // * (float) Math.sin((position * duration - s) * (2.f * Math.PI) / p) * - // .5f - // + 1.f; - // } - // }; - // - // public static final EasingFunction EaseInBack = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // return position * position * ((s + 1.f) * position - s); - // } - // }; - // - // public static final EasingFunction EaseOutBack = new EasingFunction() - // { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // position--; - // return (position * position * ((s + 1.f) * position + s) + 1.f); - // } - // }; - // - // public static final EasingFunction EaseInOutBack = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float s = 1.70158f; - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * - // position - s)); - // } - // return 0.5f * ((position -= 2.f) * position - // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - // } - // }; - // - // public static final EasingFunction EaseInBounce = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return 1.f - EaseOutBounce.ease(duration - elapsed, duration); - // } - // }; - // - // public static final EasingFunction EaseOutBounce = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // if (position < (1.f / 2.75f)) - // { - // return (7.5625f * position * position); - // } - // else if (position < (2.f / 2.75f)) - // { - // return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); - // } - // else if (position < (2.5f / 2.75f)) - // { - // return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); - // } - // else - // { - // return (7.5625f * (position -= (2.625f / 2.75f)) * position + - // .984375f); - // } - // } - // }; - // - // public static final EasingFunction EaseInOutBounce = new - // EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed < duration / 2.f) - // { - // return EaseInBounce.ease(elapsed * 2, duration) * .5f; - // } - // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * .5f + - // .5f; - // } - // }; + public static final EasingFunction EaseInQuart = new EasingFunction() { + + public float getInterpolation(float input) { + return input * input * input * input; + } + }; + + public static final EasingFunction EaseOutQuart = new EasingFunction() { + + public float getInterpolation(float input) { + input--; + return -(input * input * input * input - 1f); + } + }; + + public static final EasingFunction EaseInOutQuart = new + EasingFunction() { + @Override + public float getInterpolation(float input) { + float position = input / 0.5f; + if (position < 1.f) { + return 0.5f * position * position * position * position; + } + position -= 2.f; + return -0.5f * (position * position * position * position - 2.f); + } + }; + + public static final EasingFunction EaseInSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; + // } + @Override + public float getInterpolation(float input) { + return -(float) Math.cos(input * (Math.PI / 2.f)) + 1.f; + } + }; + + public static final EasingFunction EaseOutSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return (float) Math.sin(position * (Math.PI / 2.f)); + // } + @Override + public float getInterpolation(float input) { + return (float) Math.sin(input * (Math.PI / 2.f)); + } + }; + + public static final EasingFunction EaseInOutSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); + // } + + @Override + public float getInterpolation(float input) { + return -0.5f * ((float) Math.cos(Math.PI * input) - 1.f); + } + }; + + public static final EasingFunction EaseInExpo = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed + // / (float) duration - 1.f)); + // } + @Override + public float getInterpolation(float input) { + return (input == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (input - 1.f)); + } + }; + + public static final EasingFunction EaseOutExpo = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * + // elapsed + // / (float) duration) + 1.f); + // } + + @Override + public float getInterpolation(float input) { + return (input == 1f) ? 1.f : (-(float) Math.pow(2.f, -10.f * (input + 1.f))); + } + }; + + public static final EasingFunction EaseInOutExpo = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // if (elapsed == duration) + // { + // return 1.f; + // } + // + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); + // } + // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + + // 2.f); + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + if (input == 1f) + { + return 1.f; + } + + float position = input / 0.5f; + if (position < 1.f) + { + return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); + } + return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); + } + }; + + public static final EasingFunction EaseInCirc = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -((float) Math.sqrt(1.f - position * position) - 1.f); + // } + + @Override + public float getInterpolation(float input) { + return -((float) Math.sqrt(1.f - input * input) - 1.f); + } + }; + + public static final EasingFunction EaseOutCirc = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // position--; + // return (float) Math.sqrt(1.f - position * position); + // } + @Override + public float getInterpolation(float input) { + input--; + return (float) Math.sqrt(1.f - input * input); + } + }; + + public static final EasingFunction EaseInOutCirc = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return -0.5f * ((float) Math.sqrt(1.f - position * position) + // - 1.f); + // } + // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * + // position) + // + 1.f); + // } + + @Override + public float getInterpolation(float input) { + float position = input / 0.5f; + if (position < 1.f) + { + return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); + } + return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) + + 1.f); + } + }; + + public static final EasingFunction EaseInElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (float) duration; + // if (position == 1) + // { + // return 1.f; + // } + // + // float p = duration * .3f; + // float s = p / (2.f * (float) Math.PI) * (float) + // Math.asin(1.f); + // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * + // (float) + // Math + // .sin((position * duration - s) * (2.f * Math.PI) / p)); + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input; + if (position == 1) + { + return 1.f; + } + + float p = .3f; + float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); + return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) + Math + .sin((position - s) * (2.f * Math.PI) / p)); + } + }; + + public static final EasingFunction EaseOutElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (float) duration; + // if (position == 1) + // { + // return 1.f; + // } + // + // float p = duration * .3f; + // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); + // return (float) Math.pow(2, -10 * position) + // * (float) Math.sin((position * duration - s) * (2.f * + // Math.PI) / p) + + // 1.f; + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input; + if (position == 1) + { + return 1.f; + } + + float p = .3f; + float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); + return (float) Math.pow(2, -10 * position) + * (float) Math.sin((position - s) * (2.f * Math.PI) / p) + + 1.f; + } + }; + + public static final EasingFunction EaseInOutElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (duration / 2.f); + // if (position == 2) + // { + // return 1.f; + // } + // + // float p = duration * (.3f * 1.5f); + // float s = p / (2.f * (float) Math.PI) * (float) + // Math.asin(1.f); + // if (position < 1.f) + // { + // return -.5f + // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) + // Math + // .sin((position * duration - s) * (2.f * Math.PI) / p)); + // } + // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) + // * (float) Math.sin((position * duration - s) * (2.f * + // Math.PI) / p) * + // .5f + // + 1.f; + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input / 0.5f; + if (position == 2) + { + return 1.f; + } + + float p = (.3f * 1.5f); + float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); + if (position < 1.f) + { + return -.5f + * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math + .sin((position * 1f - s) * (2.f * Math.PI) / p)); + } + return (float) Math.pow(2.f, -10.f * (position -= 1.f)) + * (float) Math.sin((position * 1f - s) * (2.f * Math.PI) / p) * + .5f + + 1.f; + } + }; + + public static final EasingFunction EaseInBack = new EasingFunction() + { + // @Override + // public float ease(long elapsed, long duration) { + // final float s = 1.70158f; + // float position = elapsed / (float) duration; + // return position * position * ((s + 1.f) * position - s); + // } + + @Override + public float getInterpolation(float input) { + final float s = 1.70158f; + float position = input; + return position * position * ((s + 1.f) * position - s); + } + }; + + public static final EasingFunction EaseOutBack = new EasingFunction() + { + // @Override + // public float ease(long elapsed, long duration) { + // final float s = 1.70158f; + // float position = elapsed / (float) duration; + // position--; + // return (position * position * ((s + 1.f) * position + s) + 1.f); + // } + + @Override + public float getInterpolation(float input) { + final float s = 1.70158f; + float position = input; + position--; + return (position * position * ((s + 1.f) * position + s) + 1.f); + } + }; + + public static final EasingFunction EaseInOutBack = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float s = 1.70158f; + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) + // * + // position - s)); + // } + // return 0.5f * ((position -= 2.f) * position + // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); + // } + + @Override + public float getInterpolation(float input) { + float s = 1.70158f; + float position = input / 0.5f; + if (position < 1.f) + { + return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * + position - s)); + } + return 0.5f * ((position -= 2.f) * position + * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); + } + }; + + public static final EasingFunction EaseInBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return 1.f - EaseOutBounce.ease(duration - elapsed, + // duration); + // } + + @Override + public float getInterpolation(float input) { + return 1.f - EaseOutBounce.getInterpolation(1f - input); + } + }; + + public static final EasingFunction EaseOutBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // if (position < (1.f / 2.75f)) + // { + // return (7.5625f * position * position); + // } + // else if (position < (2.f / 2.75f)) + // { + // return (7.5625f * (position -= (1.5f / 2.75f)) * position + + // .75f); + // } + // else if (position < (2.5f / 2.75f)) + // { + // return (7.5625f * (position -= (2.25f / 2.75f)) * position + + // .9375f); + // } + // else + // { + // return (7.5625f * (position -= (2.625f / 2.75f)) * position + + // .984375f); + // } + // } + + @Override + public float getInterpolation(float input) { + float position = input; + if (position < (1.f / 2.75f)) + { + return (7.5625f * position * position); + } + else if (position < (2.f / 2.75f)) + { + return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); + } + else if (position < (2.5f / 2.75f)) + { + return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); + } + else + { + return (7.5625f * (position -= (2.625f / 2.75f)) * position + + .984375f); + } + } + }; + + public static final EasingFunction EaseInOutBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed < duration / 2.f) + // { + // return EaseInBounce.ease(elapsed * 2, duration) * .5f; + // } + // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * + // .5f + + // .5f; + // } + + @Override + public float getInterpolation(float input) { + if (input < 0.5f) + { + return EaseInBounce.getInterpolation(input * 2) * .5f; + } + return EaseOutBounce.getInterpolation(input * 2 - 1f) * .5f + + .5f; + } + }; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 19e7bcbb76..54a9370af4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1438,6 +1438,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } + /** * Setting this to true will set the layer-type HARDWARE for the view, false diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 79ac51fd51..382c253417 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -73,7 +73,7 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - if (mPathBitmap == null) { + if (mPathBitmap == null || ((int) mViewPortHandler.getChartHeight() != mPathBitmap.getHeight())) { mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mPathBitmap); @@ -141,10 +141,14 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cubicPath.reset(); - int size = (int)Math.ceil((maxx - minx) * phaseX + minx); + int size = (int) Math.ceil((maxx - minx) * phaseX + minx); - minx = Math.max(minx, 0); // Decrement by 2 as we always render two extra points to keep cubic flowing - size = Math.min(size + 2, entries.size()); // Increment by 2 as we always render two extra points to keep cubic flowing + minx = Math.max(minx, 0); // Decrement by 2 as we always render two + // extra points to keep cubic flowing + size = Math.min(size + 2, entries.size()); // Increment by 2 as we + // always render two extra + // points to keep cubic + // flowing if (size - minx >= 4) { @@ -337,7 +341,8 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { } } - protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries, int minx, int maxx, + protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries, int minx, + int maxx, Transformer trans) { mRenderPaint.setStyle(Paint.Style.FILL); @@ -353,7 +358,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries trans.pathValueToPixel(filled); - mBitmapCanvas.drawPath(filled, mRenderPaint); + c.drawPath(filled, mRenderPaint); // restore alpha mRenderPaint.setAlpha(255); @@ -375,14 +380,18 @@ private Path generateFilledPath(List entries, float fillMin, int from, in filled.lineTo(entries.get(from).getXIndex(), entries.get(from).getVal() * phaseY); // create a new path - for (int x = from + 1, count = (int)Math.ceil((to - from) * phaseX + from); x < count; x++) { + for (int x = from + 1, count = (int) Math.ceil((to - from) * phaseX + from); x < count; x++) { Entry e = entries.get(x); filled.lineTo(e.getXIndex(), e.getVal() * phaseY); } // close up - filled.lineTo(entries.get(Math.max(Math.min((int)Math.ceil((to - from) * phaseX + from) - 1, entries.size() - 1), 0)).getXIndex(), fillMin); + filled.lineTo( + entries.get( + Math.max( + Math.min((int) Math.ceil((to - from) * phaseX + from) - 1, + entries.size() - 1), 0)).getXIndex(), fillMin); filled.close(); From 721ee5f3ca2a0b2f5241521a414c41a548a56615 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Apr 2015 15:30:48 +0200 Subject: [PATCH 0296/1390] Fixed issue concerning linechart crash (issue #529). --- .../mpchartexample/LineChartActivity1.java | 2 +- .../github/mikephil/charting/buffer/AbstractBuffer.java | 8 ++++++-- .../mikephil/charting/renderer/LineChartRenderer.java | 6 +++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index b0ce2f78af..76ed219cbb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -245,7 +245,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.animateY: { - mChart.animateY(3000); + mChart.animateY(3000, EasingFunction.EaseInCubic); break; } case R.id.animateXY: { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java index 32eacf3016..3089c0bde6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -23,10 +23,10 @@ public abstract class AbstractBuffer { /** animation phase y-axis */ protected float phaseY = 1f; - + /** indicates from which x-index the visible data begins */ protected int mFrom = 0; - + /** indicates to which x-index the visible data ranges */ protected int mTo = 0; @@ -42,11 +42,15 @@ public AbstractBuffer(int size) { /** limits the drawing on the x-axis */ public void limitFrom(int from) { + if (from < 0) + from = 0; mFrom = from; } /** limits the drawing on the x-axis */ public void limitTo(int to) { + if (to < 0) + to = 0; mTo = to; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 382c253417..12d4c48b4b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -73,7 +73,8 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - if (mPathBitmap == null || ((int) mViewPortHandler.getChartHeight() != mPathBitmap.getHeight())) { + if (mPathBitmap == null + || ((int) mViewPortHandler.getChartHeight() != mPathBitmap.getHeight())) { mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mPathBitmap); @@ -430,6 +431,9 @@ public void drawValues(Canvas c) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = dataSet.getEntryPosition(entryFrom); + if (minx < 0) + minx = 0; + int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); float[] positions = trans.generateTransformedValuesLine( From 3561cb0b79c3dcd46a6c19f753a1f3a4f863d2eb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Apr 2015 23:28:01 +0200 Subject: [PATCH 0297/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index bad4ff8d24..2c3567bced 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Donations +Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + Demo ----- From b40964b7358413e6d06d6bf54e340a55c9c5c5b1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Apr 2015 16:35:52 +0200 Subject: [PATCH 0298/1390] Fixed issues concerning PieChart (issue #519, #527, #535). --- .../mpchartexample/PieChartActivity.java | 24 +++---- .../mikephil/charting/charts/PieChart.java | 7 +- .../charting/renderer/PieChartRenderer.java | 70 +++++++++++-------- 3 files changed, 56 insertions(+), 45 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index b16628dc26..f3851f232d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -12,7 +12,6 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import com.github.mikephil.charting.animation.EasingFunction; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -57,22 +56,21 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); - - // change the color of the center-hole - // mChart.setHoleColor(Color.rgb(235, 235, 235)); - mChart.setHoleColorTransparent(true); + mChart.setDescription(""); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); - mChart.setHoleRadius(60f); - - mChart.setDescription(""); - - mChart.setDrawCenterText(true); - mChart.setDrawHoleEnabled(true); + mChart.setHoleColorTransparent(true); + + mChart.setTransparentCircleColor(Color.WHITE); + + mChart.setHoleRadius(58f); + mChart.setTransparentCircleRadius(61f); + + mChart.setDrawCenterText(true); mChart.setRotationAngle(0); // enable rotation of the chart by touch @@ -83,13 +81,12 @@ protected void onCreate(Bundle savedInstanceState) { // add a selection listener mChart.setOnChartValueSelectedListener(this); - // mChart.setTouchEnabled(false); mChart.setCenterText("MPAndroidChart\nby Philipp Jahoda"); setData(3, 100); - mChart.animateXY(1500, 1500, EasingFunction.EaseInOutQuad, EasingFunction.EaseInOutQuad); + mChart.animateXY(1500, 1500);//, EasingFunction.EaseInOutQuad, EasingFunction.EaseInOutQuad); // mChart.spin(2000, 0, 360); Legend l = mChart.getLegend(); @@ -191,6 +188,7 @@ private void setData(int count, float range) { PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); dataSet.setSliceSpace(3f); + dataSet.setSelectionShift(5f); // add a lot of colors diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 5818a86c73..f7d00726bb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -282,8 +282,9 @@ public void setHoleColor(int color) { */ public void setHoleColorTransparent(boolean enable) { if (enable) { + ((PieChartRenderer) mRenderer).getPaintHole().setColor(0xFFFFFFFF); ((PieChartRenderer) mRenderer).getPaintHole().setXfermode( - new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } else { ((PieChartRenderer) mRenderer).getPaintHole().setXfermode(null); } @@ -442,6 +443,10 @@ public void setHoleRadius(final float percent) { public float getHoleRadius() { return mHoleRadiusPercent; } + + public void setTransparentCircleColor(int color) { + ((PieChartRenderer) mRenderer).getPaintTransparentCircle().setColor(color); + } /** * sets the radius of the transparent circle that is drawn next to the hole diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index fdaf3c9958..b32b785636 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -6,6 +6,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.graphics.Paint.Style; import android.graphics.PointF; import android.graphics.RectF; @@ -28,7 +29,8 @@ public class PieChartRenderer extends DataRenderer { * paint for the hole in the center of the pie chart and the transparent * circle */ - private Paint mHolePaint; + protected Paint mHolePaint; + protected Paint mTransparentCirclePaint; /** * paint object for the text that can be displayed in the center of the @@ -48,7 +50,12 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mHolePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mHolePaint.setColor(Color.WHITE); + mHolePaint.setStyle(Style.FILL); + mTransparentCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mTransparentCirclePaint.setColor(Color.WHITE); + mTransparentCirclePaint.setStyle(Style.FILL); + mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); @@ -62,6 +69,10 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, public Paint getPaintHole() { return mHolePaint; } + + public Paint getPaintTransparentCircle() { + return mTransparentCirclePaint; + } public Paint getPaintCenterText() { return mCenterTextPaint; @@ -75,13 +86,14 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - - if (mDrawBitmap == null) { + + if (mDrawBitmap == null + || ((int) mViewPortHandler.getChartHeight() != mDrawBitmap.getHeight())) { mDrawBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), - (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); + (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_8888); mBitmapCanvas = new Canvas(mDrawBitmap); } - + mDrawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -91,8 +103,6 @@ public void drawData(Canvas c) { if (set.isVisible()) drawDataSet(c, set); } - - c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, PieDataSet dataSet) { @@ -148,7 +158,7 @@ public void drawValues(Canvas c) { float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); - float off = r / 3f; + float off = r / 10f * 3.6f; if (mChart.isDrawHoleEnabled()) { off = (r - (r / 100f * mChart.getHoleRadius())) / 2f; @@ -174,7 +184,8 @@ public void drawValues(Canvas c) { List entries = dataSet.getYVals(); - for (int j = 0, maxEntry = Math.min((int)Math.ceil(entries.size() * mAnimator.getPhaseX()), entries.size()); j < maxEntry; j++) { + for (int j = 0, maxEntry = Math.min( + (int) Math.ceil(entries.size() * mAnimator.getPhaseX()), entries.size()); j < maxEntry; j++) { // offset needed to center the drawn text in the slice float offset = drawAngles[cnt] / 2; @@ -191,18 +202,14 @@ public void drawValues(Canvas c) { / mChart.getYValueSum() * 100f : entries.get(j).getVal(); String val = dataSet.getValueFormatter().getFormattedValue(value); + + float lineHeight = Utils.calcTextHeight(mValuePaint, val) + Utils.convertDpToPixel(4f); boolean drawYVals = dataSet.isDrawValuesEnabled(); // draw everything, depending on settings if (drawXVals && drawYVals) { - // use ascent and descent to calculate the new line - // position, - // 1.6f is the line spacing - float lineHeight = (mValuePaint.ascent() + mValuePaint.descent()) * 1.6f; - y -= lineHeight / 2; - c.drawText(val, x, y, mValuePaint); if (j < data.getXValCount()) c.drawText(data.getXVals().get(j), x, y + lineHeight, @@ -210,10 +217,10 @@ public void drawValues(Canvas c) { } else if (drawXVals && !drawYVals) { if (j < data.getXValCount()) - c.drawText(data.getXVals().get(j), x, y, mValuePaint); + c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); } else if (!drawXVals && drawYVals) { - c.drawText(val, x, y, mValuePaint); + c.drawText(val, x, y + lineHeight / 2f, mValuePaint); } cnt++; @@ -224,6 +231,7 @@ public void drawValues(Canvas c) { @Override public void drawExtras(Canvas c) { drawHole(c); + c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); drawCenterText(c); } @@ -238,26 +246,26 @@ protected void drawHole(Canvas c) { float transparentCircleRadius = mChart.getTransparentCircleRadius(); float holeRadius = mChart.getHoleRadius(); float radius = mChart.getRadius(); - - PointF center = mChart.getCenterCircleBox(); - - int color = mHolePaint.getColor(); - - // draw the hole-circle - mBitmapCanvas.drawCircle(center.x, center.y, - radius / 100 * holeRadius, mHolePaint); - + + PointF center = mChart.getCenterCircleBox(); + if (transparentCircleRadius > holeRadius) { + + int color = mTransparentCirclePaint.getColor(); // make transparent - mHolePaint.setColor(color & 0x60FFFFFF); + mTransparentCirclePaint.setColor(color & 0x60FFFFFF); // draw the transparent-circle mBitmapCanvas.drawCircle(center.x, center.y, - radius / 100 * transparentCircleRadius, mHolePaint); - - mHolePaint.setColor(color); - } + radius / 100 * transparentCircleRadius, mTransparentCirclePaint); + + mTransparentCirclePaint.setColor(color); + } + + // draw the hole-circle + mBitmapCanvas.drawCircle(center.x, center.y, + radius / 100 * holeRadius, mHolePaint); } } From b495c7a432568981ecb9d5027b34b934e3e71012 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Apr 2015 16:53:29 +0200 Subject: [PATCH 0299/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 2c3567bced..db9f8d31f3 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Remember: *It's all about the looks.* An **iOS** version of this library is now available, go check it out: [**ios-charts**](https://github.com/danielgindi/ios-charts) +Are you using this library? Add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/edit/master/Projects_using_MPAndroidChart.txt). + Donations ----- From 2eb93e75dd82e02a62b0de28309db2c06f367c12 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Apr 2015 17:13:48 +0200 Subject: [PATCH 0300/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index db9f8d31f3..ebab01eddd 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Donations Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) +Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). Demo ----- From 4a385ba5f33e835384f310d95fb3268f6aa2c3da Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Apr 2015 17:14:19 +0200 Subject: [PATCH 0301/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ebab01eddd..ab3c27a398 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Donations Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). Demo From 80525905dc1b7cee817b3183a461acedb4b50ef6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Apr 2015 11:00:42 +0200 Subject: [PATCH 0302/1390] Worked on animation easing. --- .../mpchartexample/LineChartActivity1.java | 6 +- .../mpchartexample/PieChartActivity.java | 3 +- .../charting/animation/ChartAnimator.java | 139 +++++++++++++++--- .../mikephil/charting/animation/Easing.java | 107 ++++++++++++++ .../mikephil/charting/charts/Chart.java | 128 +++++++++------- .../charting/renderer/PieChartRenderer.java | 14 +- 6 files changed, 308 insertions(+), 89 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/animation/Easing.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 76ed219cbb..1f1bec478e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -13,7 +13,7 @@ import android.widget.TextView; import android.widget.Toast; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; @@ -141,7 +141,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setVisibleYRange(20f, AxisDependency.LEFT); // mChart.centerViewTo(20, 50, AxisDependency.LEFT); - mChart.animateX(2500, EasingFunction.EaseInOutQuart); + mChart.animateX(2500, Easing.EasingOption.EaseInOutQuart); // mChart.invalidate(); // get the legend (only possible after setting data) @@ -245,7 +245,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.animateY: { - mChart.animateY(3000, EasingFunction.EaseInCubic); + mChart.animateY(3000, Easing.EasingOption.EaseInCubic); break; } case R.id.animateXY: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index f3851f232d..8470f147ba 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -12,6 +12,7 @@ import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -86,7 +87,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(3, 100); - mChart.animateXY(1500, 1500);//, EasingFunction.EaseInOutQuad, EasingFunction.EaseInOutQuad); + mChart.animateY(1500, Easing.EasingOption.EaseInOutQuad); // mChart.spin(2000, 0, 360); Legend l = mChart.getLegend(); diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java index 8e1d1e1297..b325eba738 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java @@ -36,6 +36,11 @@ public ChartAnimator(AnimatorUpdateListener listener) { /** the phase that is animated and influences the drawn values on the x-axis */ protected float mPhaseX = 1f; + /** + * ################ ################ ################ ################ + */ + /** METHODS FOR CUSTOM EASING */ + /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further @@ -43,16 +48,21 @@ public ChartAnimator(AnimatorUpdateListener listener) { * * @param durationMillisX * @param durationMillisY + * @param easingX + * @param easingY */ - public void animateXY(int durationMillisX, int durationMillisY) { + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, + EasingFunction easingY) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setInterpolator(easingY); animatorY.setDuration( durationMillisY); ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(easingX); animatorX.setDuration( durationMillisX); @@ -67,7 +77,52 @@ public void animateXY(int durationMillisX, int durationMillisY) { animatorX.start(); animatorY.start(); } - + + /** + * Animates the rendering of the chart on the x-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. + * + * @param durationMillis + * @param easing + */ + public void animateX(int durationMillis, EasingFunction easing) { + + if (android.os.Build.VERSION.SDK_INT < 11) + return; + + ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(easing); + animatorX.setDuration(durationMillis); + animatorX.addUpdateListener(mListener); + animatorX.start(); + } + + /** + * Animates the rendering of the chart on the y-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. + * + * @param durationMillis + * @param easing + */ + public void animateY(int durationMillis, EasingFunction easing) { + + if (android.os.Build.VERSION.SDK_INT < 11) + return; + + ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setInterpolator(easing); + animatorY.setDuration(durationMillis); + animatorY.addUpdateListener(mListener); + animatorY.start(); + } + + /** + * ################ ################ ################ ################ + */ + /** METHODS FOR PREDEFINED EASING */ + /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further @@ -78,17 +133,18 @@ public void animateXY(int durationMillisX, int durationMillisY) { * @param easingX * @param easingY */ - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, EasingFunction easingY) { + public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, + Easing.EasingOption easingY) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easingY); + animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easingY)); animatorY.setDuration( durationMillisY); ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easingX); + animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easingX)); animatorX.setDuration( durationMillisX); @@ -110,71 +166,108 @@ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction e * invalidate() is necessary to refresh the chart. * * @param durationMillis + * @param easing */ - public void animateX(int durationMillis) { + public void animateX(int durationMillis, Easing.EasingOption easing) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easing)); animatorX.setDuration(durationMillis); animatorX.addUpdateListener(mListener); animatorX.start(); } - + /** - * Animates the rendering of the chart on the x-axis with the specified + * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * * @param durationMillis * @param easing */ - public void animateX(int durationMillis, EasingFunction easing) { + public void animateY(int durationMillis, Easing.EasingOption easing) { + + if (android.os.Build.VERSION.SDK_INT < 11) + return; + + ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easing)); + animatorY.setDuration(durationMillis); + animatorY.addUpdateListener(mListener); + animatorY.start(); + } + + /** + * ################ ################ ################ ################ + */ + /** METHODS FOR ANIMATION WITHOUT EASING */ + + /** + * Animates the drawing / rendering of the chart on both x- and y-axis with + * the specified animation time. If animate(...) is called, no further + * calling of invalidate() is necessary to refresh the chart. + * + * @param durationMillisX + * @param durationMillisY + */ + public void animateXY(int durationMillisX, int durationMillisY) { if (android.os.Build.VERSION.SDK_INT < 11) return; + ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setDuration( + durationMillisY); ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easing); - animatorX.setDuration(durationMillis); - animatorX.addUpdateListener(mListener); + animatorX.setDuration( + durationMillisX); + + // make sure only one animator produces update-callbacks (which then + // call invalidate()) + if (durationMillisX > durationMillisY) { + animatorX.addUpdateListener(mListener); + } else { + animatorY.addUpdateListener(mListener); + } + animatorX.start(); + animatorY.start(); } /** - * Animates the rendering of the chart on the y-axis with the specified + * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * * @param durationMillis */ - public void animateY(int durationMillis) { + public void animateX(int durationMillis) { if (android.os.Build.VERSION.SDK_INT < 11) return; - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setDuration(durationMillis); - animatorY.addUpdateListener(mListener); - animatorY.start(); + ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setDuration(durationMillis); + animatorX.addUpdateListener(mListener); + animatorX.start(); } - + /** * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * * @param durationMillis - * @param easing */ - public void animateY(int durationMillis, EasingFunction easing) { - + public void animateY(int durationMillis) { + if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easing); animatorY.setDuration(durationMillis); animatorY.addUpdateListener(mListener); animatorY.start(); diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java new file mode 100644 index 0000000000..0351532ebe --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java @@ -0,0 +1,107 @@ + +package com.github.mikephil.charting.animation; + +/** + * Easing options. + * + * @author Daniel Cohen Gindi + */ +public class Easing { + + /** + * Use EasingOption instead of EasingFunction to avoid crashes below Android + * 3.0 + */ + public enum EasingOption { + Linear, + EaseInQuad, + EaseOutQuad, + EaseInOutQuad, + EaseInCubic, + EaseOutCubic, + EaseInOutCubic, + EaseInQuart, + EaseOutQuart, + EaseInOutQuart, + EaseInSine, + EaseOutSine, + EaseInOutSine, + EaseInExpo, + EaseOutExpo, + EaseInOutExpo, + EaseInCirc, + EaseOutCirc, + EaseInOutCirc, + EaseInElastic, + EaseOutElastic, + EaseInOutElastic, + EaseInBack, + EaseOutBack, + EaseInOutBack, + EaseInBounce, + EaseOutBounce, + EaseInOutBounce, + } + + public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { + switch (easing) { + default: + case Linear: + return EasingFunction.Linear; + case EaseInQuad: + return EasingFunction.EaseInQuad; + case EaseOutQuad: + return EasingFunction.EaseOutQuad; + case EaseInOutQuad: + return EasingFunction.EaseInOutQuad; + case EaseInCubic: + return EasingFunction.EaseInCubic; + case EaseOutCubic: + return EasingFunction.EaseOutCubic; + case EaseInOutCubic: + return EasingFunction.EaseInOutCubic; + case EaseInQuart: + return EasingFunction.EaseInQuart; + case EaseOutQuart: + return EasingFunction.EaseOutQuart; + case EaseInOutQuart: + return EasingFunction.EaseInOutQuart; + case EaseInSine: + return EasingFunction.EaseInSine; + case EaseOutSine: + return EasingFunction.EaseOutSine; + case EaseInOutSine: + return EasingFunction.EaseInOutSine; + case EaseInExpo: + return EasingFunction.EaseInExpo; + case EaseOutExpo: + return EasingFunction.EaseOutExpo; + case EaseInOutExpo: + return EasingFunction.EaseInOutExpo; + case EaseInCirc: + return EasingFunction.EaseInCirc; + case EaseOutCirc: + return EasingFunction.EaseOutCirc; + case EaseInOutCirc: + return EasingFunction.EaseInOutCirc; + case EaseInElastic: + return EasingFunction.EaseInElastic; + case EaseOutElastic: + return EasingFunction.EaseOutElastic; + case EaseInOutElastic: + return EasingFunction.EaseInOutElastic; + case EaseInBack: + return EasingFunction.EaseInBack; + case EaseOutBack: + return EasingFunction.EaseOutBack; + case EaseInOutBack: + return EasingFunction.EaseInOutBack; + case EaseInBounce: + return EasingFunction.EaseInBounce; + case EaseOutBounce: + return EasingFunction.EaseOutBounce; + case EaseInOutBounce: + return EasingFunction.EaseInOutBounce; + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 54a9370af4..ccd30ce39f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -26,6 +26,7 @@ import android.view.ViewParent; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.animation.EasingFunction; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; @@ -608,6 +609,12 @@ protected void drawMarkers(Canvas canvas) { public ChartAnimator getAnimator() { return mAnimator; } + + /** + * ################ ################ ################ ################ + * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + */ + /** CODE BELOW FOR PROVIDING EASING FUNCTIONS */ /** @@ -618,12 +625,44 @@ public ChartAnimator getAnimator() { * * @param durationMillisX * @param durationMillisY - * @param easingX an easing function option to be used on the animation phase - * @param easingY an easing function option to be used on the animation phase + * @param easingX a custom easing function to be used on the animation phase + * @param easingY a custom easing function to be used on the animation phase */ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, EasingFunction easingY) { mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); } + + /** + * Animates the rendering of the chart on the x-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR + * API LEVEL 11 (Android 3.0.x) AND HIGHER. + * + * @param durationMillis + * @param easing a custom easing function to be used on the animation phase + */ + public void animateX(int durationMillis, EasingFunction easing) { + mAnimator.animateX(durationMillis, easing); + } + + /** + * Animates the rendering of the chart on the y-axis with the specified + * animation time. If animate(...) is called, no further calling of + * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR + * API LEVEL 11 (Android 3.0.x) AND HIGHER. + * + * @param durationMillis + * @param easing a custom easing function to be used on the animation phase + */ + public void animateY(int durationMillis, EasingFunction easing) { + mAnimator.animateY(durationMillis, easing); + } + + /** + * ################ ################ ################ ################ + * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + */ + /** CODE BELOW FOR PREDEFINED EASING OPTIONS */ /** * Animates the drawing / rendering of the chart on both x- and y-axis with @@ -633,9 +672,11 @@ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction e * * @param durationMillisX * @param durationMillisY + * @param easingX a predefined easing option + * @param easingY a predefined easing option */ - public void animateXY(int durationMillisX, int durationMillisY) { - mAnimator.animateXY(durationMillisX, durationMillisY); + public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, Easing.EasingOption easingY) { + mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); } /** @@ -645,37 +686,44 @@ public void animateXY(int durationMillisX, int durationMillisY) { * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @param durationMillis - * @param easing an easing function option to be used on the animation phase + * @param easing a predefined easing option */ - public void animateX(int durationMillis, EasingFunction easing) { + public void animateX(int durationMillis, Easing.EasingOption easing) { mAnimator.animateX(durationMillis, easing); } /** - * Animates the rendering of the chart on the x-axis with the specified + * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @param durationMillis + * @param easing a predefined easing option */ - public void animateX(int durationMillis) { - mAnimator.animateX(durationMillis); + public void animateY(int durationMillis, Easing.EasingOption easing) { + mAnimator.animateY(durationMillis, easing); } + + /** + * ################ ################ ################ ################ + * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + */ + /** CODE BELOW FOR ANIMATIONS WITHOUT EASING */ + /** - * Animates the rendering of the chart on the y-axis with the specified + * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @param durationMillis - * @param easing an easing function to be used on the animation phase */ - public void animateY(int durationMillis, EasingFunction easing) { - mAnimator.animateY(durationMillis, easing); + public void animateX(int durationMillis) { + mAnimator.animateX(durationMillis); } - + /** * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of @@ -687,53 +735,25 @@ public void animateY(int durationMillis, EasingFunction easing) { public void animateY(int durationMillis) { mAnimator.animateY(durationMillis); } - + /** - * ################ ################ ################ ################ + * Animates the drawing / rendering of the chart on both x- and y-axis with + * the specified animation time. If animate(...) is called, no further + * calling of invalidate() is necessary to refresh the chart. ANIMATIONS + * ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + * + * @param durationMillisX + * @param durationMillisY */ - /** BELOW THIS FOR DYNAMICALLY ADDING ENTRIES AND DATASETS */ - - // public void addEntry(Entry e, int dataSetIndex) { - // mOriginalData.getDataSetByIndex(dataSetIndex).addEntry(e); - // - // prepare(); - // calcMinMax(false); - // prepareMatrix(); - // calculateOffsets(); - // } - // - // public void addEntry(Entry e, String label) { - // mOriginalData.getDataSetByLabel(label, false).addEntry(e); - // - // prepare(); - // calcMinMax(false); - // prepareMatrix(); - // calculateOffsets(); - // } - // - // public void addDataSet(DataSet d) { - // mOriginalData.addDataSet(d); - // - // prepare(); - // calcMinMax(false); - // prepareMatrix(); - // calculateOffsets(); - // } - + public void animateXY(int durationMillisX, int durationMillisY) { + mAnimator.animateXY(durationMillisX, durationMillisY); + } + /** * ################ ################ ################ ################ */ /** BELOW THIS ONLY GETTERS AND SETTERS */ - // /** - // * Returns the canvas object the chart uses for drawing. - // * - // * @return - // */ - // public Canvas getCanvas() { - // return mDrawCanvas; - // } - /** * Returns the default ValueFormatter that has been determined by the chart * considering the provided minimum and maximum values. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index b32b785636..7b5cedc596 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -94,6 +94,11 @@ public void drawData(Canvas c) { mBitmapCanvas = new Canvas(mDrawBitmap); } +// Paint p = new Paint(); +// p.setStyle(Paint.Style.FILL); +// p.setColor(Color.BLACK); +// c.drawRect(mChart.getCircleBox(), p); + mDrawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -129,17 +134,10 @@ protected void drawDataSet(Canvas c, PieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawArc(mChart.getCircleBox(), - angle + sliceSpace / 2f, + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), newangle * mAnimator.getPhaseY() - sliceSpace / 2f, true, mRenderPaint); } - - // if(sliceSpace > 0f) { - // - // PointF outer = getPosition(c, radius, angle); - // PointF inner = getPosition(c, radius * mHoleRadiusPercent - // / 100f, angle); - // } } angle += newangle * mAnimator.getPhaseX(); From 6b0a32aa90a68a215a19cbb9fee71a5a46382d08 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Apr 2015 11:08:47 +0200 Subject: [PATCH 0303/1390] More fixes concerning Animation easing. --- .../ListViewBarChartActivity.java | 4 +- .../mpchartexample/RadarChartActivitry.java | 4 +- .../mikephil/charting/animation/Easing.java | 670 +++++++++++++++++- .../charting/animation/EasingFunction.java | 615 +--------------- .../charting/charts/PieRadarChartBase.java | 6 +- 5 files changed, 653 insertions(+), 646 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 2c3b4b906c..f2a66d1942 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -12,7 +12,7 @@ import android.widget.ArrayAdapter; import android.widget.ListView; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -111,7 +111,7 @@ public View getView(int position, View convertView, ViewGroup parent) { // do not forget to refresh the chart // holder.chart.invalidate(); - holder.chart.animateY(700, EasingFunction.EaseInCubic); + holder.chart.animateY(700, Easing.EasingOption.EaseInCubic); return convertView; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index c1083f6dd4..b7f07a1abc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -8,7 +8,7 @@ import android.view.WindowManager; import android.widget.Toast; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -140,7 +140,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleSpin: { - mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, EasingFunction.EaseInCubic); + mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption.EaseInCubic); break; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java index 0351532ebe..1741f6f511 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java @@ -47,61 +47,675 @@ public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { switch (easing) { default: case Linear: - return EasingFunction.Linear; + return Easing.EasingFunctions.Linear; case EaseInQuad: - return EasingFunction.EaseInQuad; + return Easing.EasingFunctions.EaseInQuad; case EaseOutQuad: - return EasingFunction.EaseOutQuad; + return Easing.EasingFunctions.EaseOutQuad; case EaseInOutQuad: - return EasingFunction.EaseInOutQuad; + return Easing.EasingFunctions.EaseInOutQuad; case EaseInCubic: - return EasingFunction.EaseInCubic; + return Easing.EasingFunctions.EaseInCubic; case EaseOutCubic: - return EasingFunction.EaseOutCubic; + return Easing.EasingFunctions.EaseOutCubic; case EaseInOutCubic: - return EasingFunction.EaseInOutCubic; + return Easing.EasingFunctions.EaseInOutCubic; case EaseInQuart: - return EasingFunction.EaseInQuart; + return Easing.EasingFunctions.EaseInQuart; case EaseOutQuart: - return EasingFunction.EaseOutQuart; + return Easing.EasingFunctions.EaseOutQuart; case EaseInOutQuart: - return EasingFunction.EaseInOutQuart; + return Easing.EasingFunctions.EaseInOutQuart; case EaseInSine: - return EasingFunction.EaseInSine; + return Easing.EasingFunctions.EaseInSine; case EaseOutSine: - return EasingFunction.EaseOutSine; + return Easing.EasingFunctions.EaseOutSine; case EaseInOutSine: - return EasingFunction.EaseInOutSine; + return Easing.EasingFunctions.EaseInOutSine; case EaseInExpo: - return EasingFunction.EaseInExpo; + return Easing.EasingFunctions.EaseInExpo; case EaseOutExpo: - return EasingFunction.EaseOutExpo; + return Easing.EasingFunctions.EaseOutExpo; case EaseInOutExpo: - return EasingFunction.EaseInOutExpo; + return Easing.EasingFunctions.EaseInOutExpo; case EaseInCirc: - return EasingFunction.EaseInCirc; + return Easing.EasingFunctions.EaseInCirc; case EaseOutCirc: - return EasingFunction.EaseOutCirc; + return Easing.EasingFunctions.EaseOutCirc; case EaseInOutCirc: - return EasingFunction.EaseInOutCirc; + return Easing.EasingFunctions.EaseInOutCirc; case EaseInElastic: - return EasingFunction.EaseInElastic; + return Easing.EasingFunctions.EaseInElastic; case EaseOutElastic: - return EasingFunction.EaseOutElastic; + return Easing.EasingFunctions.EaseOutElastic; case EaseInOutElastic: - return EasingFunction.EaseInOutElastic; + return Easing.EasingFunctions.EaseInOutElastic; case EaseInBack: - return EasingFunction.EaseInBack; + return Easing.EasingFunctions.EaseInBack; case EaseOutBack: - return EasingFunction.EaseOutBack; + return Easing.EasingFunctions.EaseOutBack; case EaseInOutBack: - return EasingFunction.EaseInOutBack; + return Easing.EasingFunctions.EaseInOutBack; case EaseInBounce: - return EasingFunction.EaseInBounce; + return Easing.EasingFunctions.EaseInBounce; case EaseOutBounce: - return EasingFunction.EaseOutBounce; + return Easing.EasingFunctions.EaseOutBounce; case EaseInOutBounce: - return EasingFunction.EaseInOutBounce; + return Easing.EasingFunctions.EaseInOutBounce; } } + + private static class EasingFunctions { + + /** + * ########## ########## ########## ########## ########## ########## + * PREDEFINED EASING FUNCTIONS BELOW THIS + */ + + public static final EasingFunction Linear = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return elapsed / (float) duration; + // } + + @Override + public float getInterpolation(float input) { + return input; + } + }; + + public static final EasingFunction EaseInQuad = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return position * position; + // } + + @Override + public float getInterpolation(float input) { + return input * input; + } + }; + + public static final EasingFunction EaseOutQuad = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -position * (position - 2.f); + // } + + @Override + public float getInterpolation(float input) { + return -input * (input - 2f); + } + }; + + public static final EasingFunction EaseInOutQuad = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * position * position; + // } + // return -0.5f * ((--position) * (position - 2.f) - 1.f); + // } + + @Override + public float getInterpolation(float input) { + + float position = input / 0.5f; + + if (position < 1.f) { + return 0.5f * position * position; + } + + return -0.5f * ((--position) * (position - 2.f) - 1.f); + } + }; + + public static final EasingFunction EaseInCubic = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return position * position * position; + // } + + @Override + public float getInterpolation(float input) { + return input * input * input; + } + }; + + public static final EasingFunction EaseOutCubic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // position--; + // return (position * position * position + 1.f); + // } + + @Override + public float getInterpolation(float input) { + input--; + return (input * input * input + 1.f); + } + }; + + public static final EasingFunction EaseInOutCubic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * position * position * position; + // } + // position -= 2.f; + // return 0.5f * (position * position * position + 2.f); + // } + + @Override + public float getInterpolation(float input) { + + float position = input / 0.5f; + if (position < 1.f) { + return 0.5f * position * position * position; + } + position -= 2.f; + return 0.5f * (position * position * position + 2.f); + } + }; + + public static final EasingFunction EaseInQuart = new EasingFunction() { + + public float getInterpolation(float input) { + return input * input * input * input; + } + }; + + public static final EasingFunction EaseOutQuart = new EasingFunction() { + + public float getInterpolation(float input) { + input--; + return -(input * input * input * input - 1f); + } + }; + + public static final EasingFunction EaseInOutQuart = new + EasingFunction() { + @Override + public float getInterpolation(float input) { + float position = input / 0.5f; + if (position < 1.f) { + return 0.5f * position * position * position * position; + } + position -= 2.f; + return -0.5f * (position * position * position * position - 2.f); + } + }; + + public static final EasingFunction EaseInSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; + // } + @Override + public float getInterpolation(float input) { + return -(float) Math.cos(input * (Math.PI / 2.f)) + 1.f; + } + }; + + public static final EasingFunction EaseOutSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return (float) Math.sin(position * (Math.PI / 2.f)); + // } + @Override + public float getInterpolation(float input) { + return (float) Math.sin(input * (Math.PI / 2.f)); + } + }; + + public static final EasingFunction EaseInOutSine = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); + // } + + @Override + public float getInterpolation(float input) { + return -0.5f * ((float) Math.cos(Math.PI * input) - 1.f); + } + }; + + public static final EasingFunction EaseInExpo = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed + // / (float) duration - 1.f)); + // } + @Override + public float getInterpolation(float input) { + return (input == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (input - 1.f)); + } + }; + + public static final EasingFunction EaseOutExpo = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * + // elapsed + // / (float) duration) + 1.f); + // } + + @Override + public float getInterpolation(float input) { + return (input == 1f) ? 1.f : (-(float) Math.pow(2.f, -10.f * (input + 1.f))); + } + }; + + public static final EasingFunction EaseInOutExpo = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // if (elapsed == duration) + // { + // return 1.f; + // } + // + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); + // } + // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + + // 2.f); + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + if (input == 1f) + { + return 1.f; + } + + float position = input / 0.5f; + if (position < 1.f) + { + return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); + } + return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); + } + }; + + public static final EasingFunction EaseInCirc = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // return -((float) Math.sqrt(1.f - position * position) - 1.f); + // } + + @Override + public float getInterpolation(float input) { + return -((float) Math.sqrt(1.f - input * input) - 1.f); + } + }; + + public static final EasingFunction EaseOutCirc = new EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // position--; + // return (float) Math.sqrt(1.f - position * position); + // } + @Override + public float getInterpolation(float input) { + input--; + return (float) Math.sqrt(1.f - input * input); + } + }; + + public static final EasingFunction EaseInOutCirc = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return -0.5f * ((float) Math.sqrt(1.f - position * position) + // - 1.f); + // } + // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * + // position) + // + 1.f); + // } + + @Override + public float getInterpolation(float input) { + float position = input / 0.5f; + if (position < 1.f) + { + return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); + } + return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) + + 1.f); + } + }; + + public static final EasingFunction EaseInElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (float) duration; + // if (position == 1) + // { + // return 1.f; + // } + // + // float p = duration * .3f; + // float s = p / (2.f * (float) Math.PI) * (float) + // Math.asin(1.f); + // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * + // (float) + // Math + // .sin((position * duration - s) * (2.f * Math.PI) / p)); + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input; + if (position == 1) + { + return 1.f; + } + + float p = .3f; + float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); + return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) + Math + .sin((position - s) * (2.f * Math.PI) / p)); + } + }; + + public static final EasingFunction EaseOutElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (float) duration; + // if (position == 1) + // { + // return 1.f; + // } + // + // float p = duration * .3f; + // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); + // return (float) Math.pow(2, -10 * position) + // * (float) Math.sin((position * duration - s) * (2.f * + // Math.PI) / p) + + // 1.f; + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input; + if (position == 1) + { + return 1.f; + } + + float p = .3f; + float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); + return (float) Math.pow(2, -10 * position) + * (float) Math.sin((position - s) * (2.f * Math.PI) / p) + + 1.f; + } + }; + + public static final EasingFunction EaseInOutElastic = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed == 0) + // { + // return 0.f; + // } + // + // float position = elapsed / (duration / 2.f); + // if (position == 2) + // { + // return 1.f; + // } + // + // float p = duration * (.3f * 1.5f); + // float s = p / (2.f * (float) Math.PI) * (float) + // Math.asin(1.f); + // if (position < 1.f) + // { + // return -.5f + // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) + // Math + // .sin((position * duration - s) * (2.f * Math.PI) / p)); + // } + // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) + // * (float) Math.sin((position * duration - s) * (2.f * + // Math.PI) / p) * + // .5f + // + 1.f; + // } + + @Override + public float getInterpolation(float input) { + if (input == 0) + { + return 0.f; + } + + float position = input / 0.5f; + if (position == 2) + { + return 1.f; + } + + float p = (.3f * 1.5f); + float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); + if (position < 1.f) + { + return -.5f + * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math + .sin((position * 1f - s) * (2.f * Math.PI) / p)); + } + return (float) Math.pow(2.f, -10.f * (position -= 1.f)) + * (float) Math.sin((position * 1f - s) * (2.f * Math.PI) / p) * + .5f + + 1.f; + } + }; + + public static final EasingFunction EaseInBack = new EasingFunction() + { + // @Override + // public float ease(long elapsed, long duration) { + // final float s = 1.70158f; + // float position = elapsed / (float) duration; + // return position * position * ((s + 1.f) * position - s); + // } + + @Override + public float getInterpolation(float input) { + final float s = 1.70158f; + float position = input; + return position * position * ((s + 1.f) * position - s); + } + }; + + public static final EasingFunction EaseOutBack = new EasingFunction() + { + // @Override + // public float ease(long elapsed, long duration) { + // final float s = 1.70158f; + // float position = elapsed / (float) duration; + // position--; + // return (position * position * ((s + 1.f) * position + s) + 1.f); + // } + + @Override + public float getInterpolation(float input) { + final float s = 1.70158f; + float position = input; + position--; + return (position * position * ((s + 1.f) * position + s) + 1.f); + } + }; + + public static final EasingFunction EaseInOutBack = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float s = 1.70158f; + // float position = elapsed / (duration / 2.f); + // if (position < 1.f) + // { + // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) + // * + // position - s)); + // } + // return 0.5f * ((position -= 2.f) * position + // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); + // } + + @Override + public float getInterpolation(float input) { + float s = 1.70158f; + float position = input / 0.5f; + if (position < 1.f) + { + return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * + position - s)); + } + return 0.5f * ((position -= 2.f) * position + * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); + } + }; + + public static final EasingFunction EaseInBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // return 1.f - EaseOutBounce.ease(duration - elapsed, + // duration); + // } + + @Override + public float getInterpolation(float input) { + return 1.f - EaseOutBounce.getInterpolation(1f - input); + } + }; + + public static final EasingFunction EaseOutBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // float position = elapsed / (float) duration; + // if (position < (1.f / 2.75f)) + // { + // return (7.5625f * position * position); + // } + // else if (position < (2.f / 2.75f)) + // { + // return (7.5625f * (position -= (1.5f / 2.75f)) * position + + // .75f); + // } + // else if (position < (2.5f / 2.75f)) + // { + // return (7.5625f * (position -= (2.25f / 2.75f)) * position + + // .9375f); + // } + // else + // { + // return (7.5625f * (position -= (2.625f / 2.75f)) * position + + // .984375f); + // } + // } + + @Override + public float getInterpolation(float input) { + float position = input; + if (position < (1.f / 2.75f)) + { + return (7.5625f * position * position); + } + else if (position < (2.f / 2.75f)) + { + return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); + } + else if (position < (2.5f / 2.75f)) + { + return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); + } + else + { + return (7.5625f * (position -= (2.625f / 2.75f)) * position + + .984375f); + } + } + }; + + public static final EasingFunction EaseInOutBounce = new + EasingFunction() { + // @Override + // public float ease(long elapsed, long duration) { + // if (elapsed < duration / 2.f) + // { + // return EaseInBounce.ease(elapsed * 2, duration) * .5f; + // } + // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * + // .5f + + // .5f; + // } + + @Override + public float getInterpolation(float input) { + if (input < 0.5f) + { + return EaseInBounce.getInterpolation(input * 2) * .5f; + } + return EaseOutBounce.getInterpolation(input * 2 - 1f) * .5f + + .5f; + } + }; + + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java index 7eb42fd457..54202984d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java @@ -5,619 +5,12 @@ import android.annotation.SuppressLint; /** - * Interface for creating custom made easing functions. + * Interface for creating custom made easing functions. Uses the + * TimeInterpolator interface provided by Android. */ @SuppressLint("NewApi") public interface EasingFunction extends TimeInterpolator { - /** - * ########## ########## ########## ########## ########## ########## - * PREDEFINED EASING FUNCTIONS BELOW THIS - */ - - public static final EasingFunction Linear = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return elapsed / (float) duration; - // } - - @Override - public float getInterpolation(float input) { - return input; - } - }; - - public static final EasingFunction EaseInQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input; - } - }; - - public static final EasingFunction EaseOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -position * (position - 2.f); - // } - - @Override - public float getInterpolation(float input) { - return -input * (input - 2f); - } - }; - - public static final EasingFunction EaseInOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position; - // } - // return -0.5f * ((--position) * (position - 2.f) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - - float position = input / 0.5f; - - if (position < 1.f) { - return 0.5f * position * position; - } - - return -0.5f * ((--position) * (position - 2.f) - 1.f); - } - }; - - public static final EasingFunction EaseInCubic = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input * input; - } - }; - - public static final EasingFunction EaseOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (position * position * position + 1.f); - // } - - @Override - public float getInterpolation(float input) { - input--; - return (input * input * input + 1.f); - } - }; - - public static final EasingFunction EaseInOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position * position; - // } - // position -= 2.f; - // return 0.5f * (position * position * position + 2.f); - // } - - @Override - public float getInterpolation(float input) { - - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position; - } - position -= 2.f; - return 0.5f * (position * position * position + 2.f); - } - }; - - public static final EasingFunction EaseInQuart = new EasingFunction() { - - public float getInterpolation(float input) { - return input * input * input * input; - } - }; - - public static final EasingFunction EaseOutQuart = new EasingFunction() { - - public float getInterpolation(float input) { - input--; - return -(input * input * input * input - 1f); - } - }; - - public static final EasingFunction EaseInOutQuart = new - EasingFunction() { - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position * position; - } - position -= 2.f; - return -0.5f * (position * position * position * position - 2.f); - } - }; - - public static final EasingFunction EaseInSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; - // } - @Override - public float getInterpolation(float input) { - return -(float) Math.cos(input * (Math.PI / 2.f)) + 1.f; - } - }; - - public static final EasingFunction EaseOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return (float) Math.sin(position * (Math.PI / 2.f)); - // } - @Override - public float getInterpolation(float input) { - return (float) Math.sin(input * (Math.PI / 2.f)); - } - }; - - public static final EasingFunction EaseInOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -0.5f * ((float) Math.cos(Math.PI * input) - 1.f); - } - }; - - public static final EasingFunction EaseInExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed - // / (float) duration - 1.f)); - // } - @Override - public float getInterpolation(float input) { - return (input == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (input - 1.f)); - } - }; - - public static final EasingFunction EaseOutExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * - // elapsed - // / (float) duration) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - return (input == 1f) ? 1.f : (-(float) Math.pow(2.f, -10.f * (input + 1.f))); - } - }; - - public static final EasingFunction EaseInOutExpo = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // if (elapsed == duration) - // { - // return 1.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - // } - // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + - // 2.f); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - if (input == 1f) - { - return 1.f; - } - - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - } - return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); - } - }; - - public static final EasingFunction EaseInCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -((float) Math.sqrt(1.f - position * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -((float) Math.sqrt(1.f - input * input) - 1.f); - } - }; - - public static final EasingFunction EaseOutCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (float) Math.sqrt(1.f - position * position); - // } - @Override - public float getInterpolation(float input) { - input--; - return (float) Math.sqrt(1.f - input * input); - } - }; - - public static final EasingFunction EaseInOutCirc = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return -0.5f * ((float) Math.sqrt(1.f - position * position) - // - 1.f); - // } - // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * - // position) - // + 1.f); - // } - - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) - { - return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); - } - return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) - + 1.f); - } - }; - - public static final EasingFunction EaseInElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * - // (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - Math - .sin((position - s) * (2.f * Math.PI) / p)); - } - }; - - public static final EasingFunction EaseOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - // return (float) Math.pow(2, -10 * position) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) + - // 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - return (float) Math.pow(2, -10 * position) - * (float) Math.sin((position - s) * (2.f * Math.PI) / p) + - 1.f; - } - }; - - public static final EasingFunction EaseInOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position == 2) - // { - // return 1.f; - // } - // - // float p = duration * (.3f * 1.5f); - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // if (position < 1.f) - // { - // return -.5f - // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) * - // .5f - // + 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input / 0.5f; - if (position == 2) - { - return 1.f; - } - - float p = (.3f * 1.5f); - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - if (position < 1.f) - { - return -.5f - * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math - .sin((position * 1f - s) * (2.f * Math.PI) / p)); - } - return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - * (float) Math.sin((position * 1f - s) * (2.f * Math.PI) / p) * - .5f - + 1.f; - } - }; - - public static final EasingFunction EaseInBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // return position * position * ((s + 1.f) * position - s); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - return position * position * ((s + 1.f) * position - s); - } - }; - - public static final EasingFunction EaseOutBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // position--; - // return (position * position * ((s + 1.f) * position + s) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - position--; - return (position * position * ((s + 1.f) * position + s) + 1.f); - } - }; - - public static final EasingFunction EaseInOutBack = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float s = 1.70158f; - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) - // * - // position - s)); - // } - // return 0.5f * ((position -= 2.f) * position - // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - // } - - @Override - public float getInterpolation(float input) { - float s = 1.70158f; - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * - position - s)); - } - return 0.5f * ((position -= 2.f) * position - * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - } - }; - - public static final EasingFunction EaseInBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return 1.f - EaseOutBounce.ease(duration - elapsed, - // duration); - // } - - @Override - public float getInterpolation(float input) { - return 1.f - EaseOutBounce.getInterpolation(1f - input); - } - }; - - public static final EasingFunction EaseOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // if (position < (1.f / 2.75f)) - // { - // return (7.5625f * position * position); - // } - // else if (position < (2.f / 2.75f)) - // { - // return (7.5625f * (position -= (1.5f / 2.75f)) * position + - // .75f); - // } - // else if (position < (2.5f / 2.75f)) - // { - // return (7.5625f * (position -= (2.25f / 2.75f)) * position + - // .9375f); - // } - // else - // { - // return (7.5625f * (position -= (2.625f / 2.75f)) * position + - // .984375f); - // } - // } - - @Override - public float getInterpolation(float input) { - float position = input; - if (position < (1.f / 2.75f)) - { - return (7.5625f * position * position); - } - else if (position < (2.f / 2.75f)) - { - return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); - } - else if (position < (2.5f / 2.75f)) - { - return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); - } - else - { - return (7.5625f * (position -= (2.625f / 2.75f)) * position + - .984375f); - } - } - }; - - public static final EasingFunction EaseInOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed < duration / 2.f) - // { - // return EaseInBounce.ease(elapsed * 2, duration) * .5f; - // } - // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * - // .5f + - // .5f; - // } - - @Override - public float getInterpolation(float input) { - if (input < 0.5f) - { - return EaseInBounce.getInterpolation(input * 2) * .5f; - } - return EaseOutBounce.getInterpolation(input * 2 - 1f) * .5f + - .5f; - } - }; - + @Override + public float getInterpolation(float input); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index e93102645c..86ae266675 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -12,7 +12,7 @@ import android.util.Log; import android.view.MotionEvent; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; @@ -466,7 +466,7 @@ public List getYValsAtIndex(int xIndex) { * @param toangle */ @SuppressLint("NewApi") - public void spin(int durationmillis, float fromangle, float toangle, EasingFunction easing) { + public void spin(int durationmillis, float fromangle, float toangle, Easing.EasingOption easing) { if (android.os.Build.VERSION.SDK_INT < 11) return; @@ -475,7 +475,7 @@ public void spin(int durationmillis, float fromangle, float toangle, EasingFunct ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); spinAnimator.setDuration(durationmillis); - spinAnimator.setInterpolator(easing); + spinAnimator.setInterpolator(Easing.getEasingFunctionFromOption(easing)); spinAnimator.addUpdateListener(new AnimatorUpdateListener() { From 43418902cd1a17927e01bb94e65b9d111dda3b79 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Apr 2015 13:12:10 +0200 Subject: [PATCH 0304/1390] Fixed bug concerning cubic-lines (issue #528). --- .../mpchartexample/LineChartActivity1.java | 2 +- .../charting/renderer/LineChartRenderer.java | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 1f1bec478e..489ad3d1fe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -361,7 +361,7 @@ private void setData(int count, float range) { set1.setValueTextSize(9f); set1.setFillAlpha(65); set1.setFillColor(Color.BLACK); - set1.setDrawFilled(true); +// set1.setDrawFilled(true); // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 12d4c48b4b..cd57f01397 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -144,14 +144,13 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { int size = (int) Math.ceil((maxx - minx) * phaseX + minx); - minx = Math.max(minx, 0); // Decrement by 2 as we always render two + minx = Math.max(minx - 2, 0); // Decrement by 2 as we always render two // extra points to keep cubic flowing size = Math.min(size + 2, entries.size()); // Increment by 2 as we // always render two extra // points to keep cubic // flowing - - if (size - minx >= 4) { + if (size - minx >= 2) { float prevDx = 0f; float prevDy = 0f; @@ -170,7 +169,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { prevDy = (next.getVal() - cur.getVal()) * intensity; cur = entries.get(1); - next = entries.get(2); + next = entries.get((entries.size() > 2) ? 2 : 1); curDx = (next.getXIndex() - prev.getXIndex()) * intensity; curDy = (next.getVal() - prev.getVal()) * intensity; @@ -200,7 +199,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cur = entries.get(entries.size() - 1); prev = entries.get(entries.size() - 2); - prevPrev = entries.get(entries.size() - 3); + prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3 : entries.size() - 2); next = cur; prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; @@ -221,7 +220,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, minx, maxx); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, minx, size); } mRenderPaint.setColor(dataSet.getColor()); @@ -242,7 +241,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo(to - 1, fillMin); + spline.lineTo(to-1, fillMin); spline.lineTo(from, fillMin); spline.close(); From aa7cbce0330de983dac26bf0cda3a23b46b4df1d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Apr 2015 14:18:53 +0200 Subject: [PATCH 0305/1390] Fixed issue concerning transparent circle when animating (issue #543). --- .../charting/renderer/PieChartRenderer.java | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 7b5cedc596..998af82d1c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -55,7 +55,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mTransparentCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTransparentCirclePaint.setColor(Color.WHITE); mTransparentCirclePaint.setStyle(Style.FILL); - + mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); @@ -69,7 +69,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, public Paint getPaintHole() { return mHolePaint; } - + public Paint getPaintTransparentCircle() { return mTransparentCirclePaint; } @@ -86,19 +86,19 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - + if (mDrawBitmap == null || ((int) mViewPortHandler.getChartHeight() != mDrawBitmap.getHeight())) { mDrawBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_8888); mBitmapCanvas = new Canvas(mDrawBitmap); } - -// Paint p = new Paint(); -// p.setStyle(Paint.Style.FILL); -// p.setColor(Color.BLACK); -// c.drawRect(mChart.getCircleBox(), p); - + + // Paint p = new Paint(); + // p.setStyle(Paint.Style.FILL); + // p.setColor(Color.BLACK); + // c.drawRect(mChart.getCircleBox(), p); + mDrawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -200,8 +200,9 @@ public void drawValues(Canvas c) { / mChart.getYValueSum() * 100f : entries.get(j).getVal(); String val = dataSet.getValueFormatter().getFormattedValue(value); - - float lineHeight = Utils.calcTextHeight(mValuePaint, val) + Utils.convertDpToPixel(4f); + + float lineHeight = Utils.calcTextHeight(mValuePaint, val) + + Utils.convertDpToPixel(4f); boolean drawYVals = dataSet.isDrawValuesEnabled(); @@ -244,11 +245,12 @@ protected void drawHole(Canvas c) { float transparentCircleRadius = mChart.getTransparentCircleRadius(); float holeRadius = mChart.getHoleRadius(); float radius = mChart.getRadius(); - - PointF center = mChart.getCenterCircleBox(); - - if (transparentCircleRadius > holeRadius) { - + + PointF center = mChart.getCenterCircleBox(); + + if (transparentCircleRadius > holeRadius && mAnimator.getPhaseX() >= 1f + && mAnimator.getPhaseY() >= 1f) { + int color = mTransparentCirclePaint.getColor(); // make transparent @@ -257,10 +259,10 @@ protected void drawHole(Canvas c) { // draw the transparent-circle mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * transparentCircleRadius, mTransparentCirclePaint); - - mTransparentCirclePaint.setColor(color); - } - + + mTransparentCirclePaint.setColor(color); + } + // draw the hole-circle mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * holeRadius, mHolePaint); From 5d84b0055af13a999d61e3f92122870ab0682f72 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 12 Apr 2015 16:50:00 +0300 Subject: [PATCH 0306/1390] Bugfix: Consider viewport for second point in cubic line --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index cd57f01397..87ffc0f23a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -168,8 +168,8 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { prevDx = (next.getXIndex() - cur.getXIndex()) * intensity; prevDy = (next.getVal() - cur.getVal()) * intensity; - cur = entries.get(1); - next = entries.get((entries.size() > 2) ? 2 : 1); + cur = entries.get(minx + 1); + next = entries.get(minx + (size - minx > 2 ? 2 : 1)); curDx = (next.getXIndex() - prev.getXIndex()) * intensity; curDy = (next.getVal() - prev.getVal()) * intensity; From 791a487456801a64c5bb50cc8c3a958da3e3a81c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 12 Apr 2015 16:54:25 +0300 Subject: [PATCH 0307/1390] Bugfix: Last label were sometimes invisible due to rounding errors --- .../src/com/github/mikephil/charting/utils/ViewPortHandler.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index ad1b26d577..d95468f0a3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -379,6 +379,7 @@ public boolean isInBoundsLeft(float x) { } public boolean isInBoundsRight(float x) { + x = (float)((int)(x * 100.f)) / 100.f; return mContentRect.right >= x ? true : false; } @@ -387,6 +388,7 @@ public boolean isInBoundsTop(float y) { } public boolean isInBoundsBottom(float y) { + y = (float)((int)(y * 100.f)) / 100.f; return mContentRect.bottom >= y ? true : false; } From ca256ace2807453c3793951abe488fa18ade8cf2 Mon Sep 17 00:00:00 2001 From: Michael Balzer Date: Sun, 12 Apr 2015 18:58:20 +0200 Subject: [PATCH 0308/1390] - Extended gesture listener by translate/drag callback - Disabled debug log output in ViewPortHandler --- .../mpchartexample/LineChartActivity1.java | 9 +++++-- .../fragments/BarChartFrag.java | 6 +++++ .../listener/BarLineChartTouchListener.java | 25 ++++++++++++------- .../listener/OnChartGestureListener.java | 10 ++++++++ .../charting/utils/ViewPortHandler.java | 2 +- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index eaf916577e..14952deeac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -396,8 +396,13 @@ public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, floa public void onChartScale(MotionEvent me, float scaleX, float scaleY) { Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); } - - @Override + + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); + } + + @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); Log.i("", "low: " + mChart.getLowestVisibleXIndex() + ", high: " + mChart.getHighestVisibleXIndex()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 473516d366..e1c5aa4309 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -90,4 +90,10 @@ public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, floa public void onChartScale(MotionEvent me, float scaleX, float scaleY) { Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); } + + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); + } + } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 79b8e0e23d..c51d721265 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -202,25 +202,32 @@ private void performDrag(MotionEvent event) { mMatrix.set(mSavedMatrix); - // check if axis is inverted + OnChartGestureListener l = mChart.getOnChartGestureListener(); + + float dX, dY; + + // check if axis is inverted if (mChart.isAnyAxisInverted() && mClosestDataSetToTouch != null && mChart.getAxis(mClosestDataSetToTouch.getAxisDependency()).isInverted()) { // if there is an inverted horizontalbarchart if (mChart instanceof HorizontalBarChart) { - - mMatrix.postTranslate(-(event.getX() - mTouchStartPoint.x), event.getY() - - mTouchStartPoint.y); + dX = -(event.getX() - mTouchStartPoint.x); + dY = event.getY() - mTouchStartPoint.y; } else { - - mMatrix.postTranslate(event.getX() - mTouchStartPoint.x, -(event.getY() - - mTouchStartPoint.y)); + dX = event.getX() - mTouchStartPoint.x; + dY = -(event.getY() - mTouchStartPoint.y); } } else { - mMatrix.postTranslate(event.getX() - mTouchStartPoint.x, event.getY() - - mTouchStartPoint.y); + dX = event.getX() - mTouchStartPoint.x; + dY = event.getY() - mTouchStartPoint.y; } + + mMatrix.postTranslate(dX, dY); + + if (l != null) + l.onChartTranslate(event, dX, dY); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java index 338fff4921..6ebad1ecc5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -49,4 +49,14 @@ public interface OnChartGestureListener { * @param scaleY scalefactor on the y-axis */ public void onChartScale(MotionEvent me, float scaleX, float scaleY); + + /** + * Callbacks when the chart is moved / translated via drag gesture. + * + * @param me + * @param dX translation distance on the x-axis + * @param dY translation distance on the y-axis + */ + public void onChartTranslate(MotionEvent me, float dX, float dY); + } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index ad1b26d577..e50f86cacb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -222,7 +222,7 @@ public synchronized void centerViewPort(final float[] transformedPts, final View final float x = transformedPts[0] - offsetLeft(); final float y = transformedPts[1] - offsetTop(); - Log.i("", "Moving view to x: " + x + ", y: " + y); + //Log.i("", "Moving view to x: " + x + ", y: " + y); save.postTranslate(-x, -y); From 1b351934e282827afbdf87e11022d852b07163a0 Mon Sep 17 00:00:00 2001 From: Michael Balzer Date: Sun, 12 Apr 2015 19:43:07 +0200 Subject: [PATCH 0309/1390] - Fixed LineChart & PieChart data rendering bug on resized views --- .../mikephil/charting/renderer/LineChartRenderer.java | 6 ++++-- .../github/mikephil/charting/renderer/PieChartRenderer.java | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index edc75e563d..56ed94c5a6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -73,8 +73,10 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - if (mPathBitmap == null) { - mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), + if (mPathBitmap == null + || mPathBitmap.getWidth() != mViewPortHandler.getChartWidth() + || mPathBitmap.getHeight() != mViewPortHandler.getChartHeight()) { + mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mPathBitmap); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 82d70dc85c..87ded29883 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -77,7 +77,9 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - if (mDrawBitmap == null) { + if (mDrawBitmap == null + || mDrawBitmap.getWidth() != mViewPortHandler.getChartWidth() + || mDrawBitmap.getHeight() != mViewPortHandler.getChartHeight()) { mDrawBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mDrawBitmap); From 847e6c354511bdf65bbcde914e9a3bed914c1e3e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Apr 2015 21:36:33 +0200 Subject: [PATCH 0310/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ab3c27a398..5311083a65 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). +Do me a favor, like this page: [**Cycle Savers**](https://www.facebook.com/ontaptechs?ref=ts&fref=ts) + Demo ----- From 55cc1747321106b17f3ff02b06b46d3f76b87fc3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 13 Apr 2015 18:33:28 +0200 Subject: [PATCH 0311/1390] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 5311083a65..ab3c27a398 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,6 @@ Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). -Do me a favor, like this page: [**Cycle Savers**](https://www.facebook.com/ontaptechs?ref=ts&fref=ts) - Demo ----- From 055050b4e28387de3fad263b1498e547669e22ed Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 17 Apr 2015 10:01:06 +0200 Subject: [PATCH 0312/1390] Enhanced customizability of description text (issue #563). --- .../DynamicalAddingActivity.java | 6 +- .../mikephil/charting/charts/Chart.java | 108 ++++++++++-------- 2 files changed, 65 insertions(+), 49 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 446306f345..314bb02cf8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -71,11 +71,11 @@ private void addEntry() { // let the chart know it's data has changed mChart.notifyDataSetChanged(); -// mChart.setVisibleXRange(6); -// mChart.setVisibleYRange(30, AxisDependency.LEFT); + mChart.setVisibleXRange(6); + mChart.setVisibleYRange(10, AxisDependency.LEFT); // // // this automatically refreshes the chart (calls invalidate()) -// mChart.moveViewTo(data.getXValCount()-7, 55f, AxisDependency.LEFT); + mChart.moveViewTo(data.getXValCount()-7, 50f, AxisDependency.LEFT); // redraw the chart mChart.invalidate(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index ccd30ce39f..fef66779fe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -398,6 +398,9 @@ protected void onDraw(Canvas canvas) { // mDrawBitmap.eraseColor(Color.TRANSPARENT); } + /** the custom position of the description text */ + private PointF mDescriptionPosition; + /** * draws the description text in the bottom right corner of the chart */ @@ -405,9 +408,14 @@ protected void drawDescription(Canvas c) { if (!mDescription.equals("")) { - c.drawText(mDescription, getWidth() - mViewPortHandler.offsetRight() - 10, - getHeight() - mViewPortHandler.offsetBottom() - - 10, mDescPaint); + if (mDescriptionPosition == null) { + + c.drawText(mDescription, getWidth() - mViewPortHandler.offsetRight() - 10, + getHeight() - mViewPortHandler.offsetBottom() + - 10, mDescPaint); + } else { + c.drawText(mDescription, mDescriptionPosition.x, mDescriptionPosition.y, mDescPaint); + } } } @@ -609,14 +617,13 @@ protected void drawMarkers(Canvas canvas) { public ChartAnimator getAnimator() { return mAnimator; } - + /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. */ /** CODE BELOW FOR PROVIDING EASING FUNCTIONS */ - /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further @@ -628,7 +635,8 @@ public ChartAnimator getAnimator() { * @param easingX a custom easing function to be used on the animation phase * @param easingY a custom easing function to be used on the animation phase */ - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, EasingFunction easingY) { + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, + EasingFunction easingY) { mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); } @@ -657,13 +665,13 @@ public void animateX(int durationMillis, EasingFunction easing) { public void animateY(int durationMillis, EasingFunction easing) { mAnimator.animateY(durationMillis, easing); } - + /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. */ /** CODE BELOW FOR PREDEFINED EASING OPTIONS */ - + /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further @@ -675,7 +683,8 @@ public void animateY(int durationMillis, EasingFunction easing) { * @param easingX a predefined easing option * @param easingY a predefined easing option */ - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, Easing.EasingOption easingY) { + public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, + Easing.EasingOption easingY) { mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); } @@ -704,13 +713,12 @@ public void animateX(int durationMillis, Easing.EasingOption easing) { public void animateY(int durationMillis, Easing.EasingOption easing) { mAnimator.animateY(durationMillis, easing); } - + /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. */ /** CODE BELOW FOR ANIMATIONS WITHOUT EASING */ - /** * Animates the rendering of the chart on the x-axis with the specified @@ -723,7 +731,7 @@ public void animateY(int durationMillis, Easing.EasingOption easing) { public void animateX(int durationMillis) { mAnimator.animateX(durationMillis); } - + /** * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of @@ -735,7 +743,7 @@ public void animateX(int durationMillis) { public void animateY(int durationMillis) { mAnimator.animateY(durationMillis); } - + /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further @@ -748,7 +756,7 @@ public void animateY(int durationMillis) { public void animateXY(int durationMillisX, int durationMillisY) { mAnimator.animateXY(durationMillisX, durationMillisY); } - + /** * ################ ################ ################ ################ */ @@ -838,16 +846,6 @@ public float getYMin() { return mData.getYMin(); } - // /** - // * Get the total number of X-values. - // * - // * @return - // */ - // @Override - // public float getDeltaX() { - // return mDeltaX; - // } - @Override public float getXChartMax() { return mXChartMax; @@ -911,6 +909,37 @@ public PointF getCenterOffsets() { return mViewPortHandler.getContentCenter(); } + /** + * set a description text that appears in the bottom right corner of the + * chart, size = Y-legend text size + * + * @param desc + */ + public void setDescription(String desc) { + if (desc == null) + desc = ""; + this.mDescription = desc; + } + + /** + * Sets a custom position for the description text in pixels on the screen. + * + * @param x - xcoordinate + * @param y - ycoordinate + */ + public void setDescriptionPosition(float x, float y) { + mDescriptionPosition = new PointF(x, y); + } + + /** + * sets the typeface for the description paint + * + * @param t + */ + public void setDescriptionTypeface(Typeface t) { + mDescPaint.setTypeface(t); + } + /** * sets the size of the description text in pixels, min 6f, max 16f * @@ -926,6 +955,15 @@ public void setDescriptionTextSize(float size) { mDescPaint.setTextSize(Utils.convertDpToPixel(size)); } + /** + * Sets the color of the description text. + * + * @param color + */ + public void setDescriptionColor(int color) { + mDescPaint.setColor(color); + } + /** * Set this to true to enable logcat outputs for the chart. Default: * disabled @@ -945,18 +983,6 @@ public boolean isLogEnabled() { return mLogEnabled; } - /** - * set a description text that appears in the bottom right corner of the - * chart, size = Y-legend text size - * - * @param desc - */ - public void setDescription(String desc) { - if (desc == null) - desc = ""; - this.mDescription = desc; - } - /** * Sets the text that informs the user that there is no data available with * which to draw the chart. @@ -1218,15 +1244,6 @@ public float getPercentOfTotal(float val) { return val / mData.getYValueSum() * 100f; } - /** - * sets the typeface for the description paint - * - * @param t - */ - public void setDescriptionTypeface(Typeface t) { - mDescPaint.setTypeface(t); - } - /** * Returns the ViewPortHandler of the chart that is responsible for the * content area of the chart and its offsets and dimensions. @@ -1458,7 +1475,6 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } - /** * Setting this to true will set the layer-type HARDWARE for the view, false From bff61718198f839aa819c8769d4f71e755625b94 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 17 Apr 2015 10:10:27 +0200 Subject: [PATCH 0313/1390] Fixed issue concerning drawbitmap (issue #554). --- .../charting/renderer/LineChartRenderer.java | 31 ++++++++++++------- .../charting/renderer/PieChartRenderer.java | 16 +++++++--- 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 2ef28257f0..34c8e6968c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -31,7 +31,7 @@ public class LineChartRenderer extends DataRenderer { * Bitmap object used for drawing the paths (otherwise they are too long if * rendered directly on the canvas) */ - protected Bitmap mPathBitmap; + protected Bitmap mDrawBitmap; /** * on this canvas, the paths are rendered, it is initialized with the @@ -73,15 +73,21 @@ public void initBuffers() { @Override public void drawData(Canvas c) { - if (mPathBitmap == null - || (mPathBitmap.getWidth() != (int) mViewPortHandler.getChartWidth()) - || (mPathBitmap.getHeight() != (int) mViewPortHandler.getChartHeight())) { - mPathBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), - (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_4444); - mBitmapCanvas = new Canvas(mPathBitmap); + int width = (int) mViewPortHandler.getChartWidth(); + int height = (int) mViewPortHandler.getChartHeight(); + + if (mDrawBitmap == null + || (mDrawBitmap.getWidth() != width) + || (mDrawBitmap.getHeight() != height)) { + + if (width > 0 && height > 0) { + + mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mBitmapCanvas = new Canvas(mDrawBitmap); + } } - mPathBitmap.eraseColor(Color.TRANSPARENT); + mDrawBitmap.eraseColor(Color.TRANSPARENT); LineData lineData = mChart.getLineData(); @@ -91,7 +97,7 @@ public void drawData(Canvas c) { drawDataSet(c, set); } - c.drawBitmap(mPathBitmap, 0, 0, mRenderPaint); + c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, LineDataSet dataSet) { @@ -146,7 +152,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { int size = (int) Math.ceil((maxx - minx) * phaseX + minx); minx = Math.max(minx - 2, 0); // Decrement by 2 as we always render two - // extra points to keep cubic flowing + // extra points to keep cubic flowing size = Math.min(size + 2, entries.size()); // Increment by 2 as we // always render two extra // points to keep cubic @@ -200,7 +206,8 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cur = entries.get(entries.size() - 1); prev = entries.get(entries.size() - 2); - prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3 : entries.size() - 2); + prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3 + : entries.size() - 2); next = cur; prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; @@ -242,7 +249,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), mChart.getYChartMin()); - spline.lineTo(to-1, fillMin); + spline.lineTo(to - 1, fillMin); spline.lineTo(from, fillMin); spline.close(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 6efe532537..778d6854cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -87,12 +87,18 @@ public void initBuffers() { @Override public void drawData(Canvas c) { + int width = (int) mViewPortHandler.getChartWidth(); + int height = (int) mViewPortHandler.getChartHeight(); + if (mDrawBitmap == null - || (mDrawBitmap.getWidth() != (int) mViewPortHandler.getChartWidth()) - || (mDrawBitmap.getHeight() != (int) mViewPortHandler.getChartHeight())) { - mDrawBitmap = Bitmap.createBitmap((int) mViewPortHandler.getChartWidth(), - (int) mViewPortHandler.getChartHeight(), Bitmap.Config.ARGB_8888); - mBitmapCanvas = new Canvas(mDrawBitmap); + || (mDrawBitmap.getWidth() != width) + || (mDrawBitmap.getHeight() != height)) { + + if (width > 0 && height > 0) { + + mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mBitmapCanvas = new Canvas(mDrawBitmap); + } } // Paint p = new Paint(); From 497bc296cfa1db330da0a3ded65c83236b4d8c36 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 17 Apr 2015 10:12:54 +0200 Subject: [PATCH 0314/1390] Additional fix. --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 3 ++- .../github/mikephil/charting/renderer/PieChartRenderer.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 34c8e6968c..751d1a57e4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -84,7 +84,8 @@ public void drawData(Canvas c) { mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mDrawBitmap); - } + } else + return; } mDrawBitmap.eraseColor(Color.TRANSPARENT); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 778d6854cb..6b4386ccf0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -98,7 +98,8 @@ public void drawData(Canvas c) { mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); mBitmapCanvas = new Canvas(mDrawBitmap); - } + } else + return; } // Paint p = new Paint(); From e249a15c58a69985557c190bbeff1c2da0ab8344 Mon Sep 17 00:00:00 2001 From: mesrop_davoyan Date: Fri, 17 Apr 2015 13:23:16 +0400 Subject: [PATCH 0315/1390] - fix cubic fill bug for the LineChart --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 751d1a57e4..7e3ecd8294 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -229,7 +229,8 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, minx, size); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, + entryFrom.getXIndex(), entryFrom.getXIndex() + size); } mRenderPaint.setColor(dataSet.getColor()); From 5b6ab3cf325693c40e3514ff194e9d1dae07fe68 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 17 Apr 2015 19:52:55 +0200 Subject: [PATCH 0316/1390] Fixed issue that caused candle-body not to be drawn. --- .../com/github/mikephil/charting/data/CandleEntry.java | 4 ++-- .../charting/renderer/CandleStickChartRenderer.java | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java index e65be942da..00740171ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java @@ -26,8 +26,8 @@ public class CandleEntry extends Entry { * @param xIndex The index on the x-axis. * @param shadowH The (shadow) high value. * @param shadowL The (shadow) low value. - * @param open - * @param close + * @param open The open value. + * @param close The close value. */ public CandleEntry(int xIndex, float shadowH, float shadowL, float open, float close) { super((shadowH + shadowL) / 2f, xIndex); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index fb5da745b8..bae707b416 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import com.github.mikephil.charting.animation.ChartAnimator; @@ -137,7 +138,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { // draw the body c.drawRect(leftBody, close, rightBody, open, mRenderPaint); - } else { + } else if(open < close) { if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) { mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); @@ -148,6 +149,11 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle()); // draw the body c.drawRect(leftBody, open, rightBody, close, mRenderPaint); + } else { // equal values + + mRenderPaint.setColor(Color.BLACK); + mRenderPaint.setStyle(Paint.Style.STROKE); + c.drawLine(leftBody, open, rightBody, close, mRenderPaint); } } } From 52d58c7098e4b059fa9a79927926837c5b72ad70 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 20 Apr 2015 11:59:20 +0200 Subject: [PATCH 0317/1390] Now highlighting values via drag gesture is possible (issue #567, #106). --- .../mpchartexample/LineChartActivity2.java | 1 + .../charting/charts/BarLineChartBase.java | 42 ++++++++++++----- .../mikephil/charting/charts/Chart.java | 2 +- .../listener/BarLineChartTouchListener.java | 46 ++++++++++--------- 4 files changed, 57 insertions(+), 34 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 7d77dee103..03d0753a11 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -75,6 +75,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); mChart.setDrawGridBackground(false); + mChart.setHighlightPerDragEnabled(true); // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 2cc2637357..597b68310f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -61,9 +61,21 @@ public abstract class BarLineChartBase= 2) { - + OnChartGestureListener l = mChart.getOnChartGestureListener(); // get the distance between the pointers of the touch @@ -256,12 +258,12 @@ private void performZoom(MotionEvent event) { float scale = totalDist / mSavedDist; // total // scale - + float scaleX = (mChart.isScaleXEnabled()) ? scale : 1f; float scaleY = (mChart.isScaleYEnabled()) ? scale : 1f; mMatrix.set(mSavedMatrix); - mMatrix.postScale(scaleX, scaleY, t.x, t.y); + mMatrix.postScale(scaleX, scaleY, t.x, t.y); if (l != null) l.onChartScale(event, scaleX, scaleY); @@ -274,7 +276,7 @@ private void performZoom(MotionEvent event) { mMatrix.set(mSavedMatrix); mMatrix.postScale(scaleX, 1f, t.x, t.y); - + if (l != null) l.onChartScale(event, scaleX, 1f); @@ -288,7 +290,7 @@ private void performZoom(MotionEvent event) { // y-axis comes from top to bottom, revert y mMatrix.postScale(1f, scaleY, t.x, t.y); - + if (l != null) l.onChartScale(event, 1f, scaleY); } @@ -315,7 +317,7 @@ private void performHighlight(MotionEvent e) { } /** - * Highlights upon dragging. + * Highlights upon dragging, generates callbacks for the selection-listener. * * @param e */ From 3d9d2927368275b6bcdb8f221bf2a37452410a17 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Apr 2015 03:34:17 +0300 Subject: [PATCH 0318/1390] Sync cubic line drawing to animation --- .../charting/renderer/LineChartRenderer.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 7e3ecd8294..5de4449202 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -152,12 +152,6 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { int size = (int) Math.ceil((maxx - minx) * phaseX + minx); - minx = Math.max(minx - 2, 0); // Decrement by 2 as we always render two - // extra points to keep cubic flowing - size = Math.min(size + 2, entries.size()); // Increment by 2 as we - // always render two extra - // points to keep cubic - // flowing if (size - minx >= 2) { float prevDx = 0f; @@ -177,7 +171,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { prevDy = (next.getVal() - cur.getVal()) * intensity; cur = entries.get(minx + 1); - next = entries.get(minx + (size - minx > 2 ? 2 : 1)); + next = entries.get(minx + (entries.size() - minx > 2 ? 2 : 1)); curDx = (next.getXIndex() - prev.getXIndex()) * intensity; curDy = (next.getVal() - prev.getVal()) * intensity; @@ -186,7 +180,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); - for (int j = minx + 2; j < size - 1; j++) { + for (int j = minx + 2, count = Math.min(size, entries.size() - 1); j < count; j++) { prevPrev = entries.get(j - 2); prev = entries.get(j - 1); @@ -205,10 +199,10 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { if (size > entries.size() - 1) { - cur = entries.get(entries.size() - 1); - prev = entries.get(entries.size() - 2); prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3 : entries.size() - 2); + prev = entries.get(entries.size() - 2); + cur = entries.get(entries.size() - 1); next = cur; prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; From e9f8ae63857ddece697de99ddf0533dad2638268 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Apr 2015 03:50:21 +0300 Subject: [PATCH 0319/1390] Consider yOffsest when rendering pie-chart legend --- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 377813eaa1..61263bf3be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -307,7 +307,7 @@ public void renderLegend(Canvas c) { case PIECHART_CENTER: posX = mViewPortHandler.getChartWidth() / 2f + (direction == Legend.LegendDirection.LEFT_TO_RIGHT ? -mLegend.mTextWidthMax / 2f : mLegend.mTextWidthMax / 2f); - posY = mViewPortHandler.getChartHeight() / 2f - mLegend.mNeededHeight / 2f; + posY = mViewPortHandler.getChartHeight() / 2f - mLegend.mNeededHeight / 2f + mLegend.getYOffset(); for (int i = 0; i < labels.length; i++) { From d86a5cbcb2517b202792d1a2e76a699db133bc58 Mon Sep 17 00:00:00 2001 From: Alexander Martinz Date: Sat, 25 Apr 2015 17:47:47 +0200 Subject: [PATCH 0320/1390] Readme: add notice about Proguard * When using proguard and NOT whitelisting MPAndroidChart, some functionality will break like animate methods. Change-Id: If329842301eb41f7f713c1148b5ca364917e3d7a Signed-off-by: Alexander Martinz --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index ab3c27a398..ae0cb15a55 100644 --- a/README.md +++ b/README.md @@ -166,6 +166,15 @@ dependencies { - Import the library folder (`MPChartLib`) into your Eclipse workspace - Add it as a reference to your project: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) +Proguard +======= + +In case you are using Proguard, you will need to whitelist MPAndroidChart, which requires to add the following line to your Proguard configuration file. + +``` +-keep class com.github.mikephil.charting.** { *; } +``` + Documentation ======= For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). From 674cd8b9754ec8a11982369167edf4eca670544e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 00:05:07 +0200 Subject: [PATCH 0321/1390] Major bugfixes, fixed issue concerning x-axis labels jumping. --- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 2 +- .../mikephil/charting/charts/BarChart.java | 41 +++++++++++++++++++ .../charting/charts/BarLineChartBase.java | 20 +++------ .../charting/charts/HorizontalBarChart.java | 40 ++++++++++++++++++ .../BarLineScatterCandleDataProvider.java | 3 ++ .../charting/renderer/BarChartRenderer.java | 1 - .../renderer/CandleStickChartRenderer.java | 3 +- .../renderer/CombinedChartRenderer.java | 7 ++++ .../charting/renderer/DataRenderer.java | 6 +++ .../renderer/HorizontalBarChartRenderer.java | 1 - .../charting/renderer/LineChartRenderer.java | 4 +- .../mikephil/charting/renderer/Renderer.java | 33 ++++++++++----- .../renderer/ScatterChartRenderer.java | 1 - .../charting/renderer/XAxisRenderer.java | 13 +----- .../renderer/XAxisRendererBarChart.java | 18 +------- .../XAxisRendererHorizontalBarChart.java | 4 +- 17 files changed, 133 insertions(+), 66 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 7f086e063b..edf6073c2c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -189,7 +189,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add((i + 1990) + ""); + xVals.add((i) + ""); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 2ea81d1745..363e5e0763 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -48,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { // draw bars behind lines mChart.setDrawOrder(new DrawOrder[] { - DrawOrder.BAR, DrawOrder.LINE + DrawOrder.BAR, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); YAxis rightAxis = mChart.getAxisRight(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 8c580b9665..d890f42557 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -6,6 +6,7 @@ import android.util.AttributeSet; import android.util.Log; +import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -325,4 +326,44 @@ public boolean isDrawBarShadowEnabled() { public BarData getBarData() { return mData; } + + /** + * Returns the lowest x-index (value on the x-axis) that is still visible on + * the chart. + * + * @return + */ + @Override + public int getLowestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { + mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() + }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) (((pts[0] <= 0) ? 0 : ((pts[0])) / div) + 1); + } + + /** + * Returns the highest x-index (value on the x-axis) that is still visible + * on the chart. + * + * @return + */ + @Override + public int getHighestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { + mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() + }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 597b68310f..5bfd529bee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -176,20 +176,11 @@ protected void onDraw(Canvas canvas) { long starttime = System.currentTimeMillis(); - // // if data filtering is enabled - // if (mFilterData) { - // mData = getFilteredData(); - // - // Log.i(LOG_TAG, "FilterTime: " + (System.currentTimeMillis() - - // starttime) + " ms"); - // starttime = System.currentTimeMillis(); - // } else { - // mData = getData(); - // // Log.i(LOG_TAG, "Filtering disabled."); - // } - if (mXAxis.isAdjustXLabelsEnabled()) calcModulus(); + + mXAxisRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); + mRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); // execute all drawing commands drawGridBackground(canvas); @@ -248,14 +239,11 @@ protected void onDraw(Canvas canvas) { mRenderer.drawValues(canvas); mLegendRenderer.renderLegend(canvas); - // drawLegend(); drawMarkers(canvas); drawDescription(canvas); - // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); - if (mLogEnabled) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; @@ -1167,6 +1155,7 @@ public BarLineScatterCandleDataSet getDataSetByTouchPoint(float * * @return */ + @Override public int getLowestVisibleXIndex() { float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() @@ -1181,6 +1170,7 @@ public int getLowestVisibleXIndex() { * * @return */ + @Override public int getHighestVisibleXIndex() { float[] pts = new float[] { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 61d05707dd..791a2b82d8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -222,4 +222,44 @@ public Highlight getHighlightByTouchPoint(float x, float y) { return getHighlight(pts[1], pts[0]); } + + /** + * Returns the lowest x-index (value on the x-axis) that is still visible on + * the chart. + * + * @return + */ + @Override + public int getLowestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { + mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() + }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); + } + + /** + * Returns the highest x-index (value on the x-axis) that is still visible + * on the chart. + * + * @return + */ + @Override + public int getHighestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { + mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() + }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java index e2172308ff..368f87c1ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java @@ -8,4 +8,7 @@ public interface BarLineScatterCandleDataProvider extends ChartInterface { public Transformer getTransformer(AxisDependency axis); public int getMaxVisibleCount(); public boolean isInverted(AxisDependency axis); + + public int getLowestVisibleXIndex(); + public int getHighestVisibleXIndex(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 90ac689545..d06fb15223 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -79,7 +79,6 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - calcXBounds(trans); mShadowPaint.setColor(dataSet.getBarShadowColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index bae707b416..0117d24020 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -62,7 +62,6 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, CandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - calcXBounds(trans); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -288,7 +287,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { }; float[] horPts = new float[] { - 0, low, mChart.getXChartMax(), low, 0, high, mChart.getXChartMax(), high + mChart.getXChartMin(), low, mChart.getXChartMax(), low, mChart.getXChartMin(), high, mChart.getXChartMax(), high }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(vertPts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 71a526b747..649d75d52a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -6,6 +6,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -100,6 +101,12 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { renderer.drawHighlighted(c, indices); } + @Override + public void calcXBounds(BarLineScatterCandleDataProvider chart, int xAxisModulus) { + for (DataRenderer renderer : mRenderers) + renderer.calcXBounds(chart, xAxisModulus); + } + /** * Returns the sub-renderer object at the specified index. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 6f44acb617..68a9615005 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -15,6 +15,7 @@ public abstract class DataRenderer extends Renderer { + /** the animator object used to perform animations on the chart data */ protected ChartAnimator mAnimator; /** main paint object used for rendering */ @@ -93,6 +94,11 @@ protected void applyValueTextStyle(DataSet set) { mValuePaint.setTextSize(set.getValueTextSize()); } + /** + * Initializes the buffers used for rendering with a new size. Since this + * method performs memory allocations, it should only be called if + * necessary. + */ public abstract void initBuffers(); public abstract void drawData(Canvas c); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 9443811e30..81242a6438 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -51,7 +51,6 @@ public void initBuffers() { protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - calcXBounds(trans); mShadowPaint.setColor(dataSet.getBarShadowColor()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5de4449202..708113e67a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -108,8 +108,6 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { if (entries.size() < 1) return; - calcXBounds(mChart.getTransformer(dataSet.getAxisDependency())); - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); @@ -558,7 +556,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // y-position float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, mChart.getXChartMax(), y }; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index 4e1cd462f9..6ea83adc52 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.renderer; -import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -16,8 +16,10 @@ public abstract class Renderer { */ protected ViewPortHandler mViewPortHandler; + /** the minimum value on the x-axis that should be plotted */ protected int mMinX = 0; + /** the maximum value on the x-axis that should be plotted */ protected int mMaxX = 0; public Renderer(ViewPortHandler viewPortHandler) { @@ -45,16 +47,25 @@ protected boolean fitsBounds(float val, float min, float max) { * Calculates the minimum and maximum x-value the chart can currently * display (with the given zoom level). * - * @param trans + * @param chart + * @param modulus */ - protected void calcXBounds(Transformer trans) { - - double minx = trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; - double maxx = trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; - - if (!Double.isInfinite(minx)) - mMinX = (int) minx; - if (!Double.isInfinite(maxx)) - mMaxX = (int) Math.ceil(maxx); + public void calcXBounds(BarLineScatterCandleDataProvider chart, int xAxisModulus) { + + int low = chart.getLowestVisibleXIndex(); + int high = chart.getHighestVisibleXIndex(); + + int subLow = (low % xAxisModulus == 0) ? xAxisModulus : 0; + + mMinX = Math.max((low / xAxisModulus) * (xAxisModulus) - subLow, 0); + mMaxX = Math.min((high / xAxisModulus) * (xAxisModulus) + xAxisModulus, (int) chart.getXChartMax()); + +// double minx = trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; +// double maxx = trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; +// +// if (!Double.isInfinite(minx)) +// mMinX = (int) minx; +// if (!Double.isInfinite(maxx)) +// mMaxX = (int) Math.ceil(maxx); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 4701738f2e..e40c8560e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -61,7 +61,6 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - calcXBounds(trans); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 02c5e34183..426abd7c78 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -86,8 +86,6 @@ public void renderAxisLabels(Canvas c) { @Override public void renderAxisLine(Canvas c) { - - calcXBounds(mTrans); if (!mXAxis.isDrawAxisLineEnabled() || !mXAxis.isEnabled()) return; @@ -124,16 +122,7 @@ protected void drawLabels(Canvas c, float pos) { 0f, 0f }; - int maxx = mMaxX; - int minx = mMinX; - - if (maxx >= mXAxis.getValues().size()) - maxx = mXAxis.getValues().size()-1; - - if (minx < 0) - minx = 0; - - for (int i = minx; i <= maxx; i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[0] = i; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index f9fc0cd32b..fb792687d4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -36,14 +36,8 @@ protected void drawLabels(Canvas c, float pos) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - float div = (float) step + (step > 1 ? bd.getGroupSpace() : 0f); - float min = (float) mMinX - / div; - float max = (float) mMaxX - / div; - - for (int i = (int) min; i <= max; i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; @@ -88,8 +82,6 @@ protected void drawLabels(Canvas c, float pos) { @Override public void renderGridLines(Canvas c) { - calcXBounds(mTrans); - if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; @@ -102,14 +94,8 @@ public void renderGridLines(Canvas c) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - float div = (float) step + (step > 1 ? bd.getGroupSpace() : 0f); - - float min = (float) mMinX - / div; - float max = (float) mMaxX - / div; - for (int i = (int) min; i <= max; i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i < mMaxX; i += mXAxis.mAxisLabelModulus) { position[0] = i * step + i * bd.getGroupSpace() - 0.5f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 2096f645c3..dc6a52ec6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -91,7 +91,7 @@ protected void drawLabels(Canvas c, float pos) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[1] = i * step + i * bd.getGroupSpace() + bd.getGroupSpace() / 2f; @@ -129,7 +129,7 @@ public void renderGridLines(Canvas c) { // take into consideration that multiple DataSets increase mDeltaX int step = bd.getDataSetCount(); - for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[1] = i * step + i * bd.getGroupSpace() - 0.5f; From 9e100286f98d8e0774f3f1013251089b37c67311 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 13:07:51 +0200 Subject: [PATCH 0322/1390] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ae0cb15a55..f1d3781c5b 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,10 @@ Donations -Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) -Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). + Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + + Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). Demo ----- From 24ad450813bbcb4d8b399b166f451b5544c0dd38 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 13:08:32 +0200 Subject: [PATCH 0323/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1d3781c5b..11a2d2b2de 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Donations - Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + Follow me on Twitter: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). From f887144e00a5ae82faf514a0ac79363be85b5894 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 13:08:58 +0200 Subject: [PATCH 0324/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11a2d2b2de..77f65ea37d 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Donations - Follow me on Twitter: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + Follow me on **Twitter**: [**PhilippJahoda**](https://twitter.com/PhilippJahoda) Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). From 1a7413f5506e8dbcb9d138ee4c4a88f4d909c598 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 30 Apr 2015 19:30:33 +0300 Subject: [PATCH 0325/1390] Allow custom axis label modulus --- .../mikephil/charting/charts/BarLineChartBase.java | 14 +++++++++----- .../github/mikephil/charting/components/XAxis.java | 7 +++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 5bfd529bee..764f7fa8d7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -447,12 +447,16 @@ protected void calcModulus() { if (mXAxis == null) return; - float[] values = new float[9]; - mViewPortHandler.getMatrixTouch().getValues(values); + if (!mXAxis.axisLabelModulusCustom) { - mXAxis.mAxisLabelModulus = (int) Math - .ceil((mData.getXValCount() * mXAxis.mLabelWidth) - / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); + float[] values = new float[9]; + mViewPortHandler.getMatrixTouch().getValues(values); + + mXAxis.mAxisLabelModulus = (int) Math + .ceil((mData.getXValCount() * mXAxis.mLabelWidth) + / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); + + } if (mLogEnabled) Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + ", x-axis label width: " diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 0abb2df683..8a8bd882ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -41,6 +41,13 @@ public class XAxis extends AxisBase { */ public int mAxisLabelModulus = 1; + /** + * is axisLabelModulus a custom value or auto calculated? + * If false, then it's auto, if true, then custom. + * default: false (automatic modulus) + */ + public boolean axisLabelModulusCustom = false; + /** * the modulus that indicates if a value at a specified index in an * array(list) for the y-axis-labels is drawn or not. If index % modulus == From 24a3b1cdefb530046bc93ef497cae0628c7b25d5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 19:47:51 +0200 Subject: [PATCH 0326/1390] Enhanced possibility to set the number of x-labels to be skipped upon drawing. --- .../mpchartexample/AnotherBarActivity.java | 11 --- .../mpchartexample/BarChartActivity.java | 11 --- .../BarChartActivityMultiDataset.java | 13 +-- .../mpchartexample/BarChartActivitySinus.java | 11 --- .../CandleStickChartActivity.java | 11 --- .../CubicLineChartActivity.java | 11 --- .../mpchartexample/DrawChartActivity.java | 11 --- .../HorizontalBarChartActivity.java | 11 --- .../InvertedLineChartActivity.java | 11 --- .../mpchartexample/LineChartActivity1.java | 12 --- .../mpchartexample/LineChartActivity2.java | 11 --- .../MultiLineChartActivity.java | 12 --- .../mpchartexample/ScatterChartActivity.java | 11 --- .../mpchartexample/StackedBarActivity.java | 11 --- .../charting/charts/BarLineChartBase.java | 9 +-- .../mikephil/charting/components/XAxis.java | 81 +++++++++++-------- .../mikephil/charting/components/YAxis.java | 6 +- 17 files changed, 54 insertions(+), 200 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index e15f57b7e2..cf6fbe9070 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -135,17 +135,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xAxis = mChart.getXAxis(); - - if (xAxis.isAdjustXLabelsEnabled()) - xAxis.setAdjustXLabels(false); - else - xAxis.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 97cd372d82..fbf1edb7ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -189,17 +189,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index edf6073c2c..d994831bb4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -148,17 +148,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xAxis = mChart.getXAxis(); - - if (xAxis.isAdjustXLabelsEnabled()) - xAxis.setAdjustXLabels(false); - else - xAxis.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); @@ -189,7 +178,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add((i) + ""); + xVals.add((i+1990) + ""); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 7e77bb94dc..da02dee99b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -174,17 +174,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(2000, 2000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 823a75ee69..3dc3faf480 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -123,17 +123,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xAxis = mChart.getXAxis(); - - if (xAxis.isAdjustXLabelsEnabled()) - xAxis.setAdjustXLabels(false); - else - xAxis.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 2572150690..4714b37895 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -190,17 +190,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { // the angle of filtering is 35° diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 3d47cfffca..021eb60ca5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -132,17 +132,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index d6c7f348c2..77db08da4a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -183,17 +183,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 3b9a98b375..7555cf7180 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -198,17 +198,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { // the angle of filtering is 35° diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f4d238d2ff..62cf4c11df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -19,7 +19,6 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; -import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -252,17 +251,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { // the angle of filtering is 35° diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 03d0753a11..9a31bbfc42 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -216,17 +216,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { // the angle of filtering is 35° diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index fafc9506eb..928ee21e09 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -156,17 +155,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index d117a97f53..f2a03502d7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -131,17 +131,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index b8f22ca098..a0be9f34d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -150,17 +150,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleAdjustXLegend: { - XAxis xLabels = mChart.getXAxis(); - - if (xLabels.isAdjustXLabelsEnabled()) - xLabels.setAdjustXLabels(false); - else - xLabels.setAdjustXLabels(true); - - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 764f7fa8d7..42e8baffb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -176,9 +176,8 @@ protected void onDraw(Canvas canvas) { long starttime = System.currentTimeMillis(); - if (mXAxis.isAdjustXLabelsEnabled()) - calcModulus(); - + calcModulus(); + mXAxisRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); mRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); @@ -444,10 +443,10 @@ protected void calculateOffsets() { */ protected void calcModulus() { - if (mXAxis == null) + if (mXAxis == null || !mXAxis.isEnabled()) return; - if (!mXAxis.axisLabelModulusCustom) { + if (!mXAxis.isAxisModulusCustom()) { float[] values = new float[9]; mViewPortHandler.getMatrixTouch().getValues(values); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 8a8bd882ff..1e03100fbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -42,11 +42,10 @@ public class XAxis extends AxisBase { public int mAxisLabelModulus = 1; /** - * is axisLabelModulus a custom value or auto calculated? - * If false, then it's auto, if true, then custom. - * default: false (automatic modulus) + * Is axisLabelModulus a custom value or auto calculated? If false, then + * it's auto, if true, then custom. default: false (automatic modulus) */ - public boolean axisLabelModulusCustom = false; + private boolean mIsAxisModulusCustom = false; /** * the modulus that indicates if a value at a specified index in an @@ -61,12 +60,6 @@ public class XAxis extends AxisBase { */ private boolean mAvoidFirstLastClipping = false; - /** - * if set to true, the x-axis label entries will adjust themselves when - * scaling the graph - */ - protected boolean mAdjustXAxisLabels = true; - /** the position of the x-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; @@ -74,31 +67,11 @@ public class XAxis extends AxisBase { public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } - + public XAxis() { super(); } - /** - * if set to true, the x-label entries will adjust themselves when scaling - * the graph default: true - * - * @param enabled - */ - public void setAdjustXLabels(boolean enabled) { - mAdjustXAxisLabels = enabled; - } - - /** - * returns true if the x-labels adjust themselves when scaling the graph, - * false if not - * - * @return - */ - public boolean isAdjustXLabelsEnabled() { - return mAdjustXAxisLabels; - } - /** * returns the position of the x-labels */ @@ -117,12 +90,50 @@ public void setPosition(XAxisPosition pos) { /** * Sets the space (in characters) that should be left out between the x-axis - * labels, default 4 + * labels, default 4. This only applies if the number of labels that will be + * skipped in between drawn axis labels is not custom set. * * @param space */ - public void setSpaceBetweenLabels(int space) { - mSpaceBetweenLabels = space; + public void setSpaceBetweenLabels(int spaceCharacters) { + mSpaceBetweenLabels = spaceCharacters; + } + + /** + * Sets the number of labels that should be skipped on the axis before the + * next label is drawn. This will disable the feature that automatically + * calculates an adequate space between the axis labels and set the number + * of labels to be skipped to the fixed number provided by this method. Call + * resetLabelsToSkip(...) to re-enable automatic calculation. + * + * @param count + */ + public void setLabelsToSkip(int count) { + + if (count < 0) + count = 0; + + mIsAxisModulusCustom = true; + mAxisLabelModulus = count + 1; + } + + /** + * Calling this will disable a custom number of labels to be skipped (set by + * setLabelsToSkip(...)) while drawing the x-axis. Instead, the number of + * values to skip will again be calculated automatically. + */ + public void resetLabelsToSkip() { + mIsAxisModulusCustom = false; + } + + /** + * Returns true if a custom axis-modulus has been set that determines the + * number of labels to skip when drawing. + * + * @return + */ + public boolean isAxisModulusCustom() { + return mIsAxisModulusCustom; } /** @@ -171,7 +182,7 @@ public void setValues(List values) { public List getValues() { return mValues; } - + @Override public String getLongestLabel() { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 3a17a7badc..85eb9327d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -141,7 +141,7 @@ public void setDrawTopYLabelEntry(boolean enabled) { } /** - * sets the number of label entries for the y-axis max = 15, min = 2, + * sets the number of label entries for the y-axis max = 25, min = 2, * default: 6, be aware that this number is not fixed and can only be * approximated * @@ -149,8 +149,8 @@ public void setDrawTopYLabelEntry(boolean enabled) { */ public void setLabelCount(int yCount) { - if (yCount > 15) - yCount = 15; + if (yCount > 25) + yCount = 25; if (yCount < 2) yCount = 2; From 9a2d5fcc8b94df1aa31fe95e2af1d5424ce92d7f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 00:13:43 +0300 Subject: [PATCH 0327/1390] Bubble chart implementation, ported from the iOS version :-) --- MPChartExample/AndroidManifest.xml | 1 + .../res/layout/activity_bubblechart.xml | 60 ++++ MPChartExample/res/menu/bubble.xml | 45 +++ .../mpchartexample/BubbleChartActivity.java | 258 ++++++++++++++++++ .../notimportant/MainActivity.java | 38 +-- .../mikephil/charting/charts/BubbleChart.java | 72 +++++ .../mikephil/charting/data/BubbleData.java | 41 +++ .../mikephil/charting/data/BubbleDataSet.java | 120 ++++++++ .../mikephil/charting/data/BubbleEntry.java | 66 +++++ .../interfaces/BubbleDataProvider.java | 9 + .../renderer/BubbleChartRenderer.java | 234 ++++++++++++++++ .../mikephil/charting/utils/Transformer.java | 29 ++ 12 files changed, 957 insertions(+), 16 deletions(-) create mode 100644 MPChartExample/res/layout/activity_bubblechart.xml create mode 100644 MPChartExample/res/menu/bubble.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 65b65facda..fba4e3d074 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -34,6 +34,7 @@ + diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/res/layout/activity_bubblechart.xml new file mode 100644 index 0000000000..ca0ce6d4cb --- /dev/null +++ b/MPChartExample/res/layout/activity_bubblechart.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/res/menu/bubble.xml new file mode 100644 index 0000000000..3020bdb786 --- /dev/null +++ b/MPChartExample/res/menu/bubble.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java new file mode 100644 index 0000000000..e6461b54b2 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -0,0 +1,258 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.charts.BubbleChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class BubbleChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private BubbleChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + private Typeface tf; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_bubblechart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX.setOnSeekBarChangeListener(this); + + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY.setOnSeekBarChangeListener(this); + + mChart = (BubbleChart) findViewById(R.id.chart1); + mChart.setDescription(""); + + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + mChart.setOnChartValueSelectedListener(this); + + mChart.setDrawGridBackground(false); + + mChart.setTouchEnabled(true); + mChart.setHighlightEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + mChart.setMaxVisibleValueCount(200); + mChart.setPinchZoom(true); + + mChart.getAxisLeft().setStartAtZero(false); + mChart.getAxisRight().setStartAtZero(false); + + mSeekBarX.setProgress(5); + mSeekBarY.setProgress(50); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setTypeface(tf); + + YAxis yl = mChart.getAxisLeft(); + yl.setTypeface(tf); + + mChart.getAxisRight().setEnabled(false); + + XAxis xl = mChart.getXAxis(); + xl.setPosition(XAxis.XAxisPosition.BOTTOM); + xl.setTypeface(tf); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bubble, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.invalidate(); + break; + } + case R.id.actionToggleFilter: { + + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + // mChart.saveToGallery("title"+System.currentTimeMillis()); + mChart.saveToPath("title" + System.currentTimeMillis(), ""); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + int count = mSeekBarX.getProgress() + 1; + int range = mSeekBarY.getProgress(); + + tvX.setText("" + count); + tvY.setText("" + range); + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add((i) + ""); + } + + ArrayList yVals1 = new ArrayList(); + ArrayList yVals2 = new ArrayList(); + ArrayList yVals3 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + float size = (float) (Math.random() * range); + + yVals1.add(new BubbleEntry(i, val, size)); + } + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + float size = (float) (Math.random() * range); + + yVals2.add(new BubbleEntry(i, val, size)); + } + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + float size = (float) (Math.random() * range); + + yVals3.add(new BubbleEntry(i, val, size)); + } + + // create a dataset and give it a type + BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1"); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); + set1.setDrawValues(true); + BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2"); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); + set2.setDrawValues(false); + BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3"); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); + set3.setDrawValues(false); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); // add the datasets + dataSets.add(set2); + dataSets.add(set3); + + // create a data object with the datasets + BubbleData data = new BubbleData(xVals, dataSets); + data.setValueTypeface(tf); + + mChart.setData(data); + mChart.invalidate(); + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + Log.i("VAL SELECTED", + "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + + ", DataSet index: " + dataSetIndex); + } + + @Override + public void onNothingSelected() { + // TODO Auto-generated method stub + + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index eedb521a43..2d88c88b04 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -24,6 +24,7 @@ import com.xxmassdeveloper.mpchartexample.BarChartActivity; import com.xxmassdeveloper.mpchartexample.BarChartActivityMultiDataset; import com.xxmassdeveloper.mpchartexample.BarChartActivitySinus; +import com.xxmassdeveloper.mpchartexample.BubbleChartActivity; import com.xxmassdeveloper.mpchartexample.CandleStickChartActivity; import com.xxmassdeveloper.mpchartexample.CombinedChartActivity; import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; @@ -72,6 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { "Demonstrates how to create a combined chart (bar and line in this case).")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); + objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); objects.add(new ContentItem("Stacked Bar Chart", "A simple demonstration of a bar chart with stacked bars.")); objects.add(new ContentItem("Another Bar Chart", @@ -162,22 +164,26 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 7: - i = new Intent(this, StackedBarActivity.class); + i = new Intent(this, BubbleChartActivity.class); startActivity(i); break; case 8: - i = new Intent(this, AnotherBarActivity.class); + i = new Intent(this, StackedBarActivity.class); startActivity(i); break; case 9: - i = new Intent(this, MultiLineChartActivity.class); + i = new Intent(this, AnotherBarActivity.class); startActivity(i); break; case 10: - i = new Intent(this, BarChartActivityMultiDataset.class); + i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; case 11: + i = new Intent(this, BarChartActivityMultiDataset.class); + startActivity(i); + break; + case 12: // i = new Intent(this, DrawChartActivity.class); // startActivity(i); @@ -187,51 +193,51 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { b.setPositiveButton("OK", null); b.create().show(); break; - case 12: + case 13: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 13: + case 14: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 14: + case 15: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 15: + case 16: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 16: + case 17: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 17: + case 18: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 18: + case 19: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 19: + case 20: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 20: + case 21: i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; - case 21: + case 22: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; - case 22: + case 23: i = new Intent(this, PerformanceLineChart.class); startActivity(i); break; - case 23: + case 24: i = new Intent(this, BarChartActivitySinus.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java new file mode 100644 index 0000000000..fb6cebe957 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -0,0 +1,72 @@ + +package com.github.mikephil.charting.charts; + +import android.content.Context; +import android.util.AttributeSet; + +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.interfaces.BubbleDataProvider; +import com.github.mikephil.charting.renderer.BubbleChartRenderer; + +/** + * The BubbleChart. Draws bubbles. + * + * Bubble chart implementation: + * Copyright 2015 Pierre-Marc Airoldi + * Licensed under Apache License 2.0 + * + * @author Philipp Jahoda + */ +public class BubbleChart extends BarLineChartBase implements BubbleDataProvider { + + public BubbleChart(Context context) { + super(context); + } + + public BubbleChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BubbleChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + mRenderer = new BubbleChartRenderer(this, mAnimator, mViewPortHandler); + } + + @Override + protected void calcMinMax() { + super.calcMinMax(); + + if (mDeltaX == 0 && mData.getYValCount() > 0) + mDeltaX = 1; + + mXChartMin = -0.5f; + mXChartMax = (float)mData.getXValCount() - 0.5f; + + if (mRenderer != null) { + for (BubbleDataSet set : mData.getDataSets()) { + + final float xmin = set.getXMin(); + final float xmax = set.getXMax(); + + if (xmin < mXChartMin) + mXChartMin = xmin; + + if (xmax > mXChartMax) + mXChartMax = xmax; + } + } + + mDeltaX = Math.abs(mXChartMax - mXChartMin); + } + + public BubbleData getBubbleData() { + return mData; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java new file mode 100644 index 0000000000..a2c6146bef --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -0,0 +1,41 @@ +package com.github.mikephil.charting.data; + +import java.util.ArrayList; +import java.util.List; + +public class BubbleData extends BarLineScatterCandleData { + + public BubbleData() { + super(); + } + + public BubbleData(List xVals) { + super(xVals); + } + + public BubbleData(String[] xVals) { + super(xVals); + } + + public BubbleData(List xVals, List dataSets) { + super(xVals, dataSets); + } + + public BubbleData(String[] xVals, List dataSets) { + super(xVals, dataSets); + } + + public BubbleData(List xVals, BubbleDataSet dataSet) { + super(xVals, toList(dataSet)); + } + + public BubbleData(String[] xVals, BubbleDataSet dataSet) { + super(xVals, toList(dataSet)); + } + + private static List toList(BubbleDataSet dataSet) { + List sets = new ArrayList(); + sets.add(dataSet); + return sets; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java new file mode 100644 index 0000000000..6b97411153 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -0,0 +1,120 @@ + +package com.github.mikephil.charting.data; + +import android.graphics.Color; + +import java.util.ArrayList; +import java.util.List; + +public class BubbleDataSet extends BarLineScatterCandleDataSet { + + // NOTE: Do not initialize these, as the calcMinMax is called by the super, + // and the initializers are called after that and can reset the values + protected float mXMax; + protected float mXMin; + protected float mMaxSize; + + public BubbleDataSet(List yVals, String label) { + super(yVals, label); + + if (mMaxSize < 1.f) + mMaxSize = 1.f; + } + + @Override + public void setColor(int color) { + super.setColor(Color.argb(127, Color.red(color), Color.green(color), Color.blue(color))); + } + + @Override + protected void calcMinMax() + { + final List entries = getYVals(); + + //need chart width to guess this properly + + for (BubbleEntry entry : entries) + { + final float ymin = yMin(entry); + final float ymax = yMax(entry); + + if (ymin < mYMin) + { + mYMin = ymin; + } + + if (ymax > mYMax) + { + mYMax = ymax; + } + + final float xmin = xMin(entry); + final float xmax = xMax(entry); + + if (xmin < mXMin) + { + mXMin = xmin; + } + + if (xmax > mXMax) + { + mXMax = xmax; + } + + final float size = largestSize(entry); + + if (size > mMaxSize) + { + mMaxSize = size; + } + } + } + + @Override + public DataSet copy() { + + List yVals = new ArrayList(); + + for (int i = 0; i < mYVals.size(); i++) { + yVals.add(mYVals.get(i).copy()); + } + + BubbleDataSet copied = new BubbleDataSet(yVals, getLabel()); + copied.mColors = mColors; + copied.mHighLightColor = mHighLightColor; + + return copied; + } + + public float getXMax() { + return mXMax; + } + + public float getXMin() { + return mXMin; + } + + public float getMaxSize() { + return mMaxSize; + } + + private float yMin(BubbleEntry entry) { + return entry.getVal(); + } + + private float yMax(BubbleEntry entry) { + return entry.getVal(); + } + + private float xMin(BubbleEntry entry) { + return (float)entry.getXIndex(); + } + + private float xMax(BubbleEntry entry) { + return (float)entry.getXIndex(); + } + + private float largestSize(BubbleEntry entry) { + return entry.getSize(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java new file mode 100644 index 0000000000..5a2e6f546d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java @@ -0,0 +1,66 @@ + +package com.github.mikephil.charting.data; + +/** + * Subclass of Entry that holds a value for one entry in a BubbleChart. + * + * Bubble chart implementation: + * Copyright 2015 Pierre-Marc Airoldi + * Licensed under Apache License 2.0 + * + * @author Philipp Jahoda + */ +public class BubbleEntry extends Entry { + + /** size value */ + private float mSize = 0f; + + /** + * Constructor. + * + * @param xIndex The index on the x-axis. + * @param val + * @param size The size value. + */ + public BubbleEntry(int xIndex, float val, float size) { + super(val, xIndex); + + this.mSize = size; + } + + /** + * Constructor. + * + * @param xIndex The index on the x-axis. + * @param val + * @param size The size value. + * @param data Spot for additional data this Entry represents. + */ + public BubbleEntry(int xIndex, float val, float size, Object data) { + super(val, xIndex, data); + + this.mSize = size; + } + + public BubbleEntry copy() { + + BubbleEntry c = new BubbleEntry(getXIndex(), getVal(), mSize, getData()); + + return c; + } + + + /** + * Returns the size of this entry + * + * @return + */ + public float getSize() { + return mSize; + } + + public void setSize(float size) { + this.mSize = size; + } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java new file mode 100644 index 0000000000..2161303e01 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.interfaces; + +import com.github.mikephil.charting.data.BubbleData; + +public interface BubbleDataProvider extends BarLineScatterCandleDataProvider { + + public BubbleData getBubbleData(); + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java new file mode 100644 index 0000000000..d621049e89 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -0,0 +1,234 @@ + +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint.Style; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.interfaces.BubbleDataProvider; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.util.List; + +/** + * Bubble chart implementation: + * Copyright 2015 Pierre-Marc Airoldi + * Licensed under Apache License 2.0 + * + * Ported by Daniel Cohen Gindi + */ +public class BubbleChartRenderer extends DataRenderer { + + protected BubbleDataProvider mChart; + + public BubbleChartRenderer(BubbleDataProvider chart, ChartAnimator animator, + ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + mChart = chart; + + mRenderPaint.setStyle(Style.FILL); + + mHighlightPaint.setStyle(Style.STROKE); + mHighlightPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + } + + @Override + public void initBuffers() + { + + } + + @Override + public void drawData(Canvas c) { + + BubbleData bubbleData = mChart.getBubbleData(); + + for (BubbleDataSet set : bubbleData.getDataSets()) { + + if (set.isVisible()) + drawDataSet(c, set); + } + } + + private float[] _pointBuffer = new float[2]; + + protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + BubbleData bubbleData = mChart.getBubbleData(); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + List entries = dataSet.getYVals(); + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); + int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + + final float chartSize = (mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX()) + <= (mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY()) ? + mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : + mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); + + final float bubbleSizeFactor = (float)(bubbleData.getXVals().size() > 0 ? bubbleData.getXVals().size() : 1); + + for (int j = minx; j < maxx; j++) { + + final BubbleEntry entry = entries.get(j); + + _pointBuffer[0] = (float)(entry.getXIndex() - minx) * phaseX + (float)minx; + _pointBuffer[1] = (float)(entry.getVal()) * phaseY; + trans.pointValuesToPixel(_pointBuffer); + + final float shapeSize = (chartSize / bubbleSizeFactor) * (float)(Math.sqrt(entry.getSize()/dataSet.getMaxSize())); + final float shapeHalf = shapeSize / 2.f; + + if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) + continue; + + final int color = dataSet.getColor(entry.getXIndex()); + + mRenderPaint.setColor(color); + c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mRenderPaint); + } + } + + @Override + public void drawValues(Canvas c) { + + BubbleData bubbleData = mChart.getBubbleData(); + if (bubbleData == null) + return; + + // if values are drawn + if (bubbleData.getYValCount() < (int)(Math.ceil((float)(mChart.getMaxVisibleCount()) * mViewPortHandler.getScaleX()))) + { + final List dataSets = bubbleData.getDataSets(); + + float lineHeight = -mValuePaint.ascent() + mValuePaint.descent(); + + for (BubbleDataSet dataSet : dataSets) { + + if (!dataSet.isDrawValuesEnabled()) + continue; + + final float phaseX = mAnimator.getPhaseX(); + final float phaseY = mAnimator.getPhaseY(); + + final float alpha = phaseX == 1 ? phaseY : phaseX; + int valueTextColor = dataSet.getValueTextColor(); + valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), Color.green(valueTextColor), Color.blue(valueTextColor)); + + mValuePaint.setColor(valueTextColor); + + final List entries = dataSet.getYVals(); + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + + int minx = dataSet.getEntryPosition(entryFrom); + int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); + + final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()).generateTransformedValuesBubble(entries, phaseX, phaseY, minx, maxx); + + for (int j = 0; j < positions.length; j += 2) { + + float x = positions[j]; + float y = positions[j + 1]; + + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) + { + continue; + } + + final BubbleEntry entry = entries.get(j / 2 + minx); + + final float val = entry.getSize(); + + c.drawText(dataSet.getValueFormatter().getFormattedValue(val), + x, + y + (0.5f * lineHeight), + mValuePaint); + } + } + } + + } + + @Override + public void drawExtras(Canvas c) { + } + + private float[] _hsvBuffer = new float[3]; + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + BubbleData bubbleData = mChart.getBubbleData(); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + final float chartSize = (mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX()) + <= (mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY()) ? + mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : + mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); + + final float bubbleSizeFactor = (float)(bubbleData.getXVals().size() > 0 ? bubbleData.getXVals().size() : 1); + + for (Highlight indice : indices) { + + BubbleDataSet dataSet = bubbleData.getDataSetByIndex(indice.getDataSetIndex()); + + if (dataSet == null) + continue; + + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + + int minx = dataSet.getEntryPosition(entryFrom); + int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); + + final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + _pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; + _pointBuffer[1] = (float) (entry.getVal()) * phaseY; + trans.pointValuesToPixel(_pointBuffer); + + final float shapeSize = (chartSize / bubbleSizeFactor) * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); + final float shapeHalf = shapeSize / 2.f; + + if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) + continue; + + if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) + continue; + + final int originalColor = dataSet.getColor(entry.getXIndex()); + + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor), _hsvBuffer); + _hsvBuffer[2] *= 0.5f; + final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + + mHighlightPaint.setColor(color); + c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mHighlightPaint); + } + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 4ff5e09878..349c76aae8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -117,6 +117,35 @@ public float[] generateTransformedValuesScatter(List entries, return valuePoints; } + + /** + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the BUBBLECHART. + * + * @param entries + * @return + */ + public float[] generateTransformedValuesBubble(List entries, + float phaseX, float phaseY, int from, int to) { + + final int count = (int)Math.ceil((to - from) * phaseX) * 2; + + float[] valuePoints = new float[count]; + + for (int j = 0; j < count; j += 2) { + + Entry e = entries.get(j / 2 + from); + + if (e != null) { + valuePoints[j] = (float)(e.getXIndex() - from) * phaseX + from; + valuePoints[j + 1] = e.getVal() * phaseY; + } + } + + pointValuesToPixel(valuePoints); + + return valuePoints; + } /** * Transforms an List of Entry into a float array containing the x and From 3e5d4e6e6ed206a2d1e412f06107facbff384dee Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 00:16:15 +0300 Subject: [PATCH 0328/1390] Safety checks --- .../charting/renderer/CandleStickChartRenderer.java | 4 ++-- .../mikephil/charting/renderer/LineChartRenderer.java | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 0117d24020..598cbae367 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -73,7 +73,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); int range = (maxx - minx) * 4; @@ -222,7 +222,7 @@ public void drawValues(Canvas c) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); float[] positions = trans.generateTransformedValuesCandle( diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 708113e67a..f73072b04d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -138,7 +138,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); float phaseX = mAnimator.getPhaseX(); @@ -289,7 +289,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); int range = (maxx - minx) * 4 - 4; @@ -431,10 +431,7 @@ public void drawValues(Canvas c) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); - if (minx < 0) - minx = 0; - + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); float[] positions = trans.generateTransformedValuesLine( @@ -490,7 +487,7 @@ protected void drawCircles(Canvas c) { Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); + int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); CircleBuffer buffer = mCircleBuffers[i]; From ce069c60c633cd6fe3440546f79d76d3b9b2b590 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 00:17:15 +0300 Subject: [PATCH 0329/1390] Prevent labels from drawing way out of bounds --- .../github/mikephil/charting/renderer/ScatterChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index e40c8560e7..3d279091f5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -229,7 +229,7 @@ public void drawValues(Canvas c) { break; // make sure the lines don't do shitty things outside bounds - if (j != 0 && (!mViewPortHandler.isInBoundsLeft(positions[j]) + if ((!mViewPortHandler.isInBoundsLeft(positions[j]) || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; From 872e121a9c17fabfa2b8bf57f0f61eea45da99fa Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Apr 2015 23:30:51 +0200 Subject: [PATCH 0330/1390] Minor bugfix concerning addXValue(). --- .../RealtimeLineChartActivity.java | 43 ++++++++++++++++--- .../charting/charts/BarLineChartBase.java | 4 +- .../mikephil/charting/data/ChartData.java | 2 + 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 3c0bf9cf6c..1cb994d822 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -82,15 +82,43 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTextColor(Color.WHITE); xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); + xl.setSpaceBetweenLabels(5); + xl.setEnabled(false); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setTextColor(Color.WHITE); - leftAxis.setAxisMaxValue(120f); + leftAxis.setAxisMaxValue(100f); + leftAxis.setAxisMinValue(0f); + leftAxis.setStartAtZero(false); leftAxis.setDrawGridLines(true); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); + +// new Thread(new Runnable() { +// +// @Override +// public void run() { +// for(int i = 0; i < 5000; i++) { +// +// runOnUiThread(new Runnable() { +// +// @Override +// public void run() { +// addEntry(); +// } +// }); +// +// try { +// Thread.sleep(35); +// } catch (InterruptedException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// } +// } +// }).start(); } @Override @@ -116,7 +144,7 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - private int year = 15; + private int year = 2015; private void addEntry() { @@ -135,17 +163,17 @@ private void addEntry() { // add a new x-value first data.addXValue(mMonths[data.getXValCount() % 12] + " " + (year + data.getXValCount() / 12)); - data.addEntry(new Entry((float) (Math.random() * 40) + 40f, set.getEntryCount()), 0); + data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); // let the chart know it's data has changed mChart.notifyDataSetChanged(); // limit the number of visible entries - mChart.setVisibleXRange(6); + mChart.setVisibleXRange(120); // mChart.setVisibleYRange(30, AxisDependency.LEFT); // move to the latest entry - mChart.moveViewToX(data.getXValCount() - 7); + mChart.moveViewToX(data.getXValCount() - 121); // this automatically refreshes the chart (calls invalidate()) // mChart.moveViewTo(data.getXValCount()-7, 55f, @@ -161,14 +189,15 @@ private LineDataSet createSet() { LineDataSet set = new LineDataSet(null, "Dynamic Data"); set.setAxisDependency(AxisDependency.LEFT); set.setColor(ColorTemplate.getHoloBlue()); - set.setCircleColor(ColorTemplate.getHoloBlue()); + set.setCircleColor(Color.WHITE); set.setLineWidth(2f); set.setCircleSize(4f); set.setFillAlpha(65); set.setFillColor(ColorTemplate.getHoloBlue()); set.setHighLightColor(Color.rgb(244, 117, 117)); set.setValueTextColor(Color.WHITE); - set.setValueTextSize(10f); + set.setValueTextSize(9f); + set.setDrawValues(false); return set; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 42e8baffb6..7750e7f67f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -174,9 +174,7 @@ protected void onDraw(Canvas canvas) { if (mDataNotSet) return; - long starttime = System.currentTimeMillis(); - - calcModulus(); + long starttime = System.currentTimeMillis();calcModulus(); mXAxisRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); mRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index e309f04a1a..cff3ae36d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -389,6 +389,8 @@ public List getXVals() { * @param xVal */ public void addXValue(String xVal) { + + mXValAverageLength = (mXValAverageLength + xVal.length()) / 2f; mXVals.add(xVal); } From fe9f904c351aa37b134e68add6560d48a3679c35 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 May 2015 00:00:09 +0200 Subject: [PATCH 0331/1390] Minor improvements to BubbleChart. --- .../res/layout/activity_bubblechart.xml | 2 +- .../mpchartexample/BubbleChartActivity.java | 6 +- .../mikephil/charting/data/BubbleData.java | 27 ++++++--- .../mikephil/charting/data/BubbleDataSet.java | 24 +++++++- .../renderer/BubbleChartRenderer.java | 56 ++++++++++--------- 5 files changed, 76 insertions(+), 39 deletions(-) diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/res/layout/activity_bubblechart.xml index ca0ce6d4cb..9d17307a4a 100644 --- a/MPChartExample/res/layout/activity_bubblechart.xml +++ b/MPChartExample/res/layout/activity_bubblechart.xml @@ -30,7 +30,7 @@ android:layout_marginBottom="35dp" android:layout_toLeftOf="@+id/tvXMax" android:layout_marginRight="5dp" - android:max="30" + android:max="100" android:paddingBottom="12dp" /> dataSets = new ArrayList(); dataSets.add(set1); // add the datasets @@ -226,6 +226,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a data object with the datasets BubbleData data = new BubbleData(xVals, dataSets); data.setValueTypeface(tf); + data.setValueTextSize(8f); + data.setHighLightCircleWidth(1.5f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index a2c6146bef..d835d098bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.data; import java.util.ArrayList; @@ -8,15 +9,15 @@ public class BubbleData extends BarLineScatterCandleData { public BubbleData() { super(); } - + public BubbleData(List xVals) { super(xVals); } - + public BubbleData(String[] xVals) { super(xVals); } - + public BubbleData(List xVals, List dataSets) { super(xVals, dataSets); } @@ -24,18 +25,30 @@ public BubbleData(List xVals, List dataSets) { public BubbleData(String[] xVals, List dataSets) { super(xVals, dataSets); } - + public BubbleData(List xVals, BubbleDataSet dataSet) { - super(xVals, toList(dataSet)); + super(xVals, toList(dataSet)); } - + public BubbleData(String[] xVals, BubbleDataSet dataSet) { super(xVals, toList(dataSet)); } - + private static List toList(BubbleDataSet dataSet) { List sets = new ArrayList(); sets.add(dataSet); return sets; } + + /** + * Sets the width of the circle that surrounds the bubble when highlighted + * for all DataSet objects this data object contains, in dp. + * + * @param width + */ + public void setHighLightCircleWidth(float width) { + for (BubbleDataSet set : mDataSets) { + set.setHighLightCircleWidth(width); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 6b97411153..ca458210a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -3,6 +3,8 @@ import android.graphics.Color; +import com.github.mikephil.charting.utils.Utils; + import java.util.ArrayList; import java.util.List; @@ -14,6 +16,8 @@ public class BubbleDataSet extends BarLineScatterCandleDataSet { protected float mXMin; protected float mMaxSize; + private float mHighlightCircleWidth = 2.5f; + public BubbleDataSet(List yVals, String label) { super(yVals, label); @@ -21,6 +25,20 @@ public BubbleDataSet(List yVals, String label) { mMaxSize = 1.f; } + /** + * Sets the width of the circle that surrounds the bubble when highlighted, + * in dp. + * + * @param width + */ + public void setHighLightCircleWidth(float width) { + mHighlightCircleWidth = Utils.convertDpToPixel(width); + } + + public float getHighLightCircleWidth() { + return mHighlightCircleWidth; + } + @Override public void setColor(int color) { super.setColor(Color.argb(127, Color.red(color), Color.green(color), Color.blue(color))); @@ -31,7 +49,7 @@ protected void calcMinMax() { final List entries = getYVals(); - //need chart width to guess this properly + // need chart width to guess this properly for (BubbleEntry entry : entries) { @@ -107,11 +125,11 @@ private float yMax(BubbleEntry entry) { } private float xMin(BubbleEntry entry) { - return (float)entry.getXIndex(); + return (float) entry.getXIndex(); } private float xMax(BubbleEntry entry) { - return (float)entry.getXIndex(); + return (float) entry.getXIndex(); } private float largestSize(BubbleEntry entry) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index d621049e89..5616c9e667 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -19,30 +19,26 @@ import java.util.List; /** - * Bubble chart implementation: - * Copyright 2015 Pierre-Marc Airoldi - * Licensed under Apache License 2.0 - * - * Ported by Daniel Cohen Gindi + * Bubble chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed + * under Apache License 2.0 Ported by Daniel Cohen Gindi */ public class BubbleChartRenderer extends DataRenderer { protected BubbleDataProvider mChart; public BubbleChartRenderer(BubbleDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; mRenderPaint.setStyle(Style.FILL); mHighlightPaint.setStyle(Style.STROKE); - mHighlightPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + mHighlightPaint.setStrokeWidth(Utils.convertDpToPixel(1.5f)); } @Override - public void initBuffers() - { + public void initBuffers() { } @@ -82,17 +78,19 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); - final float bubbleSizeFactor = (float)(bubbleData.getXVals().size() > 0 ? bubbleData.getXVals().size() : 1); + final float bubbleSizeFactor = (float) (bubbleData.getXVals().size() > 0 ? bubbleData + .getXVals().size() : 1); for (int j = minx; j < maxx; j++) { final BubbleEntry entry = entries.get(j); - _pointBuffer[0] = (float)(entry.getXIndex() - minx) * phaseX + (float)minx; - _pointBuffer[1] = (float)(entry.getVal()) * phaseY; + _pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; + _pointBuffer[1] = (float) (entry.getVal()) * phaseY; trans.pointValuesToPixel(_pointBuffer); - final float shapeSize = (chartSize / bubbleSizeFactor) * (float)(Math.sqrt(entry.getSize()/dataSet.getMaxSize())); + final float shapeSize = (chartSize / bubbleSizeFactor) + * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); final float shapeHalf = shapeSize / 2.f; if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) @@ -109,18 +107,20 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { public void drawValues(Canvas c) { BubbleData bubbleData = mChart.getBubbleData(); + if (bubbleData == null) return; // if values are drawn - if (bubbleData.getYValCount() < (int)(Math.ceil((float)(mChart.getMaxVisibleCount()) * mViewPortHandler.getScaleX()))) - { + if (bubbleData.getYValCount() < (int) (Math.ceil((float) (mChart.getMaxVisibleCount()) + * mViewPortHandler.getScaleX()))) { + final List dataSets = bubbleData.getDataSets(); - float lineHeight = -mValuePaint.ascent() + mValuePaint.descent(); + float lineHeight = Utils.calcTextHeight(mValuePaint, "1"); for (BubbleDataSet dataSet : dataSets) { - + if (!dataSet.isDrawValuesEnabled()) continue; @@ -129,7 +129,8 @@ public void drawValues(Canvas c) { final float alpha = phaseX == 1 ? phaseY : phaseX; int valueTextColor = dataSet.getValueTextColor(); - valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), Color.green(valueTextColor), Color.blue(valueTextColor)); + valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), + Color.green(valueTextColor), Color.blue(valueTextColor)); mValuePaint.setColor(valueTextColor); @@ -141,7 +142,8 @@ public void drawValues(Canvas c) { int minx = dataSet.getEntryPosition(entryFrom); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); - final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()).generateTransformedValuesBubble(entries, phaseX, phaseY, minx, maxx); + final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) + .generateTransformedValuesBubble(entries, phaseX, phaseY, minx, maxx); for (int j = 0; j < positions.length; j += 2) { @@ -151,10 +153,8 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsRight(x)) break; - if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) - { + if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; - } final BubbleEntry entry = entries.get(j / 2 + minx); @@ -167,7 +167,7 @@ public void drawValues(Canvas c) { } } } - + } @Override @@ -189,7 +189,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); - final float bubbleSizeFactor = (float)(bubbleData.getXVals().size() > 0 ? bubbleData.getXVals().size() : 1); + final float bubbleSizeFactor = (float) (bubbleData.getXVals().size() > 0 ? bubbleData + .getXVals().size() : 1); for (Highlight indice : indices) { @@ -212,7 +213,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { _pointBuffer[1] = (float) (entry.getVal()) * phaseY; trans.pointValuesToPixel(_pointBuffer); - final float shapeSize = (chartSize / bubbleSizeFactor) * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); + final float shapeSize = (chartSize / bubbleSizeFactor) + * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); final float shapeHalf = shapeSize / 2.f; if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) @@ -223,11 +225,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final int originalColor = dataSet.getColor(entry.getXIndex()); - Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor), _hsvBuffer); + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), + Color.blue(originalColor), _hsvBuffer); _hsvBuffer[2] *= 0.5f; final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); mHighlightPaint.setColor(color); + mHighlightPaint.setStrokeWidth(dataSet.getHighLightCircleWidth()); c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mHighlightPaint); } } From 21cb6424415150bd74a2207d2cbfd8bdd338a24c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 07:24:42 +0300 Subject: [PATCH 0332/1390] Minor improvements to Bubble chart --- .../mpchartexample/BubbleChartActivity.java | 2 +- .../src/com/github/mikephil/charting/data/BubbleData.java | 4 ++-- .../com/github/mikephil/charting/data/BubbleDataSet.java | 7 ++----- .../mikephil/charting/renderer/BubbleChartRenderer.java | 8 +++++--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index c691ce89fe..82b6be5873 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -227,7 +227,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BubbleData data = new BubbleData(xVals, dataSets); data.setValueTypeface(tf); data.setValueTextSize(8f); - data.setHighLightCircleWidth(1.5f); + data.setHighlightCircleWidth(1.5f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index d835d098bf..943cf902eb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -46,9 +46,9 @@ private static List toList(BubbleDataSet dataSet) { * * @param width */ - public void setHighLightCircleWidth(float width) { + public void setHighlightCircleWidth(float width) { for (BubbleDataSet set : mDataSets) { - set.setHighLightCircleWidth(width); + set.setHighlightCircleWidth(width); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index ca458210a2..a2a2efa1c3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -20,9 +20,6 @@ public class BubbleDataSet extends BarLineScatterCandleDataSet { public BubbleDataSet(List yVals, String label) { super(yVals, label); - - if (mMaxSize < 1.f) - mMaxSize = 1.f; } /** @@ -31,11 +28,11 @@ public BubbleDataSet(List yVals, String label) { * * @param width */ - public void setHighLightCircleWidth(float width) { + public void setHighlightCircleWidth(float width) { mHighlightCircleWidth = Utils.convertDpToPixel(width); } - public float getHighLightCircleWidth() { + public float getHighlightCircleWidth() { return mHighlightCircleWidth; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 5616c9e667..441d169684 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -90,7 +90,8 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { trans.pointValuesToPixel(_pointBuffer); final float shapeSize = (chartSize / bubbleSizeFactor) - * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); + * (float) (Math.sqrt(entry.getSize() / + (dataSet.getMaxSize() > 0.0 ? dataSet.getMaxSize() : 1.0))); final float shapeHalf = shapeSize / 2.f; if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) @@ -214,7 +215,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { trans.pointValuesToPixel(_pointBuffer); final float shapeSize = (chartSize / bubbleSizeFactor) - * (float) (Math.sqrt(entry.getSize() / dataSet.getMaxSize())); + * (float) (Math.sqrt(entry.getSize() / + (dataSet.getMaxSize() > 0.0 ? dataSet.getMaxSize() : 1.0))); final float shapeHalf = shapeSize / 2.f; if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) @@ -231,7 +233,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); mHighlightPaint.setColor(color); - mHighlightPaint.setStrokeWidth(dataSet.getHighLightCircleWidth()); + mHighlightPaint.setStrokeWidth(dataSet.getHighlightCircleWidth()); c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mHighlightPaint); } } From 1e59b095e0a8732f19ec1423c747257679f785a4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 09:38:43 +0300 Subject: [PATCH 0333/1390] Deceleration after dragging in Line and Pie/Radar charts --- .../notimportant/MainActivity.java | 2 +- .../charting/charts/BarLineChartBase.java | 57 +++++++++++ .../charting/charts/PieRadarChartBase.java | 65 +++++++++++- .../listener/BarLineChartTouchListener.java | 96 ++++++++++++++++++ .../listener/PieRadarChartTouchListener.java | 99 +++++++++++++++++-- .../github/mikephil/charting/utils/Utils.java | 84 ++++++++++++++++ .../charting/utils/ViewPortHandler.java | 3 +- 7 files changed, 395 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 2d88c88b04..b800acce7a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -59,7 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main); // initialize the utilities - Utils.init(getResources()); + Utils.init(this); ArrayList objects = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 7750e7f67f..39358fd6c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -95,6 +95,16 @@ public abstract class BarLineChartBase= 1.f) + newValue = 0.f; + + mDragDecelarationFrictionCoef = newValue; + } + /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 86ae266675..cb6f7e93fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -41,6 +41,16 @@ public abstract class PieRadarChartBase= 1.f) + newValue = 0.f; + + mDragDecelarationFrictionCoef = newValue; + } + /** * returns the diameter of the pie- or radar-chart * diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index bf245e4226..658b6582e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -4,12 +4,15 @@ import android.annotation.SuppressLint; import android.graphics.Matrix; import android.graphics.PointF; +import android.os.Build; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; +import android.view.VelocityTracker; import android.view.View; import android.view.View.OnTouchListener; +import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.HorizontalBarChart; @@ -18,6 +21,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -70,6 +74,13 @@ public class BarLineChartTouchListener Utils.getMinimumFlingVelocity() || + Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) { + + if (mTouchMode == DRAG && mChart.isDragDecelarationEnabled()) { + + stopDeceleration(); + + mDecelarationLastTime = AnimationUtils.currentAnimationTimeMillis(); + mDecelarationCurrentPoint = new PointF(event.getX(), event.getY()); + mDecelarationVelocity = new PointF(velocityX, velocityY); + + Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google + } + } + mTouchMode = NONE; mChart.enableScroll(); + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; case MotionEvent.ACTION_POINTER_UP: + Utils.velocityTrackerPointerUpCleanUpIfNecessary(event, mVelocityTracker); + mTouchMode = POST_ZOOM; break; + + case MotionEvent.ACTION_CANCEL: + + mTouchMode = NONE; + + break; } // Perform the transformation, update the chart @@ -513,4 +575,38 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve return super.onFling(e1, e2, velocityX, velocityY); } + + public void stopDeceleration() { + mDecelarationVelocity = new PointF(0.f, 0.f); + } + + public void computeScroll() { + + if (mDecelarationVelocity.x == 0.f && mDecelarationVelocity.y == 0.f) + return; // There's no deceleration in progress + + final long currentTime = AnimationUtils.currentAnimationTimeMillis(); + + mDecelarationVelocity.x *= mChart.getDragDecelarationFrictionCoef(); + mDecelarationVelocity.y *= mChart.getDragDecelarationFrictionCoef(); + + final float timeInterval = (float)(currentTime - mDecelarationLastTime) / 1000.f; + + float distanceX = mDecelarationVelocity.x * timeInterval; + float distanceY = mDecelarationVelocity.y * timeInterval; + + mDecelarationCurrentPoint.x += distanceX; + mDecelarationCurrentPoint.y += distanceY; + + MotionEvent event = MotionEvent.obtain(currentTime, currentTime, MotionEvent.ACTION_MOVE, mDecelarationCurrentPoint.x, mDecelarationCurrentPoint.y, 0); + performDrag(event); + mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, false); + + mDecelarationLastTime = currentTime; + + if (Math.abs(mDecelarationVelocity.x) >= 0.001 || Math.abs(mDecelarationVelocity.y) >= 0.001) + Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google + else + stopDeceleration(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 022e5446a6..5b0a7cd6f7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -6,8 +6,10 @@ import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; +import android.view.VelocityTracker; import android.view.View; import android.view.View.OnTouchListener; +import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieRadarChartBase; @@ -36,6 +38,13 @@ public class PieRadarChartTouchListener extends SimpleOnGestureListener implemen private GestureDetector mGestureDetector; + /** used for tracking velocity of dragging */ + private VelocityTracker mVelocityTracker; + + private long mDecelarationLastTime = 0; + private PointF mDecelarationCurrentPoint = new PointF(); + private float mDecelarationAngularVelocity = 0.f; + public PieRadarChartTouchListener(PieRadarChartBase ctx) { this.mChart = ctx; @@ -44,21 +53,33 @@ public PieRadarChartTouchListener(PieRadarChartBase ctx) { @SuppressLint("ClickableViewAccessibility") @Override - public boolean onTouch(View v, MotionEvent e) { + public boolean onTouch(View v, MotionEvent event) { + + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + mVelocityTracker.addMovement(event); - if (mGestureDetector.onTouchEvent(e)) + if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) { + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + } + + if (mGestureDetector.onTouchEvent(event)) return true; // if rotation by touch is enabled if (mChart.isRotationEnabled()) { - float x = e.getX(); - float y = e.getY(); + float x = event.getX(); + float y = event.getY(); - switch (e.getAction()) { + switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - mChart.setStartAngle(x, y); + mChart.setGestureStartAngle(x, y); mTouchStartPoint.x = x; mTouchStartPoint.y = y; break; @@ -76,8 +97,49 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) break; case MotionEvent.ACTION_UP: + + final VelocityTracker velocityTracker = mVelocityTracker; + final int pointerId = event.getPointerId(0); + velocityTracker.computeCurrentVelocity(1000, Utils.getMaximumFlingVelocity()); + final float velocityY = velocityTracker.getYVelocity(pointerId); + final float velocityX = velocityTracker.getXVelocity(pointerId); + + if (Math.abs(velocityX) > Utils.getMinimumFlingVelocity() || + Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) { + + if (mChart.isDragDecelarationEnabled()) { + stopDeceleration(); + + mDecelarationLastTime = AnimationUtils.currentAnimationTimeMillis(); + + float newAngle = mChart.getAngleForPoint(event.getX(), event.getY()); + float previousAngle = mChart.getAngleForPoint(event.getX() - mVelocityTracker.getXVelocity(), + event.getY() - mVelocityTracker.getYVelocity()); + + if (previousAngle >= 270.f && newAngle <= 90.f) { + // This is the wrapping point between 360 and 0, + // which prevents us from knowing if it's clockwise or counter. + newAngle += 360.f; + } else if (previousAngle <= 90.f && newAngle >= 270.f) { + // This is the wrapping point between 0 and 360, + // which prevents us from knowing if it's clockwise or counter. + previousAngle += 360.f; + } + + mDecelarationAngularVelocity = newAngle - previousAngle; + + Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google + } + } + mChart.enableScroll(); mTouchMode = NONE; + + if (mVelocityTracker != null) { + mVelocityTracker.recycle(); + mVelocityTracker = null; + } + break; } } @@ -192,4 +254,29 @@ private static float distance(float eventX, float startX, float eventY, float st float dy = eventY - startY; return (float) Math.sqrt(dx * dx + dy * dy); } + + public void stopDeceleration() { + mDecelarationAngularVelocity = 0.f; + } + + public void computeScroll() { + + if (mDecelarationAngularVelocity == 0.f) + return; // There's no deceleration in progress + + final long currentTime = AnimationUtils.currentAnimationTimeMillis(); + + mDecelarationAngularVelocity *= mChart.getDragDecelarationFrictionCoef(); + + final float timeInterval = (float)(currentTime - mDecelarationLastTime) / 1000.f; + + mChart.setRotationAngle(mChart.getRotationAngle() + mDecelarationAngularVelocity * timeInterval); + + mDecelarationLastTime = currentTime; + + if (Math.abs(mDecelarationAngularVelocity) >= 0.001) + Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google + else + stopDeceleration(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 8f4da46332..0512b6df86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -1,12 +1,18 @@ package com.github.mikephil.charting.utils; +import android.content.Context; import android.content.res.Resources; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; +import android.os.Build; import android.util.DisplayMetrics; import android.util.Log; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; import com.github.mikephil.charting.components.YAxis.AxisDependency; @@ -24,14 +30,47 @@ public abstract class Utils { private static DisplayMetrics mMetrics; + private static int mMinimumFlingVelocity = 50; + private static int mMaximumFlingVelocity = 8000; /** * initialize method, called inside the Chart.init() method. * * @param res */ + public static void init(Context context) { + + Resources res = context.getResources(); + + mMetrics = res.getDisplayMetrics(); + + if (context == null) { + //noinspection deprecation + mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); + //noinspection deprecation + mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); + } else { + ViewConfiguration viewConfiguration = ViewConfiguration.get(context); + mMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity(); + mMaximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity(); + } + } + + /** + * initialize method, called inside the Chart.init() method. + * backwards compatibility - to not break existing code + * + * @param res + */ + @Deprecated public static void init(Resources res) { + mMetrics = res.getDisplayMetrics(); + + //noinspection deprecation + mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); + //noinspection deprecation + mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); } /** @@ -431,4 +470,49 @@ public static PointF getPosition(PointF center, float dist, float angle) { (float) (center.y + dist * Math.sin(Math.toRadians(angle)))); return p; } + + public static void velocityTrackerPointerUpCleanUpIfNecessary(MotionEvent ev, VelocityTracker tracker) { + + // Check the dot product of current velocities. + // If the pointer that left was opposing another velocity vector, clear. + tracker.computeCurrentVelocity(1000, mMaximumFlingVelocity); + final int upIndex = ev.getActionIndex(); + final int id1 = ev.getPointerId(upIndex); + final float x1 = tracker.getXVelocity(id1); + final float y1 = tracker.getYVelocity(id1); + for (int i = 0, count = ev.getPointerCount(); i < count; i++) { + if (i == upIndex) continue; + + final int id2 = ev.getPointerId(i); + final float x = x1 * tracker.getXVelocity(id2); + final float y = y1 * tracker.getYVelocity(id2); + + final float dot = x + y; + if (dot < 0) { + tracker.clear(); + break; + } + } + } + + /** + * Original method view.postInvalidateOnAnimation() only supportd in API >= 16, + * This is a replica of the code from ViewCompat. + * + * @param view + */ + public static void postInvalidateOnAnimation(View view) { + if (Build.VERSION.SDK_INT >= 16) + view.postInvalidateOnAnimation(); + else + view.postInvalidateDelayed(10); + } + + public static int getMinimumFlingVelocity() { + return mMinimumFlingVelocity; + } + + public static int getMaximumFlingVelocity() { + return mMaximumFlingVelocity; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index c09df879e5..77b90d0e75 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -260,7 +260,8 @@ public Matrix refresh(Matrix newMatrix, View chart, boolean invalidate) { // make sure scale and translation are within their bounds limitTransAndScale(mMatrixTouch, mContentRect); - chart.invalidate(); + if (invalidate) + chart.invalidate(); newMatrix.set(mMatrixTouch); return newMatrix; From d4b242210382de6168591942e023638bcbb03a65 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 May 2015 10:27:00 +0200 Subject: [PATCH 0334/1390] Minor improvements to recent PR. --- .../mpchartexample/LineChartActivity2.java | 2 + .../charting/charts/BarLineChartBase.java | 52 +--------------- .../mikephil/charting/charts/Chart.java | 60 +++++++++++++++++-- .../charting/charts/PieRadarChartBase.java | 50 ---------------- .../listener/BarLineChartTouchListener.java | 9 +-- .../listener/PieRadarChartTouchListener.java | 5 +- .../github/mikephil/charting/utils/Utils.java | 11 ++-- .../charting/utils/ViewPortHandler.java | 1 - 8 files changed, 71 insertions(+), 119 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9a31bbfc42..a7fcafe51d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -70,6 +70,8 @@ protected void onCreate(Bundle savedInstanceState) { // enable touch gestures mChart.setTouchEnabled(true); + + mChart.setDragDecelerationFrictionCoef(0.95f); // enable scaling and dragging mChart.setDragEnabled(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 39358fd6c2..03758980d7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -95,16 +95,6 @@ public abstract class BarLineChartBase) mListener).computeScroll(); } /** @@ -985,46 +975,6 @@ public void setBorderColor(int color) { mBorderPaint.setColor(color); } - /** - * If set to true, chart continues to scroll after touch up - * - * default: true - */ - public boolean isDragDecelarationEnabled() { - return mDragDecelarationEnabled; - } - - /** - * If set to true, chart continues to scroll after touch up - * - * @param enabled - */ - public void setDragDecelarationEnabled(boolean enabled) { - mDragDecelarationEnabled = enabled; - } - - /** - * Returns drag deceleration friction coefficient - * @return - */ - public float getDragDecelarationFrictionCoef() { - return mDragDecelarationFrictionCoef; - } - - /**+ - * Decelaration friction coefficient in [0 ; 1] interval, higher values indicate that - * speed will decrease slowly, for example if it set to 0, it will stop immediately. - * 1 is an invalid value, and will be converted to 0 automatically. - * - * @param newValue - */ - public void setDragDecelarationFrictionCoef(float newValue) { - if (newValue < 0.f || newValue >= 1.f) - newValue = 0.f; - - mDragDecelarationFrictionCoef = newValue; - } - /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 1715b9e22d..6da8caa733 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -72,12 +72,20 @@ public abstract class Chart= 1f) + newValue = 0.999f; + + mDragDecelerationFrictionCoef = newValue; + } + /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index cb6f7e93fd..f4ba2cc2b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -41,16 +41,6 @@ public abstract class PieRadarChartBase= 1.f) - newValue = 0.f; - - mDragDecelarationFrictionCoef = newValue; - } - /** * returns the diameter of the pie- or radar-chart * diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 658b6582e8..a1baff079c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.graphics.Matrix; import android.graphics.PointF; -import android.os.Build; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; @@ -15,6 +14,7 @@ import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; @@ -198,7 +198,7 @@ public boolean onTouch(View v, MotionEvent event) { if (Math.abs(velocityX) > Utils.getMinimumFlingVelocity() || Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) { - if (mTouchMode == DRAG && mChart.isDragDecelarationEnabled()) { + if (mTouchMode == DRAG && mChart.isDragDecelerationEnabled()) { stopDeceleration(); @@ -587,8 +587,8 @@ public void computeScroll() { final long currentTime = AnimationUtils.currentAnimationTimeMillis(); - mDecelarationVelocity.x *= mChart.getDragDecelarationFrictionCoef(); - mDecelarationVelocity.y *= mChart.getDragDecelarationFrictionCoef(); + mDecelarationVelocity.x *= mChart.getDragDecelerationFrictionCoef(); + mDecelarationVelocity.y *= mChart.getDragDecelerationFrictionCoef(); final float timeInterval = (float)(currentTime - mDecelarationLastTime) / 1000.f; @@ -600,6 +600,7 @@ public void computeScroll() { MotionEvent event = MotionEvent.obtain(currentTime, currentTime, MotionEvent.ACTION_MOVE, mDecelarationCurrentPoint.x, mDecelarationCurrentPoint.y, 0); performDrag(event); + event.recycle(); mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, false); mDecelarationLastTime = currentTime; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 5b0a7cd6f7..b2bc24b08f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -42,7 +42,6 @@ public class PieRadarChartTouchListener extends SimpleOnGestureListener implemen private VelocityTracker mVelocityTracker; private long mDecelarationLastTime = 0; - private PointF mDecelarationCurrentPoint = new PointF(); private float mDecelarationAngularVelocity = 0.f; public PieRadarChartTouchListener(PieRadarChartBase ctx) { @@ -107,7 +106,7 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) if (Math.abs(velocityX) > Utils.getMinimumFlingVelocity() || Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) { - if (mChart.isDragDecelarationEnabled()) { + if (mChart.isDragDecelerationEnabled()) { stopDeceleration(); mDecelarationLastTime = AnimationUtils.currentAnimationTimeMillis(); @@ -266,7 +265,7 @@ public void computeScroll() { final long currentTime = AnimationUtils.currentAnimationTimeMillis(); - mDecelarationAngularVelocity *= mChart.getDragDecelarationFrictionCoef(); + mDecelarationAngularVelocity *= mChart.getDragDecelerationFrictionCoef(); final float timeInterval = (float)(currentTime - mDecelarationLastTime) / 1000.f; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 0512b6df86..d4acd8105c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.utils; +import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; import android.graphics.Paint; @@ -13,9 +14,7 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; - import com.github.mikephil.charting.components.YAxis.AxisDependency; - import java.text.DecimalFormat; import java.util.List; @@ -40,10 +39,6 @@ public abstract class Utils { */ public static void init(Context context) { - Resources res = context.getResources(); - - mMetrics = res.getDisplayMetrics(); - if (context == null) { //noinspection deprecation mMinimumFlingVelocity = ViewConfiguration.getMinimumFlingVelocity(); @@ -54,6 +49,9 @@ public static void init(Context context) { mMinimumFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity(); mMaximumFlingVelocity = viewConfiguration.getScaledMaximumFlingVelocity(); } + + Resources res = context.getResources(); + mMetrics = res.getDisplayMetrics(); } /** @@ -501,6 +499,7 @@ public static void velocityTrackerPointerUpCleanUpIfNecessary(MotionEvent ev, Ve * * @param view */ + @SuppressLint("NewApi") public static void postInvalidateOnAnimation(View view) { if (Build.VERSION.SDK_INT >= 16) view.postInvalidateOnAnimation(); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 77b90d0e75..76bd923c28 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -4,7 +4,6 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; -import android.util.Log; import android.view.View; public class ViewPortHandler { From 0b25bd3cbf67b5ab450871c43dce5a7dc3cfc033 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 May 2015 10:48:21 +0200 Subject: [PATCH 0335/1390] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 77f65ea37d..3b833e8687 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Remember: *It's all about the looks.* ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) -**MPAndroidChart** is a powerful & easy to use chart library for Android, supporting line-, bar-, scatter-, candlestick-, pie- and radarcharts (spider web), as well as scaling, dragging (panning), selecting and animations. Works on **Android 2.2 (API level 8)** and upwards. +**MPAndroidChart** is a powerful & easy to use chart library for Android, supporting line-, bar-, scatter-, candlestick-, bubble-, pie- and radarcharts (spider web), as well as scaling, dragging (panning), selecting and animations. Works on **Android 2.2 (API level 8)** and upwards. An **iOS** version of this library is now available, go check it out: [**ios-charts**](https://github.com/danielgindi/ios-charts) @@ -60,6 +60,7 @@ Features ======= **Core features:** + - 7 different chart types - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) From e16c2de7deec53c3512b97696768a0ec324ff579 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Fri, 1 May 2015 21:28:24 +0300 Subject: [PATCH 0336/1390] Large value formatter now can appends a specified text to the result string --- .../charting/utils/LargeValueFormatter.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java index 608c8b7b36..9f6d19610f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java @@ -11,25 +11,34 @@ * (https://github.com/romangromov) for this piece of code. * * @author Philipp Jahoda + * @author Oleksandr Tyshkovets */ public class LargeValueFormatter implements ValueFormatter { - private static String[] SUFFIX = new String[] { + private static final String[] SUFFIX = new String[] { "", "k", "m", "b", "t" }; - - private static int MAX_LENGTH = 4; + private static final int MAX_LENGTH = 4; private DecimalFormat mFormat; + private String mText; public LargeValueFormatter() { - mFormat = new DecimalFormat("###E0"); } + /** + * Creates a formatter that appends a specified text to the result string + * @param text a text that will be appended + */ + public LargeValueFormatter(String text) { + this(); + mText = text; + } + @Override public String getFormattedValue(float value) { - return makePretty(value); + return makePretty(value) + " " + mText; } /** From b78f4e8071cd0c630aad4fa2926838b3d6e99951 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 2 May 2015 20:36:59 +0300 Subject: [PATCH 0337/1390] Theoretically these values could be negative --- .../mikephil/charting/renderer/BubbleChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 441d169684..d61b19b7b2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -91,7 +91,7 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { final float shapeSize = (chartSize / bubbleSizeFactor) * (float) (Math.sqrt(entry.getSize() / - (dataSet.getMaxSize() > 0.0 ? dataSet.getMaxSize() : 1.0))); + (dataSet.getMaxSize() != 0.0 ? dataSet.getMaxSize() : 1.0))); final float shapeHalf = shapeSize / 2.f; if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) @@ -216,7 +216,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float shapeSize = (chartSize / bubbleSizeFactor) * (float) (Math.sqrt(entry.getSize() / - (dataSet.getMaxSize() > 0.0 ? dataSet.getMaxSize() : 1.0))); + (dataSet.getMaxSize() != 0.0 ? dataSet.getMaxSize() : 1.0))); final float shapeHalf = shapeSize / 2.f; if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) From fb70ef74ae8ad539d1aa20257ce3b0f2e09c032e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 May 2015 15:39:26 +0300 Subject: [PATCH 0338/1390] An improved velocity tracker for radial charts + typo fixes --- .../mikephil/charting/charts/Chart.java | 6 +- .../mikephil/charting/charts/PieChart.java | 2 +- .../charting/charts/PieRadarChartBase.java | 66 ++---- .../mikephil/charting/charts/RadarChart.java | 2 +- .../listener/BarLineChartTouchListener.java | 37 ++- .../listener/PieRadarChartTouchListener.java | 211 +++++++++++++----- .../github/mikephil/charting/utils/Utils.java | 8 + 7 files changed, 207 insertions(+), 125 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 6da8caa733..6dc37b460e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -76,10 +76,10 @@ public abstract class Chart a) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index f4ba2cc2b0..827fc9c956 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -32,11 +32,11 @@ public abstract class PieRadarChartBase>> extends Chart { - /** holds the current rotation angle of the chart */ - protected float mRotationAngle = 270f; - - /** the angle where the dragging started */ - private float mStartAngle = 0f; + /** holds the normalized version of the current rotation angle of the chart */ + private float mRotationAngle = 270f; + + /** holds the raw version of the current rotation angle of the chart */ + private float mRawRotationAngle = 270f; /** flag that indicates if rotation is enabled or not */ protected boolean mRotateEnabled = true; @@ -203,39 +203,6 @@ protected void calculateOffsets() { + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); } - /** - * sets the starting angle of the rotation, this is only used by the touch - * listener, x and y is the touch position - * - * @param x - * @param y - */ - public void setGestureStartAngle(float x, float y) { - - mStartAngle = getAngleForPoint(x, y); - - // take the current angle into consideration when starting a new drag - mStartAngle -= mRotationAngle; - } - - /** - * updates the view rotation depending on the given touch position, also - * takes the starting angle into consideration - * - * @param x - * @param y - */ - public void updateRotation(float x, float y) { - - mRotationAngle = getAngleForPoint(x, y); - - // take the offset into consideration - mRotationAngle -= mStartAngle; - - // keep the angle >= 0 and <= 360 - mRotationAngle = (mRotationAngle + 360f) % 360f; - } - /** * returns the angle relative to the chart center for the given point on the * chart in degrees. The angle is always between 0 and 360°, 0° is NORTH, @@ -336,16 +303,25 @@ public float distanceToCenter(float x, float y) { * @param angle */ public void setRotationAngle(float angle) { + mRawRotationAngle = angle; + mRotationAngle = Utils.getNormalizedAngle(mRawRotationAngle); + } - while (angle < 0.f) - angle += 360.f; - - mRotationAngle = angle % 360; + /** + * gets the raw version of the current rotation angle of the pie chart + * the returned value could be any value, negative or positive, outside of the 360 degrees. + * this is used when working with rotation direction, mainly by gestures and animations. + * + * @return + */ + public float getRawRotationAngle() { + return mRawRotationAngle; } /** - * gets the current rotation angle of the pie chart - * + * gets a normalized version of the current rotation angle of the pie chart, + * which will always be between 0.0 < 360.0 + * * @return */ public float getRotationAngle() { @@ -480,7 +456,7 @@ public void spin(int durationmillis, float fromangle, float toangle, Easing.Easi if (android.os.Build.VERSION.SDK_INT < 11) return; - mRotationAngle = fromangle; + setRotationAngle(fromangle); ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); spinAnimator.setDuration(durationmillis); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 4a9dfaf219..6c03096d46 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -201,7 +201,7 @@ public float getSliceAngle() { public int getIndexForAngle(float angle) { // take the current angle of the chart into consideration - float a = (angle - mRotationAngle + 360) % 360f; + float a = Utils.getNormalizedAngle(angle - getRotationAngle()); float sliceangle = getSliceAngle(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index a1baff079c..35b6336063 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -14,7 +14,6 @@ import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; @@ -77,9 +76,9 @@ public class BarLineChartTouchListener= 0.001 || Math.abs(mDecelarationVelocity.y) >= 0.001) + if (Math.abs(mDecelerationVelocity.x) >= 0.001 || Math.abs(mDecelerationVelocity.y) >= 0.001) Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google else stopDeceleration(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index b2bc24b08f..5778bf490c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -6,7 +6,6 @@ import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; -import android.view.VelocityTracker; import android.view.View; import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; @@ -18,6 +17,7 @@ import com.github.mikephil.charting.utils.SelInfo; import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; import java.util.List; /** @@ -34,15 +34,17 @@ public class PieRadarChartTouchListener extends SimpleOnGestureListener implemen private PieRadarChartBase mChart; + /** the angle where the dragging started */ + private float mStartAngle = 0f; + private int mTouchMode = NONE; private GestureDetector mGestureDetector; - /** used for tracking velocity of dragging */ - private VelocityTracker mVelocityTracker; + private ArrayList _velocitySamples = new ArrayList<>(); - private long mDecelarationLastTime = 0; - private float mDecelarationAngularVelocity = 0.f; + private long mDecelerationLastTime = 0; + private float mDecelerationAngularVelocity = 0.f; public PieRadarChartTouchListener(PieRadarChartBase ctx) { this.mChart = ctx; @@ -54,18 +56,6 @@ public PieRadarChartTouchListener(PieRadarChartBase ctx) { @Override public boolean onTouch(View v, MotionEvent event) { - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(event); - - if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) { - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - } - if (mGestureDetector.onTouchEvent(event)) return true; @@ -78,54 +68,47 @@ public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - mChart.setGestureStartAngle(x, y); + + stopDeceleration(); + + resetVelocity(); + + if (mChart.isDragDecelerationEnabled()) + sampleVelocity(x, y); + + setGestureStartAngle(x, y); mTouchStartPoint.x = x; mTouchStartPoint.y = y; + break; case MotionEvent.ACTION_MOVE: + if (mChart.isDragDecelerationEnabled()) + sampleVelocity(x, y); + if (mTouchMode == NONE && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) > Utils.convertDpToPixel(8f)) { mTouchMode = ROTATE; mChart.disableScroll(); } else if (mTouchMode == ROTATE) { - mChart.updateRotation(x, y); + updateGestureRotation(x, y); mChart.invalidate(); } break; case MotionEvent.ACTION_UP: - final VelocityTracker velocityTracker = mVelocityTracker; - final int pointerId = event.getPointerId(0); - velocityTracker.computeCurrentVelocity(1000, Utils.getMaximumFlingVelocity()); - final float velocityY = velocityTracker.getYVelocity(pointerId); - final float velocityX = velocityTracker.getXVelocity(pointerId); - - if (Math.abs(velocityX) > Utils.getMinimumFlingVelocity() || - Math.abs(velocityY) > Utils.getMinimumFlingVelocity()) { - - if (mChart.isDragDecelerationEnabled()) { - stopDeceleration(); + if (mChart.isDragDecelerationEnabled()) { - mDecelarationLastTime = AnimationUtils.currentAnimationTimeMillis(); + stopDeceleration(); - float newAngle = mChart.getAngleForPoint(event.getX(), event.getY()); - float previousAngle = mChart.getAngleForPoint(event.getX() - mVelocityTracker.getXVelocity(), - event.getY() - mVelocityTracker.getYVelocity()); + sampleVelocity(x, y); - if (previousAngle >= 270.f && newAngle <= 90.f) { - // This is the wrapping point between 360 and 0, - // which prevents us from knowing if it's clockwise or counter. - newAngle += 360.f; - } else if (previousAngle <= 90.f && newAngle >= 270.f) { - // This is the wrapping point between 0 and 360, - // which prevents us from knowing if it's clockwise or counter. - previousAngle += 360.f; - } + mDecelerationAngularVelocity = calculateVelocity(); - mDecelarationAngularVelocity = newAngle - previousAngle; + if (mDecelerationAngularVelocity != 0.f) { + mDecelerationLastTime = AnimationUtils.currentAnimationTimeMillis(); Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google } @@ -134,11 +117,6 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) mChart.enableScroll(); mTouchMode = NONE; - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - break; } } @@ -239,6 +217,115 @@ public boolean onDoubleTap(MotionEvent e) { return super.onDoubleTap(e); } + private void resetVelocity() + { + _velocitySamples.clear(); + } + + private void sampleVelocity(float touchLocationX, float touchLocationY) + { + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + + _velocitySamples.add(new AngularVelocitySample(currentTime, mChart.getAngleForPoint(touchLocationX, touchLocationY))); + + // Remove samples older than our sample time - 1 seconds + for (int i = 0, count = _velocitySamples.size(); i < count - 2; i++) + { + if (currentTime - _velocitySamples.get(i).time > 1000) + { + _velocitySamples.remove(0); + i--; + count--; + } + else + { + break; + } + } + } + + private float calculateVelocity() + { + if (_velocitySamples.isEmpty()) + return 0.f; + + AngularVelocitySample firstSample = _velocitySamples.get(0); + AngularVelocitySample lastSample = _velocitySamples.get(_velocitySamples.size() - 1); + + // Look for a sample that's closest to the latest sample, but not the same, so we can deduce the direction + AngularVelocitySample beforeLastSample = firstSample; + for (int i = _velocitySamples.size() - 1; i >= 0; i--) + { + beforeLastSample = _velocitySamples.get(i); + if (beforeLastSample.angle != lastSample.angle) + { + break; + } + } + + // Calculate the sampling time + float timeDelta = (lastSample.time - firstSample.time) / 1000.f; + if (timeDelta == 0.f) + { + timeDelta = 0.1f; + } + + // Calculate clockwise/ccw by choosing two values that should be closest to each other, + // so if the angles are two far from each other we know they are inverted "for sure" + boolean clockwise = lastSample.angle >= beforeLastSample.angle; + if (Math.abs(lastSample.angle - beforeLastSample.angle) > 270.0) + { + clockwise = !clockwise; + } + + // Now if the "gesture" is over a too big of an angle - then we know the angles are inverted, and we need to move them closer to each other from both sides of the 360.0 wrapping point + if (lastSample.angle - firstSample.angle > 180.0) + { + firstSample.angle += 360.0; + } + else if (firstSample.angle - lastSample.angle > 180.0) + { + lastSample.angle += 360.0; + } + + // The velocity + float velocity = Math.abs((lastSample.angle - firstSample.angle) / timeDelta); + + // Direction? + if (!clockwise) + { + velocity = -velocity; + } + + return velocity; + } + + /** + * sets the starting angle of the rotation, this is only used by the touch + * listener, x and y is the touch position + * + * @param x + * @param y + */ + public void setGestureStartAngle(float x, float y) { + + mStartAngle = mChart.getAngleForPoint(x, y) - mChart.getRawRotationAngle(); + + } + + /** + * updates the view rotation depending on the given touch position, also + * takes the starting angle into consideration + * + * @param x + * @param y + */ + public void updateGestureRotation(float x, float y) { + + mChart.setRotationAngle(mChart.getAngleForPoint(x, y) - mStartAngle); + + } + /** * returns the distance between two points * @@ -255,27 +342,39 @@ private static float distance(float eventX, float startX, float eventY, float st } public void stopDeceleration() { - mDecelarationAngularVelocity = 0.f; + mDecelerationAngularVelocity = 0.f; } public void computeScroll() { - if (mDecelarationAngularVelocity == 0.f) + if (mDecelerationAngularVelocity == 0.f) return; // There's no deceleration in progress final long currentTime = AnimationUtils.currentAnimationTimeMillis(); - mDecelarationAngularVelocity *= mChart.getDragDecelerationFrictionCoef(); + mDecelerationAngularVelocity *= mChart.getDragDecelerationFrictionCoef(); - final float timeInterval = (float)(currentTime - mDecelarationLastTime) / 1000.f; + final float timeInterval = (float)(currentTime - mDecelerationLastTime) / 1000.f; - mChart.setRotationAngle(mChart.getRotationAngle() + mDecelarationAngularVelocity * timeInterval); + mChart.setRotationAngle(mChart.getRotationAngle() + mDecelerationAngularVelocity * timeInterval); - mDecelarationLastTime = currentTime; + mDecelerationLastTime = currentTime; - if (Math.abs(mDecelarationAngularVelocity) >= 0.001) + if (Math.abs(mDecelerationAngularVelocity) >= 0.001) Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google else stopDeceleration(); } + + private class AngularVelocitySample + { + public long time; + public float angle; + + public AngularVelocitySample(long time, float angle) + { + this.time = time; + this.angle = angle; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index d4acd8105c..8b76a889be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -514,4 +514,12 @@ public static int getMinimumFlingVelocity() { public static int getMaximumFlingVelocity() { return mMaximumFlingVelocity; } + + /** returns an angle between 0.f < 360.f (not less than zero, less than 360) */ + public static float getNormalizedAngle(float angle) { + while (angle < 0.f) + angle += 360.f; + + return angle % 360.f; + } } From 6a60e2c94b5a56449f7e7cf0dcc854f1157d47f9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 2 May 2015 19:51:31 +0200 Subject: [PATCH 0339/1390] Merged recent PRs. --- .../xxmassdeveloper/mpchartexample/PieChartActivity.java | 2 ++ .../github/mikephil/charting/charts/PieRadarChartBase.java | 6 +++--- .../charting/listener/PieRadarChartTouchListener.java | 2 +- .../github/mikephil/charting/utils/LargeValueFormatter.java | 6 +++--- .../src/com/github/mikephil/charting/utils/Utils.java | 2 ++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 8470f147ba..9f6fda4c39 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -58,6 +58,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); mChart.setDescription(""); + + mChart.setDragDecelerationFrictionCoef(0.99f); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 827fc9c956..47434ebc95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -81,7 +81,7 @@ public boolean onTouchEvent(MotionEvent event) { public void computeScroll() { if (mListener instanceof PieRadarChartTouchListener) - ((PieRadarChartTouchListener)mListener).computeScroll(); + ((PieRadarChartTouchListener) mListener).computeScroll(); } @Override @@ -442,7 +442,6 @@ public List getYValsAtIndex(int xIndex) { */ /** CODE BELOW THIS RELATED TO ANIMATION */ - /** * Applys a spin animation to the Chart. * @@ -458,7 +457,8 @@ public void spin(int durationmillis, float fromangle, float toangle, Easing.Easi setRotationAngle(fromangle); - ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); + ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, + toangle); spinAnimator.setDuration(durationmillis); spinAnimator.setInterpolator(Easing.getEasingFunctionFromOption(easing)); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 5778bf490c..78bd9f269a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -41,7 +41,7 @@ public class PieRadarChartTouchListener extends SimpleOnGestureListener implemen private GestureDetector mGestureDetector; - private ArrayList _velocitySamples = new ArrayList<>(); + private ArrayList _velocitySamples = new ArrayList(); private long mDecelerationLastTime = 0; private float mDecelerationAngularVelocity = 0.f; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java index 9f6d19610f..4d8cf4ec0d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java @@ -31,14 +31,14 @@ public LargeValueFormatter() { * Creates a formatter that appends a specified text to the result string * @param text a text that will be appended */ - public LargeValueFormatter(String text) { + public LargeValueFormatter(String appendix) { this(); - mText = text; + mText = appendix; } @Override public String getFormattedValue(float value) { - return makePretty(value) + " " + mText; + return makePretty(value) + mText; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 8b76a889be..ddabfbc723 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -14,7 +14,9 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; + import com.github.mikephil.charting.components.YAxis.AxisDependency; + import java.text.DecimalFormat; import java.util.List; From 1301f1189e609156d1f658d8a6849cfaf366ec98 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 2 May 2015 19:55:58 +0200 Subject: [PATCH 0340/1390] Minor fix in large valueformatter. --- .../com/github/mikephil/charting/utils/LargeValueFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java index 4d8cf4ec0d..119c671588 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java @@ -21,7 +21,7 @@ public class LargeValueFormatter implements ValueFormatter { private static final int MAX_LENGTH = 4; private DecimalFormat mFormat; - private String mText; + private String mText = ""; public LargeValueFormatter() { mFormat = new DecimalFormat("###E0"); From 1c5819274d15441e4b0c477430d4bb883801ac98 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 May 2015 11:18:24 +0200 Subject: [PATCH 0341/1390] Worked on integrating BubbleChart into CombinedChart. --- .../mpchartexample/CombinedChartActivity.java | 31 ++++++++++++++-- .../mikephil/charting/charts/Chart.java | 5 +++ .../charting/charts/CombinedChart.java | 36 ++++++++++++++++--- .../mikephil/charting/data/BubbleDataSet.java | 4 +-- .../mikephil/charting/data/BubbleEntry.java | 19 +++++----- .../mikephil/charting/data/ChartData.java | 7 ++-- .../mikephil/charting/data/CombinedData.java | 11 ++++++ .../mikephil/charting/data/DataSet.java | 16 +++++++-- .../charting/interfaces/ChartInterface.java | 2 ++ .../renderer/BubbleChartRenderer.java | 6 ++-- .../renderer/CombinedChartRenderer.java | 5 +++ 11 files changed, 112 insertions(+), 30 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 363e5e0763..25ff1835ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -15,6 +15,9 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; @@ -25,6 +28,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -48,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { // draw bars behind lines mChart.setDrawOrder(new DrawOrder[] { - DrawOrder.BAR, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER + DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); YAxis rightAxis = mChart.getAxisRight(); @@ -64,6 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { data.setData(generateLineData()); data.setData(generateBarData()); +// data.setData(generateBubbleData()); // data.setData(generateScatterData()); // data.setData(generateCandleData()); @@ -125,7 +130,7 @@ protected ScatterData generateScatterData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(20, 30), index)); + entries.add(new Entry(getRandom(20, 15), index)); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); set.setColor(Color.GREEN); @@ -155,6 +160,28 @@ protected CandleData generateCandleData() { return d; } + + protected BubbleData generateBubbleData() { + + BubbleData bd = new BubbleData(); + + ArrayList entries = new ArrayList(); + + for (int index = 0; index < itemcount; index++) { + float rnd = getRandom(20, 30); + entries.add(new BubbleEntry(index, rnd, rnd)); + } + + BubbleDataSet set = new BubbleDataSet(entries, "Bubble DataSet"); + set.setColors(ColorTemplate.VORDIPLOM_COLORS); + set.setValueTextSize(10f); + set.setValueTextColor(Color.WHITE); + set.setHighlightCircleWidth(1.5f); + set.setDrawValues(true); + bd.addDataSet(set); + + return bd; + } private float getRandom(float range, float startsfrom) { return (float) (Math.random() * range) + startsfrom; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 6dc37b460e..6568995f6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -908,6 +908,11 @@ public float getXChartMin() { return mXChartMin; } + @Override + public int getXValCount() { + return mData.getXValCount(); + } + /** * returns the average value of all values the chart holds * diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 0eebb3a520..f9b0504205 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -5,11 +5,14 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.BubbleDataProvider; import com.github.mikephil.charting.interfaces.CandleDataProvider; import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.interfaces.ScatterDataProvider; @@ -23,7 +26,7 @@ * @author Philipp Jahoda */ public class CombinedChart extends BarLineChartBase implements LineDataProvider, - BarDataProvider, ScatterDataProvider, CandleDataProvider { + BarDataProvider, ScatterDataProvider, CandleDataProvider, BubbleDataProvider { /** the fill-formatter used for determining the position of the fill-line */ protected FillFormatter mFillFormatter; @@ -50,7 +53,7 @@ public class CombinedChart extends BarLineChartBase implements Lin private boolean mDrawBarShadow = false; protected DrawOrder[] mDrawOrder = new DrawOrder[] { - DrawOrder.BAR, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER + DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER }; /** @@ -58,7 +61,7 @@ public class CombinedChart extends BarLineChartBase implements Lin * for the combined-chart are drawn */ public enum DrawOrder { - BAR, LINE, CANDLE, SCATTER + BAR, BUBBLE, LINE, CANDLE, SCATTER } public CombinedChart(Context context) { @@ -85,10 +88,26 @@ protected void init() { @Override protected void calcMinMax() { super.calcMinMax(); - - if (getBarData() != null || getCandleData() != null) { + + if (getBarData() != null || getCandleData() != null || getBubbleData() != null) { mXChartMin = -0.5f; mXChartMax = mData.getXVals().size() - 0.5f; + + if (getBubbleData() != null) { + + for (BubbleDataSet set : getBubbleData().getDataSets()) { + + final float xmin = set.getXMin(); + final float xmax = set.getXMax(); + + if (xmin < mXChartMin) + mXChartMin = xmin; + + if (xmax > mXChartMax) + mXChartMax = xmax; + } + } + mDeltaX = Math.abs(mXChartMax - mXChartMin); } } @@ -141,6 +160,13 @@ public CandleData getCandleData() { return mData.getCandleData(); } + @Override + public BubbleData getBubbleData() { + if (mData == null) + return null; + return mData.getBubbleData(); + } + @Override public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index a2a2efa1c3..cca4cf5743 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -42,8 +42,8 @@ public void setColor(int color) { } @Override - protected void calcMinMax() - { + protected void calcMinMax() { + final List entries = getYVals(); // need chart width to guess this properly diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java index 5a2e6f546d..ae4875c1f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java @@ -2,11 +2,9 @@ package com.github.mikephil.charting.data; /** - * Subclass of Entry that holds a value for one entry in a BubbleChart. - * - * Bubble chart implementation: - * Copyright 2015 Pierre-Marc Airoldi - * Licensed under Apache License 2.0 + * Subclass of Entry that holds a value for one entry in a BubbleChart. Bubble + * chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed under + * Apache License 2.0 * * @author Philipp Jahoda */ @@ -19,8 +17,8 @@ public class BubbleEntry extends Entry { * Constructor. * * @param xIndex The index on the x-axis. - * @param val - * @param size The size value. + * @param val The value on the y-axis. + * @param size The size of the bubble. */ public BubbleEntry(int xIndex, float val, float size) { super(val, xIndex); @@ -32,8 +30,8 @@ public BubbleEntry(int xIndex, float val, float size) { * Constructor. * * @param xIndex The index on the x-axis. - * @param val - * @param size The size value. + * @param val The value on the y-axis. + * @param size The size of the bubble. * @param data Spot for additional data this Entry represents. */ public BubbleEntry(int xIndex, float val, float size, Object data) { @@ -49,9 +47,8 @@ public BubbleEntry copy() { return c; } - /** - * Returns the size of this entry + * Returns the size of this entry (the size of the bubble). * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index cff3ae36d1..2a04822117 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -389,8 +389,8 @@ public List getXVals() { * @param xVal */ public void addXValue(String xVal) { - - mXValAverageLength = (mXValAverageLength + xVal.length()) / 2f; + + mXValAverageLength = (mXValAverageLength + xVal.length()) / 2f; mXVals.add(xVal); } @@ -891,7 +891,8 @@ public void setDrawValues(boolean enabled) { } /** - * Clears this data object from all DataSets and removes all Entries. + * Clears this data object from all DataSets and removes all Entries. Don't + * forget to invalidate the chart after this. */ public void clearValues() { mDataSets.clear(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 90fcb04a13..266369496c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -15,6 +15,7 @@ public class CombinedData extends BarLineScatterCandleData yVals, String label) { if (mYVals == null) mYVals = new ArrayList(); - + mColors = new ArrayList(); // default color @@ -346,7 +346,9 @@ public String toSimpleString() { * * @return */ - public void setLabel(String label) { mLabel = label; } + public void setLabel(String label) { + mLabel = label; + } /** * Returns the label string that describes the DataSet. @@ -430,7 +432,7 @@ public void addEntry(Entry e) { float val = e.getVal(); - if(mYVals == null) { + if (mYVals == null) { mYVals = new ArrayList(); } @@ -718,4 +720,12 @@ public boolean contains(Entry e) { return false; } + + /** + * Removes all values from this DataSet and recalculates min and max value. + */ + public void clear() { + mYVals.clear(); + notifyDataSetChanged(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index fcacaee105..c24b50a36e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -21,6 +21,8 @@ public interface ChartInterface { public float getYChartMin(); public float getYChartMax(); + + public int getXValCount(); public int getWidth(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index d61b19b7b2..a973d62560 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -78,8 +78,7 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); - final float bubbleSizeFactor = (float) (bubbleData.getXVals().size() > 0 ? bubbleData - .getXVals().size() : 1); + final float bubbleSizeFactor = (float) (mChart.getXValCount() > 0 ? mChart.getXValCount() : 1); for (int j = minx; j < maxx; j++) { @@ -190,8 +189,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); - final float bubbleSizeFactor = (float) (bubbleData.getXVals().size() > 0 ? bubbleData - .getXVals().size() : 1); + final float bubbleSizeFactor = (float) (mChart.getXValCount() > 0 ? mChart.getXValCount() : 1); for (Highlight indice : indices) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 649d75d52a..32f92968bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -50,6 +50,11 @@ protected void createRenderers(CombinedChart chart, ChartAnimator animator, if (chart.getBarData() != null) mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); break; + + case BUBBLE: + if (chart.getBubbleData() != null) + mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); + break; case LINE: if (chart.getLineData() != null) mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); From 207af8993a58741fe975818b87149e929f982542 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 3 May 2015 23:03:54 +0300 Subject: [PATCH 0342/1390] Minor bug fix to cubic line rendering while scrolling --- .../charting/renderer/LineChartRenderer.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index f73072b04d..604681459c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -157,30 +157,28 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { float curDx = 0f; float curDy = 0f; + Entry prevPrev = entries.get(minx); + Entry prev = entries.get(minx); Entry cur = entries.get(minx); Entry next = entries.get(minx + 1); - Entry prev = entries.get(minx); - Entry prevPrev = entries.get(minx); // let the spline start cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); - prevDx = (next.getXIndex() - cur.getXIndex()) * intensity; - prevDy = (next.getVal() - cur.getVal()) * intensity; + prevDx = (cur.getXIndex() - prev.getXIndex()) * intensity; + prevDy = (cur.getVal() - prev.getVal()) * intensity; - cur = entries.get(minx + 1); - next = entries.get(minx + (entries.size() - minx > 2 ? 2 : 1)); - curDx = (next.getXIndex() - prev.getXIndex()) * intensity; - curDy = (next.getVal() - prev.getVal()) * intensity; + curDx = (next.getXIndex() - cur.getXIndex()) * intensity; + curDy = (next.getVal() - cur.getVal()) * intensity; // the first cubic cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); - for (int j = minx + 2, count = Math.min(size, entries.size() - 1); j < count; j++) { + for (int j = minx + 1, count = Math.min(size, entries.size() - 1); j < count; j++) { - prevPrev = entries.get(j - 2); + prevPrev = entries.get(j == 1 ? 0 : j - 2); prev = entries.get(j - 1); cur = entries.get(j); next = entries.get(j + 1); From 83cb3eec70b52920476ea48e027dbac16f08269a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 4 May 2015 15:58:42 +0200 Subject: [PATCH 0343/1390] Minor changes on BubbleChart. --- .../mpchartexample/BubbleChartActivity.java | 15 ++- .../mpchartexample/PieChartActivity.java | 2 +- .../mikephil/charting/charts/BubbleChart.java | 11 +- .../mikephil/charting/data/BubbleDataSet.java | 14 ++- .../renderer/BubbleChartRenderer.java | 101 +++++++++++------- 5 files changed, 87 insertions(+), 56 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 82b6be5873..a4b4f70154 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; @@ -16,11 +17,11 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -86,6 +87,9 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); + yl.setSpaceTop(30f); + yl.setStartAtZero(false); + yl.setSpaceBottom(30f); mChart.getAxisRight().setEnabled(false); @@ -209,13 +213,13 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a dataset and give it a type BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1"); - set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); set1.setDrawValues(true); BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2"); - set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); set2.setDrawValues(true); BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3"); - set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); set3.setDrawValues(true); ArrayList dataSets = new ArrayList(); @@ -227,6 +231,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BubbleData data = new BubbleData(xVals, dataSets); data.setValueTypeface(tf); data.setValueTextSize(8f); + data.setValueTextColor(Color.WHITE); data.setHighlightCircleWidth(1.5f); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 9f6fda4c39..940e4f8590 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -59,7 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setUsePercentValues(true); mChart.setDescription(""); - mChart.setDragDecelerationFrictionCoef(0.99f); + mChart.setDragDecelerationFrictionCoef(0.95f); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java index fb6cebe957..6e61689740 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -10,11 +10,10 @@ import com.github.mikephil.charting.renderer.BubbleChartRenderer; /** - * The BubbleChart. Draws bubbles. - * - * Bubble chart implementation: - * Copyright 2015 Pierre-Marc Airoldi - * Licensed under Apache License 2.0 + * The BubbleChart. Draws bubbles. Bubble chart implementation: Copyright 2015 + * Pierre-Marc Airoldi Licensed under Apache License 2.0. In the BubbleChart, it + * is the area of the bubble, not the radius or diameter of the bubble that + * conveys the data. * * @author Philipp Jahoda */ @@ -47,7 +46,7 @@ protected void calcMinMax() { mDeltaX = 1; mXChartMin = -0.5f; - mXChartMax = (float)mData.getXValCount() - 0.5f; + mXChartMax = (float) mData.getXValCount() - 0.5f; if (mRenderer != null) { for (BubbleDataSet set : mData.getDataSets()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index cca4cf5743..d82eb87d03 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -36,9 +36,13 @@ public float getHighlightCircleWidth() { return mHighlightCircleWidth; } - @Override - public void setColor(int color) { - super.setColor(Color.argb(127, Color.red(color), Color.green(color), Color.blue(color))); + /** + * Sets a color with a specific alpha value. + * @param color + * @param alpha from 0-255 + */ + public void setColor(int color, int alpha) { + super.setColor(Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color))); } @Override @@ -48,8 +52,8 @@ protected void calcMinMax() { // need chart width to guess this properly - for (BubbleEntry entry : entries) - { + for (BubbleEntry entry : entries) { + final float ymin = yMin(entry); final float ymax = yMax(entry); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index a973d62560..7ba6b9f748 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -6,10 +6,10 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.BubbleDataProvider; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -54,14 +54,19 @@ public void drawData(Canvas c) { } } - private float[] _pointBuffer = new float[2]; + private float[] sizeBuffer = new float[4]; + private float[] pointBuffer = new float[2]; + + protected float getShapeSize(float entrySize, float maxSize, float reference) { + final float factor = (maxSize == 0f) ? 1f : (float) Math.sqrt(entrySize / maxSize); + final float shapeSize = reference * factor; + return shapeSize; + } protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - BubbleData bubbleData = mChart.getBubbleData(); - float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -73,33 +78,42 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); - final float chartSize = (mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX()) - <= (mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY()) ? - mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : - mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); + sizeBuffer[0] = 0f; + sizeBuffer[1] = mChart.getYChartMin(); + sizeBuffer[2] = 1f; + sizeBuffer[3] = mChart.getYChartMax(); + + trans.pointValuesToPixel(sizeBuffer); - final float bubbleSizeFactor = (float) (mChart.getXValCount() > 0 ? mChart.getXValCount() : 1); + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = sizeBuffer[2] - sizeBuffer[0]; + final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); for (int j = minx; j < maxx; j++) { final BubbleEntry entry = entries.get(j); - _pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; - _pointBuffer[1] = (float) (entry.getVal()) * phaseY; - trans.pointValuesToPixel(_pointBuffer); + pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; + pointBuffer[1] = (float) (entry.getVal()) * phaseY; + trans.pointValuesToPixel(pointBuffer); + + float shapeHalf = getShapeSize(entry.getSize(), dataSet.getMaxSize(), referenceSize) / 2f; - final float shapeSize = (chartSize / bubbleSizeFactor) - * (float) (Math.sqrt(entry.getSize() / - (dataSet.getMaxSize() != 0.0 ? dataSet.getMaxSize() : 1.0))); - final float shapeHalf = shapeSize / 2.f; + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; - if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) continue; + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; + final int color = dataSet.getColor(entry.getXIndex()); mRenderPaint.setColor(color); - c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mRenderPaint); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint); } } @@ -107,14 +121,14 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { public void drawValues(Canvas c) { BubbleData bubbleData = mChart.getBubbleData(); - + if (bubbleData == null) return; // if values are drawn if (bubbleData.getYValCount() < (int) (Math.ceil((float) (mChart.getMaxVisibleCount()) * mViewPortHandler.getScaleX()))) { - + final List dataSets = bubbleData.getDataSets(); float lineHeight = Utils.calcTextHeight(mValuePaint, "1"); @@ -153,7 +167,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsRight(x)) break; - if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) + if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; final BubbleEntry entry = entries.get(j / 2 + minx); @@ -184,13 +198,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - final float chartSize = (mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX()) - <= (mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY()) ? - mViewPortHandler.contentWidth() * mViewPortHandler.getScaleX() : - mViewPortHandler.contentHeight() * mViewPortHandler.getScaleY(); - - final float bubbleSizeFactor = (float) (mChart.getXValCount() > 0 ? mChart.getXValCount() : 1); - for (Highlight indice : indices) { BubbleDataSet dataSet = bubbleData.getDataSetByIndex(indice.getDataSetIndex()); @@ -207,20 +214,36 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + sizeBuffer[0] = 0f; + sizeBuffer[1] = mChart.getYChartMin(); + sizeBuffer[2] = 1f; + sizeBuffer[3] = mChart.getYChartMax(); + + trans.pointValuesToPixel(sizeBuffer); + + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = sizeBuffer[2] - sizeBuffer[0]; + final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - _pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; - _pointBuffer[1] = (float) (entry.getVal()) * phaseY; - trans.pointValuesToPixel(_pointBuffer); + pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; + pointBuffer[1] = (float) (entry.getVal()) * phaseY; + trans.pointValuesToPixel(pointBuffer); - final float shapeSize = (chartSize / bubbleSizeFactor) - * (float) (Math.sqrt(entry.getSize() / - (dataSet.getMaxSize() != 0.0 ? dataSet.getMaxSize() : 1.0))); - final float shapeHalf = shapeSize / 2.f; + float shapeHalf = getShapeSize(entry.getSize(), dataSet.getMaxSize(), referenceSize) / 2f; - if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; + + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) continue; - if (!mViewPortHandler.isInBoundsY(_pointBuffer[1])) + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; + + if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) continue; final int originalColor = dataSet.getColor(entry.getXIndex()); @@ -232,7 +255,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mHighlightPaint.setColor(color); mHighlightPaint.setStrokeWidth(dataSet.getHighlightCircleWidth()); - c.drawCircle(_pointBuffer[0], _pointBuffer[1], shapeHalf, mHighlightPaint); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); } } } From 2576308412fa1c7a6e627a33b0cfb5c43e5456ba Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 4 May 2015 16:09:24 +0200 Subject: [PATCH 0344/1390] Added bubblechart screenshot. --- screenshots/bubblechart.png | Bin 0 -> 218355 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/bubblechart.png diff --git a/screenshots/bubblechart.png b/screenshots/bubblechart.png new file mode 100644 index 0000000000000000000000000000000000000000..c04a03529ba997e89e271ed4680e68f9ca73c5e9 GIT binary patch literal 218355 zcmZs>1yEaE)HNL3ol@K>THM{O6nFPfTtgwaQz%Y>;#Nx0;x5HY3GVKN5CX;h&-1=B z-+c4UpSejcHzD`jbJksZt-W`=wx$XmHYGLy0KijIRn!FlP&EJmBnC`$#1RKQp&Y~; zmZz$T4*)>M^4}9lO_%u$0KnGzprD|w?d0L>;p61tNw21$K=0}8;rPMT0RZ^8lCKBU z*E=GUy4kpte-{^)@yKhIQEJF1-hT`Q{I{idSN~lz$MR6!eNnwev zbhvOoVJ~6qF_a`lmd1Vh{jd!#by?`TIhc5EUX(tpzQ}K!#OTAs{h}(MBNT>PDNjqZ z6*)3EyuHUQ8;;HF2_VF5v}f>nVnPDkhDb_sGWKEg0FXY;;$Q;$-skr5Qpdg!9LwjJ zBZWmF_4%fXzQYV71;_>_$$taLDkFvEXTQ+{6rlpF$L(x)0orc?)~ulivw*Pt+Z-?w zz$}B|6;e?ufS$x5P7&ZF0jQod{G)iIHi4g zd4F$jNqtb>%;vXI@H6n2RiDw5>s^TCh0FAKbIQi)RSpgQMPLb z$tsVnI4_Shvy6jkw(Z6oq`NxAUP+2y6EFD78RO;C*oRnVUhH=^xgJoYH-!N8&eBNW z)VJR)>`<=Xu@V~l_U+sN0RK8Y`sdg%QNo-ewrI!lk!Fui#1p7NR=1`@JBqxbgA%Vgg59&&EYmH zw0{?&j8ZPanX>og`T||noFwR>8Y6oiB_;g zuu!6Oez7v9e}C8Xri18ikldD^FVLo9=fo^v#MFMn@fPhgK~kKvygcD}8wSJ|!J4x8?8 zXLX8w!hOMgbcbwyIfK%#y6fMI^@)U%P33EfTXgGmV!x9J`h69fh$K^cS6)++IZNsE z+Ue#)-Cy4hqV-H#&8#V-neii)zgd4#F8y)wVqQg#!~xkTa>+5sffWAab=exo(6<6YG$z zBI_dL(*`M=eTSXuo1jKJpM$x}k1ttYjH^_ubgERK-NLo7iu`ZgN}VPT;rMbR>a6Ch zD!^n2TK=Klvfg?Hb_LmcDe*efFAqr?o{`ma9R-U4S%q?&Oq;CjsMPjp$*|{2G>p&YI2&qKbCSbj_-Q z1>ivadCOQ!Wh+Jf{u26XZHrq=uno}mHL!K4cHlItRx_{LXA-l#JPvk{hLj1dkaqcW> z?p&(j_0jGAy5i|xRftNh%?++VQot97TsryovZ*9!j#7P1$Z2>475j4EvD>`%+! z6lU_eY*vS8DQJZQn-7_I?08a*Y8LBT%l&`c*uY;)UrT!z?n>`Uifr(2m{|Q0>1!Qr z9oHK0D6op&R0w5yv407CnFdsZu^<6a;=|>_&5$2%1A`cPlVrqK9j+UeVRDH@?Q*Z= zk|Sy&_WNrXoJLPlY8Y+~vmvRF5BSmAA%7R9Fl-KN5(YwWS)*g4jbdbyJmZWhr}?sk z{HNCxd^Q#D6~8EMJH{WASa{d;}k z)0y>Vo5frA=~F6j*R|lu{Hj^k&6D(4&#D2E!TWi~d4~tJhsGP3+V~$ww_hIIENV2} zykH|JGbm3OO!zH}?Q`=qGgA7x$qSrN75ovpp67hH|64p^JcG}9!#hl#iUE5^H&~lD zw0PnxphR%>HpVO+hz3Z*<1GL6-&f^ay{`{uwq_k#f25}ujyD1yRaWT;@&qMK0@N?` z$3CnaMa-rH|4k<5XXXcoaNn(2ua>lc5A7hE&IBIt4np7U8KswmLy0a4i21)Z-+v9O z`y@tfMqlg1t=x`%k0qbeXSGH;^E$uQwwt@Op9Xd}gB@>zCaD=VUJn^95p3 z>)jWD9ydcbSDR$(A>OP{knzrCf7a8QF0C%BOIeuQvch`oyo}lN+7f&%)Va^U=wfRK-I&MSA)RDoXanqn*IpRfOK8w^P-94*&!r^k!Hj0C4w$cs~LF{CEL?V`~6F zJR1Ob?U80Rqzph&r&Uvw)Bm_~@)VF_zidLAC<7O}IWPpn*Jsxo;iWm#{AuLz^T=3# zMq<6JQHC*d0ju|8HrtqlEnc$Zt2U?%WYN)Xe|GBoan6b-&#-Wqr-X9_UHm6!q`KdG z%+EI)xr@NPA@JnRe4o>aAAhRNe{@_ZI(6u0=CHy|HueKHZvu|yD)nBMX9y^w0#bA% z;`m>_hC&^(3v+KeCwfLe2h_vn$9cKIr;eL;5xfBGtTk>u*bU|HMF^>BNCX9QbVe!3#DF%@XOZRKs+~8!J zvHXz2+@DgO&}G`vrE$4Ce~F>cbr`r^;cC8Ph#VpQ`~;RkJl;HZOFl`qJ+Nv5yOVFB z5F5BdoeMTVKCZSG4!V9ZY-bXAcv^zcP(%mOjOUw~X>DM81NFu2gH+rL8XL{_?%d}l z@@qXFJ7Chg?mwZ!9d`$9bWfs<62UzF@$LmJVS=`p#9835V1RK~DvG`TpdSqQ`eDNG_4m5&^M6OVB{h{QO)C{KQF!b>X?=#<<)> ztKPn>%#ByoWXJNpZ11991vKTSg}+Z;zRg&;TtU9skn-k-8#`lf>mU%Q(4v)O5+5)X zjq}=&?|_#g`JDX!Z;KoG+H8S-_`e^@CBs0el>g^z(A;zK!ixVsT84oVk<$O$TRPu0 z%+j+f7y91`TM*ghlh)hiYe^qI1l=m2XlQ7Dx;=C!aA}PNNnBi)!hKqswV(cuY)o7X z!C?m`7j4pk%j1@d%~|&imXP-{5N8o^JB=>;MJK);4_K5fN!Iusd-=)z zTK1;TlsBtZ!KSM>kW}2B^<=+(@yak&Vj$&kRjg{ayGzVhwayzT(Q;Q)rXXy#s2L)| zCE=az4P4@OboKK@Z_diERjRx2V{*N}O3Y1VA~-(5wdIi@VjQqslsj>dfgID{G*AUhpGvqk ze?wp!mNyTY?9khTu=%Q1Aa0b%=_7&b&V&ijjW?-x#b!r4Nd<7u8%TZ#Tmp+>gMp;r zWuErgN-bWt^{#Z+#Sn-HM`6*XH;@&2;J(;IBEd;O&9~WVcH_PDKNn18Jopto`|^UJ zwKHxt--j?C8?=&F`f+%@BWw3UTv}qcd(8yAj3vs8*llb?3`5guab5h-I2M6IF8>x8 z4;i!CjUUo-y~x+C4fxAgz=}faBK|YTh*^iKOfuusOuG(EOkJCH!JE>tHP;wK2 z*GW;!#dCoTSMQ3|ney}H;?$tna~g`ryvTceSK|btUJqj-4aKG!CFs>tcNb5xien0# z>dNxEL3%Zy2PSz4y7ndq7A?XldqX8(V~7en46sN&$33Q4 z&Ciu9`J5}|(t8L)txg~c8E*gpdf@(<9Kyd3spj+YYh8MkA5G-rXfEhy8g?<2idKDbki-001q}uA@IAKEQBYwjUrb8-(41|PS zD8iHbcm)J}^zNiY#`80Df87LoLP$JaxcouGKEy<1uV3p_>hlT-WiGjk zoOjfktZS^`&EA7HJ*5ADgc%`R9|S3_6PuONTOWeDgW#40={`x((P*RzO2%KJ4XcFG z{0wAD=`0*tyuWq4YI+J8*0iLH^pVH(gosQytw8d+tD&IDfg%W`eovDNgL-6H$GeE` z;y+Z~ZNPMS<1yt3nPY+~{@G_wivH-Pj?sYIOEbzhE^8z%h9JLrI({>q5I#3%Le=ED zej1eLGY7pwbxowX2!W<(`d;w*je_-ii_L}JtPsaUzoh#Ood?u`DYMnon#hfJ!{n5o(XpeE$?byCG(a;Q zKk8ar^z`Q6R;cnw4Lk_Z*;TvEHPHR4T%7!SB{sg#j~y*P`P3PEl?VIn+rekqI;#aH z2hQg;YP0#~mn^thShPY{PM=oW(@Wc!o>EY}K3!_2qDa{A#0IOZJh@d-uE46HyahiC z{mW+Io%x3+2PcE#f=QQ^{4N!BF1>9-9VUx5GNleC6jC!)wKN&-JrusGt($I~!Hvtb zxXu=WFiIUsd3{&FqN^0<%bm-*LV zYu0feKWUe2RGuf^z(AplKQDN;5KHPf%L74zam1|9O}3jsAfV00*}@A$afu&0-4uJW zz1QBIdnQjGdo=AY-7_S*^YURQV?~9H>$G_3ZC<2^GZs^SA!%6erhukA|6Z{4h1A1F zVUAlT!;Q05TJ`Dsec$(>MWa7%ByN(fFq(lR9Y#lW-i~bh^Ni(u5kf3htD;p}VQvMX>08pTirT;xb zeDFL3v$iso`u`Ky&;V9gq0g{UZ`i>1>kpxaPs>N(_S`*L9`QrN6bXs#6I>MD_GJW2 zCN(Ac>|1~5=YHVvuac_IzvB{kuln9d=LI&L>XAiR_RQmf?^D}_0cCmLoU^)(ftwqLxmoukCn5sw&o;gAKGjCGhWxZoI27pB=%=lM?)& zy4TdvFToH^dvh6htQb({a76?CQX$q?0Lbct=WX#Iw)p+pyRq@>jro)3ZxJZ9aGa08 zr|y%>>TA8z><0l{#Dbmd^ZKc_f|uWaSpR-9s|A1$L<+ z!oTG>#W1ik?*5pfdHsR)I0bfFXK1;uW4=lLvg*zkMaY(^p8fUfuPf-{xy;Mq%ivJL z>z@q`5xp1w&-evF|J2%QaTw))8Y?y~4+5nxC?v1u^hCY)FhjO5LI4CZkGu$WXl@F) z!XYL?+#hdPSJF(Hb z{_b0?!^Y#2{B_G$7sAQ*<#xVam0qG1n?Lg~%WKXVk>hSxe-maZ{U@X@>RtIzx#)hbl^Ec9w77zHN1Ihn&9-B`SQrtnj-0t3xgBiwT87jV&yc2vM>4 zjw(oFIg9o>pE%+`SI_d-cy0SzH*N&pSLb?2h#qAL< z|AK-HN5t(B$FtVj=TDHT774h>53dWYX5Ri#%Zx<6yN_YL_U}9`$Hc%n+ z^g;4&Fa36pRVH2n-bDg9OY-kRnUr~v41q0%;I(dsNYI8pdR5oe{l7lsf1Qa4$}16p zw&vW0GB><&L#uD*+`A&77a}^`S?2^V+cKyC^PV7z#afGjl@(Lnq+L;bNP!g2h}T)o z=6#JPHS6623V~!8{1E~le7U!J!AaWfYk}=uh#g`^0RH+ZB4 z77U~^sd)aKVhB3*DI93`IkYw*bMJ%+cfs5|2DS%ce|B{x;=JZAGUl?~>a=W&Q4vcs)~?)=*y2ZS-HBo*maTKoCE0%)_5o=qtbAOTEkzFc?z zAAjdATpq9)w5<;P-=6XR+E?j~K`W{#SpKYx^2K3$=(W`#hRm(pWXw-q8g8 zOD`Nm{P_8<%=0dxd{|tc*rIfn5B_S4kBm%6J|QDR7}{l1TQ-hEl}(G^DooX@*K{#y zWa}C|Y~gpH!ooUcznvYq0Uj=+*tNG@oc=N1JUJB}jF z+X0zJg`le{t0Aq&K`m=T^d@|HoFd2yDjUWMO z2K+KI1Pp^;U{Q8`<*;LKHC?q5q zl-0O82|e%#pkH*)9dF=TYx6<@Y>DCrZNiV&aCbDCAJ*jRJa`%$Qov*6k-MUv7OzFz z*OnG;mYjLO!3UQ65cdMk=UhTYq(uWX$+&jVZ%fd{Q%p_WKj}Ktni6d`=D+}Q@v_D4 zlh#D4A#*c|(Qg|JjEM2Sho6vvt*hGaE2&~X5OBSH%VM&;zJwAfsrQs&_tYd6<3=!e z?Q`<(1RcEP*eW&GtHw@*Dz|fkH%|MvLUZNR5`PDBJwR)nXyfLFSFZbE1QBT=`yJc| z2M3-nPdBV;lmT#P`#T7NugUG&9!@*G_C|>WbKlQF{RoM!PuCN6N0LiTYa-&#wjv2i z5YYGXB5GX+nIT7+clcr<4DcMkmZPI%pO{MNv~00Ud`LkS8vO4C2 z6y~JIAq_Bn z!Q#!+d!%%^zbQI@t0t%eeNHudCyQW6BVO9vS$v2GF}TRe=dLH&yS=MfQslMD1pV@f zN4YK*-ThSTS!P`jTIe+}G^Y2d^##Pgog)A|JIM9eaq|FExvmcXN0*hA?2m}B##g@$7g! zPxQuv;oYwRp1Z?%kNtFyNT;1}={2tr8Z3?sfAToY9(bv4<<4_I$keas2i_X|xp^dK zAkBbkzK9^m&&s8&-2&(u_cDmo!O&w!B)SHuVeJEkD86k^P2Ys5o>?=-aG09M#aDg2 zCv**4aEDdcn0uoI22AT(+-hxX!7DFy8D*eg^7sm;#q@0#)B^r%MCRG+@fXh{@_(@1 zI@=!bq{cwt;#CU`T}6ORS%*M5r`L{sKewToxqxo5o~-{yC? z&ia@;0@v)r0~_P(AQ@!_j2JHvC}NG`dih9+6_MS%J;A*fYc;dv)ySWQcPGAk@Bfcx z*^MH#a~TA?rcK<3LPRADThUv@7Zw-K*AY7LG zp(yBtJOtVrf{+sCeaFWfT;spacSp_)MeOYE%XDbMCyJzF}7V&dKB;ItYN7xqpI&l{U z&|?C}{MJn z2}6ts(nkafLR7PFn|=+IxkS6ZoaA73wB^&TZbkP8p+m={k1_|xSB!|nRyBkMx@#00DSx2zf4{OavKjnEW1c<lC zA`Zj<$S#$i#!-aGNxM#x$nu!RhH=}2SK8+{37amfAmoz4Ej3o_F~h&PYA3=PDj!Hc zH5bOXcTU2h&O@|^{R&wS{W zqT9l)wvIITR5ZqaYfoWslF~y!f!Rm!EA%sbW5V)!{JTeMPXJg-quz}We}x_%*Ukfz zZnRikvSDl25$ldb4q0KJ3z6u~N92nO91v;is>!t_|HTNWFmq>&s)7poW8dUns@k zS9}HZOWmFYp28wCa7CeXKijEF1=JYusF8*`rmPqgIjjS8!PCy$ZvexuP#ktjs5y z|C>cmJ7hw`lBL56?a*U#eOeor`y=+FI!|siziXjzpoeMTiv%JEVG~-n&H;^S&gur? z9WQoVrxEe}5sURBd$`J1W}ozD99hy_gN8_3)%ll^(6(grH6znCYw>cN zX6qaiR_PVP_8ncRp_MVv|dZrjLjAn^nm# zP~X0To*iUu)w%XrRWcgaDSQIhn{7iWqD@#^@J!rf5N=s=P0u3+CKq3 zK+5X^cH;-24b2LQ3kX}EJvMh`i^$N@|uL5Zh?l+L6#LN&K2oT zi2qk}h9Oe4DqnJ(zQAh=*t~jb{e)T-IL$ENjfv5}&HG8BVcvu$6Q5$C1D|8%>mM~# zLI7c$&cBykKZkN;ZOq-YYJF5DELHk@t=sM>+{SmMoA0n>w=s{EV{vDbsH3Z)tsBRC zow%#4bXGUz7MUFe6EGo`W?%ZWC9I2JpzBlR{2Q$-x;>% zi(y>l<+3MP9-R2`#2T!wA1yC)WCo4*mn_~&N5r6bgit{4Ts$|ws??jJaW18B?Qz-6 zW}f*lFwMsH(f4!V%p5SV>DD7DTTfSEqUMB{pw5d&Tv47Kyh<6errU_!k!tPlfzjXU zvj@r~B(g6r`q5l1w;SyB@t%$%^0vMEVITgw?zegPTRad^P+oQoNK33s7Iti|y20D@ z{6;kq?G{d-An^rbO&OTq)6SutV-gN=<2qX{8+M>vT-SOT!G0}o(zl5+moD7 zOmmSSk4uU{%s5wUZKp^=J0efw2)0h8Sl5cTf4@JaXu`sE){=FW{07qe%))6nrsgzz zV9MY_M^Oo912xvL03INa5Ge^(T{X|{Tpn^~8T~=z%H;qYD8;<~?VDSycD)6*L95G5 zRsB&@wQZ+gcXwILl?#suN`ijzSEJJIA?C0Q!Yi^hPLU}|Km6yNKxEIeF@EL}>$HEH zgy>k23dHA(Dl{4*XSph*iMqnAR`aiez(B!m zXo|b9IihGMb7jyf-S0ld06SeOf`ub$T}#(}MfS2X*A1`N*Pxd8UMcfBP7>mi19(~+9fjT4rO$(R-*lZ#NvfI;i^pkA9RZTMn4#h{5pCUF_O zG~ihBn5P>{&?3$dhd)Ip@NHxnDfu)55!+V$Gf7EdLtXq!uZCoA*V+QyL}d~^xi#90#QL=yYc2!_^!88Cx=L1j9!G0 zI}BtuW_6z|(k#b|mlgWk&s{@!Pr_}+ede8LZ!d_#MNt~vFejszoccO{V&CjYc16EZ z)dDbL!WA>zB4o?ignXQRBk;@5=ESt7Dqs*rnQ%XBX7t z)Jh=1;hke6y~(@Uf91mys}v`c0iQb;gX0&(^ytW}WL^Jzwi%~kXCb#!kg0n5t$REOI0jz&WrN$(;Ul1Z&ALa$$iKEC zqX8-`lNi@Q#6=}|h7AZvZTvwVld^7FwHhd`~E<__c=g=&?~3@(m%ug z)3789G9#ue(ULqr7d%r}zIt(cqAu(cT73y#j|b%tIJwxu{s@KnFutS4V#yTW>* zYZNUT3YYEcZo$>@C#+u7?s)-`!ljY7+fpo3%IXq-jQ>Wsp8@+$Iy6~<>Xj88&IQZN zb9d;B(4Sz+`QV-$n(}pDm6lQkcgl7qBw-y?&R5$OR?1H1}`>G=wBvkbLTJkPr94#1KKdyB|+ol z1`jiqhut|h{1-vGZ*rJ6GO3&_I+9iz>l9q)`W;zGds0W+_;4xb8`6fY^rsZZ-s<48 zJHg|usvz{AdyxR5kwOw!+fDM;hxZ&DE(RHNT`2lZ3>F^Dhv22dZ&tu&Gw<)~2V7ST z7@b}`{{J?7&6qZm{nl%4yhZ*VthasZ)D%hfwutZhBy4SV#{IU>$}|$}NAx-Ukl`!$ zsIB!7vQq={7dtHb2wGAM4PS`}VpYXfw4EsZ%7{04(dDve5|4?pzdAqCyd6Qy{B-tu zaf^oWUDo-csLL5{FmUYYdy2M_!`L_1yC3Eph{ts9Z~MrR^#@ zgo-KOq0p3tvp9o3xMF=54*&P?w~=j!dz^3}9hI0WOqMMCBauEkl6=wK3Yws02ubuR zf$edy2TE>EgpddpsjKSbi19yPkW9xBJ^#srSJf?Q_m{mBvh^;iD+7^7mZ!aqm7{@Q zA5W5sX%$OOUPuoECB4xJR&ScQEmf{AtYW_l^>YlJMZBxjpU}4dGkB)v+BQ1c$Jd{h z$EJ%v8DG%BDS%o(#;P8XlfWn!MrtFZQ;vyjv&+*%8}TN29mlZ#*XYbgsK*Buk^fSw zcI^#%xTiEv)m|Ah7u$8NMfdx!w=FCqn2}dS@B~N{QIu3MlvGjlQq1z0g!Z|Z22m+t zox%x%zXORiZ|fBZa@kNwWa~|bRthE2T;N>adX99ARjy+_Z0EjEgCvLjo&G168>VK3 zn*mb}u(Mh8uUCA^`W4EKq+#p!o+k3mz$eG#pqF@AG%5&{NAdmLYkEl;M&HbwuXb2M zQihaM=to#>)22XKQh7@G--Cr2^3-V`j%%-Jbq^N*eB0|hQ^#tq&_sm8Hyc;<#>@C( z??K_)y;Tqh;eKC@Ej6OS=QIEUYYL_w6hL(JEWp>Xyvx$zyuTY2l&EZLV(xM31_E~Z z6$t^tM*J$IYmDC*6XI9PA;!d&-fV4Zm=SEM*h9j(5pDK1#Of1W9^{rVu4M(yb|v^17+Uinl!f`*u<{=si0-0wVqQMHZ|k6V zl>qBb_2ev@Mbd^E-uD?qaeSDI3iY}Q^-b8J-RRqQo>7WN^W%gUc-1v%XJx3Fu4g%F z#*OLq*AvKSoX&Er2n5eu%xb>vOeA;h1jbJ4PlwGJ zMs-K3eF(b4M)@yh(|{x*-x(Vs0eLjErg-raLWSLE5!p1}yB-x;VK|oHvaVYGoSv(3JDT)$TE-uQQqqCz;(Q?CVMT&kFUREtU{h<41U-CzA>Jr8Q#!w;4JbylE zQ!0Nm`!5+xRUTRBr330a=y%Bwx;GnsGK!68M;H>%Nhg<$KAeA3);X;F(_AMSq3+)r z1xBkY);&R7J_2(|$X*h|Ata;OuS#sAsGQ4Nv#*w7 zZ;Cxn==&(j4&_=T=~I^6i=p2ph58V6O2cM2QFpvq`h_BfohnJ1m!QtUFY%#Pt`<6a zllGH$LI(NY^oWEQHci94`M}cnM2HCKs$JNP9XX;nx`qT`S9AhqViP9CuIRB&eLNR@ z+{a6C3xCC>bfD6nk4-Q4^*s@W_)J*L21_!(hQrJ#X*sTr>(?rIQ&8poU7%XM-~qjD z5pv{N(8r7M??Rf4##JT%uEG7lHw+eZGdB`Ft@(&XEq+}ZAwwSuxfO2eowpz*IqLq_18IFdjN-{ki~9p2&Q(6g2?RSW;w6<}#?fV!o~-y*zgUJ*JgaQy+(e@xwPA z(Wcj~4af-5aa}C6HJe#bLa<&9{eI1_s7^k*bH;6@0z1+>tE~yk#GzL<^&O33)Ia;h z)ru8b?!6ABk2eV`HRMi53dvUV-kxM9FRi#e5TeD$W3%Lz7c_P13Zk_4(ccIN{kw$f z%?s@qhnHhz|2Wx?M2%5?>mP&gUF8a(Pm-HgU^P-Ao z^MO<{jm(*)%jh3{YJsNdE!cu=Z2uNR? zJMetA`yUSH*rVLWa-x1*Zjs@ zK~o|y%BOnC=fUl#d2tvnQ|K0MLj9~vv$MkAb;r`g{ioE=kEmfgDu)pfbkPmD6_*Kz z54>rSSWz3ev@bRO;Lo!XMJrd4VjjOobuke2Fh?$A8<6gL9o?B+z`*6RbM7*uZ$cgxwS4@V@>cFn7UR;ePnYw1>eqgz zM!MXzVReDyjKcPkr}xO!=21>9Q@8g}M1~@Ru8pR?hL@>wTx!V+ynGmNVcZ=%9pN^$ zERZ`PhD{-%PQ#BK-0X7A4Y`u?c+>Xgh795kPuDGA{MPi@@;}39S!UrZw!>G7~pB-xt zzpCqwS-7j(UM^&FRJRuNRrvZo+>fRX)HK#5WJmj*rGxK-=QYC<;4{hL*4tWnQCjsI8ZB3}%PAVixf}0l1$TTzL8?VcxjhRd7pJ&D zOZ=lQbGWG1RgYUaF<;Bi@{@L=AF@a4F~vn_E{)`;qe zX|g%E%;HwL{^rg|qx+qql8*jG8+^tbh{8$65EQ;LTVXw+*)QE7@^*502rL#C5JNF^ zirP$jnKux$V5Ss%@}rwsy+Nfcg)oT}ndiqWKn{9ackC*auaSNlW1=M}}^6xAX z>@PX`Cs_4oS9D)vBt$&?>^;j%MSE1$AE8xJ8x=c7}#65wpaV=25I~ zJJ?6x=SJ0~k1Lm~iW>igVEG55agDrcSXmfzgpd#t7%o^H3AUz_03i14XVxdqL=nx~ z_d>?m!O*S%ig})11mBZ+cRBo%o=Hr-)N&qW&V}cIex{B+VfqQPzr4R{TN{*qcY>wf zt|NFB$@Y$y^P*jM$Ecj5YP;g6H&MxkBJ7AnmaypY8Vm@{S`GNG`+M3-0_lTEP26)d zDdGFqB^$Uei;W539kUk9w;rH!{oda zw{oc8?FSH!1z|fCp#Sg)31+k7eao>bv!b1p=+#Z-Ux)i6rO^ZW*~MsIH}n4k^Xj#G_EnJT@$g?;xs`W5eJ-y+E2$=w=VPbj~b1IY(8m~ zZb;RZNhGUU0Va&PSRd>Gc)zDtW4cor{0vH%9fj4v>FNB}sGP=x&2Nsaz<9qd_|69- zcddUT8YY%BG2PG-AQEx95op@YzOFB6L={4CO9y+!1`Q~rHkcp1H%XRB! zF@XHVod`nf()RyTwzc;jF2#-FvN8UhR4ck?TKk6GfX+)8g{54)c$$jS9ElN~D1Act zV*FMc2kWTK$-*S+Wx0ayd_#rzd=Mq2mM#qfYO94gL(svC>;nW$Km3{?<}t1Hl#XAt z$@Zo`Iqk?MFiWkJm3Myi;aJk6&d(eT7xew8;DYmAr>oLk4R;HG`Xvo@#6KE|Fi@$9 z68Z_v0LEDtW}wa{!0N{umd_#f>sBj!MX~G_zsC1_iMXinl1++X;6jm~ z>w>fZRS|I0f$>vE<)Rs9YnFsf$`?cZh8B(I6_Kd>XePgWyTG4r>XtQ%OLGaO*s~)w zM37c|a;al5wj_wxR>L5jIYVRDf1}&jx$HhkTy=-YYTDrk{ z`@RV$f<$MYSO+lTRpKaYY5I`V6+y_;-rGF2C4SG8rdee4lr_BIvVFNWOXH4rmDP6f zFC=4>o3ZxPGhPgeguiLZqdNc$--Wj=t$bYv2YV#Y8nK!20cqkLj#HQKn-gZmfU;U;i?0j9ONoEJ3;pqW_ts`^v0NEy`l^k^K)lw@Ag^L!{zI4#tWfC@f>l01rX7&xQ zqxp=Drd;QwyrX9z+eI7N$#kQu+GlIMPi#LRw_7eU-65Kc5Xk;EXfs!R*k~z3@}+3b zcl3hX<@&K~=U&at^`xodycb$?GYU>{7DiQcLQ#6=M`sf68hlgp$X>(fixs7e(+)g@ zRE!mp3NKpFK-xi~?1I^^eGi+JE1b6xR}c8-TXY?k!Jw5lG$js3L!?^z^R3VuYf@%4 zu-`_>#kdRtgK`Ldm zq`x`OSs;C`2zUMIesL4f_?Gmv=k1>07(?8qGY^KJVXOl|_MunG{jp&KhPazr&BQzB zdxLucq_D{W-G``jtskQfY3D**t9JU}$`DH}u$oN(?K1WAFOK87UNrbUHbSY?cOZq9 z;uG6UDgBF!EwipLVHz`4`NzeWoQ$=XGsQ_|{P;yyRzEik6M%G^xK*dWo!5=)(h%|M z9EEKIEa@t{bGQ8xbE4j#=*ToUYbkQ${%j-6exv1=$F2iKL25l z>xlfl3Xg6MB|Aew`#{~_0pev{CX3id5RGMcuPIt?zP`Fm5efsb+qmsYP)EZ?z)^<| z?x#PQ-*Cr6zDRP{1VM&lG}=_eNOUsPHjQ!=)169C5C1qAV;mqTOaXJjWwnPX5}+9y z5YllJGg~Ky=ZNlDu3HZ=wlyE=Dvdqt# ztfb7c`Tvo0&S81J{~vy`ZQHhO*R$5LmTfOvpKQCur7gSVmbq-(_}%;dj-#W$I$Et8 z*Y$dzuk$ixm)F=w6l)39uvx zQHqm5?e)c>M^76Dz-_i_`{{`@LT(}9%Xz^0oEPp|d0ZTaxcU9ENh(sNjl8M_~Ik0%2rC?cZ^(q%@z{_K7qy0H+-x+?5(3_!N`hc49dm* zYzPZxFn!L`UQa5KX)#fr>u4{33=>pt*83Zd|?P7kUhA+mhliHpM(y-V{UA8%-Y^A6J)QPlK z15GQQz(m-pUr#&C_Xrk<&y0=E_X<`FJ%Z=ZZeNjq&97^5IxL+@!>REy>@1L%%M43$_d#CxZ=~VK`1gjW zdgsV4wHm8Xn)Q8Lx2IK3b!+fkmPlF^-`(AM=?OlGM{_e!3zk2{nleL(_u(N`a@R&( zD2D%*wjnSejL2Fr)jkkaaHvU>B}_MwLKwm_vrFF%w+F9sInbR?)D_&1GbpDb)}x(; z*|o^Fq~{)1Ni0Kon?IABRQ>%f1#5*?Vc#hMZJ}cVYnDO+qeiY>)mz6)ZomgED2<*N zRmNhi03VqKw|IxH8NJz(>*9b8#UIvdH3?dU%x3J*$^xaH-r_z%gp#cRm9Y_hiy;D> zeq@Y`Ax7W{FlQthv(Q=sgzktFT(dL+rn>a3>tQojQuKdGU2>uRP9?%8x#Ir`M9f zU$Gw?mr$1<2rw|)U*T%0e_W4Qb@^lXIVj5Ue{Cj6cN}olunM&}D9u@L4^)LwRK(SL zH^&4A5ANnqKLqyW7YQDN6${KlUO_cn=@djP%Ko!E^=KCe8pdHI<;gLtY6qof`tT=C zdVE@2HH#){YN2bCvDVZwjLZ3~RJky0WUFZRtlBlyc%N6#h`gk3^Yk zNz!xj1i|bI3aFUIveMR(CgDl!x@Zx7v8gfeTD+SbSGcEN;eyDQ05auA`agKbf)=@r zx?InDWeQ%c-1UxYr}!%gB*Kt4udxy|CN`m}Mzm$TEYd{=eplCuhOYu>hghOtqF&?o zkWp9Q!r+PV9_49>Z(_-$%{k#-Fn%T}QMi7XwB}D{DM;%uFV1T9h0^b=vaU^O8iMF@ zh{G)=XW2owP}Ofov-J-XCfncsD{yRQ%?V|-o>P8m8;-jrlXoNwEgptAV_MaumBZ~6}^jHAP*CUWk??G0=G z2$v^%N%L(^-Nv0f%mWq5eO&~@aS6PW1~azL#-ADE;!+P{W{xT~#cytDfV)Dus}5RJ zC&;Qb`#37s6zvvi?MpycsoQYiX^^%W2;03p1zwl6eoN9zLLR$KBf{5&v^a5@Z<3dZfp*H0j8gk*38u2HY^i}Pu@kM@E0_IvnpyY5S#897|3;~1y z-;-f*Sm;H=9`M+gc{_3J5eT4JORsbp^`vh!5ZIZ=<9G|y1Ra#LN)ysAC>AA*wp4q5 z4K3bbiG9?B7e5&g;06YppEe%x8P!CQA)%IqZS0w!4S82m zlxIF;aX37PtQ0DeV6EZj+foL2Pp#d_vIkczOnaSU>mJnhWo0j*^UTwzf~Di!hY5dp zN9age_-k?d`(@}va}G(1=w@Zj45?-%iZk@v5ztPzwZY%_on&}T_1E7|Ny--rQ7EMeM#5a>xpWsTm5mHPRzBMSh$IzbV zj}B`7H6TYw@grmW%d(-lfqRiIBi?jd1H9jv`)TKmll&<4&-eznhV-}S!&^pApUhcm zuajNh+mjBDoAI|iSGhA9Ne?%Ml04x_d>}>EBod#NRc8#Q;Tcm@;o=a{UE6xT=lc6= z*7DqaazYdjz87=a>5s5CZe045gdpo_=7>6xeAMf9W(TTX^qNwSiF++Obp9x?XkCET zOp9Vbqvy^2{pX+<+Y7djld=kV+Nu8jx6#nt&n_se3qNw`ZYU0R5>ENn*|DePc;Z8? zp*uZ3w0=@@p3ZzOZleGsqK^Xs_0o*XFzeDWLLOH$ z|0tU@`4h~WdDvUb*h|dblf#5jpFPp<6!mmmBue#L(oTC_Ap@JXvh@!u@OnKFK#UGA z<^n_Un!0D&6KeE@1@w}GUhf;uEVf(;bysmo>No`Wz|RZ}U20hpmHQ0rVxS%2R%B%q zwjl&v$-Yh}lJl^Wk#CkVM0*kE;!j&b0GmYd-v+NlAu#AKJg2clkHaNo>x^1yEEks{ zs@5ELdy!OC4@(HH%d}L79F9^}+$B+J2)X7wD}-PWXn_oqFw|l#c%LEQKd3X^CV41+ zZE5$6T{~*4sgE9VndA@=At7uT0tkL9Zo-j|gPgAbJDhWp*zePcy7;%Pb9r}{8Zj*R zUg)v*s?g+DoU;REhV)nFQ^Zv# z#V!;5M3f~(&|amp|4ONTyvr57f07;;95>=AhHMK!ZhLnr4!jk*q7D2&_PfPW9a`a$ zZOI*zeGQ(y>2kD-Jv^5Yx|Ax@_%yGc^xS?Exe-{+A(#0jVcIAHlR_G{h^TJ>5)6Gt zhKX?+Pq1u_||H zaz)=US+U>6*KwVt7jYsUY>y8FCIz*4*Gw?m3;aUh;3?JKP8X=EfNRZR<_jMaTf>r| z0^!7_sU$7cgmMjr&%-5+x5~nfJ=K4&T_rU&m}Q!Kc^P5 zU7fPJVkfHK`uDePnluWrYeUb2J9^d#2gb3t8W3>cDy^eOGY`bi_8w<>v`6$BmbeT> zU~h3~$O#~m?RdvkZ&K&?0bx0Iqxns_X}|A0X^8w)F>A-{u`K_W%ime5_3G)vIHx&T zW_bjy6KOK)M=K7ME{M#9N@{jtN7==oymc<)9<_BQbgXQn^UyKRiUgpzemuNLWluTF zd5D4B&@u*MtX6@_4)5iS*vHM|>w(yRPfq|xlG|~9;D3H_SuFNk3^1Yq99^S@^l_U1 z#`QXq|B3*#?o4!WMK6QUHZ1`R-Wh0V{i@Awt#{TL1aNTwm!APd-B(22K>#ls=o$~u zrXaDqPhw$?uS1T~h3bJj{QY9X;9zDXO=jbro2h;QR~o?|S{dJ^OW2bVoTcOLV>D8v zL|mTC3jcU1&xK_8*;F4=#c*qEI>Sr$@jq5>Ptlvbd0;Mcjfh@t#E0 z099)STD76aBW1O?N}xA;WFYs8;NXQ{VaX)U#Www_sUPRcq3psg>KKw-j!nB2Vt`H5 z6#NE`hP2Ghk?)1yBev4gt>^CaP1v@5LY?rwZGRHS zv$_IX0tRU!`2g6uAuhY2bL&GBxkKN<$`2#MvzdlOXn^a8H5&SjmIFP%!o;PoBikB3 zOccESA)#OM07-Nbc=+H4Qt%JAEl(_Ht||=~Pbe39KT|G`A^N({ z8vd`O@V{;K440zT2=)yf4&G6f?r)QS8dvy~7*ka6ObdFVyuTs>nUiddD&NAHdVmh4-)w8a2d-MbrsKqhYK2HFv2{6H# z;9~`{J9YXm9`)<1asP1A^3~S1G$Ak~KoT)aJww(2abSlBMz1W?`!THaUjzsQ(zGSa zugeW8rDl25E5WCXljWbd5kbt`caV|4V5MQ>k>;{YD%XIof8~4}r$+Q7mV8QV7f;0; zkQISeYom7lt05Q)+9s}NnadN18oDXpVsQ-BA>ue{SCp+Wzd5XzMO*-{_PC_k#3R?r zl7wq)FuS^Srlf$;rSIcYApb#19f8eLemFqMFtE=c0*FeT8Yb>8V7QyxG~AA5wsXFk zm_X#eomv7_uB(Ul^^N}PYnSV`ufOAaAHHca;sEuXtq1>$hs*qrn}8vp8s*@3C`Hyc zI*OR*bIjm(`jxEzUrCjH2pwM*{eZaZVrT08bn4Po?7=l7GqZQ&tvvwm&WEI~`(5z; zNbIfraokcg1dhxPy+*5wt?xULi3AK0I%Hh>~M_b z+Sx#`TVeMGeS1{m0<{kvLo1JUS4`d$<&9Hs5sHp&(bIJ{uyofX?M5rwDp+is`9OFYd!7y&_W z!f&$H2G!Pq272hmE^FBeonA1o9mU{ZF1r$RHmqq9i%sfI$j{-Hafe&f1NOLWjQnBN z@60bN6~TFUO1XB9EFulXw0Q|y;RP82vJkDKb>yj{Lg3L?_@rwT)3@XV-eF?M(_bkG zZgIGl1?nT=w@^*BEWM6`=&DGmzb}y7!DA<*Jv`n>;m&e%Q}|_moy&WuOXEHJf_ul*Zx}&+V}f$Hv}xy=1WJ4WQOd4lx)c zeS1OoG-g(oOTu<-v)9vYO`vThr#iM`cXNoa{uhmo6Zq2*S9o4R6Fy*`*Y41kj!8jo z9zj5GSFTp{G^zu{iR$&e%xTXEE?jXeT%2sM=}|5q9fFfn{sFe@g0+E41%Z;8%~(x6 zY`LzA6!}ByNDlQvcm_XU%|f|U0cav2Qb@a~pxcfo?1N}Khe@gyNASM_z2gXToyS75 zXNuQrwvUGU2if8v-~(tv{ja@yZ`&RI(0TFgajsl6>|fVOJR|J7?tQ+ykL-PmY+H)# z8C|gyQ<#k>7%0W+FAma)ULk;b{(bga^!$bg+N^s&uDb+!jk%8#8?P$=>pB9pse)7x z%35N~Xac}c&gF@~Y&G>+`JWyRl^9+XMyhkCz6hVL(66>sg_%~2+WE0*SaG@%Acu%g ztLC?d4q+%fkJAmMGiKRQE9>GDKtvo%V}36R1;9p-mhhs_A2JuIlBqKgL?_FJsNc<^psuI;9xg>An*rr zt=Roa*GpWjKD%TvLfDyn?V=n#q{gm_+iCx zJqLYh+kJN)4~F15*rvTg;4z}vearbe&sd!qRRK+>x|~jEV(y?&rWtL8?GFbo+Afr$ z@9AmSVxr2%AUw@K3AYwf!L$#7;QSq`M6EqgP7{L-**(>Pc=TM+@n%@Bh)}d=f4tPZ z116Hji_N7!anNd&YJmxGMwtMjJfoW4tW0TI68+;h!tv_FiN^_g*T6+88zTP>BV4D68DyWg3M3WYH0G!>BJL%(TTJOM2>u0Nlj0M8@0?1}}GX*M|1^a7c zC(4@(!U9+9A!6EPp15K$fS3mgiV%^JJVf|0q;UN=m@q=0zgU7$Y7G(+M7PDnQX z=U*iP7ysUd%{qsIt3K<0WE>}akD?3KDsD#220~q%#M?>if?z&p(ll}ha!dVjxFJ~JNMB;PLs}OD?C6S^J1f} zbK&9JV;9<319@oA)6IeN-SOwwkbp}xpr!T>z4VxO@kIK+BG$jl9w>2Q#|*}b>lhji zHBO1fkO3{gfn+t&D6J|O3TRTFLkhpgezKu}N3;(JwysA?#nPEFxY|!!i;3jPnAOBB zl6Dng-#5KQ)UXIeMf$KnPj3u~SqT1!B(Egru5lOqQJjNkvLrAb z3yao1`3{F};q|CGkryHXH=m)aqB?rxJ{o}>6|L#qLywbuN$4*0lGZQ*hRo&9MltSP z&0i){0_c=Y6o3D7I5_>?hKW&OMODG`hu@pjHs2SODF1^nc%E=c8lhSrQD{RQ_UHTs zImOod$frr?XnIN)^9BI`^n?t#d6u#BJGZUy-!pGo*M%pTN4gK(o!p#acP2Qy zvs<@HhPAkoDhTbJaS;!YHJQa9A-)?41U)YrMpW?iGf$D852`;jM9e*&jjx{Robg4i zv!6mh7QXipJn}8{Fv`F)pg7bWmMCW0?kZ+vb{|JkO~@&q1#qhH8Kg0ovyKF5*;PZM zCeGAfjMHN4{L!|5`5TW!1Dnnu*A;GLL`kL?wQk7VQ^%w6vQm|hmktdhSD5{CcaShh zq(0kCo-O~!{6ldON&~Z3OqG*idt_YqBjIeSdKDB7CNv&*+z$oKze%9VV%cv2zq4KWUHN?g!zSZ{vk`5yc{s(j0sj?YwHiuV;c zCML!>w%3{Xe`RFVoSu`q?s(h9S_*hbpzvK?Q?u2)Xb5#cEEi7<0rJX&TXg>clsP+I z{$31~Dy46}blpGYxbnw`a9K|FI1~S?#%AQ?gzoSITW90gExoQiJ)q+acr5sEI`l;H z5og>&-({7z&tEx#9UCHvyNo(DqE0k5i@rN{$#uvaYO=GR!sims#ojMF*x)@04&mg> zRx@pjA}R*KUrEI8w>L=}F0e;%z$Bp$*h$TxiKjImwQ}gq+(B8ZJSc*KG=HI*l0p*@ zUc&}waty3On#xwjN9rYxgqBmsUk(LpOP^3P?3yG9mZkRonFlkZ>gduQP}<>SsL-Wp zDD_`Hg~jU0R4proBS!1iJu#gGl2P~MwbmX#qq?x&*d(k@EZ6z$)vRFNx93`w+ehE5 zJm2la|I2zJ3kDCAxb^-$dKS7ag@c<3ALpRe)mP!lYaB+Lc4voBIjtMl&nFcVzzyLQ z$dTfylC3e@tY3-U{nuN~^lso9O7FpcLjFqSMh6EuCZ%V=Z za5(mw`2tbElr7LrHwyJw_S~&8JtRR0Kth^$?1dbwPw>OYslOJA^l9I=vwzmb413N> z_~Mke%KO8}rTmj`!S5(ZA{P^!nwv#*U}G>ss8F-doW=m2pGeRZmV$ZE{KK)sPjAT) zrNzW+;L~D`_&SopO}@sOe7r&5J&6#VU}}jDFZtb5{z#c7wW20vcx(sJNKW9Db+lUe z)OdfQ4yayWUeEo2I5*D*=)^M)E5q-?zQ#*}X6;jpBl;xEP>CIhL4lt381rnMp>b@& zXpWVLygCp}II$0(+zxJ^@3@)rkO%Wi5$AW}>=iw>y9Y-$Gf%(&8Aazvpln3=RBaqo z#t2W0H(!_6Gi2mPGPyivqT@)d_EYeIYFP<#702&M{5#fMnh=-i#<4xl!@ND1Zcj zzz8ic4i0}h>`rR^ig?ytP<1|-e?6GrsjaTw#0$8>yE-iXZ+nC;e*mc6K5T8guLi`7 zrLz?S+OB0g)BmXj5CH2!n7Iz1^vF9f@$n)2{U6zsh^90kVX6P|0|K>+GgRad2XaOgd^~=@h34N5m1nl7sp!NuS^U0MMUkl?3!*=Fg3h9b57*2wJG8du zOeP7O!-Q2r$Ievn=X?(cZaSW#Gt=#q2=Adh)S)~2L3{S+Qz1|mvg)|Dpx5MYHdyR% zokyKMr~Y1N^m@n@LXI;)SXiU1cWyqwJSOdL>_(|L_%qVMt%Hv;OD;qG^YKg~!Dmh( zqD09G>^mho&Ogos2sDM#DYFMi5(G1on8=AK!gOB~f zbsb>jYMfQby|i$(r-5q8s>;=0Ry^PRo7i#i_dAm|pYQV7icNS*3NYE!{#bLh%4tJi zV8N^YBOgVA!*Hu=oPr0`1&OG@;(9aJf58l;a!H|#x^&UNmsj}T;mmd4+d!j_v7jtZ z+yfO?;GeXq+Y+|_?>m+SRQK$@3@WdHWL%0(5W@_8L52QYs+m3rso$HU?Xz4cM)66wGD(AL-TFMny%xR_Cn+0Zj6I0Lp zqB?H;-cm3pPHw$K{QNd9$ZeuN4s89rq3>u5pa)=!q*m6(9PIy7omBnl8oxq%NWE%Y z)qEDwML8KLUhp)Nt^KmY)}L(z@e9VnwV5rbOokqUzQlzsMWED1#B$2d=gZA?>CB5F z7>279)=-hfo6|R@^qNZt*bQ#gE!4l4PlcD}-)YTx+p+_O#J}Ia(S8L8t2?~O0_SaF ztD+Q8OA4iCbiP!$Q4eRE?&3zJ1I5`>XyS;JK!MV6<1uH1wJ5DQHDeO%H-)4i7yqOJ zy=hdg5W~*E{V3OjuJkMGwmT`oR3Q=93}7YZ2iOC|{z>$>2~qx;mxzdny!KMRTrzcE zGihsU_td?P))_lEpynMEYBSrggoUBgV5^bg#DfJ#n>*udF(T$30QOaVrlRMm2u#^0d zxMu3Y$q}Iv_BiIG4xeyGLdB@C_EJGGkft@LA2X1riZrJee`O|&*sQ+o$4U=~_uchI zk_-IDNq6f=x`6RXGeVA$Ja_eo_D%%8XipMa^t2N3G?M}TcbMxphSNV9jK|fFDU^p= zKR^`y6`1@}9%mGg!JwcM2}t_WTo|^M%Z2agC~%sL6(eGZ&!qYGBH?!6fn$biOyeyc zJf)L*@%rdNXp(gY+(C~bq5dqcyr~9e?KGH4@82#3Y?kg3b=HeFiXhw&bjWiL~rvviM> z14utF9jklv^kwR&V+H%0$#Zct*f8`vVV8()%N@z*Q!~noH+|us= zmfZJ{T%Nv;m!uT`xgPBMPB`q`TbxvF#}_fTo>Xa`8eTzPGr>32HbP6;i)o3h+f6*W zhiPJC70!Vk_E!RbXA`#7v`oduO)N#&+`g-cQ{JMh`M5gtFD<^y_pOHcZJTg>Bzydi zQOe;v6FemJptWhwl0|{9LgeqB>ZN9YMc{0_YC@+4qk3K=U>}>1ZYs<&PowByzLAPS z?f3Am2YAgLED)p&bFKiv%P{l}ri7Y(vKZ4XjF0`(W2H8n>=OZjs$gXfq0LuR1`7N5 zg(^JqDi!697YghPL1b=SA-M?kr8k$eF(bK~J-%M0F!t3yzc#LP*{!1ZGZzyqkV=BK z2i_?Wl9;7hh%6_643nydOysOQ(YI|Xh^biJ8|sTzOsgd%seGvqv_P7Sa;+bgNg-=R z>Hwp*libzUa;&4HK;b;u^1273O*{ zX|KkP%e-`=;x*MBwf`*WwP`cSZf|j`VW>VqZ8Y(SOVFOg0sGI`!Cl|b04a6}9A>fN z3X|a$6Y4=Onb(`WUcK^(EvOOX;(*z3?v{c(&li!p9hZzLwKlaDtgW}{Y87cTmKy{hedv`#X#jyHei zZXeVy@4GSdl)j&sv?yjvWh=30s1 zaCxqj8O+KpDEy{4ALSo$S{nuvwjA1PkP~%%-se1zd|Fb*f3|fegSdAontKiBUI-)A zbvR8kzhn$V>>JG!QIv-28$jt9${sztUp|P27FbDfXCLwgxO(|Am`tfk<#fj{d{ON& z`U^^pZWRn3U+}ZnFDGWKS^Ho^iBikNLCG&)cH7ie;m&Ru@~eaTP2kHz$6lb==mAsC zPAy=*&Xi_Qy=bd#tBJAp4IdByK>cVBQl_kT!DzAX|K3dQPz`iVv0IMqTF7-BmYf;U zO$q>+C&FCS{H1U0JXJv$lyLQ;+%#-miZNMEi2E&w{Zo*o>mv)F_3zFd2&b43Z&4=? z(ut}?if?4&4Na)((hT(F!KB$R@=e|N_gdkg04#BiiyYS>zzIRwr7R}KlSqytxz{Tbcj4{!H1PGUSP>LNT{-Y6N*iiXPWTx00wB>Wf4I zNBPoGb-fs=`BFqqHa*t*Cghi6;b_NpB)1Ry%Pbc7jg6wbfF8>TjOr-N;Bq6mlT=r9 z36LS{z6U7G#ib z*M7Bk$4RvyxgIur%&VG1bnj}BKraB?aKnjItq-(A^3@I_|IHDyPTd&GF!%zd9l+oU z+>DQha$?bH0nf8uSA%%H`2B!tP@`_~pS2MXoCI=&1Gb;}`Oko~M?%WoE0h|M!g!VU zpOX#L^ZM%N<;<_<_358pj=?;swLu55DFri@Lz6Mp9zm9u3*lgH3_abUfSU_pBm;v) zJUU_ju4q!D)#l@of@|=QOyDh#cvi`AGBHOHq zN}n(11yA2xd$2dI3+_W6D3>i)Aqi1+tK78*K&z@Va(9M&v>Z(4;>FCzgk^>#uM2eb z7jKSoH^(T|-5wBw-)1v>Uqbk=1HN$$!K)w z((KKp`C3UCf0Fd{qKP0>X$}k#Iri4^_0Wxy8}+f`_WR=W-j^gYm&VRv=_O$p zLqeqdf-z)-h;>w|bo>J0_Gz`%oWvPAK4GFityv=in*chY3qG?+gp3-(wiB^^9fTKF z(aZw1%v+%eYUDT8G07w;t{3H0?@56mQkpBrwTAjTM&Gt&)EczkSSL}dX_C$aS~OSj z;Vy;UFFRXE4Eh93oslr@!H9tpMjYE`9EvM28D$Xqvy&X8)*}``Lcc`c`CwAt=}S(i zswQm$sAhRJ!hO9V)|DKCwQT8?RSthpW_qj_c(4pH{6_!0o6k+4lJduRW?`y6iN11& z+G#4p+!>e_2F66`YavtCkeHG3Q_WYTYs%l;;TLE!i@v=|i|OJ1aoXy1A-$i2K9%w< zYDqPL4z9D!-CXu3xSTf z#|gQCM&*?k=ysgok1mUWr-h-f7tEX<*!c+{CXw%Zza`{tXk_nCxZN1LM?$A6qE``F zjauJb%@wYN`ve6)DBW)EGcB|NEy}QZ9z%S zEh?+cvz;lNyT_CW592tGbw;r1fg&OVsT1m1XHpC+*gp?Hw+B+v^(2|?AXw>J`LyH` zR-iO4GCPE|l^e^^6fm4g;c|a!Z#gbdw8K(#l{3d}p7zrv0_cT~x_sHA)%Bp6>2K)G zvT_m}?nc4nfDCR446B{1zwOaEVrgN~7lTu%1U!LT?EkqULF^nHKq9jl1P2Hg4FlfX zg#n%4zwE_a=a9MK;4pUI$=amVIc!E0YAAKKTLTY;#(K+g4&M(F06R5ywkEmXr3PB1B?I;wH!SpID|r4b7hgRbQ19nb zEbw7i@a}`&_#e+MB#wGW_1_)y2agwxLN=_5>OFA>Tdl`QmdfY7ZOk<-s>Ehqa*GY1 z1zgDQPnTo1xB5+vb>Ym0Lx5cqC|UpaU&Ka2a_SN?09NQX(vefQ4@C_m6Mu$~E`~XJ zCa36KSk$OkwWG>i$sK`d|?2C>;Abr^@JrS+E68J}fCry>?|UiD3#zzP$T1C^_duxdHhy_v+|8%#u$@V9t2{PSj9^MI8HbM&hgJxUaRD!W-REUM zICH_#6d+9IZeXg)=xB+L^4x&+_ywA_a#z9Tt?!IQ5HujOb?k&NbeDj8h}aXbc|hww z{*z?LP--$CvL_2o;5{VQ6c(qMoUxLgH{gSGGLt{L#zi5tmSx< zp7wQe2*-;kVPvD3AE3k`OJkTaymv(}M-W4IP*v}5_0}=M21;Ym*R;cgx*=cID0L5T z$)OOing5KtrNF8YIO$9FHP~^Jz(E_^SRi&C5aq`7iKIw?nE5~&a7Ok;12Oa(5QD4t zArs2tf)1<5x&A`k1~4bu^cT5V|C#qnV42i2?qkmO=q4fj5@(!dsGM-1cjX(dhnEI> zP+?(yS*E2Wg6yK~445uSGw-!;O#lH(UJPh|hcV;XN^~%t`+On_)%y1qt_8bxj|6#C z`bzv-3|~U&<|vUp1!ZF4P~%bSs)ulEq+3_fNdW-40M-}Imz%vo5VY;Rq>)dF75dPx zAi!i`3^bfp5ygEULJ9t|_bNd7Da)@Gmd2J0Y%*xrO6ukv$<)a=AG-QY!R_Gk7b|b_ z-nW+6;3aRlWeVJ;94pum38zM_C)dJxoWs&SoJ#DSJp`+1k_*>S2`tw&D&{~TU)I$b zzx8n+22|2=bAFxYzF5d|vQ2@65vWJo5TgZcE zoOb{$aRp@TYXKi`^yy>&bhbcrdx_M2iNx=Ai2lA}^kNGN^gVBdyYQa!y)^nb2^a(n zgqL{_9sd*0IewgVZ=EhTJ_3d|1K?p17--M*Q3lzK^ue)q=DmDn0-{jwLgRN~kk6{fXS z0`L8-WXoyJB+Ys-)B`?Py*@Za%fWU&Rt5&rC%1Z+TD;;dI4-N|ZrYJO{Jqw#P9k{o z^A?ipOf=$@$FN64Q!5DsJm}w>$Vbn3%W}0!PD!x3!f^mWB z)8Rkc;^WFyi{6jD>sv<>)WM@`UUsV)SYf%^<6KAtP_)R*RK6vqWJi@<%i5o{++Zb* z?<%n_S;C_{ML-O%d0;-chIHvbIBtOFcy47%z@90N65kayG8{2cM35p^+#^-ahVm|D zm2V5kjQhr8ARdTrf>%!tPabw$kh#HJ4k91DS8Ix#J4p+=FD82?$`);2nk&X8d9|X;Xru{R~Y(|1jv@TYA?o3sZzJ;(} zM<7H}ok8UV9FVSg1?G`YTk`P6*z@qNNI{>#f`_2CaWsUzSLt8pf|?%cBH}fkVOy1g zhnTuaO8SsU-91J06<4fJLeX(7xEdAE?0)6kt~CpU-h2E~=7-zrN2EiN0&RE`?4M~W z5G9T%4y{OAa&9@uVxzEc`DOnK>qp1?nyfKxA_H#3MXUBx-;I;4iYA~pSki3W+0+r6 zMA?B3u!fp1S1V|4z}*tX6i;xpPMmJhpU2@;S``o1R2oZ@E<*+g;m|QNe%577y=)YFX$1Vd zy>g=07{o#z$mwiGLu4OUWIJJahCOU=Gi+PF-4DK7FQV~eV)0}zKgjxlZ9d0qd%(lR zrIgsMl-K*y!Ie<=jnLyJoLJ;Pc0g6pNA#{zZAHqCi*!-_z z9!rg$X#lMw5CVKWl6_G9Ta5e<*8wb!z{X`}(MsJvC8QWg4LfYdj7uelL<(|H)K6Ns z#dGbjf^6#q8KP2-bABt7xs6)b`GH|Ew31D(XDZ`#{|;QKh6H9oFrT2B%_1n_!ScJb zN5~VDG5j_+&9u!7s^f}}Sn$#IZf$Q0fBLwn0@0=XM*^(?$+lcU{P({e=Pl;iusvdl z!0jLr{@cG7awpG-3x=X`t)3#-vdAVDP13~k7&jh&tV}=nI-yFx!T~cow9ze0?bLy3hbBa*Vp< zLp)u{8vi*gHlL&w#TGu#A#khZ!sOS`PlL!$R1e=sH9=~G#!=j+d5Tp`rLqDrfn4P| zb1dv!j43m5T1b;4H}z#q^nU|Ge87n!=d+0M+9n97^shCY?f*4tU4w_7;K%rNNy%7GZecaSsNN+9qt52h{>E*{w z8oI+T<4QLp06#c>IW@YOpxpk*f)z~hjAf=$rj0Hd_=r7h*ME0#L4`gExn9LK6(Q3C z=O3??e>=P$`y!PHZ&za~tu;9pf3HHrnX$zN|2xgf5U_w&6*n#N=j#S^0cZzSly(9uq7* z{!iXuc5g53&_}u3aW0&QJ+UAMSOWgInnQq}8r)3=+&+h~W^O{3sYOE=MMwWemy_9F zlI*0DKj^XQzlaw$NwyjA$8c_jw`mcmw~}xufNg9o;*O0Ko;wxB5)^u^Lr(wJLyh0a zNf($x00e)%YL3j)l`qB5`U{`dbgjBzMff12=Tf7-e`^oVn_|GuLs3pS1?dmtIr0lt3aSelKe>JU@kspI24%v9VHwIKUYTDMHDxNw8Za> zo4Shjb;_4a;%bw)_I(Sl&joYz)0fOVDuIG7O8pe<2X$2h7?HG9@Q@UbHogAKg5IKr z?=v;PH6_?fz*1J9#iGm+8#80{l(e~U{?_@TERP5Q-sZGBI`*mPzJw)Y%ZFe_Y9#Yx zi}oZ5cUohg_=bnZ^^MQbXk;7ciNc;gJtdswWq^Y+jKqKGlqrygRjyA{@RcPputwdS zs%%obBjNN{YX=H-!yk;}q?`*z$Nm&8;Q4#2?TWg5tr4(=5-E!`-ZG0juDB4n9K|;l zP~aL8YMV$!Q-Ufypz(k&JO|q4ePXt5|6Sc^Ls+K!<%`+sq1o{9_Dtdcc^UCzsfaTR z8=eNB2f3_7jDA>y)$n}Yzr6jtu7IG$+S}e13S8}>KkKtDldSsmAa#O8XB-ULuzoZ$ zbKmASMVnL}-Ij!mOA|C46+M^YY51>-08r98x~4~G;c#xv1%lM(ugmm>Ub<*q?p6|k zZ-y3ie;&7aXNya)2#_)#@Xn;aH>iK_kc|48u@ce-QyKxdY#LJR^Ww4DX<$u5rzPi{ zm~ZSw@dgAT)DSo0*#r{6Ly)J;uuPwO0WdMfRIKidNV?JN|4!k{8sfZH0B zn8TtbW`fs=aa1a;QV8oayRtbaS|*D8W&-o6mGmrF@b2=oXK}a<{jjPv`*!)naMzJ2 z;Cx`Ur-ME3fNoj`Mp|JqB6HJ}IGR$y#9cB$r~UDl&TrB}incNy8pkh5*4-n*Rzpqr zu1okh*Iq0=#h>*`A&5W)MKF%mDCc`H|KfRQDEP>`9FrNF=F7*O|91W{*;il1?!N-) zHef7&xj*Ya`?*2--JZsv9WaJR(dG4YKkRzWHpQq1&zz@~3YXt#l-C2` zbYrS2jDCe*+rMzU#KSr5Oyv(gR~={wHo+Ma&!BDc5o^z4nLH#6Y!#OL^u3FV(e{4E z@v8bPj3ajo8FTBj}r_$1(fuk(&pGb6J+Ux(e{LV-}Gzh!8)4$DBB%r!u*u6x;p8k z6?b_>65dK_;%nmH%oME{ONd5aoxQ%`Zn4%BdR=gwsow7R-y$*pcsQ4M+vBST)>%^P z=<@87Tsk4g&wt9kts9G{gJYH|8&qXwK1PmZdEN#<8lHc=_K<_aXq3NgB51!HpjT`0 zxo5z2)(!{&&D7vQo_-k4Mw3SNJOpM=N|ts_!ZX>M*q2M~p*~fM+aGpF7;qslnI zz~w15;YSmOMFT_0;FC-Z4D{~sHb6Km$^olFTXkA+EqvAJ77GG+`v6`ZsFvc=zGBv@ zodK&|O2{)6Bd!Ocas2pd6wT0sV!cc=imD!uoU9{1io97Cn9=3fwknB8XLvgYLsa9s zSbw!_$^NABUznxhZQV1)td@4oGSBkVJQA_zkJgjgcBhNZ2ik75U=VOLm^B4)x7c~b z&1FB@&c8zh0uz3@16W2*MCBQPkpmv`Aak9H#S`EbjpYCaVZfPezzw)n+kTFitG%J7 z8)Q$by?v4J;A&{bb8%y8;r1|!5?O|%O+0Mv93_peuGt+OT9b+0qcV#BR2++uQ~4e* zR7#%hk=0VJn#xI)1|nuC>v2mEA4?l+Nl=a=x;ywU>LIBaT0$Ec;P-oFMVO<81;pMY z$9OQSA|bL;PuWN7Jk}FT(&L;=KBsFBilNwPwJwFSBT-ifnb^O!GFf%FlXU10uj%G{hvRggmsW1yslu5vrZOfZW30}|3o~eK=-PNY% zIpMApplcrDp+(;%j)d%aA0?C?gUSKR(OhS(yO`|9sPW;JTUOUU`c&y}2a3>)SH_Nh4@)tx|*I6$8 zxbRmNP!!$F7603|Mdk|q9ql7RI-eOLjL%L)@<|>c`}%o#CTR8mc~XUGcXY| zCBX+BWk50)+jWB8b6%Oo5y{kyT;Z%fT>3Zo47UuO&epZ`K|V|4?U7UoYmQg(NZy8o z88B3^)%LeH!227c&fLkC)jiwG0mn|RXP%Wa<42+%xfnFJqFb2XC?dq+0d}>_Pv|Eq zmo5?`hJPsdGmCjNH$@T;IAKka=M3c;C|mP90)kCr5>pV#<#dPO2r_9_64MyI;8{N; zfeGlS8k|?CLwI4~u{w)->cCS==rTkN(~>(+e1Ou4wtLG2pyq-98Lz{sR+CiDtU5#K zom4&v7`-c7P6nb%HU*1K_HHg!Lt2%rAbDAkGEJdYLn{MLL98+KOi5B)7K)~gxmwB_ zuQJTj=M7%S`qC8HK;e`x5}i@|txOq@;ehQh!Y*0%7Y=N~!%yXOVrz7XQI(7z-!^^^ z4axpKthjgqa`Qz|E{8LmZn-z%Ps4LI&8SfPXL|AW_kQ+a*i^&fecm^i(wzjUpoBtw zb6J5*5=u8Jy6-A@lx~lmG;I>|#GFvipD+-}?I*qD!ss@Pw!pW>i1EgO(aUVN_}@(MTXdz(WlE!bOPH`EZw^ zZ5FT9v7mNUgB5oc^KHHRd!&hL=gBr90Epd!n^6FSso(pJQrGb>h#zV7FN30hXcfE0 z;RNy@1`@wn5gkZbT~4N6Tu= zPo9=bg9&I32ZTB5{;%tY1TqH=fApIkIe*lPmN?x z#`Wko0=S_oR-H2Kn$y3NOOtqXfpMEopE)(}Ko?PIZ)yEN$)=^7T{f5f^+UFrjG7M;Ch)o9YhD2ZuM2KcQy72@_d6q+B}1@2Rgc! zGQ8t}g!ASVRG&JDV5J)Imars~O3%i~$vRZOCNtX$n;aNw@F}&|i4?+dY2=2;cJ#{G zKA>s&qHLS#k^t(-ocX%bq>-jf78!w6N(kx>>d%}4FWD&Ge|xxgu9tu{+g2AAhre1y z>%u(5Y7K19RNK7p&2kR&b2TYfcI9arX~@~UnuMG!GQcP^pqtmVOCKWX#-q#fERbWI z)q)MQJk*|h4HHj109Gy}Gzi`LJm$|;Ovp_W+zDXgFxySb?`z1>+3hJWLzsEX-c8EpQ_6g=>%z zqA62|H`)B4;lP?GWAdKkVYFTXeyxt?)f*6=2W}UD+^Ryg-Y@?i=zs%*^h5;sP+MU= zh_q%9ft89W?5RSDQfF*#&xQbG+$teqO;6z9cRq>w`KxGNT0r2mU`>=!JUACQk{r&$ zGS*&vBitX`0!axzQNqN;Q3Q<^>gTS&->8Euj^e>N1T7Ci!-2QDfuP}F;_hRxXQ$A( zG!J47mD>)0I78#=4TZ$EjR4x@%I0;QkSRi$yHD*5mww-`yvVD9o`Mx^_%~KjfAI}8 zUpa@M;ebt5^!0#V2dNP&8_{R2Oo#NuO@(1EefFpoB|(MDP4`Txp)3_aLcqVgi0ZXv zh(;6T2X2S8Z#L{k(eef=vnVH9s9!BpiE{|YL+kuC1dUdjF_aBEvjNz!tE|M~3Hjy%O7c+W;Gq8ygT4yeyRxDupgYOBSL2QrYx+i;p zGl-T8QFlNVOG{=|A{?lyKhNk@T8(R`St`wgk!>5C-@QEI*^x%tuS_#|bL6959zeO! zN1EL$H4c)D$6PAwce6!g69hZcSp!}!b**j(c zm^eeQvVq!DC*ZHv!ptp}W@V5xvl0mHXj#>Ev>H>0giaAF(`laU>- z09q6oLS{!-AS!isJv3fAgUX|KgQm)D0TY#&yAxliqmrCK3WH9{fBI^;Y*CWaR?!Cm zq%VwWxGXW379CZ}C)9M?m{gRc#N^$_u;&{eL+Qx=gv7LZ;R=?&@>0mx;JYa7na1S3 z$5A5)@IxmiadBD5A( z(Y$;e6L%lQ!S8r4)=s>M!u}cTeezNG^(MS(9nGr?xbg>|2V)FE0@C*|dCyTy+{ zD>rcI_dbitu|p{ApT)rsycerqdll~T8k$#bVC9(;*!OKuVDI}L11}X&*fWEv2k$^@ zVFk6bm%+H=sGDb0JFEFM-I_C`)@=&w7w)=TlqQVBtphy$V3(y3+sM`K<%kh@UAXl^1TnE zaQmUq5b=YItjm)@{a)AY%5^GO2v#>x{pu^>GuT!dw^aZtBDHLfC9*A?W1 z-0nikq^Y-;lr=#~bv7y`Br=_D2>ERUk@=a@bY3IHSp{-pJt~w)WL``wzvU}3&cDgG z6*Jnzr6VA;q)CLCmfWQ!1&GRYly9YcCz;WMY33cZA+*fvSeDp*1Vi5UUvCZD_Aq^d%}R0x zshdY(53qt2mff8^2XAQ|#2A>xmGXzIEtS`CDRY;U7g1`6r{^k?JB%n7%-6sOMF!>v z1C{wn=_*A)(nCuPG7vJnh2}j}eIS{m&ocUxF_2|JdOm8;yo%{>dnfGuGYFb)U-nSA z9=x}%!(XX_O_miPL#70^QR$Nzh|(I5DCF^}yp!4HBrvkgG&%^SR95QLzeH*IR9+K+ zG!xt?fz*N`lms=^>{3$w1clndq>{*x1xG;&_sR`WrKs8AoB1JI=_@M_X&JPT+Dd>7 zYP1tfo6Z{(zIs8D7K|JvtJUzUuAEj|uK*E}V9!k9;9q|dWLa4J!q?H7U&7SGcVqUQ z4??;=mcQ~6+^aXR_ZuF;{%?B^{CX4CWChKZn`vRJ8mB?i!J+SZANIcQaWpP3VCBm% z0XE0JZ+ijmHciRFl6i_*S2pg}R10*46xmZ8(ChX}+Og(ZprXRi& zU=~`}m$3B3=ix4{f=8J%8W=~2YC)OC89;5#%rxaaHh@`yw7y z3oF?8i?735uSc0f*=`WIb=N?qJzQRw5A9A<*rGV8g$I=AhRi6Cc1~g9)`u*?;1fl- zmv3Oh^)UGj52Jkl?P0`W&`z1LFWqo7ZTfkEP&#Fh?u3|e1I1BEm0ZsK(z@B`QBFN7 zo4@YRR-TOLRLEPDZBa*=sI?RV&Z`$-@81JHH`!5Ss8_&U3-DEnXgqTkjhD}WRm!;l zfR?yQsZ%7QY?_qY1i4^{o^{o>7nF)x=%%Y$2OaaNMCA|?daAV4q06?l?s;HMUeH`h zkz{D<8A8;iyPMt~InHt-i$gYBXkEOH;_U~c(j3{5?a^0f(Bcr)1{$xNg?D8!Y#nTI z-5yD{AthwZbFQ_Vxu`|6k@T+c+^7VLQs=%RGCJ-=`zIALPynoGLo}MGy?h32ZW6^~ z2Qur}E*RDq+l~mb~?u06k$`sPZ%(;;|C?}10u_-4sqV!C+D4Fsmm@-c4-ib6D zZReoHCJ8;-T4Px*BdOS?x&xXm)yV^i@>{hURG5q)MHGD%Qs*ripl!Duebo=$Imn=G zzjR2?epbYv=Ulpu`U|H4%LcR3j07Ec)-5iT8wYuMSyIOTQHfoplp4)|85RLZrQ^}t zVH5IhVtTsOEc0j$SrQP_Ee##`F$0Vm3!YJwL)!a*sAO46xR(~-ym=X{QVP3^bZKM&bA&2tU}i+_5%OcEcKj7Q&q< z_AP-HFVIrV$h1QAaR zu=dg$;H4tgPn^U0%WtB1a1V}t|F;{J%0|_lkl@7vD#s4NTd(5UAAKQAr)PwX*=Zd3 zj`yH^+X1XHJ$lzJ?LEU%tX_whXpA!m$3?Kw0H2wF6v4pvQi?EJ!rnI%cAXKS08xd5 znzEL4qGcw!qnbLbXrpyw1@oWzGVDFmDDItxUvHtcxC+140Jp5jk%=R`Vf$Hsc^#)d z_4^P(fVus95C|WwrB$5&kADQwa$!w}5wgH>vH0Z|vG&So6!y*{a9VJe))3U2;Kf3& z52X?=X4&!cBUlMH0AsLbCqw?7E=x9YNwWHtGRngeq1M@}sQ%T92%Hv(GX*WrwiA^( zU`ZAnlewv*GD`JJ9MPQUwOZcOHnvTa0pXIohN2CBaUJ!iPXWF_`H{OIq84X^ma*+V zzk3-Q6154}kAMWqbcID;D>_mw8^a`zBczhrW(nl3c65kMKp?NoL}nb8JQq7k%LpXA z>#LBS7aBeT)FJxgFo;?cLA434g4U!*&UJQrwN0!{2p?EY( zmp0*?K|6p^n!9^>5sjDL1S}SkqbopI{+g-Ju4n2b=B3nmHS`WUini7`OxihRlxbN^ zah6NLhNv}A`_fCW{^mEsnw?I&lx@?t+mf`OGX&K}*xokEjFgJwqZ#U24WG=&Ed7il z<2WTjapYxtrO|h(qP+?Mee#_|C@*D1pqi91#s9MW62$liAw_znD7Ez%8IfM7fjDFu zaBtd~%7A4u)(|P@h6o5m*G}Lte1d+H&kj-+%MEyXpwvhiJ97Z6m5Pya7slTxy1ZrsvDk6Tqx4h^4HgnX`n3jvMiZ@t zm9Q+!3qpW~GlQ!raw>uV&dOTo7R}5eaKm!0*76#-ZG$Y9WWxjvC*-VIS`VGlAOJWA zi(ivy4az-Fln^0N+X!xSctHgYzHc^6Arw1z8|Lo}VThMUZ^ ziOk_=0WykF_uW&D2DKJ6vu4taX5^R!nRG@~281d2{?a;X&z^$td`vukFQgxYM&~YQ ziAV*GV6BeU*(*>xa_OyLvw#Jp3S>x#K!g!>#zRgfqZMcfeu^-Yg<$XwneBp=T^ABU z1YvYJx{IWhj~Ha2T0|lRZvw{!F&2^`OF8hpA=`p;@fzIuB{0i~9OY!~( zdaGSBfRQ{Ghc-1LgK874GgrYLErJybeQ}_-bP^duuwDzhP*^-8la)d-Exejfj|v00 zQ@TpXJYFWF^9BIP03JmzV_m~IhwyzM>I6c?0w6^AtvClSSbzYCTj9ADdI~*=LHYp# z#|1CiD9lZQ7)NVq6~5!5Fg1~XFLT?9=IO_FWeCWX4H=F!783ghiyL4wm3$>TDm}H! z+6#|#ew#zq9kebj!e3qko0-tqYw}7`DCbPk7D2kWB-d=;YueeW9?~2dHStlVpOv3= zr)M^*AZY5N>7^j;IRO>mI-}Rxa|0&X$$>!g)r+wA&BDHIKSbT>^`L;Hguk!?(QJX0 z3mNG}0L=U}vpZfUn3w}vP~P3wd_T&Z5#&l!-IkWdx*{j=gRIxprZRxqpS4T?1{tXq ztkxhLH>4s6wntVs228ewWs`PnCW%f4>7=|3&q+Ru`VF_1R?)nC1J+apg?+OiVj&Ue zWCiQ5oPoPh1KAv~IC!}jcFv)+ZImgp)HYAeOA8@+>C7bTaseR1%wzY#+o+*>_A-d6 z1dcfoKxsscWxnD~QbU7as1b-L7dKP_fk>BG>d}8y04Aw^(m*3K&UkDIF|b1DND0pm z$+C)8`c5;`Hk#Wi6{E;fkT}r1RMg6-h$v(#mm$bP6h`v$5MeSRNbTy^Gg2i=ua-i9 zafad@he1UPGUy+}WzP{F#z3VankUX;;|nh!s5Zc(`gG(vk@-9rGS?)OxRbWZ3w7)WW?G}59$iZ+w^d?;pipZVSMl6K8B zX+6V6{fzwE3FMFkGlKL2xR-Cho|^*71waHtxSRt*282;eavrv4Y`l0Hh2sanj~*C`z9-HQtkn=~G$Oz? zPj^cNXw&%?NM@fa<9w<1fZAEcAYBdW4NO0L59Z$e5O}2wZd*~>I$`;lleqDh&tdj$ z_u=sW{Vfo_hnNrTkmo|Qe6T>Ed2JEPPrU*Je#j?AVYVr^Ip&^t5HpY64{NHN$lulH zPGaM=^Wc?o^2BCFNS>2O$oBitey>Do+wlt}H=c8dx&!z65=yhTZ;SMIJVrGn_|zn7 z&zwZ#l{djEC1krm$u;AH-ykiU^2;g2?fT%T7-b>_U z!{xx*_B zj_kwq!*`>6>;UYUX#`FS>o1;0P;G=pJhYNr4T;PEJ5dCkS4s$+77BBdIPih@LP~*& zJ8#3<^RJ6g+0@C%BdTh#V*VJEoln^imRxE&6$l#w> zDxo{xc@_O;GeG0&Q&$}ER}B~b}*TOsz^wgJt{<$IFP!K%3|t?Xj1ygt3*zw z0VtJdJcwZJoeraPLiTho^Y*gWs0k|<&^mo7WNBYs2j4p#)x~GsfNTP2Hr;`8BOubK zLucvPmN~uUk&V_SXGH@;DWiZ*qk|&A4YrM7y^7kir$9DG@t$L0TX4?{&+Gt=&#q;h z0Zxc!3;tRa*4~-6KvSN{Ej?8X-0uwtS)!ht#4_0fC%@$ax2q{Gd5>kmM5p`Kh%9%7e zNhHKZS1>_J_XAy;<#N9mzsW08$z~Yj zwUo>Ux6FW095wdWs&LL+hBY%80)DPPSlf;+MN^3(K&;yJ7eGB>=_HcKb3 z?XdbXzu7|R$bL-Rbrjxu4c=Nc$>tKC2jXFO24`Uj(od`V-Fg#~58Q#$^d#JsbtRo1 zKp;SjFmcZ@9QbQbAaFc1FE2n6VdmkxQJ9{9Uu&XuV-;Z8>@tl6+Tfcbtre#pJyxrV zG$PM#IT9k$IdV!|+3f>ho9}-nAQOzIGA8Y8BSL8H0x? z?*^G<()k^hbi`K&@XX9DHSn4N^++dK)}3rwj$)Saw${jVv{7&Sl`5d>ixxy2woAMVN;h;fvT?1$HIAY3yw zrA!&vRo)H&VJdt?azl(D1A@O%2QQUS*f)#jl^ez(HU)+X3Q$g&0%>f?iF6!hoGS~Mxbq06AG!9&p~>A3RFfwNMZjR4t>}AP&&L9&W#n= zb2FH{_ZawO8B1Sy9zoLy+rG>EbD)7IQMk*yz5>x`^~7V+`I?5-mp8v0I#UH(Ap$mm z9B3_l(=3n8Q&TftF*LcSn?f=p!#qoLL3g27helqyYK#^?JmWGV4!m z$#V7BU>?At#TSXdDn&F;oI~Nz9+V!sGZ!%F)&|>Z9c2(i%!AqJWc#P7juZ>9jvvAD zv!_C`@hC_Vv^G9VZt znzmd%2KCOH+;gNklExX-+OlQ?6+{4h0oig#Za(zY4&e;Uwg8`l73>hy3o-^4V^dWUOQbxZo&?WdIVk zCqY4w5VuKU02m}JfH*)L5}^7<0B%l(0r5Uz*GdyZkx zH$0B&Yv(cl|9%Oz^H*`;1Mk7nzx4s^`_?D0@%nj?&2jKM-UDV^xbk~{hQ%+vfayo? z#jzj$E*$>u_rqOUL;c((aH|XgK?DN4U}N9=A4lo%UflSL=P>{OeHFz$GdT3u--o$( zK8V_@7f`=&6;foo$B+vCT+q05 z)Xpb45p(S`;;aQyfkw)Wo@GdVmDK&zDWeR?q4PcH*&n$bl>m(&g>npEjaMb7d_Woz zElnRwmHU$c3~(=9hqZSaY@!^3acyK=Kkg%Oj@H#B`131a7C}rfok2;mJxZh&4cx3e z6B)2QucRiUKg`gnRthDx^OR=N#w3mm{%RHO{4xr69ti_IzUbPv>pC_fl@_;(b7jP! zbJj|2Jl?K*Lw;_jrY{7*D`nV|6$saZUvp4AxCc_okkDI7$UuN>3x&P2$@&MS0*?K_ z2Qhi~QC$7Z7tvZ=fmJRh4?*qIUW%w3gRk&rN~Vn(&s_AzUBUM5(Pak^zB{ z%^J>&z*0^OpNQHpK!*GbvK8JLq1brC)>qrVmuX`F1R`{#>JCKRfgpfc9AFf-*_9G9 zDwiJAvkubdQRfO)HsD=fLEyAtO;u7kkrOnMIdVe>RyJ==FO_ULYGW~w0S@PZ$dmy> zq;a?9Cf`A6n5G6ID9t>hHh~{KlUSFTv>C7)KQCkOH|lUN&ci;ke^Z+~ZwTLmXtaPJ zY`-aUdJ5%%p(a>l-ui6lNE&=k`CLwUcC=dhDIpa5TWX<3C}ojS=5*_m`MXPKXBV|E z>1`L-A)7%o9Rzg;tWty&e$PISWuho1OKe`7xPCahTXk^AE1lWyoOyz|-Tdat6EWm* z7*LJ~XxI8MIW7Vqi%>i`hr*s2G%qi}U0#DdI|;@)nr~f$J$FBda}6=fM3W?Gk%idF z79=rw`yoIG)ZV-dYia_3MB~bJ_|*n@xddyng1~XXShlV=TOOh(Yvt9#gK_XeL8%|^ z|M|%BAqw<#|?+21>2sQ(c?}caWfp6`Fpdti#w3BSp+I4Bv2kJ(i zYCeaKj&MEjz0;_?^Zux8No;vPI*|pv8Y{wa(R}d?{Dsv7QEvxcQJd&S@_ZSGPcOic zxy^?4R@r$JRQVBv{BM${u%H20=@;Zv6*OKt1ABH7Q{VjdglM#{ElhjZ%e*@&lg?k% zw)>a)(>SSE7}M)8VJ_wu=dXYzUZnu*H-JQcV-Chr`dm62f8y2#x>YnZdxvu z-%?a}N+hHZ;Kc%1!A8(H1iG`UL7%ZX~6z@w~$GG4seh;0Nch^wR5C zf9W*r*-33pd8Gtrei4`d%b%u4$KnWxLg2*WXf3R!>FLNLpdIjM?+p0tBv`=? zqy2sEz_UFa(!;!r0f9jC{qK#m61N9e9WA@NKFpGzk1RdxM>G|-N z)nKhiPPn&vkvoTcvqLuJpESKorLrJY>}i^Rj(kD(%>eM z$ceMYf=*`AkMnB&O+`+IA&}|$o>QKN9D^Za#z)V@CQ7J1a|)2a)CZn`*r@fjHDWt? zwwYYd1&E`Jshsjs9Te5NDG+$6fQ>i8Ob@@|L_94%xNU)#iV4wcd3FlK7@X@%aMw0q zO-+O)iR;x!o{-X7Iwg=}#Ug^GH3Tgej4=oy5HuYCgu=erupCDO0PL)hmSbp8CZneF zb?sP(L~uuZybmVt&sN__zaM7yf>|bz zPafFbiESHAqIOv)l*!bH-{3E=hiSPHcTgu0rC#qP*&P1j8iHyQuz1dMWXp*1cu7(x zqMhL?Gj~MhfBfyWKH=0;|;kAUM-*h`< zj^4_bc7aG)Dnz3RDiqq< z^_lw*vs78lOvvgkGR~sLG1VrUAivZ@>L4ej*^6rT9pvadGAu8dE8Fz^JIc|)i8n{2 z1p)F)k&HEpfsd69_{(ds_s@mo!8GAv-mo4W=!leB($L`%7ym-FFOVwtCW6 zJ!P2m3u)cS87BIiVH#@4jggNks;S6;Q9o;>_EU5*q#t18#97Qe@dyrm=t)dJa0mQq z1Er$}P?(#>>T{>yt!zXb0uf6WW8jq%?1?gnQ<4JDi#GPY_idPb@D5!2fBp)!bC=Ot zT*1U$x8ctJ-`_&x;yjqeF?sh<$RI%VwR2%=o|5WGTN>*5jL{Nd+9I!%LM{r(p=2m& zKf69A-f=&IjRsnmu7g)f2C|tlaA!MG0D>$CHUW}8itbw|dl$fhI!HL+q6Q|LVc88u zB|1?CiX^58_H>^`g4pn=97oT84FBo@!UYgSB$yIb;DCz_R9de>Pyrr4h-UGAc-9=a zY=H?U*PLq?^-nrza1K^3LO89qK2W!4YnN66SfvDiWdrr+Uq{e%Gy||*njWEj4|%hX zdj{Z;`Qm)D)a?8ShE9kmB{B^`S(^BmNju-wGvx*SgUK{jtvo0d<>O^NM0(T#1_RRYp= z6E9dLq-_VbnQf4DLQ1_;SG#jd5=N&PnYKZcdC?>taLCP~BE1uf)}CAHEzh@#>g#1Z zS&FzUtG;@nC=)=4Wrj=<&V=AOSgVEQR}@9bJ%8+T?>+9mG?iJv=tfjk*30{@IcM*^*80}BzVF;s7M^<*r4^Rv zu>HS#mf4R#j=#7<@7z_RX(9#nz1yhl+RWvzf1lNNPqTUFc4DQ9?5RXlUMr0XL#&F+ z)}Q?--s}`tzWO}D{3=$>0~lYbXl_7IL^BOc!VsDdaF49$2GUwaCxievzsW8secyZ513mYo=ff_wr zZz_z@Q8Lb#I(LO*BW*jw2F?C=d~-#Vu$9V&z62U=N#fNGYPB=WJKqz-0y?a;rxfR19UipTQHZxgPxY3$ohb?XLn z46UQ*SUYl>?uiRX*DjSqESX{-+Zh`sv#~}tDp(tus7~*W-pjIJqNA9~{_XVMIZglg zd33FkN*Hx2smg9SEvv+`jvHR0-aCw?I@s|NPBf2Hz5zspjTTNy*jpieT!j6{_;XGPcIC35*UO>qjzO#kCy9cI^uk{o8eIS{;o~j>d=4ZG{L0>!v+%Nf?;}00hu)z9YM-kGsgOD+;-OaDW0Ky z*{FL~6vND-+Zh^DDWzSP_8`oMwI*r=SC?qN@D>vve-s_4A1#qNAq;gnj8hioq5za+ zvWg%zCEMic*{`1a=y0#L@PI&SsQaxgA4&X6 ziSCTjsMQYfY8&BL*X^F(dirJDCq{PRW#sKKqOO@nPo9!qK9-v)64MMO+al`rng8~y zXcg1HIFGO`lpiqjZ0r0OZnsF9OCf8o4*ph=_tsz!O z&t>yZJVSNICKjK6o#j{FMYvXxa+Mw}&IP}`%S~SNRg~no#g4Sd=(k8)B0anG8o$>Z z`;O!vT4T*L2`|pmdHG%X$1f1Cc969Svf`$IpBSMn<3_2I_>ru&xZNds>lE?g8miNy z`siJTsnYG=G-z_W*f=-!uq1KMr+4@yI*N^koi1aoiIKZXUK6uK;{@`6%P3xzvpK|A zTVGuY0gNfba>ArKb+0mw8(mht6ie#CbU=B0E(mu0w|5$sAAWvqcJ0G>e;Z>G5SwZ78t+zCTIFQF2mx6Y@oa~ z^-xbxp@Jw8DNiz=TR3;@8~vpp7Ep30t&MN$yIK}j)gx|qN9g+4Vr}e{Xa;JvDjsWZ zo}hK?9MzqhaVF~YFVEv&T}0TnDJ*4jAUFIcZCNpf@;(t7(OYj2%E zS`ufnL9ozb{=zG)y?LDao~@`z(K~yYV6B5yagnY&+`I*eupHQsCukKYS5hE68(}-3 z#{(ux-Fi}Wy)~eJ0EOdh#feu477UV^2i_szj5bEasJ)e8NyXX(83t{L502i_1ROs27YYMl$7 zg)o^dCS^{=LNQJ}aMa-+20&dDs2l*LdaRR9$-e~%+a_*x=^i~xt6YyFi{gvate!|j0%PKSK;xd>?D*@SA`Sws{K@kK3oCeYGozW{ zI35;oBI)i8?}i?MOj25CrC56LFm|)f^yByAZQOuXn(DSW23FBfmIP&sr*t+kE)d_= zhm@!|#y@)n6^0$`WMzXUY@LfzSipNuNXmlMYg*5dz>jYQEKq(R2)LA#R z0nn2jk<>XVv>4mf90CcttgEiCV^*Ac3CA`a=Cuyi=9wD;Om2Q7n*W3s7tnrSI%wnW zWl1_5wmWz;lT1Ez0C&2HiWT8ni|*;m#62G@f$Ez^%EW#9@HS2%EgQm+&I_*-uB;8~ z5`iAN3&nnjGg+s0?;d2uHRF)N00H4ji~facgzYZUk_ApiwoW(yXBs#?Lpk3%m$-}E zIRF=F8Z+Zl=Dfe3h7w%`kz2dzd?qiwJGgd6J6)T+sp6pe8d>!cXBBOjZeY5x1Ev~K z-L{cvxkb3rGDW)5qe3kRiIqmWHqsKPAi}D6Z1~7yH1FTT$}8`%@Z2FYQd@Bgtjo+= zPdDq*6#JCWqR#c)GeDh4J8WcQ)m{{=Mv4Y(*E9CbPgX!x(?Pv zEjNBEvT$I^iAw-fJw&VsuPxJh{xDdQ>O=bw6&KwP-d{(^n~pgGVnw{#CR|uC-!*Y& z61oJo)oJiL6){qIPqv^P$92lXlVvvdqyPq8;1cFntj_bxbhcqF#yX0LTmxaOTz#p` zXn9tbcil=pt;lLh4nJ)W5?owBHtPt-f%S5{1TZ0pK&XN+xXu9^A{VuDC{)J$p$ImY zjI0Y`j7K(aVCJa@u^fl1UweVL=c9s%+V0IvJ$f&8tzv3Z1hLTcPF-O2)uV*VKGL;D zcVBB%7}2%SB02JNTx_U&yKlen{u#BQ&3V0#R`x z{t-FulJi4U2Y?B=u8JUok!1FSVW$u)s@sg?m)43aU-=I0cTVC?Cu4g_;vhXI(XvTf zv82132`9)hv*n$W=ehEgfSIQrqPA-@{VPkX96G}6haWY8J&qH%oAnbZk#j21Qe?(? zZhOHOYvQF$buNf^S&$?W+%kO z*qxV8@W#cKQjnxLfSyfoODrq(I-h3{BUQVL@`H?BzYAzqUwxN_=ieY)Z6h6<=H0v5`01x0(e1LT9#Nyh!gGg+x;>Me zr`|<%`&94U&DOv2G2>L$4-kN?xO7fkWPYVZu+jp{8l(S_%@ec~#J!NX-NTW0IJSs^ zxV#$ITO6ZYl4d=n#RE(1I8z!`LqX;A86HMB8)w+^)6Wq1L(crWFQBv$z;$OP(NRpW zw3-6QG|ton;k9L=)wa>3OTD`@*#Iet{eZaB$Er9?K5`dR2k&C(#lu|t+KYs19qfrJ zao;e9*4-~9d(XtiRDPOjVq|m}be5l05Y5%5VK}sy*SEJOxFf6!rD%We4SGkygP}Y*Y}j_MO)eu1)pcJ!s2Hf%`vt4`ErTo=gLGen95|%=dNt+j8%`%&kwVCX%g8OEQ$yof9qS#0fBd8!VYL;5d<3_B<8uS)i z=EgZ}mGRX@#*je_m~m1PoW6{=doxzOit5GJt#4EiW=6^>8754BUa=0d9kRKqE_lkN z8k0eYbS$PGI>7X!_kz}3{rV5ku|oBIs@pa)anEkhny}S1uc8#v^OB3L06QZGprV-S z_D$4wZzWu58BM#vy?4wQV&<;sV$&mAa*6fLAX01D$S{m7WesaOgv2fMR?aQ^Mn#5h z*L?lWbU<&5yP%;t zp^CoN1(l{$S9e4&8;S+X3QBtj9Z>5ZrsAKVU3moG+hJHKSb!QOw?Rbhkpt8Y?!WGs z)XfNu-K>bOthw}FKSBT4S!AP{L+2@Uy(n{TNU^!{9qPi~6O>a!Q!}AO1IBXK8(m`4 znhx~i)XIgui@p=k+v( zNsw`z@itAf<)@xONXexyev7rYPGCAg-k+G3hI?)w46~`UjLZVjsvn^I@TT|GP4CAjLTfb=17D|WIRMzT zQf&O>Q%pZ`AFa1fa`kI3;!HQ$@btq>Klvb?Qy1x7xW@G3_cHgXr_e%h>A!x1aHYkD zrygSS(+BZvhf81l7S5!TNtQJlE3vcfoW97~;S;DR!ty+#R+p&NOU8f4Tf1jE%)(Hx zbw3f0zf&2N$M*hE3)AOlSf=IGN2c{(;*(p;ytF11}-n11wL zdY7(I-LVO8Zkn}sPt!Vn&H%syGx|}h7%hM>9yUY<=fU&`9>AGuu=L_vv=+}Y`S5-= zKKmq{)0b$ydkVWz!=0TPY6nEE?#NPEq~e*@1x|?0m5akpa!w>!!+OJPWHiNWfv7sA zNb37l6Wq|cNgRCoN6z4%ziRHb>m;KKrie9bRZ$%J)kAO_KsrwHdI}{#^?cf|97R?u zR1R!6+F3UV3f*c9x#_ycwg}fc_$Mx;s?99Wkr`bTB4ztp!W9vss2eq|NG}-+qhzci zv+8uw;cI}AYLRUVj8YGgt69d4a*JWTk}blsjFaLxcA2d9c)?ncJ1GYacK(HH)LK34 zjng->8HTZ0i2OO6<3IeelN|351^GI?)EcUMY3Xal&=2y z3oO2P7%3&K)*4>5O1052XJ1aZPkJs^twOlc;@EF|4q2-teEPqLh9;MeJKSjBn&M#=ci#7iZ5+B0R@< zv!`7c#sCb(lCazob{yhKNyjb8O-fK+QC9O5EkN{joy*7nBvpV6M-k!}XXDfmqRtbOw}qa&$72@5N3Q}vHg^-mxPA<+&IjJHc2u}DM?P|Di} z|o+8J&Q#R%!v<62^8|VT;LJ@? zLVsF!-LH3m+{(QaQV=h-h?dq6Rc|cdkzH@Pa0r&M1WJ3>x~%h-4WlX(degcJI=fHw zxbjQn_Qd*5@MYgvfawkk=%2VieX@b5S50@}J#^`A=3cIskO?V<-2kbJyoYic04P7i z+c?dpk3WGoH^b$xJZI+mE8fV(N<*-?O8=tKBWWGkO84Al8hf@e`_acyU7u*p%(vF= z-Hkgt#oAk^P<~**n2pm!oj!VDh1#wy%zoq%bQIG%c9y8!OA5nOS1b2X^9hltxCmR0 zrB&o($cGk50kRqpvBFcA$&JPLcyaq|J(^S^EEV~xjZ)li0y6;02n*#i1@8!+p9YJWcy@VKh ze+r~j4Ygfc@aLCVe&t<)#Wmu7!1Bv)Q{TUx#@)MU9XUgF%Pe-I%C&F4Oz*-qbR0AP z+##wvHc{KN1#k0=5o{hZx6GQ8o;iPe=dRE?dKMjq2rB_el45e$i5xUU7~`ZO1v-pS zL68AUZZ@~O5vG7ut6)`K;(kzaUx#DylwR1eZc6#*loyhNB2U;h;aZF3m)^#1)Y$Sf zA0h4s$cjs_w8rXdM~PNDSe}EhEh=-<$V5XzN70DUpp1rHegAg6xoK8jKZZNqr1`)B z0P1_TP~Z8JDQ1kspI_$8zx#sGm`OJe^vL2hzYoS74kg8)7&`(tNOiPQSgwoJtY?~Z zcPh7gFExRX5*>wfUOh^@+Cd~moK_0y*m#>~QGP(Myp|b(O~+;x$Ji4!YTGwqP1J~% zTXfG~K`Tvkd6D4aJeB?1udhjQyJE=AUrT*G9%tK4;$%HR&hG0xNk6Zh@Ia$S1o zuHbE&83G@|l2{cNtu_9_D$=n496{s05W+Ij5td9GLbI_=g%Q>5oA5SH8CIudA(Q5P zu8_?!b=J!;QxQO{m+w=W2kBUknlLv|Qx;ru*88P9VGUcx6evsHZwFXXhJcTIt#Nij znTzhZ=-8lCW#B{M))mBeL?KZgZQj(VPL5VI=&*^Q1%SQ|*fCPf&jE9}4ny7#VN5~+ zC1QgkRMOeJ0cY!m0$}o9QS$YINa?zX6{6~4Z=J>2I7ztFM#(B}bcuTJb-eI$@&)D4 zy=I*6xXvHi>C#1vv5(cd5KJ;wn<5RG71g~9ceOx!(AhB-p>V>hG@}+hZy)XI!w4Z! zew*4Ocj4~Yg7W>FN?2|ua4Kw@;LH_*i}NXw&D35f%*K{DN|p3v3xH#8(Pj%#QIMLH zV|B!fi~qVnrY@KKErUu5SId$R#q{1eL*?#W$Y%XLpKU`C-%9lY+S2WB$2Ari1=x-)GCuew3|0`!VJ|`2pi@6)UcM zcyHZQMZI>S8zRs3>Con=cWqw2iP`Y1ABz zw&eGjta)HtN!Rh_z^L^s=>})Hjy1}U3Zkglpg&IKVw~_>SxP6y3RjY1mLLQho_Yvx z(}tw8uCZ*3sMF`#H(o~feIh@gvUvkjPux#!*H%=oPw(6n`p>;=lAlTm_$eUn^spxz zOg(xpjk|Ul$B9;#r5E3#d+C}PO%P%%=%Wj1VL4c&$66VcY0~H+2&lS&0VSolqq#>M zMrNGMmSbaT8kpC@02V8Uju7_){Dl=nB1{{1`$p(B(fg4#Gp5lxe8T8r2uW~d5r1)o z+Kx>)Q%#~)HxZj1>Ey_y+0#CL4sUK6VM%%yuMv0qM)Xyrb!fyGOU_gV8bzo?%OQWw zu4k8eqt{m}g`BJ*YgM9!wJ~K_T9`2ho(&3BT`oE-5IN1A@!*1V9lGZ(bMX(qfxB@A zXQEEr>Ed5oHUiWYH?gdS{-p)Z{JSqe6r*E>O!Om=5-s537rueCY@*dRLTl##;zj1a zX#jL-+1bWu6pz4?65xL5ge7wKEj7|Aa`vbNtSHSO%<1##SRrd3?%Z@jp}%vv-FkJ% z_12BBBr1#u&R#`z{G?}<=)-splMmm;%u^51K7NkH@4Zg6(jJcL4z5hN++z9z_p|Ba zPhd|@5C=ZecIaQa#??Q2f$qr*1ZOVO-!_Z4XX_2K)!tJKxykD*EaP$)t*n*&t}cZ_ zhPzzn8?hAjNO_T4%HyP<8&(3Aq#fH3yW@*Nlhg@6FYe`9Ir( zCyxUa%Km(-Gl%QFSAJvXe|{_PxgI!jz0X(ne!`MC8>flpS0Peh3CLJJiY&8aUGyuj zmyr5holPOLD#4JKl3o#W$#iC$QC$nJ(8(j*1{kl)A@Vxg1S3?Sh-z#aic>B%=6B zLg<1LcIHqJsY5M~(`!Ij2x2U~M$La0D{j-R+>7;r58~am8)-@7j&q%E#`VsCao7KP z_fdKd{)vl(SC^2kQ)FRjT{tYs6qQ+W@c_XuSX=8dGQKX@)9ImKg)U#?>lCFruW6&p zfkZJDzRY)HMxj1#_lTC(u;->shwK)`k#FQ)jyrGj?oXQQjWbXd-kk zUE|Uhzln}Dvf^gv_oE2^@&bTy3H#Ewso%AW%ElRj3QS)1q|k7JH?|lrD)eN;7fa9=y3}{KYlX#rIsSb_WDR zy*`coJDGd-161Z_=$yWUaBXIudI)dZEZ6?xMfw*PQ?~S`%N=+6RJU$qh>b>(8PiBQc1kH@dx}V` z8nbIj1ImvOmc^Ez{s?xnhV(rAt4qv(`xRPmoy2a`3il>Yj~>3Plqf$!b^Rg3yU`;iUjp|5KA~mL!oysp;D`Hd|=rSj^fwltc=;S2(P8xS2|LPL{;tJAn%uIY_ z?vnvs&1#N&KEd)DPQ@Ep2akvw^e-)-mBOx65SGNhx-?`w6tWK~u&b4^MNk^MFK4TX zoJK{ygC??e*EvR~j$+e@+O)yg@Rr=)_o72`GjVIZnm{-(ykeeYlv1r)_=rRyIBRK|pZ%E6)*keX2V*v*GE7nEv4XM6C|~|r{mF0%CfH<*6n{)`3+ zQX*UnVO!L9Z$(8B?o5;IKmH*W>NS>Lc++Tvq)Z)D6yi=dai=Cm$50&8yl*ew>=al3 z>;>A#&SE!enQ<_k0(MI!AJ-!pQFH_w=1;MLI6?@CP6mo^sHRN)+2+6D$88s=jWzX0 z?;=`h;h(&OtXD@Av=RZHvTj*%ahFfbWec%EVVRv-)g{9u<(-o2iv|@{)LE~;WL`1W zI5QK-X59n@#dTNr?Ep*Gc@kO)M72g`wuL=)4lccc3|rtddQ7KBB5cw#V*Gn=K z7-dEm@1#zt5QyYDj+!00WP1?bb4`_~?;HL0$SmIG{d<`C;DfBadz#*bYY9^(Sx5Hh zq>)mZzevTM;rWtmJmH#jFIaBTK5-ta;xhH`2rMj>ztg3PB(otkw-x9}&Oqbmf zSoLZG78kAT?P?{{SdkSMS?Fx(%%~9S?uvxXrnAE7=%Ox!(D_!}^?K17X0i(SgwtCev$f~ZPX9!V)gJz`WNPj*E%`SDYibt@pLg(ZKmS1_t2vXNP=05Wwrk=PT|JpJuZyd#* zs12{bv@N1`m+rYM1XmYXe)R~#v6*~eKhqz)pUH>z(>;612=!am=<}t|tqfC#EJLW! zU}b$Dx&iZXkUQPN+4J8tU~=1Qh&aaGxdnT2g1#R@qc*y+I=9VBIvTnZ3l!zr47vnf z(d5kUO02p{>BPx6MV9zuSP5X!GvZgiKauJq|SU7`w z`n%L>XYprT{6!C95LSs^NZBD$amr^aC?Dz&g&u2>OP|`*IczQO8*j8} zZA8UlVy=g{_C2CA9>KQ9(B1^XZ@s@3c*%DNuP&k5y^^afGNM!C40+3DW=qPVY%-A3 zt{4ZW41>HVNv2Ch%gSdd(};go!8>)+gvdC|WO^rwm}dXPdAz%K;B1~T`UgMkv(683 zHcwN3{BBy`d7Uz~`oeV>1T)9NootLPY=@jKAxw86R>Ym2(TSRFNmBc6 z@H=6rhmaC`s!CBpMxXLyqB*@F3ZP|~;p6yw zT$Xlc;O00sIudvK2(;~y(;a0J)rIhd04&EgOp!Qd;(@))ec}Uztu71SJv7wkG3UKD z^VpUwEy(i^tK!nXbd9AK-elo>uM;e+3hh*Q8;=9Ll$43UDT@;V6=^0M5xfi8s( zQ=L{pSr(zkY=LY;A?xy!O>W9^LrOTVBfTRn#P~6|ADtE{N=cOP&{7~&j8q|$kKDuL zeLHEt@-p7O1K4VXYH$p8RvrhE`58%vBfo0Kra38^9i(qAqPWh7{vmaiFu^=}Z_ZnUT|D%4^01bn+XCJh)MI=oD#Xg_a*#t4qofrU8Z1 zvGMkA$KKF1{?@nYzTe1ND7=>CfRxDPGq}gThJEohbafJE#|~64d3ZQ!1ORGbMRR z(IrYkc@Cu>jB1S)KO^VBQtSkZ^q8J5iY8`RGJ<$XtEdE7B#7PNi2=6v6gkfvGgo zwW;mgjMkdUrVY$~_z|pnm0)R=-i2$ZAV4ck|MDX4>=fRXS)A!6_T&VWt#igwaB0oZ z^pkxp&?u$xw#+7LM=|-(ermh6fmQ^|tMtxZHFM5M!Xh&C+j2tpx&Y-EC}Mpn_2k@% z)zAs!cIGRYhvyi2vd)6^I-{GBJyQ(uq|re{eg6(Ne)5A@o^ibiuB{|Z^aO;F5~MYX zK`Q0?q4dc4B>~AXTD?;$+{ zWN<5D;5YGHtu@lK&AhwTXdw$a2gP`uby?FT;6&cti86>zGX~Tzi&@#cpty8(u3?aa zp)>`!M~~g_WsV?O-LA|X)MXk6xz8d-ZbG9bUBV)>#*1RVm;C%@bMwJ-g-AIRN*gUL zgjPtujiXi&Q4iKGQM>N}CLcaPbn-R&U;7W#{)hhsPhF$gd7ij+2JO_0sBPpR&_sXw zHP!+jx7J{TH%ZW~BlkT{b@L4V@x#bVZ&I;Vko{TI(h{ORfwnA!ib2KYr`9d#K;Epo z=kOr~It+=|+Nf?HS#^g+cB$?LB_k?O+UyWxnj~e}@3@9=21pdek&8U^U*x^(LUSSO z*hh&-xVSFcWq6%a$>+H5uS=_|qAOxPUx`;*L@RBqdbQLbW1zE!v{IUdWdnzdX)@~4 z`ZIf7Mk9zSim)c?%sg=)u^&*`w81zV+O`>?cWh=q@ie`2S6Te-A!5Ie^c?JpgK%9e z8^TVTCr;DRFY!v7_Dk;|Cu%t!!Z_>1 zJhMX=#sa(0MM5 zD9+QAyq?a`S+o7Y0!=b?Z-wWgT3zB+7g=$~E2-bWeYrjNGMV{|G}5-wk;;*?GTgLG zu`>Ev>#?hHmr-XYlSSzfsI&S^DNriy#!_ZoSa_*eAsh#9{|-dOMThFn#E=B+Q%aF1 zk`;hAO=fs24fu>ki^>5iu}-2iOue*97&>)y7%}mePtao0|&+vbS<5a~MDjVcSz zy~@%HZ=#}jq?8W@SBCMO(A4)#TM6rOP^2g>IBegcqZB}PgAQUhu@lYPxXvhdks>4P zTiiLLb)cdcZ}Tj3AA209QRC8=zD@VcWz(1un6arSLRLMh+vbc*j#gN%gI%kDQp7!f zIIbm~f0@@s$i~OL$8#{#XZPq#AI3{r!P_{?>Hq!zjU_G6n%d?^5n7>_ zFXHJ1Y{V|pm; zDsn{Oan%39YmjE9=qxe^nZ!ou>us)e<`^@awBjIyRtls=_5QusleMuTMz`~^ZbD|e zSc|7|kNp{P;W*lBj;?MTBPSa;u|mZ$al4yn9f(4AX&i8s)~U&K+j2hXqi%Qc*h+Wa zvuFCqJx7!raKoT5&@#!5=m-_#Y@Ei~J~u3~h1RC)qBYLRZzH-Z^dJA5h{%Wckyfii zWn2zytF-e_dVMks6J64C7Gt}8BYQWI>(+@7QN3xv5%=~u`(b&74EkE&LW}di@?%6AJ`vJZ4S7;qQ!|XGUviUO~ z0%h*Z!pm>dzqW`~am!L*oJN(-$%|b4;x|pg>e%f18=qmrj~ygfT4VX8w~>>L%=gOY zhk6VZTI7IaG0rkolrtnV=g1wV(M!iR1>HJ8S%zhrB-YZg*!1I1;m%EQ`K!;f^2RYU zCX+Bol-7hTqn|MS_&xN_T}JsKjRQNWZQn@$@)G?kOGsN9%@S?cVv!%x*teajNA6+m ztrMuk?zXyZBhqmQl4iniMU|lUBIk&OZ6jRQuww4u_0&;})u>@lHwoI;QmkH`8Cyxm z&e4cWxoBl39_ym2+z8A|11@?@EGd_M6nWTAWO}>>w~u_`nAO!vbzcRgLgVEY!D*ca zN*WPmhVi3ksUX7JxdC_QCL?hBqmYAZ5Yhq^qTj+k^E}R#!=MAA)h=3D7ybzU(ARPAek@rtI?-wxhLix3;E3B zRHm!MU;EeCOXq3&9jw*6vG3Z;wvX(g|Gh6^@4Sb`V-KRPoJPF<|7C-`iub@@#o2i; zoiF}t!sU06N1Jf}0UG!2XX(YmNY7#OPkb1wUctXKPqf+|>Khgt%sMj&UPdw~x4{-g zJ;EgS5z@*SHry=8Z{Pf3RSsY%rEnaFi3y{K+wb@3^+x&yj^og1Gzz~Lh9Rw1>$<+= z)6>(Xf48=_MjVe99?L6K-wu#Q2O*U`Tc|&JfbN?o5f!(%rF2ojJRQn@1YO|)$gs~ zp8O{EwPR@89ijY#%@ixFsRkaK3C>?7T5H2_OeB54>6CT|S)rFwri~b*+L-NJ>M|>} zGD}>MFN1V;d@tj@rqF(jyJI8X&duf}l+JYbg%F?=_SJXr-ug2BgMS&J6hwZOCVmUS z{Cf9NSjJHRr3;rSodk-MwOLlliW0#)kt?cF%I4{$S?8^rvxTZoDX$L_;w@LZge%o7@_GR7*IS9i%h)&#atKDF-q^oxPmz;PA!QwSu+VtczZ$L48>Q7q{tH) zF|%^EQkrofilZmFPF}uHETyIqsrEw{Wy(% z+vuIW#KuoP$Pdb(UUw+X(l{QHo!Lyp_dDq061FM9%I#tq+#v2BgR1O2pNZ&h$Y0Sm7GynCMu&Y&Oo_dhI zn`eo7#+`^*vG(RMg5^~v4(w#--}*`XD~nwD^B3q}UNlz26_@@0;O7ahEn#^s&g>N3 z3s+ft<2bV7B{_u16da|K{u+d16*Lm=L^Di>G4@OoXVVP+sY~d@aV>l9>)a|3r3rOb z0ChB8T)Gu?9=<5@7%5wuC9uf=q)T_ui*7c$>{F%+9-VRhNo!`66~eltORY=v*hHbg z7+qQ24{)~5;_cst>hylND2e5uD-(z)#5(^n&e`vS-$DdEh`J^o#eH*~Ds|i^J`K`B zxHTHT@N3BFO$e`!wQWE3pZI(D&wq*Du~)&Xr<#QV-EAS93e}JQ0`B9_()-%)61?#( z=y$>KAc#OH1R=r?(6n(*d<*B)cZjEU67K&v@uq!+w2FDZ1pb5&=$>zwSc%1T zp_y9>n&er%`Z^8ORHJ5$hE&nXMw{F`2#CYTjCwf^(y>M^Is$YU4egr6;2h2EjI?Zk z*4j9<#Hx^JO4mVHA}ba;etx6;$0ZU9qLctpWaSV4UP^Qjp#1>kc;N-4KspX8_D2&I zxk6!dWmD}6ov$rYnde}LBp=8B8H|SFHk5CCtL2ns3wGod!i0b{w-ZhlJf@NFu z|Kf8h15Y|Fl?kBmCf_ZZdjT8Mf&U(iD0+ztkFpS4@>k_ zDaFjp46Rm+Pk;K;c%H}K|NDQRkAC!{bh}*|jRyUGpMUg^{t@5&<~QkdI@q?&Bab}7 zum0+;Nq+mcf1CgKAO9nZi;GAp*}8Qr|KK0|13v!ok5j2s z==b~Y8xuwK1FYF8DhGDZJ#->1W}ah(O$QE9?(T(NW)53LFP#b`p2f z41PZ_Nr@#=UCUH@kOrC75zI}GJ{9c@jm}3|5mHF`f2`tN; z%T}4jMTz!`l(deVrF-TID21#zNZT>sc;W&Qb$e)~S$zHtqHdqYzU^4G3TuZ?aPbFk z(7!NGZEAwp4_JEfFk!og>Ic|U4O&M|6Z-+xZ5yd?>y(a zuR`ZU$jh1wCC(@%%?VL)k&cH_y&sOSzmTZLB(lANcl2vm3&#+hMda#5P%+A>qAkZT zo-AW~?Cw8^a6NSBW9@kW`@ScWI9|b;*^E8Ao$%xv=vV&&)$5=dlZZ+kRE+NTsQ$z+ zQTg!C5WMu~^uGOHAn2RsVA6<^wu|tphIJz}qPK#KdWh~avb%(u+(taRk7(xy&6Vw~ zG2&0&Nrs6a?)j*`Z*-0rOKw77tXjy5iG4x+q;#i zecModpZ1xnMBNDCcxWvM7p_v>Jk8Xj_k$30PM@cB@;uhmMx1JW=;~rtYQhqdG2V0& zyIw)18Xv;8@#mLO{QxYH)45B1*8y`}kI@FvWv$OLfzj-wL8i$q1aUtk_QUIpvnTP1 z@tQFCW=Z}WC@9mUn9NGLDA~Y{mYC=s!itv>L^#nBmR<$Nhae*S&VM3)>sz2AM73!~ zimsif`)B`=@a#JXw+bqxcj|5Q`6I~cBr1&Pf9J~tuYVWS>q27|-EYx<{>#J*7qMq% zK`Z+07SXX2G}=B?CkdR*^t`(O3#on3(NHUM2(<}anpc+P(q)qwS}QYI;JF60y2Xcm zI}(Iuv&q`p8o&M9zs*Z8y~OhJGN1h9CwcbSXQ@`JEG;eZd%yR4{N``|CI=55kTyhyRc- zfBDPYfB*diLGb?3-V&Otvt^FP(+|)&bi@>&CBj%)c1MxARVL&*9sn(dIWZOxEtiQc zvmMTMEpy^YdSsKO`T=-0)dzOtZJ$F$##WFY!pM|%Du|$icjT)$7vD7Jnp4TKF!boK zj}_XI$YveamWYZ&aCsgAGj>3lolsK!j>d2b5u`vXEXAHPqg#1UrZ{4vhjRxhrTSQb zQdko;>)^ZiZ*e1wp;O36Q%au z#qq3?nf&r2E&GVg{j)buQ@MASap#Hk9nWKh6r;p!Ob4srqoPYhkhK^upsR}>7wO)( z3L~sqm5m=dh*hhw_?<&^&s{+{Htx(M(w0O$-`J#Dl4!L41uxf-`9UH6S z60LQNWq7rMkb>Uj1#}qV%}pU(hiI*Xuq2g@#&IX=^-)2HblpO-CkipL2!xdZa7E1r zkr7l*uQd$_OS~_Dq`Q5N-qCaDR%hrWqsK9T2767y%4&NF{ zCE5VOMhP2@L<<{BwQ-`W*s6_CeFiekmXyTdDxj%%CKD|qF_IDx6=FF-Y)uha^%Te% zB6SR?Y&U((XD{NUq7a$J<%{F&$hA^f6Ll=lK}X^H3znF<8?;vk6=7d^1Lxvv*q09@ zJM(C_j&|##F{c5FWLa1h58Yj(`^Ucx)w=1@2R^d7f$B3qhg!Zy@a_)?j=qGw>ptu~ z55vk;;%jG7OY>Ae`3qD&@Z zV_5UYuoh1tS1%K7J4igW!)WmY?K_(t&3nW|<~PS_eLV z_M$b?bJ+N)r{1~_auhQ+)zH6D(O7B+5l1v@&16JDhfp2LdQ zKnRp@QMlk#5Gp1-br}8bOUS7?uoH22uSR_BtQk#9^n?5;#+jVKYD}Sn9^uiK(P4mW z&VXej8Z)R~oBsE|GOEp##;#X!9ShOFKoDKUj#r6g9pBkbWKAP=h|vBB0M}wH^Culc zM>g2}dRY}@9K{^*bR=l}el^IO05Tl}rR^|yxLh3mQ;J$jVi z_>JG-*=L{SbD#U%aJ=R>e&aXz$N%^r^W`spnNNQ5lT@o!!ql9k>$>>9&#(XbuOo!u z^Pm4b&ph)C0EZ48;>jnUCY=}cTp%n_XDhEjr!9M63#CZ zoWEic@1%33#~PZZMZ8J^b!HJ{(ci4Q&W*7c($sD-ru5KyJ;B*QM@gZzrn+Y<^$*;K z4&yP!{(J8zjr-jpAm&sNVGrljb2w+di?)*vgVsY4)y$O;qhbjmko79wo(f2at}dgZ z$RyEnpxB(0HDZjpcV6#8le-QBHHJKNJi6e9YBw7FC^-J5TF^!eFhp1u_UttF?4(Il zwQ*D!Lu*LM9!T@O!w&9|KLf8xwB-TQ9oF$J&Df5+mqJQZ6cS!uK!;IE7&1?n*6Ub0 zGIrkp=pewGn`ZXI2bny0H{n_bVudq3fjiaY+F$&DxZN|(K{HKepLvvtd-fy?UE!~^ zSzKI0&yViKkWnEdm2I6hheektBoDON# zxAPVV@I#|5pwxP(>5c7?+u1Rf0&o8|+#?%_mRhEubF2(dqDy#j1x!$vb+2@e9ibDK z97;8YvVcGlbjw?(>s+Hq_X3>FGt?g3Zx|BXnWkT6e+UfwEl2Dhp67Zn9wthyh1UaR zv&li;VIUVr5+P!5!xW8scN_N9i*Mr1%`pAJ2LR}vxlFLMO0c-b#Jzji_A?))bK(NB z>QULg33qCO-pLCDi>tVE(=_&Oqkn0EU}=^9rFnW6uF^QLgH4})iq7ea*!3EdkKIkw z>d-lHAz}TATnt-B6R0E}W;r?KiEi->Njg-P9Ez~ssb&g*vwb60vqp4ndCYlM0()s= z|2s^4g#fH!EYjNiOz9Zg0})3=m(LQ#F>cjnq8TAXj1{b)l)|bClyuOdg3lF+S*}kq zf^Boo7f|9>mODFyNQK_C#)$@DnW6%XrMpUvsOStnVkSphic7A|(_5i9njR?A+ z?+mL^NHfBwLX+2t0(UBF3Ng-jyF3i(8v+rs4tf$5fvi@UetbW(A9)PDbb-#HAK*++ zQI9)>;akwTOm**m8h`D_Ar1*&`~o_TsNMS*wNHG2?zum}zwjKwtD9n7I7G5RObyYz zmx;YUj@?j17v4ZuHV|7)LNu|q6IU&9-FjQIemYPT?H`>Dy5y|PL$ErE5_g<2@1PXY zad0+F5-qHtBZlKN8Nu^RbEN2uxz8*BP>LHGBehN)(E$PaJ|Axij&W8#Va&BKOmNM zdX;5-dn=JWXU;#&**C<1$7t&00lUmkwL(@rWWAalA-ffqocu55tts<=mw!x5OmOJX zA%5@oevg9(5Avx`eTqt@g75pog!}B-vn(tu@b~`S-@|bnI-L&ndYw;v;uAdiaB~ZZ`=)tc*SgSwfA-oz}yzA_W=`*}jT% z=6mQ$lX!Y3BIvBUA8y*IN*Hi0T3Ss$`?vrsa)o|zZ)x_PO{6U#GHVj+v((V)Eg;Sbp&^3*UK-APmrsgR7FxUCQZ0 z1tIQClMO%i5Z_;DE_3#P9v`WpFigiGq{GQikeRVzR z4(T8ox?J3FCTUUh9;ekL{rRfNS4)32UOt)FXFO-?atdNbHFkYi}K= zbNn39T8EW4j^Io+4A^+@9)xA#OgHftR#<)eB*D@elMfzX^G|-5Yk%<~;aVFNMl8Mb zHg>bY+{YfLao=9!+#)3N-+qbCi3`|`DkGY>$htUW)==7Nbvz^TdP#gXj%idfhADC& zerRW3*0jh<6id@pAJ{_Z2&sEUL=rXpu9j+J#mmUJhag7E z2rCF7S_5pVof%v$(b6T7bz*xO#Xz%5g0QeEHcC`dtY?+jfajSd+4v_gc9hQMY23{- zBaN1lJnD8{R~<%JlXbj(+vpuTn;E$*qob#ZjF}OgGzTsP*p>@>5AKq=FG7V#R*|ZQ z8(yXwoWxRXWZX@QDjm}XAl<-i(qv!1> zaCf3)4J~YxFnNzm8ZkOEew6Rwm2s%q}kW`@s454 zmS!B-1V10Ita@)!n1OKe=z zIbO*qPJUcgVH?oUU#7BQ1G67_jQ(3cp!IwIJL>#f$f|2x)GAf59NdRLg6;-%zxc1| z{PDjRq{8z-b2jTeJD8Gl0o&haY8!KAEwWqKN=sou}mVfh~5O4b+{mOn~ zX9`)Lz?rC_wM^JrDid?Eb&}4p6vl%`A{W22@V&_B>c5S8FiVT3a`jXO7$8QEGd zXC7A%**8)sjSF&)cRiY}tZk zSwvAp7>3Nv&GGQV5A%nA_=kq-o&q#1%OVH@jvYHjr_*8Au3a>nO}gDKN-12|<*BEh z;o>|Yh2I}HpR3n%y@+CDtxEO2-MIUU<+N9*WW>ic)#%uE_ttBT9SJ-bAYylW_t zTH~*+;Z8I&`VgQK|9Bf`vPrPGO8evm;(kc)!ZlXkIL?NrAEt3&2dyJ#&_QIx#7ZPe zbpe_bxicV7f!0I!7_HRMk>tI!!Ee_YH#+NLyxp6rUfV^q(n5Fp;MfHg$olr`r0j83 zZYDYb6NwX%E^FlMl9{?L+DjXNv^W}+=bz{>q;k)0DtGTRYW3p1UDq1|+_g5W2G1F0 z7e#PDXM`6s+$)_k4b|mEk4|Zol-VKR5x#+cj+1z{*SK_EUuzej5ATEclHVw z{*OPWzJDjRJzMFud$fw4usDzhr;zeZKMG}Jc4J$A$<}N@= zfv1d~lNXr#p~V1C|fqz)2=o2qK)#8?a}mlJOXB zI3Kv>>!~!-vvFpd*i#Lnl}^&p7bWo{YoD4Q2^_8rU3MSRHr@k0ml&aAyx=U=;5d$2 z1{DoE*RfSAS-~Q;-&0K#H7F8N@j_UMR@vZ6ht&FSQS;v+wx;R3`{=oQ602yrUQ4aC zLq0yU6Jv5lbMDBdiL(O>>N^3J6q+VdBH|GH@?o4Ke~O6uXm=u&N9Y3BiO?xmJaZlG z<^*97CM*zvsMJyI71sXU|2(8(SX=heJM?urFZ~&=XKYpb&wq*j_r90_F*)Z%r4XKn zw|hUrwoyS;-Xuunpc=qyfL1uCpGU4-CcN*{#Es1cG*Rl-o3>;3N;-#FCs!>kz(-80 zB9M|UOhwA^E?1&z!>|@YVug!T!*^)d+aZn!U;1M#wT8WCKL`sQM@H)o=zaey_^*D0 zc>X-r)_o91P^p265!DI9I_h^*b&No33$f!tbY%jB!rQtDIn|?~-XPXCkv~h1dkE|~ zbG8aWQQ)@NxEN0>F9V56K&h1eMuvf;#*hDMr4X)zy>&K`cNoJdEo1BEDno?Cj@PLA zNAUa;=DSPRz^!^*jZ=h$3UdqzATn03UStcQp}W`cSk^gv%JdD8#MD42s{T88;d#21 zd+B<2r_OOPR=X+-o~L7RjJ*mX@egD$LEzVcRyo?-NB4)6>)J-o2YJG=+>z%@#{3@qM4w z)l~pCZ{CcQk|>JMTI0Gd2M!zn$c*vaY$0)@-*xOmnFUmP_yBRYNB8v;M(E9PQX?Uv zAY54{4hu!0wX{55&RnywWb-9iwzIGv*CmhHr53-^=pba`=?ADCJYZ<-dVB}=X4cQm zgC$ku@_Fowhmh@Lj+LCUckX-=LYH#yMz+Hm;o3MmHepRQ39l^?uC5_s1(ro_?qGQ1 zMDpjt=#|LQ(aLp8DCI)xVOFQm3M|LM-m(E_ZW8G@qwY_JIz65NH7F*tEF%GS1?R#m zXs=0l@23&{*6q8O0~Sv|819Xde5?e1%F_u&DSj?&lVn`|ix?)*y~iet@oe!x5ZlwLKb{ z8B5?4<5^|NT`Oan2q8?@DvFI5>Fr=--HtOZdBpvI+QEIq{XXsQ9!6L?HIJJ;pVHRB zI_c1w@q!3jtzyM3WZcHm9ix!06`BaGVnp&>!-}#{qC#vnQF4OFno88&Ns3FA>k1c7 zM*%25z}YrO?cjdgjWb3R?>%1Evg=#QIFJ(Q*+YO%mH_GL7H`pTTjWw-T@aoun(t9q zVQHW~?(}HAbDGw%bLMj;S~UYJN`xfp^jUlR6z!wQbK;n&*T;2Tgl!Rb`gFUOGjteX zN#cG$`^afJC(fgl8oFf-#e#<-ZbkR7tSxtuPstby*DUx_KK!CoGV z?xW*AR@}mgu2Ac}iLz=0_8h*wlfd1YEV^ zHty~%#BZHK`vF4OV*#k_B@hJ$lPDc;8^n4u8Y8q%wSOEhI*S#rCb}XdvkweK%?o-b zC3MfCK3X}OSEptet!SBA{2CSi7=g2ucJ*PDtYNAC*oc$u3sb__%!-ib8Esl?w9-`X z-i19qF%pUe9Vp40YtpZI>Wztd(=fH@-l)>j|P=Pa&KN zM12NgvbOD@ zB?9Q_nxya z#Ic=>u8AmEOpc#>O&=CT`c)D<`aaE%Jx1fn2e2xh0Zg3hGk9+MLqP0!ILF?=zWNqa z04_n%zG`UcjOW-4eaXiov6)RG1b8k^qe|SHMXj`m=2whBkR{FBq*a#W=uDz2rNj~f zC8X&prUWHLx?CDDHxufdMn|S#u_x=;8>X=*>WHc-PJ}iHw5C*oj)IIzYTz&1rPhFr z^jpYR7MWhE?(@wSV4U6?_a?iCG-EPd}ax<}5M0A`tcV%G%1 z4`>}ag7dM*+4z^9qOoTi&de0`13PHHeTsNt1zTDMOv|_v=#r2r3Ls|DP7S7 z7M^7ztGCaA>UOfcWW~jO@RjveCl)qhy^}Hi_(6`p#BjYZ^&_BpS}UrcpVe!I_z&`OITf z@7ZYpwu*S)uB)iH#1j!-y-uXNL#-sn*tm~V<1hAtM5+5nIV7I@b5a!PUSM1wEMel6 z5Lw&$SV3q;#H1y$92?tlaBRoK(Sb#>O_Nzo_bBlmTHxj8=W@uuV0(LL4**olW$eorLa2 zBaW>74EG7GsqWlFbMJPl6HQ{jzkUIBJFlx0h^a}OgLk7(Um*+!z_J+U4>1O`E{`*V zSBXRwp|jHtO~a79hXn0fqOyseuIi>Ok$bGaRYxZ=U$ zRh(mA$GP+>T4=QGjqmfP_2tTP9b01U-$noAdBVjNgy$y0$}$BSNwjUFgg{t!@?J7q zqz=ybSmEv5g0poa!nRD|C1rMH74#*tyaX*ks0h(tz&`tZqM%K1&yQnGPGj|ZqfY#L zc-YdRXW3XnB5ZpIQj1a$U>t`+ubZ=Fzq0{R&B&O*3olXikKshukg5Z!g>V|k#uOm1 zH*6+6@-pFT-@<$N!&E=|*AN=|U;jJ=J=EGFwa@$_l~4RULRjF{@L&Bp;jx#IN+Bv< zwxAbaZQg;Lm_hf>5gvUNYx@D*NBL15atwCa0xT9ISbAb>=iH0HLroaXfnYbgR#FEkwCB*u&(rHK8VMnCYW?6z(*o4^X zGEVn7Gp6J1M_4wN>W$(26yI6Lib|tSeWFPm_@soSGBscv$N0X#E{pD#L|?VmEG;eZ zPygvZ<;f?Xa{x?EP67;BC28a)2m)HIRwPdQcB`DW^HW^rBsHQGVbBJF7xyAy!z^^+^L6EuM)ZeQB@;OUc_=7#E`b0-(VxL z!*cPOV)tXPNu-eU`ewl>4RIWmTmMlehDHIcECp?X2o*=f`?uga0oKuX(SG>;IT7W+ z4{cXzw$Ctm@@v>@7g3ewF!vny%_!}jlmrEl(g%=d6w zxnYF6vO?vN15EDQjx{xbH$8y{F8%3uxO(gqvf?6ad)Q&p>+(xdbFqcJuCsapJ)gzX zF6U-!BgFVav+Q1fFG|lPcKU>Fj68D=;W|j$LJLVu1&PMfi&R*mqL-2J3R-oERR^uZ zWY5V_U=*@YKn%s32YW^6q|i&o3q%DiYuHv3EvM+|DSC2_NYoHIGUE%%h~H@e`ruyN z_BF)oOU6OqeRO;fu8r>WiB=bo%k7lVuow%LjNcjK$DZUD`bh#o8GIZR}u2yI7PJa!bha@9B%+`)&e zRfu{^#HxpNei7Yl*HDB5Zxs+0#Y10|5~m0EG6;iVGfJ=5 z{T6vnP6wgp0gaMpk=8MUHA_csp(kchScdJQlmV(A-OI&=i^$b$iHPC*xR-1TB1IUs z5lf3mrO}qm-TC5LFK2Y*n^Tfl)~M)5$1DyrIFB^JkE&*HAtG z4&G1;9FJ=6D$^HV#GQZJjA*zGU^PqDDan6w%Q+j29h!6KPgIFdoP?{_OxzLU&tc7YC#mrza(awdqjAu}#bb@8I)jKW6GsauA`mulua8v; zu(iMiR=)iOx-b4IYIUCK$-_+jjbFok;!`aD#pj7ztLR=Ib@d|g@wY*OGqVwU^BzLC zf!{ufh;_nNO+f!BK)n4D_VN<_H@`#w@b|E{>|x?B{Y~mmJWITBKkav4Ln?{TOCT?CpH)zDD9h(#F8s@BjUH2(b&SXlApGFES)*S*~1O!^v7%mi4G&;&Jtqb z8u)<$zDn1=9+vT1Sa_^5rA|U{3Sak8*hw7em&AZU^H#5q`j`BDdM$)egtROyUuFpp zV_vyj%TTZT{sM(i3kZ7&ZJ%e^IzUJrOLa11l)B`qqaltW7A~E`ISi`nm+B@&QN+Z= z1bg@HU6+7iuXoUw{z5WR^ZCzzp09rOt33MXqx{Q%`7gP6@ghP9+U+)4Yd-h6&vEtY zRi1tJS?;^fsi1?73>rcH$dNfFwAffsJvg%QP_&)T#+lXw5_M`X3 zjYrZjm5GNj)m|XgySGx7b-5)T(p}A#>KJe z?&`#nw7?F^4zHwLl+2n+&HKyLH5tlVd&sbZy>J}2x`TN0{YjGW9ur{8d_P>rSkekn zI$R?JL#k_Om`>3nGb|HfL~>OeqLm`<`Ly0SW!C0Bd#LZ+%+$fVSbg(^=|~E}+Tjx{ zz4#XXY776uJk^ON+n)U()h!$8Uc8#TnM8*n&P1K*$L>Q)$0cnP7QsDAY?n=PgUiQ-GW(=?A9u2nOAFAtm}p#9g=;U1HpsCbbVgjDGVB{gW4o zm5sEa5?#R!FH_O;R9VHPl`O-AAtEco#hRHI5Lwfl0f?!EHFDQBO!?#-4RPWny!aZi zwy>DS5i|JqMgnIG5jBVf&QuNW-d)6ZZ$%~6ewO|IURZ$y$HCdPg{XTL)$Lo$^fAHPTP0;A(ibLq3shcc8R5jB)|*KP>C;6SC^=; zngDE#~ODCN^0oW+ZHYz6CrxIPj4KE|Ph-Gb~ z@9ZG5W)POf+0;PZwF5m-M|b^%Y4`r_CShB64x_=B}@ zjLL-9&Y=e-xTq zko~pywmYOW+G37{PU-{J;ZLN0o{kskQ#C!^J=|MDpoNFjF>ZK{dU%`$SCAq?3kOXi zC@rPYeu)A=6Q6zyy*iJuETRiX36H&k^WmSt+OVB?@hZac2;Y95_{3`vN4R?*VEXU> zODfO&Rl=2d^zv0ir8e;D1*byr!k-YRn5fr=&?h>5nC@5pE%nDgfox17Y!`tvjC7%J z)DpJ8faWUFIzZpug|;S;x|guhMX6(u$jsH}YZRSvJI!r7(wA}lN>`5%$&)gG{cZZE4>JJ@& z9h-<_WAi=^A4n4~#^N8hx-qX@xx!JT3X_XC!XN3 z#~#CR91b5o%-wh2O|xm(0T(V@;JN3X-r+MRzH&|X? zW@csvfOfmhAOGm>CY!fxCJ2ITK*`yBjvLp>11LIHW_XS3%xKPg01~C=60NjYII%!D zznTSa#xb8nHUTX@H`fo7V0kVm2v*iue(p6R&U*SPd;Z=}bN5eul2ccDRICaJLB+Az zv~3Gw+g8F}7rnBI0JcAH53QsNB5a4K8&co9jqN}Eaau>tF#q*e@UJbSQOtehF}D8f zN2y`4@SWFC-5xmBuwW^&wMGmwp^GelvT=-ftBdDd$GW2;I*V)$@?=q_v|gM$8=jC8L`Z#+*lN+YBKr1D z^ydB4o;XPT!JSC06IX-x{~!}mqGN@>X&XyxA@R~G!t>TmV#k!YIe@La>yzJO>pic$ z^QcQEgAGv9YPE1&hiautoM@GaF>xpRrn+FeJ{;Y&*}&_yhO8m6f0UH5;KPBqg77(V!fRv3fEf-i4<)#P^&f2TCFoKRMfgE z$?QQ)0E!9SWurVwr&giw?L&zwf*7q;G1n6mOaKb`Wo(Q-EBm%G^U)`T^qG!6Ty{5;*}06@Xd&> z(nN8LiesE)v~<8?5{`q_s9|qtVow>deW7%@d28<4W}G2&`(pjk^zpgZ04W)OaKnfz9E3LDZ@qsKCtM(6A{ik} zy+*}Dh#0P%1R<%;ZpNOUMk|dqF^TOMo9A8TxkLBpSyMYo zQ9v7%Fk`N6c$r53JWjBJVsZ$J>Kn`|%Hgz8v|h*9hrZv(v21MHp^VR`OQa>%eZh7A zZUU+MG{rUiN|RP)7G=#CgJP{Hp(7Btx@>szAdUO>qWxejMlg^7>G%8Vjvd}KU=oHQ zLI^(l+0XKK|L)%%j>HVu8_UbfJpTCO{F8t3PxzHz`4uK6CV2DBH+kZTC-~wQzsOy8 z-Nl0sK8Wx8eCbPH;^@(%{D=SWAE;KVNGbXL_rK4jOP6@!i6?mQ!3SwJoBY&I{S@E( z-uL+GSHH^7{_M}9wdVQfpXWU+dvmiP8%Cy_8B{I;N%+x6{B-QIb7h zcb4ZEIjdR?NEM-Oc=-bVTe{iqICZw`WQGk#Xj|W8`RF7L|=IkjV6#@R&+QSG|+{zcvJ)ou94P> zYmShG=Ltrg#dI>Nffx&@Ap##aI)poQ8L?wCa&MiW)gDpH_~DEc0w~XnmqtO1u%a9{ zVjM7{bF72WS&(0QI@e(@FTIN+Z{_1NC7m`Qh~fwlNx~=`3a4gb*q|F+D9%KQxOov+ zDIZTAKQ@&99i2+VTI-}a1dG6rHD#;5_$wt7$k2q;6B|AEoNQ3#yMV>*m=i&ctP;MZC5I$6uosh1h!^B)oVWHGctnb{p1? zyNH*r5?naOEsGEnfq#hM3-LYM}NCy5FJs zbN>@^Vuse|{;&8y_*1Oe?YIv;1D1{Iwoze-u$&YH$TTs18i=q%HFyE(UZP!nl*pP$ zzPB0=?2qY06dSi>Y;=`YgmFlZhqISBO^HNYBZN-6GIJ;f3d@b`K$= zYlO0zyqn6}Zi}MF>Zr`rL*}y{17HZUYdZ5#8YLA<$N4aoT1UFXngp_%O4RD&Mv+T%o4W5{U9%U=l3A(qe&{EWNnx`c=I0Lii^kF(ZEKW}1Uf{BTV zOowCOVgt}@Hkq89#P@x6?%c^Q{^Bq4E5Gt9bh}-C?&p4v!-o&^JHPWgeBu+I;1_=3 z7Ys{62tNP$&+`X=@CW?bul*Va4<1BH$uIx%FZ1(1|MUF%um3vNu3aMt0zUV-&#`IK zCO-Sw&$4URuA#N?jb4y4Tgcl9q3ggL($xp{;%=Fv^}W{#&R;XONTOK0W)3O6uETlp zcXCwcAze`nT&zUqkQX`+)R>gZ+dfO<$p`UvZy{P)yNSH;#(b=A;q-^FhkfO32wDt< z??iSwR|uK0XB*bxnH{W4aa1w1@70ugWr_56)I;%ABTPwhfn}o4mk4b+3BB2K(2*F9 z*bMS7(${AA8H*@~5F=)4W_~EWFZGy#-csu^oo&)h zSQ`;YQLQGO^=K?uFm#X7>HRqR|Gc239;~rgQQa~_BrCJqnOo zX{@=exZ5{kw+|70=Pca!8RD5eAf4M%of|5)~I}!FEbXRQ{DR#M%WE8F`dc-XuA$N%$=}VcZ~vA62-`>i?@3- z?)F*3HrDEn+)HhHSgV(CPJ9!&c*2~^xyz7Q^IDJa?tE69!QFL^gr!r&AB~93&#ZbC zt8Vg>An=KTkZQf2*xirLosn&@roijVi<0Rv=i7+doP1tAbRrwNCRr}15c}%eXs1rJ z_d{r>a%-__U}JAdbjWC*=c@j~_06qGJ#Nivfu*}NIxpgdS3u~*wQl@Em$r*mG0}x% zR6h9&=s3cE<2!gydm->7ypFX_5*m2{Uy}pGiadlk-viUDs-R!64A*w za36Yx>ZkrMsMUEo|KZ*kiyC<;Y7J6gZJ1!{XFo#c`-f?L|1BeLQT0-_K{`PaDRPBITy+r@5SD4tpiETgsX`;nN!_uDF zKz!*G{`bCwbS+eOmEPC?6ScqgD@^>-|4RMpS>(({aO?EG{-04n57k;?;&1$8)XFth z{-2*EUb>9`(w|X%_7~XrKm1Q@ShxbUCU&Dnbmcs~Z+!u!wxHcf3<)qambf{9s^AZ= zvup}dEQ#U07SagHR$S-@x8eA?@$>vsc-u|7~GtHzsoew*E`RIV_{9!iI&%f?lNWRY3X@BU`po|@HG^IN zp)(!%Z26OpCuuN5myE>~?rRhys~+CAIb_X+-V)x+|B>+C&k*kYh>0IjkAi*f?LK$P zuCX6beQ+<~!ZMv#jv!_xQ|~2GF*MaFP8fY!xJcEd+CMS`OLR_%IRgt8u2G(=GRChj zMT62>7ad6Q#Yy@emspBsP7AG3qYeXg{~d(Tbi~8NvToeSiU>?$|7roc=VNc(K=qLW znMTa*zL(ne5Zz_$GvCL)_!`>wicBg^=G+lN7&eOrt*LEyuL}=9$l1!xjJ=V43?5Y8&Ft~rz>XpCHawu46-T46hj3S zn9)8K5~*XH=qiowtF#&)BoY%?x^MW*3Dc=^*G}X_ZQb$Fo2g&L^78Vs5MpXvC-P=G zF9U~=!-o&EW5*7*Y}qn&#u0Pu|SoMnOC~Ma3!leVhWm%j&b&}>plZ~4;4aWnN z9&`tbihrYnTcCmn-RdH$F13RPsNS^`XUhgts70}H=eU7_V!dnlUKu7jnK!g9AI5v* z_ZdpG36VYUbdGhAr<+j}qfaLaLg%P(**0n_pAqFpQu@0}BZj!JumEUgXXl9Hs65t| zXo?I4#FC;x=D$z+dr3jIji}4{NTNgorI1i-q*g?eI|v{A8Pv=k@Y}a`FQo*f2(K=) z`sY6&T5cI}TZ(pUVj$p(9G%m7D_WxNAH|NYLD<1^E!^1+I6DvE-upqc z?cl%peZpgh&`Vd$Yf2;JXKmSqd*6p}_B}*!=@h*m{3%vz5#4K}fJ=)xw<25zd!hlB zFhy}hI;^jS0<;}|kAL<&GI?eApM{EYJ2fOR5_vc7atTBZcU_3+QFRtwj4sa7h)Iw3A= z5~qO(p~E5YK@K9#pFD$(nI7syjJ~A#elo|#(ix#svLUYA;!yyR>6TCZ#M4yvZBM9| z>elb&dew^Mpxqkw#n-S;eHVN2xN-gP>If-OJ)i!ub3~m!(w5o#opOiLV|Y5cJaizX zpxf;NP^;C9aAgL#%CnhLg(bQ79K?(`1|;s54S2gZqhm7;BK!`xHG|UzI6z)5Jj{DXZ&8N1jsZlYJ(acqY94I?Sod77R z00wIq@645(oRLX$*Y|zGD5O@cCxj`T8FS9$(|LxAATzEoc9d{ROiOW4#`Mbw6>dd;NRq zxdhjiSo_u?`p3>=O*RrhFQ(afo=R{Mu#A{~dd&?Q@PbnI#=11E96V7}9?RCEzVBn% zmeDX#YQ$p6Z;nDOLN;)Vbe_jZ{5t1-R~%c_2(9V6dui7mBeo`yQ46GnvvroKAAiyS zChIsO-sl-8gjlg}=fSA8#`8Qr{_&3!1Oe@Kd+2x*1Oc{fbMW9n4jw!>WS=ZAFAte1 zzVCD2efJ@R3H}35evUV)O#>neqA z_mH&;)w_3MZOMJPW) zcl$V7H&A_eKlYYc+^rjMW~b0mj2esq+(h^FdPUhS)0{02xpooz!mG(#WFmZ&PKI>J zh|1u-7zI9&?p}{QIYyvE-jyiZO~`iXj3w$w(Orr`KCW|tGA}ZdI)aB|Q>oryN_;l0 zzCKJWh7`NRk3N?u=u}WlV?k+PH|36w76SX)J4C&Yp&c9Pb8GifDTI{R8=7Dn@I(~w zC_U7a7=DISt658jSXQy(9@YLayyy~A2RPwnthfbIqB@Fj{v_ea!vx0gG^ zerb)UR}r3@85wx5V9E8)^&8%o(m`7u&Z*~d-~D6c>Lqk-3N7TQGZCwy?XawP#%XGz zit6+Um)D5f-Q+!`(Q=Y9d)A2ZQJewOKqrn=Dpp9>#o5qAPSmk#9@fkx(vqksHo6hR z%-AyEYrl2+Kc5M(>eAU#s(dQsCjsMx1o-l zA@25!gNI1R@8JmhF!|MDy&iX#yex9yOP+NkN~Q_&BREFWOriV;ck3+f_Km~&P>p~} z6Z)&zXTFOF`-FQxgr44s4toe4-@b+w>@%X*0eC-D#z+H^8rlGEgAhB$= zsrKHX-g^z9LzJwg=m6vr{L~pFM8*k2WD1HbsFI&{Dg(Q8L9-;A8wio6E#@?Nbe1h) z&Ib>vder=P(MUSggA{$)be7B!E3hQh2li3De=h{lx^d#Y+)LG%!a4gY?& zW_@chT#z~$bsm7lI+c$O$1ZgdEXku4BgeHOi*EqNSYmXxnUOW4DZJo3lb!G2L<@<|M*(Wc#=&%JaiC*YtrK58OML#Q(PxtuRBDK- z(F~H6I=bH_c=u&Uv~0Ar&|VGcRuGnrYAq9AJ7`TD?h~BI!k58CW6zKO>>HviS7^Zf>TM}?hGCD(qL#_V7OE(q_A&9p->VjfOs%M zBT85w0|!fTF*%c*=$zhw$kMV4acemGlxmm_X|^KK6_RLTs=+a0t4X)|Ad#Woo;jt>K0xY92fi+*0m$1 zYnMVF$0Z>7^)R&1)LAjrv}{QUalSB!pVkr3X+fn76)`&ol|?UfiOIp}_knjiGL3J61ndwQiqd9U}=q9K8Kh)a7%R1^czXnF$(P>RlcP= zJfs8H-~hBy!og9ixWNUS@ETSB6mE10B|Vh%h%Hl;2v;M#2E-B3g=2|Rat*49CE=jx zvK_?CW(a-av+ts{z}mPIyd;puF|xTK8L=`h0n)3Xy&5{`5uJGpEDKqkFaaKjalon} zR79nJ9El>d=a8z4l63-mGqK$?it8#cg>RwzKU%L!8v$T@s$l?zA1SfdWbPJ?edYzc zcfO41Ttn68OxH%I_tc1Cf|OWQ7pJ)q6@(p*>3wZ9<7EAc(9fLVFe^Y@`lBM;IX|nRXu> zodub~PGkmC2bQRs{P^k^KJy@nS24H_l|5S#o|~+Z+a0eI+M56s{SOd`S#&e`uH{5H{nj}mX#YtG2X=jQyM-UB!snzN;P?{0#t zi*#Q)hro9otLEu1PdXnCB>2MXEOS{@Z9-rCYflbd0ea7AdBU*;#SBPwnA-)DG@PcrL2d zDOjH0hU6CzSo5cG-u)_K?Xp=vWZ5=(E9C)>Iw+R(AQw{<0lonMP+$a6a7rWtH08QX zas*?8wRs5r; zXj;dq^^c&0G&b~lWOF_0IVSh7q*2`B z3((s)va;TL-fkeI>^qEm|JyRZoI|DZ|J8m-?1ugFALK_kGk*#aUpo^+br=*NTYF1T@EJz2UN<$H=tZqlTHWzuWrbvlj z30!*cJ^H}ak2vH6X;$faFM%|0S!I_?& z9p%y4&bUrGEUGered#sy)OMnsPayhX`TD(qJ))IDIF4Zv=yU^3j2s0LCloDgJTeT`b)p7BwP!Cik8y5r8yZ3Q=oh3DY9$TBEf_*e=rX5K)8(BhXGR^`&65 zDV&P2`OAl};dq;cwkC+sNY$a)`950MbSe+fclMy{CQ8=OI!4I2;B`M(w^9h=Na1Xl zz-rb<42ky$VqR}w-WapQLg*NI=@8!GKScO#bZst?{3@?0h6%UQsD1!K;BKBlY@I{J zF{edy=6BjQYV%z3KJtg5VeQg>I6>TXTlLKDam z5|%9q^stP@W3fOBF!;fGPdxkpFE2g3jFA9Y1|)<10Be@I)j}Y3_1x9fU0w5-L*+c* zywjN?_V4|%<3#MeBW_NW)xv8z*Xphu?!D)nh}e7oe&64Bz*bsyCr6w4Vu1{Lq|1wr zmfA@$3bwE?&Pz!bo{8zKDfA3>6$iX_7fH{*3}5+|jNkWXu>Bo~&C6z9Zfc*q(e=IF zb=7G>|G`7#m#;B7?_@bqJL^rf>qHa@CPm(BdEaasrB>LuS#i?1#I9p>jLA3YPhY1$ zIY#La=nT~)L6d$B4Oe?BpI(O|xx?RR6&R{o&$P7I5Cv}0N`&J>*<-V^q6I#8sAZSFr z_eq)&Dp>-zrrRamu|((K9;B0^!%1|GmoJtL&|*S*?s;Ug3XlCD#g4m?(!}z*HPD@^ zBaOjsjxh5*7Qf|P6qi<+p1bV4*|M}^E~yAs4OwxSxy@%t?FzYB2&mnDGubfYl`soU zT4H&F$#Z0EP_<}k138RF>pf^%BiTUkNQlS2n!Ss10AkG?Vn@skpJ$rwWMX!e({5WP z?zySIofc%fw=w_zN624Hlk=5@oGo^^F&6Uz8_s6X~FZw)5sT2eS_XGB3Uq%RKwq6{JmcU z>|i_Di7%pq-Ao?%cq^>DC1BF;A^l$M)#U9b{@D?nA&uTyKoS?@y7_rJ`6;H!4xnfx zmxLIUR3KipD*V7a|Ia=+6Z}MNnea7ZAe%zN+QU!+bJl2b;NMqiB4C1Ll5C@spJ8eJ zGpsCp%$;3Y)Vv$5&ncCVNg*o1M|Xi+7Bkn!%=K>pFmZCZ&VfA)9v{LhpJ9IU83&Y< zCbq%nsA`7U;5V$!GzR!+0>q6d;mR7o3k(s@^cHUo#bF{6fiO|xgtiPg3|q*%yda3i zX{d@d1CsnI-Qja^*8>bb{GEiAUw zvdN&s{70W);UkY@hhvJ35#zVcGd**W{K^`3IAMm0q)CGIyU1LRbZH)2nzV`m(@8N) z3v}<=L-){blErz*k}|QRpt!akcqn`$ufh+QjD7oGnmB0wjn^aXSA`J$Ofv-p09?VQ- znWd6=z)KW~D9}i1@j(=olw{*P`Q~Nk197_yqVgIhi+vJlCpU7jO6@YrN}W0^X@>+^&Q=JZhAeM6x5Pje3R_O-vm3w z_LnM6br5|$iviZSdMsaSl4HqB7ypE8?~al+RX&S_Vr^0SOBqa>RLnXbgu@otVc}6a zo3)!SLu>fCG36Z(%IVSM@`;}hqcZ&b@n zr;XJbNKu02W~)NYm%P-{PG{_Fbd0eh2IE)gjgLFyK9f>N7o=O2_@QOKM3Mlhido_|8;i_lGHQj6%WX+<#~2vM7lhW=^kc$@*MeCR;bMogyR^QOM+U7b`<5@hu(*-O8L zKKlLG?RO(uw63Q+nv~WV!SgDi2@l{PUK+>;0s=w>eJ*c?W7blYq@ht{g))E>$u~UrJO-a3Z3Vc=tiP zw3}K+q1D>2rPtb$qE!OuRl-R5bsF(h#G7WT-1C{R>sn{F zMkL;k!&I2Y#^D#(v-RdfCzbp#uIJp}o3N5?m!(qL0~$5GrtOJ7%U9w?_a?l&zgm{gg#0( z0wEfOtVE!0Y^Yj3)8U{-JrE{(fVGXM7*%>Kd>Zw_p$5o#~6)APQo)YRy3wY{luZ0Gb-|({*3R)vy)_)jf2-u(cV~1k|HW4VJ%tx*@|M+c!zWp^Vc>2w6tKT-gSu&THjq; zB8T&+nea_*t7ugX&D`SejmIP!fxsfbbPA(2m`o9q1cqZbdoR_CMVp?x%;fSarrW_! zd#d!v7vEXVE4uEpIfA_#@ELw)D}pX{0|vtPcM$axp&s+6}X2x@BMI zB`6(4E&b68bn??|_8wx~xw|e92kHX5&sD~&4yz*1wwWgiofDE+Er`+9|d`vT+qqt`Fc zeeT~fe&SDI=l3Af&2P+pC*snOx>=Q$NeL7}ck(9P$qB}tgA99*GEJ6CsQ{r#d1J5` zk3OSy-I6>}{dY1YU7Vx$=smTuy58Y6(p?}u{&})D|Io2!OvmlRgh?B23k#)RI-O!V zDcwVRoWWlikBi>~NKg?s3r>;X)BDq3t-$oAAIj`!*&2-`nd{L#xEGlpR8)Cs^nvxT zqTafkxwWjEBt80R^0bRx+<#N+>CO$qO7cdp!_s$sfUCdvC8nn?kqkPhCK#R2AHPak zTq@a3X-El(o#DM^D|{$xL)ReI&08-upb^Gqwm(x+?PE<4qy`jC6^W`|Ga5&7st5GD z<~%7@>5pGyv-c>4adE>sElB3NEPedFWP7)}+Aw-=cdD+_q=OklnStGh7`9gxa%JV=7kMNo=q_LP}##9K!v`W3UBof+&kBo+Az4e(n z1OQ4P{SjQE+od;1&wP!^&ijy?08Fr2GR*rVbG^VQJ%stf=Q8|v=atc!o}oK^3!@`f zlg;)c*@_j_I^K$78LQ{CAsUg;$*TrOykszcuvHEE#AC}zGsj50B+Vc&swL9MZz?b# zmMp(YfA}h!{RhkIkb8a`;dRwGiAc-$Zxyp`9<#K7-Moc;G09;4D(T7_BQ`~M~ntU^aipn-5XeQp_iNMWlyj#7GJMlWUbjJTigF?4- zUA==t(gf4ZFue}R{D5?Mfpq&K>CR<}#R0N?fo$h8$@WE(<$26}-rt6xEw_odSQY-rFIisyq8dc7#^O7<{Gr>-e9Nil1uF;|YFNp^epvi#ca z{Rc5i3r=DZfnJ3fkk~Oxn_pyM{j(&xhG5&n88rqk{Mg7AWTd*LP0xH02_Gi$;4{?_ z4hSBNEs{^f|2bMs0i7ADCCx80xA`>|HooW#24zqd3w0ulTBUnn7s=9G>7(+_0l+tH zVA)^BTs=YWEB_LitmDUJi`P8)(nR_k-GVWk|v&GuACq{^E@)yC?hWQwy*2Wt`R#NGkD}~=H7Kbb~tQC#1cM- zp?+RGUP;MT(sq#0N)JVtA3e{~`lsnkPGEGyHH?AeAe{cGFJp?&=it_c6T?P<>`7+; zzCc001Vwa0Z*rW)^{1HMd=??6sK8N$I40g}W;KqA0*qk>?p=F19qak@;0`e z#z4PpStk2G%UX*aPLMRAdw3tc`wwFlT$)e4A4V9Mrz>wG;H9U(Mtbrq$ao#n&O2V$ z1^2Nm*t4D6Soq*$WV@Eg*EXHpQ%CeBZz4K!b3$+6Qn3zOUD3S=OurfOoxCgKZdb%x zRob#f;z_^6Q;TX0uJr>`{+o?W>q`L4pYB%8S_NFYbFDvq6=R23(?!=eF})58-}WS( zLwg}jTGz#$sOvOIk;x|M`ByO;mul1CD8Vt@=d5=$i)UhOg8`SSKXGnFNumoqJIuq# zSDDEl(a`q5P!!&r?5|*bTBzBX*@HvuVtxk|?OM3KTb^RSrC6car0}l#YK;$RsWOb40L|rU{sDT;wC=Glokv=nGjLkz_J_X$g^8 znv>GH0jEiy_I2qRHW=#R1rj5tTJtbeT1Y5qk7VT($%R)T>AtOdY36#EekY&+Dhbx~ z=uJW$x6e27mzFh? zEpmEC?qdFZ50h-$2`iVG8^40F>!C*s5~Y^4O*U$T%O8e>C5ARGlxeUFJXtWYJiyDx z^L;hEgoxRnYoJQ1=2il1C+0{B#*UdEKTmr37%XjP@uQDB5HU43mB{Az0yn)zR3V!u z*|
    L;sxNeHLfs*yxY{nv27MdRyyE@`w5nxHQ2 z@z9afv10C2%muH>6u(jT?wdrwgAk^Q(FC~~L%-S2oLzrofA3Tv?UGzOOM3FFkoC7P zbB+O%f@FR`vU6LR{G$!1M7(i_sb-QEYkC-+GBaF8?`H&#pb|1jJzv1BOlJM-7@j|~v(f_*B=Y!*VCJgN@~oYWZZH^r9a9WJI^}ce zR~_|rt-*iW*#>V(w=X!x&n*nZH0xqk&XSyc4q3YlS(jwn0-gQ4U7$){&^&1gdxFNl z#tTKfG*NAmLjpW27=P4k_n=M-8kPE)EB7?tlTD=gKB|3FqzSS3!yzH46C_E<_H8HK zwurR`S-(K%#ovT{a?^vbo54R){v-MIM=FQ;kMe&t%Yxn*cfdXV;Dw8XmM%7V~{?Bz?HSLmIdL6TJ64GASq(-jJe$(sIx|-owgvBP_geEEiD}-1h z@WpS=)YpDCr9T=pd@Ypn2+*l$@PYS2{p0<3;Ks0HR#a(C->-~kr8$fYyl#Dh_pER; z2{M0L!)#tbjoi@J;kuLbNls_qPNpX>kgpD**GF{1VDu{e@tb7%`I3#%r=;+-WXIPu zT8T8Tv`q1QUAYg8g=EcgZIx3i3Cah*hz``zG-N=HZh|T$p?coR236G3oxFwEA!)J7 zsCOSl(#PbRXkp3r?ZC|Uv6K9dcug8GDd~Ud=SWUIjrQiNh}Zhz)K;x{y)G@a{HU#x zY7VJFl*D*G9O|Wd1X{RoVpmd|t>Kyl z?Y&Obt&P1q7(9N2@muF1OBz$55IC)q3nZS#c;$?h4no0T{4%}qn`G0|ptkgE2zP%1 z-!DV_JyE>1&`P;(nXXDa&yxVmKr_GAZb8KXC!%Azlj9h>PHL|)?A%Xo=16qIQQ*;d z22~eGs;z6kD#gW6tgq33@NVYb{eVl0yHod4wFK6b?B!38UU=E<9Z42=AGGWMQ6k`+_reEz03cj34`rpoX8TEsRIA0Ww-4ee=`UxgF$py&D-``^MHFWy(+Q z;ls`}{PX{g?(vsgGFl9X`VF8j`xD<2gfP7*`dC(CSJcGkW;9EXO{}GomLT=x&b3{#w6k}xdG-mBAI=9P<3vKS< z)gP<}NLUT`o9NhY80dTcIvS@SYV$OoHGbARBeZ2e?h}v2XNvh(yCTfA)Oy}pue|r- zw=bZR3DOy${9U zWu=xmZUR|;p5EjbL-R0dveFaCr5w(H*qS{g!Trc~EMw;T=&h`|tWSFC-;rE@d>!o! z+Y^G-i5f#Q`uTq2copdzWYoC~C+ORXmT8ph@t6%J6~Sl5H9dgf;d$kLtqwT*}bn%r6a?BmuFeW*tIOA8<(P5eFl7?FlhJclk-%4g+&4m9r5sf&9& zdxgo@kCECDgUKrlhA+AZUg_3{ztF11)Tn`!U}DiS7(^S%A}wC-b&8Ou4Q~Tq>XW2) z2uH#xSmS_f;sRIZAEHR+$oBV1wk^~KsDG5dI&-AwUnV{M3^E;} zogIF*V{%n_ksLnZac}j z7fBWml5f8UlJw3z|66YLf)2-Idv`GZ!AF^%z8Ljlo@Yp)SdwFzT9A4rkj()~PuXpAH zV7K1LJ-@3cfkPu%W+g?My64UedUWS|6r(YAedJQ@Hb>}ajGel(T$R#iL{Tl=kYpyq zHO8e?36L0)EOY698FM|7K@ZdKL6$gRB?4(hT4%UH5iPTcyfy(P?Ji+f&(L}Kli2xP zXm_zOBzR{_DM7~*WPXvk`zCNskP8XZiFN0Vp~VX$vN35n%{5Lvl9uMd2g0N&@AQ*O znyw{&Vu)|!=uc0gGo2_Fj>0>UwN_z6kFxVE( zilg+P>bh7Ts8bKr@FaqwEyEwLJ#I}x^lGk_C|DDFWCRyih;uvYm-A#6LHa=6s($>jB(k?PyB|G*Rig*2p^R>vwTVMOaCFP_$7BN{CgtCP5y%J8)8d&R2 z&odakSh5j+Q)Y>CN@#LR?A;MLwrJ}xE3S>a*B3u#*1Otqtxn9|i+xmL?+p!r&)DZq z{IBuZu~D7wel%^RxV9j5GY^?`=Q7#eok*6V)2VxhCUO6E;*02gA43PrrD^ipGwo0B+!-Zz zoNaKculGmsns4v*%Ef6?_aNjGWW0vtW6Wd&8C^xj>&R#w8Ll9cHAHg~wcK^?IhKaY zB>5|UbaEWH(4D8~EI@Yw?aiaTZP?zT15&bXIT;fNoM>^=pYxq&jvQ!kDwh(l*lcQ_$!YHO!dPEfI4?40Swa!-(6|rcrS)1sZ&P zxUYrMkT5yOXJo{Pkw>=|TbpTmRNFeKN0DNGa&snQ*SnX6CEdP_?5=%eue?Ej<7MWj z&!LiHP0t%MwVBs}e{r=rtB5-fe9EY_q#T5!UiBWS2;%S&@A5sEs-ageRxKJI$A@}L zL06bLL`Mup&%tD!;r912|K2B&xxtp~l5gBz=fKtM*k?#Czkv>R1Yn|zh>m08ngf}C zS>lA0AX8ilY25mn`l`893m5z7gC15ixUzl|8vb4z6Nn&kShV)B@ig$Zzf5}NP3+09 zFunVO&V%6{-s=P*+rCKep+k&cKjmVQjfoV;+AQ!|Iwd6~DHCw!N6(;YT=GqjprQ?l zc<`)h81)(WIzIO5G6Eg6m6P+0LskEXdba6=7-N>bj*7HNvtG@=25#CX5eV0 zZ`PV^QNEpGbIkk)AEp1;y>+zU9rR&KPRYKdrM z9WnmMbF6^LGLjuVH(6ArSlhs^Z=%z}u|jO&sM#uvGY67%mX|01Nm6$P^*W?~%L|xZ z$5D-o0t$s`-mtV52^ma*ho6{W?=hw}Rc`D}-GKv5Ui?kQ@BT4J5-9T9swg9XA6jF)IpMA{2#L>gjHni|l5PeWxYY;|T&NAQgp*s8H_%ex@D1j4G4K@U| zoNg8J7Cuf2A_<~X%(auqXboNHIWTl9xve@TLb`pCZ2vB%msaZc9-JwEKHz6CI;Ar` zO?P@4YX$*8<=433^BV%bQYKD@QPAOZB*<|LBF|lBBA#%k<|t^iE~S>s<1t1nmT%}S z7i1tvC@6|$^F({Aez!FAm+RMcB{MmB z>r2SSMKtRN2D6%5(&c%7*g;|O-!A#`ysHd}B2jR_4bZss%I$?JOEXQz}Fxy?|()F`G% z%djf0RU#h}Ozj>Y>hziu2mi3rXf5NJxruL#*pT|n?yqr^zvuuASuQm&pxS&t+Njbr zFyE{{vzGO&pJX0?r76susLKLP$_Yo~STiY%*D%*kV+XsonxWnJUW#C+Io(A=ws?y4 z;?rn5(KE!3Cz!b&^B;VS>AB13)%BKXoV1oK6&1Pk2T7PR7(LJ2=Cn=DNOls3$2FQB@qCAZJpSlo7vbxZY!2x6zm>UmhZgjraoch6mnPo1M!-KeDx z{*{opanOpfrV=HaZ8@p*&Za<4MuP{U-r1qS6y5)`1`WRkO`x<(k3CNTnd{L#u$Odc z4mPiU!rG;viFrqW_awt?Tyf2PXU>5o;!TA;P&F{Kju=^f5{X7@gD4uj5pq;Xl|v@Q zjPWSmGi_}Rx;K(of;x|2V{0Rh%x*vc?0R?AkKC0OiA)$R>@P!u|8YU zt1co>LMi>wk_1^jgY38)k{;OU+uHBUt$u@u+*C1tD~10pP368puN#=s+~Re);rEGg z)2U)ga`ia9=l%_y&;4UMFZ?>`*=Lb|&C4b8Bm)xHc#A}+>1+cq_4K#&JekRJP(ju& zlAU~-&I`Xz_cQ+!z32W7>D8m|aZfupwSeEwb-A5;BAS={%y0@MUIi{KR?ixZugz>z zx8e~lWD7{&_nh*KiTswui$x1%AsQScNLx;bw|V$ch_hzV?@6QRNAa5NW`R?Gem3K| z_4|j5Y6D;P&objng=TNoB*=IJbL~vrz24fhU{YAU%-q^nn3Ffr(nOYKe-$_r=&PY`h(wK@H7SG9iws6DVapibI2+8@YdcTevQhIu#^Bitapf|9Wl;j)thyTw z?YRcVdOo8fzQv~M9^CuxOx|K?{fkf;)P_x}Zm}+B#aJ;Kv-r_>(R<)>t8sD&R_IukN z%N!5x+|;@T!<_Nm7Erl=c&5R#sk=l;MrjwBY|we(*OAdG>ZRsvb%xw*F?*wXscDb& z@==mYub0vSF#Qg_`|l##yTkc2%m8ZjL|xi)g(R>#j9Rximm=hb1?R0sg!YExx^FS= zOA}^wLo9pnPIQT;uPE8}MFtPv?Z6Tgk%VM;ndIv6Quh7!&k+BA{#C#4^hqwgN_y#a zw9^lEvFek~>RFA8ub?Q{x>+lm-!{MA@Un(Ag(;1`>w!^dROz2tGZu;j^){jAyJWI9 zQU@hE10r}qG&EP1pyr6ySLywPEl5v4i%izgq;vgsQ4}P-9@(Dlo{6cy*fr!4n2fBr zNT)cDCG(5cXtJ+=6$^Rx?-HEELYycijkJ>pSZK*{)F@I?G_JFx5!)P_`vxe8ge=$K zxzOmaYgC{9_#z=Gu94Mjn|h+p~y+jzJQFbR)beD zhA@!`bUY>9u}Jsc{g^Cu^1B(6NMqZXraaJxZl%E*mgxF_gwH{P(63&i)E2SE>YW$y zGwFlvK@uWOutbXjvp7%p?){if8u(1A)IlJEph<`9_-8SfjyfNhw^Z-+>(!!-ljeUx>g~=v5T!ry! zIe9i=2xvY=N2@Tp=A4;*7E0|-Sx20DQ#?VC=?KYxM~K?ipqQ}xi=L}lVXL9<0g-{2 z#OVrU+?)oHZzW(d*}z;o&Gm9Iwtf!E>zHJuul+vhsi#R6=Sj9LqrNM@_;MENgV;NC zH8P}Xvw5rvqqqRoI;u1t1vO^Yv$f^B<`Wz6Da0{^<)-eJ)NW%9k7bQwCp0fmlaOtn zC%JNel+KI4joG|{?Jkwh_O}jV-tM{-V^C|6)w88RqcdI&^w?37Q?<{iHiC)*lfDKx zQO5mBTqtRM{eyZpbafY@*~C@%K!ORLzgGl+K_iN|{GP0bY+N9H>uD&at)<-UoFUi! z8f%d>VeZ`zknP*y?qgwtQc?m)AOtgtWWfA?=GPgFUP8zbNdl9#>%oaZ0i>Q!zBavS zs-h?=A$6;XyT6Hv9|Ks+9!0@=V2hF<b`6q&>aE^qGD_or zIj+tyt6n5)8y($0Qf39d4c2cQi|l_u-yB#q^bL?|%^7DxzkZ%%nJ*B-j}>_fU;>}Xs84BGGjhy`KsiK7wJ!Iq6eO@@ja zx^S}Ej03%%UzdcU4^`}FjHDUe!~5xf9Ny;|sad_#nIpM;l=O{HqoxzW__uk6H0tE? znMkf2#augCHTJ%IBG^k>bSctqpHNQ7#bf_UtcGngSB=R%wvtFU=j&lFU)NIFU@_J# z<1m#lco@9Bp?O)o^e<^K1EU_k`3C4_c$t~s;a2;5HCRjpv*e7OiT%+u1Y1lf7qgcs;RqMkzs)|^pvws(6(7!2@Wi<(+mgM5AFxf=XEa;mW zb&rK~+Y;S-4d%v4R?m`bTnxM#Z?_&Ww^Kme&I`S>n#n(U zhRKZ@NISm`iYc9!f0y2u{~77gr!be_z^q>YTVT^3nsgA8hI#946F)zH8(XL+L9sVt zY5qo%Voip22BppC~21_DNZVkE!_8!c&@>}kXHwgS%s zL*>X1ONf-3p3ZzWV2GO^njR0qGp-thB`GrroB<5kOTSHW?KG5AzPB@cyYanLG!*Hx8qx6_usv&%&8X66^?Gjo8k)q*Q+-L*{jZ9n3 zTLX`r2*px=(D4NFg3i8O^d2}&x@$Yq&9H^7<7-U<<8{p1xpE+-w*>Cq+&vLwvVn}& z%a8%%u{uMO$uJh!YpyHlYTN|JF}#s7EdVki;8G+wkXwXNfd`rY{cWtUibd!9JU40; zZ&2m!iz-1!UVWBuFRrE5cppJ*L3-&;X9SvL*9EbEY*AqPT?XHDKawUcPCNi5W`F3= znVu%iFQbwLA4oI;1EigC5XhyYCPX})lzP33A|Z=YwbA5dHN?WB9p0ZhM(TI&WS8rJguvr>VMn^$4Df|~Sg?REcG zO3pjihPXL%)^&8Z6JH@c^;MFKuOaK_(B2Y%bmpso!O9Pyu{{S$ligV?;&~j54n5&{3jhqBi$Mk7L7fT8WQ-x zi=(Cb63=|F;n5#`jZ)H;^C55xO`}@0GY?q0FaHkNo1aGP)IDD!Bun#TJGV2raJkyZ z>Wx`qp)jE#Y?N)UG^mBGY#e_zNqf3~Ks_x9AxQ}gY-mX<@TFGbHJ0K13R4{CIOq1o_re84wHwz8|^J3lg)1gs_dH0(F*CMH=O%^+HE#QacQDa+~TZI zqfR;SJodu4$7)~m*k6&Ub4={<*+YKw8Qe7w5NVYlXtM|lJpNT7?IXpQ^yF86m~K0G z<3xfxa#ScfnbO&_llk{QOun+t^wL$*rTGR8UrJB`pp&0rZulI=uDir3yzA5!Er{=u zUq8p%KAIyAE!MUH5Fr^`+oF?NlOUSLezjc6AU0=y_;m`i%&2oW=z5FKid)mg<_Ocx zSor8S(b>Pl{aaygsB6F3UpDD~kgQ!Ky?hLrtfQSl*pvnI5E}8LkwrMT({U6uTaT$#u-h^8%A4^zOTh zji+D6u8)w2YcPAobb67bSO?RMa6j?<``XMsX_|&dqB3pl2+|&~9fL6qhuUJ`67OGrjjaJt62nk+$19CG zS)<;Ic>kQ;9g)bt#IbE{kz@KjI(v4|xoZ#fJJ|8G&hYTfVzrh7SI=!WM{?;kl1oR( z55Er?-oB5?H@G8z{su!9cR-SJ+h9qVOk>tBkez;p?z8_p+3WufiV-@$2a;~U1gSSj zf4UJCG?iqsrRVXdA_3y90caf_l4%d^FCjqZwNKG~?%$BT@oCKZ1+>3y%LDbDbXS+j zhNHvJA`yM;F!-E)ud88ype;jG^%GGVgCP8PG6f_bBa3@~NS^#*%)KANUOSCF{tWiw zo9<_(9Y>kleu(s4KL~?u*wfEpU;iwFd*8#tcl;D~+aU*tlpBtUhNf8RqRNtQ`V*La z4q$+sGg*OVD8bfCzOqGvM@)sYq>ItM9Z~k3z8FGAbaBvYgyhq4pOEt-Nalz>SRPS zDNcit6@y7p@v5=k4o%HBl^uycD2f+o%TpRp_nI|-Z9R>k@-qqM!k)K}mV2bOP4<%n z@-gY9*D;d~xURwD+do76e=kTg*#K zAK%d0NG%_0$bS3{Qp5e%FEIV7mquDCZKNc`<5y@dn=e4EFYqx5WFx9KAz?&_vqQH)w*HOA{k#yHG-MjbEy?Y;~n_)*2m!LEQ zq@|woi%F4UT*_^^<7bQ}8OiyVFl*;3DO4+KM%ztwV)NSoaaY>eWg4Z*c(riI0GmC3 zm*Q=05=d`#i-e{?;v6-|+T#5b^x(1fE&}x>TvDa1A&i-?Sz-xt^@L+iCCSY#hi*pi z!9yhTJ#?CvvJ!85%P*4JRls6rPfEa+@e_rvvt#)d03%!(1Ep>PD*F*HnN>dZenY1X6ol`{j;ku$S@kh*rV)0|{!j_%?8WOwaB`d#OVHuGwd2z&BPfIKFa$`gDoVWLD#l_d$VRa z?P9JRC%OD)x!>LX8FO0?b=2@96A4?S+mlegYg>4>93M5?4daDuD5?*ZgfbS z6f+%?oPX85()4v{2;hcbIjGZD6%>CY}@=DJ2QgfJTI7g;yyIDtbXQM=PO}+ep-sr3BAd2 zI+OEmVvK3PS+y&@1TjV88K=g|r!aP_u|b3$4jutaTY%h<`4FXlD}*B<0<&1H-&>w6 zGZ?>wH65ErJwzqUqu$N4tz(R7Hp_$p@YEOu^Zn4YC! zymbKZdL^L5phXn*CZ1+SsayoYL2CsRYOvS)CXw;9w*i`XDaX}qZ<{oFNpaF(e`)x= zDq$1oQK@IqteSRzNKbqTyZs)DT@So1M#+uj-D*;j%daCF7o7Qh@K8qf+l9pz6T}Gp z`wybyg7K;I%=5Z`a5gmpBDa8-wm9ARVyb z!no~yqUbKKLlp)0Y^& zd5R=U0)ygz-sDY8v0h0!+q^3@rlM8yqA(WSHzW?h)fqcVn*fq(SR_>5d(yz!E4Gca zlYp*QElJ!sMVnvUYI$igUN5eJ8Dc`B8+3}34CUTR{*MTDb4+LNcIH3ynDaYqnR2)8 zdnQ5c6ti)ulJn14P*yaM<%-6PXsx{Q5a`~$k7Uq)V|@H9nwOx7w8!_-%+w70(o{mp zQ*G+*F;4oXtf}~X%QE&|l7w`5p6)&Skxs|?{#nQMtKWvVf0W6M0ps46 z*-tiMxE{y%z4L&{+XfW=Pw;xTZER}{Y7FMWYjj`uwbC8FSKdt9ptA)Jy*6XhG>9>c zwBi+iU9T<8G+ON8(OkY)@iu*hq>IjVNY1}R?+gEg@e_Xv9c(WP1$}3)>+G-dA=qiN zu`ipmwxNvpg)32Xu!cFrvqe=W&P0dp3{*)nWa$8m*3b)YV74E2QUz7O!f+L{{V-<# zqcGWo=_b+{z|ua7m2+_Q45q(K8(kTk7L~z&64_(li(Y&aS={Spy|al=V9=+2Ul<(a zB3c_Z#!|AvBx_8squ)L`kVcYOq5`q;Co{7H}X8tiA<3x$%J%QLNnnp^4Mb^S+35qE}$;~`jewqIGD5LIum{RPf z*7;Eko_vsnk32!Xw*C&R50_AoTzm~PT0^sbC2t67{D#}VC-ah)`MR_f`t=%r50lG0 zutLM<+&|mI+t)=xbVS;^F3<0wHqhfVq5+v)?%r9$EThw)>Dke$D4(uY^xm?S3rg_WI zAZE0bNk&PEOot>_PB2y5%EY=YkHWG>l;Jg`m{v^1X5g9Bk@H?NqZ)H@yfng=_hTYf zM)mbRFzgSgvJQ@z8$43 zt_hB8RU1f=!*sJIfBE%)es$*5_oN^0udo@tp0Qv z2?j|TqxHe9l?I8V?e@2iX|?%KYsm07oerISJIHo#tIqlWBh=8(#s`JPm*mW3+9rj3 zgc)7K_LpvZpG#>$Ju63E@4t5n@VM32k`{{G?IcLV5s&fDkKf0C?R~fe&3dG7eVOhH zzX8R#yn!ZQbj*s=*=reT?mZ1qMKy@kB?3jNB2Bza!Pyg(c*hpH_So-4#7!Ztou>D- zf5qhCKS93xes|E>2}CBQ*Sm&o|8}E7hkWds6KQJq#e{}M^`=7Db~`N)6iHcdMwfARO>)!#=XLDD{2w-Afn8dWH1t*D+U*mp&%VqFp^kROi5Mm`<60UR-e-ys2Z~Y-3*z6|ZeR z4DHjd2)*{{qEfru*KY9|t&X-o#WzI56G%LvDBe0yOSWeR>Ec}2n5$O6B{OqllVLV4 z(0%n&jNkKP*tCmGhukcc@J9QodXs+1r^x0CGTkVrjqQ=x>J{CgR5`jvp1z)7FY+8G zwS^((Cn!jN^xRN;6-ni4A5Q5!Jf#K&gFPrToD)BSdp04jeu#6bH>;;zB1)1X#bnDp zZma8i+pM45lFs)SJbEu|j@fweC=?2v9$B$MZ~7LZ6EIzxHhG~*q3;``F)AOe9U)9} z5;QRXl&VqjK6Ajp^6O7+nKCs)Q%&jj)07>}ydgS&r1@p~(_>7!hpKm3tZg!Q*L}>t z_aP)rT(f(NK-LZKr4cYG$(3W6;T1?SPsI|l=YnSyf0*a9Yofy1^9QJ=ngIgQ*ufi( zc9pWBwL!I?cv77u9@c9lzUI;ZW!ns1!}T6v)lElIZ~rU5DD9H0o*}t*ihS=Q$RvN; zb>!B6_c9MDP#zV$;g!_FrXw+=+m}d|7tm>r9gdj1`6gz^-SocWN6C)7$4O_$n~XmD zYfQfOAJEAVrW2$;NB_J2EZKwa#Vl>3w|0%m7e7hRb|0qy-9Lf3 z>p>*zkiYpH<3Id26epi2yZdg;d>_d&OqN!E0E$2C(U|$u0+_mA)+I99e9PnW#@Dxf zkCX8_6nQQ63D_kytG5XRNC?nL$P5<$`~5n&!eS$z6wv_8ln8y0NNV6Whw->Y%ky2D z#IOK>QO}S+TqY6|?Yt;dj{zIV6*Te*^J)Z1F{|e=8&|Pu53$o5t`R%US^V(h*tH>l zn=iacvOHhzuZBd27;>z1noPB5s1q}9CGgmjV29ThDNPMNXaIb)Es%o166RIl#h)o~ZWXn;Tpi$VbTL z6-++GrkVGQnhL55*Lw&$`s;M|d^zBMVJGR*0+Vx>$gf;;Y?CZ)?Tpj|V`d=|CbUNO z*sFEDQC+WwH%a8YsL`3=-_gRcak>Y0k?q=sWLepNnEHH`n&l-LGAU#BSkMC|DKc8c zte!#VwpS6)x7xp&7zC*_d(nU2F7u)t_}lum^m>t5Z{zjaUeo{m+X72E1JdJvpQrQE zZy}>=)kC6Q6qXHQ!)UIrnZzYs2@(R_4g{RnoCUL9*(th zbe{he(vx2;Sp@x7RC}xI>i^r#URNn5phd-)2sX}0lQN4=oH0*S)m>lFTEp4~GSQq2 z2JacrwBx=g>jM`1+;365^6!y<>6G+|??d)IiXE?^CeDMOA)Cgd@c9!KoZ;HSPRs+} zO7YqsqUT<6lO&V0Jm>B++42Hd4d1JHv_uclLhZQeO-4frpfs*Q4Rl=ZUJ7JA z(i2}IJMjfH>4eVpjp=K-k*5jW!~03MFQJoZ<)vahqO1~m0>l+q(4n_~jaBfnZZym^ zP;F47@upJJG8xw(pOYv_q8^#~Vj!%A!jf)Vbg{9W3@wTvj?=AEukkUd)4^VTll0Yp zhm6-#14sF z^xd*HA#18!_ihiUS)#^&Z%Vz1x3{%6kZKio-;$M+=wy>w(!*BQGXA@^z3!F<4XTh^ zlBIbDPd>=tk-O0%Cm$O+#aa5pmr&EGicdcxaz;n5fx(*d;YVEt?2roZ(@0lLgMVeK z^&yR9v2g9xrXF#YNI2_NjHhE(d?Su}U1s?udgEiL8tmGT!K3$ou<*gh98>KU8t>Wq zxS85RRl(+%tH)rx1||!bR>71mM&kou-(QzubCGyz8#-8q{)z2VVQW3+QQE~^Jw|frbtiMXLk!~9ds*0u+O6U@ zyV`C7*AgQtsloJrIwbRb(#0PA_kM`EANosl-}5oJ{0jDsFQd~bgYW%G(nr6U{LFD= zc`tK+>aWrJ=IX-;wFA~Ls)!Jqo8 zB>Nx49)A{l?2BX%zMHup`6~=Q_${P6mPqCXB>k>SnzOcl`t0u9)XFnTd=S6~N>zhs zJ;|poX!SZQlbfmS{Aa^V)*W+bwm;9(G^92z4ua4E>l+QcjeG#t`e%W*u|vzBTuh;u zpwkIjOd%hmHV@a9`m6(6dB)8q)s3E@VyId)A0v}Z#{`ft=}2NVqxVet4P3x7s$=Ks zbIgkf7x9^YvE|Q563p6p%;x2rT1T_>V74vNJ-nA>VSr8xC-5v*F?Q52$#1b54^3Uw z1D({bg#;5Fu(3ypO2gTrS-Z{pma2xf&2%sgp%{&-JTwISE6*8^mac8rN_^NSl#+zk z!XP@KGd+t?xV_FQ*}ffg?%w0%F*keUn+~#hh2-*on`KYo7e^W}vCx`rKa&pm{eXDN z17~EPkSq-79^Oa)p}R@{#lTHXirKt^x%w6==}p%Iu@7B( zGqlxzJMCE#>m}Q!Jn`$^5%=^PFkNo{hZ(ffCq4FAI9?5(Ob@;v&3Z^a zVyisst?uPbHwvW}hS;L%SEAI^WB=!SoM4fE_QtukF_0)?Mj9Jub?wqFI$XiN{uK7~ z^GMc%i*J&A{HHN{9;7(=HK#`qQ_`7>hE7?KVDr`CHO$U?NS^rP=%r&6&;A;E`B-`X z3v{>&!&N8m(a4uUN^N^7!7*O1?x&OZwXH}CVBs|*fs`q5@V_}igLVfbr=KT1^$bjZ zhUj2h4H(2jZ0|m4VUcc!&cVH?wM;KuLCRe9fT_qRzd%b6^kB@0AlaZyG2qT5EB>LKHdKi7$}vdlcQd z%-b=mYF&?|;j64)2nt-SsMEECNgDirV`*+d{{6BRrbDOSS9Jz;S>Ks3`cCH4k^353 zl+ocCbo

    + * A formatter specifically for stacked BarChart that allows to specify whether the all stack values + * or just the top value should be drawn. + */ +public class StackedValueFormatter implements ValueFormatter { + + /** + * if true, all stack values of the stacked bar entry are drawn, else only top + */ + private boolean mDrawWholeStack; + + /** + * a string that should be appended behind the value + */ + private String mAppendix; + + private DecimalFormat mFormat; + + /** + * Constructor. + * + * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top + * @param appendix a string that should be appended behind the value + * @param decimals the number of decimal digits to use + */ + public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { + this.mDrawWholeStack = drawWholeStack; + this.mAppendix = appendix; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < decimals; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + } + + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + + if (entry instanceof BarEntry && !mDrawWholeStack) { + + BarEntry barEntry = (BarEntry) entry; + float[] vals = barEntry.getVals(); + + if (vals != null) { + + // find out if we are on top + if (vals[vals.length - 1] == value) { + return mFormat.format(barEntry.getVal()) + mAppendix; + } else { + return ""; + } + } + } + + return mFormat.format(value) + mAppendix; + } +} From 1882d5ac25c4ed14a4040dc27001a1d5381087b6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 28 Jan 2016 14:42:33 +0100 Subject: [PATCH 0706/1390] Performance improvement & documentation of new formatter --- .../charting/formatter/StackedValueFormatter.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 4240832da4..7a8ef0a193 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -50,22 +50,25 @@ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decima @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - if (entry instanceof BarEntry && !mDrawWholeStack) { + if (!mDrawWholeStack && entry instanceof BarEntry) { BarEntry barEntry = (BarEntry) entry; float[] vals = barEntry.getVals(); if (vals != null) { - // find out if we are on top + // find out if we are on top of the stack if (vals[vals.length - 1] == value) { + + // return the "sum" across all stack values return mFormat.format(barEntry.getVal()) + mAppendix; } else { - return ""; + return ""; // return empty } } } + // return the "proposed" value return mFormat.format(value) + mAppendix; } } From 7e35393ec2d093e65321e69df42c2089c558f0d1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 17:36:05 +0200 Subject: [PATCH 0707/1390] Fixed pie text bounds --- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 5d094f01ad..49bc596f51 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -328,7 +328,7 @@ protected void drawCenterText(Canvas c) { RectF boundingRect = mRectBuffer[1]; boundingRect.set(holeRect); - float radiusPercent = mChart.getCenterTextRadiusPercent(); + float radiusPercent = mChart.getCenterTextRadiusPercent() / 100f; if (radiusPercent > 0.0) { boundingRect.inset( (boundingRect.width() - boundingRect.width() * radiusPercent) / 2.f, From 93746fa0174b8231fcbd68504f6d1d4a2ca3844f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 18:03:49 +0200 Subject: [PATCH 0708/1390] Another minor fix for pie center text --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 49bc596f51..cc26c73e18 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -318,7 +318,9 @@ protected void drawCenterText(Canvas c) { PointF center = mChart.getCenterCircleBox(); - float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); + float innerRadius = mChart.isDrawHoleEnabled() + ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) + : mChart.getRadius(); RectF holeRect = mRectBuffer[0]; holeRect.left = center.x - innerRadius; From f19b8e862af655a20ed301b273de80ad501a68c9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 31 Jan 2016 11:25:15 +0100 Subject: [PATCH 0709/1390] Fix #1425 --- .../src/com/github/mikephil/charting/data/BaseDataSet.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 3c151d783f..612f440474 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -208,6 +208,7 @@ public void setColor(int color, int alpha) { * @param alpha */ public void setColors(int[] colors, int alpha) { + resetColors(); for (int color : colors) { addColor(Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color))); } From a6e6fed0faaf6bbffec63d34781a4427c7c041c9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 6 Feb 2016 18:21:46 +0100 Subject: [PATCH 0710/1390] Work on new example with multicolor barchart --- MPChartExample/AndroidManifest.xml | 1 + .../BarChartPositiveNegative.java | 160 ++++++++++++++++++ .../notimportant/MainActivity.java | 8 + 3 files changed, 169 insertions(+) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 906001d44c..8ee59693af 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -61,6 +61,7 @@ + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java new file mode 100644 index 0000000000..b4d6039c68 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -0,0 +1,160 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.ViewPortHandler; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; + +public class BarChartPositiveNegative extends DemoBase { + + protected BarChart mChart; + private Typeface mTf; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart_noseekbar); + + mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + mChart = (BarChart) findViewById(R.id.chart1); + mChart.setExtraTopOffset(-30f); + mChart.setExtraBottomOffset(10f); + + mChart.setDrawBarShadow(false); + mChart.setDrawValueAboveBar(true); + + mChart.setDescription(""); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + mChart.setDrawGridBackground(false); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setTypeface(mTf); + xAxis.setDrawGridLines(false); + xAxis.setDrawAxisLine(false); + xAxis.setSpaceBetweenLabels(2); + xAxis.setTextColor(Color.LTGRAY); + xAxis.setTextSize(12f); + + YAxis left = mChart.getAxisLeft(); + left.setDrawLabels(false); + left.setStartAtZero(false); + left.setSpaceTop(25f); + left.setSpaceBottom(25f); + left.setDrawAxisLine(false); + left.setDrawGridLines(false); + mChart.getAxisRight().setEnabled(false); + mChart.getLegend().setEnabled(false); + + // THIS IS THE ORIGINAL DATA YOU WANT TO PLOT + List data = new ArrayList<>(); + data.add(new Data(0, -224.1f, "12-29")); + data.add(new Data(1, 238.5f, "12-30")); + data.add(new Data(2, 1280.1f, "12-31")); + data.add(new Data(3, -442.3f, "01-01")); + data.add(new Data(4, -2280.1f, "01-02")); + + setData(data); + } + + private void setData(List dataList) { + + ArrayList positiveValues = new ArrayList(); + ArrayList negativeValues = new ArrayList(); + String[] dates = new String[dataList.size()]; + + for (int i = 0; i < dataList.size(); i++) { + + Data d = dataList.get(i); + BarEntry entry = new BarEntry(d.yValue, d.xIndex); + + if (d.yValue >= 0) + positiveValues.add(entry); + else + negativeValues.add(entry); + + dates[i] = dataList.get(i).xAxisValue; + } + + int green = Color.rgb(110, 190, 102); + int red = Color.rgb(211, 74, 88); + + BarDataSet positive = new BarDataSet(positiveValues, "Positive"); + positive.setBarSpacePercent(35f); + positive.setColor(red); + positive.setValueTextColor(red); + + BarDataSet negative = new BarDataSet(negativeValues, "Negative"); + negative.setBarSpacePercent(35f); + negative.setColor(green); + negative.setValueTextColor(green); + + ArrayList dataSets = new ArrayList(); + dataSets.add(positive); + dataSets.add(negative); + + BarData data = new BarData(dates, dataSets); + data.setValueTextSize(12f); + data.setValueTypeface(mTf); + data.setValueFormatter(new ValueFormatter()); + + mChart.setData(data); + mChart.invalidate(); + } + + /** + * Demo class representing data. + */ + private class Data { + + public String xAxisValue; + public float yValue; + public int xIndex; + + public Data(int xIndex, float yValue, String xAxisValue) { + this.xAxisValue = xAxisValue; + this.yValue = yValue; + this.xIndex = xIndex; + } + } + + private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter { + + private DecimalFormat mFormat; + + public ValueFormatter() { + mFormat = new DecimalFormat("######.0"); + } + + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value); + } + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 621d7ae77d..bd6139c63a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -18,6 +18,7 @@ import com.xxmassdeveloper.mpchartexample.BarChartActivity; import com.xxmassdeveloper.mpchartexample.BarChartActivityMultiDataset; import com.xxmassdeveloper.mpchartexample.BarChartActivitySinus; +import com.xxmassdeveloper.mpchartexample.BarChartPositiveNegative; import com.xxmassdeveloper.mpchartexample.BubbleChartActivity; import com.xxmassdeveloper.mpchartexample.CandleStickChartActivity; import com.xxmassdeveloper.mpchartexample.CombinedChartActivity; @@ -123,6 +124,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Chart in ScrollView", "This demonstrates how to use a chart inside a ScrollView.")); + objects.add(new ContentItem( + "BarChart positive / negative", + "This demonstrates how to create a BarChart with positive and negative values in different colors.")); ContentItem realm = new ContentItem( "Realm.io Database", @@ -249,6 +253,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 26: + i = new Intent(this, BarChartPositiveNegative.class); + startActivity(i); + break; + case 27: i = new Intent(this, RealmMainActivity.class); startActivity(i); break; From 9615cc2af130ef9b77ef7fad7d005d2d4ec1e92e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 6 Feb 2016 18:28:28 +0100 Subject: [PATCH 0711/1390] Improve example --- .../BarChartPositiveNegative.java | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index b4d6039c68..97d4485b3e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -7,9 +7,6 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -17,8 +14,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -42,6 +37,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setExtraTopOffset(-30f); mChart.setExtraBottomOffset(10f); + mChart.setExtraLeftOffset(70f); + mChart.setExtraRightOffset(70f); mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); @@ -60,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setSpaceBetweenLabels(2); xAxis.setTextColor(Color.LTGRAY); - xAxis.setTextSize(12f); + xAxis.setTextSize(13f); YAxis left = mChart.getAxisLeft(); left.setDrawLabels(false); @@ -85,42 +82,35 @@ protected void onCreate(Bundle savedInstanceState) { private void setData(List dataList) { - ArrayList positiveValues = new ArrayList(); - ArrayList negativeValues = new ArrayList(); + ArrayList values = new ArrayList(); String[] dates = new String[dataList.size()]; + List colors = new ArrayList(); + + int green = Color.rgb(110, 190, 102); + int red = Color.rgb(211, 74, 88); for (int i = 0; i < dataList.size(); i++) { Data d = dataList.get(i); BarEntry entry = new BarEntry(d.yValue, d.xIndex); + values.add(entry); + dates[i] = dataList.get(i).xAxisValue; + + // specific colors if (d.yValue >= 0) - positiveValues.add(entry); + colors.add(red); else - negativeValues.add(entry); - - dates[i] = dataList.get(i).xAxisValue; + colors.add(green); } - int green = Color.rgb(110, 190, 102); - int red = Color.rgb(211, 74, 88); - - BarDataSet positive = new BarDataSet(positiveValues, "Positive"); - positive.setBarSpacePercent(35f); - positive.setColor(red); - positive.setValueTextColor(red); - - BarDataSet negative = new BarDataSet(negativeValues, "Negative"); - negative.setBarSpacePercent(35f); - negative.setColor(green); - negative.setValueTextColor(green); - - ArrayList dataSets = new ArrayList(); - dataSets.add(positive); - dataSets.add(negative); + BarDataSet set = new BarDataSet(values, "Values"); + set.setBarSpacePercent(40f); + set.setColors(colors); + set.setValueTextColor(red); - BarData data = new BarData(dates, dataSets); - data.setValueTextSize(12f); + BarData data = new BarData(dates, set); + data.setValueTextSize(13f); data.setValueTypeface(mTf); data.setValueFormatter(new ValueFormatter()); From 31de4f2a2905ba4f9a211095799e3fa65376778d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 6 Feb 2016 18:44:23 +0100 Subject: [PATCH 0712/1390] Add feature to allow setting different colors for values (#1389, ...) --- .../BarChartPositiveNegative.java | 2 +- .../mikephil/charting/data/BaseDataSet.java | 24 ++++++++++++------- .../interfaces/datasets/IDataSet.java | 13 ++++++++-- .../charting/renderer/BarChartRenderer.java | 8 ++++--- .../renderer/BubbleChartRenderer.java | 14 +++++------ .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/DataRenderer.java | 7 +++--- .../charting/renderer/LineChartRenderer.java | 2 +- .../charting/renderer/PieChartRenderer.java | 4 ++-- .../charting/renderer/RadarChartRenderer.java | 2 +- .../renderer/ScatterChartRenderer.java | 2 +- 11 files changed, 49 insertions(+), 31 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 97d4485b3e..eb251c2126 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -107,7 +107,7 @@ private void setData(List dataList) { BarDataSet set = new BarDataSet(values, "Values"); set.setBarSpacePercent(40f); set.setColors(colors); - set.setValueTextColor(red); + set.setValueTextColors(colors); BarData data = new BarData(dates, set); data.setValueTextSize(13f); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 612f440474..51cbd7ba9d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -26,6 +26,11 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; + /** + * List representing all colors that are used for drawing the actual values for this DataSet + */ + protected List mValueColors = null; + /** * label that describes the DataSet or the data the DataSet represents */ @@ -46,11 +51,6 @@ public abstract class BaseDataSet implements IDataSet { */ protected transient ValueFormatter mValueFormatter; - /** - * the color used for the value-text - */ - protected int mValueColor = Color.BLACK; - /** * the typeface used for the value text */ @@ -76,9 +76,11 @@ public abstract class BaseDataSet implements IDataSet { */ public BaseDataSet() { mColors = new ArrayList(); + mValueColors = new ArrayList(); // default color mColors.add(Color.rgb(140, 234, 255)); + mValueColors.add(Color.BLACK); } /** @@ -261,7 +263,13 @@ public ValueFormatter getValueFormatter() { @Override public void setValueTextColor(int color) { - mValueColor = color; + mValueColors.clear(); + mValueColors.add(color); + } + + @Override + public void setValueTextColors(List colors) { + mValueColors = colors; } @Override @@ -275,8 +283,8 @@ public void setValueTextSize(float size) { } @Override - public int getValueTextColor() { - return mValueColor; + public int getValueTextColor(int index) { + return mValueColors.get(index % mValueColors.size()); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index d92bb174e9..251270d577 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -288,6 +288,13 @@ public interface IDataSet { */ void setValueTextColor(int color); + /** + * Sets a list of colors to be used as the colors for the drawn values. + * + * @param colors + */ + void setValueTextColors(List colors); + /** * Sets a Typeface for the value-labels of this DataSet. * @@ -303,11 +310,13 @@ public interface IDataSet { void setValueTextSize(float size); /** - * Returns the color that is used for drawing the values inside the chart + * Returns the color at the specified index that is used for drawing the values inside the chart. + * Uses modulus internally. * + * @param index * @return */ - int getValueTextColor(); + int getValueTextColor(int index); /** * Returns the typeface that is used for drawing the values inside the chart diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index d4ae8eb422..763fb87986 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -223,7 +223,7 @@ public void drawValues(Canvas c) { float val = entry.getVal(); drawValue(c, dataSet.getValueFormatter(), val, entry, i, valuePoints[j], - valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset)); + valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset), dataSet.getValueTextColor(j / 2)); } // if we have stacks @@ -248,11 +248,13 @@ public void drawValues(Canvas c) { continue; drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, valuePoints[j], - valuePoints[j + 1] + (entry.getVal() >= 0 ? posOffset : negOffset)); + valuePoints[j + 1] + (entry.getVal() >= 0 ? posOffset : negOffset), dataSet.getValueTextColor(j / 2)); // draw stack values } else { + int color = dataSet.getValueTextColor(j / 2); + float[] transformed = new float[vals.length * 2]; float posY = 0f; @@ -289,7 +291,7 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(x)) continue; - drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y); + drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y, color); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 509fd337f4..754fc38be8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -141,13 +141,6 @@ public void drawValues(Canvas c) { final float phaseX = mAnimator.getPhaseX(); final float phaseY = mAnimator.getPhaseY(); - final float alpha = phaseX == 1 ? phaseY : phaseX; - int valueTextColor = dataSet.getValueTextColor(); - valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), - Color.green(valueTextColor), Color.blue(valueTextColor)); - - mValuePaint.setColor(valueTextColor); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); @@ -159,6 +152,11 @@ public void drawValues(Canvas c) { for (int j = 0; j < positions.length; j += 2) { + final float alpha = phaseX == 1 ? phaseY : phaseX; + int valueTextColor = dataSet.getValueTextColor(j / 2); + valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), + Color.green(valueTextColor), Color.blue(valueTextColor)); + float x = positions[j]; float y = positions[j + 1]; @@ -171,7 +169,7 @@ public void drawValues(Canvas c) { BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, - y + (0.5f * lineHeight)); + y + (0.5f * lineHeight), valueTextColor); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 2b4838365c..86000f67de 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -217,7 +217,7 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); - drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset); + drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet.getValueTextColor(j / 2)); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index ec963ddccd..f4a88fe08d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -9,10 +9,10 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -102,7 +102,6 @@ public Paint getPaintRender() { */ protected void applyValueTextStyle(IDataSet set) { - mValuePaint.setColor(set.getValueTextColor()); mValuePaint.setTypeface(set.getValueTypeface()); mValuePaint.setTextSize(set.getValueTextSize()); } @@ -138,8 +137,10 @@ protected void applyValueTextStyle(IDataSet set) { * @param dataSetIndex the index of the DataSet the drawn Entry belongs to * @param x position * @param y position + * @param color */ - public void drawValue(Canvas c, ValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y) { + public void drawValue(Canvas c, ValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { + mValuePaint.setColor(color); c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 7708cfdd93..30511c8f19 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -461,7 +461,7 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + minx); drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, x, - y - valOffset); + y - valOffset, dataSet.getValueTextColor(j / 2)); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index cc26c73e18..d9b9200410 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -244,7 +244,7 @@ public void drawValues(Canvas c) { // draw everything, depending on settings if (drawXVals && drawYVals) { - drawValue(c, formatter, value, entry, 0, x, y); + drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); if (j < data.getXValCount()) c.drawText(data.getXVals().get(j), x, y + lineHeight, @@ -255,7 +255,7 @@ public void drawValues(Canvas c) { c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); } else if (drawYVals) { - drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f); + drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); } xIndex++; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index f9fde8a72a..32f3481f71 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -162,7 +162,7 @@ public void drawValues(Canvas c) { (entry.getVal() - mChart.getYChartMin()) * factor * phaseY, sliceangle * j * phaseX + mChart.getRotationAngle()); - drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, p.x, p.y - yoffset); + drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, p.x, p.y - yoffset, dataSet.getValueTextColor(j)); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 2d9e051a01..63ba8252f1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -232,7 +232,7 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2); drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, positions[j], - positions[j + 1] - shapeSize); + positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2)); } } } From ce84fe270bdfae9b4321a92532653522826f8bc2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 9 Feb 2016 11:06:24 +0100 Subject: [PATCH 0713/1390] Fixes for last commit --- .../mikephil/charting/data/BaseDataSet.java | 5 +++++ .../github/mikephil/charting/data/ChartData.java | 16 ++++++++++++++-- .../charting/interfaces/datasets/IDataSet.java | 7 +++++++ .../charting/renderer/BubbleChartRenderer.java | 6 +++--- .../charting/renderer/PieChartRenderer.java | 7 +++++-- 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 51cbd7ba9d..a318c1d3ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -282,6 +282,11 @@ public void setValueTextSize(float size) { mValueTextSize = Utils.convertDpToPixel(size); } + @Override + public int getValueTextColor() { + return mValueColors.get(0); + } + @Override public int getValueTextColor(int index) { return mValueColors.get(index % mValueColors.size()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index b33f02d641..e9d5ad25d6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -158,7 +158,7 @@ private void calcXValMaximumLength() { int length = mXVals.get(i).length(); - if(length > max) + if (length > max) max = length; } @@ -382,7 +382,7 @@ public List getXVals() { */ public void addXValue(String xVal) { - if(xVal != null && xVal.length() > mXValMaximumLength) + if (xVal != null && xVal.length() > mXValMaximumLength) mXValMaximumLength = xVal.length(); mXVals.add(xVal); @@ -858,6 +858,18 @@ public void setValueTextColor(int color) { } } + /** + * Sets the same list of value-colors for all DataSets this + * data object contains. + * + * @param colors + */ + public void setValueTextColors(List colors) { + for (IDataSet set : mDataSets) { + set.setValueTextColors(colors); + } + } + /** * Sets the Typeface for all value-labels for all DataSets this data object * contains. diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 251270d577..38ea9484c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -309,6 +309,13 @@ public interface IDataSet { */ void setValueTextSize(float size); + /** + * Returns only the first color of all colors that are set to be used for the values. + * + * @return + */ + int getValueTextColor(); + /** * Returns the color at the specified index that is used for drawing the values inside the chart. * Uses modulus internally. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 754fc38be8..45329aae9f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -150,10 +150,11 @@ public void drawValues(Canvas c) { final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesBubble(dataSet, phaseX, phaseY, minx, maxx); + final float alpha = phaseX == 1 ? phaseY : phaseX; + for (int j = 0; j < positions.length; j += 2) { - final float alpha = phaseX == 1 ? phaseY : phaseX; - int valueTextColor = dataSet.getValueTextColor(j / 2); + int valueTextColor = dataSet.getValueTextColor(j / 2 + minx); valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), Color.green(valueTextColor), Color.blue(valueTextColor)); @@ -173,7 +174,6 @@ public void drawValues(Canvas c) { } } } - } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index d9b9200410..689052b24b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -246,13 +246,16 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); - if (j < data.getXValCount()) + if (j < data.getXValCount()) { c.drawText(data.getXVals().get(j), x, y + lineHeight, mValuePaint); + } } else if (drawXVals) { - if (j < data.getXValCount()) + if (j < data.getXValCount()) { + mValuePaint.setColor(dataSet.getValueTextColor(j)); c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); + } } else if (drawYVals) { drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); From 9c546bcfa959e1077a0b3047efc2c0b9d19ae475 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Feb 2016 21:48:14 +0200 Subject: [PATCH 0714/1390] Percentages on MPAndroidCharts are 0-100 --- .../src/com/github/mikephil/charting/charts/PieChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 9f7255eb6e..efe8cabc35 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -84,7 +84,7 @@ public class PieChart extends PieRadarChartBase { */ private boolean mDrawCenterText = true; - private float mCenterTextRadiusPercent = 1.f; + private float mCenterTextRadiusPercent = 100.f; protected float mMaxAngle = 360f; From b73e3d0af2b641aaecd6b6a538430e1e7af78cd4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Feb 2016 21:48:23 +0200 Subject: [PATCH 0715/1390] Cleaned up this residue --- .../charting/renderer/PieChartRenderer.java | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 689052b24b..fbdace8587 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -366,45 +366,6 @@ protected void drawCenterText(Canvas c) { c.translate(boundingRect.left, boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); mCenterTextLayout.draw(c); c.restore(); - -// } -// -// else { -// -// -// // get all lines from the text -// String[] lines = centerText.toString().split("\n"); -// -// float maxlineheight = 0f; -// -// // calc the maximum line height -// for (String line : lines) { -// float curHeight = Utils.calcTextHeight(mCenterTextPaint, line); -// if (curHeight > maxlineheight) -// maxlineheight = curHeight; -// } -// -// float linespacing = maxlineheight * 0.25f; -// -// float totalheight = maxlineheight * lines.length - linespacing * (lines.length - 1); -// -// int cnt = lines.length; -// -// float y = center.y; -// -// for (int i = 0; i < lines.length; i++) { -// -// String line = lines[lines.length - i - 1]; -// -// -// -// c.drawText(line, center.x, y -// + maxlineheight * cnt - totalheight / 2f, -// mCenterTextPaint); -// cnt--; -// y -= linespacing; -// } -// } } } From c3b8b1161ad719cb7ce5ecb43cec6022db30ddf1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Feb 2016 21:55:33 +0200 Subject: [PATCH 0716/1390] Clipping to path on Hardware layer available since API 18 --- .../mikephil/charting/renderer/PieChartRenderer.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index fbdace8587..3f35ea542e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -7,8 +7,10 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; +import android.graphics.Path; import android.graphics.PointF; import android.graphics.RectF; +import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -356,15 +358,19 @@ protected void drawCenterText(Canvas c) { Layout.Alignment.ALIGN_CENTER, 1.f, 0.f, false); } - // I wish we could make an ellipse clipping path on Android to clip to the hole... - // If we ever find out how, this is the place to add it, based on holeRect - //float layoutWidth = Utils.getStaticLayoutMaxWidth(mCenterTextLayout); float layoutHeight = mCenterTextLayout.getHeight(); c.save(); + if (Build.VERSION.SDK_INT >= 18) { + Path path = new Path(); + path.addOval(holeRect, Path.Direction.CW); + c.clipPath(path); + } + c.translate(boundingRect.left, boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); mCenterTextLayout.draw(c); + c.restore(); } } From 2c62ac87f0ad6cdcce1eab1cb628270a6bc097ba Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Feb 2016 22:39:01 +0200 Subject: [PATCH 0717/1390] Center the "no data text" vertically --- .../mikephil/charting/charts/Chart.java | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index cde8f605ee..e795d24bb5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -415,13 +415,29 @@ protected void onDraw(Canvas canvas) { if (mData == null) { + boolean hasText = !TextUtils.isEmpty(mNoDataText); + boolean hasDescription = !TextUtils.isEmpty(mNoDataTextDescription); + float line1height = hasText ? Utils.calcTextHeight(mInfoPaint, mNoDataText) : 0.f; + float line2height = hasDescription ? Utils.calcTextHeight(mInfoPaint, mNoDataTextDescription) : 0.f; + float lineSpacing = (hasText && hasDescription) ? + (mInfoPaint.getFontSpacing() - line1height) : 0.f; + // if no data, inform the user - canvas.drawText(mNoDataText, getWidth() / 2, getHeight() / 2, mInfoPaint); - if (!TextUtils.isEmpty(mNoDataTextDescription)) { - float textOffset = -mInfoPaint.ascent() + mInfoPaint.descent(); - canvas.drawText(mNoDataTextDescription, getWidth() / 2, (getHeight() / 2) - + textOffset, mInfoPaint); + float y = (getHeight() - + (line1height + lineSpacing + line2height)) / 2.f + + line1height; + + if (hasText) { + canvas.drawText(mNoDataText, getWidth() / 2, y, mInfoPaint); + + if (hasDescription) { + y = y + line1height + lineSpacing; + } + } + + if (hasDescription) { + canvas.drawText(mNoDataTextDescription, getWidth() / 2, y, mInfoPaint); } return; } From ccada2d3f1eb7f0e12396ac088625a33b3accf35 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Feb 2016 01:38:20 +0200 Subject: [PATCH 0718/1390] Support for holes in Scatter shapes --- .../charting/data/ScatterDataSet.java | 46 ++++++- .../implementation/RealmScatterDataSet.java | 41 ++++++ .../interfaces/datasets/IScatterDataSet.java | 14 ++ .../renderer/ScatterChartRenderer.java | 120 ++++++++++++++++-- 4 files changed, 206 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 686c5e9639..22f5d54aa4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -1,10 +1,9 @@ package com.github.mikephil.charting.data; -import android.graphics.Path; - import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -23,6 +22,19 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme */ private ScatterShape mScatterShape = ScatterShape.SQUARE; + /** + * The radius of the hole in the shape (applies to Square, Circle and Triangle) + * - default: 0.0 + */ + private float mScatterShapeHoleRadius = 0f; + + /** + * Color for the hole in the shape. + * Setting to `ColorTemplate.COLOR_NONE` will behave as transparent. + * - default: ColorTemplate.COLOR_NONE + */ + private int mScatterShapeHoleColor = ColorTemplate.COLOR_NONE; + /** * Custom path object the user can provide that is drawn where the values * are at. This is used when ScatterShape.CUSTOM is set for a DataSet. @@ -47,6 +59,8 @@ public DataSet copy() { copied.mColors = mColors; copied.mShapeSize = mShapeSize; copied.mScatterShape = mScatterShape; + copied.mScatterShapeHoleRadius = mScatterShapeHoleRadius; + copied.mScatterShapeHoleColor = mScatterShapeHoleColor; //copied.mCustomScatterPath = mCustomScatterPath; copied.mHighLightColor = mHighLightColor; @@ -82,6 +96,34 @@ public ScatterShape getScatterShape() { return mScatterShape; } + /** + * Sets the radius of the hole in the shape + * + * @param holeRadius + */ + public void setScatterShapeHoleRadius(float holeRadius) { + mScatterShapeHoleRadius = Utils.convertDpToPixel(holeRadius); + } + + @Override + public float getScatterShapeHoleRadius() { + return mScatterShapeHoleRadius; + } + + /** + * Sets the color for the hole in the shape + * + * @param holeColor + */ + public void setScatterShapeHoleColor(int holeColor) { + mScatterShapeHoleColor = holeColor; + } + + @Override + public int getScatterShapeHoleColor() { + return mScatterShapeHoleColor; + } + // /** // * Sets a path object as the shape to be drawn where the values are at. Do // * not forget to call setScatterShape(...) and set the shape to diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 1991b59926..053355aa38 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import io.realm.DynamicRealmObject; @@ -26,6 +27,18 @@ public class RealmScatterDataSet extends RealmLineScatter */ private ScatterChart.ScatterShape mScatterShape = ScatterChart.ScatterShape.SQUARE; + /** + * The radius of the hole in the shape (applies to Square, Circle and Triangle) + * - default: 0.0 + */ + private float mScatterShapeHoleRadius = 0f; + + /** + * Color for the hole in the shape. + * Setting to `ColorTemplate.COLOR_NONE` will behave as transparent. + * - default: ColorTemplate.COLOR_NONE + */ + private int mScatterShapeHoleColor = ColorTemplate.COLOR_NONE; /** * Constructor for creating a ScatterDataSet with realm data. @@ -108,4 +121,32 @@ public void setScatterShape(ScatterChart.ScatterShape shape) { public ScatterChart.ScatterShape getScatterShape() { return mScatterShape; } + + /** + * Sets the radius of the hole in the shape + * + * @param holeRadius + */ + public void setScatterShapeHoleRadius(float holeRadius) { + mScatterShapeHoleRadius = Utils.convertDpToPixel(holeRadius); + } + + @Override + public float getScatterShapeHoleRadius() { + return mScatterShapeHoleRadius; + } + + /** + * Sets the color for the hole in the shape + * + * @param holeColor + */ + public void setScatterShapeHoleColor(int holeColor) { + mScatterShapeHoleColor = holeColor; + } + + @Override + public int getScatterShapeHoleColor() { + return mScatterShapeHoleColor; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java index e1d9904919..d3a6d3400d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java @@ -21,4 +21,18 @@ public interface IScatterDataSet extends ILineScatterCandleRadarDataSet { * @return */ ScatterChart.ScatterShape getScatterShape(); + + /** + * Returns radius of the hole in the shape + * + * @return + */ + float getScatterShapeHoleRadius(); + + /** + * Returns the color for the hole in the shape + * + * @return + */ + int getScatterShapeHoleColor(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 63ba8252f1..a8ee1ebf0f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -29,8 +30,6 @@ public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; - - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); } @Override @@ -65,7 +64,13 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - float shapeHalf = dataSet.getScatterShapeSize() / 2f; + final float shapeSize = dataSet.getScatterShapeSize(); + final float shapeHalf = shapeSize / 2f; + final float shapeHoleSizeHalf = dataSet.getScatterShapeHoleRadius(); + final float shapeHoleSize = shapeHoleSizeHalf * 2.f; + final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); + final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; + final float shapeStrokeSizeHalf = shapeStrokeSize / 2.f; ScatterShape shape = dataSet.getScatterShape(); @@ -79,8 +84,6 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { switch (shape) { case SQUARE: - mRenderPaint.setStyle(Style.FILL); - for (int i = 0; i < buffer.size(); i += 2) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) @@ -91,15 +94,42 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); - c.drawRect(buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] - + shapeHalf, buffer.buffer[i + 1] - + shapeHalf, mRenderPaint); + + if (shapeHoleSize > 0.0) { + mRenderPaint.setStyle(Style.STROKE); + mRenderPaint.setStrokeWidth(shapeStrokeSize); + + c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf - shapeStrokeSizeHalf, + buffer.buffer[i + 1] - shapeHoleSizeHalf - shapeStrokeSizeHalf, + buffer.buffer[i] + shapeHoleSizeHalf + shapeStrokeSizeHalf, + buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, + mRenderPaint); + + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + mRenderPaint.setStyle(Style.FILL); + + mRenderPaint.setColor(shapeHoleColor); + c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf, + buffer.buffer[i + 1] - shapeHoleSizeHalf, + buffer.buffer[i] + shapeHoleSizeHalf, + buffer.buffer[i + 1] + shapeHoleSizeHalf, + mRenderPaint); + } + + } else { + mRenderPaint.setStyle(Style.FILL); + + c.drawRect(buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + } } + break; - case CIRCLE: - mRenderPaint.setStyle(Style.FILL); + case CIRCLE: for (int i = 0; i < buffer.size(); i += 2) { @@ -111,10 +141,39 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); - c.drawCircle(buffer.buffer[i], buffer.buffer[i + 1], shapeHalf, - mRenderPaint); + + if (shapeHoleSize > 0.0) { + mRenderPaint.setStyle(Style.STROKE); + mRenderPaint.setStrokeWidth(shapeStrokeSize); + + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHoleSizeHalf + shapeStrokeSizeHalf, + mRenderPaint); + + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + mRenderPaint.setStyle(Style.FILL); + + mRenderPaint.setColor(shapeHoleColor); + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHoleSizeHalf, + mRenderPaint); + } + } else { + mRenderPaint.setStyle(Style.FILL); + + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHalf, + mRenderPaint); + } } break; + case TRIANGLE: mRenderPaint.setStyle(Style.FILL); @@ -132,18 +191,52 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { continue; mRenderPaint.setColor(dataSet.getColor(i / 2)); + tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); + + if (shapeHoleSize > 0.0) { + tri.lineTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); + + tri.moveTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); + tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + } + tri.close(); c.drawPath(tri, mRenderPaint); tri.reset(); + + if (shapeHoleSize > 0.0 && + shapeHoleColor != ColorTemplate.COLOR_NONE) { + + mRenderPaint.setColor(shapeHoleColor); + + tri.moveTo(buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); + tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.close(); + + c.drawPath(tri, mRenderPaint); + tri.reset(); + } } break; + case CROSS: mRenderPaint.setStyle(Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); for (int i = 0; i < buffer.size(); i += 2) { @@ -164,6 +257,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { + shapeHalf, mRenderPaint); } break; + default: break; } From 3592adf52253e696d783db2469fc2f5cc3c43ffb Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Feb 2016 01:45:13 +0200 Subject: [PATCH 0719/1390] New X shape for Scatter --- .../charting/charts/ScatterChart.java | 6 +-- .../renderer/ScatterChartRenderer.java | 47 +++++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 773d280fae..76a10cb894 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -18,12 +18,10 @@ public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { /** - * enum that defines the shape that is drawn where the values are, CIRCLE - * and SCQUARE offer the best performance, TRIANGLE has the worst - * performance. + * enum that defines the shape that is drawn where the values are */ public enum ScatterShape { - CROSS, TRIANGLE, CIRCLE, SQUARE + SQUARE, CIRCLE, TRIANGLE, CROSS, X, } public ScatterChart(Context context) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index a8ee1ebf0f..37ad728216 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -249,12 +249,49 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(i / 2)); - c.drawLine(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1], + c.drawLine( + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1], buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1], mRenderPaint); - c.drawLine(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i], buffer.buffer[i + 1] - + shapeHalf, mRenderPaint); + buffer.buffer[i + 1], + mRenderPaint); + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i], + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + } + break; + + case X: + + mRenderPaint.setStyle(Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + c.drawLine( + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + c.drawLine( + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); } break; From 54dc87cf5510189acf1d0e311a3ecb54bc45ecb6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Feb 2016 01:50:15 +0200 Subject: [PATCH 0720/1390] On the fly conversion of dp - to avoid confusion --- .../com/github/mikephil/charting/data/ScatterDataSet.java | 8 +++----- .../data/realm/implementation/RealmScatterDataSet.java | 8 ++++---- .../mikephil/charting/renderer/ScatterChartRenderer.java | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 22f5d54aa4..89efe063d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -12,7 +12,7 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet implements IScatterDataSet { /** - * the size the scattershape will have, in screen pixels + * the size the scattershape will have, in density pixels */ private float mShapeSize = 15f; @@ -42,8 +42,6 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme //private Path mCustomScatterPath = null; public ScatterDataSet(List yVals, String label) { super(yVals, label); - - // mShapeSize = Utils.convertDpToPixel(8f); } @Override @@ -74,7 +72,7 @@ public DataSet copy() { * @param size */ public void setScatterShapeSize(float size) { - mShapeSize = Utils.convertDpToPixel(size); + mShapeSize = size; } @Override @@ -102,7 +100,7 @@ public ScatterShape getScatterShape() { * @param holeRadius */ public void setScatterShapeHoleRadius(float holeRadius) { - mScatterShapeHoleRadius = Utils.convertDpToPixel(holeRadius); + mScatterShapeHoleRadius = holeRadius; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 053355aa38..c895bc09ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -17,9 +17,9 @@ public class RealmScatterDataSet extends RealmLineScatterCandleRadarDataSet implements IScatterDataSet { /** - * the size the scattershape will have, in screen pixels + * the size the scattershape will have, in density pixels */ - private float mShapeSize = 15f; + private float mShapeSize = 10f; /** * the type of shape that is set to be drawn where the values are at, @@ -98,7 +98,7 @@ public void build(RealmResults results) { * @param size */ public void setScatterShapeSize(float size) { - mShapeSize = Utils.convertDpToPixel(size); + mShapeSize = size; } @Override @@ -128,7 +128,7 @@ public ScatterChart.ScatterShape getScatterShape() { * @param holeRadius */ public void setScatterShapeHoleRadius(float holeRadius) { - mScatterShapeHoleRadius = Utils.convertDpToPixel(holeRadius); + mScatterShapeHoleRadius = holeRadius; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 37ad728216..37a1672ac6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -64,9 +64,9 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - final float shapeSize = dataSet.getScatterShapeSize(); + final float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); final float shapeHalf = shapeSize / 2f; - final float shapeHoleSizeHalf = dataSet.getScatterShapeHoleRadius(); + final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); final float shapeHoleSize = shapeHoleSizeHalf * 2.f; final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; @@ -348,7 +348,7 @@ public void drawValues(Canvas c) { .generateTransformedValuesScatter(dataSet, mAnimator.getPhaseY()); - float shapeSize = dataSet.getScatterShapeSize(); + float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { From 28775755ef56cb53fbdf1eebf732e596935da9f5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 10 Feb 2016 11:09:35 +0100 Subject: [PATCH 0721/1390] Introducing zero line which can be drawn regardless of grid lines --- .../BarChartPositiveNegative.java | 1 + .../StackedBarActivityNegative.java | 2 + .../charting/components/AxisBase.java | 184 ++++++++++-------- .../mikephil/charting/components/YAxis.java | 19 ++ .../charting/renderer/YAxisRenderer.java | 62 ++++-- .../YAxisRendererHorizontalBarChart.java | 56 +++--- 6 files changed, 202 insertions(+), 122 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index eb251c2126..b858541931 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -66,6 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { left.setSpaceBottom(25f); left.setDrawAxisLine(false); left.setDrawGridLines(false); + left.setDrawZeroLine(true); // draw a zero line mChart.getAxisRight().setEnabled(false); mChart.getLegend().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 17625a8ede..dce0c27852 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -62,6 +62,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisRight().setStartAtZero(false); mChart.getAxisRight().setAxisMaxValue(25f); mChart.getAxisRight().setAxisMinValue(-25f); + mChart.getAxisRight().setDrawGridLines(false); + mChart.getAxisRight().setDrawZeroLine(true); mChart.getAxisRight().setLabelCount(7, false); mChart.getAxisRight().setValueFormatter(new CustomFormatter()); mChart.getAxisRight().setTextSize(9f); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index f9eb05d2ec..26f26b361f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -12,12 +12,12 @@ /** * Baseclass of all labels. - * + * * @author Philipp Jahoda */ public abstract class AxisBase extends ComponentBase { - private int mGridColor = Color.GRAY; + private int mGridColor = Color.GRAY; private float mGridLineWidth = 1f; @@ -25,35 +25,49 @@ public abstract class AxisBase extends ComponentBase { private float mAxisLineWidth = 1f; - /** flag indicating if the grid lines for this axis should be drawn */ + /** + * flag indicating if the grid lines for this axis should be drawn + */ protected boolean mDrawGridLines = true; - /** flag that indicates if the line alongside the axis is drawn or not */ + /** + * flag that indicates if the line alongside the axis is drawn or not + */ protected boolean mDrawAxisLine = true; - /** flag that indicates of the labels of this axis should be drawn or not */ + /** + * flag that indicates of the labels of this axis should be drawn or not + */ protected boolean mDrawLabels = true; - /** the path effect of the grid lines that makes dashed lines possible */ + /** + * the path effect of the grid lines that makes dashed lines possible + */ private DashPathEffect mGridDashPathEffect = null; - /** array of limit lines that can be set for the axis */ - protected List mLimitLines; + /** + * array of limit lines that can be set for the axis + */ + protected List mLimitLines; - /** flag indicating the limit lines layer depth */ - protected boolean mDrawLimitLineBehindData = false; + /** + * flag indicating the limit lines layer depth + */ + protected boolean mDrawLimitLineBehindData = false; - /** default constructor */ + /** + * default constructor + */ public AxisBase() { this.mTextSize = Utils.convertDpToPixel(10f); this.mXOffset = Utils.convertDpToPixel(5f); this.mYOffset = Utils.convertDpToPixel(5f); - this.mLimitLines = new ArrayList(); - } + this.mLimitLines = new ArrayList(); + } /** * Set this to true to enable drawing the grid lines for this axis. - * + * * @param enabled */ public void setDrawGridLines(boolean enabled) { @@ -62,7 +76,7 @@ public void setDrawGridLines(boolean enabled) { /** * Returns true if drawing grid lines is enabled for this axis. - * + * * @return */ public boolean isDrawGridLinesEnabled() { @@ -71,7 +85,7 @@ public boolean isDrawGridLinesEnabled() { /** * Set this to true if the line alongside the axis should be drawn or not. - * + * * @param enabled */ public void setDrawAxisLine(boolean enabled) { @@ -80,7 +94,7 @@ public void setDrawAxisLine(boolean enabled) { /** * Returns true if the line alongside the axis should be drawn. - * + * * @return */ public boolean isDrawAxisLineEnabled() { @@ -90,7 +104,7 @@ public boolean isDrawAxisLineEnabled() { /** * Sets the color of the grid lines for this axis (the horizontal lines * coming from each label). - * + * * @param color */ public void setGridColor(int color) { @@ -100,7 +114,7 @@ public void setGridColor(int color) { /** * Returns the color of the grid lines for this axis (the horizontal lines * coming from each label). - * + * * @return */ public int getGridColor() { @@ -109,7 +123,7 @@ public int getGridColor() { /** * Sets the width of the border surrounding the chart in dp. - * + * * @param width */ public void setAxisLineWidth(float width) { @@ -118,7 +132,7 @@ public void setAxisLineWidth(float width) { /** * Returns the width of the axis line (line alongside the axis). - * + * * @return */ public float getAxisLineWidth() { @@ -128,7 +142,7 @@ public float getAxisLineWidth() { /** * Sets the width of the grid lines that are drawn away from each axis * label. - * + * * @param width */ public void setGridLineWidth(float width) { @@ -138,7 +152,7 @@ public void setGridLineWidth(float width) { /** * Returns the width of the grid lines that are drawn away from each axis * label. - * + * * @return */ public float getGridLineWidth() { @@ -147,7 +161,7 @@ public float getGridLineWidth() { /** * Sets the color of the border surrounding the chart. - * + * * @param color */ public void setAxisLineColor(int color) { @@ -156,7 +170,7 @@ public void setAxisLineColor(int color) { /** * Returns the color of the axis line (line alongside the axis). - * + * * @return */ public int getAxisLineColor() { @@ -166,7 +180,7 @@ public int getAxisLineColor() { /** * Set this to true to enable drawing the labels of this axis (this will not * affect drawing the grid lines or axis lines). - * + * * @param enabled */ public void setDrawLabels(boolean enabled) { @@ -175,70 +189,70 @@ public void setDrawLabels(boolean enabled) { /** * Returns true if drawing the labels is enabled for this axis. - * + * * @return */ public boolean isDrawLabelsEnabled() { return mDrawLabels; } - /** - * Adds a new LimitLine to this axis. - * - * @param l - */ - public void addLimitLine(LimitLine l) { - mLimitLines.add(l); - - if (mLimitLines.size() > 6) { - Log.e("MPAndroiChart", - "Warning! You have more than 6 LimitLines on your axis, do you really want that?"); - } - } - - /** - * Removes the specified LimitLine from the axis. - * - * @param l - */ - public void removeLimitLine(LimitLine l) { - mLimitLines.remove(l); - } - - /** - * Removes all LimitLines from the axis. - */ - public void removeAllLimitLines() { - mLimitLines.clear(); - } - - /** - * Returns the LimitLines of this axis. - * - * @return - */ - public List getLimitLines() { - return mLimitLines; - } - - /** - * If this is set to true, the LimitLines are drawn behind the actual data, - * otherwise on top. Default: false - * - * @param enabled - */ - public void setDrawLimitLinesBehindData(boolean enabled) { - mDrawLimitLineBehindData = enabled; - } - - public boolean isDrawLimitLinesBehindDataEnabled() { - return mDrawLimitLineBehindData; - } - - /** + /** + * Adds a new LimitLine to this axis. + * + * @param l + */ + public void addLimitLine(LimitLine l) { + mLimitLines.add(l); + + if (mLimitLines.size() > 6) { + Log.e("MPAndroiChart", + "Warning! You have more than 6 LimitLines on your axis, do you really want that?"); + } + } + + /** + * Removes the specified LimitLine from the axis. + * + * @param l + */ + public void removeLimitLine(LimitLine l) { + mLimitLines.remove(l); + } + + /** + * Removes all LimitLines from the axis. + */ + public void removeAllLimitLines() { + mLimitLines.clear(); + } + + /** + * Returns the LimitLines of this axis. + * + * @return + */ + public List getLimitLines() { + return mLimitLines; + } + + /** + * If this is set to true, the LimitLines are drawn behind the actual data, + * otherwise on top. Default: false + * + * @param enabled + */ + public void setDrawLimitLinesBehindData(boolean enabled) { + mDrawLimitLineBehindData = enabled; + } + + public boolean isDrawLimitLinesBehindDataEnabled() { + return mDrawLimitLineBehindData; + } + + /** * Returns the longest formatted label (in terms of characters), this axis * contains. - * + * * @return */ public abstract String getLongestLabel(); @@ -248,12 +262,12 @@ public boolean isDrawLimitLinesBehindDataEnabled() { * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. * Keep in mind that hardware acceleration boosts performance. * - * @param lineLength the length of the line pieces + * @param lineLength the length of the line pieces * @param spaceLength the length of space in between the pieces - * @param phase offset, in degrees (normally, use 0) + * @param phase offset, in degrees (normally, use 0) */ public void enableGridDashedLine(float lineLength, float spaceLength, float phase) { - mGridDashPathEffect = new DashPathEffect(new float[] { + mGridDashPathEffect = new DashPathEffect(new float[]{ lineLength, spaceLength }, phase); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index c87d64b04e..07be8b58f3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -67,6 +67,11 @@ public class YAxis extends AxisBase { */ protected boolean mForceLabels = false; + /** + * flag that indicates if the zero-line should be drawn regardless of other grid lines + */ + protected boolean mDrawZeroLine = true; + /** * custom minimum value this axis represents */ @@ -346,6 +351,20 @@ public float getSpaceBottom() { return mSpacePercentBottom; } + public boolean isDrawZeroLineEnabled() { + return mDrawZeroLine; + } + + /** + * Set this to true to draw the zero-line regardless of weather other + * grid-lines are enabled or not. + * + * @param mDrawZeroLine + */ + public void setDrawZeroLine(boolean mDrawZeroLine) { + this.mDrawZeroLine = mDrawZeroLine; + } + /** * This is for normal (not horizontal) charts horizontal spacing. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 1d174f430e..303b8bd20e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -247,34 +247,66 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo @Override public void renderGridLines(Canvas c) { - if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) + if (!mYAxis.isEnabled()) return; // pre alloc float[] position = new float[2]; - mGridPaint.setColor(mYAxis.getGridColor()); - mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); - mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); + if (mYAxis.isDrawGridLinesEnabled()) { - Path gridLinePath = new Path(); + mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { + Path gridLinePath = new Path(); - position[1] = mYAxis.mEntries[i]; - mTrans.pointValuesToPixel(position); + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { + + position[1] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); - gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); - gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); + gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); + gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); - // draw a path because lines don't support dashing on lower android versions - c.drawPath(gridLinePath, mGridPaint); + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); + + gridLinePath.reset(); + } + } + + if (mYAxis.isDrawZeroLineEnabled()) { + + // draw zero line + position[1] = 0f; + mTrans.pointValuesToPixel(position); - gridLinePath.reset(); + drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1], position[1]); } } + /** + * Draws the zero line at the specified position. + * + * @param c + * @param x1 + * @param x2 + * @param y1 + * @param y2 + */ + protected void drawZeroLine(Canvas c, float x1, float x2, float y1, float y2) { + + Path zeroLinePath = new Path(); + + zeroLinePath.moveTo(x1, y1); + zeroLinePath.lineTo(x2, y2); + + // draw a path because lines don't support dashing on lower android versions + c.drawPath(zeroLinePath, mGridPaint); + } + /** * Draws the LimitLines associated with this axis to the screen. * @@ -295,7 +327,7 @@ public void renderLimitLines(Canvas c) { LimitLine l = limitLines.get(i); - if(!l.isEnabled()) + if (!l.isEnabled()) continue; mLimitLinePaint.setStyle(Paint.Style.STROKE); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index e9ff473efc..31febfedda 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -21,15 +21,15 @@ public class YAxisRendererHorizontalBarChart extends YAxisRenderer { public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yAxis, - Transformer trans) { + Transformer trans) { super(viewPortHandler, yAxis, trans); - + mLimitLinePaint.setTextAlign(Align.LEFT); } /** * Computes the axis values. - * + * * @param yMin - the minimum y-value in the data object for this axis * @param yMax - the maximum y-value in the data object for this axis */ @@ -131,13 +131,13 @@ public void renderAxisLine(Canvas c) { /** * draws the y-labels on the specified x-position - * + * * @param fixedPosition * @param positions */ @Override protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { - + mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); @@ -156,30 +156,42 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo @Override public void renderGridLines(Canvas c) { - if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) + if (!mYAxis.isEnabled()) return; // pre alloc float[] position = new float[2]; - mGridPaint.setColor(mYAxis.getGridColor()); - mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + if (mYAxis.isDrawGridLinesEnabled()) { - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { + mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { - position[0] = mYAxis.mEntries[i]; + position[0] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); + + c.drawLine(position[0], mViewPortHandler.contentTop(), position[0], + mViewPortHandler.contentBottom(), + mGridPaint); + } + } + + if (mYAxis.isDrawZeroLineEnabled()) { + + // draw zero line + position[0] = 0f; mTrans.pointValuesToPixel(position); - c.drawLine(position[0], mViewPortHandler.contentTop(), position[0], - mViewPortHandler.contentBottom(), - mGridPaint); + drawZeroLine(c, position[0], position[0], mViewPortHandler.contentTop(), mViewPortHandler.contentBottom()); } } - + /** * Draws the LimitLines associated with this axis to the screen. - * This is the standard XAxis renderer using the YAxis limit lines. + * This is the standard XAxis renderer using the YAxis limit lines. * * @param c */ @@ -193,14 +205,14 @@ public void renderLimitLines(Canvas c) { float[] pts = new float[4]; Path limitLinePath = new Path(); - + for (int i = 0; i < limitLines.size(); i++) { LimitLine l = limitLines.get(i); - if(!l.isEnabled()) + if (!l.isEnabled()) continue; - + pts[0] = l.getLimit(); pts[2] = l.getLimit(); @@ -208,11 +220,11 @@ public void renderLimitLines(Canvas c) { pts[1] = mViewPortHandler.contentTop(); pts[3] = mViewPortHandler.contentBottom(); - + limitLinePath.moveTo(pts[0], pts[1]); limitLinePath.lineTo(pts[2], pts[3]); - mLimitLinePaint.setStyle(Paint.Style.STROKE); + mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setPathEffect(l.getDashPathEffect()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); @@ -225,7 +237,7 @@ public void renderLimitLines(Canvas c) { // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { - mLimitLinePaint.setStyle(l.getTextStyle()); + mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setTypeface(l.getTypeface()); From 08dfebcc08419a83719ced006b3aff93ce4e2794 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 10 Feb 2016 20:18:56 +0100 Subject: [PATCH 0722/1390] Final fixes and improvements concerning zero line --- .../BarChartPositiveNegative.java | 2 + .../mpchartexample/LineChartActivity1.java | 1 + .../mpchartexample/LineChartActivity2.java | 1 + .../mikephil/charting/components/YAxis.java | 37 +++++++++++++++++++ .../charting/renderer/YAxisRenderer.java | 14 ++++++- .../YAxisRendererHorizontalBarChart.java | 2 +- 6 files changed, 54 insertions(+), 3 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index b858541931..7cd203ae0a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -67,6 +67,8 @@ protected void onCreate(Bundle savedInstanceState) { left.setDrawAxisLine(false); left.setDrawGridLines(false); left.setDrawZeroLine(true); // draw a zero line + left.setZeroLineColor(Color.GRAY); + left.setZeroLineWidth(0.7f); mChart.getAxisRight().setEnabled(false); mChart.getLegend().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f1ad5d47a2..d1d32923fc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -133,6 +133,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); + leftAxis.setDrawZeroLine(false); // limit lines are drawn behind data (and not on top) leftAxis.setDrawLimitLinesBehindData(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index f69c07b561..4573bf89b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -123,6 +123,7 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setStartAtZero(false); rightAxis.setAxisMinValue(-200); rightAxis.setDrawGridLines(false); + rightAxis.setDrawZeroLine(false); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 07be8b58f3..9f0962c2b8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.components; +import android.graphics.Color; import android.graphics.Paint; import com.github.mikephil.charting.formatter.DefaultValueFormatter; @@ -72,6 +73,16 @@ public class YAxis extends AxisBase { */ protected boolean mDrawZeroLine = true; + /** + * Color of the zero line + */ + protected int mZeroLineColor = Color.GRAY; + + /** + * Width of the zero line in pixels + */ + protected float mZeroLineWidth = 1f; + /** * custom minimum value this axis represents */ @@ -365,6 +376,32 @@ public void setDrawZeroLine(boolean mDrawZeroLine) { this.mDrawZeroLine = mDrawZeroLine; } + public int getZeroLineColor() { + return mZeroLineColor; + } + + /** + * Sets the color of the zero line + * + * @param color + */ + public void setZeroLineColor(int color) { + mZeroLineColor = color; + } + + public float getZeroLineWidth() { + return mZeroLineWidth; + } + + /** + * Sets the width of the zero line in dp + * + * @param width + */ + public void setZeroLineWidth(float width) { + this.mZeroLineWidth = Utils.convertDpToPixel(width); + } + /** * This is for normal (not horizontal) charts horizontal spacing. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 303b8bd20e..24df7523a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -21,6 +21,8 @@ public class YAxisRenderer extends AxisRenderer { protected YAxis mYAxis; + protected Paint mZeroLinePaint; + public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { super(viewPortHandler, trans); @@ -28,6 +30,11 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mAxisLabelPaint.setColor(Color.BLACK); mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + + mZeroLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mZeroLinePaint.setColor(Color.GRAY); + mZeroLinePaint.setStrokeWidth(1f); + mZeroLinePaint.setStyle(Paint.Style.STROKE); } /** @@ -283,7 +290,7 @@ public void renderGridLines(Canvas c) { position[1] = 0f; mTrans.pointValuesToPixel(position); - drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1], position[1]); + drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1]-1, position[1]-1); } } @@ -298,13 +305,16 @@ public void renderGridLines(Canvas c) { */ protected void drawZeroLine(Canvas c, float x1, float x2, float y1, float y2) { + mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); + mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); + Path zeroLinePath = new Path(); zeroLinePath.moveTo(x1, y1); zeroLinePath.lineTo(x2, y2); // draw a path because lines don't support dashing on lower android versions - c.drawPath(zeroLinePath, mGridPaint); + c.drawPath(zeroLinePath, mZeroLinePaint); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 31febfedda..b5afb2bb86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -185,7 +185,7 @@ public void renderGridLines(Canvas c) { position[0] = 0f; mTrans.pointValuesToPixel(position); - drawZeroLine(c, position[0], position[0], mViewPortHandler.contentTop(), mViewPortHandler.contentBottom()); + drawZeroLine(c, position[0]+1, position[0]+1, mViewPortHandler.contentTop(), mViewPortHandler.contentBottom()); } } From 5bc113680008ff700ae1ad20801e6b359e85af29 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 10 Feb 2016 20:19:54 +0100 Subject: [PATCH 0723/1390] Version upgrade --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 8ee59693af..a1d5c3a9c0 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="48" + android:versionName="2.2.2" > Date: Wed, 10 Feb 2016 20:23:33 +0100 Subject: [PATCH 0724/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eeba891e04..8d35b587c9 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.0/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) @@ -148,7 +148,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' + compile 'com.github.PhilJay:MPAndroidChart:v2.2.2' } ``` @@ -163,7 +163,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.2.0 + v2.2.2 ``` @@ -183,7 +183,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.0/javadoc/). +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 5809f713c5b75bd2c6d356f3baed437f8158835f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 09:55:02 +0200 Subject: [PATCH 0725/1390] Default filled/not-filled in candle chart were wrong --- .../mpchartexample/CandleStickChartActivity.java | 4 ++-- .../mpchartexample/realm/RealmDatabaseActivityCandle.java | 4 ++-- .../com/github/mikephil/charting/data/CandleDataSet.java | 6 ++++-- .../data/realm/implementation/RealmCandleDataSet.java | 6 ++++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 414530a9c3..b64ced195a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -201,9 +201,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setShadowColor(Color.DKGRAY); set1.setShadowWidth(0.7f); set1.setDecreasingColor(Color.RED); - set1.setDecreasingPaintStyle(Paint.Style.STROKE); + set1.setDecreasingPaintStyle(Paint.Style.FILL); set1.setIncreasingColor(Color.rgb(122, 242, 84)); - set1.setIncreasingPaintStyle(Paint.Style.FILL); + set1.setIncreasingPaintStyle(Paint.Style.STROKE); //set1.setHighlightLineWidth(1f); CandleData data = new CandleData(xVals, set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index bf788620a5..3b749c9f59 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -58,9 +58,9 @@ private void setData() { set.setShadowColor(Color.DKGRAY); set.setShadowWidth(0.7f); set.setDecreasingColor(Color.RED); - set.setDecreasingPaintStyle(Paint.Style.STROKE); + set.setDecreasingPaintStyle(Paint.Style.FILL); set.setIncreasingColor(Color.rgb(122, 242, 84)); - set.setIncreasingPaintStyle(Paint.Style.FILL); + set.setIncreasingPaintStyle(Paint.Style.STROKE); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 176c4422aa..97a3fdd0d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -34,13 +34,15 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im /** * paint style when open <= close + * increasing candlesticks are traditionally hollow */ - protected Paint.Style mIncreasingPaintStyle = Paint.Style.FILL; + protected Paint.Style mIncreasingPaintStyle = Paint.Style.STROKE; /** * paint style when open > close + * descreasing candlesticks are traditionally filled */ - protected Paint.Style mDecreasingPaintStyle = Paint.Style.STROKE; + protected Paint.Style mDecreasingPaintStyle = Paint.Style.FILL; /** * color for open <= close diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 0a2f8c03d3..a398fde92c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -39,13 +39,15 @@ public class RealmCandleDataSet extends RealmLineScatterC /** * paint style when open <= close + * increasing candlesticks are traditionally hollow */ - protected Paint.Style mIncreasingPaintStyle = Paint.Style.FILL; + protected Paint.Style mIncreasingPaintStyle = Paint.Style.STROKE; /** * paint style when open > close + * descreasing candlesticks are traditionally filled */ - protected Paint.Style mDecreasingPaintStyle = Paint.Style.STROKE; + protected Paint.Style mDecreasingPaintStyle = Paint.Style.FILL; /** * color for open <= close From 83ebea7fd281a2c78a91d590841eb667fe7009e7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 10:26:14 +0200 Subject: [PATCH 0726/1390] Do not show shadow through candle bar --- .../charting/buffer/CandleBodyBuffer.java | 40 ------ .../charting/buffer/CandleShadowBuffer.java | 34 ------ .../renderer/CandleStickChartRenderer.java | 114 +++++++++++------- 3 files changed, 68 insertions(+), 120 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java deleted file mode 100644 index d40c35ddce..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java +++ /dev/null @@ -1,40 +0,0 @@ - -package com.github.mikephil.charting.buffer; - -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; - -public class CandleBodyBuffer extends AbstractBuffer { - - private float mBodySpace = 0f; - - public CandleBodyBuffer(int size) { - super(size); - } - - public void setBodySpace(float bodySpace) { - this.mBodySpace = bodySpace; - } - - private void addBody(float left, float top, float right, float bottom) { - - buffer[index++] = left; - buffer[index++] = top; - buffer[index++] = right; - buffer[index++] = bottom; - } - - @Override - public void feed(ICandleDataSet data) { - - int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); - - for (int i = mFrom; i < size; i++) { - - CandleEntry e = data.getEntryForIndex(i); - addBody(e.getXIndex() - 0.5f + mBodySpace, e.getClose() * phaseY, e.getXIndex() + 0.5f - mBodySpace, e.getOpen() * phaseY); - } - - reset(); - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java deleted file mode 100644 index 2c413d66b4..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java +++ /dev/null @@ -1,34 +0,0 @@ - -package com.github.mikephil.charting.buffer; - -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; - -public class CandleShadowBuffer extends AbstractBuffer { - - public CandleShadowBuffer(int size) { - super(size); - } - - private void addShadow(float x1, float y1, float x2, float y2) { - - buffer[index++] = x1; - buffer[index++] = y1; - buffer[index++] = x2; - buffer[index++] = y2; - } - - @Override - public void feed(ICandleDataSet data) { - - int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); - - for (int i = mFrom; i < size; i++) { - - CandleEntry e = data.getEntryForIndex(i); - addShadow(e.getXIndex(), e.getHigh() * phaseY, e.getXIndex(), e.getLow() * phaseY); - } - - reset(); - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 86000f67de..f9cbe5a908 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -5,8 +5,6 @@ import android.graphics.Paint; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.buffer.CandleBodyBuffer; -import com.github.mikephil.charting.buffer.CandleShadowBuffer; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.highlight.Highlight; @@ -23,8 +21,8 @@ public class CandleStickChartRenderer extends LineScatterCandleRadarRenderer { protected CandleDataProvider mChart; - private CandleShadowBuffer[] mShadowBuffers; - private CandleBodyBuffer[] mBodyBuffers; + private float[] mShadowBuffers = new float[8]; + private float[] mBodyBuffers = new float[4]; public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -34,15 +32,7 @@ public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator @Override public void initBuffers() { - CandleData candleData = mChart.getCandleData(); - mShadowBuffers = new CandleShadowBuffer[candleData.getDataSetCount()]; - mBodyBuffers = new CandleBodyBuffer[candleData.getDataSetCount()]; - for (int i = 0; i < mShadowBuffers.length; i++) { - ICandleDataSet set = candleData.getDataSetByIndex(i); - mShadowBuffers[i] = new CandleShadowBuffer(set.getEntryCount() * 4); - mBodyBuffers[i] = new CandleBodyBuffer(set.getEntryCount() * 4); - } } @Override @@ -63,8 +53,7 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - - int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet); + float bodySpace = dataSet.getBodySpace(); int minx = Math.max(mMinX, 0); int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); @@ -72,23 +61,6 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { int range = (maxx - minx) * 4; int to = (int) Math.ceil((maxx - minx) * phaseX + minx); - CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; - bodyBuffer.setBodySpace(dataSet.getBodySpace()); - bodyBuffer.setPhases(phaseX, phaseY); - bodyBuffer.limitFrom(minx); - bodyBuffer.limitTo(maxx); - bodyBuffer.feed(dataSet); - - trans.pointValuesToPixel(bodyBuffer.buffer); - - CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex]; - shadowBuffer.setPhases(phaseX, phaseY); - shadowBuffer.limitFrom(minx); - shadowBuffer.limitTo(maxx); - shadowBuffer.feed(dataSet); - - trans.pointValuesToPixel(shadowBuffer.buffer); - mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); // draw the body @@ -100,16 +72,55 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { if (!fitsBounds(e.getXIndex(), mMinX, to)) continue; + final int xIndex = e.getXIndex(); + final float open = e.getOpen(); + final float close = e.getClose(); + final float high = e.getHigh(); + final float low = e.getLow(); + + // calculate the shadow + + mShadowBuffers[0] = xIndex; + mShadowBuffers[2] = xIndex; + mShadowBuffers[4] = xIndex; + mShadowBuffers[6] = xIndex; + + if (open > close) + { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = open * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = close * phaseY; + } + else if (open < close) + { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = close * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = open * phaseY; + } + else + { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = open * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = mShadowBuffers[3]; + } + + trans.pointValuesToPixel(mShadowBuffers); + + // draw the shadows + if (dataSet.getShadowColorSameAsCandle()) { - if (e.getOpen() > e.getClose()) + if (open > close) mRenderPaint.setColor( dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ? dataSet.getColor(j) : dataSet.getDecreasingColor() ); - else if (e.getOpen() < e.getClose()) + else if (open < close) mRenderPaint.setColor( dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ? dataSet.getColor(j) : @@ -133,15 +144,16 @@ else if (e.getOpen() < e.getClose()) mRenderPaint.setStyle(Paint.Style.STROKE); - // draw the shadow - c.drawLine(shadowBuffer.buffer[j], shadowBuffer.buffer[j + 1], - shadowBuffer.buffer[j + 2], shadowBuffer.buffer[j + 3], - mRenderPaint); + c.drawLines(mShadowBuffers, mRenderPaint); + + // calculate the body - float leftBody = bodyBuffer.buffer[j]; - float open = bodyBuffer.buffer[j + 1]; - float rightBody = bodyBuffer.buffer[j + 2]; - float close = bodyBuffer.buffer[j + 3]; + mBodyBuffers[0] = xIndex - 0.5f + bodySpace; + mBodyBuffers[1] = close * phaseY; + mBodyBuffers[2] = (xIndex + 0.5f - bodySpace); + mBodyBuffers[3] = open * phaseY; + + trans.pointValuesToPixel(mBodyBuffers); // draw body differently for increasing and decreasing entry if (open > close) { // decreasing @@ -153,8 +165,11 @@ else if (e.getOpen() < e.getClose()) } mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle()); - // draw the body - c.drawRect(leftBody, close, rightBody, open, mRenderPaint); + + c.drawRect( + mBodyBuffers[0], mBodyBuffers[3], + mBodyBuffers[2], mBodyBuffers[1], + mRenderPaint); } else if (open < close) { @@ -165,12 +180,19 @@ else if (e.getOpen() < e.getClose()) } mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle()); - // draw the body - c.drawRect(leftBody, open, rightBody, close, mRenderPaint); + + c.drawRect( + mBodyBuffers[0], mBodyBuffers[1], + mBodyBuffers[2], mBodyBuffers[3], + mRenderPaint); } else { // equal values mRenderPaint.setColor(dataSet.getShadowColor()); - c.drawLine(leftBody, open, rightBody, close, mRenderPaint); + + c.drawLine( + mBodyBuffers[0], mBodyBuffers[1], + mBodyBuffers[2], mBodyBuffers[3], + mRenderPaint); } } } From 45a896025145df2d84f89dd0733e3e5af1b288b9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 10:33:35 +0200 Subject: [PATCH 0727/1390] Separate neutralColor in candlestick chart --- .../CandleStickChartActivity.java | 1 + .../realm/RealmDatabaseActivityCandle.java | 1 + .../mikephil/charting/data/CandleDataSet.java | 22 ++++++++++++++++- .../implementation/RealmCandleDataSet.java | 24 +++++++++++++++++-- .../interfaces/datasets/ICandleDataSet.java | 13 +++++++--- .../renderer/CandleStickChartRenderer.java | 10 +++++--- 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index b64ced195a..44c044cf49 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -204,6 +204,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setDecreasingPaintStyle(Paint.Style.FILL); set1.setIncreasingColor(Color.rgb(122, 242, 84)); set1.setIncreasingPaintStyle(Paint.Style.STROKE); + set1.setNeutralColor(Color.BLUE); //set1.setHighlightLineWidth(1f); CandleData data = new CandleData(xVals, set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 3b749c9f59..70e324d4dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -61,6 +61,7 @@ private void setData() { set.setDecreasingPaintStyle(Paint.Style.FILL); set.setIncreasingColor(Color.rgb(122, 242, 84)); set.setIncreasingPaintStyle(Paint.Style.STROKE); + set.setNeutralColor(Color.BLUE); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 97a3fdd0d0..cebb1acd90 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -45,7 +45,12 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im protected Paint.Style mDecreasingPaintStyle = Paint.Style.FILL; /** - * color for open <= close + * color for open == close + */ + protected int mNeutralColor = ColorTemplate.COLOR_NONE; + + /** + * color for open < close */ protected int mIncreasingColor = ColorTemplate.COLOR_NONE; @@ -164,6 +169,21 @@ public float getShadowWidth() { /** BELOW THIS COLOR HANDLING */ + /** + * Sets the one and ONLY color that should be used for this DataSet when + * open == close. + * + * @param color + */ + public void setNeutralColor(int color) { + mNeutralColor = color; + } + + @Override + public int getNeutralColor() { + return mNeutralColor; + } + /** * Sets the one and ONLY color that should be used for this DataSet when * open > close. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index a398fde92c..c3acddfd1b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -50,7 +50,12 @@ public class RealmCandleDataSet extends RealmLineScatterC protected Paint.Style mDecreasingPaintStyle = Paint.Style.FILL; /** - * color for open <= close + * color for open == close + */ + protected int mNeutralColor = ColorTemplate.COLOR_NONE; + + /** + * color for open < close */ protected int mIncreasingColor = ColorTemplate.COLOR_NONE; @@ -200,6 +205,21 @@ public float getShadowWidth() { /** BELOW THIS COLOR HANDLING */ + /** + * Sets the one and ONLY color that should be used for this DataSet when + * open == close. + * + * @param color + */ + public void setNeutralColor(int color) { + mNeutralColor = color; + } + + @Override + public int getNeutralColor() { + return mNeutralColor; + } + /** * Sets the one and ONLY color that should be used for this DataSet when * open > close. @@ -217,7 +237,7 @@ public int getDecreasingColor() { /** * Sets the one and ONLY color that should be used for this DataSet when - * open <= close. + * open < close. * * @param color */ diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java index 8f2b96c96d..bdc746ee1e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java @@ -29,17 +29,24 @@ public interface ICandleDataSet extends ILineScatterCandleRadarDataSet close). * * @return */ int getDecreasingColor(); /** - * Returns the increasing color. + * Returns the increasing color (for open < close). * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index f9cbe5a908..e8ab49eec1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -129,9 +129,9 @@ else if (open < close) else mRenderPaint.setColor( - dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ? + dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE ? dataSet.getColor(j) : - dataSet.getShadowColor() + dataSet.getNeutralColor() ); } else { @@ -187,7 +187,11 @@ else if (open < close) mRenderPaint); } else { // equal values - mRenderPaint.setColor(dataSet.getShadowColor()); + if (dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE) { + mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); + } else { + mRenderPaint.setColor(dataSet.getNeutralColor()); + } c.drawLine( mBodyBuffers[0], mBodyBuffers[1], From f5c2336eb15b437edf00a43a0303f0fa6a7720c3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 10:44:42 +0200 Subject: [PATCH 0728/1390] Got rid of the confusing 4 multiplier here --- .../renderer/CandleStickChartRenderer.java | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index e8ab49eec1..a368d659f0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -58,21 +58,22 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { int minx = Math.max(mMinX, 0); int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); - int range = (maxx - minx) * 4; - int to = (int) Math.ceil((maxx - minx) * phaseX + minx); - mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); // draw the body - for (int j = 0; j < range; j += 4) { + for (int j = minx, + count = (int) Math.ceil((maxx - minx) * phaseX + (float)minx); + j < count; + j++) { // get the entry - CandleEntry e = dataSet.getEntryForIndex(j / 4 + minx); + CandleEntry e = dataSet.getEntryForIndex(j); + + final int xIndex = e.getXIndex(); - if (!fitsBounds(e.getXIndex(), mMinX, to)) + if (xIndex < minx || xIndex >= maxx) continue; - final int xIndex = e.getXIndex(); final float open = e.getOpen(); final float close = e.getClose(); final float high = e.getHigh(); @@ -159,7 +160,7 @@ else if (open < close) if (open > close) { // decreasing if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); + mRenderPaint.setColor(dataSet.getColor(j)); } else { mRenderPaint.setColor(dataSet.getDecreasingColor()); } @@ -174,7 +175,7 @@ else if (open < close) } else if (open < close) { if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); + mRenderPaint.setColor(dataSet.getColor(j)); } else { mRenderPaint.setColor(dataSet.getIncreasingColor()); } @@ -188,7 +189,7 @@ else if (open < close) } else { // equal values if (dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); + mRenderPaint.setColor(dataSet.getColor(j)); } else { mRenderPaint.setColor(dataSet.getNeutralColor()); } From 95ce8b2bf624659f260a168cc6ed824006c74a65 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 10:47:08 +0200 Subject: [PATCH 0729/1390] Changed order of those properties for consistency --- .../mikephil/charting/data/CandleDataSet.java | 46 +++++++++---------- .../implementation/RealmCandleDataSet.java | 46 +++++++++---------- .../interfaces/datasets/ICandleDataSet.java | 16 +++---- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index cebb1acd90..3df2f42239 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -33,7 +33,7 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im private boolean mShadowColorSameAsCandle = false; /** - * paint style when open <= close + * paint style when open < close * increasing candlesticks are traditionally hollow */ protected Paint.Style mIncreasingPaintStyle = Paint.Style.STROKE; @@ -186,60 +186,60 @@ public int getNeutralColor() { /** * Sets the one and ONLY color that should be used for this DataSet when - * open > close. + * open <= close. * * @param color */ - public void setDecreasingColor(int color) { - mDecreasingColor = color; + public void setIncreasingColor(int color) { + mIncreasingColor = color; } @Override - public int getDecreasingColor() { - return mDecreasingColor; + public int getIncreasingColor() { + return mIncreasingColor; } /** * Sets the one and ONLY color that should be used for this DataSet when - * open <= close. + * open > close. * * @param color */ - public void setIncreasingColor(int color) { - mIncreasingColor = color; + public void setDecreasingColor(int color) { + mDecreasingColor = color; } @Override - public int getIncreasingColor() { - return mIncreasingColor; + public int getDecreasingColor() { + return mDecreasingColor; } @Override - public Paint.Style getDecreasingPaintStyle() { - return mDecreasingPaintStyle; + public Paint.Style getIncreasingPaintStyle() { + return mIncreasingPaintStyle; } /** - * Sets paint style when open > close + * Sets paint style when open < close * - * @param decreasingPaintStyle + * @param paintStyle */ - public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { - this.mDecreasingPaintStyle = decreasingPaintStyle; + public void setIncreasingPaintStyle(Paint.Style paintStyle) { + this.mIncreasingPaintStyle = paintStyle; } @Override - public Paint.Style getIncreasingPaintStyle() { - return mIncreasingPaintStyle; + public Paint.Style getDecreasingPaintStyle() { + return mDecreasingPaintStyle; } /** - * Sets paint style when open <= close + * Sets paint style when open > close * - * @param paintStyle + * @param decreasingPaintStyle */ - public void setIncreasingPaintStyle(Paint.Style paintStyle) { - this.mIncreasingPaintStyle = paintStyle; + public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { + this.mDecreasingPaintStyle = decreasingPaintStyle; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index c3acddfd1b..092550696e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -38,7 +38,7 @@ public class RealmCandleDataSet extends RealmLineScatterC private boolean mShadowColorSameAsCandle = false; /** - * paint style when open <= close + * paint style when open < close * increasing candlesticks are traditionally hollow */ protected Paint.Style mIncreasingPaintStyle = Paint.Style.STROKE; @@ -222,60 +222,60 @@ public int getNeutralColor() { /** * Sets the one and ONLY color that should be used for this DataSet when - * open > close. + * open < close. * * @param color */ - public void setDecreasingColor(int color) { - mDecreasingColor = color; + public void setIncreasingColor(int color) { + mIncreasingColor = color; } @Override - public int getDecreasingColor() { - return mDecreasingColor; + public int getIncreasingColor() { + return mIncreasingColor; } /** * Sets the one and ONLY color that should be used for this DataSet when - * open < close. + * open > close. * * @param color */ - public void setIncreasingColor(int color) { - mIncreasingColor = color; + public void setDecreasingColor(int color) { + mDecreasingColor = color; } @Override - public int getIncreasingColor() { - return mIncreasingColor; + public int getDecreasingColor() { + return mDecreasingColor; } @Override - public Paint.Style getDecreasingPaintStyle() { - return mDecreasingPaintStyle; + public Paint.Style getIncreasingPaintStyle() { + return mIncreasingPaintStyle; } /** - * Sets paint style when open > close + * Sets paint style when open < close * - * @param decreasingPaintStyle + * @param paintStyle */ - public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { - this.mDecreasingPaintStyle = decreasingPaintStyle; + public void setIncreasingPaintStyle(Paint.Style paintStyle) { + this.mIncreasingPaintStyle = paintStyle; } @Override - public Paint.Style getIncreasingPaintStyle() { - return mIncreasingPaintStyle; + public Paint.Style getDecreasingPaintStyle() { + return mDecreasingPaintStyle; } /** - * Sets paint style when open <= close + * Sets paint style when open > close * - * @param paintStyle + * @param decreasingPaintStyle */ - public void setIncreasingPaintStyle(Paint.Style paintStyle) { - this.mIncreasingPaintStyle = paintStyle; + public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { + this.mDecreasingPaintStyle = decreasingPaintStyle; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java index bdc746ee1e..7b1af35680 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java @@ -39,32 +39,32 @@ public interface ICandleDataSet extends ILineScatterCandleRadarDataSet close). + * Returns the increasing color (for open < close). * * @return */ - int getDecreasingColor(); + int getIncreasingColor(); /** - * Returns the increasing color (for open < close). + * Returns the decreasing color (for open > close). * * @return */ - int getIncreasingColor(); + int getDecreasingColor(); /** - * Returns paint style when open > close + * Returns paint style when open < close * * @return */ - Paint.Style getDecreasingPaintStyle(); + Paint.Style getIncreasingPaintStyle(); /** - * Returns paint style when open <= close + * Returns paint style when open > close * * @return */ - Paint.Style getIncreasingPaintStyle(); + Paint.Style getDecreasingPaintStyle(); /** * Is the shadow color same as the candle color? From b8f3d49b11e775ad489687ed5a8093525c9a666f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 10:58:40 +0200 Subject: [PATCH 0730/1390] Support for rendering candlesticks without the bars --- .../mikephil/charting/data/CandleDataSet.java | 23 ++ .../implementation/RealmCandleDataSet.java | 22 ++ .../interfaces/datasets/ICandleDataSet.java | 10 + .../renderer/CandleStickChartRenderer.java | 230 +++++++++++------- 4 files changed, 196 insertions(+), 89 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 3df2f42239..45612bd0e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -22,6 +22,14 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im */ private float mShadowWidth = 3f; + /** + * should the candle bars show? + * when false, only "ticks" will show + * + * - default: true + */ + private boolean mShowCandleBar = true; + /** * the space between the candle entries, default 0.1f (10%) */ @@ -81,6 +89,7 @@ public DataSet copy() { CandleDataSet copied = new CandleDataSet(yVals, getLabel()); copied.mColors = mColors; copied.mShadowWidth = mShadowWidth; + copied.mShowCandleBar = mShowCandleBar; copied.mBodySpace = mBodySpace; copied.mHighLightColor = mHighLightColor; copied.mIncreasingPaintStyle = mIncreasingPaintStyle; @@ -157,6 +166,20 @@ public float getShadowWidth() { return mShadowWidth; } + /** + * Sets whether the candle bars should show? + * + * @param showCandleBar + */ + public void setShadowWidth(boolean showCandleBar) { + mShowCandleBar = showCandleBar; + } + + @Override + public boolean getShowCandleBar() { + return mShowCandleBar; + } + // TODO /** * It is necessary to implement ColorsList class that will encapsulate diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 092550696e..921fb95d0b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -27,6 +27,14 @@ public class RealmCandleDataSet extends RealmLineScatterC */ private float mShadowWidth = 3f; + /** + * should the candle bars show? + * when false, only "ticks" will show + * + * - default: true + */ + private boolean mShowCandleBar = true; + /** * the space between the candle entries, default 0.1f (10%) */ @@ -202,6 +210,20 @@ public float getShadowWidth() { return mShadowWidth; } + /** + * Sets whether the candle bars should show? + * + * @param showCandleBar + */ + public void setShadowWidth(boolean showCandleBar) { + mShowCandleBar = showCandleBar; + } + + @Override + public boolean getShowCandleBar() { + return mShowCandleBar; + } + /** BELOW THIS COLOR HANDLING */ diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java index 7b1af35680..6929f9d997 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java @@ -17,6 +17,16 @@ public interface ICandleDataSet extends ILineScatterCandleRadarDataSet close) { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = open * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = close * phaseY; + } else if (open < close) { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = close * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = open * phaseY; + } else { + mShadowBuffers[1] = high * phaseY; + mShadowBuffers[3] = open * phaseY; + mShadowBuffers[5] = low * phaseY; + mShadowBuffers[7] = mShadowBuffers[3]; + } - mShadowBuffers[0] = xIndex; - mShadowBuffers[2] = xIndex; - mShadowBuffers[4] = xIndex; - mShadowBuffers[6] = xIndex; + trans.pointValuesToPixel(mShadowBuffers); - if (open > close) - { - mShadowBuffers[1] = high * phaseY; - mShadowBuffers[3] = open * phaseY; - mShadowBuffers[5] = low * phaseY; - mShadowBuffers[7] = close * phaseY; - } - else if (open < close) - { - mShadowBuffers[1] = high * phaseY; - mShadowBuffers[3] = close * phaseY; - mShadowBuffers[5] = low * phaseY; - mShadowBuffers[7] = open * phaseY; - } - else - { - mShadowBuffers[1] = high * phaseY; - mShadowBuffers[3] = open * phaseY; - mShadowBuffers[5] = low * phaseY; - mShadowBuffers[7] = mShadowBuffers[3]; - } + // draw the shadows - trans.pointValuesToPixel(mShadowBuffers); + if (dataSet.getShadowColorSameAsCandle()) { - // draw the shadows + if (open > close) + mRenderPaint.setColor( + dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getDecreasingColor() + ); - if (dataSet.getShadowColorSameAsCandle()) { + else if (open < close) + mRenderPaint.setColor( + dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getIncreasingColor() + ); - if (open > close) - mRenderPaint.setColor( - dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ? - dataSet.getColor(j) : - dataSet.getDecreasingColor() - ); + else + mRenderPaint.setColor( + dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getNeutralColor() + ); - else if (open < close) + } else { mRenderPaint.setColor( - dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ? + dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ? dataSet.getColor(j) : - dataSet.getIncreasingColor() + dataSet.getShadowColor() ); + } - else - mRenderPaint.setColor( - dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE ? - dataSet.getColor(j) : - dataSet.getNeutralColor() - ); + mRenderPaint.setStyle(Paint.Style.STROKE); - } else { - mRenderPaint.setColor( - dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ? - dataSet.getColor(j) : - dataSet.getShadowColor() - ); - } + c.drawLines(mShadowBuffers, mRenderPaint); - mRenderPaint.setStyle(Paint.Style.STROKE); + // calculate the body - c.drawLines(mShadowBuffers, mRenderPaint); + mBodyBuffers[0] = xIndex - 0.5f + bodySpace; + mBodyBuffers[1] = close * phaseY; + mBodyBuffers[2] = (xIndex + 0.5f - bodySpace); + mBodyBuffers[3] = open * phaseY; - // calculate the body + trans.pointValuesToPixel(mBodyBuffers); - mBodyBuffers[0] = xIndex - 0.5f + bodySpace; - mBodyBuffers[1] = close * phaseY; - mBodyBuffers[2] = (xIndex + 0.5f - bodySpace); - mBodyBuffers[3] = open * phaseY; + // draw body differently for increasing and decreasing entry + if (open > close) { // decreasing - trans.pointValuesToPixel(mBodyBuffers); + if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) { + mRenderPaint.setColor(dataSet.getColor(j)); + } else { + mRenderPaint.setColor(dataSet.getDecreasingColor()); + } - // draw body differently for increasing and decreasing entry - if (open > close) { // decreasing + mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle()); - if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j)); - } else { - mRenderPaint.setColor(dataSet.getDecreasingColor()); - } + c.drawRect( + mBodyBuffers[0], mBodyBuffers[3], + mBodyBuffers[2], mBodyBuffers[1], + mRenderPaint); - mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle()); + } else if (open < close) { - c.drawRect( - mBodyBuffers[0], mBodyBuffers[3], - mBodyBuffers[2], mBodyBuffers[1], - mRenderPaint); + if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) { + mRenderPaint.setColor(dataSet.getColor(j)); + } else { + mRenderPaint.setColor(dataSet.getIncreasingColor()); + } - } else if (open < close) { + mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle()); - if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j)); - } else { - mRenderPaint.setColor(dataSet.getIncreasingColor()); + c.drawRect( + mBodyBuffers[0], mBodyBuffers[1], + mBodyBuffers[2], mBodyBuffers[3], + mRenderPaint); + } else { // equal values + + if (dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE) { + mRenderPaint.setColor(dataSet.getColor(j)); + } else { + mRenderPaint.setColor(dataSet.getNeutralColor()); + } + + c.drawLine( + mBodyBuffers[0], mBodyBuffers[1], + mBodyBuffers[2], mBodyBuffers[3], + mRenderPaint); } + } else { - mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle()); + mRangeBuffers[0] = xIndex; + mRangeBuffers[1] = high * phaseY; + mRangeBuffers[2] = xIndex; + mRangeBuffers[3] = low * phaseY; - c.drawRect( - mBodyBuffers[0], mBodyBuffers[1], - mBodyBuffers[2], mBodyBuffers[3], - mRenderPaint); - } else { // equal values + mOpenBuffers[0] = xIndex - 0.5f + bodySpace; + mOpenBuffers[1] = open * phaseY; + mOpenBuffers[2] = xIndex; + mOpenBuffers[3] = open * phaseY; - if (dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor(j)); - } else { - mRenderPaint.setColor(dataSet.getNeutralColor()); - } + mCloseBuffers[0] = xIndex + 0.5f - bodySpace; + mCloseBuffers[1] = close * phaseY; + mCloseBuffers[2] = xIndex; + mCloseBuffers[3] = close * phaseY; + + trans.pointValuesToPixel(mRangeBuffers); + trans.pointValuesToPixel(mOpenBuffers); + trans.pointValuesToPixel(mCloseBuffers); + + // draw the ranges + int barColor; + if (open > close) + barColor = dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE + ? dataSet.getColor(j) + : dataSet.getDecreasingColor(); + else if (open < close) + barColor = dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE + ? dataSet.getColor(j) + : dataSet.getIncreasingColor(); + else + barColor = dataSet.getNeutralColor() == ColorTemplate.COLOR_NONE + ? dataSet.getColor(j) + : dataSet.getNeutralColor(); + + mRenderPaint.setColor(barColor); c.drawLine( - mBodyBuffers[0], mBodyBuffers[1], - mBodyBuffers[2], mBodyBuffers[3], + mRangeBuffers[0], mRangeBuffers[1], + mRangeBuffers[2], mRangeBuffers[3], mRenderPaint); + c.drawLine( + mOpenBuffers[0], mOpenBuffers[1], + mOpenBuffers[2], mOpenBuffers[3], + mRenderPaint); + c.drawLine( + mCloseBuffers[0], mCloseBuffers[1], + mCloseBuffers[2], mCloseBuffers[3], + mRenderPaint); + } } } From 32fc58d8dd5e559f4521e7684cc6258b9b1dee5c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Feb 2016 11:00:16 +0200 Subject: [PATCH 0731/1390] Renamed candleDataSet.bodySpace -> barSpace --- .../mpchartexample/CombinedChartActivity.java | 2 +- .../github/mikephil/charting/data/CandleDataSet.java | 12 ++++++------ .../realm/implementation/RealmCandleDataSet.java | 10 +++++----- .../charting/interfaces/datasets/ICandleDataSet.java | 2 +- .../charting/renderer/CandleStickChartRenderer.java | 10 +++++----- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index b2e4c7a4e0..b7e45e865d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -154,7 +154,7 @@ protected CandleData generateCandleData() { CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); set.setColor(Color.rgb(80, 80, 80)); - set.setBodySpace(0.3f); + set.setBarSpace(0.3f); set.setValueTextSize(10f); set.setDrawValues(false); d.addDataSet(set); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 45612bd0e8..03f09251bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -33,7 +33,7 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im /** * the space between the candle entries, default 0.1f (10%) */ - private float mBodySpace = 0.1f; + private float mBarSpace = 0.1f; /** * use candle color for the shadow @@ -90,7 +90,7 @@ public DataSet copy() { copied.mColors = mColors; copied.mShadowWidth = mShadowWidth; copied.mShowCandleBar = mShowCandleBar; - copied.mBodySpace = mBodySpace; + copied.mBarSpace = mBarSpace; copied.mHighLightColor = mHighLightColor; copied.mIncreasingPaintStyle = mIncreasingPaintStyle; copied.mDecreasingPaintStyle = mDecreasingPaintStyle; @@ -137,19 +137,19 @@ public void calcMinMax(int start, int end) { * * @param space */ - public void setBodySpace(float space) { + public void setBarSpace(float space) { if (space < 0f) space = 0f; if (space > 0.45f) space = 0.45f; - mBodySpace = space; + mBarSpace = space; } @Override - public float getBodySpace() { - return mBodySpace; + public float getBarSpace() { + return mBarSpace; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 921fb95d0b..8c7c9c8e78 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -38,7 +38,7 @@ public class RealmCandleDataSet extends RealmLineScatterC /** * the space between the candle entries, default 0.1f (10%) */ - private float mBodySpace = 0.1f; + private float mBarSpace = 0.1f; /** * use candle color for the shadow @@ -181,19 +181,19 @@ public void calcMinMax(int start, int end) { * * @param space */ - public void setBodySpace(float space) { + public void setBarSpace(float space) { if (space < 0f) space = 0f; if (space > 0.45f) space = 0.45f; - mBodySpace = space; + mBarSpace = space; } @Override - public float getBodySpace() { - return mBodySpace; + public float getBarSpace() { + return mBarSpace; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java index 6929f9d997..1d004ed959 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java @@ -15,7 +15,7 @@ public interface ICandleDataSet extends ILineScatterCandleRadarDataSet Date: Thu, 11 Feb 2016 16:24:30 +0100 Subject: [PATCH 0732/1390] Add zeroline screenshot --- .../BarChartPositiveNegative.java | 1 + screenshots/zero_line_example_barchart.png | Bin 0 -> 21080 bytes 2 files changed, 1 insertion(+) create mode 100644 screenshots/zero_line_example_barchart.png diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 7cd203ae0a..26f8e6fceb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -35,6 +35,7 @@ protected void onCreate(Bundle savedInstanceState) { mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart = (BarChart) findViewById(R.id.chart1); + mChart.setBackgroundColor(Color.WHITE); mChart.setExtraTopOffset(-30f); mChart.setExtraBottomOffset(10f); mChart.setExtraLeftOffset(70f); diff --git a/screenshots/zero_line_example_barchart.png b/screenshots/zero_line_example_barchart.png new file mode 100644 index 0000000000000000000000000000000000000000..514238569fb2fbee36a91cb4e08d98aae8e40a8d GIT binary patch literal 21080 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 literal 0 HcmV?d00001 From b47dd6522773f5abc40914e6ed5695ec84d21198 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Feb 2016 13:03:06 +0100 Subject: [PATCH 0733/1390] Minor adjustments to scatter-hole PR --- .../xxmassdeveloper/mpchartexample/ScatterChartActivity.java | 3 +++ .../com/github/mikephil/charting/data/ScatterDataSet.java | 5 ++--- .../mikephil/charting/renderer/ScatterChartRenderer.java | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 02a7760873..b4e3e34dbf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; @@ -211,6 +212,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); set2.setScatterShape(ScatterShape.CIRCLE); + set2.setScatterShapeHoleColor(Color.WHITE); + set2.setScatterShapeHoleRadius(5f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); set3.setScatterShape(ScatterShape.CROSS); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 89efe063d1..6c12f4dd96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -4,7 +4,6 @@ import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; @@ -95,7 +94,7 @@ public ScatterShape getScatterShape() { } /** - * Sets the radius of the hole in the shape + * Sets the radius of the hole in the shape. Set this to <= 0 to remove holes. * * @param holeRadius */ @@ -109,7 +108,7 @@ public float getScatterShapeHoleRadius() { } /** - * Sets the color for the hole in the shape + * Sets the color for the hole in the shape. Set to ColorTemplate.COLOR_NONE (-1) to remove holes. * * @param holeColor */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 37a1672ac6..90a3903825 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -105,7 +105,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, mRenderPaint); - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + if (shapeHoleColor != ColorTemplate.COLOR_NONE && shapeHoleSize > 0f) { mRenderPaint.setStyle(Style.FILL); mRenderPaint.setColor(shapeHoleColor); @@ -152,7 +152,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { shapeHoleSizeHalf + shapeStrokeSizeHalf, mRenderPaint); - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + if (shapeHoleColor != ColorTemplate.COLOR_NONE && shapeHoleSize > 0f) { mRenderPaint.setStyle(Style.FILL); mRenderPaint.setColor(shapeHoleColor); From 8703a0b88645be9d40683a740852e6c4d75e0b62 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Feb 2016 17:47:52 +0100 Subject: [PATCH 0734/1390] Example adjustments --- .../com/xxmassdeveloper/mpchartexample/BarChartActivity.java | 4 +++- .../mpchartexample/BarChartActivityMultiDataset.java | 1 + .../xxmassdeveloper/mpchartexample/BubbleChartActivity.java | 1 + .../mpchartexample/CombinedChartActivity.java | 2 ++ .../mpchartexample/HorizontalBarChartActivity.java | 2 ++ .../mpchartexample/InvertedLineChartActivity.java | 1 + .../xxmassdeveloper/mpchartexample/ScatterChartActivity.java | 1 + .../xxmassdeveloper/mpchartexample/StackedBarActivity.java | 5 +++-- .../mpchartexample/fragments/BarChartFrag.java | 1 + .../mpchartexample/fragments/ComplexityFragment.java | 1 + .../mpchartexample/listviewitems/BarChartItem.java | 2 ++ .../mpchartexample/listviewitems/LineChartItem.java | 2 ++ 12 files changed, 20 insertions(+), 3 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 1b80881596..2ced16b1f6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -96,6 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); leftAxis.setSpaceTop(15f); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); @@ -103,6 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); + rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) Legend l = mChart.getLegend(); l.setPosition(LegendPosition.BELOW_CHART_LEFT); @@ -244,7 +246,7 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = (range + 1); - float val = -10; //(float) (Math.random() * mult); + float val = (float) (Math.random() * mult); yVals1.add(new BarEntry(val, i)); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 92046405dd..4f869ecc3a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -99,6 +99,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); leftAxis.setSpaceTop(30f); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index fa6568f8f2..0943315341 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -86,6 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { yl.setTypeface(tf); yl.setSpaceTop(30f); yl.setSpaceBottom(30f); + yl.setDrawZeroLine(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index b7e45e865d..1cc5a5d9ab 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -58,9 +58,11 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); + rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setDrawGridLines(false); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index a23fb51432..93deb45198 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -97,12 +97,14 @@ protected void onCreate(Bundle savedInstanceState) { yl.setDrawAxisLine(true); yl.setDrawGridLines(true); yl.setGridLineWidth(0.3f); + yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); YAxis yr = mChart.getAxisRight(); yr.setTypeface(tf); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); + yr.setAxisMinValue(0f); // this replaces setStartAtZero(true) // yr.setInverted(true); setData(12, 50); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 36c0a5f3dd..26f8e9719b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -88,6 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setInverted(true); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 11163ef041..fa72f64e33 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -84,6 +84,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); + yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 9a65c5913d..8356c5bcb6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -72,8 +72,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValueAboveBar(false); // change the position of the y-labels - YAxis yLabels = mChart.getAxisLeft(); - yLabels.setValueFormatter(new MyYAxisValueFormatter()); + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setValueFormatter(new MyYAxisValueFormatter()); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); XAxis xLabels = mChart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 98e368a4db..29b378d44b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -52,6 +52,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 98b904b2b7..8213f4f017 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -41,6 +41,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index dabdb9a2a8..70463a7534 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -62,11 +62,13 @@ public View getView(int position, View convertView, Context c) { leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(20f); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(20f); + rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChartData.setValueTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 1e2ab2301f..e43b64d1bd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -62,11 +62,13 @@ public View getView(int position, View convertView, Context c) { YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); rightAxis.setDrawGridLines(false); + rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) // set data holder.chart.setData((LineData) mChartData); From 2a55eaceca960ebae3a489f0418bec4b5410c4a0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 16:53:32 +0100 Subject: [PATCH 0735/1390] Update candlestickchart screenshot --- .../mikephil/charting/components/YAxis.java | 3 ++- screenshots/candlestickchart.png | Bin 41297 -> 78079 bytes screenshots/candlestickchart_old.png | Bin 0 -> 41297 bytes 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 screenshots/candlestickchart_old.png diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 31ff1cf0a0..ce0f19f0a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -259,7 +259,8 @@ public boolean isInverted() { } /** - * This method is deprecated - Use setAxisMinValue(...) instead. + * This method is deprecated. + * Use setAxisMinValue(...) / setAxisMaxValue(...) instead. * * @param startAtZero */ diff --git a/screenshots/candlestickchart.png b/screenshots/candlestickchart.png index e12f8c2893e6c147319d5fd6cf6932d5877408fb..633de36e80413108250124ec242909e95ce0015f 100644 GIT binary patch delta 75967 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

    ;nXf)x%qHg7X|O>SNtq)DHv<8k&; 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

    HXAwy`VN>s#+INuyfq?TOS_o`yY({EdL^=UOJ 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 F;$K}Pnl%6b diff --git a/screenshots/candlestickchart_old.png b/screenshots/candlestickchart_old.png new file mode 100644 index 0000000000000000000000000000000000000000..e12f8c2893e6c147319d5fd6cf6932d5877408fb GIT binary patch literal 41297 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 F;$K}Pnl%6b literal 0 HcmV?d00001 From c53917a6d66a1d5fb196cfdf14959b69d0bdef8a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 16:54:37 +0100 Subject: [PATCH 0736/1390] Update ScatterDataSet documentation --- .../charting/data/ScatterDataSet.java | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 6c12f4dd96..4f91420c81 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -108,7 +108,7 @@ public float getScatterShapeHoleRadius() { } /** - * Sets the color for the hole in the shape. Set to ColorTemplate.COLOR_NONE (-1) to remove holes. + * Sets the color for the hole in the shape. * * @param holeColor */ @@ -120,25 +120,4 @@ public void setScatterShapeHoleColor(int holeColor) { public int getScatterShapeHoleColor() { return mScatterShapeHoleColor; } - -// /** -// * Sets a path object as the shape to be drawn where the values are at. Do -// * not forget to call setScatterShape(...) and set the shape to -// * ScatterShape.CUSTOM. -// * -// * @param shape -// */ -// public void setCustomScatterShape(Path shape) { -// mCustomScatterPath = shape; -// } -// -// /** -// * returns the custom path / shape that is specified to be drawn where the -// * values are at -// * -// * @return -// */ -// public Path getCustomScatterShape() { -// return mCustomScatterPath; -// } } From 9104e775953fef26787c1ead5b6ee7fc163de00b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 16:56:25 +0100 Subject: [PATCH 0737/1390] Remove redundant if-check --- .../mikephil/charting/renderer/ScatterChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 90a3903825..37a1672ac6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -105,7 +105,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, mRenderPaint); - if (shapeHoleColor != ColorTemplate.COLOR_NONE && shapeHoleSize > 0f) { + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { mRenderPaint.setStyle(Style.FILL); mRenderPaint.setColor(shapeHoleColor); @@ -152,7 +152,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { shapeHoleSizeHalf + shapeStrokeSizeHalf, mRenderPaint); - if (shapeHoleColor != ColorTemplate.COLOR_NONE && shapeHoleSize > 0f) { + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { mRenderPaint.setStyle(Style.FILL); mRenderPaint.setColor(shapeHoleColor); From 71c67892ff601ac083da6c2070d4995b0d68b348 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 17:04:19 +0100 Subject: [PATCH 0738/1390] Minor changes for negative zero fix --- .../mikephil/charting/renderer/YAxisRenderer.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index a26624f8dc..cfd46fed07 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -143,14 +143,11 @@ protected void computeAxisValues(float min, float max) { mYAxis.mEntries = new float[n]; } - f = first; - Double d = new Double(f); + for (f = first, i = 0; i < n; f += interval, ++i) { - // check negative zero - mYAxis.mEntries[0] = (float) (d.equals(-0.0) ? Math.abs(f) : f); - f += interval; + if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) + f = 0.0; - for (i = 1; i < n; f += interval, ++i) { mYAxis.mEntries[i] = (float) f; } } @@ -297,7 +294,7 @@ public void renderGridLines(Canvas c) { position[1] = 0f; mTrans.pointValuesToPixel(position); - drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1]-1, position[1]-1); + drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1] - 1, position[1] - 1); } } From bdac14c83c48b7f372f50a0659b7335f33a682c8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 17:07:52 +0100 Subject: [PATCH 0739/1390] New candlestickchart screenshot --- .../CandleStickChartActivity.java | 1 + screenshots/candlestickchart.png | Bin 78079 -> 34019 bytes 2 files changed, 1 insertion(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index af5eb39e62..36211e175c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -48,6 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mChart = (CandleStickChart) findViewById(R.id.chart1); + mChart.setBackgroundColor(Color.WHITE); mChart.setDescription(""); diff --git a/screenshots/candlestickchart.png b/screenshots/candlestickchart.png index 633de36e80413108250124ec242909e95ce0015f..0dce18ab3eda20c6f0bcfbf6749a71228cc36cfd 100644 GIT binary patch delta 31539 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

    )I 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 From 92e60e5eedfdfa93a2851e0a1bb3544d07f12ec8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Feb 2016 21:16:14 +0100 Subject: [PATCH 0740/1390] Add feature for equal slice-spaces from center to outside (#444). --- .../mpchartexample/PieChartActivity.java | 2 +- .../mikephil/charting/data/PieDataSet.java | 20 ++++----- .../interfaces/datasets/IPieDataSet.java | 2 +- .../charting/renderer/PieChartRenderer.java | 42 +++++++++++++++---- 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index d7d19164d0..941705871c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -197,7 +197,7 @@ private void setData(int count, float range) { xVals.add(mParties[i % mParties.length]); PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); - dataSet.setSliceSpace(2f); + dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); // add a lot of colors diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index 2fe974b76b..3f4b555da4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -9,7 +9,7 @@ public class PieDataSet extends DataSet implements IPieDataSet { - /** the space in degrees between the chart-slices, default 0f */ + /** the space in pixels between the chart-slices, default 0f */ private float mSliceSpace = 0f; /** indicates the selection distance of a pie slice */ @@ -37,19 +37,19 @@ public DataSet copy() { } /** - * sets the space that is left out between the piechart-slices, default: 0° - * --> no space, maximum 45, minimum 0 (no space) + * Sets the space that is left out between the piechart-slices in dp. + * Default: 0 --> no space, maximum 20f * - * @param degrees + * @param spaceDp */ - public void setSliceSpace(float degrees) { + public void setSliceSpace(float spaceDp) { - if (degrees > 45) - degrees = 45f; - if (degrees < 0) - degrees = 0f; + if (spaceDp > 20) + spaceDp = 20f; + if (spaceDp < 0) + spaceDp = 0f; - mSliceSpace = degrees; + mSliceSpace = Utils.convertDpToPixel(spaceDp); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index f431d21a18..b8f85922b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -9,7 +9,7 @@ public interface IPieDataSet extends IDataSet { /** * Returns the space that is set to be between the piechart-slices of this - * DataSet, in degrees. + * DataSet, in pixels. * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 3f35ea542e..8f166b8a4c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -9,6 +9,8 @@ import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.PointF; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.Build; import android.text.Layout; @@ -40,6 +42,8 @@ public class PieChartRenderer extends DataRenderer { protected Paint mHolePaint; protected Paint mTransparentCirclePaint; + protected Paint mSliceSpacePaint; + /** * paint object for the text that can be displayed in the center of the * chart @@ -75,11 +79,15 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); - //mCenterTextPaint.setTextAlign(Align.CENTER); mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); mValuePaint.setColor(Color.WHITE); mValuePaint.setTextAlign(Align.CENTER); + + mSliceSpacePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mSliceSpacePaint.setStyle(Style.STROKE); + mSliceSpacePaint.setColor(0xFFFFFFFF); // transparent + mSliceSpacePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } public Paint getPaintHole() { @@ -130,6 +138,11 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, IPieDataSet dataSet) { + float sliceSpace = dataSet.getSliceSpace(); + mSliceSpacePaint.setStrokeWidth(sliceSpace); + + PointF center = mChart.getCenterOffsets(); + float angle = 0; float rotationAngle = mChart.getRotationAngle(); @@ -141,7 +154,6 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { for (int j = 0; j < dataSet.getEntryCount(); j++) { float sliceAngle = drawAngles[j]; - float sliceSpace = dataSet.getSliceSpace(); Entry e = dataSet.getEntryForIndex(j); @@ -153,14 +165,28 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawArc(mChart.getCircleBox(), - rotationAngle + (angle + sliceSpace / 2f) * phaseY, - (sliceAngle - sliceSpace / 2f) * phaseY, + rotationAngle + angle * phaseY, + sliceAngle * phaseY, true, mRenderPaint); } } + // draw the slice space + if(sliceSpace > 0 && dataSet.getEntryCount() > 1) { + + PointF pos = Utils.getPosition(center, mChart.getRadius(), rotationAngle * phaseX + angle * phaseY); + mBitmapCanvas.drawLine(center.x, center.y, pos.x, pos.y, mSliceSpacePaint); + } + angle += sliceAngle * phaseX; } + + // cover the final slice with slice space + if(sliceSpace > 0 && dataSet.getEntryCount() > 1) { + + PointF pos = Utils.getPosition(center, mChart.getRadius(), rotationAngle * phaseX + angle * phaseY); + mBitmapCanvas.drawLine(center.x, center.y, pos.x, pos.y, mSliceSpacePaint); + } } @Override @@ -221,10 +247,9 @@ public void drawValues(Canvas c) { angle = absoluteAngles[xIndex - 1] * phaseX; final float sliceAngle = drawAngles[xIndex]; - final float sliceSpace = dataSet.getSliceSpace(); // offset needed to center the drawn text in the slice - final float offset = (sliceAngle - sliceSpace / 2.f) / 2.f; + final float offset = (sliceAngle) / 2.f; angle = angle + offset; @@ -407,7 +432,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { angle = absoluteAngles[xIndex - 1] * phaseX; float sliceAngle = drawAngles[xIndex]; - float sliceSpace = set.getSliceSpace(); float shift = set.getSelectionShift(); RectF circleBox = mChart.getCircleBox(); @@ -428,8 +452,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // redefine the rect that contains the arc so that the // highlighted pie is not cut off mBitmapCanvas.drawArc(highlighted, - rotationAngle + (angle + sliceSpace / 2f) * phaseY, - (sliceAngle - sliceSpace / 2f) * phaseY, + rotationAngle + angle * phaseY, + sliceAngle * phaseY, true, mRenderPaint); } } From 9c92003c3e8d1319f6501250f84ca11ac616134e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 15 Feb 2016 10:42:56 +0100 Subject: [PATCH 0741/1390] PieChart fixes for realm dataset --- .../realm/implementation/RealmPieDataSet.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index c6d9116e66..c11518bc54 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -15,7 +15,7 @@ public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { /** - * the space in degrees between the chart-slices, default 0f + * the space in pixels between the chart-slices, default 0f */ private float mSliceSpace = 0f; @@ -77,19 +77,19 @@ public void build(RealmResults results) { } /** - * sets the space that is left out between the piechart-slices, default: 0° - * --> no space, maximum 45, minimum 0 (no space) + * Sets the space that is left out between the piechart-slices in dp. + * Default: 0 --> no space, maximum 20f * - * @param degrees + * @param spaceDp */ - public void setSliceSpace(float degrees) { + public void setSliceSpace(float spaceDp) { - if (degrees > 45) - degrees = 45f; - if (degrees < 0) - degrees = 0f; + if (spaceDp > 20) + spaceDp = 20f; + if (spaceDp < 0) + spaceDp = 0f; - mSliceSpace = degrees; + mSliceSpace = Utils.convertDpToPixel(spaceDp); } @Override From 4f1f5bc3ef3a95c22b126633f8b98219b69ab85b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 16 Feb 2016 16:34:49 +0100 Subject: [PATCH 0742/1390] Code & example cleanup --- MPChartExample/res/menu/bar.xml | 4 -- MPChartExample/res/menu/bubble.xml | 4 -- MPChartExample/res/menu/draw.xml | 4 -- MPChartExample/res/menu/line.xml | 4 -- MPChartExample/res/menu/scatter.xml | 4 -- .../mpchartexample/AnotherBarActivity.java | 12 ------ .../mpchartexample/BarChartActivity.java | 12 ------ .../mpchartexample/BarChartActivitySinus.java | 12 ------ .../mpchartexample/BubbleChartActivity.java | 12 ------ .../CubicLineChartActivity.java | 13 ------ .../HorizontalBarChartActivity.java | 12 ------ .../InvertedLineChartActivity.java | 13 ------ .../mpchartexample/LineChartActivity1.java | 13 ------ .../mpchartexample/LineChartActivity2.java | 13 ------ .../MultiLineChartActivity.java | 13 ------ .../mpchartexample/ScatterChartActivity.java | 12 ------ .../mpchartexample/StackedBarActivity.java | 12 ------ .../StackedBarActivityNegative.java | 12 ------ .../mikephil/charting/charts/BarChart.java | 26 +----------- .../charting/charts/BarLineChartBase.java | 40 +------------------ .../mikephil/charting/charts/Chart.java | 38 +++--------------- .../charting/charts/CombinedChart.java | 2 +- .../YAxisRendererHorizontalBarChart.java | 1 - 23 files changed, 9 insertions(+), 279 deletions(-) diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index a65c8730e8..2cce21aacf 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -29,10 +29,6 @@ android:id="@+id/actionToggleAdjustXLegend" android:title="Toggle AdjustXLegend"> - - diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/res/menu/bubble.xml index a100c5085d..a25afd9861 100644 --- a/MPChartExample/res/menu/bubble.xml +++ b/MPChartExample/res/menu/bubble.xml @@ -25,10 +25,6 @@ android:id="@+id/animateXY" android:title="Animate XY"> - - diff --git a/MPChartExample/res/menu/draw.xml b/MPChartExample/res/menu/draw.xml index 3965a75607..50f35239e7 100644 --- a/MPChartExample/res/menu/draw.xml +++ b/MPChartExample/res/menu/draw.xml @@ -21,10 +21,6 @@ android:id="@+id/actionToggleAdjustXLegend" android:title="Toggle AdjustXLegend"> - - diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index 5d248a4145..42ca211c06 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -37,10 +37,6 @@ android:id="@+id/actionToggleAdjustXLegend" android:title="Toggle AdjustXLegend"> - - diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/res/menu/scatter.xml index a100c5085d..a25afd9861 100644 --- a/MPChartExample/res/menu/scatter.xml +++ b/MPChartExample/res/menu/scatter.xml @@ -25,10 +25,6 @@ android:id="@+id/animateXY" android:title="Animate XY"> - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index edf3409c01..cabd72e9dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -147,18 +147,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 2ced16b1f6..99d3d027fd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -188,18 +188,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index a84281e9d6..62d9b43096 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -169,18 +169,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(2000, 2000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 0943315341..03d97ed812 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -133,18 +133,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 48731d868e..31f951a379 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -198,19 +198,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 93deb45198..3027188cf5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -190,18 +190,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 26f8e9719b..2f92912e60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -201,19 +201,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 4a6f2826c0..99f096f66e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -270,19 +270,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index da49cd89b1..8d1396ede1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -228,19 +228,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 5ff37be451..05e25fae64 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -155,19 +155,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleFilter: { - - // the angle of filtering is 35° - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 35); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index fa72f64e33..e716f7ff47 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -137,18 +137,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 8356c5bcb6..77c6d1f23f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -161,18 +161,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 77ccfd5199..d25ee39f2b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -175,18 +175,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } case R.id.actionSave: { if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index c2dc39b3c3..19aaa2fe54 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -10,8 +10,8 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; @@ -30,11 +30,6 @@ public class BarChart extends BarLineChartBase implements BarDataProvid */ private boolean mDrawValueAboveBar = true; - /** - * if set to true, all values of a stack are drawn individually, and not just their sum - */ - // private boolean mDrawValuesForWholeStack = true; - /** * if set to true, a grey area is drawn behind each bar that indicates the maximum value */ @@ -166,25 +161,6 @@ public boolean isDrawValueAboveBarEnabled() { return mDrawValueAboveBar; } - // /** - // * if set to true, all values of a stack are drawn individually, and not - // * just their sum - // * - // * @param enabled - // */ - // public void setDrawValuesForWholeStack(boolean enabled) { - // mDrawValuesForWholeStack = enabled; - // } - // - // /** - // * returns true if all values of a stack are drawn, and not just their sum - // * - // * @return - // */ - // public boolean isDrawValuesForWholeStackEnabled() { - // return mDrawValuesForWholeStack; - // } - /** * If set to true, a grey area is drawn behind each bar that indicates the maximum value. Enabling his will reduce * performance by about 50%. diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 172318437f..fa6e75750f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -22,7 +22,6 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; @@ -84,11 +83,6 @@ public abstract class BarLineChartBase Date: Wed, 17 Feb 2016 09:59:31 +0100 Subject: [PATCH 0743/1390] Fix issue related to value-text colors (issue #1478). --- .../github/mikephil/charting/charts/CombinedChart.java | 2 +- .../com/github/mikephil/charting/data/BaseDataSet.java | 2 ++ .../charting/renderer/HorizontalBarChartRenderer.java | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index dd9d008645..caa011203a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -11,12 +11,12 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.renderer.CombinedChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index a318c1d3ec..3d816c0f34 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -110,6 +110,8 @@ public List getColors() { return mColors; } + public List getValueColors() { return mValueColors; } + @Override public int getColor() { return mColors.get(0); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index fe2178b33b..facccc945c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -150,7 +150,7 @@ public void drawValues(Canvas c) { } drawValue(c, formattedValue, valuePoints[j] + (val >= 0 ? posOffset : negOffset), - valuePoints[j + 1] + halfTextHeight); + valuePoints[j + 1] + halfTextHeight, dataSet.getValueTextColor(j / 2)); } // if each value of a potential stack should be drawn @@ -191,7 +191,7 @@ public void drawValues(Canvas c) { drawValue(c, formattedValue, valuePoints[j] + (e.getVal() >= 0 ? posOffset : negOffset), - valuePoints[j + 1] + halfTextHeight); + valuePoints[j + 1] + halfTextHeight, dataSet.getValueTextColor(j / 2)); } else { @@ -246,7 +246,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(y)) continue; - drawValue(c, formattedValue, x, y + halfTextHeight); + drawValue(c, formattedValue, x, y + halfTextHeight, dataSet.getValueTextColor(j / 2)); } } } @@ -255,7 +255,8 @@ public void drawValues(Canvas c) { } } - protected void drawValue(Canvas c, String valueText, float x, float y) { + protected void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); c.drawText(valueText, x, y, mValuePaint); } From daa0115ab5712f67e5c24a7fb26e9c0eabd0e057 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 17 Feb 2016 18:12:06 +0200 Subject: [PATCH 0744/1390] Minor docs update --- .../src/com/github/mikephil/charting/data/ScatterDataSet.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 4f91420c81..199a20638b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -94,7 +94,8 @@ public ScatterShape getScatterShape() { } /** - * Sets the radius of the hole in the shape. Set this to <= 0 to remove holes. + * Sets the radius of the hole in the shape (applies to Square, Circle and Triangle) + * Set this to <= 0 to remove holes. * * @param holeRadius */ From d1fb7bbe95f1d798e033a752c27e8ba1da19ae94 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 17 Feb 2016 18:31:38 +0200 Subject: [PATCH 0745/1390] Update BarLineChartBase.java --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 1 - 1 file changed, 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index fa6e75750f..4430fda0cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -371,7 +371,6 @@ protected void calcMinMax() { mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - // Consider sticking one of the edges of the axis to zero (0.0) // Use the values as they are mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); From dcb20889ba3635d3d2697c81d70381e17bba0046 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 17 Feb 2016 21:56:31 +0200 Subject: [PATCH 0746/1390] Improvements for drawing pie slices Xfer tricks not needed anymore - we only draw what we need! --- .../charting/renderer/PieChartRenderer.java | 181 ++++++++++++------ 1 file changed, 127 insertions(+), 54 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 8f166b8a4c..93eb9e1997 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -9,8 +9,6 @@ import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.PointF; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.os.Build; import android.text.Layout; @@ -42,8 +40,6 @@ public class PieChartRenderer extends DataRenderer { protected Paint mHolePaint; protected Paint mTransparentCirclePaint; - protected Paint mSliceSpacePaint; - /** * paint object for the text that can be displayed in the center of the * chart @@ -83,11 +79,6 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); mValuePaint.setColor(Color.WHITE); mValuePaint.setTextAlign(Align.CENTER); - - mSliceSpacePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mSliceSpacePaint.setStyle(Style.STROKE); - mSliceSpacePaint.setColor(0xFFFFFFFF); // transparent - mSliceSpacePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); } public Paint getPaintHole() { @@ -136,12 +127,10 @@ public void drawData(Canvas c) { } } - protected void drawDataSet(Canvas c, IPieDataSet dataSet) { - - float sliceSpace = dataSet.getSliceSpace(); - mSliceSpacePaint.setStrokeWidth(sliceSpace); + private Path mPathBuffer = new Path(); + private RectF mInnerRectBuffer = new RectF(); - PointF center = mChart.getCenterOffsets(); + protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = 0; float rotationAngle = mChart.getRotationAngle(); @@ -149,11 +138,29 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - float[] drawAngles = mChart.getDrawAngles(); + final RectF circleBox = mChart.getCircleBox(); - for (int j = 0; j < dataSet.getEntryCount(); j++) { + final int entryCount = dataSet.getEntryCount(); + final float[] drawAngles = mChart.getDrawAngles(); + final PointF center = mChart.getCenterCircleBox(); + final float radius = mChart.getRadius(); + final float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + ? radius * (mChart.getHoleRadius() / 100.f) + : 0.f; + + // API < 21 does not receive floats in addArc, but a RectF + mInnerRectBuffer.set( + center.x - innerRadius, + center.y - innerRadius, + center.x + innerRadius, + center.y + innerRadius); + + for (int j = 0; j < entryCount; j++) { float sliceAngle = drawAngles[j]; + float sliceSpace = dataSet.getSliceSpace(); + final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); + final float sliceSpaceInnerAngle = sliceSpace / (Utils.FDEG2RAD * innerRadius); Entry e = dataSet.getEntryForIndex(j); @@ -164,28 +171,54 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mChart.getData().getIndexOfDataSet(dataSet))) { mRenderPaint.setColor(dataSet.getColor(j)); - mBitmapCanvas.drawArc(mChart.getCircleBox(), - rotationAngle + angle * phaseY, - sliceAngle * phaseY, - true, mRenderPaint); - } - } - // draw the slice space - if(sliceSpace > 0 && dataSet.getEntryCount() > 1) { + final float startAngleOuter = rotationAngle + (angle + sliceSpaceOuterAngle / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceOuterAngle) * phaseY; + if (sweepAngleOuter < 0.f) + { + sweepAngleOuter = 0.f; + } - PointF pos = Utils.getPosition(center, mChart.getRadius(), rotationAngle * phaseX + angle * phaseY); - mBitmapCanvas.drawLine(center.x, center.y, pos.x, pos.y, mSliceSpacePaint); - } + mPathBuffer.reset(); + + mPathBuffer.moveTo( + center.x + radius * (float)Math.cos(startAngleOuter * Utils.FDEG2RAD), + center.y + radius * (float)Math.sin(startAngleOuter * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + circleBox, + startAngleOuter, + sweepAngleOuter + ); + + if (innerRadius > 0.0) + { + final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; + if (sweepAngleInner < 0.f) + { + sweepAngleInner = 0.f; + } + final float endAngleInner = startAngleInner + sweepAngleInner; + + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } - angle += sliceAngle * phaseX; - } + mPathBuffer.close(); - // cover the final slice with slice space - if(sliceSpace > 0 && dataSet.getEntryCount() > 1) { + mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); + } + } - PointF pos = Utils.getPosition(center, mChart.getRadius(), rotationAngle * phaseX + angle * phaseY); - mBitmapCanvas.drawLine(center.x, center.y, pos.x, pos.y, mSliceSpacePaint); + angle += sliceAngle * phaseX; } } @@ -247,9 +280,11 @@ public void drawValues(Canvas c) { angle = absoluteAngles[xIndex - 1] * phaseX; final float sliceAngle = drawAngles[xIndex]; + final float sliceSpace = dataSet.getSliceSpace(); + final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * r); // offset needed to center the drawn text in the slice - final float offset = (sliceAngle) / 2.f; + final float offset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f; angle = angle + offset; @@ -348,7 +383,7 @@ protected void drawCenterText(Canvas c) { PointF center = mChart.getCenterCircleBox(); - float innerRadius = mChart.isDrawHoleEnabled() + float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); @@ -411,6 +446,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); + final PointF center = mChart.getCenterCircleBox(); + final float radius = mChart.getRadius(); + final float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + ? radius * (mChart.getHoleRadius() / 100.f) + : 0.f; + + final RectF highlightedCircleBox = new RectF(); for (int i = 0; i < indices.length; i++) { @@ -430,31 +472,62 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { angle = 0.f; else angle = absoluteAngles[xIndex - 1] * phaseX; - + float sliceAngle = drawAngles[xIndex]; + float sliceSpace = set.getSliceSpace(); + final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); + final float sliceSpaceInnerAngle = sliceSpace / (Utils.FDEG2RAD * innerRadius); float shift = set.getSelectionShift(); - RectF circleBox = mChart.getCircleBox(); - - /** - * Make the box containing current arc larger equally in every - * dimension, to preserve shape of arc. Code provided by: - * - * @link https://github.com/wogg - */ - RectF highlighted = new RectF(circleBox.left - shift, - circleBox.top - shift, - circleBox.right + shift, - circleBox.bottom + shift); + final float highlightedRadius = radius + shift; + highlightedCircleBox.set(mChart.getCircleBox()); + highlightedCircleBox.inset(-shift, -shift); mRenderPaint.setColor(set.getColor(xIndex)); - // redefine the rect that contains the arc so that the - // highlighted pie is not cut off - mBitmapCanvas.drawArc(highlighted, - rotationAngle + angle * phaseY, - sliceAngle * phaseY, - true, mRenderPaint); + final float startAngleOuter = rotationAngle + (angle + sliceSpaceOuterAngle / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceOuterAngle) * phaseY; + if (sweepAngleOuter < 0.f) + { + sweepAngleOuter = 0.f; + } + + mPathBuffer.reset(); + + mPathBuffer.moveTo( + center.x + highlightedRadius * (float)Math.cos(startAngleOuter * Utils.FDEG2RAD), + center.y + highlightedRadius * (float)Math.sin(startAngleOuter * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + highlightedCircleBox, + startAngleOuter, + sweepAngleOuter + ); + + if (innerRadius > 0.0) + { + final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; + if (sweepAngleInner < 0.f) + { + sweepAngleInner = 0.f; + } + final float endAngleInner = startAngleInner + sweepAngleInner; + + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } + + mPathBuffer.close(); + + mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); } } From acd8dc1337aa4a6d1962efb42d9b819b4faee721 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 18 Feb 2016 02:31:11 +0200 Subject: [PATCH 0747/1390] Improved transparentCircle for Pie Instead of using PorterDuffXfer to clear everything in the hole - we allow both hole color and transparentCircle to co-exist. Also now we allow to see through to the inner ends of the pie slices. --- .../mikephil/charting/charts/PieChart.java | 26 +++++------ .../charting/renderer/PieChartRenderer.java | 46 +++++++++++++------ 2 files changed, 43 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index efe8cabc35..93f120eda9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.renderer.PieChartRenderer; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import java.util.List; @@ -53,6 +54,11 @@ public class PieChart extends PieRadarChartBase { */ private boolean mDrawHole = true; + /** + * if true, the hole will see-through to the inner ends of the slices + */ + private boolean mDrawHoleTransparent = true; + /** * if true, the values inside the piechart are drawn as percent values */ @@ -332,25 +338,17 @@ public float[] getAbsoluteAngles() { * @param color */ public void setHoleColor(int color) { - ((PieChartRenderer) mRenderer).getPaintHole().setXfermode(null); + if (color == ColorTemplate.COLOR_NONE || color == ColorTemplate.COLOR_SKIP) { + color = 0; // Transparent + } ((PieChartRenderer) mRenderer).getPaintHole().setColor(color); } /** - * Set the hole in the center of the PieChart transparent. Thank you, code - * provided by: - * - * @param enable - * @link https://github.com/tbarthel-fr + * Set the hole in the center of the PieChart transparent. */ public void setHoleColorTransparent(boolean enable) { - if (enable) { - ((PieChartRenderer) mRenderer).getPaintHole().setColor(0xFFFFFFFF); - ((PieChartRenderer) mRenderer).getPaintHole().setXfermode( - new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - } else { - ((PieChartRenderer) mRenderer).getPaintHole().setXfermode(null); - } + mDrawHoleTransparent = enable; } /** @@ -360,7 +358,7 @@ public void setHoleColorTransparent(boolean enable) { * @return true if hole is transparent. */ public boolean isHoleTransparent() { - return ((PieChartRenderer) mRenderer).getPaintHole().getXfermode() != null; + return mDrawHoleTransparent; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 93eb9e1997..aac48b5ecf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -160,7 +160,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float sliceAngle = drawAngles[j]; float sliceSpace = dataSet.getSliceSpace(); final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); - final float sliceSpaceInnerAngle = sliceSpace / (Utils.FDEG2RAD * innerRadius); + final float sliceSpaceInnerAngle = innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); Entry e = dataSet.getEntryForIndex(j); @@ -211,6 +211,11 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { -sweepAngleInner ); } + else { + mPathBuffer.lineTo( + center.x, + center.y); + } mPathBuffer.close(); @@ -336,6 +341,8 @@ public void drawExtras(Canvas c) { drawCenterText(c); } + private Path mHoleCirclePath = new Path(); + /** * draws the hole in the center of the chart and the transparent circle / * hole @@ -344,30 +351,35 @@ protected void drawHole(Canvas c) { if (mChart.isDrawHoleEnabled()) { - float transparentCircleRadius = mChart.getTransparentCircleRadius(); - float holeRadius = mChart.getHoleRadius(); float radius = mChart.getRadius(); - + float holeRadius = radius * (mChart.getHoleRadius() / 100); PointF center = mChart.getCenterCircleBox(); + boolean hasHoleColor = mHolePaint.getColor() != 0; + + if (hasHoleColor) { + // draw the hole-circle + mBitmapCanvas.drawCircle( + center.x, center.y, + holeRadius, mHolePaint); + } // only draw the circle if it can be seen (not covered by the hole) - if (transparentCircleRadius > holeRadius) { + if (hasHoleColor && mChart.getTransparentCircleRadius() > mChart.getHoleRadius()) { - // get original alpha int alpha = mTransparentCirclePaint.getAlpha(); + float secondHoleRadius = radius * (mChart.getTransparentCircleRadius() / 100); + mTransparentCirclePaint.setAlpha((int) ((float) alpha * mAnimator.getPhaseX() * mAnimator.getPhaseY())); // draw the transparent-circle - mBitmapCanvas.drawCircle(center.x, center.y, - radius / 100 * transparentCircleRadius, mTransparentCirclePaint); + mHoleCirclePath.reset(); + mHoleCirclePath.addCircle(center.x, center.y, secondHoleRadius, Path.Direction.CW); + mHoleCirclePath.addCircle(center.x, center.y, holeRadius, Path.Direction.CCW); + mBitmapCanvas.drawPath(mHoleCirclePath, mTransparentCirclePaint); // reset alpha mTransparentCirclePaint.setAlpha(alpha); } - - // draw the hole-circle - mBitmapCanvas.drawCircle(center.x, center.y, - radius / 100 * holeRadius, mHolePaint); } } @@ -476,7 +488,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float sliceAngle = drawAngles[xIndex]; float sliceSpace = set.getSliceSpace(); final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); - final float sliceSpaceInnerAngle = sliceSpace / (Utils.FDEG2RAD * innerRadius); + final float sliceSpaceInnerAngle = innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); float shift = set.getSelectionShift(); final float highlightedRadius = radius + shift; @@ -504,8 +516,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { sweepAngleOuter ); - if (innerRadius > 0.0) - { + if (innerRadius > 0.0) { final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; if (sweepAngleInner < 0.f) @@ -524,6 +535,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { -sweepAngleInner ); } + else { + mPathBuffer.lineTo( + center.x, + center.y); + } mPathBuffer.close(); From 016b760df42872d96091d8d611b47562ce247f25 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 18 Feb 2016 14:42:57 +0100 Subject: [PATCH 0748/1390] Add documentation for chartinterface --- .../mpchartexample/LineChartActivity1.java | 3 ++- .../dataprovider/ChartInterface.java | 26 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 99f096f66e..a439e3afc1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -402,7 +402,8 @@ public void onChartTranslate(MotionEvent me, float dX, float dY) { @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); - Log.i("", "low: " + mChart.getLowestVisibleXIndex() + ", high: " + mChart.getHighestVisibleXIndex()); + Log.i("LOWHIGH", "low: " + mChart.getLowestVisibleXIndex() + ", high: " + mChart.getHighestVisibleXIndex()); + Log.i("MIN MAX", "xmin: " + mChart.getXChartMin() + ", xmax: " + mChart.getXChartMax() + ", ymin: " + mChart.getYChartMin() + ", ymax: " + mChart.getYChartMax()); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 5d060cb8a0..350d35e644 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -9,19 +9,39 @@ /** * Interface that provides everything there is to know about the dimensions, * bounds, and range of the chart. - * + * * @author Philipp Jahoda */ public interface ChartInterface { + /** + * Returns the minimum x-value of the chart, regardless of zoom or translation. + * + * @return + */ float getXChartMin(); + /** + * Returns the maximum x-value of the chart, regardless of zoom or translation. + * + * @return + */ float getXChartMax(); + /** + * Returns the minimum y-value of the chart, regardless of zoom or translation. + * + * @return + */ float getYChartMin(); + /** + * Returns the maximum y-value of the chart, regardless of zoom or translation. + * + * @return + */ float getYChartMax(); - + int getXValCount(); int getWidth(); @@ -33,7 +53,7 @@ public interface ChartInterface { PointF getCenterOffsets(); RectF getContentRect(); - + ValueFormatter getDefaultValueFormatter(); ChartData getData(); From b598ee14481364c87a0200f1a3331ed44761143c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 19 Feb 2016 14:47:28 +0200 Subject: [PATCH 0749/1390] Fixed drawing full circle without slice spacing --- .../charting/renderer/PieChartRenderer.java | 146 ++++++++++++------ 1 file changed, 102 insertions(+), 44 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index aac48b5ecf..890356bc98 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -142,6 +142,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { final int entryCount = dataSet.getEntryCount(); final float[] drawAngles = mChart.getDrawAngles(); + float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); final float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() @@ -155,12 +156,17 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { center.x + innerRadius, center.y + innerRadius); + int visibleAngleCount = 0; + for (int j = 0; j < entryCount; j++) { + // draw only if the value is greater than zero + if ((Math.abs(dataSet.getEntryForIndex(j).getVal()) > 0.000001)) { + visibleAngleCount++; + } + } + for (int j = 0; j < entryCount; j++) { float sliceAngle = drawAngles[j]; - float sliceSpace = dataSet.getSliceSpace(); - final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); - final float sliceSpaceInnerAngle = innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); Entry e = dataSet.getEntryForIndex(j); @@ -172,6 +178,9 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); + final float sliceSpaceOuterAngle = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * radius); final float startAngleOuter = rotationAngle + (angle + sliceSpaceOuterAngle / 2.f) * phaseY; float sweepAngleOuter = (sliceAngle - sliceSpaceOuterAngle) * phaseY; if (sweepAngleOuter < 0.f) @@ -181,18 +190,27 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mPathBuffer.reset(); - mPathBuffer.moveTo( - center.x + radius * (float)Math.cos(startAngleOuter * Utils.FDEG2RAD), - center.y + radius * (float)Math.sin(startAngleOuter * Utils.FDEG2RAD)); + if (sweepAngleOuter % 360f == 0.f) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); + } else { - mPathBuffer.arcTo( - circleBox, - startAngleOuter, - sweepAngleOuter - ); + mPathBuffer.moveTo( + center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), + center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + circleBox, + startAngleOuter, + sweepAngleOuter + ); + } if (innerRadius > 0.0) { + final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * innerRadius); final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; if (sweepAngleInner < 0.f) @@ -201,20 +219,30 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } final float endAngleInner = startAngleInner + sweepAngleInner; - mPathBuffer.lineTo( - center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), - center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + if (sweepAngleOuter % 360f == 0.f) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); + } else { - mPathBuffer.arcTo( - mInnerRectBuffer, - endAngleInner, - -sweepAngleInner - ); + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } } else { - mPathBuffer.lineTo( - center.x, - center.y); + + if (sweepAngleOuter % 360f != 0.f) { + mPathBuffer.lineTo( + center.x, + center.y); + } + } mPathBuffer.close(); @@ -480,15 +508,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; + final int entryCount = set.getEntryCount(); + int visibleAngleCount = 0; + for (int j = 0; j < entryCount; j++) { + // draw only if the value is greater than zero + if ((Math.abs(set.getEntryForIndex(j).getVal()) > 0.000001)) { + visibleAngleCount++; + } + } + if (xIndex == 0) angle = 0.f; else angle = absoluteAngles[xIndex - 1] * phaseX; - float sliceAngle = drawAngles[xIndex]; float sliceSpace = set.getSliceSpace(); - final float sliceSpaceOuterAngle = sliceSpace / (Utils.FDEG2RAD * radius); - final float sliceSpaceInnerAngle = innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); + + float sliceAngle = drawAngles[xIndex]; + final float sliceSpaceOuterAngle = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * radius); float shift = set.getSelectionShift(); final float highlightedRadius = radius + shift; @@ -506,17 +545,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mPathBuffer.reset(); - mPathBuffer.moveTo( - center.x + highlightedRadius * (float)Math.cos(startAngleOuter * Utils.FDEG2RAD), - center.y + highlightedRadius * (float)Math.sin(startAngleOuter * Utils.FDEG2RAD)); + if (sweepAngleOuter % 360f == 0.f) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, highlightedRadius, Path.Direction.CW); + } else { - mPathBuffer.arcTo( - highlightedCircleBox, - startAngleOuter, - sweepAngleOuter - ); + mPathBuffer.moveTo( + center.x + highlightedRadius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), + center.y + highlightedRadius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + highlightedCircleBox, + startAngleOuter, + sweepAngleOuter + ); + } if (innerRadius > 0.0) { + final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * innerRadius); final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; if (sweepAngleInner < 0.f) @@ -525,20 +573,30 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } final float endAngleInner = startAngleInner + sweepAngleInner; - mPathBuffer.lineTo( - center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), - center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + if (sweepAngleOuter % 360f == 0.f) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); + } else { - mPathBuffer.arcTo( - mInnerRectBuffer, - endAngleInner, - -sweepAngleInner - ); + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } } else { - mPathBuffer.lineTo( - center.x, - center.y); + + if (sweepAngleOuter % 360f != 0.f) { + mPathBuffer.lineTo( + center.x, + center.y); + } + } mPathBuffer.close(); From 72cabd15aa98c4c18fd99a6199e353853f1c6545 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 20 Feb 2016 11:25:34 +0100 Subject: [PATCH 0750/1390] Add feature to move the viewport to a specified position animated --- .../mpchartexample/LineChartActivity2.java | 8 +- .../charting/charts/BarLineChartBase.java | 99 ++++++++++++++----- .../mikephil/charting/charts/Chart.java | 15 +++ .../mikephil/charting/jobs/AnimatedJob.java | 46 +++++++++ .../charting/jobs/AnimatedMoveViewJob.java | 29 ++++++ .../charting/jobs/AnimatedZoomJob.java | 71 +++++++++++++ .../github/mikephil/charting/jobs/Job.java | 35 +++++++ .../mikephil/charting/jobs/MoveViewJob.java | 31 ++---- .../charting/utils/ViewPortHandler.java | 37 ++++++- 9 files changed, 319 insertions(+), 52 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/jobs/Job.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 8d1396ede1..b2e816147e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -23,12 +23,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -228,6 +226,7 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(3000, 3000); break; } + case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", @@ -327,6 +326,9 @@ private void setData(int count, float range) { @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); + + //mChart.centerViewToAnimated(e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); + //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 4430fda0cf..a6c97f24a9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -26,6 +26,8 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.jobs.AnimatedMoveViewJob; +import com.github.mikephil.charting.jobs.AnimatedZoomJob; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; @@ -683,6 +685,28 @@ public void zoom(float scaleX, float scaleY, float x, float y) { postInvalidate(); } + /** + * Zooms by the specified scale factor to the specified values on the specified axis. + * STILL WORK IN PROGRESS + * + * @param scaleX + * @param scaleY + * @param xValue + * @param yValue + * @param axis + * @param duration + */ + private void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { + + PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue - xsInView / 2f, yValue + valsInView / 2f, (float) bounds.x, (float) bounds.y, duration); + postJob(job); + } + /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. @@ -774,11 +798,7 @@ public void moveViewToX(float xIndex) { Runnable job = new MoveViewJob(mViewPortHandler, xIndex, 0f, getTransformer(AxisDependency.LEFT), this); - if (mViewPortHandler.hasChartDimens()) { - post(job); - } else { - mJobs.add(job); - } + postJob(job); } /** @@ -795,16 +815,12 @@ public void moveViewToY(float yValue, AxisDependency axis) { Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f, getTransformer(axis), this); - if (mViewPortHandler.hasChartDimens()) { - post(job); - } else { - mJobs.add(job); - } + postJob(job); } /** * This will move the left side of the current viewport to the specified - * x-index on the x-axis, and center the viewport to the specified y-value + * x-value on the x-axis, and center the viewport to the specified y-value * on the y-axis. * This also refreshes the chart by calling invalidate(). * @@ -819,23 +835,41 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { Runnable job = new MoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, getTransformer(axis), this); - if (mViewPortHandler.hasChartDimens()) { - post(job); - } else { - mJobs.add(job); - } + postJob(job); + } + + /** + * This will move the left side of the current viewport to the specified x-position + * and center the viewport to the specified y-position animated. + * This also refreshes the chart by calling invalidate(). + * + * @param xIndex + * @param yValue + * @param axis + * @param duration the duration of the animation in milliseconds + */ + public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { + + PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + + postJob(job); } /** * This will move the center of the current viewport to the specified - * x-index and y-value. + * x-value and y-value. * This also refreshes the chart by calling invalidate(). * * @param xIndex * @param yValue * @param axis - which axis should be used as a reference for the y-axis */ - public void centerViewTo(int xIndex, float yValue, AxisDependency axis) { + public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); @@ -844,11 +878,30 @@ public void centerViewTo(int xIndex, float yValue, AxisDependency axis) { xIndex - xsInView / 2f, yValue + valsInView / 2f, getTransformer(axis), this); - if (mViewPortHandler.hasChartDimens()) { - post(job); - } else { - mJobs.add(job); - } + postJob(job); + } + + /** + * This will move the center of the current viewport to the specified + * x-value and y-value animated. + * + * @param xIndex + * @param yValue + * @param axis + * @param duration the duration of the animation in milliseconds + */ + public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { + + PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, + xIndex - xsInView / 2f, yValue + valsInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + + postJob(job); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 5865943e43..1b6d617617 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1630,6 +1630,21 @@ public void clearAllJobs() { mJobs.clear(); } + /** + * Either posts a job immediately if the chart has already setup it's + * dimensions or adds the job to the execution queue. + * + * @param job + */ + protected void postJob(Runnable job) { + + if (mViewPortHandler.hasChartDimens()) { + post(job); + } else { + mJobs.add(job); + } + } + /** * Returns all jobs that are scheduled to be executed after * onSizeChanged(...). diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java new file mode 100644 index 0000000000..a9dfb2160d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java @@ -0,0 +1,46 @@ +package com.github.mikephil.charting.jobs; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.view.View; + +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 19/02/16. + */ +@SuppressLint("NewApi") +public abstract class AnimatedJob extends Job implements ValueAnimator.AnimatorUpdateListener { + + protected ObjectAnimator animator; + + protected float phase; + + protected float xOrigin; + protected float yOrigin; + + public AnimatedJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { + super(viewPortHandler, xValue, yValue, trans, v); + this.xOrigin = xOrigin; + this.yOrigin = yOrigin; + animator = ObjectAnimator.ofFloat(this, "phase", 0f, 1f); + animator.setDuration(duration); + animator.addUpdateListener(this); + } + + @SuppressLint("NewApi") + @Override + public void run() { + animator.start(); + } + + public float getPhase() { + return phase; + } + + public void setPhase(float phase) { + this.phase = phase; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java new file mode 100644 index 0000000000..d0d6708d8e --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java @@ -0,0 +1,29 @@ +package com.github.mikephil.charting.jobs; + +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.view.View; + +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 19/02/16. + */ +public class AnimatedMoveViewJob extends AnimatedJob { + + public AnimatedMoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { + super(viewPortHandler, xValue, yValue, trans, v, xOrigin, yOrigin, duration); + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + + pts[0] = xOrigin + (xValue - xOrigin) * phase; + pts[1] = yOrigin + (yValue - yOrigin) * phase; + + mTrans.pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, view); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java new file mode 100644 index 0000000000..aa47506da7 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -0,0 +1,71 @@ +package com.github.mikephil.charting.jobs; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.view.View; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 19/02/16. + */ +@SuppressLint("NewApi") +public class AnimatedZoomJob extends AnimatedJob implements Animator.AnimatorListener { + + protected float zoomOriginX; + protected float zoomOriginY; + + protected float zoomCenterX; + protected float zoomCenterY; + + @SuppressLint("NewApi") + public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { + super(viewPortHandler, scaleX, scaleY, trans, v, xOrigin, yOrigin, duration); + + this.zoomCenterX = zoomCenterX; + this.zoomCenterY = zoomCenterY; + this.zoomOriginX = zoomOriginX; + this.zoomOriginY = zoomOriginY; + this.animator.addListener(this); + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + + float scaleX = xOrigin + (xValue - xOrigin) * phase; + float scaleY = yOrigin + (yValue - yOrigin) * phase; + + pts[0] = zoomOriginX + (zoomCenterX - zoomOriginX) * phase; + pts[1] = zoomOriginY + (zoomCenterY - zoomOriginY) * phase; + + mTrans.pointValuesToPixel(pts); + + //Matrix save = mViewPortHandler.zoomAndCenter(xValue * phase, yValue * phase, zoomCenterX * phase, zoomCenterY * phase); + + mViewPortHandler.zoomAndCenter(scaleX, scaleY, pts, view);//zoomOriginX + (zoomCenterX - zoomOriginX) * phase, zoomOriginY + (zoomCenterY - zoomOriginY) * phase); + } + + @Override + public void onAnimationEnd(Animator animation) { + ((BarLineChartBase) view).calculateOffsets(); + view.postInvalidate(); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + + @Override + public void onAnimationStart(Animator animation) { + + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/Job.java b/MPChartLib/src/com/github/mikephil/charting/jobs/Job.java new file mode 100644 index 0000000000..607779cec3 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/Job.java @@ -0,0 +1,35 @@ + +package com.github.mikephil.charting.jobs; + +import android.view.View; + +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Runnable that is used for viewport modifications since they cannot be + * executed at any time. This can be used to delay the execution of viewport + * modifications until the onSizeChanged(...) method of the chartview is called. + * + * @author Philipp Jahoda + */ +public abstract class Job implements Runnable { + + protected float[] pts = new float[2]; + + protected ViewPortHandler mViewPortHandler; + protected float xValue = 0f; + protected float yValue = 0f; + protected Transformer mTrans; + protected View view; + + public Job(ViewPortHandler viewPortHandler, float xValue, float yValue, + Transformer trans, View v) { + + this.mViewPortHandler = viewPortHandler; + this.xValue = xValue; + this.yValue = yValue; + this.mTrans = trans; + this.view = v; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java index 8fddd48858..91e9be2a08 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java @@ -7,36 +7,19 @@ import com.github.mikephil.charting.utils.ViewPortHandler; /** - * Runnable that is used for viewport modifications since they cannot be - * executed at any time. This can be used to delay the execution of viewport - * modifications until the onSizeChanged(...) method of the chartview is called. - * - * @author Philipp Jahoda + * Created by Philipp Jahoda on 19/02/16. */ -public class MoveViewJob implements Runnable { - - protected ViewPortHandler mViewPortHandler; - protected float xIndex = 0f; - protected float yValue = 0f; - protected Transformer mTrans; - protected View view; - - public MoveViewJob(ViewPortHandler viewPortHandler, float xIndex, float yValue, - Transformer trans, View v) { - - this.mViewPortHandler = viewPortHandler; - this.xIndex = xIndex; - this.yValue = yValue; - this.mTrans = trans; - this.view = v; +public class MoveViewJob extends Job { + + public MoveViewJob(ViewPortHandler viewPortHandler, float xIndex, float yValue, Transformer trans, View v) { + super(viewPortHandler, xIndex, yValue, trans, v); } @Override public void run() { - float[] pts = new float[] { - xIndex, yValue - }; + pts[0] = xValue; + pts[1] = yValue; mTrans.pointValuesToPixel(pts); mViewPortHandler.centerViewPort(pts, view); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index a0384a8c51..33bd8e462c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -223,13 +223,46 @@ public Matrix zoom(float scaleX, float scaleY, float x, float y) { Matrix save = new Matrix(); save.set(mMatrixTouch); - // Log.i(LOG_TAG, "Zooming, x: " + x + ", y: " + y); - save.postScale(scaleX, scaleY, x, y); return save; } + public Matrix zoom(float scaleX, float scaleY) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.setScale(scaleX, scaleY); + + return save; + } + + /** + * Zooms by the specified scale factors and moves the viewport to the specified values. + * + * @param scaleX + * @param scaleY + * @param pts + * @param view + * @return + */ + public synchronized Matrix zoomAndCenter(float scaleX, float scaleY, float[] pts, final View view) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + final float x = pts[0] - offsetLeft(); + final float y = pts[1] - offsetTop(); + + PointF center = getContentCenter(); + + save.setScale(scaleX, scaleY, center.x, center.y); + save.postTranslate(-x, -y); + + return refresh(save, view, true); + } + /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. From 9278b3d3298361dd5b674974bd3523e9bfdc8a80 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 21 Feb 2016 00:56:41 +0200 Subject: [PATCH 0751/1390] Added calculation of minimum inner radius for proper spacing This also allows for animating the spacing :-) --- .../charting/renderer/PieChartRenderer.java | 101 +++++++++++++++--- 1 file changed, 88 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 890356bc98..2caf60439b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -130,6 +130,48 @@ public void drawData(Canvas c) { private Path mPathBuffer = new Path(); private RectF mInnerRectBuffer = new RectF(); + protected float calculateMinimumRadiusForSpacedSlice( + PointF center, + float radius, + float angle, + float arcStartPointX, + float arcStartPointY, + float startAngle, + float sweepAngle) + { + final float angleMiddle = startAngle + sweepAngle / 2.f; + + // Other point of the arc + float arcEndPointX = center.x + radius * (float) Math.cos((startAngle + sweepAngle) * Utils.FDEG2RAD); + float arcEndPointY = center.y + radius * (float) Math.sin((startAngle + sweepAngle) * Utils.FDEG2RAD); + + // Middle point on the arc + float arcMidPointX = center.x + radius * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); + float arcMidPointY = center.y + radius * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); + + // Middle point on straight line between the two point. + // This is the base of the contained triangle + double basePointsDistance = Math.sqrt( + Math.pow(arcEndPointX - arcStartPointX, 2) + + Math.pow(arcEndPointY - arcStartPointY, 2)); + + // After reducing space from both sides of the "slice", + // the angle of the contained triangle should stay the same. + // So let's find out the height of that triangle. + float containedTriangleHeight = (float)(basePointsDistance / 2.0 * + Math.tan((180.0 - angle) / 2.0 * Utils.DEG2RAD)); + + // Now we subtract that from the radius + float spacedRadius = radius - containedTriangleHeight; + + // And now subtract the height of the arc that's between the triangle and the outer circle + spacedRadius -= Math.sqrt( + Math.pow(arcMidPointX - (arcEndPointX + arcStartPointX) / 2.f, 2) + + Math.pow(arcMidPointY - (arcEndPointY + arcStartPointY) / 2.f, 2)); + + return spacedRadius; + } + protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = 0; @@ -145,17 +187,10 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; - // API < 21 does not receive floats in addArc, but a RectF - mInnerRectBuffer.set( - center.x - innerRadius, - center.y - innerRadius, - center.x + innerRadius, - center.y + innerRadius); - int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { // draw only if the value is greater than zero @@ -167,6 +202,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { for (int j = 0; j < entryCount; j++) { float sliceAngle = drawAngles[j]; + float innerRadius = userInnerRadius; Entry e = dataSet.getEntryForIndex(j); @@ -190,14 +226,17 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mPathBuffer.reset(); + float arcStartPointX = 0.f, arcStartPointY = 0.f; + if (sweepAngleOuter % 360f == 0.f) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { - mPathBuffer.moveTo( - center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), - center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD)); + arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); + + mPathBuffer.moveTo(arcStartPointX, arcStartPointY); mPathBuffer.arcTo( circleBox, @@ -206,6 +245,23 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { ); } + if (sliceSpace > 0.f) { + innerRadius = Math.max(innerRadius, + calculateMinimumRadiusForSpacedSlice( + center, radius, + sliceAngle * phaseY, + arcStartPointX, arcStartPointY, + startAngleOuter, + sweepAngleOuter)); + } + + // API < 21 does not receive floats in addArc, but a RectF + mInnerRectBuffer.set( + center.x - innerRadius, + center.y - innerRadius, + center.x + innerRadius, + center.y + innerRadius); + if (innerRadius > 0.0) { final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? @@ -488,7 +544,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -528,6 +584,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float sliceSpaceOuterAngle = visibleAngleCount == 1 ? 0.f : sliceSpace / (Utils.FDEG2RAD * radius); + float innerRadius = userInnerRadius; float shift = set.getSelectionShift(); final float highlightedRadius = radius + shift; @@ -544,7 +601,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } mPathBuffer.reset(); - + if (sweepAngleOuter % 360f == 0.f) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, highlightedRadius, Path.Direction.CW); @@ -561,6 +618,24 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { ); } + if (sliceSpace > 0.f) { + innerRadius = Math.max(innerRadius, + calculateMinimumRadiusForSpacedSlice( + center, radius, + sliceAngle * phaseY, + center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), + center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD), + startAngleOuter, + sweepAngleOuter)); + } + + // API < 21 does not receive floats in addArc, but a RectF + mInnerRectBuffer.set( + center.x - innerRadius, + center.y - innerRadius, + center.x + innerRadius, + center.y + innerRadius); + if (innerRadius > 0.0) { final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? 0.f : From 7a67f25b7d92ac33f435d4a612721fccde2ba6b4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 22 Feb 2016 19:06:31 +0200 Subject: [PATCH 0752/1390] Fixed range calculation according to axisMin/axisMax --- .../charting/charts/BarLineChartBase.java | 34 ++++++++++++++----- .../mikephil/charting/charts/RadarChart.java | 16 ++++++--- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 4430fda0cf..6ebdea659b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -344,10 +344,18 @@ protected void calcMinMax() { if (mAutoScaleMinMaxEnabled) mData.calcMinMax(getLowestVisibleXIndex(), getHighestVisibleXIndex()); - float minLeft = mData.getYMin(AxisDependency.LEFT); - float maxLeft = mData.getYMax(AxisDependency.LEFT); - float minRight = mData.getYMin(AxisDependency.RIGHT); - float maxRight = mData.getYMax(AxisDependency.RIGHT); + float minLeft = !Float.isNaN(mAxisLeft.getAxisMinValue()) + ? mAxisLeft.getAxisMinValue() + : mData.getYMin(AxisDependency.LEFT); + float maxLeft = !Float.isNaN(mAxisLeft.getAxisMaxValue()) + ? mAxisLeft.getAxisMaxValue() + : mData.getYMax(AxisDependency.LEFT); + float minRight = !Float.isNaN(mAxisRight.getAxisMinValue()) + ? mAxisRight.getAxisMinValue() + : mData.getYMin(AxisDependency.RIGHT); + float maxRight = !Float.isNaN(mAxisRight.getAxisMaxValue()) + ? mAxisRight.getAxisMaxValue() + : mData.getYMax(AxisDependency.RIGHT); float leftRange = Math.abs(maxLeft - minLeft); float rightRange = Math.abs(maxRight - minRight); @@ -372,11 +380,19 @@ protected void calcMinMax() { mDeltaX = Math.abs(mXChartMax - mXChartMin); // Use the values as they are - mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); - mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); - - mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight); - mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight); + mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) + ? mAxisLeft.getAxisMinValue() + : (minLeft - bottomSpaceLeft); + mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) + ? mAxisLeft.getAxisMaxValue() + : (maxLeft + topSpaceLeft); + + mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) + ? mAxisRight.getAxisMinValue() + : (minRight - bottomSpaceRight); + mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) + ? mAxisRight.getAxisMaxValue() + : (maxRight + topSpaceRight); mAxisLeft.mAxisRange = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); mAxisRight.mAxisRange = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index d317fc35a0..ea012e7abe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -107,8 +107,12 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - float minLeft = mData.getYMin(AxisDependency.LEFT); - float maxLeft = mData.getYMax(AxisDependency.LEFT); + float minLeft = !Float.isNaN(mYAxis.getAxisMinValue()) + ? mYAxis.getAxisMinValue() + : mData.getYMin(AxisDependency.LEFT); + float maxLeft = !Float.isNaN(mYAxis.getAxisMaxValue()) + ? mYAxis.getAxisMaxValue() + : mData.getYMax(AxisDependency.LEFT); mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); @@ -122,8 +126,12 @@ protected void calcMinMax() { mDeltaX = Math.abs(mXChartMax - mXChartMin); // Use the values as they are - mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft); - mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft); + mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) + ? mYAxis.getAxisMinValue() + : (minLeft - bottomSpaceLeft); + mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) + ? mYAxis.getAxisMaxValue() + : (maxLeft + topSpaceLeft); mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); } From 1a0e90aacf97ea84944b434400b59674819a9ba2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Feb 2016 09:37:33 +0100 Subject: [PATCH 0753/1390] Changes related to PieChart --- .../mpchartexample/PieChartActivity.java | 2 +- .../mikephil/charting/charts/PieChart.java | 25 ++----------------- .../charting/renderer/PieChartRenderer.java | 20 +++++++++++---- 3 files changed, 18 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 941705871c..3046a1fcbb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setCenterText(generateCenterSpannableText()); mChart.setDrawHoleEnabled(true); - mChart.setHoleColorTransparent(true); + mChart.setHoleColor(Color.TRANSPARENT); mChart.setTransparentCircleColor(Color.WHITE); mChart.setTransparentCircleAlpha(110); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 93f120eda9..e88a270c7e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -332,37 +332,16 @@ public float[] getAbsoluteAngles() { /** * Sets the color for the hole that is drawn in the center of the PieChart - * (if enabled). NOTE: Use setHoleColorTransparent(boolean enabled) to make - * the hole transparent. + * (if enabled). Use transparent colors to make things beneath the hole visible. * * @param color */ public void setHoleColor(int color) { - if (color == ColorTemplate.COLOR_NONE || color == ColorTemplate.COLOR_SKIP) { - color = 0; // Transparent - } ((PieChartRenderer) mRenderer).getPaintHole().setColor(color); } /** - * Set the hole in the center of the PieChart transparent. - */ - public void setHoleColorTransparent(boolean enable) { - mDrawHoleTransparent = enable; - } - - /** - * Returns true if the hole in the center of the PieChart is transparent, - * false if not. - * - * @return true if hole is transparent. - */ - public boolean isHoleTransparent() { - return mDrawHoleTransparent; - } - - /** - * set this to true to draw the pie center empty + * Set this to true to draw a hole in the pie center (the pie center is empty). * * @param enabled */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 2caf60439b..b601f3135b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -187,7 +187,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -447,8 +447,8 @@ protected void drawHole(Canvas c) { holeRadius, mHolePaint); } - // only draw the circle if it can be seen (not covered by the hole) - if (hasHoleColor && mChart.getTransparentCircleRadius() > mChart.getHoleRadius()) { + // only draw the circle if it can be seen (not covered by the hole), circle is independent of hole + if (mChart.getTransparentCircleRadius() > mChart.getHoleRadius()) { int alpha = mTransparentCirclePaint.getAlpha(); float secondHoleRadius = radius * (mChart.getTransparentCircleRadius() / 100); @@ -479,7 +479,7 @@ protected void drawCenterText(Canvas c) { PointF center = mChart.getCenterCircleBox(); - float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + float innerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); @@ -544,7 +544,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -680,6 +680,16 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } + /** + * Returns true if the hole in the center of the PieChart is transparent, + * false if not. + * + * @return true if hole is transparent. + */ + private boolean isHoleTransparent() { + return Color.alpha(mHolePaint.getColor()) <= 0; + } + /** * This gives all pie-slices a rounded edge. * From 2dd9d5aa34899207fb5fdfffc33bd1ccea28dfb5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Feb 2016 11:39:34 +0100 Subject: [PATCH 0754/1390] Introduce zoomToAnimated(...) method - first version --- .../mpchartexample/LineChartActivity1.java | 4 +- .../mpchartexample/LineChartActivity2.java | 1 + .../charting/charts/BarLineChartBase.java | 27 +++++-- .../mikephil/charting/jobs/AnimatedJob.java | 10 ++- .../charting/jobs/AnimatedZoomJob.java | 25 +++++-- .../mikephil/charting/jobs/MoveViewJob.java | 6 +- .../jobs/{Job.java => ViewPortJob.java} | 18 ++++- .../mikephil/charting/jobs/ZoomJob.java | 50 +++++++++++++ .../charting/utils/ViewPortHandler.java | 75 ++++++++++++++----- 9 files changed, 172 insertions(+), 44 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/jobs/{Job.java => ViewPortJob.java} (64%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index a439e3afc1..0c331f1738 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -27,8 +27,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; @@ -357,7 +355,7 @@ private void setData(int count, float range) { @Override public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "START"); + Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index b2e816147e..9be0ac4f3a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -329,6 +329,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { //mChart.centerViewToAnimated(e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); + mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 8b5a6db96d..80767571a0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -29,6 +29,7 @@ import com.github.mikephil.charting.jobs.AnimatedMoveViewJob; import com.github.mikephil.charting.jobs.AnimatedZoomJob; import com.github.mikephil.charting.jobs.MoveViewJob; +import com.github.mikephil.charting.jobs.ZoomJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; @@ -701,9 +702,24 @@ public void zoom(float scaleX, float scaleY, float x, float y) { postInvalidate(); } + /** + * Zooms in or out by the given scale factor. + * x and y are the values to or which to zoom from (the values of the zoom center). + * + * @param scaleX + * @param scaleY + * @param xValue + * @param yValue + * @param axis the axis relative to which the zoom should take place + */ + public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { + + Runnable job = new ZoomJob(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); + postJob(job); + } + /** * Zooms by the specified scale factor to the specified values on the specified axis. - * STILL WORK IN PROGRESS * * @param scaleX * @param scaleY @@ -712,14 +728,11 @@ public void zoom(float scaleX, float scaleY, float x, float y) { * @param axis * @param duration */ - private void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { + public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { - PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue - xsInView / 2f, yValue + valsInView / 2f, (float) bounds.x, (float) bounds.y, duration); + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); postJob(job); } diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java index a9dfb2160d..75084abaf1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java @@ -12,7 +12,7 @@ * Created by Philipp Jahoda on 19/02/16. */ @SuppressLint("NewApi") -public abstract class AnimatedJob extends Job implements ValueAnimator.AnimatorUpdateListener { +public abstract class AnimatedJob extends ViewPortJob implements ValueAnimator.AnimatorUpdateListener { protected ObjectAnimator animator; @@ -43,4 +43,12 @@ public float getPhase() { public void setPhase(float phase) { this.phase = phase; } + + public float getXOrigin() { + return xOrigin; + } + + public float getYOrigin() { + return yOrigin; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index aa47506da7..82cf3fdc0e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -3,9 +3,11 @@ import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.graphics.Matrix; import android.view.View; import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -21,8 +23,12 @@ public class AnimatedZoomJob extends AnimatedJob implements Animator.AnimatorLis protected float zoomCenterX; protected float zoomCenterY; + protected YAxis yAxis; + + protected float xValCount; + @SuppressLint("NewApi") - public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { + public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, YAxis axis, float xValCount, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { super(viewPortHandler, scaleX, scaleY, trans, v, xOrigin, yOrigin, duration); this.zoomCenterX = zoomCenterX; @@ -30,6 +36,8 @@ public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer tran this.zoomOriginX = zoomOriginX; this.zoomOriginY = zoomOriginY; this.animator.addListener(this); + this.yAxis = axis; + this.xValCount = xValCount; } @Override @@ -38,14 +46,19 @@ public void onAnimationUpdate(ValueAnimator animation) { float scaleX = xOrigin + (xValue - xOrigin) * phase; float scaleY = yOrigin + (yValue - yOrigin) * phase; - pts[0] = zoomOriginX + (zoomCenterX - zoomOriginX) * phase; - pts[1] = zoomOriginY + (zoomCenterY - zoomOriginY) * phase; + Matrix save = mViewPortHandler.setZoom(scaleX, scaleY); + mViewPortHandler.refresh(save, view, false); - mTrans.pointValuesToPixel(pts); + float valsInView = yAxis.mAxisRange / mViewPortHandler.getScaleY(); + float xsInView = xValCount / mViewPortHandler.getScaleX(); - //Matrix save = mViewPortHandler.zoomAndCenter(xValue * phase, yValue * phase, zoomCenterX * phase, zoomCenterY * phase); + pts[0] = zoomOriginX + ((zoomCenterX - xsInView / 2f) - zoomOriginX) * phase; + pts[1] = zoomOriginY + ((zoomCenterY + valsInView / 2f) - zoomOriginY) * phase; + + mTrans.pointValuesToPixel(pts); - mViewPortHandler.zoomAndCenter(scaleX, scaleY, pts, view);//zoomOriginX + (zoomCenterX - zoomOriginX) * phase, zoomOriginY + (zoomCenterY - zoomOriginY) * phase); + save = mViewPortHandler.translate(pts); + mViewPortHandler.refresh(save, view, true); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java index 91e9be2a08..e96aba8052 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java @@ -9,10 +9,10 @@ /** * Created by Philipp Jahoda on 19/02/16. */ -public class MoveViewJob extends Job { +public class MoveViewJob extends ViewPortJob { - public MoveViewJob(ViewPortHandler viewPortHandler, float xIndex, float yValue, Transformer trans, View v) { - super(viewPortHandler, xIndex, yValue, trans, v); + public MoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v) { + super(viewPortHandler, xValue, yValue, trans, v); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/Job.java b/MPChartLib/src/com/github/mikephil/charting/jobs/ViewPortJob.java similarity index 64% rename from MPChartLib/src/com/github/mikephil/charting/jobs/Job.java rename to MPChartLib/src/com/github/mikephil/charting/jobs/ViewPortJob.java index 607779cec3..912ab38431 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/Job.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/ViewPortJob.java @@ -9,11 +9,13 @@ /** * Runnable that is used for viewport modifications since they cannot be * executed at any time. This can be used to delay the execution of viewport - * modifications until the onSizeChanged(...) method of the chartview is called. + * modifications until the onSizeChanged(...) method of the chart-view is called. + * This is especially important if viewport modifying methods are called on the chart + * directly after initialization. * * @author Philipp Jahoda */ -public abstract class Job implements Runnable { +public abstract class ViewPortJob implements Runnable { protected float[] pts = new float[2]; @@ -23,8 +25,8 @@ public abstract class Job implements Runnable { protected Transformer mTrans; protected View view; - public Job(ViewPortHandler viewPortHandler, float xValue, float yValue, - Transformer trans, View v) { + public ViewPortJob(ViewPortHandler viewPortHandler, float xValue, float yValue, + Transformer trans, View v) { this.mViewPortHandler = viewPortHandler; this.xValue = xValue; @@ -32,4 +34,12 @@ public Job(ViewPortHandler viewPortHandler, float xValue, float yValue, this.mTrans = trans; this.view = v; } + + public float getXValue() { + return xValue; + } + + public float getYValue() { + return yValue; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java new file mode 100644 index 0000000000..108a6f3955 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java @@ -0,0 +1,50 @@ + +package com.github.mikephil.charting.jobs; + +import android.graphics.Matrix; +import android.view.View; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 19/02/16. + */ +public class ZoomJob extends ViewPortJob { + + protected float scaleX; + protected float scaleY; + + protected YAxis.AxisDependency axisDependency; + + public ZoomJob(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, Transformer trans, YAxis.AxisDependency axis, View v) { + super(viewPortHandler, xValue, yValue, trans, v); + + this.scaleX = scaleX; + this.scaleY = scaleY; + this.axisDependency = axis; + } + + @Override + public void run() { + + Matrix save = mViewPortHandler.zoom(scaleX, scaleY); + mViewPortHandler.refresh(save, view, false); + + float valsInView = ((BarLineChartBase) view).getDeltaY(axisDependency) / mViewPortHandler.getScaleY(); + float xsInView = ((BarLineChartBase) view).getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + + pts[0] = xValue - xsInView / 2f; + pts[1] = yValue + valsInView / 2f; + + mTrans.pointValuesToPixel(pts); + + save = mViewPortHandler.translate(pts); + mViewPortHandler.refresh(save, view, false); + + ((BarLineChartBase) view).calculateOffsets(); + view.postInvalidate(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 33bd8e462c..1c66bcc6da 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -210,13 +210,30 @@ public Matrix zoomOut(float x, float y) { } /** - * Zooms in or out by the given scale factor. x and y are the coordinates - * (in pixels) of the zoom center. + * Post-scales by the specified scale factors. * - * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in - * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in + * @param scaleX + * @param scaleY + * @return + */ + public Matrix zoom(float scaleX, float scaleY) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + save.postScale(scaleX, scaleY); + + return save; + } + + /** + * Post-scales by the specified scale factors. x and y is pivot. + * + * @param scaleX + * @param scaleY * @param x * @param y + * @return */ public Matrix zoom(float scaleX, float scaleY, float x, float y) { @@ -228,7 +245,14 @@ public Matrix zoom(float scaleX, float scaleY, float x, float y) { return save; } - public Matrix zoom(float scaleX, float scaleY) { + /** + * Sets the scale factor to the specified values. + * + * @param scaleX + * @param scaleY + * @return + */ + public Matrix setZoom(float scaleX, float scaleY) { Matrix save = new Matrix(); save.set(mMatrixTouch); @@ -239,28 +263,22 @@ public Matrix zoom(float scaleX, float scaleY) { } /** - * Zooms by the specified scale factors and moves the viewport to the specified values. + * Sets the scale factor to the specified values. x and y is pivot. * * @param scaleX * @param scaleY - * @param pts - * @param view + * @param x + * @param y * @return */ - public synchronized Matrix zoomAndCenter(float scaleX, float scaleY, float[] pts, final View view) { + public Matrix setZoom(float scaleX, float scaleY, float x, float y) { Matrix save = new Matrix(); save.set(mMatrixTouch); - final float x = pts[0] - offsetLeft(); - final float y = pts[1] - offsetTop(); - - PointF center = getContentCenter(); - - save.setScale(scaleX, scaleY, center.x, center.y); - save.postTranslate(-x, -y); + save.setScale(scaleX, scaleY, x, y); - return refresh(save, view, true); + return save; } /** @@ -290,6 +308,25 @@ public Matrix fitScreen() { return save; } + /** + * Post-translates to the specified points. + * + * @param transformedPts + * @return + */ + public Matrix translate(final float[] transformedPts) { + + Matrix save = new Matrix(); + save.set(mMatrixTouch); + + final float x = transformedPts[0] - offsetLeft(); + final float y = transformedPts[1] - offsetTop(); + + save.postTranslate(-x, -y); + + return save; + } + /** * Centers the viewport around the specified position (x-index and y-value) * in the chart. Centering the viewport outside the bounds of the chart is @@ -300,7 +337,7 @@ public Matrix fitScreen() { * @param view * @return save */ - public synchronized void centerViewPort(final float[] transformedPts, final View view) { + public void centerViewPort(final float[] transformedPts, final View view) { Matrix save = new Matrix(); save.set(mMatrixTouch); @@ -308,8 +345,6 @@ public synchronized void centerViewPort(final float[] transformedPts, final View final float x = transformedPts[0] - offsetLeft(); final float y = transformedPts[1] - offsetTop(); - //Log.i("", "Moving view to x: " + x + ", y: " + y); - save.postTranslate(-x, -y); refresh(save, view, true); From 9028b5613b7e8ce15aa8e57cb840176f1e6a8baf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Feb 2016 15:06:15 +0100 Subject: [PATCH 0755/1390] Minor fixes with zoom methods --- .../mpchartexample/LineChartActivity2.java | 4 ++-- .../charting/charts/BarLineChartBase.java | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9be0ac4f3a..7c4236f60c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -327,9 +327,9 @@ private void setData(int count, float range) { public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); - //mChart.centerViewToAnimated(e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); + mChart.centerViewToAnimated(e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 500); //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); - mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); + //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getXIndex(), e.getVal(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 80767571a0..12d9cd1a0a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -658,8 +658,11 @@ public void computeScroll() { * Zooms in by 1.4f, into the charts center. center. */ public void zoomIn() { - Matrix save = mViewPortHandler.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); - mViewPortHandler.refresh(save, this, true); + + PointF center = mViewPortHandler.getContentCenter(); + + Matrix save = mViewPortHandler.zoomIn(center.x, -center.y); + mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. @@ -672,8 +675,11 @@ public void zoomIn() { * Zooms out by 0.7f, from the charts center. center. */ public void zoomOut() { - Matrix save = mViewPortHandler.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); - mViewPortHandler.refresh(save, this, true); + + PointF center = mViewPortHandler.getContentCenter(); + + Matrix save = mViewPortHandler.zoomOut(center.x, -center.y); + mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. @@ -693,7 +699,7 @@ public void zoomOut() { */ public void zoom(float scaleX, float scaleY, float x, float y) { Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, -y); - mViewPortHandler.refresh(save, this, true); + mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. @@ -704,7 +710,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { /** * Zooms in or out by the given scale factor. - * x and y are the values to or which to zoom from (the values of the zoom center). + * x and y are the values (NOT PIXELS) to or which to zoom from (the values of the zoom center). * * @param scaleX * @param scaleY @@ -742,11 +748,8 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa */ public void fitScreen() { Matrix save = mViewPortHandler.fitScreen(); - mViewPortHandler.refresh(save, this, true); + mViewPortHandler.refresh(save, this, false); - // Range might have changed, which means that Y-axis labels - // could have changed in size, affecting Y-axis size. - // So we need to recalculate offsets. calculateOffsets(); postInvalidate(); } From 3ddcd245ec9ce990a4e13a9f72c3eb124ab8ab66 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Feb 2016 15:15:47 +0100 Subject: [PATCH 0756/1390] Upgrade to realm 0.87.5 --- MPChartExample/build.gradle | 2 +- MPChartLib/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8f3babfc7c..1ca40e064e 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -54,6 +54,6 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' - compile 'io.realm:realm-android:0.87.3' // dependency for realm-database API (http://realm.io) + compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 0b4147476c..1c7ca0e099 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -41,7 +41,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' - provided 'io.realm:realm-android:0.87.3' // "optional" dependency to realm-database API + provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API } android.libraryVariants.all { variant -> From 4a8929e9ca9b1df7525bb4485ee357dfdf6885d7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Feb 2016 23:36:48 +0100 Subject: [PATCH 0757/1390] Fix issue #1506 --- .../com/github/mikephil/charting/data/BubbleDataSet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 44a455cc0d..96396d3241 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -54,12 +54,12 @@ public void calcMinMax(int start, int end) { // need chart width to guess this properly - for (int i = start; i < endValue; i++) { + for (int i = start; i <= endValue; i++) { final BubbleEntry entry = mYVals.get(i); - final float ymin = yMin(entry); - final float ymax = yMax(entry); + float ymin = yMin(entry); + float ymax = yMax(entry); if (ymin < mYMin) { mYMin = ymin; From ebbea0651ba4f5bf1c1036a6299e98992d3dd441 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 00:28:10 +0100 Subject: [PATCH 0758/1390] Minor RadarChart fix for unequal datasets in terms of entry count --- .../mikephil/charting/data/ChartData.java | 5 +-- .../charting/renderer/RadarChartRenderer.java | 33 ++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index e9d5ad25d6..d9ef299dcd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -186,8 +186,9 @@ private void checkLegal() { } /** - * Call this method to let the CartData know that the underlying data has - * changed. + * Call this method to let the ChartData know that the underlying data has + * changed. Calling this performs all necessary recalculations needed when + * the contained data has changed. */ public void notifyDataChanged() { init(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 32f3481f71..2437a66fe5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -57,12 +57,29 @@ public void drawData(Canvas c) { for (IRadarDataSet set : radarData.getDataSets()) { - if (set.isVisible() && set.getEntryCount() > 0) - drawDataSet(c, set); + if (set.isVisible() && set.getEntryCount() > 0) { + + int mostEntries = 0; + + for (IRadarDataSet radarSet : radarData.getDataSets()) { + if (set != radarSet && radarSet.getEntryCount() > mostEntries) { + mostEntries = radarSet.getEntryCount(); + } + } + + drawDataSet(c, set, mostEntries); + } } } - protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { + /** + * Draws the RadarDataSet + * + * @param c + * @param dataSet + * @param mostEntries the entry count of the dataset with the most entries + */ + protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -100,7 +117,15 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { surface.lineTo(p.x, p.y); } - surface.close(); + // if this is the largest set, close it + if (dataSet.getEntryCount() >= mostEntries) { + surface.close(); + } else { + + // if this is not the largest set, draw a line to the center and then close it + surface.lineTo(center.x, center.y); + surface.close(); + } final Drawable drawable = dataSet.getFillDrawable(); if (drawable != null) { From d1689b6f6392ed37d10b29e5a43979bf0aadcf72 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 00:33:50 +0100 Subject: [PATCH 0759/1390] Minor performance improvement for prior fix. --- .../charting/renderer/RadarChartRenderer.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 2437a66fe5..2a2ab12dc3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -55,18 +55,17 @@ public void drawData(Canvas c) { RadarData radarData = mChart.getData(); - for (IRadarDataSet set : radarData.getDataSets()) { - - if (set.isVisible() && set.getEntryCount() > 0) { + int mostEntries = 0; - int mostEntries = 0; + for (IRadarDataSet set : radarData.getDataSets()) { + if (set.getEntryCount() > mostEntries) { + mostEntries = set.getEntryCount(); + } + } - for (IRadarDataSet radarSet : radarData.getDataSets()) { - if (set != radarSet && radarSet.getEntryCount() > mostEntries) { - mostEntries = radarSet.getEntryCount(); - } - } + for (IRadarDataSet set : radarData.getDataSets()) { + if (set.isVisible() && set.getEntryCount() > 0) { drawDataSet(c, set, mostEntries); } } From 563767076d397bb5c8e6b6cc9bca2217844d3c98 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 00:37:23 +0100 Subject: [PATCH 0760/1390] Another RadarChart fix that caused fill never to be disabled --- .../charting/renderer/RadarChartRenderer.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 2a2ab12dc3..cb7393b092 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -126,13 +126,16 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { surface.close(); } - final Drawable drawable = dataSet.getFillDrawable(); - if (drawable != null) { + if(dataSet.isDrawFilledEnabled()) { - drawFilledPath(c, surface, drawable); - } else { + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { + + drawFilledPath(c, surface, drawable); + } else { - drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha()); + drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha()); + } } mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); From 8fa30a31065e4210b6b0951fb0cc2dc8e4743f1d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 00:49:10 +0100 Subject: [PATCH 0761/1390] Update example build.gradle --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index a1d5c3a9c0..6895b904fd 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="49" + android:versionName="2.2.3" > Date: Thu, 25 Feb 2016 09:45:58 +0100 Subject: [PATCH 0762/1390] Add API level check for new animation methods --- .../charting/charts/BarLineChartBase.java | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 12d9cd1a0a..d47da9a4a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -736,10 +736,16 @@ public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDep */ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { - PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + if (android.os.Build.VERSION.SDK_INT >= 11) { - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); - postJob(job); + PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); + postJob(job); + + } else { + Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); + } } /** @@ -882,14 +888,19 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { */ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { - PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + if (android.os.Build.VERSION.SDK_INT >= 11) { - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - postJob(job); + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + + postJob(job); + } else { + Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); + } } /** @@ -924,16 +935,21 @@ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { */ public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { - PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + if (android.os.Build.VERSION.SDK_INT >= 11) { - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, - xIndex - xsInView / 2f, yValue + valsInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); - postJob(job); + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, + xIndex - xsInView / 2f, yValue + valsInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + + postJob(job); + } else { + Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); + } } /** From fc3deccbcee541f4810e7a64ba07653b3ab8207a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 09:48:24 +0100 Subject: [PATCH 0763/1390] Add target API annotation --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d47da9a4a1..98053cc58b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.charts; import android.annotation.SuppressLint; +import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -734,6 +735,7 @@ public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDep * @param axis * @param duration */ + @TargetApi(11) public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { @@ -886,6 +888,7 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { * @param axis * @param duration the duration of the animation in milliseconds */ + @TargetApi(11) public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { @@ -933,6 +936,7 @@ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { * @param axis * @param duration the duration of the animation in milliseconds */ + @TargetApi(11) public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { From fa49f2fc83838468b8283c38e943c54c147682c4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 10:04:23 +0100 Subject: [PATCH 0764/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d35b587c9..c04a29c0c5 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Remember: *It's all about the looks.* ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) -**MPAndroidChart** is a powerful & easy to use chart library for Android, supporting line-, bar-, scatter-, candlestick-, bubble-, pie- and radarcharts (spider web), as well as scaling, dragging (panning), selecting and animations. Works on **Android 2.2 (API level 8)** and upwards. +[**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on **Android 2.2 (API level 8)** and upwards. -This library allows **cross-platform** development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) +As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) :zap:. Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). From 7ffc20c11be13bcd571b3338b9fb59e16afceb3e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 10:07:52 +0100 Subject: [PATCH 0765/1390] Update README.md --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c04a29c0c5..f75cad04c7 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,19 @@ As an additional feature, this library allows cross-platform development between Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). +Spread the word +----- + +If you like this library, please tell others about it :two_hearts: + + + + + + - Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + - Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) + - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) + Donations ----- @@ -29,20 +42,6 @@ Donations - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! -**Spread the word** - - - - - -[]() - -Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - -Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) - -Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) - Demo ----- From c2007bec12476f37314915f06b2139bd04d70122 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 10:08:52 +0100 Subject: [PATCH 0766/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f75cad04c7..68261c0abd 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ If you like this library, please tell others about it :two_hearts: - - Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + - []()Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) From bc8c0788e999137175a5f3b75c9ae5f7b02fe59b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 10:12:12 +0100 Subject: [PATCH 0767/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 68261c0abd..8c642e37bc 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ If you are having questions or problems, you should: - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - - Create new issues (please **search known issues before**, do not create duplicate issues) + - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) Features ======= @@ -182,7 +182,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 4b1112d2ef8b6799b4f547807b2e60aa6392888f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 25 Feb 2016 15:43:50 +0100 Subject: [PATCH 0768/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 8c642e37bc..ad914034e4 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ If you are having questions or problems, you should: - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) + +Please do not expect answers to your questions if you have not considered all above mentioned points in advance. Features ======= From c3f2ec2faf1139f28ca861721d006f501d8228f3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 23 Feb 2016 23:00:39 +0200 Subject: [PATCH 0769/1390] Fix cubic fill being weird when xIndex does not match entry index --- .../charting/renderer/LineChartRenderer.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 30511c8f19..64ae4bec00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -252,9 +252,18 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); - - spline.lineTo(to - 1, fillMin); - spline.lineTo(from, fillMin); + + // Take the from/to xIndex from the entries themselves, + // so missing entries won't screw up the filling. + // What we need to draw is line from points of the xIndexes - not arbitrary entry indexes! + + final Entry toEntry = dataSet.getEntryForIndex(to - 1); + final Entry fromEntry = dataSet.getEntryForIndex(from); + final float xTo = toEntry == null ? 0 : toEntry.getXIndex(); + final float xFrom = fromEntry == null ? 0 : fromEntry.getXIndex(); + + spline.lineTo(xTo, fillMin); + spline.lineTo(xFrom, fillMin); spline.close(); trans.pathValueToPixel(spline); From badc1a8508a524e7703c119a6b35bb4467ae4160 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 23 Feb 2016 23:00:50 +0200 Subject: [PATCH 0770/1390] Always start with previous xIndex to avoid clipping the cubic too soon --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 64ae4bec00..ec266ec789 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -148,7 +148,7 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff - 1, 0); int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entryCount); float phaseX = mAnimator.getPhaseX(); From d9c0fd76e5d2d469442a65de7d1a4d051059f0b9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 26 Feb 2016 14:55:23 +0200 Subject: [PATCH 0771/1390] Fixed drawing of hole colors --- .../xxmassdeveloper/mpchartexample/PieChartActivity.java | 2 +- .../mikephil/charting/renderer/PieChartRenderer.java | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 3046a1fcbb..bab7dcb525 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setCenterText(generateCenterSpannableText()); mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.TRANSPARENT); + mChart.setHoleColor(Color.WHITE); mChart.setTransparentCircleColor(Color.WHITE); mChart.setTransparentCircleAlpha(110); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index b601f3135b..a03dfb9c10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -438,17 +438,17 @@ protected void drawHole(Canvas c) { float radius = mChart.getRadius(); float holeRadius = radius * (mChart.getHoleRadius() / 100); PointF center = mChart.getCenterCircleBox(); - boolean hasHoleColor = mHolePaint.getColor() != 0; - if (hasHoleColor) { + if (Color.alpha(mHolePaint.getColor()) > 0) { // draw the hole-circle mBitmapCanvas.drawCircle( center.x, center.y, holeRadius, mHolePaint); } - // only draw the circle if it can be seen (not covered by the hole), circle is independent of hole - if (mChart.getTransparentCircleRadius() > mChart.getHoleRadius()) { + // only draw the circle if it can be seen (not covered by the hole) + if (Color.alpha(mTransparentCirclePaint.getColor()) > 0 && + mChart.getTransparentCircleRadius() > mChart.getHoleRadius()) { int alpha = mTransparentCirclePaint.getAlpha(); float secondHoleRadius = radius * (mChart.getTransparentCircleRadius() / 100); From f317299176fb867834197a839e274eb28d15eb57 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 26 Feb 2016 14:56:15 +0200 Subject: [PATCH 0772/1390] Normalise API for allowing to show slices under the hole --- .../mikephil/charting/charts/PieChart.java | 27 ++++++++++++++----- .../charting/renderer/PieChartRenderer.java | 16 +++-------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index e88a270c7e..8219a453a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -5,8 +5,6 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PointF; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; @@ -55,9 +53,9 @@ public class PieChart extends PieRadarChartBase { private boolean mDrawHole = true; /** - * if true, the hole will see-through to the inner ends of the slices + * if true, the hole will see-through to the inner tips of the slices */ - private boolean mDrawHoleTransparent = true; + private boolean mDrawSlicesUnderHole = false; /** * if true, the values inside the piechart are drawn as percent values @@ -332,7 +330,7 @@ public float[] getAbsoluteAngles() { /** * Sets the color for the hole that is drawn in the center of the PieChart - * (if enabled). Use transparent colors to make things beneath the hole visible. + * (if enabled). * * @param color */ @@ -341,7 +339,24 @@ public void setHoleColor(int color) { } /** - * Set this to true to draw a hole in the pie center (the pie center is empty). + * Enable or disable the visibility of the inner tips of the slices behind the hole + */ + public void setDrawSlicesUnderHole(boolean enable) { + mDrawSlicesUnderHole = enable; + } + + /** + * Returns true if the inner tips of the slices are visible behind the hole, + * false if not. + * + * @return true if slices are visible behind the hole. + */ + public boolean isDrawSlicesUnderHoleEnabled() { + return mDrawSlicesUnderHole; + } + + /** + * set this to true to draw the pie center empty * * @param enabled */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index a03dfb9c10..4d47b5cba7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -187,7 +187,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -479,7 +479,7 @@ protected void drawCenterText(Canvas c) { PointF center = mChart.getCenterCircleBox(); - float innerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() + float innerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); @@ -544,7 +544,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && isHoleTransparent() + final float userInnerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -680,16 +680,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - /** - * Returns true if the hole in the center of the PieChart is transparent, - * false if not. - * - * @return true if hole is transparent. - */ - private boolean isHoleTransparent() { - return Color.alpha(mHolePaint.getColor()) <= 0; - } - /** * This gives all pie-slices a rounded edge. * From f0dcd68017c3f5c9bcfc528ed390ef5ec7c8d721 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 27 Feb 2016 18:12:23 +0100 Subject: [PATCH 0773/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ad914034e4..7ff30023ff 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Remember: *It's all about the looks.* ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) -[**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on **Android 2.2 (API level 8)** and upwards. +[**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) :zap:. From 1d1a07131fc25e6bd620264b349369cea3e1e65b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 21:51:18 +0200 Subject: [PATCH 0774/1390] Fixed confusion in docs :-) --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 98053cc58b..b0c1e27b2f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -711,7 +711,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { /** * Zooms in or out by the given scale factor. - * x and y are the values (NOT PIXELS) to or which to zoom from (the values of the zoom center). + * x and y are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). * * @param scaleX * @param scaleY From 42de21f3ca3a8d240bb8acc1362fca015d6b9a99 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 22:22:14 +0200 Subject: [PATCH 0775/1390] Renamed the job functions --- .../charting/charts/BarLineChartBase.java | 16 ++++++++-------- .../github/mikephil/charting/charts/Chart.java | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b0c1e27b2f..bc810343d2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -722,7 +722,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { Runnable job = new ZoomJob(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); - postJob(job); + addViewportJob(job); } /** @@ -743,7 +743,7 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); - postJob(job); + addViewportJob(job); } else { Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); @@ -838,7 +838,7 @@ public void moveViewToX(float xIndex) { Runnable job = new MoveViewJob(mViewPortHandler, xIndex, 0f, getTransformer(AxisDependency.LEFT), this); - postJob(job); + addViewportJob(job); } /** @@ -855,7 +855,7 @@ public void moveViewToY(float yValue, AxisDependency axis) { Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f, getTransformer(axis), this); - postJob(job); + addViewportJob(job); } /** @@ -875,7 +875,7 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { Runnable job = new MoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, getTransformer(axis), this); - postJob(job); + addViewportJob(job); } /** @@ -900,7 +900,7 @@ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - postJob(job); + addViewportJob(job); } else { Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); } @@ -924,7 +924,7 @@ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { xIndex - xsInView / 2f, yValue + valsInView / 2f, getTransformer(axis), this); - postJob(job); + addViewportJob(job); } /** @@ -950,7 +950,7 @@ public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis xIndex - xsInView / 2f, yValue + valsInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - postJob(job); + addViewportJob(job); } else { Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 1b6d617617..e488220b1b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1622,11 +1622,11 @@ public void addJob(Runnable job) { mJobs.add(job); } - public void removeJob(Runnable job) { + public void removeViewportJob(Runnable job) { mJobs.remove(job); } - public void clearAllJobs() { + public void clearAllViewportJobs() { mJobs.clear(); } @@ -1636,7 +1636,7 @@ public void clearAllJobs() { * * @param job */ - protected void postJob(Runnable job) { + protected void addViewportJob(Runnable job) { if (mViewPortHandler.hasChartDimens()) { post(job); From 028f4a54cad57a15207dbd96738cfd55a0b2d3c8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 22:23:00 +0200 Subject: [PATCH 0776/1390] Removed `addJob` as possible cause for confusion People should use `addViewportJob` instead --- .../src/com/github/mikephil/charting/charts/Chart.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index e488220b1b..f697c64e5e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1612,16 +1612,6 @@ public boolean saveToGallery(String fileName, int quality) { */ protected ArrayList mJobs = new ArrayList(); - /** - * Adds a job to be executed after the chart-view is setup (after - * onSizeChanged(...) is called). - * - * @param job - */ - public void addJob(Runnable job) { - mJobs.add(job); - } - public void removeViewportJob(Runnable job) { mJobs.remove(job); } From 261720e94a82c8a8213f06708cf603cbb7e28527 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 22:23:31 +0200 Subject: [PATCH 0777/1390] If the other methods are public - this should be public as well --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f697c64e5e..647d0f944f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1626,7 +1626,7 @@ public void clearAllViewportJobs() { * * @param job */ - protected void addViewportJob(Runnable job) { + public void addViewportJob(Runnable job) { if (mViewPortHandler.hasChartDimens()) { post(job); From 922f1a8ab354e3c9408f069bf90366aadc356e6f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 22:25:08 +0200 Subject: [PATCH 0778/1390] Renamed AnimatedJob to match ViewPortJob naming --- .../github/mikephil/charting/jobs/AnimatedMoveViewJob.java | 2 +- .../jobs/{AnimatedJob.java => AnimatedViewPortJob.java} | 4 ++-- .../com/github/mikephil/charting/jobs/AnimatedZoomJob.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/jobs/{AnimatedJob.java => AnimatedViewPortJob.java} (80%) diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java index d0d6708d8e..128fdea36f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java @@ -11,7 +11,7 @@ /** * Created by Philipp Jahoda on 19/02/16. */ -public class AnimatedMoveViewJob extends AnimatedJob { +public class AnimatedMoveViewJob extends AnimatedViewPortJob { public AnimatedMoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { super(viewPortHandler, xValue, yValue, trans, v, xOrigin, yOrigin, duration); diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java similarity index 80% rename from MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java rename to MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java index 75084abaf1..ea17745ee8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java @@ -12,7 +12,7 @@ * Created by Philipp Jahoda on 19/02/16. */ @SuppressLint("NewApi") -public abstract class AnimatedJob extends ViewPortJob implements ValueAnimator.AnimatorUpdateListener { +public abstract class AnimatedViewPortJob extends ViewPortJob implements ValueAnimator.AnimatorUpdateListener { protected ObjectAnimator animator; @@ -21,7 +21,7 @@ public abstract class AnimatedJob extends ViewPortJob implements ValueAnimator.A protected float xOrigin; protected float yOrigin; - public AnimatedJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { + public AnimatedViewPortJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { super(viewPortHandler, xValue, yValue, trans, v); this.xOrigin = xOrigin; this.yOrigin = yOrigin; diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index 82cf3fdc0e..293032207a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -15,7 +15,7 @@ * Created by Philipp Jahoda on 19/02/16. */ @SuppressLint("NewApi") -public class AnimatedZoomJob extends AnimatedJob implements Animator.AnimatorListener { +public class AnimatedZoomJob extends AnimatedViewPortJob implements Animator.AnimatorListener { protected float zoomOriginX; protected float zoomOriginY; From 5f51623993aea7dbdac82842b7a02b3a0e37d460 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 28 Feb 2016 19:31:49 +0100 Subject: [PATCH 0779/1390] Add matrixbuffer to avoid constant allocations --- .../charting/utils/ViewPortHandler.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 1c66bcc6da..0a220cf508 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -4,6 +4,7 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; +import android.util.Log; import android.view.View; /** @@ -350,6 +351,11 @@ public void centerViewPort(final float[] transformedPts, final View view) { refresh(save, view, true); } + /** + * buffer for storing matrix values + */ + protected final float[] matrixBuffer = new float[9]; + /** * call this method to refresh the graph with a given matrix * @@ -377,14 +383,13 @@ public Matrix refresh(Matrix newMatrix, View chart, boolean invalidate) { */ public void limitTransAndScale(Matrix matrix, RectF content) { - float[] vals = new float[9]; - matrix.getValues(vals); + matrix.getValues(matrixBuffer); - float curTransX = vals[Matrix.MTRANS_X]; - float curScaleX = vals[Matrix.MSCALE_X]; + float curTransX = matrixBuffer[Matrix.MTRANS_X]; + float curScaleX = matrixBuffer[Matrix.MSCALE_X]; - float curTransY = vals[Matrix.MTRANS_Y]; - float curScaleY = vals[Matrix.MSCALE_Y]; + float curTransY = matrixBuffer[Matrix.MTRANS_Y]; + float curScaleY = matrixBuffer[Matrix.MSCALE_Y]; // min scale-x is 1f, max is the max float mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX); @@ -408,13 +413,13 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); mTransY = newTransY; - vals[Matrix.MTRANS_X] = mTransX; - vals[Matrix.MSCALE_X] = mScaleX; + matrixBuffer[Matrix.MTRANS_X] = mTransX; + matrixBuffer[Matrix.MSCALE_X] = mScaleX; - vals[Matrix.MTRANS_Y] = mTransY; - vals[Matrix.MSCALE_Y] = mScaleY; + matrixBuffer[Matrix.MTRANS_Y] = mTransY; + matrixBuffer[Matrix.MSCALE_Y] = mScaleY; - matrix.setValues(vals); + matrix.setValues(matrixBuffer); } /** From ed77cb452353bcac7f5ac11ab43525117aa04a3d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 28 Feb 2016 20:05:59 +0100 Subject: [PATCH 0780/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7ff30023ff..50da145069 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -149,7 +149,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.2.2' + compile 'com.github.PhilJay:MPAndroidChart:v2.2.3' } ``` @@ -164,7 +164,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.2.2 + v2.2.3 ``` @@ -184,7 +184,7 @@ dependencies { Documentation ======= -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.2/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 8f4432c52d42cdbc7a15dc8d98ef7b6ab42959b2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 27 Feb 2016 22:27:42 +0200 Subject: [PATCH 0781/1390] Make the extra last line clearer in the rendering code flow --- .../charting/renderer/RadarChartRenderer.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index cb7393b092..3888df9bef 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -116,16 +116,13 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { surface.lineTo(p.x, p.y); } - // if this is the largest set, close it - if (dataSet.getEntryCount() >= mostEntries) { - surface.close(); - } else { - - // if this is not the largest set, draw a line to the center and then close it + if (dataSet.getEntryCount() > mostEntries) { + // if this is not the largest set, draw a line to the center before closing surface.lineTo(center.x, center.y); - surface.close(); } + surface.close(); + if(dataSet.isDrawFilledEnabled()) { final Drawable drawable = dataSet.getFillDrawable(); From acd046d7874e142edb3439cf2a065c367c0d5b3f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 2 Mar 2016 00:14:33 +0200 Subject: [PATCH 0782/1390] Fixed some bugs calculating offset center point for space pie slice (Fixes #1528) --- .../charting/renderer/PieChartRenderer.java | 157 +++++++++++++----- 1 file changed, 115 insertions(+), 42 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 4d47b5cba7..fd7cb3c034 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -149,7 +149,6 @@ protected float calculateMinimumRadiusForSpacedSlice( float arcMidPointX = center.x + radius * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); float arcMidPointY = center.y + radius * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); - // Middle point on straight line between the two point. // This is the base of the contained triangle double basePointsDistance = Math.sqrt( Math.pow(arcEndPointX - arcStartPointX, 2) + @@ -187,7 +186,8 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() + final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); + final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -214,11 +214,11 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); - final float sliceSpaceOuterAngle = visibleAngleCount == 1 ? + final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : sliceSpace / (Utils.FDEG2RAD * radius); - final float startAngleOuter = rotationAngle + (angle + sliceSpaceOuterAngle / 2.f) * phaseY; - float sweepAngleOuter = (sliceAngle - sliceSpaceOuterAngle) * phaseY; + final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; if (sweepAngleOuter < 0.f) { sweepAngleOuter = 0.f; @@ -245,16 +245,6 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { ); } - if (sliceSpace > 0.f) { - innerRadius = Math.max(innerRadius, - calculateMinimumRadiusForSpacedSlice( - center, radius, - sliceAngle * phaseY, - arcStartPointX, arcStartPointY, - startAngleOuter, - sweepAngleOuter)); - } - // API < 21 does not receive floats in addArc, but a RectF mInnerRectBuffer.set( center.x - innerRadius, @@ -262,13 +252,29 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { center.x + innerRadius, center.y + innerRadius); - if (innerRadius > 0.0) - { - final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? + if (drawInnerArc && + (innerRadius > 0.f || sliceSpace > 0.f)) { + + if (sliceSpace > 0.f) { + float minSpacedRadius = + calculateMinimumRadiusForSpacedSlice( + center, radius, + sliceAngle * phaseY, + arcStartPointX, arcStartPointY, + startAngleOuter, + sweepAngleOuter); + + if (minSpacedRadius < 0.f) + minSpacedRadius = -minSpacedRadius; + + innerRadius = Math.max(innerRadius, minSpacedRadius); + } + + final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); - final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; - float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; + final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; if (sweepAngleInner < 0.f) { sweepAngleInner = 0.f; @@ -294,9 +300,34 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { else { if (sweepAngleOuter % 360f != 0.f) { - mPathBuffer.lineTo( - center.x, - center.y); + if (sliceSpace > 0.f) { + + float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; + + float sliceSpaceOffset = + calculateMinimumRadiusForSpacedSlice( + center, + radius, + sliceAngle * phaseY, + arcStartPointX, + arcStartPointY, + startAngleOuter, + sweepAngleOuter); + + float arcEndPointX = center.x + + sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); + float arcEndPointY = center.y + + sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); + + mPathBuffer.lineTo( + arcEndPointX, + arcEndPointY); + + } else { + mPathBuffer.lineTo( + center.x, + center.y); + } } } @@ -544,7 +575,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final float userInnerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() + final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); + final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; @@ -581,9 +613,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float sliceSpace = set.getSliceSpace(); float sliceAngle = drawAngles[xIndex]; - final float sliceSpaceOuterAngle = visibleAngleCount == 1 ? - 0.f : - sliceSpace / (Utils.FDEG2RAD * radius); float innerRadius = userInnerRadius; float shift = set.getSelectionShift(); @@ -593,13 +622,28 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mRenderPaint.setColor(set.getColor(xIndex)); - final float startAngleOuter = rotationAngle + (angle + sliceSpaceOuterAngle / 2.f) * phaseY; - float sweepAngleOuter = (sliceAngle - sliceSpaceOuterAngle) * phaseY; + final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * radius); + + final float sliceSpaceAngleShifted = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * highlightedRadius); + + final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; if (sweepAngleOuter < 0.f) { sweepAngleOuter = 0.f; } + final float startAngleShifted = rotationAngle + (angle + sliceSpaceAngleShifted / 2.f) * phaseY; + float sweepAngleShifted = (sliceAngle - sliceSpaceAngleShifted) * phaseY; + if (sweepAngleShifted < 0.f) + { + sweepAngleShifted = 0.f; + } + mPathBuffer.reset(); if (sweepAngleOuter % 360f == 0.f) { @@ -608,25 +652,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } else { mPathBuffer.moveTo( - center.x + highlightedRadius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), - center.y + highlightedRadius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD)); + center.x + highlightedRadius * (float) Math.cos(startAngleShifted * Utils.FDEG2RAD), + center.y + highlightedRadius * (float) Math.sin(startAngleShifted * Utils.FDEG2RAD)); mPathBuffer.arcTo( highlightedCircleBox, - startAngleOuter, - sweepAngleOuter + startAngleShifted, + sweepAngleShifted ); } + float sliceSpaceRadius = 0.f; if (sliceSpace > 0.f) { - innerRadius = Math.max(innerRadius, + sliceSpaceRadius = calculateMinimumRadiusForSpacedSlice( center, radius, sliceAngle * phaseY, center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD), center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD), startAngleOuter, - sweepAngleOuter)); + sweepAngleOuter); } // API < 21 does not receive floats in addArc, but a RectF @@ -636,12 +681,23 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { center.x + innerRadius, center.y + innerRadius); - if (innerRadius > 0.0) { - final float sliceSpaceInnerAngle = visibleAngleCount == 1 ? + if (drawInnerArc && + (innerRadius > 0.f || sliceSpace > 0.f)) { + + if (sliceSpace > 0.f) { + float minSpacedRadius = sliceSpaceRadius; + + if (minSpacedRadius < 0.f) + minSpacedRadius = -minSpacedRadius; + + innerRadius = Math.max(innerRadius, minSpacedRadius); + } + + final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? 0.f : sliceSpace / (Utils.FDEG2RAD * innerRadius); - final float startAngleInner = rotationAngle + (angle + sliceSpaceInnerAngle / 2.f) * phaseY; - float sweepAngleInner = (sliceAngle - sliceSpaceInnerAngle) * phaseY; + final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; if (sweepAngleInner < 0.f) { sweepAngleInner = 0.f; @@ -667,9 +723,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { else { if (sweepAngleOuter % 360f != 0.f) { - mPathBuffer.lineTo( - center.x, - center.y); + + if (sliceSpace > 0.0) { + final float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; + + final float arcEndPointX = center.x + + sliceSpaceRadius * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); + final float arcEndPointY = center.y + + sliceSpaceRadius * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); + + mPathBuffer.lineTo( + arcEndPointX, + arcEndPointY); + + } else { + + mPathBuffer.lineTo( + center.x, + center.y); + } + } } From 2600018ff8acd58dc7b640bc784999557cbd8902 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 2 Mar 2016 23:14:42 +0100 Subject: [PATCH 0783/1390] Fix #1535 --- .../mikephil/charting/highlight/BarHighlighter.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 1fa547884f..853e2d1773 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -105,8 +105,10 @@ protected Highlight getStackedHighlight(Highlight old, IBarDataSet set, int xInd Range[] ranges = getRanges(entry); int stackIndex = getClosestStackIndex(ranges, (float) yValue); - Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); - return h; + if(ranges.length > 0) + return new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); + else + return null; } /** @@ -187,15 +189,14 @@ protected float getBase(float x) { protected Range[] getRanges(BarEntry entry) { float[] values = entry.getVals(); + Range[] ranges = new Range[values.length]; if (values == null || values.length == 0) - return null; + return ranges; float negRemain = -entry.getNegativeSum(); float posRemain = 0f; - Range[] ranges = new Range[values.length]; - for (int i = 0; i < ranges.length; i++) { float value = values[i]; From f1d79dc67b5fda60af7581f08ecea33053db5f5c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 3 Mar 2016 00:29:43 +0200 Subject: [PATCH 0784/1390] Fixes circle-with-hole drawing hiccup (Closes #1528) --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index fd7cb3c034..a725c2afbf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -183,7 +183,6 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { final int entryCount = dataSet.getEntryCount(); final float[] drawAngles = mChart.getDrawAngles(); - float sliceSpace = dataSet.getSliceSpace(); final PointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); @@ -199,6 +198,8 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } } + final float sliceSpace = visibleAngleCount <= 1 ? 0.f : dataSet.getSliceSpace(); + for (int j = 0; j < entryCount; j++) { float sliceAngle = drawAngles[j]; @@ -610,7 +611,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { else angle = absoluteAngles[xIndex - 1] * phaseX; - float sliceSpace = set.getSliceSpace(); + final float sliceSpace = visibleAngleCount <= 1 ? 0.f : set.getSliceSpace(); float sliceAngle = drawAngles[xIndex]; float innerRadius = userInnerRadius; From 298e97381919717a397874c7980498ccf413e1d7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 2 Mar 2016 23:42:58 +0100 Subject: [PATCH 0785/1390] Minor adjustment of previous fix. --- .../github/mikephil/charting/highlight/BarHighlighter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 853e2d1773..a852aa041c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -189,10 +189,11 @@ protected float getBase(float x) { protected Range[] getRanges(BarEntry entry) { float[] values = entry.getVals(); - Range[] ranges = new Range[values.length]; if (values == null || values.length == 0) - return ranges; + return new Range[0]; + + Range[] ranges = new Range[values.length]; float negRemain = -entry.getNegativeSum(); float posRemain = 0f; From 420d17391ada2c3d64dcfaa13c3cd0665844c61f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 4 Mar 2016 22:24:59 +0100 Subject: [PATCH 0786/1390] Add dp conversion to fix issue #1540 --- .../listener/BarLineChartTouchListener.java | 59 ++++++++++++------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 34771283c6..72c1bb06ed 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -23,21 +23,29 @@ /** * TouchListener for Bar-, Line-, Scatter- and CandleStickChart with handles all * touch interaction. Longpress == Zoom out. Double-Tap == Zoom in. - * + * * @author Philipp Jahoda */ public class BarLineChartTouchListener extends ChartTouchListener>>> { - /** the original touch-matrix from the chart */ + /** + * the original touch-matrix from the chart + */ private Matrix mMatrix = new Matrix(); - /** matrix for saving the original matrix state */ + /** + * matrix for saving the original matrix state + */ private Matrix mSavedMatrix = new Matrix(); - /** point where the touch action started */ + /** + * point where the touch action started + */ private PointF mTouchStartPoint = new PointF(); - /** center between two pointers (fingers on the display) */ + /** + * center between two pointers (fingers on the display) + */ private PointF mTouchPointCenter = new PointF(); private float mSavedXDist = 1f; @@ -46,16 +54,26 @@ public class BarLineChartTouchListener extends ChartTouchListener>> chart, Matrix touchMatrix) { super(chart); this.mMatrix = touchMatrix; + + // this equals to about 9 pixels on a 5.5" FHD screen + this.mDragTriggerDist = Utils.convertDpToPixel(3f); } @SuppressLint("ClickableViewAccessibility") @@ -142,7 +160,7 @@ public boolean onTouch(View v, MotionEvent event) { } else if (mTouchMode == NONE && Math.abs(distance(event.getX(), mTouchStartPoint.x, event.getY(), - mTouchStartPoint.y)) > 5f) { + mTouchStartPoint.y)) > mDragTriggerDist) { if (mChart.hasNoDragOffset()) { @@ -237,7 +255,7 @@ public boolean onTouch(View v, MotionEvent event) { /** * Saves the current Matrix state and the touch-start point. - * + * * @param event */ private void saveTouchStart(MotionEvent event) { @@ -250,7 +268,7 @@ private void saveTouchStart(MotionEvent event) { /** * Performs all necessary operations needed for dragging. - * + * * @param event */ private void performDrag(MotionEvent event) { @@ -275,8 +293,7 @@ private void performDrag(MotionEvent event) { dX = event.getX() - mTouchStartPoint.x; dY = -(event.getY() - mTouchStartPoint.y); } - } - else { + } else { dX = event.getX() - mTouchStartPoint.x; dY = event.getY() - mTouchStartPoint.y; } @@ -289,7 +306,7 @@ private void performDrag(MotionEvent event) { /** * Performs the all operations necessary for pinch and axis zoom. - * + * * @param event */ private void performZoom(MotionEvent event) { @@ -374,7 +391,7 @@ private void performZoom(MotionEvent event) { /** * Highlights upon dragging, generates callbacks for the selection-listener. - * + * * @param e */ private void performHighlightDrag(MotionEvent e) { @@ -395,7 +412,7 @@ private void performHighlightDrag(MotionEvent e) { /** * Determines the center point between two pointer touch points. - * + * * @param point * @param event */ @@ -407,7 +424,7 @@ private static void midPoint(PointF point, MotionEvent event) { /** * returns the distance between two pointer touch points - * + * * @param event * @return */ @@ -420,7 +437,7 @@ private static float spacing(MotionEvent event) { /** * calculates the distance on the x-axis between two pointers (fingers on * the display) - * + * * @param e * @return */ @@ -432,7 +449,7 @@ private static float getXDist(MotionEvent e) { /** * calculates the distance on the y-axis between two pointers (fingers on * the display) - * + * * @param e * @return */ @@ -444,7 +461,7 @@ private static float getYDist(MotionEvent e) { /** * returns the correct translation depending on the provided x and y touch * points - * + * * @param x * @param y * @return @@ -474,7 +491,7 @@ public PointF getTrans(float x, float y) { /** * returns the matrix object the listener holds - * + * * @return */ public Matrix getMatrix() { @@ -531,7 +548,7 @@ public boolean onSingleTapUp(MotionEvent e) { l.onChartSingleTapped(e); } - if(!mChart.isHighlightPerTapEnabled()) { + if (!mChart.isHighlightPerTapEnabled()) { return false; } @@ -585,7 +602,7 @@ public void computeScroll() { mDecelerationVelocity.x *= mChart.getDragDecelerationFrictionCoef(); mDecelerationVelocity.y *= mChart.getDragDecelerationFrictionCoef(); - final float timeInterval = (float)(currentTime - mDecelerationLastTime) / 1000.f; + final float timeInterval = (float) (currentTime - mDecelerationLastTime) / 1000.f; float distanceX = mDecelerationVelocity.x * timeInterval; float distanceY = mDecelerationVelocity.y * timeInterval; From 6e35cf1c685bbf1de9f430f1b5dcf226d523ffff Mon Sep 17 00:00:00 2001 From: Cory Charlton Date: Sat, 5 Mar 2016 18:33:34 -0800 Subject: [PATCH 0787/1390] Added Chart.setNoDataTextColor(int color) --- .../src/com/github/mikephil/charting/charts/Chart.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 647d0f944f..f224e9cf6e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1178,6 +1178,15 @@ public void setNoDataText(String text) { mNoDataText = text; } + /** + * Sets the color of the no data text. + * + * @param color + */ + public void setNoDataTextColor(int color) { + mInfoPaint.setColor(color); + } + /** * Sets descriptive text to explain to the user why there is no chart * available Defaults to empty if not set From f2771a6c88870217c78d6e04a1f94b3e32b9696c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 6 Mar 2016 14:08:42 +0100 Subject: [PATCH 0788/1390] Update README.md --- README.md | 101 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 50da145069..27b8175cc5 100644 --- a/README.md +++ b/README.md @@ -84,57 +84,6 @@ Features - Gradle support - Plotting data directly from [**Realm.io**](https://realm.io) mobile database -**Chart types:** - - - **LineChart (with legend, simple design)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) - - **LineChart (with legend, simple design)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart3.png) - - - **LineChart (cubic lines)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) - - - **LineChart (gradient fill)** -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) - - - **Combined-Chart (bar- and linechart in this case)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) - - - **BarChart (with legend, simple design)** - -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) - - - **BarChart (grouped DataSets)** - -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) - - - **Horizontal-BarChart** - -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) - - - - **PieChart (with selection, ...)** - -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/simpledesign_piechart1.png) - - - **ScatterChart** (with squares, triangles, circles, ... and more) - -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/scatterchart.png) - - - **CandleStickChart** (for financial data) - -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) - - - **BubbleChart** (area covered by bubbles indicates the value) - -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) - - - **RadarChart** (spider web chart) - -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) - - - Usage ======= @@ -190,6 +139,56 @@ Furthermore, you can also rely on the [**MPChartExample**](https://github.com/Ph You have a problem that cannot be solved by having a look at the example project and documentation? No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) + +**Chart types:** + + - **LineChart (with legend, simple design)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) + - **LineChart (with legend, simple design)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart3.png) + + - **LineChart (cubic lines)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) + + - **LineChart (gradient fill)** +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) + + - **Combined-Chart (bar- and linechart in this case)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) + + - **BarChart (with legend, simple design)** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) + + - **BarChart (grouped DataSets)** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) + + - **Horizontal-BarChart** + +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) + + + - **PieChart (with selection, ...)** + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/simpledesign_piechart1.png) + + - **ScatterChart** (with squares, triangles, circles, ... and more) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/scatterchart.png) + + - **CandleStickChart** (for financial data) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) + + - **BubbleChart** (area covered by bubbles indicates the value) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) + + - **RadarChart** (spider web chart) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) + License ======= From 3b70c23a06124f8b6b033dd03c94d1dc8a953aa6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 6 Mar 2016 17:55:31 +0100 Subject: [PATCH 0789/1390] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 27b8175cc5..6e24af64a7 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ If you are having questions or problems, you should: Please do not expect answers to your questions if you have not considered all above mentioned points in advance. Features -======= +----- **Core features:** - 8 different chart types @@ -85,7 +85,7 @@ Features - Plotting data directly from [**Realm.io**](https://realm.io) mobile database Usage -======= +----- In order to use the library, there are 4 different options: @@ -132,7 +132,7 @@ dependencies { Documentation -======= +----- For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). @@ -140,7 +140,8 @@ Furthermore, you can also rely on the [**MPChartExample**](https://github.com/Ph You have a problem that cannot be solved by having a look at the example project and documentation? No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) -**Chart types:** +Chart types +----- - **LineChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) From 4845e1b0e3269e1b4e76f9fb393a9fd160b4c45f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 6 Mar 2016 18:29:08 +0100 Subject: [PATCH 0790/1390] Fix issue regarding corrupted translation (issue #1551) --- .../mpchartexample/LineChartActivity2.java | 16 +++--- .../listener/BarLineChartTouchListener.java | 55 ++++++++++++------- .../charting/utils/ViewPortHandler.java | 43 +++++++++++++-- 3 files changed, 80 insertions(+), 34 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 7c4236f60c..2d1f3baf29 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -59,14 +59,14 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - + // no description text mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures mChart.setTouchEnabled(true); - + mChart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging @@ -114,7 +114,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(200f); leftAxis.setAxisMinValue(0f); leftAxis.setDrawGridLines(true); - + YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setTextColor(Color.RED); @@ -148,7 +148,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { + if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); mChart.invalidate(); } @@ -266,8 +266,8 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = range / 2f; float val = (float) (Math.random() * mult) + 50;// + (float) - // ((mult * - // 0.1) / 10); + // ((mult * + // 0.1) / 10); yVals1.add(new Entry(val, i)); } @@ -292,8 +292,8 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = range; float val = (float) (Math.random() * mult) + 450;// + (float) - // ((mult * - // 0.1) / 10); + // ((mult * + // 0.1) / 10); yVals2.add(new Entry(val, i)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 72c1bb06ed..71168adebf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -68,12 +68,19 @@ public class BarLineChartTouchListener extends ChartTouchListener>> chart, Matrix touchMatrix) { super(chart); this.mMatrix = touchMatrix; // this equals to about 9 pixels on a 5.5" FHD screen this.mDragTriggerDist = Utils.convertDpToPixel(3f); + + this.mMinScalePointerDistance = Utils.convertDpToPixel(3.5f); } @SuppressLint("ClickableViewAccessibility") @@ -162,7 +169,6 @@ public boolean onTouch(View v, MotionEvent event) { && Math.abs(distance(event.getX(), mTouchStartPoint.x, event.getY(), mTouchStartPoint.y)) > mDragTriggerDist) { - if (mChart.hasNoDragOffset()) { if (!mChart.isFullyZoomedOut() && mChart.isDragEnabled()) { @@ -241,8 +247,7 @@ public boolean onTouch(View v, MotionEvent event) { break; } - // Perform the transformation, update the chart - // if (needsRefresh()) + // perform the transformation, update the chart mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, true); return true; // indicate event was handled @@ -311,21 +316,20 @@ private void performDrag(MotionEvent event) { */ private void performZoom(MotionEvent event) { - if (event.getPointerCount() >= 2) { + if (event.getPointerCount() >= 2) { // two finger zoom OnChartGestureListener l = mChart.getOnChartGestureListener(); - // get the distance between the pointers of the touch - // event + // get the distance between the pointers of the touch event float totalDist = spacing(event); - if (totalDist > 10f) { + if (totalDist > mMinScalePointerDistance) { // get the translation PointF t = getTrans(mTouchPointCenter.x, mTouchPointCenter.y); + ViewPortHandler h = mChart.getViewPortHandler(); - // take actions depending on the activated touch - // mode + // take actions depending on the activated touch mode if (mTouchMode == PINCH_ZOOM) { mLastGesture = ChartGesture.PINCH_ZOOM; @@ -333,14 +337,19 @@ private void performZoom(MotionEvent event) { float scale = totalDist / mSavedDist; // total scale boolean isZoomingOut = (scale < 1); + boolean canZoomMoreX = isZoomingOut ? - mChart.getViewPortHandler().canZoomOutMoreX() : - mChart.getViewPortHandler().canZoomInMoreX(); + h.canZoomOutMoreX() : + h.canZoomInMoreX(); + + boolean canZoomMoreY = isZoomingOut ? + h.canZoomOutMoreY() : + h.canZoomInMoreY(); float scaleX = (mChart.isScaleXEnabled()) ? scale : 1f; float scaleY = (mChart.isScaleYEnabled()) ? scale : 1f; - if (mChart.isScaleYEnabled() || canZoomMoreX) { + if (canZoomMoreY || canZoomMoreX) { mMatrix.set(mSavedMatrix); mMatrix.postScale(scaleX, scaleY, t.x, t.y); @@ -358,8 +367,8 @@ private void performZoom(MotionEvent event) { boolean isZoomingOut = (scaleX < 1); boolean canZoomMoreX = isZoomingOut ? - mChart.getViewPortHandler().canZoomOutMoreX() : - mChart.getViewPortHandler().canZoomInMoreX(); + h.canZoomOutMoreX() : + h.canZoomInMoreX(); if (canZoomMoreX) { @@ -377,13 +386,19 @@ private void performZoom(MotionEvent event) { float yDist = getYDist(event); float scaleY = yDist / mSavedYDist; // y-axis scale - mMatrix.set(mSavedMatrix); + boolean isZoomingOut = (scaleY < 1); + boolean canZoomMoreY = isZoomingOut ? + h.canZoomOutMoreY() : + h.canZoomInMoreY(); + + if (canZoomMoreY) { - // y-axis comes from top to bottom, revert y - mMatrix.postScale(1f, scaleY, t.x, t.y); + mMatrix.set(mSavedMatrix); + mMatrix.postScale(1f, scaleY, t.x, t.y); - if (l != null) - l.onChartScale(event, 1f, scaleY); + if (l != null) + l.onChartScale(event, 1f, scaleY); + } } } } @@ -400,7 +415,7 @@ private void performHighlightDrag(MotionEvent e) { if (h != null && !h.equalTo(mLastHighlighted)) { mLastHighlighted = h; - mChart.highlightTouch(h); + mChart.highlightValue(h, true); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 0a220cf508..44797c3f40 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -352,7 +352,7 @@ public void centerViewPort(final float[] transformedPts, final View view) { } /** - * buffer for storing matrix values + * buffer for storing the 9 matrix values of a 3x3 matrix */ protected final float[] matrixBuffer = new float[9]; @@ -391,7 +391,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float curTransY = matrixBuffer[Matrix.MTRANS_Y]; float curScaleY = matrixBuffer[Matrix.MSCALE_Y]; - // min scale-x is 1f, max is the max float + // min scale-x is 1f mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX); // min scale-y is 1f @@ -406,12 +406,10 @@ public void limitTransAndScale(Matrix matrix, RectF content) { } float maxTransX = -width * (mScaleX - 1f); - float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); - mTransX = newTransX; + mTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); float maxTransY = height * (mScaleY - 1f); - float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); - mTransY = newTransY; + mTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); matrixBuffer[Matrix.MTRANS_X] = mTransX; matrixBuffer[Matrix.MSCALE_X] = mScaleX; @@ -562,6 +560,22 @@ public float getScaleY() { return mScaleY; } + public float getMinScaleX() { + return mMinScaleX; + } + + public float getMaxScaleX() { + return mMaxScaleX; + } + + public float getMinScaleY() { + return mMinScaleY; + } + + public float getMaxScaleY() { + return mMaxScaleY; + } + /** * Returns the translation (drag / pan) distance on the x-axis * @@ -665,4 +679,21 @@ public boolean canZoomInMoreX() { return (mScaleX < mMaxScaleX); } + /** + * Returns true if the chart is not yet fully zoomed out on the y-axis + * + * @return + */ + public boolean canZoomOutMoreY() { + return (mScaleY > mMinScaleY); + } + + /** + * Returns true if the chart is not yet fully zoomed in on the y-axis + * + * @return + */ + public boolean canZoomInMoreY() { + return (mScaleY < mMaxScaleY); + } } From d4500e28ae466169853975a37eca150bbf7ce7b8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 9 Mar 2016 23:31:32 +0200 Subject: [PATCH 0791/1390] Localized buffers for line rendering To simplify rendering flow, and avoid excessive memory usage --- .../charting/buffer/CircleBuffer.java | 31 --- .../mikephil/charting/buffer/LineBuffer.java | 57 ------ .../charting/renderer/LineChartRenderer.java | 177 +++++++++++------- 3 files changed, 111 insertions(+), 154 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java deleted file mode 100644 index 2e8f753af7..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java +++ /dev/null @@ -1,31 +0,0 @@ - -package com.github.mikephil.charting.buffer; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; - -public class CircleBuffer extends AbstractBuffer { - - public CircleBuffer(int size) { - super(size); - } - - protected void addCircle(float x, float y) { - buffer[index++] = x; - buffer[index++] = y; - } - - @Override - public void feed(ILineDataSet data) { - - int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); - - for (int i = mFrom; i < size; i++) { - - Entry e = data.getEntryForIndex(i); - addCircle(e.getXIndex(), e.getVal() * phaseY); - } - - reset(); - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java deleted file mode 100644 index 723124f72d..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ /dev/null @@ -1,57 +0,0 @@ - -package com.github.mikephil.charting.buffer; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; - -public class LineBuffer extends AbstractBuffer { - - public LineBuffer(int size) { - super((size < 4) ? 4 : size); - } - - public void moveTo(float x, float y) { - - if (index != 0) - return; - - buffer[index++] = x; - buffer[index++] = y; - - // in case just one entry, this is overwritten when lineTo is called - buffer[index] = x; - buffer[index + 1] = y; - } - - public void lineTo(float x, float y) { - - if (index == 2) { - buffer[index++] = x; - buffer[index++] = y; - } else { - - float prevX = buffer[index - 2]; - float prevY = buffer[index - 1]; - buffer[index++] = prevX; - buffer[index++] = prevY; - buffer[index++] = x; - buffer[index++] = y; - } - } - - @Override - public void feed(ILineDataSet data) { - moveTo(data.getEntryForIndex(mFrom).getXIndex(), data.getEntryForIndex(mFrom).getVal() * phaseY); - - int size = (int) Math.ceil((mTo - mFrom) * phaseX + mFrom); - int from = mFrom + 1; - - for (int i = from; i < size; i++) { - - Entry e = data.getEntryForIndex(i); - lineTo(e.getXIndex(), e.getVal() * phaseY); - } - - reset(); - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index ec266ec789..e384d1b4da 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -8,8 +8,6 @@ import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.buffer.CircleBuffer; -import com.github.mikephil.charting.buffer.LineBuffer; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -52,10 +50,6 @@ public class LineChartRenderer extends LineRadarRenderer { protected Path cubicPath = new Path(); protected Path cubicFillPath = new Path(); - protected LineBuffer[] mLineBuffers; - - protected CircleBuffer[] mCircleBuffers; - public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); @@ -69,15 +63,6 @@ public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, @Override public void initBuffers() { - LineData lineData = mChart.getLineData(); - mLineBuffers = new LineBuffer[lineData.getDataSetCount()]; - mCircleBuffers = new CircleBuffer[lineData.getDataSetCount()]; - - for (int i = 0; i < mLineBuffers.length; i++) { - ILineDataSet set = lineData.getDataSetByIndex(i); - mLineBuffers[i] = new LineBuffer(set.getEntryCount() * 4 - 4); - mCircleBuffers[i] = new CircleBuffer(set.getEntryCount() * 2); - } } @Override @@ -148,8 +133,8 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff - 1, 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entryCount); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -230,7 +215,7 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet) { cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, - entryFrom.getXIndex(), entryFrom.getXIndex() + size); + minx, size); } mRenderPaint.setColor(dataSet.getColor()); @@ -278,6 +263,8 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf } } + private float[] mLineBuffer = new float[4]; + /** * Draws a normal line. * @@ -288,8 +275,6 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseX = mAnimator.getPhaseX(); @@ -309,50 +294,102 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); - int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entryCount); - - int range = (maxx - minx) * 4 - 4; - - LineBuffer buffer = mLineBuffers[dataSetIndex]; - buffer.setPhases(phaseX, phaseY); - buffer.limitFrom(minx); - buffer.limitTo(maxx); - buffer.feed(dataSet); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - trans.pointValuesToPixel(buffer.buffer); + final int count = (int)(Math.ceil((float)(maxx - minx) * phaseX + (float)(minx))); // more than 1 color if (dataSet.getColors().size() > 1) { - for (int j = 0; j < range; j += 4) { + if (mLineBuffer.length != 2 * 2) + mLineBuffer = new float[2 * 2]; + + for (int j = minx; + j < count; + j++) { + + if (count > 1 && j == count - 1) { + // Last point, we have already drawn a line to this point + break; + } + + Entry e = dataSet.getEntryForIndex(j); + if (e == null) continue; + + mLineBuffer[0] = e.getXIndex(); + mLineBuffer[1] = e.getVal() * phaseY; + + if (j + 1 < count) { + + e = dataSet.getEntryForIndex(j + 1); + + if (e == null) break; + + mLineBuffer[2] = e.getXIndex(); + mLineBuffer[3] = e.getVal() * phaseY; + } else { + mLineBuffer[2] = mLineBuffer[0]; + mLineBuffer[3] = mLineBuffer[1]; + } + + trans.pointValuesToPixel(mLineBuffer); - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + if (!mViewPortHandler.isInBoundsRight(mLineBuffer[0])) break; // make sure the lines don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]) - || (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 1]) && !mViewPortHandler - .isInBoundsBottom(buffer.buffer[j + 3])) - || (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 1]) && !mViewPortHandler - .isInBoundsBottom(buffer.buffer[j + 3]))) + if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2]) + || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler + .isInBoundsBottom(mLineBuffer[3])) + || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler + .isInBoundsBottom(mLineBuffer[3]))) continue; // get the color that is set for this line-segment - mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); + mRenderPaint.setColor(dataSet.getColor(j)); - canvas.drawLine(buffer.buffer[j], buffer.buffer[j + 1], - buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); + canvas.drawLine(mLineBuffer[0], mLineBuffer[1], + mLineBuffer[2], mLineBuffer[3], mRenderPaint); } } else { // only one color per dataset - mRenderPaint.setColor(dataSet.getColor()); + if (mLineBuffer.length != Math.max((entryCount - 1) * 2, 2) * 2) + mLineBuffer = new float[Math.max((entryCount - 1) * 2, 2) * 2]; + + Entry e1, e2; + + e1 = dataSet.getEntryForIndex(minx); + + if (e1 != null) { + + for (int x = count > 1 ? minx + 1 : minx, j = 0; x < count; x++) { + + e1 = dataSet.getEntryForIndex(x == 0 ? 0 : (x - 1)); + e2 = dataSet.getEntryForIndex(x); + + if (e1 == null || e2 == null) continue; + + mLineBuffer[j] = e1.getXIndex(); + mLineBuffer[j + 1] = e1.getVal() * phaseY; + mLineBuffer[j + 2] = e2.getXIndex(); + mLineBuffer[j + 3] = e2.getVal() * phaseY; + j += 4; + + } + + trans.pointValuesToPixel(mLineBuffer); + + final int size = Math.max((count - minx - 1) * 2, 2) * 2; - // c.drawLines(buffer.buffer, mRenderPaint); - canvas.drawLines(buffer.buffer, 0, range, - mRenderPaint); + mRenderPaint.setColor(dataSet.getColor()); + + canvas.drawLines(mLineBuffer, 0, size, + mRenderPaint); + } } mRenderPaint.setPathEffect(null); @@ -447,11 +484,13 @@ public void drawValues(Canvas c) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); + Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, + DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); - int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entryCount); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); float[] positions = trans.generateTransformedValuesLine( dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -488,6 +527,8 @@ protected void drawCircles(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + float[] circlesBuffer = new float[2]; + List dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { @@ -504,45 +545,49 @@ protected void drawCircles(Canvas c) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); + Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, + DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); - int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entryCount); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - CircleBuffer buffer = mCircleBuffers[i]; - buffer.setPhases(phaseX, phaseY); - buffer.limitFrom(minx); - buffer.limitTo(maxx); - buffer.feed(dataSet); + float halfsize = dataSet.getCircleRadius() / 2f; - trans.pointValuesToPixel(buffer.buffer); + for (int j = minx, + count = (int) Math.ceil((maxx - minx) * phaseX + minx); + j < count; + j ++) { - float halfsize = dataSet.getCircleRadius() / 2f; + Entry e = dataSet.getEntryForIndex(j); + + if (e == null) break; - for (int j = 0, count = (int) Math.ceil((maxx - minx) * phaseX + minx) * 2; j < count; j += 2) { + circlesBuffer[0] = e.getXIndex(); + circlesBuffer[1] = e.getVal() * phaseY; - float x = buffer.buffer[j]; - float y = buffer.buffer[j + 1]; + trans.pointValuesToPixel(circlesBuffer); - if (!mViewPortHandler.isInBoundsRight(x)) + if (!mViewPortHandler.isInBoundsRight(circlesBuffer[0])) break; // make sure the circles don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) + if (!mViewPortHandler.isInBoundsLeft(circlesBuffer[0]) || + !mViewPortHandler.isInBoundsY(circlesBuffer[1])) continue; - int circleColor = dataSet.getCircleColor(j / 2 + minx); + int circleColor = dataSet.getCircleColor(j); mRenderPaint.setColor(circleColor); - c.drawCircle(x, y, dataSet.getCircleRadius(), + c.drawCircle(circlesBuffer[0], circlesBuffer[1], dataSet.getCircleRadius(), mRenderPaint); if (dataSet.isDrawCircleHoleEnabled() && circleColor != mCirclePaintInner.getColor()) - c.drawCircle(x, y, + c.drawCircle(circlesBuffer[0], circlesBuffer[1], halfsize, mCirclePaintInner); } From 7b8203020de566ecd7b748848e62b5c489735532 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 9 Mar 2016 23:56:18 +0200 Subject: [PATCH 0792/1390] Added stepped line chart support --- MPChartExample/res/menu/line.xml | 6 +- .../mpchartexample/LineChartActivity1.java | 15 +++++ .../mpchartexample/LineChartActivity2.java | 15 +++++ .../mikephil/charting/data/LineDataSet.java | 20 +++++++ .../implementation/RealmLineDataSet.java | 22 ++++++++ .../interfaces/datasets/ILineDataSet.java | 7 +++ .../charting/renderer/LineChartRenderer.java | 55 ++++++++++++++----- 7 files changed, 125 insertions(+), 15 deletions(-) diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index 42ca211c06..8d1437029b 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -13,10 +13,14 @@ android:id="@+id/actionToggleCircles" android:title="Toggle Circles"> - + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 0c331f1738..1b10e12188 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -242,6 +242,21 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleStepped: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawSteppedEnabled()) + set.setDrawStepped(false); + else + set.setDrawStepped(true); + } + mChart.invalidate(); + break; + } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 2d1f3baf29..8efad8692d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -200,6 +200,21 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleStepped: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawSteppedEnabled()) + set.setDrawStepped(false); + else + set.setDrawStepped(true); + } + mChart.invalidate(); + break; + } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 0f22668500..7d9da1ac55 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -41,6 +41,9 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** if true, cubic lines are drawn instead of linear */ private boolean mDrawCubic = false; + /** if true, stepped lines are drawn instead of linear */ + private boolean mDrawStepped = false; + private boolean mDrawCircleHole = true; @@ -201,6 +204,23 @@ public boolean isDrawCubicEnabled() { return mDrawCubic; } + /** + * If set to true, the linechart lines are drawn in stepped-style instead of + * linear. + * This does not work with cubic lines, of course. + * Default: false + * + * @param enabled + */ + public void setDrawStepped(boolean enabled) { + mDrawStepped = enabled; + } + + @Override + public boolean isDrawSteppedEnabled() { + return mDrawStepped; + } + /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index 775ab665ff..ccea3823d4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -63,6 +63,11 @@ public class RealmLineDataSet extends RealmLineRadarDataS */ private boolean mDrawCubic = false; + /** + * if true, stepped lines are drawn instead of linear + */ + private boolean mDrawStepped = false; + private boolean mDrawCircleHole = true; /** @@ -203,6 +208,23 @@ public boolean isDrawCubicEnabled() { return mDrawCubic; } + /** + * If set to true, the linechart lines are drawn in stepped-style instead of + * linear. + * This does not work with cubic lines, of course. + * Default: false + * + * @param enabled + */ + public void setDrawStepped(boolean enabled) { + mDrawStepped = enabled; + } + + @Override + public boolean isDrawSteppedEnabled() { + return mDrawStepped; + } + /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ /** diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 9b7dd0558e..16a8f061cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -26,6 +26,13 @@ public interface ILineDataSet extends ILineRadarDataSet { */ boolean isDrawCubicEnabled(); + /** + * Returns true if drawing stepped lines is enabled, false if not. + * + * @return + */ + boolean isDrawSteppedEnabled(); + /** * Returns the size of the drawn circles. */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index e384d1b4da..dc2facdf14 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -275,6 +275,9 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); + final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); + final int pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2; + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseX = mAnimator.getPhaseX(); @@ -303,8 +306,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // more than 1 color if (dataSet.getColors().size() > 1) { - if (mLineBuffer.length != 2 * 2) - mLineBuffer = new float[2 * 2]; + if (mLineBuffer.length != pointsPerEntryPair * 2) + mLineBuffer = new float[pointsPerEntryPair * 2]; for (int j = minx; j < count; @@ -327,8 +330,18 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (e == null) break; - mLineBuffer[2] = e.getXIndex(); - mLineBuffer[3] = e.getVal() * phaseY; + if (isDrawSteppedEnabled) { + mLineBuffer[2] = e.getXIndex(); + mLineBuffer[3] = mLineBuffer[1]; + mLineBuffer[4] = mLineBuffer[2]; + mLineBuffer[5] = mLineBuffer[3]; + mLineBuffer[6] = e.getXIndex(); + mLineBuffer[7] = e.getVal() * phaseY; + } else { + mLineBuffer[2] = e.getXIndex(); + mLineBuffer[3] = e.getVal() * phaseY; + } + } else { mLineBuffer[2] = mLineBuffer[0]; mLineBuffer[3] = mLineBuffer[1]; @@ -351,14 +364,13 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // get the color that is set for this line-segment mRenderPaint.setColor(dataSet.getColor(j)); - canvas.drawLine(mLineBuffer[0], mLineBuffer[1], - mLineBuffer[2], mLineBuffer[3], mRenderPaint); + canvas.drawLines(mLineBuffer, 0, pointsPerEntryPair * 2, mRenderPaint); } } else { // only one color per dataset - if (mLineBuffer.length != Math.max((entryCount - 1) * 2, 2) * 2) - mLineBuffer = new float[Math.max((entryCount - 1) * 2, 2) * 2]; + if (mLineBuffer.length != Math.max((entryCount - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2) + mLineBuffer = new float[Math.max((entryCount - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2]; Entry e1, e2; @@ -373,17 +385,23 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (e1 == null || e2 == null) continue; - mLineBuffer[j] = e1.getXIndex(); - mLineBuffer[j + 1] = e1.getVal() * phaseY; - mLineBuffer[j + 2] = e2.getXIndex(); - mLineBuffer[j + 3] = e2.getVal() * phaseY; - j += 4; + mLineBuffer[j++] = e1.getXIndex(); + mLineBuffer[j++] = e1.getVal() * phaseY; + if (isDrawSteppedEnabled) { + mLineBuffer[j++] = e2.getXIndex(); + mLineBuffer[j++] = e1.getVal() * phaseY; + mLineBuffer[j++] = e2.getXIndex(); + mLineBuffer[j++] = e1.getVal() * phaseY; + } + + mLineBuffer[j++] = e2.getXIndex(); + mLineBuffer[j++] = e2.getVal() * phaseY; } trans.pointValuesToPixel(mLineBuffer); - final int size = Math.max((count - minx - 1) * 2, 2) * 2; + final int size = Math.max((count - minx - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; mRenderPaint.setColor(dataSet.getColor()); @@ -430,6 +448,7 @@ private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); Path filled = new Path(); Entry entry = dataSet.getEntryForIndex(from); @@ -441,6 +460,14 @@ private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { for (int x = from + 1, count = (int) Math.ceil((to - from) * phaseX + from); x < count; x++) { Entry e = dataSet.getEntryForIndex(x); + + if (isDrawSteppedEnabled) { + final Entry ePrev = dataSet.getEntryForIndex(x - 1); + if (ePrev == null) continue; + + filled.lineTo(e.getXIndex(), ePrev.getVal() * phaseY); + } + filled.lineTo(e.getXIndex(), e.getVal() * phaseY); } From 3995941c3cf22e8d0af0df5af4cadfb055d31f05 Mon Sep 17 00:00:00 2001 From: Leo Mehlig Date: Thu, 10 Mar 2016 13:44:16 +0100 Subject: [PATCH 0793/1390] Keep position on rotation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I’ve added a flag (keepPositionOnRotation) to BarLineChartBase indicating whether the chart should stay at its current position or not. --- .../charting/charts/BarLineChartBase.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index bc810343d2..5665553fc2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -106,6 +106,11 @@ public abstract class BarLineChartBase Date: Thu, 10 Mar 2016 17:09:27 +0100 Subject: [PATCH 0794/1390] Add contribution file --- CONTRIBUTING.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..a6fb7cac57 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,49 @@ +# How to contribute + +Bug-fixes and features often come from users of the Charts framework, and improving it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we +need contributors to follow so that we can have a chance of keeping on +top of things. + +## Simple issues and bug reports + +If you are reporting a bug which can be observed visually, please add to your issue either: + +* Screenshots, if the bug is easily explainable +* A working sample project that we can compile, run, and immediately observe the issue + +## Getting Started with Contributions + +* Make sure you have a [GitHub account](https://github.com/signup/free) +* Submit a ticket for your issue, assuming one does not already exist. + * Clearly describe the issue including steps to reproduce when it is a bug. + * Make sure you fill in the earliest version (or commit number) that you know has the issue. +* Fork the repository on GitHub + +## Making Changes + +* Create a topic branch from where you want to base your work. This is usually the master branch. +* Make commits of logical units. +* Make sure your code conforms to the code style around it. It's easy, just look around! +* If you have made changes back and forth, or have made merges, your commit history might look messy and hard to understand. A single issue or change should still be in one commit. So please squash those commits together and rebase them however you need to - to make our lives easier when reading it later. +* Check for unnecessary whitespace with `git diff --check` before committing. +* Make sure your commit messages are in the proper format. + +```` + First line must be up to 50 chars (Fixes #1234) + + The first line should be a short statement as to what have changed, and should also include an issue number, prefixed with a dash. + The body of the message comes after an empty new line, and describes the changes + more thoroughly, especially if there was a special case handled there, + or maybe some trickery that only code wizards can understand. +```` + +* Make sure you have tested your changes well. +* If your changes could theoretically affect some other component or case, which you do not necessarily use, you still have to test it. +* Create a Pull Request from your topic branch to the relevant branch in the main repo. If you go to the main repo of the framework, you'll see a big green button which pretty much prepares the PR for you. You just have to hit it. + +## Making Trivial Changes + +For changes of a trivial nature to comments and documentation, it is not +always necessary to create a new ticket. In this case, it is +appropriate to start the first line of a commit with '(doc)' instead of +a ticket number. Even the default commit message the GitHub generates is fine with us. \ No newline at end of file From a6ce45f9ac608972aec11b340c0a2cef050d796d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Mar 2016 17:20:36 +0100 Subject: [PATCH 0795/1390] Fix issue #1561 --- .../charting/renderer/BarChartRenderer.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 763fb87986..3ec7209b48 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -96,6 +96,23 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + // draw the bar shadow before the values + if (mChart.isDrawBarShadowEnabled()) { + + for (int j = 0; j < buffer.size(); j += 4) { + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + continue; + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + break; + + c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), + buffer.buffer[j + 2], + mViewPortHandler.contentBottom(), mShadowPaint); + } + } + // if multiple colors if (dataSet.getColors().size() > 1) { @@ -107,12 +124,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; - if (mChart.isDrawBarShadowEnabled()) { - c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), - buffer.buffer[j + 2], - mViewPortHandler.contentBottom(), mShadowPaint); - } - // Set the color for the currently drawn value. If the index // is // out of bounds, reuse colors. @@ -132,12 +143,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; - if (mChart.isDrawBarShadowEnabled()) { - c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), - buffer.buffer[j + 2], - mViewPortHandler.contentBottom(), mShadowPaint); - } - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); } From 21f43ed3f0e452d7598bd6f915f76628a0ca5d71 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Mar 2016 23:36:30 +0100 Subject: [PATCH 0796/1390] Minor fix related to #1565 --- .../mikephil/charting/charts/BarLineChartBase.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 5665553fc2..6b7ecc71b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -304,9 +304,12 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { //Superclass transforms chart. super.onSizeChanged(w, h, oldw, oldh); - //Restoring old position of chart. - getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); - mViewPortHandler.centerViewPort(pts, this); + if(mKeepPositionOnRotation) { + + //Restoring old position of chart. + getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, this); + } } /** @@ -1238,7 +1241,7 @@ public boolean isKeepPositionOnRotation() { } /** - * Sets the whether the chart should keep its position after a rotation. + * Sets whether the chart should keep its position (zoom / scroll) after a rotation (orientation change) */ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { mKeepPositionOnRotation = keepPositionOnRotation; From 7009cc8b967bac46a88535005aec66598d8336a4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Mar 2016 23:37:06 +0100 Subject: [PATCH 0797/1390] Move onSizeChanged(...) --- .../charting/charts/BarLineChartBase.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 6b7ecc71b9..044fb2e5fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -293,25 +293,6 @@ protected void onDraw(Canvas canvas) { } } - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - //Saving current position of chart. - float[] pts = new float[2]; - pts[0] = mViewPortHandler.contentLeft(); - pts[1] = mViewPortHandler.contentTop(); - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - - //Superclass transforms chart. - super.onSizeChanged(w, h, oldw, oldh); - - if(mKeepPositionOnRotation) { - - //Restoring old position of chart. - getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); - mViewPortHandler.centerViewPort(pts, this); - } - } - /** * RESET PERFORMANCE TRACKING FIELDS */ @@ -1614,4 +1595,23 @@ public Paint getPaint(int which) { return null; } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + //Saving current position of chart. + float[] pts = new float[2]; + pts[0] = mViewPortHandler.contentLeft(); + pts[1] = mViewPortHandler.contentTop(); + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + + //Superclass transforms chart. + super.onSizeChanged(w, h, oldw, oldh); + + if(mKeepPositionOnRotation) { + + //Restoring old position of chart. + getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); + mViewPortHandler.centerViewPort(pts, this); + } + } } From 07d7813ccb44ab9369c0d1d162dc861d140a1a69 Mon Sep 17 00:00:00 2001 From: Anant Singh Date: Sat, 12 Mar 2016 23:25:51 +0530 Subject: [PATCH 0798/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6e24af64a7..90736a4aa2 100644 --- a/README.md +++ b/README.md @@ -72,14 +72,14 @@ Features - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) - Dual (separate) Axes - - Customizeable Axes (both x- and y-axis) - - Highlighting values (with customizeable popup-views) + - Customizable Axes (both x- and y-axis) + - Highlighting values (with customizable popup-views) - Save chart to SD-Card (as image, or as .txt file) - Predefined color templates - - Legends (generated automatically, customizeable) + - Legends (generated automatically, customizable) - Animations (build up animations, on both x- and y-axis) - Limit lines (providing additional information, maximums, ...) - - Fully customizeable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) + - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart - Gradle support - Plotting data directly from [**Realm.io**](https://realm.io) mobile database From f1bc0d05d9e588d35194985fca065f26e963f271 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 13 Mar 2016 13:44:10 +0100 Subject: [PATCH 0799/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90736a4aa2..058aa739f1 100644 --- a/README.md +++ b/README.md @@ -10,14 +10,14 @@ Remember: *It's all about the looks.* [**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. -As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) :zap:. +As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) :zap: Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). Spread the word ----- -If you like this library, please tell others about it :two_hearts: +If you like this library, please tell others about it :two_hearts: :two_hearts: From 677d8ef2d45d8973af57ce106c10e17b61135aa5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 15 Mar 2016 23:37:02 +0100 Subject: [PATCH 0800/1390] Add documentation --- .../charting/interfaces/datasets/ILineRadarDataSet.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java index 4ed43f03e8..ce89822716 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java @@ -47,8 +47,10 @@ public interface ILineRadarDataSet extends ILineScatterCandleRa /** * Set to true if the DataSet should be drawn filled (surface), and not just - * as a line, disabling this will give great performance boost! default: - * false + * as a line, disabling this will give great performance boost. Please note that this method + * uses the canvas.clipPath(...) method for drawing the filled area. + * For devices with API level < 18 (Android 4.3), hardware acceleration of the chart should + * be turned off. Default: false * * @param enabled */ From 71fede97b32f58219ee1fc1f8c8fc51c4d4ac5e9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 16 Mar 2016 14:48:09 +0100 Subject: [PATCH 0801/1390] Fix #1584 --- .../src/com/github/mikephil/charting/data/CandleDataSet.java | 2 +- .../charting/data/realm/implementation/RealmCandleDataSet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 03f09251bf..c63ccee1df 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -171,7 +171,7 @@ public float getShadowWidth() { * * @param showCandleBar */ - public void setShadowWidth(boolean showCandleBar) { + public void setShowCandleBar(boolean showCandleBar) { mShowCandleBar = showCandleBar; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 8c7c9c8e78..def4e4e935 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -215,7 +215,7 @@ public float getShadowWidth() { * * @param showCandleBar */ - public void setShadowWidth(boolean showCandleBar) { + public void setShowCandleBar(boolean showCandleBar) { mShowCandleBar = showCandleBar; } From 20dd3b8ef1d6968f8160e13085d0cabdab2c9fed Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 17 Mar 2016 00:18:21 +0100 Subject: [PATCH 0802/1390] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 058aa739f1..5513d354e8 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,14 @@ Questions & Issues If you are having questions or problems, you should: + - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) -Please do not expect answers to your questions if you have not considered all above mentioned points in advance. +Please do not expect answers to your questions if you have not considered all above mentioned approaches in advance. Features ----- From 1ba4b413e86a9e60921c087a09fd71f45848219a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 17 Mar 2016 09:11:11 +0100 Subject: [PATCH 0803/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5513d354e8..78b802778e 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Questions & Issues If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). + - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) From dd50c2e49e2508d13c42eb8318756be8959b1f0b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 12:19:36 +0200 Subject: [PATCH 0804/1390] Avoid extra computed when not needed --- .../mikephil/charting/charts/BarLineChartBase.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 044fb2e5fd..8364e804aa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1598,16 +1598,19 @@ public Paint getPaint(int which) { @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - //Saving current position of chart. + + // Saving current position of chart. float[] pts = new float[2]; - pts[0] = mViewPortHandler.contentLeft(); - pts[1] = mViewPortHandler.contentTop(); - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + if (mKeepPositionOnRotation) { + pts[0] = mViewPortHandler.contentLeft(); + pts[1] = mViewPortHandler.contentTop(); + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + } //Superclass transforms chart. super.onSizeChanged(w, h, oldw, oldh); - if(mKeepPositionOnRotation) { + if (mKeepPositionOnRotation) { //Restoring old position of chart. getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); From a7da427e26ae9f759af6de6fcec27ad2f3b791ce Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 12:41:21 +0200 Subject: [PATCH 0805/1390] Fixed a bug where after rotation/resize the matrix stays out of bounds This bug existed before "keepPositionOnRotation". In my opinion - keepPositionOnRotation should be default... --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 8364e804aa..a96eb08487 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1615,6 +1615,8 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { //Restoring old position of chart. getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); mViewPortHandler.centerViewPort(pts, this); + } else { + mViewPortHandler.refresh(mViewPortHandler.getMatrixTouch(), this, true); } } } From 6347d680c8d8c7f3fa2fbf8747c2504ddbca3048 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 15:24:59 +0200 Subject: [PATCH 0806/1390] Added feature for highlight circle in radar chart --- MPChartExample/res/menu/radar.xml | 4 + .../mpchartexample/RadarChartActivitry.java | 11 ++ .../mikephil/charting/data/RadarDataSet.java | 103 +++++++++++++++++- .../implementation/RealmRadarDataSet.java | 101 +++++++++++++++++ .../interfaces/datasets/IRadarDataSet.java | 19 ++++ .../charting/renderer/RadarChartRenderer.java | 59 ++++++++++ .../charting/utils/ColorTemplate.java | 4 + 7 files changed, 300 insertions(+), 1 deletion(-) diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/res/menu/radar.xml index 8dbcf05e9c..3565065baa 100644 --- a/MPChartExample/res/menu/radar.xml +++ b/MPChartExample/res/menu/radar.xml @@ -13,6 +13,10 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index dbbdc695c8..e637a37efe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -124,6 +124,17 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleHighlightCircle: { + + ArrayList sets = (ArrayList) mChart.getData() + .getDataSets(); + + for (IRadarDataSet set : sets) { + set.setDrawHighlightCircleEnabled(!set.isDrawHighlightCircleEnabled()); + } + mChart.invalidate(); + break; + } case R.id.actionSave: { if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java index 189ac032a9..61ea26d5a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java @@ -1,17 +1,118 @@ package com.github.mikephil.charting.data; +import android.graphics.Color; + import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import java.util.ArrayList; import java.util.List; public class RadarDataSet extends LineRadarDataSet implements IRadarDataSet { - + + /// flag indicating whether highlight circle should be drawn or not + protected boolean mDrawHighlightCircleEnabled = false; + + protected int mHighlightCircleFillColor = Color.WHITE; + + /// The stroke color for highlight circle. + /// If Utils.COLOR_NONE, the color of the dataset is taken. + protected int mHighlightCircleStrokeColor = ColorTemplate.COLOR_NONE; + + protected int mHighlightCircleStrokeAlpha = (int)(0.3 * 255); + protected float mHighlightCircleInnerRadius = 3.0f; + protected float mHighlightCircleOuterRadius = 4.0f; + protected float mHighlightCircleStrokeWidth = 2.0f; + public RadarDataSet(List yVals, String label) { super(yVals, label); } + /// Returns true if highlight circle should be drawn, false if not + @Override + public boolean isDrawHighlightCircleEnabled() + { + return mDrawHighlightCircleEnabled; + } + + /// Sets whether highlight circle should be drawn or not + @Override + public void setDrawHighlightCircleEnabled(boolean enabled) + { + mDrawHighlightCircleEnabled = enabled; + } + + @Override + public int getHighlightCircleFillColor() + { + return mHighlightCircleFillColor; + } + + public void setHighlightCircleFillColor(int color) + { + mHighlightCircleFillColor = color; + } + + /// Returns the stroke color for highlight circle. + /// If Utils.COLOR_NONE, the color of the dataset is taken. + @Override + public int getHighlightCircleStrokeColor() + { + return mHighlightCircleStrokeColor; + } + + /// Sets the stroke color for highlight circle. + /// Set to Utils.COLOR_NONE in order to use the color of the dataset; + public void setHighlightCircleStrokeColor(int color) + { + mHighlightCircleStrokeColor = color; + } + + @Override + public int getHighlightCircleStrokeAlpha() + { + return mHighlightCircleStrokeAlpha; + } + + public void setHighlightCircleStrokeAlpha(int alpha) + { + mHighlightCircleStrokeAlpha = alpha; + } + + @Override + public float getHighlightCircleInnerRadius() + { + return mHighlightCircleInnerRadius; + } + + public void setHighlightCircleInnerRadius(float radius) + { + mHighlightCircleInnerRadius = radius; + } + + @Override + public float getHighlightCircleOuterRadius() + { + return mHighlightCircleOuterRadius; + } + + public void setHighlightCircleOuterRadius(float radius) + { + mHighlightCircleOuterRadius = radius; + } + + @Override + public float getHighlightCircleStrokeWidth() + { + return mHighlightCircleStrokeWidth; + } + + public void setHighlightCircleStrokeWidth(float strokeWidth) + { + mHighlightCircleStrokeWidth = strokeWidth; + } + @Override public DataSet copy() { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 2c0d8457a8..aa2dc2fdfc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -1,7 +1,10 @@ package com.github.mikephil.charting.data.realm.implementation; +import android.graphics.Color; + import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import io.realm.RealmObject; import io.realm.RealmResults; @@ -11,6 +14,20 @@ */ public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { + /// flag indicating whether highlight circle should be drawn or not + protected boolean mDrawHighlightCircleEnabled = false; + + protected int mHighlightCircleFillColor = Color.WHITE; + + /// The stroke color for highlight circle. + /// If Utils.COLOR_NONE, the color of the dataset is taken. + protected int mHighlightCircleStrokeColor = ColorTemplate.COLOR_NONE; + + protected int mHighlightCircleStrokeAlpha = (int)(0.3 * 255); + protected float mHighlightCircleInnerRadius = 3.0f; + protected float mHighlightCircleOuterRadius = 4.0f; + protected float mHighlightCircleStrokeWidth = 2.0f; + /** * Constructor for creating a RadarDataSet with realm data. * @@ -38,6 +55,90 @@ public RealmRadarDataSet(RealmResults result, String yValuesField, String xIn calcMinMax(0, results.size()); } + /// Returns true if highlight circle should be drawn, false if not + @Override + public boolean isDrawHighlightCircleEnabled() + { + return mDrawHighlightCircleEnabled; + } + + /// Sets whether highlight circle should be drawn or not + @Override + public void setDrawHighlightCircleEnabled(boolean enabled) + { + mDrawHighlightCircleEnabled = enabled; + } + + @Override + public int getHighlightCircleFillColor() + { + return mHighlightCircleFillColor; + } + + public void setHighlightCircleFillColor(int color) + { + mHighlightCircleFillColor = color; + } + + /// Returns the stroke color for highlight circle. + /// If Utils.COLOR_NONE, the color of the dataset is taken. + @Override + public int getHighlightCircleStrokeColor() + { + return mHighlightCircleStrokeColor; + } + + /// Sets the stroke color for highlight circle. + /// Set to Utils.COLOR_NONE in order to use the color of the dataset; + public void setHighlightCircleStrokeColor(int color) + { + mHighlightCircleStrokeColor = color; + } + + @Override + public int getHighlightCircleStrokeAlpha() + { + return mHighlightCircleStrokeAlpha; + } + + public void setHighlightCircleStrokeAlpha(int alpha) + { + mHighlightCircleStrokeAlpha = alpha; + } + + @Override + public float getHighlightCircleInnerRadius() + { + return mHighlightCircleInnerRadius; + } + + public void setHighlightCircleInnerRadius(float radius) + { + mHighlightCircleInnerRadius = radius; + } + + @Override + public float getHighlightCircleOuterRadius() + { + return mHighlightCircleOuterRadius; + } + + public void setHighlightCircleOuterRadius(float radius) + { + mHighlightCircleOuterRadius = radius; + } + + @Override + public float getHighlightCircleStrokeWidth() + { + return mHighlightCircleStrokeWidth; + } + + public void setHighlightCircleStrokeWidth(float strokeWidth) + { + mHighlightCircleStrokeWidth = strokeWidth; + } + @Override public void build(RealmResults results) { super.build(results); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java index 22ea37dc72..6d725df7d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java @@ -7,5 +7,24 @@ */ public interface IRadarDataSet extends ILineRadarDataSet { + /// flag indicating whether highlight circle should be drawn or not + boolean isDrawHighlightCircleEnabled(); + + /// Sets whether highlight circle should be drawn or not + void setDrawHighlightCircleEnabled(boolean enabled); + + int getHighlightCircleFillColor(); + + /// The stroke color for highlight circle. + /// If Utils.COLOR_NONE, the color of the dataset is taken. + int getHighlightCircleStrokeColor(); + + int getHighlightCircleStrokeAlpha(); + + float getHighlightCircleInnerRadius(); + + float getHighlightCircleOuterRadius(); + + float getHighlightCircleStrokeWidth(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 3888df9bef..03a333a616 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -25,6 +26,7 @@ public class RadarChartRenderer extends LineRadarRenderer { * paint for drawing the web */ protected Paint mWebPaint; + protected Paint mHighlightCirclePaint; public RadarChartRenderer(RadarChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -38,6 +40,8 @@ public RadarChartRenderer(RadarChart chart, ChartAnimator animator, mWebPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mWebPaint.setStyle(Paint.Style.STROKE); + + mHighlightCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); } public Paint getWebPaint() { @@ -289,7 +293,62 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // draw the lines drawHighlightLines(c, pts, set); + + if (set.isDrawHighlightCircleEnabled()) { + + if (!Float.isNaN(pts[0]) && !Float.isNaN(pts[1])) { + + int strokeColor = set.getHighlightCircleStrokeColor(); + if (strokeColor == ColorTemplate.COLOR_NONE) { + strokeColor = set.getColor(0); + } + + if (set.getHighlightCircleStrokeAlpha() < 255) { + strokeColor = ColorTemplate.getColorWithAlphaComponent(strokeColor, set.getHighlightCircleStrokeAlpha()); + } + + drawHighlightCircle(c, + p, + set.getHighlightCircleInnerRadius(), + set.getHighlightCircleOuterRadius(), + set.getHighlightCircleFillColor(), + strokeColor, + set.getHighlightCircleStrokeWidth()); + } + } } } + public void drawHighlightCircle(Canvas c, + PointF point, + float innerRadius, + float outerRadius, + int fillColor, + int strokeColor, + float strokeWidth) { + c.save(); + + outerRadius = Utils.convertDpToPixel(outerRadius); + innerRadius = Utils.convertDpToPixel(innerRadius); + + if (fillColor != ColorTemplate.COLOR_NONE) { + Path p = new Path(); + p.addCircle(point.x, point.y, outerRadius, Path.Direction.CW); + if (innerRadius > 0.f) { + p.addCircle(point.x, point.y, innerRadius, Path.Direction.CCW); + } + mHighlightCirclePaint.setColor(fillColor); + mHighlightCirclePaint.setStyle(Paint.Style.FILL); + c.drawPath(p, mHighlightCirclePaint); + } + + if (strokeColor != ColorTemplate.COLOR_NONE) { + mHighlightCirclePaint.setColor(strokeColor); + mHighlightCirclePaint.setStyle(Paint.Style.STROKE); + mHighlightCirclePaint.setStrokeWidth(Utils.convertDpToPixel(strokeWidth)); + c.drawCircle(point.x, point.y, outerRadius, mHighlightCirclePaint); + } + + c.restore(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java index 441d77b484..f881d11629 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java @@ -75,6 +75,10 @@ public static int getHoloBlue() { return Color.rgb(51, 181, 229); } + public static int getColorWithAlphaComponent(int color, int alpha) { + return (color & 0xffffff) | ((alpha & 0xff) << 24); + } + /** * turn an array of resource-colors (contains resource-id integers) into an * array list of actual color integers From d430dd61fba373fcf425b9474596657627e13a45 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 16:21:32 +0200 Subject: [PATCH 0807/1390] Prevent repeated y-axis values by controlling granularity --- .../mpchartexample/LineChartActivity2.java | 2 + .../mikephil/charting/components/YAxis.java | 43 +++++++++++++++++++ .../charting/renderer/YAxisRenderer.java | 8 ++++ 3 files changed, 53 insertions(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 8efad8692d..d7df678923 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -114,6 +114,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(200f); leftAxis.setAxisMinValue(0f); leftAxis.setDrawGridLines(true); + leftAxis.setGranularityEnabled(true); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(tf); @@ -122,6 +123,7 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setAxisMinValue(-200); rightAxis.setDrawGridLines(false); rightAxis.setDrawZeroLine(false); + rightAxis.setGranularityEnabled(false); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index ce0f19f0a8..bebaffe5c8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -123,6 +123,19 @@ public enum YAxisLabelPosition { */ private AxisDependency mAxisDependency; + /** + * When true, axis labels are controlled by the `granularity` property. + * When false, axis values could possibly be repeated. + * This could happen if two adjacent axis values are rounded to same value. + * If using granularity this could be avoided by having fewer axis values visible. + */ + protected boolean mGranularityEnabled = true; + + /** + * the minimum interval between axis values + */ + protected float mGranularity = 1.0f; + /** * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. * @@ -148,6 +161,36 @@ public AxisDependency getAxisDependency() { return mAxisDependency; } + /** + * @return true if granularity is enabled + */ + public boolean isGranularityEnabled() { + return mGranularityEnabled; + } + + /** + * Enabled/disable granularity control on axis value intervals + * @param enabled + */ + public void setGranularityEnabled(boolean enabled) { + mGranularityEnabled = true; + } + + /** + * @return the minimum interval between axis values + */ + public float getGranularity() { + return mGranularity; + } + + /** + * set the minimum interval between axis values + * @param granularity + */ + public void setGranularity(float granularity) { + mGranularity = granularity; + } + /** * returns the position of the y-labels */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index cfd46fed07..b9a03ef8ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -85,8 +85,16 @@ protected void computeAxisValues(float min, float max) { return; } + // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); + + // If granularity is enabled, then do not allow the interval to go below specified granularity. + // This is used to avoid repeated values when rounding values for display. + if (mYAxis.isGranularityEnabled()) + interval = interval < mYAxis.getGranularity() ? mYAxis.getGranularity() : interval; + + // Normalize interval double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { From a19ffad0461b15388e2a631198c93c5aad5c7e14 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 17:15:34 +0200 Subject: [PATCH 0808/1390] Added feature for min/max width limits on yAxis --- .../mikephil/charting/components/YAxis.java | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index bebaffe5c8..dd23bb8d9a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -123,6 +123,20 @@ public enum YAxisLabelPosition { */ private AxisDependency mAxisDependency; + /** + * the minimum width that the axis should take (in dp). + * + * default: 0.0 + */ + protected float mMinWidth = 0.f; + + /** + * the maximum width that the axis can take (in dp). + * use Inifinity for disabling the maximum + * default: Float.POSITIVE_INFINITY (no maximum specified) + */ + protected float mMaxWidth = Float.POSITIVE_INFINITY; + /** * When true, axis labels are controlled by the `granularity` property. * When false, axis values could possibly be repeated. @@ -161,6 +175,36 @@ public AxisDependency getAxisDependency() { return mAxisDependency; } + /** + * @return the minimum width that the axis should take (in dp). + */ + public float getMinWidth() { + return mMinWidth; + } + + /** + * Sets the minimum width that the axis should take (in dp). + * @param minWidth + */ + public void setMinWidth(float minWidth) { + mMinWidth = minWidth; + } + + /** + * @return the maximum width that the axis can take (in dp). + */ + public float getMaxWidth() { + return mMaxWidth; + } + + /** + * Sets the maximum width that the axis can take (in dp). + * @param maxWidth + */ + public void setMaxWidth(float maxWidth) { + mMaxWidth = maxWidth; + } + /** * @return true if granularity is enabled */ @@ -447,7 +491,20 @@ public float getRequiredWidthSpace(Paint p) { p.setTextSize(mTextSize); String label = getLongestLabel(); - return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + float width = (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + + float minWidth = getMinWidth(); + float maxWidth = getMaxWidth(); + + if (minWidth > 0.f) + minWidth = Utils.convertDpToPixel(minWidth); + + if (maxWidth > 0.f && maxWidth != Float.POSITIVE_INFINITY) + maxWidth = Utils.convertDpToPixel(maxWidth); + + width = Math.max(minWidth, Math.min(width, maxWidth > 0.0 ? maxWidth : width)); + + return width; } /** From f002a3a9cc562b3883e226ed7e09765c10610ada Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 17:53:36 +0200 Subject: [PATCH 0809/1390] Fixed cubic line "leak" on first point. Since lately we've done many fixes to the calculation for first/last points in cubic drawing - we not do not need that first "add curve". Related issue: https://github.com/danielgindi/ios-charts/issues/683 --- .../mikephil/charting/renderer/LineChartRenderer.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index dc2facdf14..edf3b99b73 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -160,17 +160,6 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet) { // let the spline start cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); - prevDx = (cur.getXIndex() - prev.getXIndex()) * intensity; - prevDy = (cur.getVal() - prev.getVal()) * intensity; - - curDx = (next.getXIndex() - cur.getXIndex()) * intensity; - curDy = (next.getVal() - cur.getVal()) * intensity; - - // the first cubic - cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, - cur.getXIndex() - curDx, - (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); - for (int j = minx + 1, count = Math.min(size, entryCount - 1); j < count; j++) { prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); From 06e63af1e1927a99c424b0da4957bdef7849cd3b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 17 Mar 2016 22:14:47 +0200 Subject: [PATCH 0810/1390] Do not let slice spacing make the chart go haywire. (Fixes #1582) If the user provides data that does not allow the spacing to stay even - he will need to manually fix that (i.e by giving a larger inner hole) Even with a hole - with very small slices it will not help. Spacing could be reduces, and small slices can be removed from the dataset. --- .../charting/renderer/PieChartRenderer.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index a725c2afbf..227337e517 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -213,6 +213,8 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { if (!mChart.needsHighlight(e.getXIndex(), mChart.getData().getIndexOfDataSet(dataSet))) { + final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; + mRenderPaint.setColor(dataSet.getColor(j)); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? @@ -254,9 +256,9 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { center.y + innerRadius); if (drawInnerArc && - (innerRadius > 0.f || sliceSpace > 0.f)) { + (innerRadius > 0.f || accountForSliceSpacing)) { - if (sliceSpace > 0.f) { + if (accountForSliceSpacing) { float minSpacedRadius = calculateMinimumRadiusForSpacedSlice( center, radius, @@ -301,7 +303,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { else { if (sweepAngleOuter % 360f != 0.f) { - if (sliceSpace > 0.f) { + if (accountForSliceSpacing) { float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; @@ -621,6 +623,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { highlightedCircleBox.set(mChart.getCircleBox()); highlightedCircleBox.inset(-shift, -shift); + final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; + mRenderPaint.setColor(set.getColor(xIndex)); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? @@ -664,7 +668,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } float sliceSpaceRadius = 0.f; - if (sliceSpace > 0.f) { + if (accountForSliceSpacing) { sliceSpaceRadius = calculateMinimumRadiusForSpacedSlice( center, radius, @@ -683,9 +687,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { center.y + innerRadius); if (drawInnerArc && - (innerRadius > 0.f || sliceSpace > 0.f)) { + (innerRadius > 0.f || accountForSliceSpacing)) { - if (sliceSpace > 0.f) { + if (accountForSliceSpacing) { float minSpacedRadius = sliceSpaceRadius; if (minSpacedRadius < 0.f) @@ -725,7 +729,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (sweepAngleOuter % 360f != 0.f) { - if (sliceSpace > 0.0) { + if (accountForSliceSpacing) { final float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; final float arcEndPointX = center.x + From 1eebf84001a9ce438bdceb58a4b4937d028d717c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 18 Mar 2016 12:00:42 +0100 Subject: [PATCH 0811/1390] Change zero line drawing default to false --- .../src/com/github/mikephil/charting/components/YAxis.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index dd23bb8d9a..60cf2f7d95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -66,7 +66,7 @@ public class YAxis extends AxisBase { /** * flag that indicates if the zero-line should be drawn regardless of other grid lines */ - protected boolean mDrawZeroLine = true; + protected boolean mDrawZeroLine = false; /** * Color of the zero line @@ -446,7 +446,7 @@ public boolean isDrawZeroLineEnabled() { /** * Set this to true to draw the zero-line regardless of weather other - * grid-lines are enabled or not. + * grid-lines are enabled or not. Default: false * * @param mDrawZeroLine */ From 7e7b6e397e07f8c5afb0bac1b9ccc7f3abcbc276 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 22 Mar 2016 23:27:38 +0100 Subject: [PATCH 0812/1390] Add documentation, set granularity in example --- .../xxmassdeveloper/mpchartexample/BarChartActivitySinus.java | 2 ++ .../src/com/github/mikephil/charting/components/YAxis.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 62d9b43096..6ed4009640 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -89,6 +89,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setLabelCount(6, false); leftAxis.setAxisMinValue(-2.5f); leftAxis.setAxisMaxValue(2.5f); + leftAxis.setGranularity(0.1f); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); @@ -96,6 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setLabelCount(6, false); rightAxis.setAxisMinValue(-2.5f); rightAxis.setAxisMaxValue(2.5f); + rightAxis.setGranularity(0.1f); mSeekBarX.setOnSeekBarChangeListener(this); mSeekBarX.setProgress(150); // set data diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 60cf2f7d95..dc995a3c46 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -228,7 +228,7 @@ public float getGranularity() { } /** - * set the minimum interval between axis values + * Set the minimum interval between axis values. This can be used to avoid label duplicating when zooming in. * @param granularity */ public void setGranularity(float granularity) { From 303ea3d764ef3e755fb0b9e09111fe5177ff563b Mon Sep 17 00:00:00 2001 From: = Date: Fri, 25 Mar 2016 00:04:16 +0100 Subject: [PATCH 0813/1390] Change values or SKIP and NONE color --- .../src/com/github/mikephil/charting/utils/ColorTemplate.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java index f881d11629..0818d05a9f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java @@ -19,13 +19,13 @@ public class ColorTemplate { /** * an "invalid" color that indicates that no color is set */ - public static final int COLOR_NONE = -1; + public static final int COLOR_NONE = 0x00112233; /** * this "color" is used for the Legend creation and indicates that the next * form should be skipped */ - public static final int COLOR_SKIP = -2; + public static final int COLOR_SKIP = 0x00112234; /** * THE COLOR THEMES ARE PREDEFINED (predefined color integer arrays), FEEL From fc72fbece172eb8df94ab8bca0777045def7010b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 25 Mar 2016 22:19:51 +0100 Subject: [PATCH 0814/1390] Fix #1323 --- .../com/github/mikephil/charting/renderer/YAxisRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index b9a03ef8ec..f1d8f8288e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -95,7 +95,7 @@ protected void computeAxisValues(float min, float max) { interval = interval < mYAxis.getGranularity() ? mYAxis.getGranularity() : interval; // Normalize interval - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { // Use one order of magnitude higher, to avoid intervals like 0.9 or From 0d1894770ce889a20a3d90108b5a72818a5d0bca Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 25 Mar 2016 22:50:03 +0100 Subject: [PATCH 0815/1390] Fix issue #1601 --- .../charting/renderer/LineRadarRenderer.java | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java index bea77bdad9..1121e37966 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java @@ -1,7 +1,10 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; @@ -24,16 +27,22 @@ public LineRadarRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler * @param drawable */ protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { - c.save(); - c.clipPath(filledPath); - drawable.setBounds((int) mViewPortHandler.contentLeft(), - (int) mViewPortHandler.contentTop(), - (int) mViewPortHandler.contentRight(), - (int) mViewPortHandler.contentBottom()); - drawable.draw(c); + if (clipPathSupported()) { - c.restore(); + c.save(); + c.clipPath(filledPath); + + drawable.setBounds((int) mViewPortHandler.contentLeft(), + (int) mViewPortHandler.contentTop(), + (int) mViewPortHandler.contentRight(), + (int) mViewPortHandler.contentBottom()); + drawable.draw(c); + + c.restore(); + } else { + throw new RuntimeException("Fill-drawables not (yet) supported below API level 18"); + } } /** @@ -46,11 +55,35 @@ protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { * @param fillAlpha */ protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) { - c.save(); - c.clipPath(filledPath); int color = (fillAlpha << 24) | (fillColor & 0xffffff); - c.drawColor(color); - c.restore(); + + if (clipPathSupported()) { + + c.save(); + c.clipPath(filledPath); + + c.drawColor(color); + c.restore(); + } else { + + // save + Paint.Style previous = mRenderPaint.getStyle(); + int previousColor = mRenderPaint.getColor(); + + // set + mRenderPaint.setStyle(Paint.Style.FILL); + mRenderPaint.setColor(color); + + c.drawPath(filledPath, mRenderPaint); + + // restore + mRenderPaint.setColor(previousColor); + mRenderPaint.setStyle(previous); + } + } + + private boolean clipPathSupported() { + return android.os.Build.VERSION.SDK_INT >= 18; } } From 96c518d3d96f780f472c6b86e8eaca6bd230f677 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 26 Mar 2016 11:16:31 +0100 Subject: [PATCH 0816/1390] Provide version checks --- .../mpchartexample/LineChartActivity1.java | 9 +++++++-- .../mikephil/charting/animation/ChartAnimator.java | 1 - .../mikephil/charting/data/LineRadarDataSet.java | 2 ++ .../mikephil/charting/renderer/LineRadarRenderer.java | 11 +++++++++-- .../src/com/github/mikephil/charting/utils/Utils.java | 3 +++ 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 1b10e12188..e3ea20a844 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -32,6 +32,7 @@ import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -354,10 +355,14 @@ private void setData(int count, float range) { set1.setCircleRadius(3f); set1.setDrawCircleHole(false); set1.setValueTextSize(9f); - Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); - set1.setFillDrawable(drawable); set1.setDrawFilled(true); + if(Utils.getSDKInt() >= 18) { + // fill drawable only supported on api level 18 and above + Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); + set1.setFillDrawable(drawable); + } + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java index b325eba738..639442a4c9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java @@ -11,7 +11,6 @@ * * @author Philipp Jahoda */ -@SuppressLint("NewApi") public class ChartAnimator { /** object that is updated upon animation update */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 2289113dbb..deced96ee9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import android.annotation.TargetApi; import android.graphics.Color; import android.graphics.drawable.Drawable; @@ -72,6 +73,7 @@ public Drawable getFillDrawable() { * * @param drawable */ + @TargetApi(18) public void setFillDrawable(Drawable drawable) { this.mFillDrawable = drawable; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java index 1121e37966..f29c77513e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java @@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -41,7 +42,8 @@ protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { c.restore(); } else { - throw new RuntimeException("Fill-drawables not (yet) supported below API level 18"); + throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " + + "this code was run on API level " + Utils.getSDKInt() + "."); } } @@ -83,7 +85,12 @@ protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fill } } + /** + * Clip path with hardware acceleration only working properly on API level 18 and above. + * + * @return + */ private boolean clipPathSupported() { - return android.os.Build.VERSION.SDK_INT >= 18; + return Utils.getSDKInt() >= 18; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index b8e6cd7964..ca19784347 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -710,4 +710,7 @@ public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, flo ); } + public static int getSDKInt() { + return android.os.Build.VERSION.SDK_INT; + } } From 893994526753c6db1cdc57ab5125dfad50cc48dc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 26 Mar 2016 19:02:13 +0100 Subject: [PATCH 0817/1390] Refactoring and change of axis min/max calculation and custom axis values --- .../charting/charts/BarLineChartBase.java | 52 +------------- .../mikephil/charting/charts/RadarChart.java | 25 +------ .../mikephil/charting/components/YAxis.java | 69 +++++++++++++++---- .../renderer/YAxisRendererRadarChart.java | 2 +- 4 files changed, 60 insertions(+), 88 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a96eb08487..d2c78579cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -353,58 +353,12 @@ protected void calcMinMax() { if (mAutoScaleMinMaxEnabled) mData.calcMinMax(getLowestVisibleXIndex(), getHighestVisibleXIndex()); - float minLeft = !Float.isNaN(mAxisLeft.getAxisMinValue()) - ? mAxisLeft.getAxisMinValue() - : mData.getYMin(AxisDependency.LEFT); - float maxLeft = !Float.isNaN(mAxisLeft.getAxisMaxValue()) - ? mAxisLeft.getAxisMaxValue() - : mData.getYMax(AxisDependency.LEFT); - float minRight = !Float.isNaN(mAxisRight.getAxisMinValue()) - ? mAxisRight.getAxisMinValue() - : mData.getYMin(AxisDependency.RIGHT); - float maxRight = !Float.isNaN(mAxisRight.getAxisMaxValue()) - ? mAxisRight.getAxisMaxValue() - : mData.getYMax(AxisDependency.RIGHT); - - float leftRange = Math.abs(maxLeft - minLeft); - float rightRange = Math.abs(maxRight - minRight); - - // in case all values are equal - if (leftRange == 0f) { - maxLeft = maxLeft + 1f; - minLeft = minLeft - 1f; - } - - if (rightRange == 0f) { - maxRight = maxRight + 1f; - minRight = minRight - 1f; - } - - float topSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceTop(); - float topSpaceRight = rightRange / 100f * mAxisRight.getSpaceTop(); - float bottomSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceBottom(); - float bottomSpaceRight = rightRange / 100f * mAxisRight.getSpaceBottom(); - mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - // Use the values as they are - mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) - ? mAxisLeft.getAxisMinValue() - : (minLeft - bottomSpaceLeft); - mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) - ? mAxisLeft.getAxisMaxValue() - : (maxLeft + topSpaceLeft); - - mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) - ? mAxisRight.getAxisMinValue() - : (minRight - bottomSpaceRight); - mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) - ? mAxisRight.getAxisMaxValue() - : (maxRight + topSpaceRight); - - mAxisLeft.mAxisRange = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); - mAxisRight.mAxisRange = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); + // calculate axis range (min / max) according to provided data + mAxisLeft.calcMinMax(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); + mAxisRight.calcMinMax(mData.getYMin(AxisDependency.RIGHT), mData.getYMax(AxisDependency.RIGHT)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index ea012e7abe..a3f9820f42 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -107,33 +107,10 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - float minLeft = !Float.isNaN(mYAxis.getAxisMinValue()) - ? mYAxis.getAxisMinValue() - : mData.getYMin(AxisDependency.LEFT); - float maxLeft = !Float.isNaN(mYAxis.getAxisMaxValue()) - ? mYAxis.getAxisMaxValue() - : mData.getYMax(AxisDependency.LEFT); - mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - float leftRange = Math.abs(maxLeft - minLeft); - - float topSpaceLeft = leftRange / 100f * mYAxis.getSpaceTop(); - float bottomSpaceLeft = leftRange / 100f * mYAxis.getSpaceBottom(); - - mXChartMax = mData.getXVals().size() - 1; - mDeltaX = Math.abs(mXChartMax - mXChartMin); - - // Use the values as they are - mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) - ? mYAxis.getAxisMinValue() - : (minLeft - bottomSpaceLeft); - mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) - ? mYAxis.getAxisMaxValue() - : (maxLeft + topSpaceLeft); - - mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); + mYAxis.calcMinMax(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index dc995a3c46..1ea8d946d6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -79,14 +79,14 @@ public class YAxis extends AxisBase { protected float mZeroLineWidth = 1f; /** - * custom minimum value this axis represents + * flag indicating that the axis-min value has been customized */ - protected float mCustomAxisMin = Float.NaN; + protected boolean mCustomAxisMin = false; /** - * custom maximum value this axis represents + * flag indicating that the axis-max value has been customized */ - protected float mCustomAxisMax = Float.NaN; + protected boolean mCustomAxisMax = false; /** * axis space from the largest value to the top in percent of the total axis range @@ -359,10 +359,6 @@ public void setStartAtZero(boolean startAtZero) { resetAxisMinValue(); } - public float getAxisMinValue() { - return mCustomAxisMin; - } - /** * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use @@ -371,7 +367,8 @@ public float getAxisMinValue() { * @param min */ public void setAxisMinValue(float min) { - mCustomAxisMin = min; + mCustomAxisMin = true; + mAxisMinimum = min; } /** @@ -379,11 +376,11 @@ public void setAxisMinValue(float min) { * done automatically. */ public void resetAxisMinValue() { - mCustomAxisMin = Float.NaN; + mCustomAxisMin = false; } - public float getAxisMaxValue() { - return mCustomAxisMax; + public boolean isAxisMinCustom() { + return mCustomAxisMin; } /** @@ -393,7 +390,8 @@ public float getAxisMaxValue() { * @param max */ public void setAxisMaxValue(float max) { - mCustomAxisMax = max; + mCustomAxisMax = true; + mAxisMaximum = max; } /** @@ -401,7 +399,11 @@ public void setAxisMaxValue(float max) { * done automatically. */ public void resetAxisMaxValue() { - mCustomAxisMax = Float.NaN; + mCustomAxisMax = false; + } + + public boolean isAxisMaxCustom() { + return mCustomAxisMax; } /** @@ -604,4 +606,43 @@ public boolean needsOffset() { else return false; } + + /** + * Calculates the minimum, maximum and range values of the YAxis with the given + * minimum and maximum values from the chart data. + * @param dataMin the y-min value according to chart data + * @param dataMax the y-max value according to chart data + */ + public void calcMinMax(float dataMin, float dataMax) { + + // if custom, use value as is, else use data value + float min = mCustomAxisMin ? mAxisMinimum : dataMin; + float max = mCustomAxisMax ? mAxisMaximum : dataMax; + + // temporary range (before calculations) + float range = Math.abs(max - min); + + // in case all values are equal + if (range == 0f) { + max = max + 1f; + min = min - 1f; + } + + // bottom-space only effects non-custom min + if(!mCustomAxisMin) { + + float bottomSpace = range / 100f * getSpaceBottom(); + this.mAxisMinimum = (min - bottomSpace); + } + + // top-space only effects non-custom max + if(!mCustomAxisMax) { + + float topSpace = range / 100f * getSpaceTop(); + this.mAxisMaximum = (max + topSpace); + } + + // calc actual range + this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 1dbefe08ae..66ddd3ceea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -97,7 +97,7 @@ protected void computeAxisValues(float min, float max) { ++n; } - if (Float.isNaN(mYAxis.getAxisMaxValue())) + if (!mYAxis.isAxisMaxCustom()) n += 1; mYAxis.mEntryCount = n; From 676e148ea1c5db07232f983057f9156c4e4915a3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 26 Mar 2016 19:11:16 +0100 Subject: [PATCH 0818/1390] Move axis min/max related code to AxisBase --- .../charting/components/AxisBase.java | 84 ++++++++++++++++++- .../mikephil/charting/components/YAxis.java | 65 -------------- 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 26f26b361f..bbaebf506c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -55,6 +55,24 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mDrawLimitLineBehindData = false; + /** + * flag indicating that the axis-min value has been customized + */ + protected boolean mCustomAxisMin = false; + + /** + * flag indicating that the axis-max value has been customized + */ + protected boolean mCustomAxisMax = false; + + public float mAxisMaximum = 0f; + public float mAxisMinimum = 0f; + + /** + * the total range of values this axis covers + */ + public float mAxisRange = 0f; + /** * default constructor */ @@ -206,7 +224,8 @@ public void addLimitLine(LimitLine l) { if (mLimitLines.size() > 6) { Log.e("MPAndroiChart", - "Warning! You have more than 6 LimitLines on your axis, do you really want that?"); + "Warning! You have more than 6 LimitLines on your axis, do you really want " + + "that?"); } } @@ -296,4 +315,67 @@ public boolean isGridDashedLineEnabled() { public DashPathEffect getGridDashPathEffect() { return mGridDashPathEffect; } + + /** + * ###### BELOW CODE RELATED TO CUSTOM AXIS VALUES ###### + */ + + /** + * By calling this method, any custom maximum value that has been previously set is reseted, + * and the calculation is + * done automatically. + */ + public void resetAxisMaxValue() { + mCustomAxisMax = false; + } + + /** + * Returns true if the axis max value has been customized (and is not calculated automatically) + * + * @return + */ + public boolean isAxisMaxCustom() { + return mCustomAxisMax; + } + + /** + * By calling this method, any custom minimum value that has been previously set is reseted, + * and the calculation is + * done automatically. + */ + public void resetAxisMinValue() { + mCustomAxisMin = false; + } + + /** + * Returns true if the axis min value has been customized (and is not calculated automatically) + * + * @return + */ + public boolean isAxisMinCustom() { + return mCustomAxisMin; + } + + /** + * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use + * this method. Otherwise, the axis-minimum value will still be forced to 0. + * + * @param min + */ + public void setAxisMinValue(float min) { + mCustomAxisMin = true; + mAxisMinimum = min; + } + + /** + * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMaxValue() to undo this. + * + * @param max + */ + public void setAxisMaxValue(float max) { + mCustomAxisMax = true; + mAxisMaximum = max; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 1ea8d946d6..6e8c0486f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -78,16 +78,6 @@ public class YAxis extends AxisBase { */ protected float mZeroLineWidth = 1f; - /** - * flag indicating that the axis-min value has been customized - */ - protected boolean mCustomAxisMin = false; - - /** - * flag indicating that the axis-max value has been customized - */ - protected boolean mCustomAxisMax = false; - /** * axis space from the largest value to the top in percent of the total axis range */ @@ -98,14 +88,6 @@ public class YAxis extends AxisBase { */ protected float mSpacePercentBottom = 10f; - public float mAxisMaximum = 0f; - public float mAxisMinimum = 0f; - - /** - * the total range of values this axis covers - */ - public float mAxisRange = 0f; - /** * the position of the y-labels relative to the chart */ @@ -359,53 +341,6 @@ public void setStartAtZero(boolean startAtZero) { resetAxisMinValue(); } - /** - * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on - * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use - * this method. Otherwise, the axis-minimum value will still be forced to 0. - * - * @param min - */ - public void setAxisMinValue(float min) { - mCustomAxisMin = true; - mAxisMinimum = min; - } - - /** - * By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is - * done automatically. - */ - public void resetAxisMinValue() { - mCustomAxisMin = false; - } - - public boolean isAxisMinCustom() { - return mCustomAxisMin; - } - - /** - * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on - * the provided data. Use resetAxisMaxValue() to undo this. - * - * @param max - */ - public void setAxisMaxValue(float max) { - mCustomAxisMax = true; - mAxisMaximum = max; - } - - /** - * By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is - * done automatically. - */ - public void resetAxisMaxValue() { - mCustomAxisMax = false; - } - - public boolean isAxisMaxCustom() { - return mCustomAxisMax; - } - /** * Sets the top axis space in percent of the full range. Default 10f * From 7475b1292d4037cc518d354872476aede62ba2ce Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 26 Mar 2016 19:28:08 +0100 Subject: [PATCH 0819/1390] Remove redundant deltaX value from chart --- .../mikephil/charting/charts/BarChart.java | 10 +++---- .../charting/charts/BarLineChartBase.java | 28 ++++++++----------- .../mikephil/charting/charts/BubbleChart.java | 20 ++++++------- .../charting/charts/CandleStickChart.java | 6 ++-- .../mikephil/charting/charts/Chart.java | 18 ++++++------ .../charting/charts/CombinedChart.java | 20 ++++++------- .../charting/charts/HorizontalBarChart.java | 4 +-- .../mikephil/charting/charts/LineChart.java | 4 +-- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 11 ++------ .../charting/charts/ScatterChart.java | 10 +++---- 11 files changed, 62 insertions(+), 71 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 19aaa2fe54..93e0fe7d57 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -56,7 +56,7 @@ protected void init() { setHighlighter(new BarHighlighter(this)); - mXChartMin = -0.5f; + mXAxis.mAxisMinimum = -0.5f; } @Override @@ -64,14 +64,14 @@ protected void calcMinMax() { super.calcMinMax(); // increase deltax by 1 because the bars have a width of 1 - mDeltaX += 0.5f; + mXAxis.mAxisRange += 0.5f; // extend xDelta to make space for multiple datasets (if ther are one) - mDeltaX *= mData.getDataSetCount(); + mXAxis.mAxisRange *= mData.getDataSetCount(); float groupSpace = mData.getGroupSpace(); - mDeltaX += mData.getXValCount() * groupSpace; - mXChartMax = mDeltaX - mXChartMin; + mXAxis.mAxisRange += mData.getXValCount() * groupSpace; + mXAxis.mAxisMaximum = mXAxis.mAxisRange - mXAxis.mAxisMinimum; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d2c78579cc..f14709a806 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -126,11 +126,6 @@ public abstract class BarLineChartBase 0) - mDeltaX = 1; + if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) + mXAxis.mAxisRange = 1; - mXChartMin = -0.5f; - mXChartMax = (float) mData.getXValCount() - 0.5f; + mXAxis.mAxisMinimum = -0.5f; + mXAxis.mAxisMaximum = (float) mData.getXValCount() - 0.5f; if (mRenderer != null) { for (IBubbleDataSet set : mData.getDataSets()) { @@ -54,15 +54,15 @@ protected void calcMinMax() { final float xmin = set.getXMin(); final float xmax = set.getXMax(); - if (xmin < mXChartMin) - mXChartMin = xmin; + if (xmin < mXAxis.mAxisMinimum) + mXAxis.mAxisMinimum = xmin; - if (xmax > mXChartMax) - mXChartMax = xmax; + if (xmax > mXAxis.mAxisMaximum) + mXAxis.mAxisMaximum = xmax; } } - mDeltaX = Math.abs(mXChartMax - mXChartMin); + mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); } public BubbleData getBubbleData() { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 12f8dad9fd..87008d4a83 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -32,15 +32,15 @@ protected void init() { super.init(); mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); - mXChartMin = -0.5f; + mXAxis.mAxisMinimum = -0.5f; } @Override protected void calcMinMax() { super.calcMinMax(); - mXChartMax += 0.5f; - mDeltaX = Math.abs(mXChartMax - mXChartMin); + mXAxis.mAxisMaximum += 0.5f; + mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 647d0f944f..3fa81c03db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -30,6 +30,7 @@ import com.github.mikephil.charting.animation.EasingFunction; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultValueFormatter; @@ -117,12 +118,9 @@ public abstract class Chart mXChartMax) - mXChartMax = xmax; + if (xmax > mXAxis.mAxisMaximum) + mXAxis.mAxisMaximum = xmax; } } } - mDeltaX = Math.abs(mXChartMax - mXChartMin); + mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - if (mDeltaX == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { - mDeltaX = 1.f; + if (mXAxis.mAxisRange == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { + mXAxis.mAxisRange = 1.f; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index f7c4501710..2ff098b1ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -153,8 +153,8 @@ public void calculateOffsets() { @Override protected void prepareValuePxMatrix() { - mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mDeltaX, mXChartMin); - mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mDeltaX, mXChartMin); + mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mXAxis.mAxisRange, mXAxis.mAxisMinimum); + mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mXAxis.mAxisRange, mXAxis.mAxisMinimum); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index c354217a04..9acfaafe17 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -38,8 +38,8 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - if (mDeltaX == 0 && mData.getYValCount() > 0) - mDeltaX = 1; + if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) + mXAxis.mAxisRange = 1; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 64dc6abb01..a5c3bf130a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -66,7 +66,7 @@ protected void init() { @Override protected void calcMinMax() { - mDeltaX = mData.getXVals().size() - 1; + mXAxis.mAxisRange = mData.getXVals().size() - 1; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index a3f9820f42..3601ddad11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -67,11 +67,6 @@ public class RadarChart extends PieRadarChartBase { */ private YAxis mYAxis; - /** - * the object representing the x-axis labels - */ - private XAxis mXAxis; - protected YAxisRendererRadarChart mYAxisRenderer; protected XAxisRendererRadarChart mXAxisRenderer; @@ -92,7 +87,6 @@ protected void init() { super.init(); mYAxis = new YAxis(AxisDependency.LEFT); - mXAxis = new XAxis(); mXAxis.setSpaceBetweenLabels(0); mWebLineWidth = Utils.convertDpToPixel(1.5f); @@ -107,8 +101,9 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - mXChartMax = mData.getXVals().size() - 1; - mDeltaX = Math.abs(mXChartMax - mXChartMin); + // calculate / set x-axis range + mXAxis.mAxisMaximum = mData.getXVals().size() - 1; + mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); mYAxis.calcMinMax(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 76a10cb894..292568a6b3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -41,18 +41,18 @@ protected void init() { super.init(); mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); - mXChartMin = -0.5f; + mXAxis.mAxisMinimum = -0.5f; } @Override protected void calcMinMax() { super.calcMinMax(); - if (mDeltaX == 0 && mData.getYValCount() > 0) - mDeltaX = 1; + if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) + mXAxis.mAxisRange = 1; - mXChartMax += 0.5f; - mDeltaX = Math.abs(mXChartMax - mXChartMin); + mXAxis.mAxisMaximum += 0.5f; + mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); } /** From 8b4aa77237d4686fee68a86191ad352a032005b9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 27 Mar 2016 12:22:20 +0200 Subject: [PATCH 0820/1390] Move getXAxis() method --- .../charting/charts/BarLineChartBase.java | 11 ---------- .../mikephil/charting/charts/Chart.java | 12 ++++++++++ .../mikephil/charting/charts/PieChart.java | 22 ++++++++++++++++--- .../mikephil/charting/charts/RadarChart.java | 10 --------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index f14709a806..569d3b19fb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1378,17 +1378,6 @@ public boolean isInverted(AxisDependency axis) { return getAxis(axis).isInverted(); } - /** - * Returns the object representing all x-labels, this method can be used to - * acquire the XAxis object and modify it (e.g. change the position of the - * labels) - * - * @return - */ - public XAxis getXAxis() { - return mXAxis; - } - /** * If set to true, both x and y axis can be scaled simultaneously with 2 fingers, if false, * x and y axis can be scaled separately. default: false diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 3fa81c03db..055bdf7312 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -924,6 +924,18 @@ public void animateXY(int durationMillisX, int durationMillisY) { */ /** BELOW THIS ONLY GETTERS AND SETTERS */ + + /** + * Returns the object representing all x-labels, this method can be used to + * acquire the XAxis object and modify it (e.g. change the position of the + * labels, styling, etc.) + * + * @return + */ + public XAxis getXAxis() { + return mXAxis; + } + /** * Returns the default ValueFormatter that has been determined by the chart * considering the provided minimum and maximum values. diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 8219a453a7..1bee5a147d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -9,6 +9,7 @@ import android.graphics.Typeface; import android.util.AttributeSet; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.highlight.Highlight; @@ -109,6 +110,7 @@ protected void init() { super.init(); mRenderer = new PieChartRenderer(this, mAnimator, mViewPortHandler); + mXAxis = null; } @Override @@ -275,6 +277,17 @@ private float calcAngle(float value, float yValueSum) { return value / yValueSum * mMaxAngle; } + /** + * This will throw an exception, PieChart has no XAxis object. + * + * @return + */ + @Deprecated + @Override + public XAxis getXAxis() { + throw new RuntimeException("PieChart has no XAxis"); + } + @Override public int getIndexForAngle(float angle) { @@ -536,7 +549,8 @@ public float getTransparentCircleRadius() { } /** - * Sets the amount of transparency the transparent circle should have 0 = fully transparent, 255 = fully opaque. + * Sets the amount of transparency the transparent circle should have 0 = fully transparent, + * 255 = fully opaque. * Default value is 100. * * @param alpha 0-255 @@ -594,7 +608,8 @@ public boolean isUsePercentValuesEnabled() { } /** - * the rectangular radius of the bounding box for the center text, as a percentage of the pie hole + * the rectangular radius of the bounding box for the center text, as a percentage of the pie + * hole * default 1.f (100%) */ public void setCenterTextRadiusPercent(float percent) { @@ -602,7 +617,8 @@ public void setCenterTextRadiusPercent(float percent) { } /** - * the rectangular radius of the bounding box for the center text, as a percentage of the pie hole + * the rectangular radius of the bounding box for the center text, as a percentage of the pie + * hole * default 1.f (100%) */ public float getCenterTextRadiusPercent() { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 3601ddad11..8f6c1cb982 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -218,16 +218,6 @@ public YAxis getYAxis() { return mYAxis; } - /** - * Returns the object that represents all x-labels that are placed around - * the RadarChart. - * - * @return - */ - public XAxis getXAxis() { - return mXAxis; - } - /** * Sets the width of the web lines that come from the center. * From 395742f09f19ae4ad901b78af4b1be750270d4eb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 27 Mar 2016 14:56:26 +0200 Subject: [PATCH 0821/1390] Set fill color if drawable is not supported --- .../com/xxmassdeveloper/mpchartexample/LineChartActivity1.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index e3ea20a844..836afcd7f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -361,6 +361,8 @@ private void setData(int count, float range) { // fill drawable only supported on api level 18 and above Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); set1.setFillDrawable(drawable); + } else { + set1.setFillColor(Color.BLACK); } ArrayList dataSets = new ArrayList(); From 8e00d1f2e6921664135f27f9fccd6ce42d236047 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 27 Mar 2016 15:03:12 +0200 Subject: [PATCH 0822/1390] Fix issue #1550 --- .../mpchartexample/CubicLineChartActivity.java | 6 ++++-- .../github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 31f951a379..26220e5309 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -3,7 +3,9 @@ import android.graphics.Color; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; @@ -57,7 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); mChart = (LineChart) findViewById(R.id.chart1); - mChart.setViewPortOffsets(0, 20, 0, 0); + mChart.setViewPortOffsets(0, 0, 0, 0); mChart.setBackgroundColor(Color.rgb(104, 241, 175)); // no description text @@ -274,7 +276,7 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv return -10; } }); - + // create a data object with the datasets LineData data = new LineData(xVals, set1); data.setValueTypeface(tf); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 569d3b19fb..609ff478cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -652,7 +652,7 @@ public void zoomOut() { * @param y */ public void zoom(float scaleX, float scaleY, float x, float y) { - Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, -y); + Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, y); mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels From 8e4d28d0dfbb6b22e43be46ef48432816fd9218d Mon Sep 17 00:00:00 2001 From: Konstantin Schubert Date: Mon, 28 Mar 2016 22:05:22 +0200 Subject: [PATCH 0823/1390] Attempt to fix issue #1622 Remove call to super.calcMinMax() in PieChart. --- .../src/com/github/mikephil/charting/charts/PieChart.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 1bee5a147d..be8a51e140 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -161,8 +161,7 @@ public void calculateOffsets() { @Override protected void calcMinMax() { - super.calcMinMax(); - + calcAngles(); } From e221117b8f599c6ebee3753cb5eb6b74f9663ac3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 28 Mar 2016 22:39:39 +0200 Subject: [PATCH 0824/1390] Fix #1605 --- MPChartLib/src/com/github/mikephil/charting/data/ChartData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index d9ef299dcd..71663eb2cd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -174,7 +174,7 @@ private void checkLegal() { if (mDataSets == null) return; - if (this instanceof ScatterData) + if (this instanceof ScatterData || this instanceof CombinedData) return; for (int i = 0; i < mDataSets.size(); i++) { From 35845ced6297af37b3f8476022bf6df51ab844da Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 29 Mar 2016 18:26:13 +0200 Subject: [PATCH 0825/1390] Update realm dependency --- MPChartExample/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 300386b1f4..500771a9f5 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -38,6 +38,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' + classpath "io.realm:realm-gradle-plugin:0.88.2" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -54,6 +55,6 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' - compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) + //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } From b28f4aa8b8c41ec88f0027239d2f2518339c33c5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 29 Mar 2016 23:41:15 +0200 Subject: [PATCH 0826/1390] Modify realm dependency --- MPChartExample/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 500771a9f5..b38f687550 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -38,7 +38,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:1.5.0' - classpath "io.realm:realm-gradle-plugin:0.88.2" + //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -55,6 +55,6 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' - //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) + compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } From 9569cf577f82acc8d2373a805f95d5a82586eff7 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 30 Mar 2016 22:24:00 +0200 Subject: [PATCH 0827/1390] Add methods for getting axis min and max value --- .../com/github/mikephil/charting/components/AxisBase.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index bbaebf506c..f0c4e4bc2d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -320,6 +320,14 @@ public DashPathEffect getGridDashPathEffect() { * ###### BELOW CODE RELATED TO CUSTOM AXIS VALUES ###### */ + public float getAxisMaximum() { + return mAxisMaximum; + } + + public float getAxisMinimum() { + return mAxisMinimum; + } + /** * By calling this method, any custom maximum value that has been previously set is reseted, * and the calculation is From 0ee538c73474619caa7e25adf684ce01b334f12b Mon Sep 17 00:00:00 2001 From: = Date: Wed, 30 Mar 2016 22:31:17 +0200 Subject: [PATCH 0828/1390] Fix issue #1631 --- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index a9ac981c35..66e80e3bea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -232,7 +232,7 @@ public void renderLegend(Canvas c) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) originPosX -= mLegend.mNeededWidth; } else // BELOW_CHART_CENTER || ABOVE_CHART_CENTER - originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f; + originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f - mLegend.mNeededWidth / 2f; FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); From 528dd490d47c5024cf7b4997202e13ff07104d52 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 31 Mar 2016 10:36:13 +0200 Subject: [PATCH 0829/1390] Fix issue #1529 --- .../charting/charts/BarLineChartBase.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 609ff478cb..3313bd10bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -246,15 +246,6 @@ protected void onDraw(Canvas canvas) { mRenderer.drawData(canvas); - if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) - mXAxisRenderer.renderLimitLines(canvas); - - if (!mAxisLeft.isDrawLimitLinesBehindDataEnabled()) - mAxisRendererLeft.renderLimitLines(canvas); - - if (!mAxisRight.isDrawLimitLinesBehindDataEnabled()) - mAxisRendererRight.renderLimitLines(canvas); - // if highlighting is enabled if (valuesToHighlight()) mRenderer.drawHighlighted(canvas, mIndicesToHighlight); @@ -264,6 +255,15 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(canvas); + if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) + mXAxisRenderer.renderLimitLines(canvas); + + if (!mAxisLeft.isDrawLimitLinesBehindDataEnabled()) + mAxisRendererLeft.renderLimitLines(canvas); + + if (!mAxisRight.isDrawLimitLinesBehindDataEnabled()) + mAxisRendererRight.renderLimitLines(canvas); + mXAxisRenderer.renderAxisLabels(canvas); mAxisRendererLeft.renderAxisLabels(canvas); mAxisRendererRight.renderAxisLabels(canvas); From badb73607069c3e6442209dd0505f4e7022876d2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 31 Mar 2016 11:22:13 +0200 Subject: [PATCH 0830/1390] Add documentation to axis --- .../mikephil/charting/components/AxisBase.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index f0c4e4bc2d..caac60b999 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -11,7 +11,7 @@ import java.util.List; /** - * Baseclass of all labels. + * Base-class of all axes (previously called labels). * * @author Philipp Jahoda */ @@ -65,7 +65,14 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mCustomAxisMax = false; + /** + * don't touch this direclty, use setter + */ public float mAxisMaximum = 0f; + + /** + * don't touch this directly, use setter + */ public float mAxisMinimum = 0f; /** @@ -365,8 +372,10 @@ public boolean isAxisMinCustom() { } /** - * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on - * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use + * Set a custom minimum value for this axis. If set, this value will not be calculated + * automatically depending on + * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call + * setStartAtZero(false) if you use * this method. Otherwise, the axis-minimum value will still be forced to 0. * * @param min @@ -377,7 +386,8 @@ public void setAxisMinValue(float min) { } /** - * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on + * Set a custom maximum value for this axis. If set, this value will not be calculated + * automatically depending on * the provided data. Use resetAxisMaxValue() to undo this. * * @param max From 3fd2a8a17bc80a71485d653e94b839896725a39a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 31 Mar 2016 11:26:05 +0200 Subject: [PATCH 0831/1390] Update build.gradle and manifest --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 6895b904fd..250757b885 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="50" + android:versionName="2.2.4" > Date: Thu, 31 Mar 2016 11:35:01 +0200 Subject: [PATCH 0832/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 78b802778e..3d35de050b 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.4/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -99,7 +99,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.2.3' + compile 'com.github.PhilJay:MPAndroidChart:v2.2.4' } ``` @@ -114,7 +114,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.2.3 + v2.2.4 ``` From 543075027a110809b3cd2fd460b7ab3ef5ada995 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 31 Mar 2016 11:35:57 +0200 Subject: [PATCH 0833/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3d35de050b..197c1b4881 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.3/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.4/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 2e417148ce2e6b6fbc5708a3a7288f35506cc4a6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 31 Mar 2016 22:31:32 +0300 Subject: [PATCH 0834/1390] Corrected legend to center while wrapping in both "above" and "below" Fixes the bug introduced by 0ee538c --- .../github/mikephil/charting/renderer/LegendRenderer.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 66e80e3bea..45ae8b1939 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -232,7 +232,7 @@ public void renderLegend(Canvas c) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) originPosX -= mLegend.mNeededWidth; } else // BELOW_CHART_CENTER || ABOVE_CHART_CENTER - originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f - mLegend.mNeededWidth / 2f; + originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f; FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); @@ -256,7 +256,10 @@ public void renderLegend(Canvas c) { posY += labelLineHeight + labelLineSpacing; } - if (posX == originPosX && legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER && lineIndex < calculatedLineSizes.length) { + if (posX == originPosX && + (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER || + legendPosition == Legend.LegendPosition.ABOVE_CHART_CENTER) && + lineIndex < calculatedLineSizes.length) { posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT ? calculatedLineSizes[lineIndex].width : -calculatedLineSizes[lineIndex].width) / 2.f; lineIndex++; } From 135f9aa09ea7670dd78c2501bf4ca02dc8acbe7b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Apr 2016 09:50:37 +0200 Subject: [PATCH 0835/1390] Minor changes --- .gitignore | 4 ++++ MPChartExample/libs/android-support-v4.jar | Bin 758727 -> 0 bytes .../charting/data/realm/base/RealmUtils.java | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) delete mode 100644 MPChartExample/libs/android-support-v4.jar diff --git a/.gitignore b/.gitignore index 2152318d78..70e3dabbf8 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,10 @@ # generated files bin/ gen/ +generatedJar/ +docs/ + +build.xml # Local configuration file (sdk path, etc) local.properties diff --git a/MPChartExample/libs/android-support-v4.jar b/MPChartExample/libs/android-support-v4.jar deleted file mode 100644 index c31cede47e3efe9342908764db28b9a760b9a90b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 758727 zcmaI719T?s(l(l8V%xTD+qP}nn2GI)ZD(Ra68}e8K}1nTQbJ9gQ9<%vVRAxVj)8FwL5_iTdUB>om3fhE_sEq|R)Jnd zVa}rp946xoXD~a1)*3whnC97%66**{3p2gs7?aNXnBv0b&h^$6^xuZ~RjmM}{tol6 z?O%q#{@bX|o|XU4Q~b+b6GwAbCmVC7|0@OZKb{r&zogteoSmIq-TzDa+y9V8`(LCz z+5bxc{C_B5|L+PO?l$)S*80y2_@Bd2{ezaeje~{8Uv)P|GkX&^w=m5sw^S{RuPuJ3 zt{FxX7$56x&hIpwFl*p?uN5Q=^Y*HkV$w34?6aI*mx3fnTW!~JG#s>w#c5R@?(6HG z>&klg%|&d@if55(1iT;nLc35_?}tzy`>||+m_bk1#}Ei$fNi%KfhVu&mo2wx0MXaS zh7yQBs1M%8jW#j^x1;dK+^3}(E*tKk8J7Kd%AJ*_ZcgI-0q3#v`~VG}3BSpK3_r!v zJ!lDi2}2I1Ga?n$!N|z|{jHeW{XtYi)bsn`YRPwLXnPz6Oxh*)Lf-7@CH}b2R=8&Q zggCl#{ydTOI-P+UT)e9$ZIHZa> z3PRb01IllPWWN8CQIC!&KjAX5K0XV9_YXX(9T3#^>Ve(F}L(`!ZKZ3(GYzjhSj2mvW* z)JuTwlxhPuVsaTq08@emQc1P|@Oqdx{3xtKS+hnjq z^gjiTc1H8_Z(zYEIq6|sLpLDKbaOL&gwj)N^e~vz=*?-)bTAqlv}=AIiEJ}1R^=^L z`~uH%dSXPr5@_5Dz^*ppzL%bwvFN!2eL>V!>}*tA(Ez*hYQ{X(9=eMWQ%f#Gv-mxp z5(;ihn`_47=&QKMx0#9+<$EI5Gag})8b&(zjVx2YIP%hlHSu;hK!;$;u3m`RWneXI z%f#KRJWL*2$J=BxVw)L~1zi%W$b=tyWk3|$>euMN7ciFMyVIUMwh|fEFqwDi*^p_Q z&N7{W@sj~v@@=gVUsm0GaYG^U!;$(?M?lpf@ClkLyz5T870! zuNP#6c;=b-{R7`iOdmq4_=|Ut!=qHH^Wr-VeG{8U3mK}u297$8xFf7t}{1%XdKRGYAKg2`Z8qB-D$`3#=-4s6=d0C^s!O zfQOVn0T7);6*&*^f4a>d!mC!rh6voyeF>h-dcRWlXP`L_O@6)ozHb*5E7My-&a?QF zoQHjsM6YqW&@;M1Z}ezKNO*zDfV}p?YdFGs-?5SJc|7}cPCuaIEUoyS9^dU@wC?by z-dFNKZ%Oe*Wp%Ue4}!IebFKD4{hlt*U)g#2K64z0SwUxJ*i2nz$GTZ~v--)KriPN$ z`qE8iyqYl`8ApK3jV!YC2C-TmuD%qI(pMF8af7JXL-Oxvv9Z!U$Llry6eIH-S7zFd zqcA+6TQFm+-Czc674kF=&T6$CmCMZMwrW+COKP%8V7jL93Semt4fv>9jvpaFgh1z>dqZeU3gy6cLks(?Y5h1H4!x)@{fAS^gG)sC1j5*GJLN5|Dn zJjE+%im`)5-~MfL6;L$$!eZ;;)c1N+s%ds80Q?5$m}rhgKmT-amKlxE*nB{=MV2U- z&Gz{G_<Mh=)b1o*=4Za}2=RLFZQ^{XJ zTN{<{)}sMx2ifmdfh7{oR48qTxtD=(z-x%4o0`&DC1+616lMpF?z#8*TOjdgaQcwZ zt=JNMy<59``xdI6Ib_Y9F(tDUun6IfWQeYN)U7yE%nE0!ffR$>cy2LajL2)}ef zVlA6l6pe^`?KcF7h`G6ZnzDhWU9TW`3T_Vx$h;_TsR-=$gMtoRfkCw_n@83Ot~pXG zgbq;f9N7xpX? zo-L+~&Qh13u|D|%WW z?Kq4nR<-bq;lNX-Hx`ZIS}qt+%Dig*(pTzs;tiFKu*8G%LqC%XzoK`JjOvr*;XQ@7 z)bP5jw0)e^1dpg}T(98xD-^${;jMCxB-}(mORg`5{@fl6*Y|DTmYZV17+MVaH!@k} zUxtc?0s$F={|_?x-@`liKZJJ$6K63edwUBrcN-^1H}b!iGVT_xChktI|B3fMwKm+) zEbs+3^jj6u=iyRgW+7`6DN8H0nKD!vT7-!iWY=XcAUMb79c8=#mTIuU1#G?Pr zc!lO?Fq_>#zC1DDCZnxm!Z5*Xp26yh+C70LDH)8OzH1bZhvT3jN*B=T;h;HnZfcjO z_opZih?k5kTOm2j`Y6wCG-|C3_f;|&^8t#}N8_Dip z5tJ4@JQYi6;wQ@0Tshz>+f=rso|ZQqnyJ~;R8<<|w{nItP>~_*qSvIp(M(S50+_A2 zt;w3P+r)QF?5&3neeI%qsXOB2mckvx%M?V*&Wnpf)Z8DBu?>{fYoYKK{g|v>q27Lu z=1KoWx0tW3sZ2*jmT$HPmvxYZQRhGA!L07r%9yi5uUlm6;VFRV7#SnBw^E0` zNN?BDLfwmb z1ghGSHGaw|%Xc>#96L;?RxdnHuWfS`%BWjY-IxM7qyiD(t=TVvuW`ekm*gVxBP=x7 z5F7(vIMJY?l5H9QXUl0*-OAaJwd@KeEkal$W1l64CZ8Q%>pEIvJiK@(0%#6#6oO(< zxMY4N_JGIy37H#w9QHjp7(-vrZP*ad)Vn zX&AB>=!XyK;&X{NssPm|v-QWWSLexx5R=Pv3FXjQ!5kY;t~k8~nbbK@xP zj4Yca#ai4OSwwdlsCFNh_oh--D1l2R3pIz!L zsQx32W$gGA3f%@S^>w_Hyy7DdQ~BM{4U`}^Fo;+AxU^9t>n^zblfXlzW(CCe=quFm zi(9yLU_tt4yuxoUfRO;69}hv_2>c$}e9$nm0EU-Tc5iamoF&IFS}=^; z!U>Y|0P^@Ux2#^wKVb8FAaQbEmbW<@#W;qN-z#*b!Hr-m zw`;i}`w!vz#cJ0Y(saymm*i`GKr9-Lo6m52v;dJvepNW14&+JokNb{B0Y|i+D7PVw zD1bhn&DFt|0p#qor3TBT(+knRlH(wi->s<-ARq_`|K#}@{=xIhJ2_gZIh(k;S%|p0 zn)v+3-Ir?HDeGI|1PcCvoJdX#qgcB{b+uWrz!G({iA63FmH{LAZh)GlxeKt9W&K8e7bE{yZ`__uF%r$ng9=&yAbD zt2rfJhU|{qKK0y-M~LrL3{E9Wy`>hM(ymqVCf;dO0=1b+ z=)Na+=PIjCto>xTq!ZqB8fM)h$SwP~YW(n-KGW;N#zfz2mwE z!v(g_{hcc2HZ@jhV#F!NU9zN!G?#9ejWsVl)5@T|V7IfQr@E*9!xF-2Wp35Hh6F_} zp7Q~oa4Eb|0d~mD&or}twW6%RQO!B_YN2cdBN~#o!~N2jo~7`%#nia6CBDJ>y`BD2 z+4(w_>R`he5?JNd?k{vV&H<|)*nAOFHi|T5P%*D6z zDw-mKt@7C!@GQ=oJ8q6g*~TGneh?L2r|!z06>l-zk|s~dsj#CFb0uGX;^5G!NyhiK zp6xl8EU-utnGW~qO+SYzHxj`OMW(1>sg#CG@$eYOZcnBAQ-@+*&3>%&8UtFfRx@0#q6|4Ij&||AaAm8) z(ajSc@AN_P$(V9FzPn9yxxP-$b?0J7w5=tE1 z2ZWIx)qa!-!$Rus<@JV*DjAm+H)@ksxBKZo!=fJsVQMdrj9b*6#g$Q$iLHE$Jvy0M zgW2YBPFNQEw`JzA2-Om}WwUhaxU+%dMs%<|J%4=6~`A<{|ES(VLGa>n{ z!1-b=#+d~YA{pg89U;7_bcq&DeWLT;`bPu1L8(i+eVk2&HfbkpVZw&99&Kh^k}sQI zi@5Ftb7|?-o8KGa*4olS4^@@2W%pyVXKUNz?G_%|idC403{w|FkooDc!;8>E;+7)6hA^JC$F?-%*U zuBqU=xSO2vu4zEcfr&2IG8VozgG67oaMEIxV59tFl0;QPja0ngc~i;D=5U)pjuyVb zp6gS#a=l9P9;M*cJBUA|;$@$wETLE&8y|O|=bSv56wA6fZqH~-qp#Gn0(zK3x(Qs4 zgvGPRDiff;-v_5orv_f%L@44LFm>F1*C5qdw|NVWdSDQ=xo^5QwE)AS=0$chmSZ&z z0i0;q@b!v3Jb-tc7Em9hT9UijJl@|07?`*#ZQTt>DvmSDJty6tufB1Y7!dkyhG?PH z5PNz!#Sw9&rBWx>229W|3L~{QAJxjxUSY-*X0mc3Ij7bvOxSs=botKhv~*ir>X>nG za^pi_lN+U;yevN^tZNZq*WAl-rx)|NEL$1J!u$(pWpD2bX19pnonAA`^LRx#4HGi~ z8v}O*U!Y4G7ak+f8Pii1)8xLFXf7@Pd{WmD9DU`P|A9YF!7TWewxaSvivO5CxdMT1 zSO>AM9d5Si4|X9#x$!u-{&>P)^ealb1TlPa7(;~8lkE{x6qQp2SNE;LV)trawlQBP zFu^TOyMAJ*tNInc3c|4EdjKe%d!{M-WK}am>ZYwEVupF80!zz6#js1+Ex6ygAzc_; z6xx`uVK^>9Jp)yhhi1d0_Ni|r31-e-7SHn?-ZeVehqB^yP8yMw$lv{=VfEv%wZbxl zx!;eRTFA83s-zsLqj)7 z7m{5LU4Rp4{Xx#(TPLgYrw@D{#vFoDH(*ugA&-JmV)Z+O4}8T%g+=Aji!>2gAE)1P z1qS*hN@k;71@nzd@=5^Z&}TM|NAM!K76Af)b#A3Pzcgf~UoMu~V>4{7R@xLzo1=2v zk?D^P*GK1%?eVp`6WXs8OfM<2K(4my-9N7nwO!Z;-%_Jb9f%kf(PGkZ&Zyef-M|){ zjzX>K=Y-CMnhhsiEKI)W*>KAQd1HcJE+vr0YpnGLJ2$7RQhy5iDFC})?a=M5eu=mr zZTQWYP*hgau7qe$y!1+$znQq!kssvFOP0@wOgp%bd1dd|EIif;D|gxlrgwKec>Pv` zUI(K3mLcQ^Jj1u*M#h$Z{Niz{TRt&>xR3Ef7Ayhiq^=g%2=5}aep;v-$H)4Ho%zIo z24u?wMV$Gh_x~Qpn@aFzd4XYlrpdmu@&*Ssxdu(EK0|c8r|ZAa*?!>)4LjX{2F3^- zcs+9k)?Yq{-0db*!3H(L?xIlED=EF%Xx=%<*Q9u!GxrU4lH1%H2#=Le%eLX6m&)GJ z$gViCKRV46Rxr6zIGI{z|8YrmrQy0eWpz6V9Eu)d%_aX7g%6UT`OI^JOvlRUKhm7L z-M94Rw$JO|9wNm55w3Ob{~jVJSdtKQ{Ls5{9^fPb^kZ=9#?O)(9PuXmW}thi(C||o zMfT@`nlD=s_aqMjS=owBiY(n-&$7h5v?4?C#*zC)n3l%jjd$2l=YTsya!DKY$!6uR z>0DTWN(sswm2;xKGs{r_LH=m1qcHzolKbRput9Y4vaB5Cn#P+N+TAw|&E14Mb`DYJ z>F&MScU9Rm)Z z9mzzZ^K{|d7p(bq!}3{4ZgsTHDjd2+Mp8#f;TGds+o8v*sZMS0Uz_~VXCp;-9+W@3 zd>W9~8OLF+BGsRDD^mJTECrCx@>}s} z=ZO3T*Mk6C)3b~54V12TcUzIob?ouJ^ZcfBx3#(oTmE+I4x%5YUW{Y;`(1;x>nOb4NVI>FpYkV9Gp2)UB1X# zL{wOfK|{R{EG!FG96@5P%08K+W=e|-FU+&7=UV7ge&cLJ!EY|cvkbjlv1R3h=L0lX z(8?A#wztuzeu-QeLOtVn?JK6)0d>70B=oKgyR@qY>Seoa&RVbR%1S|y^KO* zpwICAN_J~_u=4S^`A?wKGel0AsKy;a<0D_AO^>Y z@x;-Sh~uM8z{&@i$@fC5^XSo=yLB_z?l|V~6euB^6ip+dTdH_c=fY`^svOS~I3PNR z+4-ck+R%APDzi~%;{h~HG{CVzdL{h3C#&lE*W^>2g zW5Cfuy0Jn#V&5@fcgy*hZtrHU;ZZ?@PoXwpcS&O;$%Qq#*=(0@1KeJ`&(>Yir?I*8 z!#@G+A5Bmci;*M1V|x*B4@n6OrQY{uabf zd*X@w9EQoy-G7TuB$F7CUeh^7EzTG*dW>C4=1q`-Jq)HrlXDot7tJx~jAWMjoi&Dr zLz3IiC7T!JbC0YVliQM8Jh8C*<_f)@r9m;YlKIx=pFxS=ZJwsZ6C_N>(n(0 zk{Se+{XX1cGh7+};8uXjV^$6EG-2?@IWHPWiv6iO*x=VwZ-v#vG{Cl3&P^N?QZOkY zy}gfbfh(~hX))-2SL{u1Ef)Az7 zb`9s$A;0oYZ4vi8d&yWV!tZ(1QziH~z zK6Gc%eWm>w+XTI9{VeAmcJO;|*2_=cEA;9v6NQ~rVc4(6j;P@t;kaNuHD*pSH{tFP zxdVG2j`KIr1A9x%_D9LH*;%)PRxbR*a@UmSM|rqQJw@RBp@&nAL0RTNV=LiZ&| zM3y1W3)E=d$80{kNQ7>I7@~VmVBHN3>b>6=*uN;1C+@fW>c5oA0o;Gbfd5%xr~HQ) z@NeJ$mqPy!mr|?wFX|lqE5PA;4b`u(6}`mx2YaDHOr*4EOUcl%p|V;CG3|!CLz_LP zNmC_*p>lTuuOP4B>tPHMx2>H=cQ;S*S8z~_Z||0QQ?|W*<`0}{uRs1L@6$(oCnZ6j z_Y3tP!?!NbP&fEgI*OPfrz7`)hoU$8uFy=ou<7~;W*|)AkzKy(4^`R~Vq*QW& zhk!`qOtdJwo^b{(Zk?li){|xKj{c~9seYuT1k!KVp|Mr6y1FP67M1e(VeTp_CEbiz z8n3a_QRj`Csp)7(vX$zK4}-5~;u7gU2fMW!Z76Yqb$lc+9-}E)Vz1`tTe!3JCn=~# zH`9|fbn=a@6A(|Z`Oo%QK_!mOHFPV`)5slE^i`$jIkYBYWEB_9KMgQ^A2c$H1lH%T zO3I?L53}(fc|kelI1*RumRp?#=HQXo60zh=4VSraw8KfZI}LR@lvT;;5FIxSk>$R$ z_94;2<1u9FwGv3<5rH28idQ;oX_nkZ>K-bZ6DiRHvqZUiXe$y6WsZsXz2nH^8(>Ef2C)b#rvybBwOz;Wl}QvEKS-+sjPNYGeI`&HoaN2tT+&Y-yL(Sm?>j60oABF6vBf zZ*G=+8q0~XH%(x0qL@=2@eK-Z9Ewg$XB_wc&S&dctZ&e#!apgKlcEBOw8vZ`>1r(zO&O1&_APh%{6Wo43ji?^Z`;Q%QB=0WP_<)i$Eoz=r$qyqlA=$sxWgs}%lI zqoJGF;WV7e6{r%IkcS)DBV-3#Red<#H`wuLR2j0|Kd5s7h%)fZ#0MIqR-HZitnCK*l{nELE$b^ah7LDn zVv!{Ywyea697GeGihEE3qG!wX3aFTmqqm2t;;5y5OXA#j^{zhMy#J8CwDPW3w(%G0 z14wu=1ihVtTkc9hZms^(sI0G)4bV_JM&lQ4T<~r_XVIEDk$V2!a1#)Il#AJsQ|QIw zR=G1&)77->CZxE@Ltfn*NMetadxm|48VMvGbq;_d*&l%CL&iQy=m3oE8y6Hf1k3B3t6_3vA%H_QU&+AK( z{AELz#4a#y&XFWC&-%!OU8&7G>49;2SLjI|J!Ct>!w_dmFF@cY_d#vvx&%_6qWqvGVW|&BW$Az&{$`+F(l$tIL zvXLf+8RQn$+KEve)O%5(6ybTzCOFfqV#2v}%;0Q~tX9w`@G(wZEu>D@=MpK2{rWv6 z*$_Q8kpXz{ycz(@jHxrt4jr!XtSe63$FgDqMw>dbjCEY5&YuFhYc#GZ?g&je^~oZ` ziw=HT^~~f;n?C|8?8+Q9nsfI-nRqG@$${($)s3`~-I=Jc-!^I4e$j{6IjtMPO}U>M`ieB>M46FuI4Tg5j4#_xNBgV7JZ0L^b;ywn8 zs(d~ zb8)hV6-T7vdAT(j$5MRx6_d7__)lw&bB=6M(4DlS?O7c(U5W@JtpGc491BODaJTNl zjU~;u1pT>G(Y`*MtQLGjlrTh|M})w|=n$HR1tscUM&>zEcEnl5;>@{Cf;Z4VTS9~- z4I@w^%;LrKtbNRq*4F@s*w(RfXkuwMl0Q%%xBZMrKR%pRV|}1~Pq$^?!*gzC?;+3_ zq}OG|lL>v(i;YlZ#Y2b$9vp_yf-w{P{}2O5%&4Gqg;8cRvn1w0V%2J>DO~c=#%a~fVYb9JwFt?E!CZjKl%S@yyNuUKN~-ePMS(o98N>-i&?$l4 zl|lcS`vzNxNM(Q96$k&$|Nq;q_&+=C{s}$EyLyP3m|0u=2R+1Ttp%a2V0=n0Tl&N{ z5Yw}OCqX7!z#Ir;b~m&uS98Yq5BHnXgb1vnnafzaIE&7cv&*HVF|Nt}2}`AC4@0*{ z%}NYSYqr^WMS3VjatI0lsx1H~V}~0{-fu##eXl!C{C9Xx;(I@LsPaLr`;ETYm-&15 zB|v?1-qYsb+#?|(^mJN-1>YS)vN%E^B78h(0MUvc+jr4wA%Aw6sfZSk*t_ zJruEG`wO#P?mqmohX!{C_0j3gMRvO9V5HvSq?ri#dSeIzJO}}q-sKYXuPCq;m7~+% z_RHt24YPo!7WY{Vz@a@Bvv+eMg)cWJ4L)(EgyJdtQ`okI6@;Z~Ru9XC$Br{ji$E@yRaa1Y3WpsrWO}sOPTIg)CsoC;0 zwmLdCJGru)2V^lLK7{D;zFCwoUQ4#(csuR0!q|nU6p}ZMG*Q*8o^C&EZX3vZueSf?jS}E;qYWLSj>nRoK{T4BDu7dwx{N_ zH)eH{+9uUqa7a}j+jSf1&PB{d(;n%n)o>Wg-OEaE(!vCrD2L33cW|a17k6{+%jovFhN`9aVqvW5f z-ULDnz1b?$YW4{8b&_IG_^MUVSW_WWU@;0 z<GUH9m*`-m; zlQM{INh11Mjp7*m^W_RRob_pn7c!U$+NE|AY4*Gndy}Y~1?d)S>Fox5RzLP3%`_)U zS^eXWBS)@0@?g^H?+WG4rQAwwfQMFB_}gcQ1Q$sWQo;=}Mwhrsnw3`l&N2?DvllU< z`Da{Z3+(xs)T*~>H!whk6zgm>)G)APfz)w%Yj+zrh(TahLZyTDR6-$U;L;09DlRBQ zo6GUQ)jJDd$|ZZNZ6hFJ%WM4uvunrpPfUdwUTf3U{-sKwe#dHk%%rf5H%3ePE-s?x zR9^tkyfbLtD1~=Kb+F(Q{5zI%KzxzLGvmgE53+SQ9-g&6+|)*7DZ3}b)MkG!MVjvA z;1h@&xh3uCv9^WN)zI3C97!?zl*)F*$l{yHf|jYQF}F6`w?|j=cHqRQk2;q^v8UDp z?Kv6Xq@gch7YtL}Olx|)M$yuvfvz0I+GC`SzWgKAa24wfmM{#p_L@ne#&Gal!Jxqg zTw+bs4fE)7dI36mwn$pd9x{fe!@46I*G^a9GTo0+t&>xA3BCBnW3CB>@Il^8=90b^ zkyIA!JGM|#$ZWOk*DoxuU*Slm85oX2!!BH?_zHUm2Lpx2=n-(44t6U08@-N@7MasAveP0BiIiUsmejC{|e^9%ZVz|5Z};eN~?jD}wad%#x(N%&(cZx=1 zy5U_uB--2;EKfFIFnA20^Y>We(+<`b6Jm^NWd7TxAbo%>HL?=^Et0oQ&g8V`(j9l=ea+DgFcyrv_fBVe@}s27_U8SOoeAsZ zmTFe?n5BUsrmZmmG{OKx%XtOT>9BljrwNNxmO7}Biz_!TD`=^#ld^j%DDZ~Q&#^w zR|KRZuNK{`b`-jsISOepN;YyBhAr08Oj*=^M)4}U_FWgj%T{U=`~nZ};cP=h7wMJi zbei^`grc^QBkkixk+ZxeEU!PWxmF%XLGPBWz?biB(WMM1Gztp2bVmK1MTc;%E*KpN z5G!tdGLzH4e_G);1(yW}u~vVD;l5`h9S23z%Eg$O#;ED&UXJe<$BOh;M`PQ&Ogg&! zy>FmH4|QF<4T%31K}~X^f2|WkU+}4iE^s6~X6+>NkSb;=gRx^UbD8z)H@&B;gn2g# z7Tkk9G=w}@?_M?h0_25RpWVi+fE9(~Ya5P?-U;WQ#*-vit^MSECe;%fwG)@c77g_i z8VxNWB@aE?Dm~>Y$2I;XhuVs|I&}lUHpjg4b-F4&%__$a{v{7hbu1bU zuL=I8(!|zpzq3y)lzz@=(af<~Gge~AN+oHw$XDCiwTQk!x7<5bI$UmatEm=AMPhm) zHgn~OZ;ARCW5sfjD*_CbP&Rkp&=~+4sCrl~_kF+gJg1VzDtPYd60b=)r*Yea)#)~n zm0Qii<~35w1zM9pi+-~0G-K3I`NZo>gg>o@WA!pqy8K=vI>L(2(Rhyfr2XSp{q^q@ zY_Q3KgY9o2gZUo|8T9{ec;FyQC} zmZ-A@=wRky&M}9b!1xtJ%8xZ0Y>{t)(U*W$`+=#$14gpy4 zZx8BkBWvPcRl>~-`Duv~eCAFiQs{}&_h4`!d%RV@=h5!vmRmg62lVSp8=b ztX%XpslcC0YVuO{-dOpW05mv;iF*<_hIjkTlT7KRSsdM@fNH~>+kFlmpREY4?&lvw zDBUywq=4t7NvARA<%l+m&ju_Yb$dF4QKx5VaHnQr4Nc1QG3wc7r}&KUyu@7L?z#5B z!7alE>IRydFX|bC+kVHVy6=Q2QDBjBqq~g%OWf_TT{@aXlRgW^yMkPnrcPJm!HFVp zUYv6+^>jT;J>ypcw9Z?Z!&u#>XxJT?G=EEs@qsU&ql^bd3{(7S!)|v^HR@XJSWR$4 zgHHcKSIKXohLq&T^^;0>FITBI%dqiL>w&2z?-BcPcetT6b>213*)E#3out*p6!Zo* zgQz@@sLxdYjcnQ>ypCEL)!1h8`K^yk^{1RmVI!k5Aug-8BR5Fb$~>N1btfYw)u#EZ z(_;U+>}0-(i#e37O3CJ-^Jh1|(5wT9#%x zXBWiYQIfjY=N3}V=KIixW7%hPr7%&`J|}B5^Ml-iSTmtuBse(}OauaEnwB_2tW;=o z$2n|CH=jHxUQrDy@l}SW^^9ESmal2KFt-{dsfyu3~U~wd|uqScw2!PoAXF=U=XEm^46D za*&~NMVB<0*G{))K`s7GKL*1#WoCNooWER3$gTxe)pl4Xl-+Eq?a36yo=;^~C$H27 z-d#W)#qQQR>!Y@I)DuvosGEB3`iOuGd}q-XQWB+QFb{p1k31^GBtb%9LV2nYGWv?Y z^_~24LpQzB742vc(x|tXZY^ETV*b$D7DZZ3i8R|m*4%9f7jkQ8~IHy3_I%%1_EN1=NCJ4drN7~4Js_Z_u3m}2v`B1;$<3Kl~92Uy1PJy&Ne6sRKM3zLS18+SdZD z0lb1-|1^Qngmgyp1(Sxg#vE)g2xr=x0Nn(&ZMV;m0b8YhV%?>s=vMl;M=V7Cbh}3G zGu#{}ZS`YX7~q*CQ%!1nx@iNisZCni8M_gDBuq+H7wffzxFO*03v~~i6CR!X94<-zgDBdualz0%5!MpjjcB)4kc#=_}-xhFiW~X&Is3mnj!f?($CjEc?BoG5Uy#! zp3wUQ#NGt*kpe$eW*si^NX;18-RuXs1v+W;VIb&AnSY`eM3<}0MXy;G^B!!T85ayC z8AI;`BecidgSzk2ZW~I7v>9V+sv!`f;4pN<^w^5=VUSjH@N-C?fYcq2OVAn(aOh{U zk0A_pf43qCgl8aH-vtgV5;-_yW7&RWhQiT|Fe+IWUvgD;?WiYc8gS{X zi!M2oo;!*n+q{Z|pHJ+g9#*90KGYe6?#M`NMl-_Z9(AJ`EmU>s!wINWPovM-FLgAC zRY&DQu^1I=Xh~rVx17V;uG>|QB~IE_pRwSIOgeW~4Lm{bqwTKEzJ{dS^oG6QZxngV z0BYQpej^fn<%MwRTHO_g2F?6!YFx^+HRBIN4QzVjdA8f(S9v=oen+sp$|kvQ5vi%Y z6Ab3?DJjLZIioHqJrTx5E&+wA%$DA&m#8+pMWfZVxc0`d5O)uLm!q*RM5n9d%haRp znS{X~R+&cHi_A;dcM;IzT&pR*Vch=WW%2)Z;KD_4mEAnjW}WbD@kt=|#t*0C3GM!y zdmYr-GE~$fa;w8J0ZiiTHPGzkJc8hC-Zd)dzMvZS#m?llpmr23-u+)2EkjA~B*z&zd@;9k zY8CwOOa?ZMc8R=ka|J1iCXFptov;v-WY9|x5`S{ekn?P`uEF*)6(ubF9ML{AGRPU% zB~Y$wV_Lw*2Hn+?WuLJlME-``V2CP(wbO#M|t6-2|bCfD&r!#QPc!_is$pR|DeLbd=W5+r>7R9u~pCHA2da%=TPPrR)Kal|)QT;{MaMi{{c93LK_LewyJLFp3G#MA!H5(O z%%k2$m5%yJ7Y4z6hP}9I?}d?C+)mAoYLy&2LKUq@Hx5a&C3og(ygbS)rhL+}CD;|N z_F4%C{zE}R_PBso@iTN^bgr?^0k6gJTwbZ`bNuGsZmGTMo1_3Bf4>R4H@I2|7p}Wr z$1=AY_<|@Q-9|XSRffKp;op<)*9o+{^)b$hNe{77d%L^%@KUF#Hw+FV))i5Iy)1EBIW*x57v~xD1t{ZaQB%1(l!nl+Ho@ z%Lvs4J(LyHBNo*?wDnpN6fX;7YUUJzzJJv|sR}#|b!^7wP&`Km@?4ovQG^Ww5D#Dt zq`OTIx?@}|eh;=c>bn=gu4Vw}c7h{P)EQb0`&hqDrl`XDrcM%4YF&Qao7!-UnOg> zhAI{M_5?Nt=vTBijnOU^JKt}yDGJ2PK7yCs_=*cey`0nNSB7ij!)*YGC!3*7&1W^v>!*5X^68|Pf%yQNcZLm5Z?veVzXHoxxiJkATO`wL%7@zoNl zlWdMD$}Sh^9hsVRxYbfS%lRf1yi~o6)z9+;X+3t5W~#z>e37eO!fMv5zCEajf4V|( zR@5NZ-w1>Q6#M*q_+5S30=kRy0v-I5oAr!B|%0v%Us}%Pq~E*#k}Ee33R5p-$C^SYL$(93SmA%RWK9 zs)7bT&fC1zKhS!sKXI%UfA0o7vIwevh3`}=-2l&pQdPey2hP3?O)+rCrfkiBy!l8?*H!fQ&m+zVQzzqfk%wW!k!DRuafK_n$t-`pE(0-mmkIre zBGkhNY?ymUFNaZo7&drzZ_(?fWmwr$(CZ9A1pDzXtpH+%1M+r8(ucHZy%v)XLy=WKI4Pal2s-UkcKJM(1ERLwwRGVme0^gi2!qJ5G{ zAQL>BIM{1?m^MjRyEqwkl$55qtau~R0JsS>JGK#Nw6!gfY^@X0TNL(|t*pdKT0oW) zQ40=B{a~BuvTcgY(C-mR>wE>wAirK9YgYwv$l?H7%VCmDJoQ1InOrB z>b9=_z$?UZ#uXxIH>bC|R~-X3y-swi<@q{u7u+T5^v;d*oN3*gsrT`|45pAlq#4b% zbWwbVlS*W`WRk&z!4f@LA9ras!dsng1Ie*?li%fgq;KSLeW(@JQ$4w5x^%$*ZZU#3 z<6tK9=weX+tXK5zaejp3_!YK0q0Wiy4}q}O!@c?`1#ss+8HU)$@*fAJBCY44=y+bj zq%9*?uK7XF|EU=^npEM@?E9z($euM{k|k<1FN+aK5UP7XyIn#YTejd1Q=?C^1weA7 z5hXI3)yHw+TJ{Rf`f;n*YY2ur$rCL$&1*8IEI?(JHK0La(VPcWBC=&LW%6yIiNmO^ zM$kmFbMIqUG1c^Ylf>Xe!Mozv#IvuM{JQImwyB?8JNwXYh>NgVj4p5Uu66In^2MlK z`4bdTmyCVjaw>$2yP~{%^RZ@W7B9kCbsGBlZ?9Gjq`EOT5)e=!(Lap_`Tl{E`6goi zZ@&~q`U_Et=wy1bEU>@TOGWRb=)#;6W>+9N#si!0N zw$D?Ji~niXF5ju`=f`vEF3{tlH{`Trq-FmrP>JY^qy7+>?oq4^oaM0V5Bfu~Pfsb* z#nkqLWFUPsBBPLA(-)FSIlAlt0u7Kh>^@r{YLRZPN_1`nrlAp2KAWQ@TZ8 z;yiLD?NL>7;~^8f*>V98BZ%n<%>~M9L&kB+9W|Iza`dRE4V>yGu-VCyNm4rPr^O#3 z&+*top^FwF3o0Vv`UsA>S<}o-BO@nAVC@Qte=7Y@SX_$mFEYrHT~ekRYZn%^K+GWJ zDm2{IX|Yk2{GwW_euMH9SivemtV350v2Y->kOeh+Z8A0aP=|DSi5Kl0UiZzraC}CU zjDZK^9Ae;39l5HgyLBXmz|BWA$rtnLNcSn17>}9H5K<^P5IEuY!N-!cl=wx?9k}ZP zH#2hQa->#`o$-}%mxf1arg{)|@}dpGWBdtW&eh5DxvTV6*D^Jv>LBo0oS09gLgp?^ zF+M~UG*7uv$$z(4Ou?fVY(Rm&U>lBz1OhR)A7VTr({oe^`5B|1-(1+E}XI zmLK|g1vtB zQr>}TJ)GAf6F!RGJc$S%7VWfk<=zf*FSW}>KWxGwiPD18ylW6H~J^a*+o zZ_fnftjHWez8zJaSaeuBk6w%rUpB(>UiC}Wi1gezK=dQg5flv&BkrO;r|FFT^dOe* zjE!?ec6)>f1Ki~H9Xu;O^L4-0Mdti5{Xt%sZ5lp_SdZglbxpasEOv{KwRAbHGZ4IBX z4r*(z8{h&)wDGTOqHAtf<_^XPK9kVKwQwik^ZSh0gcd(M6SCZrw60yMW7^au#wW~Q zsWx~*ghFGPLXX3yod+k-U1?Jp@yd<44-y0qmxzeK`WJ!;1UrW2gMA=(tABMXf#B2x z!tvC(?~Ph9?CT#T3_7_U634dg3a9lp)f#2iT~r=D*%^Q01+8~ln%x>f`1A&CmQC6% zweKMwKeFaHwKWfhcWA}5Y5e8Lt}SIdzw_8iy~9J&4t|=QpKa9!GlJWM_`9w2o_zEQz3$S=a= ziUl^_KFH6AEFq8aDejRr_?F@XJg(>t3_l}NcY!L4P;U{6hAUp$C`mlAwump$9*Qg* zd4o1f1tI%I`a0ZSD%@Wzd^dlnw`53z3gAEqaG(O*QUW@YUht$pLcf>*i>kBk``MJa zGH}V+_b$;a=UiD%h!W!vtHD+DS|TQ9sUO-PSl>#UWWgA&Ru;L_>sYv3_yOCBp^rk- zo^X04;u+&ETg^y%DqW8KgnQon^#vGCi|RyII6)MtX;yQBV(;~f4Vl<{{LSaV)m}iUMgm;|G6%z)pZ=d<*A>aripS3V8RZHmi2=9RvXHKf-*mp zC+XPj=2M6Om&UYP*hN)El$RO$(Bh7=FW;ZQ?3%5^|^}gyWJ=q4Pkrep!nDp zs?T7RS>qLz?J~0DX-Kuy@@_MrV1l}MR~N_jf?7{NqQ$&7biBQF*lWg^FH#Pjz+;^T z7zI#yND;=L%ohD*w($?>y!H^+jVN7Ijmn(4a~-9e{ad{mi7wMoiE7**O=xgFAvG&Y zm{d(K<;6`Xy--nFWvY!RrxzkGq@`C9sqS&k8gCup@$8twr0904`GwaslZ>(pwTnK# zNgu+@?EV?gMaU8bl_S(*(jl0c)l}KDhKxL8s>Ud5=L18P)Ohei5Sjb?NtF0s19xTN zZOpRnZ;9!mT^c8{+<}mxTz3Uf9^j|+YO`vy(8G$kr+v*-YF{GhkFum=J!i8+Hi<&T2B!@vk&h!`KE2`4?`@XB! zZUtfd(_vgGSjzd$DknB&r0g-Y`Wa+2!=$0q!Wft2 zJ2unnxZ{v-v5%|@V01#>lZ1K@0Z~DRXXt>cAWUviUW$FMCK*p)3ehgf99%~!Pbdn~ zuBlLsyNaMy#P~bzowz&l9b`aDP@<>A0Jx%pfu5m8vE5QlXF(Mnf>nHw2OuZN?<@sT zI4%ENfZZl!ZwZxgYGNFC@O~gF1I{+HAalEX>D);PXUv~KbzYSvdxG&58F@sN8xZF_ z>7)*StttBjW zB+}d?ew=T)gyd++eX%h`UQ*OTgS~8!;ZOAPgBp|Ft%&O+u@E<19Mf93{dN>UtiBMN z2+c?f1Oxv1khd%Da-ItvA@5MQtloBp02y>S`#YGS?+@4YR$0ls40j(EZHW@|3NURy zb4KcE*3!b1r&xki4*vR9O7_<1=i+REOW3C2mofXLjv?llb zaCMq$TS9bltF-Pc0t9_F;@GtLxN>#{I#5@KlIWbt1 zxS5zQU90WChy{-5fj&#(y08Hwu~7Y#DF-M`dn!NvV&Au;nrX_VflcLqBYqbbTz65X zs$uSdi$U|P03IlY*y@a?sm$n*>oh#FRfm>BU4=??(JEfM(sY+omiU>BDdoPs3tZ8x z*@+|u1{HoDm8BHgN&}rOwpD}BFIL{0dGCYr-|v=;n%IL^(P{*azyg)XBa9Z^ibSlK zTY93731wtQK!h_+=|5!*`fYuMj-SZJYZ9)o!F;yKV{kV}*$(M#i8&johO0#jBkk4p z?F%O5JV=}3RmZ3!%xPd%{8_S@Z0jTUNvCBw466 zRAsdBoL5cOq|adKKQk=$+{mq5=4i+ATs=-NasA95X-P*roiREwX8!Sves$gY)xYU? z*5bLD^&ZHl^6=pkP}>T@V;4!U!VdQ-0MoLjLrCH;H#kP$!G%ZCS+{9!ictNuk&N2d z8i24$LdeByT_2RPMAZPFTqI7f}CE}qGtMETcbm{ zu$x9ioKZ!6qBI->FsRAc>sVZm=v=(sdPn3PV(+y+IuQ04LL$vR%oHXJw+biG^wAq< z7{yQs$g0ddhJoMW1c$v)1kC(kpfk`B7!yCaC*do$VX4=obC;nyI%qpSjCP7f86Bui zEE+H$HltpN6pW@Em`++6oPqpCa3$cTVa|N{!Ow8eNT*3Jx_&0jeJX)|0sl*}8PsIE z{TCbvNdLPv`=1q?^#5?bDmpmWx{&^7VE(V?|59!y>p7rEpoZ)MBv$lsh2?~0veV#- z>f9+qSmkt#0}-vsWX@AADR&6W<3KZw1lfCDA70ZtUBcI4IRH-ADDjawH z7X*|%E$p%o3kQNvr?Oa1vn+Pj_Zq@ksljI~9Q#E^ zneX($Z!^a(_QZZnf}GD-Y}e2@K8{@2SxlC<#jMu&cKp;~7ZGoCYO3jp2Pq(DR9DM^ z)&Ny@uXc?-v2Gon8>+ZJqENEXdxNvsE~e<+u;adA8`bdUb1WHvLxW6nTRv}Z*yYf8 z;5|2R%O;GAO4h)uJ@!zmL>BGVUqztNiA<(cwHI?hIC)Z*@+dpBy#?U;^c-jJG`1vb z)M(kUrf6ucIc8+W->36frRo<=f_jN$6X~$klC^>{PrwL|+KgEE3yCKbms{vH^HD^( zo;T@5_=Pa&or6Bgt{0{kU#f1Oi1Uq?<(>R-Ly7QyD$Uiv!H_`F5Z7avH|hm3@5XtR zdyQWJ$#D9}s!0{WR|`n=X|}1M*^KcSc96h34<@kZFk?{FQ!p&4C!*7jUpDDLyGy8& zM-5u(Xi~3w=vW{NAc3HA;fxB$joE9)mF6UIG%nKMa}{o{oj*cbO_jflDdwdyRoHe| z0TNJoS98db@NVbq64UYjGrO(A_n5q@zw(*>MHisO-_Hs<^2+(}mgL(4<)^rT`qvBh zm~(uYJRu4w_?}*LA0z53cu1SSJ#y*LdEcRk!1&4|Br)y4GfFJrlGf=5)|P3yjwg!2 zT&;-{R+l`&fmXmZXbIQs{F4bw6Np&Wp8fWxg}VGg%A|i^TPT;Eay9j|rqTZ4T9~&N z-4lP1(^G&aV-eNB-r51B*HG=5P2(oGyh#7ZDpT@scc_%&38 zZ%m{g?$7N9+@l*clC1h(Y0Myy4y|^DE@H;<{j2u-Mh=a(g9*Q&oeHdL-H9nfQ zG)+I}jb=iGz-vE0+e)N#swp=6y!MQNYCG9ftS89HB26|%-D38&XZ!XFKlHsU3csAH@F|LHyq{>=m7LtVc}d?@k{ zY9U_810%#t5MURT>KHj_QgpL!)1+nPlK)t0*ZC96(<@Tii8M|oGD=Y8nyWM{EEUw3 z)m+pGxBrwJMf~!w(NzY0Ls!$&s<5-86c^f=vn=ti*G+0hTUUJDPJeVU9BR&6dWfJR zJa*M%I$>?sRA1L(;Fmz#2gG&7_!fAloPv zo%Oib&3M@XNvx%`&Zh;aQm1(ZXX)T`vJ+aC1EX;6Hkz;ND zCN*OLUB38GAFk5DeZ*Im8;+Z1j)x~t$f@SC$RU*A=5CNz2NqeUc1SGfuFzM`fegc? zvQyBWPngcvY3Z%tSEIGpMrEB$g%zoJ$R}Ur!P6n0H|ls;&|eSP*qy&LU_d={BGuvC zy~&ZQf%QM#*@rcy>Z|q}+akm-C@ZG9n+nmEZ(B9iQ=-}K)?Ek-D>2h?S4(O> zRo9K10q{k@JSmp+kLfed0Dhf7uWi-~b=r2*cVXED3lE^9(6He)q%#}b!Y?A&#VbfH zjd>A&LDJ+;G~z$Vd;*J^2!*WRmT;n&w+VFha=FLPj!8MA8RjvIi6EozK|^UCxKnd9 zFX{#ZUluUNOTxHKtDIrB(TAX~v23p~ojsth38v44V(Qowou-$&zwJOupG-3aN6a!w zZJ-xp^jFWvy+W0H1+VfvG^!yB!+t|Xh~N(k+eHNH4$CJRvtQUzgmM;^cp!R)q#|epR(PC-+ooO zyv#}2%p=j5vxNAskyJXx8rHM-8{5+p>~|%~!2g`Y@CzQJE_~NF-c_KhvqG?Kf@8nv z+X$GQ(_P_<<(__NQ@}oTGJ3=+_+ak%G5$4>*iYykZjEfj6kL`z@{2S2_d%7I-w?Qy z8?N&Vl`NNDA8q_q2+NVV7eI~z-ER5jLx;0Ic6aDSp5}14wa*hO6|cOOl|!{H`C2-4 zn$?1c>44X%j=^?$82(NBlK3JGm9skG~CQxNpAb`5mJ$}uvNi@q&P!M}^n3^pCQDm7Xe+w%(y( zzbR__i7J09(*p)jzgeWLwf@id^;;i(0sp_VWA=!Hps+%#HJW0wRYsasBvS6;Ta6$x zNd1g&l;J2%A_a){n$0r;px1^zXWn`RTn=?A@^$Y`zPpNTa-5HgZ0tk^LA{REr)2cHyAoOM(C?}5y_ql7Ha89*aanl173y1FU!VIEgp?ec9cQ2A(|D;#6j=e}Mq5pDtC zMdes@L}{GRtBeJs%3#t|g_VEG1gIJhb2hNn9xGlg?>tv7S0`KBnMIS4Wl_)>^9cOf z2I?WTj%rw6X^TP@tk0dTDDWYg_Y%X4<1dp^Qo`yVHHor#EB7m@MJa77V0MhiB2!t# zH9&Kw?NL*(t})Fd2gYeRcK<`Ac9o*C$^n-XS}*BdA~M=#v@EyDR#j-X&C`M-bv3p& zjDmHT7RMBBhNa-7H^QQ7s>+l(#KCNxmJGn%op^!g!rC=a7(r;GIF#s$1E8dwtHb5$ z0JqYwM*V6xvRqn^zj1R0J(7Bx?0-Pb1uqovzW4#%*1#cI+k_;0BtOXtCi^HJr$3tE zgS+)%iaF^~N+5F#NR5X1fp2rqN^f9~4Kbg%%5#-Q}V=fD^wcVI_U8U3pwWXP~P zKDzIE%%pFol0lAO-r|m#h5`fGh%0c%lJ8j#twj8{ve8E@%T|0>3nX|<3ZbI|JU2vh zg(%6<1rbV1#A0BgDPd!JTQK3Q!ocOG@XA9%5$3`d2Z&kqs7`V8syzzH z0wWapw##Qbj>qf^eiVj@#MAWGZjW2R@PoZsVD#u6J1c&#P!v zZ#xj0gPr{Nenx)go^by zAbPaITskK^$7lYUaBsJbS4Kt5CnG0~WPJ*bGtcMR|-alYo$^$Iq*aZ#+%q>__U6#Lkr_1g!+86P)Lsr z<-rXEHTQgR0UjPTIaApIQHtufZFQKWYQnS1819m~AT&!S1+f}FjYunq>GlrAb>QYATeX(a81dJSiOHt+f1Zs^5$0+}X%X zpFdVR6ge(dg2^+;Gc1KYJ}D2|S-`w7zq{7m_pICZo4-kVQrNiWX}$9^6*nx`QQo&@S3du01HU#Nzy6SbiGt2 z)N8?QU$Cl?skN@zR95R`ThwRclUet(nA)w|03k`XD{a|tkNG3Ia@$@*7pLuvdrr4u z-bt6vq{E)wajNZBxNX&}JIm2xkBPV20GGUz!w=gx6OwUaQmlT4f+z#B{+rIW)qS(g zOZM^A+RZ)yHABm1sh*eE^l>YuS$KyR@_6jby zpUa*d_tV4Hn87`#zOE2P6sB3G4R_3{AwU9v!RZlLtG4&uCHubG-J5Z2Qdv0^eRzqxJrpbhO}E#L{g3*BBhfguv*4x zBh94mbS1D--qmjAxAt3AwX>-jmRM4UvC_s-F<72?35^9HRL`6d^i&ka6c!#vy}aLa z`?PoJa_`Buoxaa_==ZwJay@T$-R+h#fV4sH!sUV7!XM~&QG`7o_}v3O32z1=jt+mm zzU2A(QijE$wqp>a5EDQd^6*z2m?Zqv-S8y*rLZRpgm92ZU83qMO})iHkgE=eiwK>h zdJT)11)clV==`9C77IRSYR6xCP!FW-q&{3AxZIR8hLygrN^CS`dRSici#(u_zvmax-_T4&EB?8!n%9~;h6tQ;O@S_VGm z)_FtW%qg&|11q#lK*!(AKbMvj59-Do_&z>>%)I3M>9^;){n+6|z*U~0RGW*oAeQ_z zb7Ar!pol3xQ^2~Y^sx}ixh1C5{Bfu$CuXvHTD4*Ha0qe75Z6^h!}8=&cxS0b&N#pN zB3+faax^hLU-ZD6q~5TuYG5CL@+P%CkLzfs*T&;Ow&&$1L`;{20XfxH(fw^j>BF!X zUuu(oD4uS#3uf0N;_%Ff6a$ZJx*w@Z+%$oB(hh~<^QwBEn@3r~NqgFZ3t4sQt}#dt zpJ-yr<+f^DC@Vp3Oayek>JO!P(LY>qJKRMi_n0=JttYKtdaZZdX`aS6=P$Ts9j9hw zPLAE6pllUI%hLDDjj8moT=naZx@#@8O-2dlskW9mn_5RuY?`R#geR7=nop==dz?Iq zhID5@%-_gYUF|oMo06-+7prchp;@{>$sQqx50-l-gm3s;k7(A(lns*^&nz18CAz_c z$r|}-Hx>>}r3#pNCr6(H``hHFsEM@ksaa!*$dW{WXZz7QMy zrs@}G;EzE|sbV|I9!N$?S^W7^dbL`qby6PsIMmuNKv8Iyz19V_kw?}2t1P}bB9|rp zn4n41{e$+jUcNRISt0w%Q z^kyFyrEzdDTLLHxaBL)_S3}k!#pARvk`@|)v37r#*3>63ITF1BYJ>~DnH@4YhAWTB z?L*N50307vGp0`zTSQ$R+_NB2e_&rF-D7*tmmbJq&+Jc9_Y~|`dg>0Myktbw+IS+% zV5h{dIN~cB_$T$pGRFKNZ%&2=-r3@Rl zMZa8V_>78UXF2%*=n$BfY|6|`W`D(exbfbG%E*g1o}}dm63Uf)Y@yY!Au5xx^~OnK zk5_dS1H2oklh{v8u{*C3Y~yw}>P^WjDJ&vHnt45EC-W}f$St5iOF9&xal0eXBM*@K{xWADVoTm)kn%y`!mZ$WYrdv(A+KIA^NrwZ z4xHIgh_Es_34_PJRn!RpbjqVoPtnlnnB(%GBgzd3;BxQ=CVU{q8gAhH>kGR3V3ppM z1il3cVv`?7Cu~?F%5JEi-PokD2)?6^$riUk=8?!e^;Jy56l5r$eQK!RWrz@V_Lj4E}nbv zbAE{E>(CHcg&n@~ljrI!wZ3QMCxU;A30`tNyf_1Uu9%1`R`O(-^-t*K z)Vk!aCu+EfHmHD6HYF6{MQTuMK4`WLTJpk5Lt50$m zEGqU!R67wQ?$G*8GENSpZfqlJGVGt%&)=_+^071ID>X#$ ztt^`S;A6KRIOO$`D&pmB(Zts&9&I6Ol2orBRrj_n9G&FYcM?)M5;+FNi^Q9Q*aw=B6RQM9jmLo&YP%tiUDilx)8WtFA*}tTfy2%LpEf9|306%WSxac9Odr8hcSyK4Mpe0JwaNnL$g$_(1n+Dw{)SD0B4tPjjz z*1SdWh|AKmpPcAUGjm#&TpykBPXZyk*NnKdDIJo#iUkIap-SQ^h&76C(qoV`qYj3( zNlA6mOoX5{d;8#S69es#a8=W+(^|R`$#r4~KB{VpzZKdUAii)2a2tM5ryb5Q0^ET2-$E zmegAl!-ey=H^I=Z->`4e0s9B^_Dg(=s)SG?!^z)nVwrQ!Ym9>-j5FK)cBi;bc^1!O za}9cc(*_R+U8hDEqqw*_sXJ|$jvV!7PRu++=pC%v&;|)ljt*Kvx>{prP z*4QFOb)qStC$BNEwV76PeGl9z?Fhf^vXOTKm89%&^k~+t&-ipVaA5KJbYB_R`q2bhpz9udPviz{`@ZB01)RVcU~5CaCB zcv+T%$9%;}3tjU~M>-W*RCqAYh~MJ9z)II*6CflX9QK*HSVVIMtYjO3M$%za3K=OiT)t|CF_ zFr32UkUORyl$8_eh=Vjd9LqAiW`f@uCc`GQOZh+Yr60H2<+mSncL~R*d#zobIVIkVCu=V*68eBk`ybv86vC*>nOjWE|S|_lvpLU zSby0qd~S3|ZL(TzkT<_)A7^}33c74t3+yb|OW9ZE>T?<2* zOG|F62co=06v<0pR3>mA6T5Yy7$he0kX~lXXSwgwbFp{axpC0gjLCUU6M9CziY!_Goor*5A7=ufvgUXfGp1qI1Rp zL?p`uSP@vrqQ;!aIAKKv&i3>hixLG(%ByJMu|>%9@gw2mrp)ou9P)NnS+Wu)(fg*P zY(`DR%JJz>L!QjU%^Gw`tch8vE$5AqRyVh6>(W|Jf|3RLpe;N(hu^db0t>0 zz*?9{==MtRBE=@$r}CKKZxZwjMF>^Ln$P<0snUV-mCV8NZ>3~MBrtC&$*6_M0uV=| z6i365SQdtEC9w{}sgQ@U3Zna(EPaR4&?&PGIs&Z63c!RX9-g3*rPxI#7_f23rKVNU zP7MOzM^&}COQwRF$SA0qt(ABvUqp?}u8{{Cez56+Cd9U#Uy76B$&ULga6=ul)05Vk5zM zFnoNeuAYLLrn-U<59f#qPiKx;K*w##q!4BHoHJ4!5AObfw`RUx>Zd+Xwo*#1)~LC! z(5PG9esgX+{F>>y0a(o&Em&#c4@*4mn7XeptLxC6$o*1n{L&F7ERXEyd;q#cHb~BvVk!fW(I!H}Vb7H%wMmW); zwSCcqWhC7qT=en<+4Xmj>)`a<>Fel#frb~>pSuH3&*cZ`=iV@{^(h{fP-#JPb;>7D zyC7oB`O9Ov>Le^$(X!exYDX4351rAC-MSdK+5OC`IEWZh8;*3n^!7lP`+aI_^3t<) zMi3dCH@bBTQ%cZwOu;$FT3+5hcW|g+cBzIB`~eetm30PzBmGWLGcKC@-BS$+-n&lY zYPX$~`wd6#W=f#pKUhcM5#a0uspKk(geonkyfaXWR;HJ{=)UYUMyR^UrKOq^WRCW> z?f1=;6Lk*!!oSy>be|C)kZI(3EQ1+@vWG6vXiB>}pJWX-&`_$(U2nT#Q07Cjx&C!V zxukvrNzxO|rkAcQ`M_>UER5##pz*aC!#P?D(Sx??4sQypT#cU~tZsP9sO~nuX|7zi zSH@d2F}^JsB1RLeO%r(qn{5`twC|+zIYR zov_8xfr>~vS31pxj?+etGvPu5-#}Q3L%Y2o)90a>g>ms@KN%X zb=_{0we^HAk`BL9XLIZ5jx*_2y_0R1rEKGD^K1p%o6kLW6e$Il*tbJ6YsGSgLDdE3 z4gIl7kMi(YKf{p#ZAU>8VJ_+0UlLj$lLOt5$G*>W&p$Ia%^aO;$|f+B^fP6IPhyOL zlH%&{-0iC8x2yn!iEFiUsOv`FIeauyn^gPYIO|&NR(|3oP-jszH;-dn^={5#nh=e< zFQe&%&PV#fIi}Gp!>zK~+@Jk#`GbM0L}eA>s#etm)tj@|(CsxF7K3xsv~jj+63;DP zC^h@ig>FA;Qe(Hqf_sTfy=;nyu3X0EOl00T(X$=?bjb_-APL(VFFcn=MY}{|YlwtC znR1A~DLM`s_Mdu!8QKgAHNYv|$sYWT1|_;EfD#3nb9Uipdi5Tf_$_hd2ix0=+uJ8H z&kHWeUviaOI`228Gi^^;3dyHZMc&SF&BW!G_JamDrD9LTRe=XaACpS-F)K1Fjg%-occkU{fJ z8iO*S2lk`O7Z|sXWbV(D#mI^30|tgOvEvl>!44z=Asn8AU|zeg{FX1}O^I9;ou>rc z>{?>?xv625_}XN%`nq#yimU=mnYH+d;2f7)Rm}>TDtZm05Dp&%bC z>wkx}4$@@Qi#P3A&s+1ky3(>-GQS_qdkUGowZQN%7rGF@v!&RWsK@dTvE1KhBuiTC z17=1S_!sVY0bZA^skWp&QLk>6oQy2!5PWHopi58rJR5~A~Ky~+rSVO_C|+|Dw*81qw8m_ zqkgZCjLEq2qnTH?9#v^^@o>hRc9U6DKc>-@5q<8l8Nl*iB(7e&I>PUi?omGLdE$Kj zUC1`;A#pHN)6iQF=c>YQO6VGV{_aVRZBFXk8P75YJ65>Aa90pklA9&@+g;TXw@naw z!WOs@48$}LauOk|kAT%s9afUFld9ZY*5d3md_2K~a8101(j1{YMH9l^X#$CZ!I=W8 zjgfhVQ8$L1u22@w&{*1(wn9V>XfVkPWU~f>+P1xQu8S<5sB<5UgYOfwrM9h-SDMZh z5csl=GFe;iOIdnoY!bh|jMRT-dIeiPsuF%tj74O<3)8eQu(F_{d^Eb4aoNz=shxR) zL1^ByOFun~9@&(2l}VG(^lU`zkd`cYe*8Plwxqo8hW0xLA06YLn&N-bMvFMuyBb;9 zn>kCG**cmz|JVBXXcajJ95qzF*$1@E#gQUBiu%lixs(n0@bOfX4Me2SB-sn{WMr`d ztvD%O>ynHOBV!5Bdf^XHcF8cYANS-qsNuw_nt?%@4JNa*d0EfKTa@P@(I?yQH(MSz zT+cnPe{*wx0y9QzLZx}~1kguGJJ8BI=+dL0lNZxzr6EhwZu!?e?MvL;Z&V1{4x&ls zh*Hx`5|qs)^aUr*Nqbot>7VFrl<_`2bsL{8t zR`v*bkd?hoPE+XoY&x+Ej(SwR*wk;k5ewLA{q1c+v4%pa+NI4_0kM3b@8Z#l&ld5H zGHgx)8Ts%>dyqu6=`6JKXVYk4EtuLa%(k`(eMHyqD<7jocJ!6@E6|IhgicZgX!s%J^Ai6m2$;}ZkUDUC^yG)9|FEH^=(dZ@xh6ryn z#%ap)70^poDQsvawVU*O#}TtAyNRpw*q~<#drDD65HwW47y!Tsm7uyIA~+J*-PePM zQz^R#ST?5;LsfTYu!3Jyzc{fTX)@1&WLtm}(p6JMCEc=rV{(GUUkRG>Ao3TFScX=m z+gjgIF=O$)OHI_^6FVK?`Vom<4)3O?_E|;j1G^u<-P9sEL)IRKP$!woM~T%kQmd}` zlR-E(>)q!}0DHp>?&f#i(d_OM*^1@(KzD2R??IM~N6}X1~jws<)in zuvM>3c?6aa7y@0D``ehH){*F*g08Fm(VeZPOEg!2i-MW zg=Wrs26;_#ekr}927d@{U(VEqYE6@GFHt6w->RuZ;@m^$AP>cM*1h~%ORmc9sO6Kx zc~b0|!yA(S7xn=&l5g1m-*Z;DXGZ_d@BUotAN%uv65{t?$KNGZK0&(*#A1>e*pcY zWU}i2jdmKx;c$}5@o%oO#%aK@&r#H{!3(BZB}he|kN!v+nr>Q`x0_ydaT__piie{C z2I~BwqUJD)t2p`5$$6ypOO+ugOM;Q@qXyrO`R@l_GZ#?x==!u6YM{GW-&e|mXBt`2rq zCgN7M|2rdG-NxhF@xQ&uODp) zA9okQ5H;*-A&igNRicvvqCPCde!riwt3MD)fyS`3a$4~aB^|aLYawtH7$d#yBhV8B zQ$SRdE#gCbq7h_bmnD9j5x62Gag-^LdR%u`KY>A& zZ_BzHtdFi;ic_a>ixCPnu^4oGD7)5JT71U?kfbz-I3uhwKbXi&#jOOgR$ek3&IdtV z*4A7yfu!Szd=BO3s>?9>8?rpPhw*yV~pWS5+a30u>in9O8XrHtn6P zY;;C|s&_KyWzLKB()Wn;Db&~4nypO|p&2U(Z#9|Y?ct?D^WkP>++(=FKTIh(`EDC6 z0E{a|z|jg`@60thH|u&9-!E$ zosoq|HDy07&ME?_hssjWB+pAy>S3IzgmfC%Q7`)P0+9`{(9}<>xSgU5MH`(~?EpVn z&3+LTtbv(k(972ag4ij4>oXM`kV;KD%Xeuzt9NlbsSkJqeuUA#U8~DJGpBE+Z_a2d ze%CH`FI#R6elaCgH`U_dWtIP>d|FwUYOjB_XCgj``Q%b)mQKc z9E;?J%{snyLjwT!$qC4kO8Lw4H#>v~7lENDECcKAtti|2W_bU>?8$_j0?dUnW?}Ek z@fT{jmFZKfB@V*UDxAJOziTN+B4mw+Y)8rHTo-Rdutu5GYE5}yv1v%EWrZ>&@k|0z zWuHXBu#!;x<$>+17v+s6YNa}LkqobVNMZwMllyF+e~aq-b+xd>B1EjvendlU7zrNU zhBZg#k2p2~^$VOLjg{20DA@sK7TD`q&gXWin^b}@ARDPN{;=Iti|0i+?`quniASyG zbIeDs!MXrqg8<|NYHR>+7v4BCHb-E#cJPr)&fO^AfcA#uct7u3G4AMnj8;PuwNlxd zJGPZJQI6C+n0kAJ513{$KRAFc2m|hnId#;!Vk8G<_zGmeV#e*hktY1?A2H;NyTLX* zAyY8#oPp|d=xSqjXWju+ZOgyu4tXh^Pj>M%Ki!kF2M{4p=WMsBhG>gEjf18bTb zb?w2;%D>aZT4g*f=44bd{|uqiyIx&9s%5t5n{B(Mq+*Fc70L`&dcfnaLLwI3-~Q?4 zg)j=o=Nx!HT#LeO#djx`jAQYI@v_7)wyw(_rq5cKR z{*wo|!;v}hB7cR?<|re+H;!&8=>Gaw!}3IWs&87)<>0~Lo#bnTi>up5aBR(;29v~* zuBO}>Cd(DX6f~`_D;}a*nmkmsg)zj5(nOl^F2Vrb@wBkTp|}n;|IWHYFk76%mm{`A zuz0ZLFVvRRT`ua^3zt60)+V6S?_!2>5|x#Ns`tmynd3KH6}zsx6;Pd(oZzuY+jls) z#GMDhPeitQ`AgCov8iJl5m19ist5kIFS7^hL43R$){5gwiBk(@)z|tJwBT@3yuUrHYLu%=8PyW**Mr|3oN&|snJ>fzxGlBa(=_dZxCYrFQ=LBipSrd|5gNG zeYY9fnK;>7n$SDDIyl%nxzM|@(7Rijn47xL|IZ%$-|sQ~?Rz3lhVG_LGKQY^t}Z0X zE`~1u-i;M@q=5txKGhZ~r76e!G~hu)zyvgx3(j`wBSDg zKNRP5ETkZsCKwu+8+N`+Ap3N80k;nS3aSVa1{Vjq>LvO1WT7GnkfKgdj%;@_L-J-# zDMu-LK(<|?<}KHN6>eWz*RV{U`_-$-ets)dE}rvF>ET;n)KEsKAYq!u;PMf-4313Y zKa3w4v~AquN$$Xezqx#xF?XU{9yD6k8U0vZ*nYs5@LNvPhYUfYKip6>@dDVeBZ9lCQGJlW19 z|22NCJ%AnKm}AyKumaZ`32kQaTqNX4YI0+Rt5$^Gom!PqTdsaJ!~wnIT%D)NQ^F$XD+&-I<|LMvPNr<~2V%VRjdGCIGw z`g)j$k~GK03Jt#P;iSa%8ZsHB9EPR!FOTgTE`*w|pP7gd;1c!>BrpshMDRZ^)5wRv z3UzS}aWo00P$(Ma$p4xb49`Hvhu<;t{|}7$-%(}z+o+0qIM~=bnF@KT*t;5A{PXz! zZ{19C3@=o_07A&lGkQ#*rUw8#Y0c{TbExM) z(4P0q$_Jo9pxzGx0SO5Al6pvb=b_-feJu)OPq**F)SNXMs5S?QJkmn``N*a^H4U(- z;)!6tk%pB@mk-MwR24C_Bkxpn{;(Vox{@`AA(N95 ze#T+L@-~Imp80*37LfJFw(z`uhW&u|Ra*1|{wpvR+Bot}-+vqYZv(^mw}JW3iErp; zYVwcS|L@pjC)(Q2E1-;gp-VxB!-ZvXWyQ7L=ADOQ6;6^)Y!X58k))9htE0Ep)9H3> zqB-~#k&>N7(a!w_zY)fqp@l^vFe8@rmY4rJarc^OJ9)~z?g2H0&V!p|xKiZj zD=`L-iFZ;N@}zt;%X5xwYM>hW0#HBFvDw(Rz^2dsD6&8drt zalF8MFO=}hB&KRrdcUcTBw>&=415WPgiEZLweb(B?&qCX2AXWT)U%7C?Kzq$*~uTO z83IAWL~_Jfg_&o<_9vrEmZsy{Jb-UfVjz@WXXBXM{hsy8zJPQFXjaW-G=?|KB9ij0 z_~D(@*#xhqAUB)>4Cxx_B+ahhmhSAaicH=&j{T7@go$`)McK~y`U zFp16tO|ojdTl2~P$-|#8Umh3yUJ}LrgNOg$6ZrqJEV^4dm@1i?Ihi_J{A*p5xBK_= ze=LjK5B4j3U|?XvV0vy~aBg6BVqnwnoq3Cm1&jMIVqj*lQw(BYHM{Tg1&1mvlUXWa zV7I$}CIeNMM*2&DMevmg8T}<^*9E!Jjoi|-(NHm0|Sh=edUbsJbnF?)GQw(jfUYW z(wG{iCHUKk zE%&z*TiMjm$=E{8@|!&K56%F|e>X_j+nIVA+uIsRetRSQb4M9UowCOk#Td?&#Hl^E zqmY$YFQcVZD9bEz>;Y<|EFQEC-|%U4mDspxYbJjH^S<<2ksLqy1rGNE;R_Hap5q5d z1z|kk@*>39BlLjrKYaLU;}X?E)v|Y|bh_ zHG*XFosz*su;o~}7A18hvskl)d^_1VXCa5RitOhFe>4YZqRF%zhFZ54+nr>GT6t2X zoYSp^)7YebvK$jc<5O%fF;I4jPCG6!Ly|?=$#@DeEqVIB*Ba*9&Tq}4S(1^&A1Qb3 zpszyApv~*^x1oFGMb(~8_8j>LDi%ppgEpMXVv@0SmX6-2_AN*i8+Or4qv)$!B071g zn`zB-izW}RFah#uY$0P6q1G(CqG2cHy*ft3)<{$$X!ICSV)Ygp>WK?$py|ffMxy)@ z234#Bvm%zfC?7y?NY;qUe0!$9m43Okft5s>YHzc}nRo-it4C*Ub{EO(}GL34nyK7T<$J$lm{wKjasu>9(i~VU5HsJwY>;4ovdERTI(G@I((GrPNc}x zt4_}CH88EVj%E5=5CgZHEB8$qr?dF#PkJgJgEp6&=vf=XObD?kL(e3c|2JFf0=mJRa zKXz75VV)A>6t{+bfn6JYktF;kWUn58-c9T-hX$_FT%ezs4p0`RJ%NK<8+X2)aNDjG zraNku@#rh^QAL5?wtf}-9sv-AZU;%|K2yHO4!h&-5jvFm>Xmg_M1&RU?t!XrAl!@y zy6=b}Jmpdpv=SVJhxjv~Fj~lWC}_oa$bhF0jpk?_Y9OR%MOw-W95?CvxPbM5BR<;ZV=DswCS=1pKsNZ4qp{F4%V_nq{O71uw zvpm|ah=k$;TWRJmukeK(_}YBR$8~T9-Mz9>c2#98t?gTKObuIwIDTK;b~o&&R)g19rqL5p{!W@X%y*wkMbF?(D~wIas;{{U1tg+xEzzvVXV|4}{Xzc(trzh8I%7k*d%->53d+8#;p zyP8gZ9dvjKN)&oksuV5y1}Li-G@)e%8)5!B$im>Wr2)CinOn=6ZrOwSX)0TjV$WM) zw7EeLECR6!Gq?G4_gz-Hv)SXywLL#T(k%}ht|qShK7=7F94zO<_&LRIiZc!4*^2oT zzZgTh)E#pOd(IMrGJM~c`t>Y_QJm!eW7b`sy zP~o#?AmzF&yF^uSFPHj*TM0MpKFvqBIwW?Xd8-*Gj_(rctCtZuoUq0?d+*5R7iwNo zFYTrrK}aS{tr@S8OTXA%aZso9*CeK}W8@F697Y@YigT56di6zE-KSm)L^ldQKmBUacvIpZ-4~>>192R+1Be?j|>cGX8?E>stg%8#u_XMKS+=0 zrEhYQ_QoXCdVxF-tSX?eO!T5+P+{5YCEKMW%Cv)sHT2#Y7y-kGxY?&$cSvT)1ZWn- zB2|p~ZN(brL|5a`NGLwg^&_!=9;4JFbo9%4vAMr>XN7;T(61+YWD#B|xu|)wMV&$Z zVfK}|@SbM~m{#mTgHZAQAGH;ICv#$zzG2qV-@+{Zza71z-&q7vGc!|Tmw%y#|7rLi zm=F^$FW=9A5#}$tISew$|HJDMfUG{vgE4CoXbcG{h6Jw@RV~k?aYC#2d5-59@Lgfp zPEpc<>~WUd^X>kr`|@q%9Qy}#)>_#H2VogR^HqrQa;D6x2C_~wm`ZTOVLp3`5OY2+ z|53wLGq`hmfu6|FVh8qA%rVoiRKSW0L&WYfxABjWTnRDM#bO^`;PW6X~fh^Mz zd|#1<(k6Xjc-~Lq`-SiX6nGjVm2^uSN;`2WvO*tzi4UW+Syn;vllK$k637^HpDLc* zNL1CevMU9;M8@-Py>W%T-%M&$+L;`d*+J6oF}Dcqfd<*Swyw9eoy(=IKGzOPpr{R= z<`!KNFrmi2xC&(ngw+Nyvd()?HYfs0JYA_oT@aB$D>QW>EV(hH-7s$wvs(9=>V*f+^*y3hhesE?HO7!J9KXscY&*7-x*gZ1bkmL`18tw|V{GlH?IY zzOB%_PIUVS8W$)h9Jz;~!^d`nCd_s^+S+N@XR47Uc4S#JYt91FBDTTe4#t`J2{06ea!1wRZq4uIN-g5K~zYjNzGi zL&7tW%H;GG3UfaB3{col|EW-*Gao=}wrOB2vU()fP2 z_;>CAPmCVnHRZ#C3G~$&Vp@k=aMBy>=}cjSdO54*4|od2^XPY=nmw*bU!r8Wd7A`Q z7PFxMKAo4vBfHe?MlIAnB*Jc+eTw`nM8&oakplMTt*bIgaasV!^I zK+XxB!=?HMU9}By_9VBmn}&b5=zCB{jBs|A5$?>Zgmj}q3qL{=?{uhFbkZhHbZ6{y z__uu~#$_}8?&@rhXw1E49VY#Z`?Bx2C2t##H2hLSQ(hBTu*FzKyf?GT^DB0oCZ(Ml z5=+>PWY!xS3U{Wk9?SMLJJm83;eJj}dk^1(E=*_Y#TjlSianNq@g8tAHpd9{k)$^i z2P?I#5ge(WdPDPyZRg%iDo%738>%z*c&=LGs12|H;!;3W4cZi16Hx)thtdkRV&(1_LX!2DW@beelgSL z3|E}Wkey|85bIf~Z=~HZc3*b-qLu<{@1C7XNxQ_BGoujonx}9?mVLiI>_QmJ&MGkQ zFi&SJNzpvsf!(&%U!*GR9I+leSjT;0I;9s?>pDf2j&6@}7aBXWcgF=+7~9se{~Q~8 zy?@EkU3&25AwE!UUfmgszc0?^7wvxFAwMF2qm1i*+Z~&`cfxhG*BuL=_6~%9_8i`( zzfX(X(_icQ9@@6EZ;RVw+_Y0DJA!{BFoN&-5RVXE;^!r%Z?kDPP3O3 zTJvSkW@+Ku9N0cUgrYZKOejSkZ<{t+3)FhPp4NZQ@-7jJ zGP?oFb6{o~hT~%J>X+_|T~(+@!4XE2hb3XG^NbA(Pdqy=TNYiKUyJR8`w%lOCJB3A z#emyzkw}=+1sSdRb{?^2sj4;k8dl3$-cMuFhh^1oV%FSE32iBb&za`9@Y>01k;_!^d;NJIS%)ko^wSIsbacol&ce8Gj{0@Gj* zf_LC^;j9j6R7AE!B#X;0?F?RwGOC8jrdjqbvNmH2V%ZoWo_rl%l|DUK9nusUlvCED(aN{T5Vh78XM4LWB5ArElE^oMLx=7KL|)DH~i*^k1|wn2N9e>$XlNF zAw!sOE*(U16ChSW0Yf15IXS}xkU_~TB}0Ej!XyL!2?^9L5>4&SAFUkiV6h?=v;p)K z97w+v99;Gr>(3Xs#J(t-JKRAxfZw?B?0TN1Mz#F~!0M_~ z+*M)3ZFS`rT;W2aaYdA0N7Auz5a4Ial_EXje7O%O2gdEay6=p98EE6%+9ZmorJ_Sb zOVQsovC7^ISqLWtxlb}K3SJ>f4i~ZT8-+e!KC7>eBT8}(Ryiw(-s>ioBhI@39zP1& zgN6xd#+stkjx*{mSPo{Otbbx~h*5IYMRE`#7vYlho~ki*HVhi+lGG%enwT5DT>TZ& zHkYLXWgXp7aw+p1PxF#ks@9_^Fw@IXR=nmie^<&9qc^W&!%?+m2;l~H>0Ir1Ew#}v zF66dH4UHBZZy$TE=D?5BXDB#_;*4c=s^*fxfZu>TVUaYXA2W92V&)5 z>SbW+j6}nXWO{u`tzhz)y|(}YY> zdv%&H-2RG>-k7St@~j-m8%uxMh7hQVCbkGYE)5IGi~(Q+2h3(eY(aW<5ha|bT(Rg3 zmofRKFZ(=Hs9sa8mV3k7W#O>@5?-|?6L;Szo*%{ht{tw}CS1v)YNGiCI#bJ`t}kP#?s}d2f!u_97Fv z!0*{lU(kPHfZ}70ZvTkUI-J`+w{KjeadmZTDxj9_xa?H;{ya>oey$6Q11=p2WrZ$>bogDySnx* zR_Ai$${so9!UN1!FZl}!{1fB7CAA-z{oyg0o!#*<8uk5db@VP9*}JCRJ7*~0%#K@Mk!thRa2<#&s*8`o;hznf1T_cSB&T}p}L&#`6mLa&4qi{Y+ znFE`f6VP}K`v=de)O-Q*Oa-N_p6ikN1GRUYJ$+Nm?+=+Uyc1K-md~`*d~rL+r|9!H zqF4I+zB_xz9W-axj3kG5zIJ-Yr2M13`1{m6KCHlYLn~>o=adAWbqOasb-Qs@&&KZ& zkcdpQ&&trBFogD9NJ`m$*Lg^fVDGfs3K|cUf*@;0rQLm{!9rG}f%Zg)jc?pbmx8P; z2>PH9DJhSzU3Mp6Alegfrm0Ft%I_blx_fymJNj`9Jq=@B9l}PQ<$}5X@LWp9&hcVI8PDb&(7sYqPV9^NXi0><{hho3h!sm$Y)f zs@K+b?XHV-ry47MokmwqRxt#p<7QuCb7i)-d#!MDd$Y5(vDuK+hg45Pdv|#0;L3Kz z)X=pwROgQg@KrXHr?c5yxFT<0XK=-!imaFt6?r4n>)38hqp1^TOU$xmm+&WS8Hh8? z$|pcot4l~E(?;$f!+7wj=I`a_3oz(3SxYY2)t2hRs=Ho3!j(f-N*bjIwjdSR4>taC zOjX~~U6O_MZGmkD@A}Z|*|*;5<}C`{3Lp%=?`u_B_C@GQ!%F_y>(J^Gs1+eLZs5$o z5FXE1=1*)o-_}B)0lpQm*BwBIuRMisb6-FHs^Z=&EAvp^#(411!{yzJ2#l<@LVOBx`X{l)x8X` zusVrlp(tc%ECDTauF55BtUyS{3$Ye7-CgINx{i4BI$$*`s?6!KeB&@HKd~85Q-_4Y zg1yAIREl(05rqy1>LbM=AXI}@iB0M@TXBeehMC%6pV69NPoU!z<;=_}SG#a|bs-c_ z=LGp~R9NA>g9zct`g0}|#UF+!DLqIR_^^T7m6vF8`G^rtcT$Sx**QToVf5D_aCx%) zs_G0`;hcORBR?lOL>nYxsq^Z!dh?6Qo*=AEB46;Ls$P9GD+H-qP-Qp3*gSrX)vlj> ztDhlzU>o7Cp|s8I>r(SxpRLvGR4Ydb=qrkT3)1}`ja-&6@XqhjRttZak1OSgB?HWr z>=069rz>s^IW8VlIR{WoT42ML=v28yBZZg;HEuDNf4Qh&JXj!+>IPgofV=nj$mz8MNzCRPC!JAmlD~NP6-Sz( zSjLEtSGs)Uwz9SwuW;yw*fQ@EdV7czLc*>d^wATOu7na|KjU7Jp8?X!2B?<>Ku_2ibEcqh zNerp1LrpRR;SIiIXFn=^e1881Y)Hsa|D7}ikG$S9U`@dk!p10Rm_<{L-{6#->eo=K zjUWRI0z?OV|JEC8k* zD(4p+Dan1}I{B_h7X78*p@ z+M?2^SwAofW8RK3r7y5vZWwC6Z`5ignSrCGCg^IR?KncvDr_p=O-lt-ZbIEED_cFN zmv6hZMDYZxcp-}!T_)UmZ)^K&AYiUNGUB*GbI7U&r!9dXCeWs&SceY5${VBSN zLYIjKYzQR~C7-^5yONp%_D|?%;A`m;Sk_%+8MvvkOaz_pq-Wetp< zHE_J;yMm1LIGMT}A2|>0CCb1?3BkpCaiBEpoT+tqk#4$FFG1pvvA-igsrRFqNZjh* z&#qz_jb!j6OG(v25`HL@b+)%-<(qjaR{9YhfzIcgainCN1q;%`mtaDiqm#)>8B?G$ zkFQ%6ph*3ETpXOE;jA2B8$qNo1wqe!m@7#t8?m6Rtl`aM?%2mj$%PF)9=xmJz=qLY z4LT?-J5Do9gN)(%%C?kYy<-lCI@sjX70j`%Ah;}-Woca(aV3c?aGR9C@HqL>VTdr& zU<%EvJKX+4?UU3ex2$~i@v5=8L`wB&NOj%{j95i?oF*7h|F%BQ39}!&f$zB~;7%_Fx|HW!jv<$J;$7^-v83_Z%7MJYeLI zS$k-lZ@>}?6nQ(pi8-~a&b|sATG*;HX~#|(zp?c&Z0|TT@j%q8+od=4f%Yf;Het8L zjQ#0z%l@nl-A#PZ@yw066XcHgZBgh#v$iwg0rh3j$3Ol|zO0bM>ayKv6W#QlImS-v ze>Q$Y@@>n$aKj4ysX6>~OON(m8SOvNGw}@Xp+4;2KV$Mt$@)zH-U4IaKST5E&-58) zE+o+JRVHO2*^61i zm>E}yrc#QTENf_{4g}k1vM0u=Gk9>5ib11$r$Nxi6ND@3B$Df0avCL4Ds~&AK^@kK zR40^TRHz3ao5Kj>IkCO6;l(}|`nH+OsZ&b7vO51da|dZzUUorKVsqEyn@v+Uly-ZigY zZY?c>9SZ$|k9UGdI%tA$$4H76MK_54FSDt5_=dLM}rNhr`pf8@#z zDjp#tCM)53=Q3Z)W182TXwBgtEM>q9-(%E_!DVnDKGoZ((&`k?gwYITEt>_LM7Ud`+{#U$T&)Vm;E)VO9Cs{>VwhL3lR53-1C`i5Lv zrF7JJ8DhQ7CizHf8L;6@<{@UbfG20ZH2CTp^!f3nxY~jL+ed9IZNO$aRBWHRH$IfsxIDd)@ETVxmLAI8?@x(lU*w=-;;Q zG-w}pUh?!jb3GKVQd|epH@H?k(uGY11=#>-;-IlYkBkAoz2AHA!cUFkrAA)(1Yg#f zJTUzT{LWf>;rCF5`bYJa;`f>iz&`l__1sldVufM{PyjOr*qDLZVxu8U91@S?iQ-Q@ zVE(Xki{%plH9*jrv{C?(1x8`gMF>#!6~oNL{t&sr37sHfNZs{>nTZoZNwP6xBG(|asF4spzpJ7WAy(}cjK^y(SHW~njG#8eK zK^M&Qo0u}pfKvx7rY^O6697FC6+WI!xM+Y{(pf$6%8qF2l017$I)htG%Nr=C@T*&t z$PZ7Cxcb*>ss#}1;AcCXTc}>4Ka!yaxP5P&MBEG_I)7+xJW{-VMSG~WC2TD{fnt># zN35_X%JMw}Lu$bDPn$->QHIGzTd=7^WZ=obD%%xJ0l!x=!LH?Ai&>1gS5zx~(#2ZD zvz5fWl-7#E!fo-By{{+3^g<3G&0t40lx0WpuSs?BzA*<=l;v}0j1aIhGYe|$gCg_9 zVxS1p5Rd`*XU#!h%(9J zjA8Fd`-pjNNW4TV16fiXeL@_hR8SY44Hq5JJ7zm>fYW~ASkB{yTpaN8cM6t~TXaOQ zA5Uc;!0DU#r!4+tAwBRRH>n_AqF`M_`$u^<3SKs6_cgPps)%0Nx7l^^EG>d}6Gm=o z8C&$h7BT(9#E0xaPDANw;FgP@Ve1RM#W6TVjj*H?qR2G8C>p_*kdrEylPZ1J6p@U~ z*L~NLo0F4jNT}K^ONu&58RDO=pB#opXhp_uf%qD*K587rm7`Mo95iK`k`!SfRMj`+ zfs-TzpWgZq_>wX<-TtJn84NXrnrN1s;$g{@vHeN=6gmoNN<`~Qb4=RkBKf4#nqp{19jsV*K^;#2=bPQ3!Zh8}w{vPT+C-3Dncc496l^8&+5Sy9X;6SO;{mU~ z-2?$V!k{_q<#$DM+STWR=De}b4#9cm?*mGpl0Ofw4E6$0T7`v$Bwqu5r+JMXlEiGAOd+bedBcA^OFzErq#kRr60+lV##lhw-Iy&lMin7^gw6F|e zGS9HWme^^)I_2VzeAem>fI(4KUSH1V1Ij5Fe zzNF9yh0bhAMPzT_U}+wPvK7#5cNm0!lw~m?g3RPsCL^fwgS9j0mk{ zbDHRFlX2~>^f#uV7vzJGzQqtPqAiP34K*MD!KqJGLO0rPgzn(`UEMN1u{!7ly{CU zqPA7?ME>CK&W+T?R&>eJTNE3*^ULN8CbyW6~*u>lvbrD$LVwRph^BziHgj+2i) zOHf2wF=8mM6P~K{1E4b@>xrs8?J)sW4>rUDSJ!JLG5IPe>XvzT2%9jRz0a-_lP|KR z7xh`Q6^$R9eg9<7tP|I6gnL(x2SUGJ*a6=UFm`Y2h5|3t{08rtZ5x{Y!1o4g8=k)( zd{5Q~!Y^cG7dIMXW%6=XE)~vui4n@I*kvG-61IAH?c1`Fh~tg)5{D8`4AcERjJ@%foT=ZHe0%@Bo8 zkhueDvaz0J@3lROX;EX|J6Mhn%A56^3y4~ROU!F#3}AnXenxp0GIVnQlwElmYrn0`S3?rq6$u z=bc<_zo!oFD~5X1ZCN5*juJGpSfx{--XJU~G+QaOE+xigW;zIH9tZrs>n6dj0DL#t zt{`l$FD+s|q(B?B-4$83&uvSD^z&4NeJ<+$WN7obG9(9sd=Co*oK$3GzU-7F8+o5B zYX*cw3cJ{*PLflBU@cE3BR#%zk~JX})PlX<=0(IsexZR>w0$8*;-Wqsm*1r|3~8sc z_Q5)4p-A)c!$`#tMR60XMN9?U=w?!PNIq;Ud5KZUfw6-<{HLqzkwtOKv7V4AC;bnK z&nhz>?{xf>$m#L<|iZqL0W#6gWm8Sb?qn z3Y}u$hP9@I%}P5mi5G={;^`D`(` z9Z~o7n2gtH4v|WnkhD$L;?_J+0n~*rl^x;;G%?&A2|HbcDixt6S_EYQ1#+YN(S7Wz*}bFQ?ZwR)l-O9 zZtc^I65N}P6&GF@o+X@VTj9Jf~(iBxqvj@NI)Y^3Nv~du11=Z$-{`@dr0kr~hM*kQ~b^Hz0r@)&to`Mh4OD002c{ z5RxYyLPJC-DrHDlcN;q?X0|d}Gqpv*0T3oMsDTKJBE!g^;aT`}`|=34izQA8r-XwP zD}BwC^87oBVp%mf^RC!Utdn*8ci9S8-MBWS-ZA<_%vEDWQ>DshQSokSitd=RklM4F zl-_CvWNC=6ofTdgcVXtJ(^4U2N$}g&+bmm5YFWGXgO%)%;zxfr?7}oXzKbSA13&u$ z_=(0Jt+3tzhd;($TK28c!4v+RBq03|zO!j{VYkiLhF{#|qs^?s{)t8jGTr}Rp)*AI zt!{q@&Gc_s=mLKmRzX)6du3xMdmEd7X>NpV3~e30MJE4f`?r!QTXjPj+Z5&N(r!N9 z1o~)ONL#2a#Mah}o_19z0EMaxP*jWlGQp>Jc*?GQP2fC{p3CiZo!r&uVdylPS&WOT zkdNz=c-!1XEO&9)*)0_TL40KL;$_;s+xa8=&iCc@v@{o(Bl3;$V#MYd_PK}RaZl`7 z^X6a+ClNh;lDTc{5G^s)$OE%Bcp6--cGv;iJ#E2Q1kEE8(pNH8ctC_`bXj0b|5c(yE?bg7+k07+fy1$1xn44MpEehqUgYvG&R8o+Q! zhb=mf$2yifI&Ffp!4g6&nB7RT7vHLZQpCVgtgSi1R$p#Zu26@|-sD8oWMxvmxF|8! z$cVps)7 zAT`nsuDfC%ZAsImIb zyZ7oDde%s~w#OaiLblWNXbQ9r@K~Jux2*5ap_W;iA|+bB(Y8tk;u; zu$QKLDkZ#cemDrP~imfh?HUM_&c#pP+zGLU}#t z2=Z`?NHoSVv(nXbC?(G;6r=F)E?oW zcV4X{{5thd#Oy!v_w;~e-Rd|4l3Ju${ig)`oPUTG+J&v@iM#h$hm~H;gOBui;Ay+n zb_3b~$8+g$r){pKx6aPh|2%B;JacIa_Cv(~UdS;pM}=A+fnY>{Z8BZ_V8-boCi)7{ zdXaA&m4}Qp|E=;vPqZSiuoh^`MnS`j)FntBm$(bz&3xC$o+ltdW9E~AV@lXQtvf+61r(9XKj-BH6f1wMVJRV)dUfV_0xIh ztis02kJe{xwXAX5N!~}4LD1xsc2Tlz&yUxa{)4G9>X>jU*>LKq)zZd1ZOb7^Q~1#D zEm}Ip>ROCftjsHf!D0Y3uJD4YkOAF*_%0K5kwJzlI&Xb;G5LI)mBn3E{L%4urI1#& zhccsFYRpeLb*^_*Q^7W)465=7J}+=?e&LC!&}G((&whI@R*ve2D#ICpaKJLe(t*uO ztZLHtJk}&)MeQp>cs9-2ZMT^6H9AcK(LPbtdWXB8yOahVV-FT+(!f^z#q!UM7 z&XXhG{_{DPcz5cl!nl6Eb!SkhJvR*W278c18r$qZ$All*?Zk)FP2H!nDBOI4cT|8^ZQkvK~s-RvCWmG^)-INwC(#X+@zDda^Y zdOfd363!p2&aj@yIA+Bear3QiE5IFHueoW8ZSB-`Z_PaoNHGqtmXdy*!RU9sQx%%o zVC{>il9aY#JLB%JzQIkTAtv3}HB0VbYR$zW{>&+&N_jmJ@~p+E+3j9+c(EIzcePXU>H<~y=!!qQf|#@qy;NsF57S$U>$_UWU;6>e~A*TArWK95WyOd zl-bP)JR-p}3KhI|uk+VzN&PVTFvQ1faLxJKb~{vk&gu(9f_LBBkmgWDw~GnCu4{2wx(ug^_QNX3{3oVwwP2t~&Y>>dMOZr`AmVJ9e~ z+kWVID_~<|W~=D6lMVWS_t3%T}G7l!BZzW*Juks z&VqKS#$2Q!Rv{lhF>WEuQpSZpGmX<5CgAlb=*3E4;Q>NU@rMXwDm1Z@nPV3~E_ZJJ)})@ue+Yqz(T$)c=y-N$vcffvv28ginbk;l!EgrtWN?v|U!GqW%K@DyM6* z_e6*=t##&RJG?WT*Eq-5Jv;sYID7veW$zTENw{TyciFaW+f`k*ZQHhO+jf_&F57y` zwymz}ug*CWGyj>1IT2r8WaLd=yz%a5KRYwmT0dJT&ziJbY-@aW-fkjPe(T~bb)oBm zb>hQ|)@n#JeH_=k#|>($3Af)9MfN<*7UL4-J0wguzg%QAxEHTwI$?0g_Yh2z7X2_0 zC(1`ED)7fR)pA@er59ssuA?}igmJi-UJ317+RAf02rpU*q}u*U^k5r?D$5hES+9## z#MBv=w+DvXK5sC}X1n~l79AJ``KtwA0$FkvDfXe|s#E)JU|6smYvBkW0O^or>b}X& z^D2TYbg@jXDDJ&*0i877Mo=z@!Jza2P#NRH;JZQT=ec?a*?N6t$1G#^Fcx|ONG|!f z;Da(c@8&oPx!L+h$Z-uYxOz*@SOytpkwD|!gVd!`-30{Q*KRc9LS=YG5{*4G0+5eA zN?l$_UQy~aJ6`%2oq50sOmELCb`a&BC*SO?rdqx~WmuuDIEm zJ_!CHu7dTc-7NT?rOm#>rv9tbfdB#ip{f4QcD%m&GcX>w7RS3u%(BCWeWUZ3pSif5N#VzYS2nDgGIq*l8db_CCo^x&E zGJDAZRfpUG|F|u3P@0*Vuf=wf=@{&*?cM**E_)Ac|n2gFwMCj{GZP=t!3F0dV zS90qo99my#@mF-zj^e|M${!9i|AL;s66Jp)6F!@gKSMuL3;GoA+^N3=hXpKmd4+N) zr?JpB$Jyu+$$lvtIy>>WDSIRz7N<29WV0z-5bNj;^ zFmtm0#tR-N+N)48zuKG_xCa*wk{d15Yr%?W`UAFkePI}unR>%#tJji9zuiL{SazQ<6HPEAb8e1;aaz~v3Wte)z354UDMW+4di%v=70cvCTo3R{r+jY zal#3X4X90y#e1Sk8iV1PUR$PT>b#b!uC`XCCr41qb8Y|rDfI}gr9C;Mx+gl_V2}u> zMRn4$$RL4w1E$)_x;jlMorJ%%xiM+|43>Gad-*8Zsz-Hlg`u+QnO%jhnyz+;hrClg zO?}l1L-C|uqP(oZ34&m5FSR_3T4V2KTVaiWuTb538RyxGqVyZa!pXT)Rk&0x8D6hdu9um6TK#P=whE5t1Sscsv zdbd!`X4*z78D%wap~Nx+8)sVzXr+SW{tPL7zz!DFd$}tFNOl<QH2Z<(+0U z@fBV#Ku0Sh;YFIE(SfW;HeC-H(iM~&<{(<))-gOzL*4whymP`Z$ge1{nF)(J_z>V; z3&PB_8X(bT-;O$#04oxVcHi1D0g3 z62JrKwzCHpb_7so*F65D;u0*A^Qf#$38|RvvLK$>Uc6j^t89^O5NUDKe0$By zV)qo9rJi}q*e6t()k@Z=LCKvZ)cYJ)+KaBUCd-7D7pX36su)lg{tJMqTL~UbO-(J~ zet+QYF*wZ`^i#B?iTv_Hf>2&7f<==hO34{=xuTDi=2sEpx}v-+ebR^&{`!V5-yOYv z{3W(r88PNHvu4D`JQN%$8r8RII&K(gZ5UBsjJ==0LJXm%2JzgIoH%B?y)so!-EKkt zUY*ERR1D?WC5veixm&9wxhOC$g#W0hMey)rnlN|Nda)ke<|dI$Gd&?h7#SX1avJ!H zP)`u%Rk%dG_xfia;zUVxi6}N4`2YpDCkW`$CBuzaF_kS1Oi?{Vr(zNVFG6i#=Xj9> z##@77e+4s|8KbBh9F%22966RSpVi7QjT5tB9%B6M407GMMkH|~q?Ul190nUP5m=`% zt$D;%yPnV-SY`q0@>NX*K1~c1=M~x38n(G+q?y8V_(QU%Cf(4o*@zkK2*rQ{gBclJuY#qyv^r0elP3aIY|1+>%fK{6<6+we`$;%S!=I6#e(f} zMf)Qzx33TmGXXch-LHHK`!VjAc^Ei6!1QfSq+zd*)HmMP!2bYkGwt$qBiDuW;rLLY z-^yMdOhS64i}`~Jv_4RG^Xc3DZrl5oBoZO}z{IV;wSdp_QhQPGiS&zO-N z%e?y?%mZ!=!6dQ1LwZfCc?g5j9}Zo3PompEDQ4k?WEu6Na480C()<8+dq5jbZJ-R`Ik#);Q`|4yy=9QRh8i4>w2zdv(_hB|;AJN$ zSC}6!28?>a;UDP2PM}o<<9_vpmiKqPkq5urPJ{0Rg&gG<8qwhS^Pz26?1J}h?ee_F zf_FpfH$CKn?+n{B@3OsS0hw2Lgs8}Fa%NbJ8Mnz}AEB0zh&`+(b)p7Sem zV6kp^fPnS;!Lg5^-TXFxnCI~bxkw3;H^J{SgYgekSX}z|@^)JIz@DJDxtJ~uC82>=q0#i+JZTUGn ztvk^#%m(jY{RAhYuwS6)mv-y}yYlz3f8$y*1L(jGWT;<}*{A|h zJX4(;kHguYISnh*RCZ|Uj+Xmr9-(cdw19MPtB3tNn%!^*P~zKV)IZn!h2pT96Ahb9 zWe!K}_&Xof`A{=AgB^6EYn^5clC<%<#L*=`c$8tE>O-KC$>O8g9s|Rpp%YL&S#Z*Y z6#N>w2Rjqf2Ym#anw}l}xV?XI`qQ6;%%y$^?p*2G<~rc5OiS0Lmjs=ui*bz#n-|Hv zBvXyuE{&e;m-XW2fb zKywQ914N}SQ|$mysFHjg`r$P@$g{HQ_?S|YzBVE$ASS{F8A)pJ z%j&^V$d#C{-rkTDJ-RtNNl$Q=(^Zm@c?T+dD0CbxhbWtk%4q6BOV%N;<3D#DxumIKZ#9gnIT<%sXt3=mt^OsZJ6D zd8lNQi9RHSoc1PNS)X<9F^f3kk)Pw3c(K$33i-jGt!^ME{Bn#L%BJ)t?Yi`7c3ZYw z3uU$*1#Z(Av(in8{xGKP42{0}6!;89vIdzjDZYI(rmsLtI@}^@-jolX6qT|$Q-oui zKpp8^RvjTX@m5J+#ScxY$xCIxE}C`3rv&RQIOe`!R3yXO6!1wE`v)>nup2 z54Bwail8*pF|P^&#JS2SICGb0n*Tj1)I>!}l02n%OoJVYBef`(Bzf0_B`c>&|Jy!<)ZX~Wh0Qi#2*tfK9iNp*exAEV35Q#lBKZC7xzGb=8muMfIo_!0|@aiXIe4 z^J5_oLha@Z8W#$G+6VF@3~%Q6r(fl>HF%)E<1h1j zD#Xb$87}yDyJEu4))UZEW#o@CAYV^AFdP^ma_i&|@2S+4FU?z;Zmwj++##gwy<6*7 z&{Zd|N5)wbW5--L^Q*@k(CqO1A6+M&4ok)~N1&V(`GJPB!dAXvj>us>yky%_#cAgE zP!caPTtI`-^8FE9MePX8?*@mCV>z|n%sO^GbR^YCOzz%|q69GmG!lf~FHo3tg}5P3 ze8aOpx2Z6lfk*glb?bq}2(5G@v{028&zu_U#>}z{0&K$~ZD6JhR)wK9z@69JC{1|` zsJf7_0rVC|9D+O>aM^%q2a+yPWV1j|zE?UuJkm$~TOP@b+$0ShArWFYsl?L0@V_I@ z=|WIF1%$y^e~`XPFq?mvFZyJc|4@|Qy(rOp=9*j6m7HqTG+*DHO~Qix0`^z+mQA+( zS%n+ENdYl71=JC1D5tQ&_=@w#H)8m06r9%2WNi3vfIobv=nNDl$1VC8#fp2Nc22s~ zl*2(Gq9cOH;iE!?f?6HAKtxE{jykQ_JXSnTi2!hVf)5`8*b_w|qp=Wyj?k7bBU3Tt z9)AWYSluhA2X6;y)u`gD(?V8{y4G7KK57#zVdQzux5z98U2Vak>@fT}Otb)4L0G@?S36*_PK!<0R8#29gy<{16(w=fgwf zK?xtZ{v19ikLx_5`b=Oqel)S$Oi3sHtpT&np+HGWWuw6}N0p9Xmmwf1xQj>vU&cBS zj=(pvR^0S!hK7?)n=j<>$zFm+ow!d%;u+=rG`A_?CSA955KT{H^pujhdTIByirLf! z2z4))97<%$S&>3uJ!mQ)B9mKD#;EjuOg$h`A1Ijvy~B%Tg@N<|qh8qaS0|0hy3|!G z_W9;tE!&+dUaoXOjbw>X*mPXEz%-ihLfl@DrL-7CI59$@v%+I>X2mJ7f@6VZhNxa6 z#hm$z+O@aO*UurNqRiRSF_^Kq?a-ot(wCcgXL&)(NV<5bE@_1$hclH@L^Adi z&PYleDJ9(^jIa*eF5Q`}z2bnLF5Swm!SAR@xlby!zO74wUce|JR))77^rS#v7pz4H~>Ow^NVEB3vi=KQsGdKo7`fx`+a4Pq% zyC*mXH1{0u2GAb4zgPL#xzGE_1vMU zAtqdL)~jO;4h$tukR0ydN&mP~F6ugf-GsgQpr|}d*N52$n)Rw8cY-kJfMuodL(~9K zWJh7h6;^8u#n)R(t&rGs68nWrCk)Al!`YOP_QD7kNt4~d>|wLRxC_!m5-plSt||H} zEn(&K3R0rDfLx23`QYj%Rit`njD@?sL6#ihf_md$r(^J>CAV9E-(~KErEh{*{&B;c ze9;2Occ&v3*tF2oAJ4!$OqC{QnQ^CZ(Tf_x(& zyQHqZIGr*XAIY=-9xePSMpAv&&^&63Jv5C@G4s~UJVY@*su4QFexr+N+f_Y!$!GT!dio<6$1lG% zpkE|SBBp+q4j5a)T5u*@XQS8dHoXYeO7A7WT{@DALLMtNh)CFgNxq+&R>uuua*_^F z#}A6}D;%kM>-Zp|C|7q=K0UY$?o_4xSg@w5xdOf^B|GfIUIY6>%lVqkn9~;;cZS0l z*9VvU#$m|rkCFPqSFyVjX8ro1Fxdxj@%mC2?El02HGYr&i|F!1K=9&CnRCh?T>c@x zFy5c|tOwMR4Hw@unrZ&<)CaziEUEQiSMNBrITyA~GP`Qf20(60ZOT}uh3l278*7af zb<9?y1T{;JCMACxfuev+p(^M&>OyMIsr4TJuJ(5!Tl z929PnJKpMI*1UuzM_`DC{8DYv1T1gO2@(WaNc4nSGvXCnwOZwsTeWIkZUC~vugWoj zt!O7@z=dW@Y=L{31r87ATOX#U-6Y(596(G5R%R`iQCm8ongw*UUSFcnB4jvoHkmtc zAF;4cHm-48q9-kpwXD^oWv+JN+)OPrSA$(yB>*o=TpqsDZVSm9PLfB0IGdR8%Ty@s zIEa@H2AYin)w?v@iU0*ZyBNb?gX*akoPa57xS78ljxpuZUHH*77UCLhqRC32xqHBg#n z$=y|6#KkDXbat%k`Lf?gw$!+*X1|@+WjrLiQ1zD0`f=7xZ)Iyiw^!-I39Qs57U~3x z%=)cuxXc)El|vRUwL(}a15Py9gn+*%C=ECv?x}!LO}g&Db7q{ldNjzjJt>cbT9Glq zng-0*z~SGjH8V=E*)d_qp7(M>0g&=$*0y^6=hmeFMQdHX!Zoe@6DojmgrG?ia&vdy z)#s25buBvr-h&TjC0&5ydMcxA7xb}JspQ)zFHEtgg`rGoZaDggi^~IP8n%(RyOFGyTWbh5lEE`Q)28MA zr*n<>w4pUXYe;vL)joFuu-XK7&VF=X2xAf^G|^e>o)DSN)!a%hi6E|#9j{;m`d%8j z-YCkKlfW`F>j~L-21J%0V=G5sGbFJn_||MrSk7L+blcBZi=?B4Vq)!wS=>U3$GyVs zLTjxO&d$`w{b<$=vE?nsr1>ari23%uDO?b3JX|Me_Xmn}DVkirH&UTm7gxHo+y{QX zs6s(Eq0lzyP76V1iG2{&76y7|g;ZK#P{hX-qvjL0F(5*QM zK>I2tQ|3+t#e-{1jDHmj6l1O!cKc9O7Xf@4JMj-~GiBym7m9am%pmOXI4#?uo(t?D z&+Siqz7B)9-mP1x(=upMSQe{PKR0@#rZOklQ;|tQM{O@mL&hDJi@12=8gmM5W3=5j zPSFf;t~v?G$9slUrpm64^%#||OlY8?9C;#9IjR5?Zm9GR?N{EL z@SavyZs*pFBgwf^4{`%Ddd(thl}WTctQ@B4apVu=?|d+B(D}=H zp&!jG4iesY_=~;p3|98V{(s1GmbU}lTVCckdJzaLcLMdTcR~fMc8uAtAZ$XOfhHGc z8l;;E8Z6htZOWdV*|k41=$8EYf35h9SGDLjfM2cFXnusaTJ;%fx9l|PuHOKr*9iby z>jZ1c>-lR@Uf#ZZ6Se2=p*we1#pJ^N-`UV4=0Rwl@R@4i%CnsOQjHw?S(cxlARHXz9+viGNSE)5}Ort7I?hp z=duzf&|nb9tHDa!m&OY_>E()NLJ9(7tS3)Jd*)^E}2~ z!^p`czF?08;I}0^Fv=RWN@|Dm<|4y*N6K*mkitiGxdll3us5+eq(vQ*NqH1S;wQRu zI+b`UD=GHa&zpe>TM^ShB4}M^>>Q$OBv3jMh(?53$3{gD3MEj5YTH4vheQB`Q3awh zK^2r?7sD<9IhrrnGTklCn?TT>n%)jU-iIiIv3m0f&=#+F=Uoe88yPZqN!qGcDK*U_sKyD;RwNGfYZ z8)>jxkH-V*V=fyti2Xhls$nfIX3S=dJj%*&$r!&w9a0*5G1#b$JkkRUv6ZhwMQu>7 zrd9`7JM^Iuev5SEC(j0QcMQy!{}x*jwthQ8Ot7})MX-y+G4f-#i+EdWCpxYhhGX&< z#WIo;xK#~&o=reTHGgAMX$u1(ph^F|7aymAgPN>WaXFSZpD2N+=_LvrI zK`YX9j5a&SdL~t=;e80v{FnI^^Md1x|x7^iT|;YhwvOr-m~=;8Ze~ZkEkD z4W&J#U9Z}0Yntpq6iwMK;S}cRJ~nB9pmVoZ=c|Zt*x{V4xKWWgYv>?6HpR%!`#OdW?T}y_w#6 zVD~E!E9Uh_2xqv+8&eE2L6Eo)Xw#5kFbqVS3(k_zfHqa4eW=xQVPGPKhh_?gtKwMx38MaxcThg z6q1;eE*gLE8a^RlQT~R|I^s8cLBz~=JUQ$I(9$f=w%tyde}DA{gt^%iOFg*{3FI_t zp6~4!Kq&9<975#dHcUt5U>u%qJPMEJXk|+`s0!0}TJ4WceYBF>Kv z%JuxPn}^v8@RLmPAZVs^R!|HhWRZ6toKCXGmihV7DedHd-YofbUJt1z{iTH8;Vq%} z>t=S6hhaeaQ>p%}$sofI%jArV5qgj59qn&YItRl3k=+H!E49tyADeOMhjBmO>!lnR zzMa$POz@1NuhcjA`hq-RfaQ|IsFm+1^ZZk7$JLe zlB=*>E;28>NLkSuGB>pPG){#-BOXgM0*+^P55jz5)oud5!h%$|I0WhWA=gaqj%zyb zISSe0`l=2}g*u8!#2?Z*cVzd;zEP8F5KYLd+CR=bdQuC{suQkU6Mn6dOyUr#>%$Gd zW4G(*Lp(e_QTE~#$k_wuUx%yl1sH9@a-0iZJebiif3d%@A_peg#Cu^&zK5cB>E78< zYS>!rIpDeF!P!UH6=Bd-*wV6=?ZZTq$93)z7J*}SEiCdic ztcU-fKhJnSab{^v6shVxZHU5MQB+ZI$n%iz=PRMB>4X-M@^D@!S_bDGP9YNcwi_rW z_!1Mhaw`gXQ$_<}Xyp!%1tdBNeW_&UHj4UU1RG7LtJqU$+mO{RsyYoU|#HIhR9AeEO1Z zrWdy)K#>d&W@SgE}GimHqeg22E3R<>RryX?RnD`dQ&)4gsF&8v_TO?q*@ju z=i^Q|_*Jto|yZ)3T-!osWY379C*VJg`yqa!V(SlX2w>x|0X_UPAFu$O?lq8j}|FiZjA)h648qn#==5K~{vocMb~PLN{1#Wb|68@K)W0ve|CL_*|G=1R z{zV=6hvZgD=s&dO|FA8oV*bS&Yb4SwfOD@gZJ?BFFQKHwq)qveifsV~YTHAXE$p;D zZD-~#e5pUg!jh&&fSdom+qc`ytw(@s&%*tF_?jEKo&t(1Mv;7(esllfcjA-&d07`P z@QwVPhU~lxifUjSQSHX;m(H*d!5~-d#ucNEsf5()A7-49T5M*W7IA=TqFykZl62G? z76MJbtBM+C{3W6gzDjB(HryCh4NDg~xtWimH_vQm9&*C+Xkz!xPFrBU)LA&vM(6lE zM1FaYV;`PV)7UGUgv%E|TGS;m6LgRcW0ir@e#O8#H@(0;E|s2;kAW||T1D14 zFr&+2V`mz(Avdm1i&{(51iM~j>&#(`l{Y%>Ok@nuTt!+dQKv@7Ta~wqCz~YBKJaS< zHX$hfOQ|ujNq=b@Jmq42)?MF7!z-SGxzLboBJp|9P3OVYAtylPS$KseUdL-MJnzsU zJB-Dzhz>rSLW-qjO==QR!%en&2qTnMUQF#Lk~HrC-veu2wU3qM9KKHHRUG8+@Ir-F zXRXm+6^73{JomwHR4$^*idnWOH$Jfr(%U=i%Tgzhsm^fe-kgUP3M_hVD&Cof_mXxU zrL#?-*ig2|yFFJQ2M1?<*Br&c)*X5QdlF~Q9+oLQZY>+ziv~Mp3_j5KDErGhO&NdQ z0mNPzikji%{8%=NrZd-_wLAJ{Osn`7_T)r&)zKAOINjSbGG|M^N}IX*1O*Q6rdVAV zIG7qXtmAL-yrsbx&s5ExqV^N6xeeD6y^5cvww>0}&D!U70rU{Ho!zoK6rJjp<=uhX z)|vPy)!TrSSq|=?3fz)0o3-aE)ud`#6a%sm*nEMh1*bLPiqVrrwi~{ok;Q$x|2S*M zNu+^mn9=HyS44u>iX*L^g1yU7)d$t>IrllfMf}{elO58oN$f86Csv&rQuHWIg5fQw zFL3U*)z%|-O))}k@XsPc*t`U9@a9j+cgVt@$#R=u(#=KmTC@D376=n~td|8;C~)F9 z5I01PNSN|hf?dI7L*W+0`NtsPi-CjmK%sMCauuh8oaA#tS^U5R{Zv2SaEXq9)>9bf zD|toI@4?KJQ$VjYioWGHtGl-|&rCSE+kj9iu$k+3b(A5oUae|n{n7Db&PmQy4L zdpN{+AL13Az%p64$HOG;`VJi#M?~Z$o)d9vxFFQx@L1@RuUri#J;4tMd!GViVd1w# zPw4m9lt+NL#mQa>=4$>(bo&eS-P3@lP5M#y8rOG@GYj%FKN|7Qx>52QHp9P^4IE146{~dDJ()D z50~OON_J_tH5us3JYrZ9XT2KuJd0!9Otr!gOV=mNZ1%j&bdcYKXHf!};tp74F@C@75nrXP;@*cJF z_O|l8a9u{+H00E0tcfztM)Tb`n5ng z8~`w4>*%}XhFzJAO2a0ab`3;|^*6sNx3%`?o{Wg4@{R}TvR9D}G95WjVjXDRtI~M;V9tOkl`^Q6P)TP&zKRglHa+H5nq$l1(;-63J{3{{ji6Gv1i1{)Ru?CG1Ak5ZLD<7-Cf!|}v zfdeKqMQmsl;S1`4qc2&`V;v{1?VTh9doI5wBc+BA!KbMji=t9xbEz;ZJKWrt*!RQj zkr;ABhN8ZPGTE}}0ma52Y6uC39Te}Tc6{7R8PZCVrjHZXFr53VJPd2xPXTW-#I@pk&mZ5W=sZ{gne;?z3N#Z}Ro(*h}? zFMkj`*W!`MPgLyWJ#ZNeLrP+ypdke-aKk3K!ansIu$+Nk?{kWG!a{I zLs}Q*WJ!$i5nYuRaWC{$JNdAbt-9puOg@3K2Rdnp0J=BfMTOm`EvRwEERtHlE_)|3 zjaBf=aC>u4OLgQd z^_HVVC%4cUG8sbJp#!zM;4DMW5HTs;xEeWG9oMcymVf93XG}+5x>ACi$uM_{k_YQA zdYP=xRW;Z8EK9PdF8#WUETJ5m&^SWHAhR9$8@o{08i2Rd9yhKQ>y4V&U}2WA-oDzA zao=0a&xZCDkbZO^u9|;J0iqmk913sbOIQ;Rq~Qf~5ys8(3Gt6*i!Jz8uJUcz$oRL* zmi6Dy75^&{mz3pSt2R}6=X=#6eue3IKk}9a1ne^mCH*AQi54SZB~LS0I6M@D9D3l7|G}|u{SsGeKT`2J2|Pl5%|$uuNWGfjX$CB zq94xV%b&bVGe$# z{OnWKER~OK@fass)c7EBW+I9F^Oi?z z(xi`~Cbh;AJxa%a%u=7_JyZ>YSXGSRG^5@z^Gjh|k?>0+n2KJ$gPRR;L|Nr6u)c6h)D=wpPIM8tEAt{L;oXO06T54Zo6E9%I=` zb5J8|k1d*7KqbC(l=29>ui+DH2~bv-@s?8j>$Y!za+mK9Y~m#UucEX&Lwp#NIQC)| z__{kRmG`iP4QX(OHlJM&0_U_NCZ~ZU$>{bOUNYJv{z;9!t-U*lV~^U#;r>^ere}KN zm66e%f7FU~e;vZa_YBJU-RA$x;PXEpd&K{3t^7A0qp*dgjftSKv8l7OrIDqLrHiMC zsg0@mf6`e?RdlWY+4M`graN0Ki&QVvs~gDI_QlrQq7+&o0~J7}fA)uuUjyQ7+y}2o z3%^kRh9YR)^%LyM-w6^7so%|z&q3ozB$|fvG`-|`&#Yy>J)caf|A^m9G1x5wLuq?- z*ciauY^e`(MR}3gG-q5&l(D7@^9mOiM4tRD3-RffL+Rdr6=&i=nbMVhn<&BkhZMg8 zuga5{q%x10lLdpV6IPS~9&}JiT+GPdVH0H>=q9vT>1>D}p^G=si(ix0$_Tc4I}tWm zcL&3g+M7A$+(bTPKY?bVVMCD=nc>iqnsPNeQP!55yiz;9n0-8%H|1tXK=Na#53eT@ zOD_+KK#Iw!i}mu*b+-5ZfzXb=1cTt^4N&H(-(*~I+)Su#B1Wiw4wlWN!LTp5A8oFL z)9bTcByRtfu%YpDJS;RTmikwQhk-E&g6xtl>zoPT)4mU@wG3)}nn2l{a;ZfXr|DZL zWUOwbO}BnV<0(*gN3B0I%xg+nD#UjZ8L`wXrrUg~kmbU!*-?X6W)Y_clm1gXtH?IX zoJRJ9MB@R~nV>P}TRJ`wc!!rx)#@taDqUg0`Wa6SS*KV4QNf-&t&Ey8OW8X*K>iW( z#!>+t1^NUMc83x@!k`kfgLS#y?gCt0T&*##rRoT`%HqVqoT5r=4tgq85M3H`um6vt z3t_+G{_$-y^!&F)_y4;={Rbl^H$~U}n-LSHUsr0V37AmB+@Yy4w&l)(Po+UbmJty; zpBt*ub39H>K5! z4n+0>9GA~?ddeiqn@}c~!+tCe3t8)i{SiEb3TtVF9j?Bspil{a0dA~mE9OV&)ER&D zwVNuJWDe-}!U_|@1J$t>Ogk20QO8$W$Kj0&UX0r>#22v|Lct1!eX9C^VM{bRzg3v& zK_vDa!4Oukm zf&36GF+C-SGQso&zt(P#Fohv^qf=3AGAOn)nElSAttg46gBN~d=n(j*#C%3KWIn7q z^UCbr!O&9Inm+co!FYkar3CBNM7?ErAwhdPtjl*6b#0ivnO0aJKBGMQ5W<_D82@w` zRNKP(buIpu2tJRul7Q_%KI`p_%t6B7J1PW7T$Bwwk| zTc{6Q$U!6t=Z!V}-~*T+svRE~e3YEbxcHrr(C0X+Qvqin8b;A|Prp9LFrAd2L;o^! zPHTv?M%64@`;|;5J{ue3iqd8=wdf11Gt*d%LliyoPuSEonv6f%ciH*nN-&EzhFlHG1)5q)7r|HJhaumr53wv)#4XWo27)&PeCH2 zNeQV)N#%LE(aw{R=t@2_L;l|MUNjf}^}|2K!`!%~z}MnrZ-(#XV3Wn&&d&b}xIQ-Z z2fo>b2Z{l#GyK$t#%;sc?v*6j760JASa$W2MW$G!ni?g}@O5u}?KHhG-AbiFhJ`d) zTvU^>Vej2R3~_9$oX5(M7`G2W&05|R*1+Io+%EZz3OnjF)LQ;33~aM%_=^ojuNK3e2pN&vBv~X{OP3z zt(*P|c9|P2rmSyRI%emeFZw_aYQQqScf6VJO8CEbJjQ=p1^+W5=3oDMsV0d_H{(Ywcr=fz>Ch|Q3qv$NWvZ1*`O7uT7- z*?F=-7(%i}P&P{ClF8(9R{+Z_&K8tayX-RCoYLA2a$Dq+&6mG_up~(^xYC}sdv3Pe zU)*;-_b>YV-m!?a=oaWZL;c1F>vAytrsuQ+K!K2hh(aN75Zo|aqkvUWJIAJ*&Wk*Y z0^D(VIj_ENOyj-W@1G7H8RSi;L>}f%0c`aB!R8XJyalug0(ox;Q7v-YfTj`V6sSxxI0a+=>o zjvW{sRbyNqI+ZHZ9=4u_ZMm(_nrGwHnKfUnGRlo^jd-GW3qw%OXHc`7(8Kn~@y(+{ktcg8DKHhB zX7D$1q(q1ldkH11{?InwvtUGv8}(Xj&~V@^f}y^-I<o!nm^vzyRpC^ zb%V@WMUN*_?$@Ydz?8gjYsV^r?(z=n)Pj)ty+c<~Qv7)wSNMDPI*!QyMbFEB z6gd>74*f;<+BACIhU??dN7bM zvYjHeAnuXT=))PxQ5sMMA6O>U=y5J!%xlau*4uIqA9WIlENlnaCA>Pr*9CbpnwB@# zTf8lHt_z=idy)d4e3ccBQa+#azU-ob-Hlm<64t3JiiqU>Sf8O#YhEEYRX4HX&bH1@ z>+>Kn&-Tw^!h;ff4Tz`OJ1pe!U`cSYjuY-2EDa}Ql-R1uk@pZemo#t}DjiBX_;PTC zU%O(iWOIJ>8?TXmzZz(uJr+{Z5VW@g>~M0}s_;3lV99Cu*uce(@x*GHCy!N{8*)T6 zWk7_mICYd7j>d6Ov)mZ)BJm@|mj)r#2d6mlB|?YG$Vg@SMLNZY7O%Y=oTCO5yY zXbcSX+#BTe=H+F=RewU^Lib_62RE}3Dvif@Vsl>1f(+#PAk-Eq!{i91c?%?hK5?q@ zZ9+wR>vf19X)T4axAGm+Qmz6ocbeSUqN^ItAD)Dyij$c{T4{AkeEFCVVOvnAjDGQ%vQeVN-!e zUt$7AxTZ_!N7xDg11nwZq?>%h+RO{N%!EJ()b0*28d%fqF$2mHisYwiZLL?m*(0?k z?NnnrO?+#uGD7Pzod#=z_MP2!?#V;1V-E{Etxq>uHL?439c{HHIxG|2>zU5Y+^3u0 z;l67J9JhBX?iMz7Ea`^rfmqa|POROD>bTj$NDnRUSFzZYjykl3dJ|` z*1SIY#UQLz^A|3v#jIp(StSsx*kuV~RAQr^oTBPrwmv6Bh|NxEajj_N0YB84+S-;a zLR@0u=M7_td51hP5B4DO)Q0J@PEmEUPSN?Q0JV{PsB@>VzB0wmygo_%rSl}PxhH!l zyqm%wY+flG_$PZTytt+t{Ih8U#*`DJO!)X1J%mU-RekFs}+u0-3mg=5>c?WDqrlNH;xZB}gCc2ZF# zso1t{TNUHWzUSO`@7e8pyS3L=eyq0gbB;0R7`^u~x&vjQAjLBT-_IE*Uc92(ybGu6 z9l9+*SO}J?s01phklFySOjJEM<8&m>JAOx1L|_I~q;LgSRd`sKB?-lD1{SI~TYO$+ zg@h#uxh?vBo2!caWdk81Utj2T5>%_LSi<5XR;;}lSNg1xca{4fU=9z@KS3dpSUejn zRM|;Lj$^OwI|Y|tn*E6Y!l44yd|U^Y$H=o4?7dQ(j9{eG~C zpyegn!#Zn|x^ZU&p*M1%P)sWbf-;SF{7ONlZ_Sz39UtQhIDFRUAo2q9WisuD6a@i$ z--(|Wl-%c(g~PF3FAo(*EQw;U_M{{xWKdUSP&2z{K=sQ(S0BM?PF%9ql6mUH5R%<6lv*GIj=G|zFq8jLWt_2l|qX6ia<8qsd!x|6Sp z+_p!|VKW1_)i_`T*;}YO#TSbkzm3&Qc;h_ki@zb1{gif5ps6Y0MGfRm_=z3-;{SNG zUEB>>a)CJO3)_YMWb^ImqWfyNC$uc#GD}ELvWNPfz_C=Hz%FTG<- z8mnbjmeC;|=hD#lbJ({%{5Yr4thqy8+ez_>=d>)^lP9zeniCNOU(D;Rk)AE^H@DKK z@`TIDo>U-#^uR9MCqBh3z)J@n{}u4ZCbc{0w$lA8)~CNjRuRY>Qpb6lG{csPBcd*a zO@Olh9T0|$eBICOyWl{M#~i^nuPLx(tg=!xt`O*3=?%urh!i=>+$$|+!6sT|X30&4 zselqniydOQgX<10J{64i&CAMfDo&OO6|X*b7p2#qWDEDN=ZTGFTSwG?l4NHMfuwk) zC{9{^b4z3tZMv=+lsP5;ymu*LCfk7BB+Gw|vjAy#zJ892nkDkV@?7?Jnl)|q+ zYM#QS06f;BUq_b|`ANEB4)J3|tQ!~`yg41FqDsLiMvOrhg9aT+Jcgp8I2=X*HzRAZ zQgV+?M#Mu`W_l?-)GiR#x}@@O?Uc83nIPo+56UQwYQM4}_E)7wg9)E-hO%cIlQ}tB z**`7pkJf#33!rHxOP(UJ043XilEgKOzo$$oip@;mk5^MnCoi|gkkpBrhnM7Qknmhi zxGyasyYGG8Z7~$X3q>B9rgL~}tfB~5v!J!IQFMn+qOV)1n!0ya`rDt<1w}!brU>GU{{LgZ+swV(WnS^&GXOx(V9yW+j8d;!lL6rV|XDHLqUD z8RxQ(Yt_$z7j7q?Z0#f38qbT(07*^6X%C32ZW9__8PPObE<4q4Nx-^29~O!iMDv*8sUU@yI~T$G+INjDuHrQiHc^NzLjNU2O0HG09CmT`)`}+eS9sMSv^JSIc&y}%$`3BMnc%~k8jt$&foJ;(4wzuH$bUkoN3l~tWwFjI zn3feSW*CT9s%n$LMf=F$_;sGZ89fZkjNpo?5PeY)YQr2TPt%g;?r4`gfXJQ_^>IBFO4MT|MyqBKqO-pTLd^JdVd2-)-CSe$MHk z8u-TKq~3A5hm2z$i_Yao5-kP)+G%|ezAUcAW;n?7N?+Zc_x$ZPOt!j)-*vk{;R54Y@O7wMq)mP3(s_O%c8H<1fj~1@H#Uix zMmdIPPjNmEFW4<+M)Ls7M){JY>z2WIg|AWE1Mv^_)tJXS1YIngL}qZ1Zajg*jo!Po z)+G>w-q`4=oTA{L;L(cE^1M?alO|Uc`w`{KLXd;NmOMfdnP(<+YQpr}Szl4#K&JbO z^ab+cgvZQ!T~?C~i_zQpMN(0iQ^v)`p5uVl$X}SHlCM;BzDO8*I`Wg-IoT8Ohw*j9 z&>fbVhd&zqy=nBCE2fD1V=Jxxpsza2?G6Ona&`*X9!6MbeUs#QWqx9mNqnWQr_Bu+ z7ay+V1*nV~eRHgoiCwh-eg}OgEkfHl%DpyU2H@R;z8vwsS37x@;-}4SeZ*n!UU%*D zowqdgeF8pB2{y^}pjSrDbJH%|OCq217Y5$Kw49kd1AVi^VgH0%&F)fqNOvpw*-*SW zW1xQV2j>)TbU#U9Yh)t*az!IGVy0>a{HFa5Z-U=v*)47;-qi?Dt(P!@KbtOHLNyBK zM`^Ty$h)A$3>%A`DlelwoO}Y)SYt?V@U8WhUcv{sj z^{-$qUho#`LPZe97=OI^6{md`ZlqZ`Jh$Gw)s@?hd&%oI>0g42rkbOD2p!pd0VI%6 zrfKZ-b4WlyP+#h(|2tqJ`j3Fg{{UqF-U|2kAO2@8T(z=}9m*FgTnN?JxN4YR>}&N) zo*oy~XIGHalB^u1xF@I?JcMQ9^1PJ?_CoLOix`My*~IVEytMp5#DreFbw)8Ni~IB~P9<=8LKi z)sBWbZ|bwEKVojD!x4gSuep+Zc`5rd{o!=>+ z!oDpkU=R@J<>D(+MHG=hcaQ5;3JEYEX0V|xC?8pNJZIWh{>fg6Db{%fK8n*`8&cra zpUl2itne@?q`O*f=$x*~~j=>nBci&&pplP~rBgCKh6h+K= zlr?Ons~G#Ezlyx_R~D?91Zrib+@MGuvD5$CagJ>MB!a!RQ8?`ddc*PuV%DqfM>~F|8@4?~z zjO~OT?zjuU-*k-S*%&i84&uq98==Aw`2|vpA`PEm3DUcKR}V z+#GC&gRTUbIL-3YEzw#yc6%{{Z7roYAIrW>O@uKQ;znMSHR3*ei&vEDnU;xq3M+F%r5t0`AvMq$uFy&}y2buIgwJ@+K0Q~47&Tf zz)0g^gPv?;R|e< z9aT`JHKkp&*;&WW0mltYX&waAT*Q!2E=32Kh2Cm-5s z13+VO-!Rw!(@7pma2z%*ulpALRZ3e-BbZz9S+Q>(FnzE-_(CF@9unaMX*QJDCYX05=y?WD_!A|c0k+n`G9Q|h zCdw1o*b}W}B@ZlY#$lc_iWkXnGBW7Ot&j`%0O_%ZnRj!k8AP)~%#S+qKzpAR4+bbk zs(KMkCM~vs)#GRBgX0V20(=(~At!|BI&_YFl}XDNEVa?MG(MbW@ghrYFxS)FbDsk5If&4Bcn*cga$f<@dE z#!R%t6Z=l)r-}H|O=x}YpF}L}gNV)YhE}HZ1;Vm?yy@CMx0w^_vwsZL<+A1abf^2I zoxVy)HSgfYUTJh}#t?a8w%tsjzKTPe}8F zB+lr)X<(iw^|*BO40 z+^@vwWQsP%S(v6G_=L`n*@%Sta=friwYd0>r0=U-4@8C`LJGUXPmv!uvOLv$Z1O9> zcAepB_M%T|SE6Mg{55DGTrI8{b_3xCbaE%?8}N%>TNpQCr&h;+^;v{43=caNdq&}b z!f6N9np6SVlJLsDs0CyAY#RX}5Yxm?GO6>AJcpOUL#oJ$cm*$@KNQzWK7m{zrrJ$R zt6dvHssOK4%C68nNlmoX0GhnDnq2XBSha7J2lzQ12eWARMMG)JQUx$&meqp4V7+%Q z4oRhux?G|P^(g;d68$WptnX~RiV3Moq&b{Bj9#~?X+&@6g{19Hm=@PAModdEsjPu5 ze4>hIx{Lq;Dp2F5x0NBnqh#Xj9xG1z0X& zA~#t?z17V1Z@oB_v_w^j#^B%+NB9|>C)X8{Lx9<+Ad*><3=_l!yD~y;Oy#===Tyt_ zVjQRPLG23W|MfMLrdc)~9c9s?o~)NY5IXcj@QObAh1c3HFT_Xhwj?KbmnfTpAxrH& zB3iw_i3V}m?!I*Eigs16qwU_)?c`6IbBZqG@!dn}bFL!&rlOx>dDmzXjhGJ>9 z;;HA)C;ltikGB5JCnoZJHlGBKcN%U?LZ7^V0NhWZ;UYq!4S;8q8_S)v5FhqVD#-?WF!zO8r5kn(fRXnl*=WLd00 zZr1VM*<}b^Q*NjHfIFw|zBM#iFSN78yKZw0@4lHa>LgVjO#@@F;#Ljmh&!lNx~Cn5mI z4l6-Djtn8lN3<*0Uuyi#geJ))m8@Aj&IlpQvJ zeO6C*W=CwX9KGICQ!UfmZw~k zwP^*+L%KKxpA@Y8D4(GWjJz+rJ#J0`W_5$P%Nm4K&FyJfKvm^Q5>%6OjA&O=jwjZ+ z9=mJP_kD3I8ol!)ddEo*{SeBy$Li2@hd)vSNbS&##D0-Y{(Eo!?Q{J_bG=cd4kI2h zu~e5=g1dN=TDu?&`XNx!f1pjFO%gKN!lWeDOkpHh<%Z=FAKp&x+U#vu?KI@l(;56U}yKn-Xo9**WM z&qdkJef)74n&$yRPnic>_`QKtP>(#X3lFAMLZ2F}$rgIfRc97WgE(6h+O6tAVv6(? z;;(X3u(@zj;Y(T<{be}+KY9Ci2?6Ur=B=o)nTe>Wsfm&EzY5MT3BkWIHd$Hgug>Qq zM9RP+^4Dr+qh=&#Udk`E3l%L*6gUMV8B`yw6yT=(HeR(kgPq}$gg{r&yuRSxKGIZ|-I5KM|0td?#(f=MpegJQgb$*Q*swgI`v6if>a z6t~30vk|&v77{K$OXm=7DY9fhk3AN!?opb0>dd0u2;bqG$5Z0|fGDgx;f&o_V4IA; zMrUQ)FjI>!XGL!@WcquQ&nEUmZL?UHn6%P> zb{tSz`CpdnRf|yAtQ)-OlhrpYeG-HZ_mDzrWcx5c;Doi+oD-he291bBj8qU~?UyHQ zC1)oofU!1g;h!ziVu+1jS-a^BDAq-e6nZ233n7=Q+zUK&G*|^uu3}rD1*sY z*4->j;yrWh&}Na|!`aZhQ971O5af(?#i@>3v_HgMR$B#Q5^?=bAiE2p@e8z@$rkXa zg>{pSiJWwmL+3;6r@@vFvouv@ROD%Z4D~--uR)GwxMjQT;9se`!hN61GK}# z1gXbbFNW;$6^|zfE~`SS2^l*3zSej|E|IPf-#E1uGKo~@J5Ifl45I~lS<5!7C$y6y6 zKY)2r>#drB<{%1?ugDv3lAHPz-1S#l5&5wsJ$!X>j$cpW|D=`N-;_B#|Cm;PM-(LN zY)w3j>}(9l{;do9r9AdEZ-vI!EV)O<&USzgQ#=hM8E5}PRR^t(Xjdg&tV{*toZ^8h zeKbAXniBbQ9v%g%C*ZG%E4PGRl6<-X!;vLcvrE3mZyz^zYi>ZX^0Y*e3nUm0M$jJX z&b5czDS>NXZd3(;q6B42Y@TJJDh?M?mhgMI?vRr|qA$Fv2IBP}xHfeXWZ}|KSKj%3 z%VpD25bvGgN_H&=(N&hG_!7vF8z~8e&;wS52cg~ftI2-u%jEkxG}W_aL4Bv`4NICq z)_p-)BlSNU*9q@eS@_W|!s1~&p+)9V>gr!nnKE6`DPejiwP$z_qwrXv!{f>qH&G)X zO_3mPi|Y{xx$|yc$x<&dpFI@Ppe@HNt0~N^W4gCeYT5Nc;xYGz$+5%43R(ZRIm2hp{ij#p<2CD$imuSN%YIX z@Vxf+`HP_#jt7898F+(P2D{O7&Wb)sGdjEk4D9OmJeMj=yYjH)< zruu>O0$vQSh(e4u0mc^hF9je-Q=KJJ6uP)COO%ioZA~Ltg_vWxGhd>n&@AV zBwVR&dUSWOmcG*VnyCeZt3J`&D}(_~C%ePGX?zW0XVczrlM`pLq>?rKT`WlZUHv}j zEOL8#!-_zPafL*EjYfXNOsGQH7HM2_IUy*$6=pxywvD$levy=9wghyws;UG7mkt;$Uz?mNE*Zx%uQlMYbZ65i9VwuhDDJ(E0|}>i z1XAn6i*o{9*EmuwORFk$AftzSD&YW4Yb(wWeptmfkVcJ(W=R733H;76?yNTJ5N{e< zntOmQdx!ir%K&}I6!Q4ncr?<|(>yb&%T18J1!DH6f<+V!{5Ya<&a(w?;4=o3k?9jA z#&r)s;Oi!VgzD{ac&`77lEVKmF!+0v{69-gng6@SK9l{+sb$c%Tt|)C5S$ST5Udzy z1FTTU#w?ORu^?h`Du?Y_>TKWEu(BcK4*dB9L%|;yj=76S*zI<$5@psTO4i@sI+DY8 zG(P@i{gwXyad*ZEgw8v>OIIRetia>|+x#nS#&A&t*-4YugekWNq)&c5MInE@R{f|G zm*!+uffGs@Yt4)Hq0`w-#MwYgPs2qty*EzF(Pp+bqcQeOFepS70PCcbEnx@Q7o$1p_WRTg7T*e1fUI1h5h&@b!^}nj>x#rDjdHh9hgwnh)=1NZ!U zTz{Dh{)3kFKN`rts#0-B1J^IX{=Z^7T3$yAeAZrHb}a+I;P^01=lSXm{QtUh0DW{EUw01C*ZKTUHS_ngq5H?P`InEQn1%KK zF>fqZ`Ijq{sg|cs1R5}SyCZFJF-@K$auP{|V3?4E_qwfkYwP*$Im004XQ)8;Qw4NT zUii%jq+im_xGOcgx;5LxWDcv-A{-qR6(64x)Y0-KKzj5 zhne2-2-D=k1u%nKGX zb1i1N&QqJzmgQ*x#YB;swGJyMyMcs28eAKCpfOvfGRp#JPj;)#h2swYL5x`|?n5gr zoK+-os>avotR=WoLlcZuF{U=9p^MT$1jXVrZLAhIWqZ-}qn%~RQ6g_$>drU<=9EpH z&cQaNMfK{!I+;HI995r$jAkAs)s`Jl5}BYQo|<{cylV~fR@miI;Ep$ZOVw{pNhf!C z8kmR(Qo}%*61fX^@;Q4Nc2PH68cP_3CZTnXu>pS@!;OcaN$RkQbzQ#_BbMlhhBTFU zF-T!IP#u~}ec1utOO|`i9>D=Vx-u$5g#jOJ#kwF!8Un*~gR>q9}-wX z*cw?)c|NhYZoG5XB625N1UnjXybPOF8n783j#A4xDw}0cHOW51T}=lgm*MeIBt6Q% z6@P2qR}2luoR2aF!W7Hy_slICFvGXgsrKC2Mh9Qur2`&-&$(atGYE9F%9=i;VNQ9cdf|17~U>WDXalP?I}Mr=-mVRUDqZ zP&XXG_KN}YuGBDpuY7a>rpwN(d|d9MV4W0COm;-O!_kquzE3&5UfQ7<=@#A)L8XSp%b^O{M(v7V}Tp}iF-&UTvp+f+45Ke;&3 zd3AXKXsjQXpUlT40iiB|IPeyj7frml-uK+fdk(EG5JJOHo4o=c7i}ZCmY5FmXYg0e zk$gGYaod4&ZR6DO+oo96q`^4P*b+MUed`&G=Vj{2%0}SaAZ-_Z=(C#!AVm zadq_tk$|@m11-di)x8&DP&~3q1?F85my?>4dKAxJYZ);4w#uU>f4idbjqioe9d4# z9kugc<#DOH=yD*$mk?5UD&Eh&`wJFM=8cl8s-SgOCU0;$Do3G=2 z`Hv_1@5jsekH`C;zGh^?2G-Vw21Zu@#_|%Sl)ln^$SVP!cn4WG1c?8;0w@hENay!& zB1-)QK_E1cmAulfL&o|mGBzB*Z+M#>TDrXIsvg%hgkLQq<@M=6y_xGR5C@7EmlIqaLt6Fu@Qp9Ad#W6$~v{tLpEG4oa}zlXPBS`n|NM?}mYE=c0e|y4Q6y zYwgX<`*9nke!#+af;g-RFSb&$^6no7+# z`FR>4QurfWB!yr2n+afDXbOy-SJy}jp_%XSa2&!qQzJ?hj1C=a%#?gWMK_`Ze<3ZH zZ@9pNZi0WvHza$*r9w=yo5Z4P6{~NfN;J})xXzK)YyEL3a^q3!HK9ANt5oyKGk`Uq z`PWHCm9FF@$4Wfm4@{(;k25Y$=-+2CV_RHJ;`G2P7(Roz@D);GxW4Sv=-Fm9L(!;p z?>Syos~1~pnK6Yg(0v7v2a6u&6&7>rS#*Zy()v13O%_Attq^05%r||MrLMNIi{^~x zNa4LSKY~AVTtPrV^0m|}J2jS#ASSh2m7+MniQm!&eiDYo{g`6#o^v2?5i=D4eGU_Y zDtJ0i$h6DH&F$y}?Vko|d?gbCW0dma!hMp3pm-NXr>X*j8}<%lDnj~cEDf~VA;Nou zsD;$WL^5>~D3+E>6t1eSS!ixC3&}eBDd+Qo(W1M@p96ed=*%%}voY8lG^ejP0&Hmo-SjWp3&Ivd^2a7o)2{sEpD=~{ zt}re~S1}AE>vG1XsKeN|SfI`RKvnYh5PxenL`mV|*%89%L0MrTOnjmp@GUqz;IQ z_!Sf|m3KkC^Zl!cB4H~Tf-w%r+jwe?Y$%u!)yD!c{bC^bG!Fh!8`Ynu2Z0Oke(xbp zA8~$M+VY;8dwxGUVgzb|XI#t2&asM{(^m+@1e=Y;Hrqt|aX3Cq^Fw*DLLP+jHfqjf zi%!98fNH_Mn9?pedbMJQ=?0&nq@BhII*UfJk6KL)dt+3y#Kv88it#|YO)QUf=$lJD zd!Gxn=i~vrt^=LwjLudQ{m>le&>wo$mAo7RaBNwjY%=?(xoUjYA9d28E!GaPj&f5G zb(b8&6|jC_)1yDqyY&spe%PjZ3gXml;psI)NgEpi88Jz(?Q&^xNOMys*|@pg zTtt&EoN+j^??P+K`xoL!u$s*VTrfu#j)FR%IVFIt9f&!)^OGd4bvED541(Gi@!a{& zw{+`0&p)>WIPRxMj+7VnphRF8K_P^9YaSAXWf(qk1-bLy^dl@0IFw8M7oM zSAm-_e6108C>}&ekZ&5Oh)Qe*wqx4>+0~PR%zUOA zp71brfJoU|`Ob`NtA@58Hg&)1msN^~;1GIzkwW=#ncI`@C-TCN5S4ZsSD?AFwJKSw zWun!{l&ho@UQ{Tb82~n_r;8A55jz#qFoB>M`oM5W;u4K}G?dhz~*i!`jry z?&A+)eW;9U%oy_U&pTajdB3+=`;tA0{?TJZqAiD6u<9q-u>olFJ~y*%pbL9Aagd=M z5iD=SAqr&SPEiuV(czD79I*%uOy{v6J_*w9w82u1ZLvf-$*}zHW&iHLAN&?WFQLFu z-Q2-~=*v|o=WJQ=`eqCIcYs|WY6fFdn1{%%LYm^ez>es$aScGd>Yc8>oB z_~tdNlT^?kukU`Dm0UPe9n_+&8vZb_pmx?=oSpP;hQ-gG4bCrSI-i?ddcZAVHQ~0Y zOBS84I4?U6B<4K^jX(;b3ovi&xKl`@Wl^#SbaO+lOPo~~u)*7H zX*$SLb%^%fZ7De5pjzBEr;+^V+he&ha#BSz)zLqic!yD$0S#Vty5?(ez;nw@`#FH9 z!QSyoP`MbWQMIT-Z~V(QCw3u(>H#XJ((Kps9Z;o>bKn93o{Ed6S5TyB0}DUbScREB z1Z~3&rE2_~nz|?tzsbVm_*9kQl3l~8-Wz(Q4y3MeGFSL1r0(~Z{q)Kz2nS)yV`^)* z_8W@I4RqLUnWEOMRmY+mrpg&M%I@lN$P$h~RKmJdqin~iYn1B+FjcQgg{Mu_mV}Pn zgSu5t(eG9W?&fH`dZ0A|z@1eP&7C88eb~+-h0=afT3$9%K7nFVnL>5;B(@o2 zHzKoqjpKaQAzo2MZ48ZbP)pdPCGpoo31S5T1n}g0;g-?o_`hV%a97y?Yv*%RmDL>v z7Y`ht6#H}6+0g?Z%imeh&REzqb+vE19=2cHvBoGl(wPfQYJbj2G=_2)9@lw|r=`!c z0~i@jrX@0Vb@I){sSGsx_MEs@tPsqTGAs6NHCYMzBCzpN7ahO)UIsUkVVZ?pZA5V%vsT2JBtoIx-||!qUwZ9HM-Khr6wkc3JDWa zik44F3bUOTVGXbzmnFu`I8gqXV~D2txcjqhtg7k8hIZ!A>?#(;pnTYxX*$dnvXP&* zlFD8GnhWdnp}UL+c-X~wmB!mtJ%3DnD#!aoA}N}Y1(bSMn)9}JSMDoET2@0!uu=(v zrX}~Q5o?~sGR8fyXhuWi^DSseSS+RwnK6i3{aMA(Eof9jDk?7Fo<{i{=gM#)w%^Vg zeko^DGXoVJL)j9e%d@JQdbi(T?3CkXBH$BYy>g_3N%amBIz$p$)s5jBy{yIM`okJI z*Gkuo{3xGGt7O5!SXe znT9%!MyX3_)IDAG9>`X_Z(VU!*ekvc?S}up*hmNYLcCu+TO5(3p7`@e8)xDJnOGGG z1VbX9dpHY2LW)(p1!9RAWB^_Ik35-r5WzMskRCWey%H|a9_==1f9wQMRuhu(1nuKE zNhU2YZWER)A|?G8>0ne7obhB{F3A$%cx?On{XS|%pi%&F76q$8&N^tR6mk}EgMR0D z2sjHQMg;6+((h}6bjV0!{w#9XZENZfry{UcW8y5@V*4DrfIAarZ6cFe_4Qhj(H)_3 z|KfTuhJ<4KI=VoUdc0N>aJtmwS|OSp6br@{@k_I;_dA3H3Mlu^xypNJ za(c|X%AXqWzES?w;>B>VGdF*s<5K^)1&R5eOUl1*SNzwjQ0)!vJtz9`l$mZf>FZVe z-UM%xza9rd9{>#eqe-4BMOgDU`Yc)F54Lj2(Vg&!s)#lMfmnK)2(=rGVtTrorJAtE z->t2>UY<3Tm#3|*y`LS=zKJC^5!)Z{)4z`0G6L?Q2N{hM?UOj%e6MPmTP?CevwNE3gw1?3QVDL{P{B9qf zguFrFAsi1~ev;>xF7N-9jGZ=Jw&Thl5KHD?Nax*%58;@aoqEfh6!q)c!4<1_?7TfI zR;>a7SpEbogY!p;bkS^hQp?=7oi_@3V)-5!jZFTmGN44kk%fGYI$dx?8bEX2o}i|{ z5}B})q^vZA2RK~yfX@{lp`KTe8u1pg{t?Z%A6e#Ek=3F-5>5A91CF#8?+BYpY zqZe7yQSMlnwA*V|atwtxxsnB}mbYeJw?sa8a*{vFJ2JYgo9#TV8Bj9T-$GLP#U=2m zejptn&V_X}Hpj5J=eo`Ew?fVNG%ovAd_+`0nh%pEy=7D=b`uuQ8YS_{S_ugD-jI=Z zd;?6%%z(4Wzc#idMHT8{wT_U==C*QiAUvnQ^X+C+u`Tx*Fg?T1b z5tL&)jb$0mMi2AE3HZ>QGW9cdu%Z${htLdOI*Szph5w;X)Z~#OaBO$qU)xd3fOQQn z6dlP+?1yv|q-DfDLEqz%e1{opCO@sm7zkY6M#HDj72GvN#ONXb>XmI4xTS`fI9BO7 zMIzTf7d6adD#{z}^xlK99!H5~eeJ%a^#mCt4s`TFP8V?Y6JEr~cfBe26WQ#KjTzA? z?V-Nf1@{z$oW?Y&C0%8tC{k`Y+-zlUzWF$61pN(|Ryaq4shV1rs#cfhPQps$kt$tU zLu-xcfHg#wSe|z(lIEcQX@o|Dni_qTPD`4gYJ)bj;>FE#Wp58t%}JVGgT9N44ZM&# zOPi~Kip;xXP9R zAJJhVhQHy}84JaNYEJtwYIJb_kSeQA5H+Nyp}~1_3~0^W3r0FH3;bCUkxT4VC8S_b z^z#-wFkK;p=?BT#ezT`TLZCmJtIwiJh)85br4rN9((H{_UkM2}!3FIU^Q)qh9Cnt( zS;XvB7An@N#cGKGiG!NvbFJv7-i>`BrD}lHddqKF=TL(rnMv!U0JU=RaT+u1!i;?O zc^1c4lGMitMkdvJlP_quYIScK1nH@dkmzqnw;#-JYW;3BjA|9VtvIF>o$jj5CRvP9 zB0J=gl<^#Ci9OEEU|x>MA;c;NOC(&%N`;dQbPOLF2VGZBGs-zo5~CYXsTwRvz-k3b z{28!#2;oTj*xxJ zJWl{$&Fq)0w-q!JNFS!QqcF&v_LjK4G!3Gf>t~~5%^KgmdlyGL;z?YR_l&0I zw%9jEhdhqcIkM1YK4#4)#4e=oheJ5Fz%dJA?X zuEe^`X32LX0~3$HoI{MRpAi+U!NbzF6{WvdM(9Jx?a7)|aB4MxelrlO1#1Zx^?@p6 zdq)}>XT)E`tCPF#jH>z#V=|J2h%w8E&y^vc(F6$o7V9TW$b>sJ47^tg&tjhmrq5y3 zdM#$fA#eHtZ1??#Yml%z0`De;z@?Q1QP2bYZw!Qq+q39}czdUIji-R&+0joOM1W*U ze{Hbv-Fr^id~1mU`)!o5ge5)vlc9_Yy)UCeF3#ag_^2l=A_;5>9wy0%E}}+Ai9MM; z#wmDXaE^o#5!z9LHfDHEBZVXB{+7A3v0V`!Ji};94ZnTK(9zwHnW^X!q^3Mf(J##) z29n=UF9dtSj!O_6&pwL&CQ>$e-~20$C8r_y?xRgPCE+|9SMCiI^Uq8+ZfbFjOhOfA zyyo-Py}dcpCvs$d@o8G){+X$!s#Ue?^%;qqrsZ%45!_%phL3!oAYkLk7jv|Y$|k2m zMThE<2snkvaoXI&58Z@m-$4YaugEUh| z(-~!=?5zhU2i^ysWIx@kFeM>E;>+tZlg3-PU|>gkY3E##xEzbpSXKN@aU)om-Mp1V z*H5a7fBn=ZqoYS|sH6pxZ6iA|`_{cw^xgc`Su_aCwpTzopm%SLOi3|phR7!ERRJ09 zm=G(Wf3KJZg*mRfKajNnW#QCbK&a0TaIb??5xPi5BVuy(U_=MMp_SQC~i+uO7;9GYGkHSem$b_%3 zoNAEJPFmx9n24@o(JY@?#e8v#rz^^SOExoP!3#;*0IDq?L13+IOc+9ISYGe+L8@{n zv3LdJG@VAl5HNW8gAV<{=%PQfj%aQ1NT3K58>&OFw2f6;bW3yqTHwGz;mb=mR*3br zh!XS)?`jUV&-o$|wkV^;i*YGEZ~+UF)k9+(nmc)IQec!z97PZkK6w!*V4XLC1&&uC z3X}_^Ja~WMqPR;TLfI1~_^i(uxWdZ$Mg}3c3Kzv&?lB}&YuM;ctoKV=0)?MXAc!3p zPc1RSnUz?g^t*xSy35n_9)>sTj%V;dbeW-6q(cn^eebp}tjX$zzTRYx%CWmf?R z#Jcz;dPqJb$Z=YbRH6oVw;RTj4r?Uy5q2Lu3|yU(5KKcOtBxCC+HM_B_S1%#l55&} zye^)aNrI0kxiKMtG9(>`bVoHyYuarb?=*j#hz6KmDk&vVnfu77Lhy=r!C@Muu*Py0=oOkE<{U91aw$SZ+wlu^S$h*tsY zDb|c2i&_k~W{`6f*M1&*pOOaZEGPnLt1E>9J05-CjIQ6b{o?tt-ZSZ7_nU91gQE)t zp`LbTOKR`4#|{!ftUA{$ZZp};+3%7ltb!LJ@dPcMQbw7W^!5N;j?VV>&=}qn_Y|l} z&SW>xZ$JF$1Z0VZoUV}d%zNc}np(X+L^AZAm5^mRlOlw9>)ya1_F@rtVY2=A+VWeV zf9?eph)+QHOCCs`r@bka1;x8)HcKZF+V!vH4yE{0gWD|LB=G-^-dTA=GV*0~Qk3Q^Ey4)ui#eh*^K6s=QB%i;HE4pDfKiA{xdY#FaMVDS&inC@)I-g zWC*?F;Wrp%oSxPbC(S44r|iL2!;&(D1lot*I;XejKC-mJGvZtAXe?1YIFSW-A&MEP zGBK3`6|;h2Nq+!z=9nd2Zv_nQuVre;$-Y3uKLoVGIP7{r``(cZ#ws+O{?` zY}>YN+ctODwv}PqjtrX_wll-FZM))}dv5)8Pt|{_RcrOQ*28{TV~;s!AG3d5F;OO; z?R27O46Fh(05V)y$pmSr0#nk^I)dPi2`RX4TmX#>*6g#kpq&~VWst}wR*VpO0IZNP zF;VGU9z3}H<0zBRk(iS0@mvlST~Y{-LN77#aM7Zw7%Ig#fk6u@q(aky7gQN>nW}hHm=6q?vfd1?@1DCDPM&XJY+X7poc>&&cMp&>^L}dsS z+1*Td@*tx=O@u9M+Nec+h`deHU@#u&3}N^d$6sRI3Q9C%Ri@MeZ>E=0ed;nJTzn!W zaf(yjU3o6DJu0q156(bolocbjY{_UB73K&t*LyUCqX zR;o-IhRkv5+&{h67?GNdx~b9QQ8xzND$bQ2)5qNs+Ly%^vdUD&gSr%Hg?;BFh-hy? zDYtQET7xBVGZxz2s-v|O4FC(o@!$`;tVWN>YP4t*s`a{6ibK-%k@7iOXr)mss`c7c z^^mH@aq*pOkhSCT#VSYS+^=P?jBAz90>l)Hw^M2}l$okXh-cFhCm+CSE0M^8PYIq8 z-}%mon#pC~07m86=)WFPg9O$wA@ALZiq?#pMxbnD%+ktYk|Am{!rH7!rUhPPE>ogG zjaIulA!Vp&W%vjUTNT#|&uP#G#>Cn~;3*&AYs+)Vyi@v$L*hpLu!_&_;Dszi-X(>L)(jf%;?*v!MkPj38ER3tb+Og#|{+3y(!sx)Y~c|>z-`i;|3_g#LdQ}o*z$%!HSZIZK=fFdOhti z$YWvlF~ETa!}Ql{-SP`zH3xOh?zzS~j>n^-Bre+8-4M2b-Ge5)u7#?^di`0!v5+Qw zrAE#o)`c8GFZB?1`Lk^7(}NMl>G+^oX3Bu&%8Wu zurAR2njSn1aC8{Kut@BkLY?w&dj`yetvV8=@9 zy9vCBQne--tLm&7PoB!ZMc!;fpE$OgVVIunz}e^Pf;+px2&=m6evT4!Be22JbVzq3 zk*N^LvmQ1AHuPbqQ%|`!G>==NIi|K(l{;1BDq1^AzbdeeFqqNL0`lBBi6aw` znN=QhweIz3Zw#;Y_?u|QR}8^oGj=}Y$_9h6ZPza2+9WX}nt!l(uT{{l@ zM#{gxkm3%ztIuN?TGU#&(HE%50B7Mzh9q&U3LpD7`}%0W$y2{?Xz35dA{Y||p5#jy zRtDSKu-(>@!iHS`Dug15WMWbR$HQG2V{?S|eaEk!>{daq-z^7pEqr5xOr|73U5 zmh`%&GLXC1vG6Lso?QazpEF$d&^XHtTG!6;xp5ND>aP|u7&mV|PnAqpU1Abwrki1t z_<18Lu5lzzt2+I3JeFII?#L9JSR^Vv0DH2;V!g3T{gQx-KZi=_{WnuOtov{z>?98Q z9w13fDUwFNKqC4SP)?OB<$wtjBAj8xiKTz(n|CTk7S@1{MJDuq*j- z$4ZBoQ!)~-hAK=hPk=X(jOS9A$TK}ATQZIk=j^7uOZO$md1tf}CfKj1a}g znJcF6LO3stKvJKt8|h=@rOj%A<4;q?C5|JdjpYhXj0xufCubY=YU~JbIL@Pr4^u*l z^dAvqZ>0Y`U(gfE`9-F`cu3wY0#yjWTe>n<+`86#5{bKcu!z_h8Qd%FM+H)O;_xCp zb(MzXHB!*#bz1TI58g$5tMsU!H2&G_S6vI^{@(A-mudr;VE z6#cl;{NgRo4fOx&`DC{O#jRDW9zzl@(W~Z?A`mhcG92m zc3`-TEtPBT?W98PFo+5?t!Bw|!zj9Sd|k->h*`mynlY9BjX6KyGNn%Ur|rsQ zpe6jGSwJru5N(a}BG~u!`fc5pHAt&Z_{nR&xw_<11Y=KH0>M=1bd*+wUU1Cb!$9Es zjOGP3ZgH2uRh(5oT`v+;wJ1SafEio9Qh7Yujzy48)xZ#)WyjC+AF8`gh@V74QKx(57d#;}Rq;p{>Ycd<8vmIfl^phXOE z@c`v|r$imtV}yQTPRPgy=3)+8$xkimW8UvOk^DeUg*vLE{rz(CYKEL8z)}C=9P>xT zlF-SZSG25P36As}*P#)a9aB~^naHM0=++8XZttR|A0G4MG(>5`!wfMYfs0%nl3hJ{ zP~6+dmIsHtB)xveCIqN4`ZPVu;f>@$r6b@EcZ;N6lrD)Ttz^ zl;br``{SyaYkJhwx2b6yQ|25~So};B3-g(^9)s6S!R0C*f?8S<}kWSx3hHJ%QLo$(A3y0B)cg_=A1w} z5y(25TaZ&L{Bk0H)QMc{E2f%fwH0H{f-Vb~d|pRrUh7X? z`cFmspF6ONz%jJIN{i4K^>B4Lwn3H4S`KhL7;cSs0ERW-u;riE+-uMVb+*@V9iX2B z^aDk++wZJY%waE=Alj8=Botw~__MI_;E8LpL$FMILO>X?qXu#5x4tCyVW=D~s zh7!_Mtt*a-jBr#BL{BOr`{JogUTwkMG*Q!3?uDzZ)6x{Sg@;(Nq0JzQOtH|YQ`t}l^~d{tLZ|6`Wspa6FvGO1S?gims=e%4)gZ7 zc7qpNkUdBbh`Ixr?nQ01v=V^07}jV_rl$wF0CbWlU5p$$&c`xno4?M27l$;QdvVWf zvyH+MyNS8PpS}W4ey|yqPdrf%BfG0FTGxPX%7-J?9=QdKo~Ynh+t!Mq-XprX0m^l5 z#_QH9h_nVq@1`?bk2`QEg;4s#X@%+-q##ZJUeMA@LpUyi^M#BnaGy zt0U-Dd)ltS4+5M6nvT2;anAx!w9JDJ2OQ>sTM%z#Wu|!{pjU{44=+J;OB;r`b5oBT z^nutjpr87v=9tP|X~Z;LvLefD=-noJw5apI$_yj%VC;oTjX&?*%BVMiSn87h47Vkq zp&;}Y9>l727~U9XT0+1sQS2+PoM;}i&oHXeoj7UY!J*i}xa+XZ@hM9b67}QR&rBS! zJakI3B(>j3$x*0j@R(4v{;sx6vhBBBlBA1$I-zEklX0$8?kllA`L#y$N9l^wmVj34 zRM@HDc0%wW*^dTiXO>y=!jzkZ2XL}iXCsZCVrHUc544a$#%<`y<8w8+3PUqnvjGM6 z!meePPJ5TaBdO9YGNhKA-3`u$-E5B64Tf8$iN`G4xek0XWwK#?p7py zu)xZt(s;_^yb4ISIq=%^DN>Txu~p5acMrLF~ zHZ!VpOJQDHmy@&eI58|ug&>_e>uy1(wj!;w84)I{nSHAWJtZsd0eoAbZ|2@jtjT|b z^LRwsSd^lqSajq96imHO7hT)uuUHS9d->lvc z&r}}AAiKe9&h)A?dgkEm2DAZAzvVu*%_ z(g$+`vCchV!SzGH&dE4qy1;3c&nyc4A*@%fm^wWm{@i!e1$KprpMtane;~=-=M^OR zLcXm?TtmKL=9=d9MxCp$F8PPGt{h!cJfiuGb_X)7^vu}!M*$ApX>)w1oRv|tnhCLJyuDo%D?Z$f6w2l`e{*2mP zikk%=?5#nC!?f#@cW(Y*f!@kzef>WK2hPupouNI$M>kI|KA&6yDgGm8KeuH<#?vBY zyJb0FpqbKZkxSlPm?CP?SzfS}Cc2Es>``NUx*%`O>NCOy(ecsKZdry>c!^g%WY`a zh>w|vWHgM+@nyKG`1FOjt!GWliJRw^Esr@!@OGe$#mRW5QWH^vA1yPOo(Lz!j`Iqr ze1Y(q4m4-CQDB`%?@g{t;YNSI=ZK!niJtI;kje<>1B%#KnV2?dtdL7gBWBGg6EH1| zU^r*4K4EVMOTtP1{K04~(ydAELMW1Hm44(m6a0%2v(2=aGww(4o-u^c2~c3PJFLe>Tb%%&DvfVxD2Iv2CaFOu=QGkd zt2TlDB}|d3+w610b$3>i*@m5??XY7_t4y-~+$vDCb7i<(+Pf>vSW$>{{= z1*?tU9BE55*oi0oK$kMjCW6DMmRXldz2=Z9BICYCPM19M`qBnWd_bt{++;&w`C$Wk z(VLiBX{yqJ$JVv(G=S}npK03!THM1!lwYE9*Uon7V(Dry8*#dT#Hl1f7$a$O5%ge! z;o5NV^I%>MZeC&uQ4i53jL5OU7_xGX@6R#GwFJM*31OyQVVL(DzHI+4L+@m50IMI_ z{!Jx-um?Q!#=7rMZSe1RFU{Vy{M@Sm(|2&qA$wqkEhzIFy}Fbw=(M}F9d18}rkf21 zoF1IZ!>3-~cmCt;r-7t*Adjf4z^50HYlTln=WBTNNuCwS%^~tzUmNzVsneHQ#bAMc z^*aj1D1kBIcMcmAe`vNBp_Ukd0s6hE2J2^M8w~%zjRE(1zIW4>xSk;F54HK@+Ioza zt7Y$ZxJNSoEZ?cG-ivqJ+@Y;Ku=lvm^e-u^0Y^r}+z`mnxZjyURHAFk?W(#bj>wnVc16LdfaEI%QiCT9e=8tmY zfWopT=!5$(f6ZbqZDZqD!f~d_&AXDlVT4k%xZnjZj!iRZu7+d=jLn*DM2yU8DUT?g z*pwTWxx~&hnduV_h_jsbUmbhP&NJCPBJn7krvE;N8w~6313Nc`jibV?GM|$66;2C; zSOHTWsWMV9+K%Q1e;5ux1&KL z>)z6^@9N_py4B749u%GRQGMU!Qp_!=vv=GY-dwg$YU<45`Mi(~OB9hE|o zbe(x{t@f*hQ|gN#xF__CgkNINp@iZrp>1DfXuUa-hMGNwqdp97x2rb*r48SvRCKm?LzuxmmS_N5jo;+f`$SKJ5zYq!Z|P zX^k6;K84wd9!h*~BV#`Ftvqa>~JJJboOVAMOgieNOqd(mW`h1BA zaxvsR#9)Is#GpE9zz0T*AbsdU`vFYRrja|e3eko?jYw(Gjh7`0wl3|&#_%CUmKpXR z2H`w}YvR+EJEn`ekY&g{P%2_t+yTF49+_U-H2`C<2FBOEY^k&knBetaN#-zQB#se# zW=nO}2V{Re+;WmHFnPynMx3dZCGTteBFGXiTH0Ldv+84K!4!^zOi8pjIpqJ`U0=N? zrJRVZIPCN4A-g>$f+lLa`wLIUij(x+u~9AOY`Y?eA7w2OCDEN>vsRkfuDWf+Fw*|y zG?khzglVA_lW1tmnvt1C17!kwBQI=ZhT3RIG7Lxu7Bj+@MVTv5o(%YHL{5u{rpQ1I zC@%{IXM)Ha)P*c~YgL*IrrSkrQ=RV@F(PUgi`r%?FxYF!Z?6y)t7x>KPgFHmLZM|_ z6?UkYX+c`pgdc06!z^AWTydjnSU1GsO;G%yfN6vC;{tpwl2P?{!g8p0d&C7RYQmDD zs7r8CGYEo}wi1P|;3jg8J=u%2^eKKla>F1sY46D~NR9j~-`~Mm`Q#sZPn;`sPL}cn z1y8N{*anJHUHKRo_d7v;PCjvtLZO$JxTw>(&n4A#opwU5h#yV#T(J9&GJrD-b+_b6dDFF=53YxtWG z8bbc=3JClSB5G6@Be24e)aZ_<5kVE|o6-ud;MuM9GA;g3m_ZbW2oGdGDnFRk@KREM z`bm}oZie1D{z*M2Bk^MGVHBY99tbQtps@s@tXFD!@G_-)nO9Z(Xw1W&Ogo9Cgkdp& zx=fiGU%tnV39<`aB8hrc&uUO)oUz@*O7!l8&dr90p>i9yRf@$HCo};W>5;Mftq@ov-YgjWYiLPabKxg;`9orGAYB|f+I z30BN*>9@&a^h>=NYD4HQ(eo)6oq2Ul#1L6S=-LN7A1HgxNv{12D{-0Jrne}vzKOEr zLcJkRwA=l#615(IuZtC`y#=S;;v70{!Vd{7k*8T)Ut`SZj3L*Xh2nq$-f@~I2*{xX z<>0Y93DM)+Rv)p|JPuhq_zs~l0t4-U1HgpjSTHOgF7U8Ax2DE3IPNNpuJ`2gz2M;I z$K}iVz}nq>8yxsWFfN>V1r3NrdV*|s4Mrzx0j1C2b|_o@db4H$;0zEbB^`$FXC`_cyxo#bM03bB>g;PH zj}xT}HYeTATCZq4g3%nptSF5}T6tMN`&LPm<2gUX=M|IGh6h|%MI0!)9$F}R)Mf4p zO#<}BWWB_tWk&V2bsvu*OhR39f@Z}jygDwYX713&|J>U(bBXm0$khk)dY0BYX6<<; zvzo53|LL?Xn-4wq(`sR>+PGwI7Ga`N!tSwxI|&?wJdgG^%ajUZ`HkY%D#R_{Hqnf5 zdAUQPYBc?=!)ccR8LC7QiC{s3B=<2YVgb{eQpzfZ_EC*HXy!);pp8pfDC;_OD??*Y z8E>19YqqIUC53246*~eHb*SQwK`G;@r-4feOKajGJix$PyciORh3YQO9eE37Q*-0H zCBVV^(PpQxf0$#3HA97BD`JKg-Dot=!CCW+wsp6c%5ik^+{4hd_y78M^r}!L7tVAd z=0xS-Op$6^p=w*PlsdFm>_`0y{a9oik}?o?>F??~0Klgw|Nij7xrqYH>uJ)uZG=Ky~X6&Z#Tq7;Vm{ zj*%jqLm`}7VKE_9vHM&ZTw*9kKM~nM*WI5iq6_NH<)I!8^9tsL5z74_AGKFXZDPVF^-a> z&vRU!cZP!kco!En07D5EG*`RhJ+T)W-^O_Yh6Fb$e?k2*asIa(=Y&HDG?C#X9)!&D zL>W9jM^-z{ z@%e$|CaS-j>i$EMRJ`B3Y^xEZENeFR&~DQ)hN#7tJOx1)jboa%E8Il@y{koGU+7@# z%eq@Bm`1(jBc|_((N&0Vrtni=gI18@QcEx$kPWL|U8dGsf=qixN#&|ef>x^#`nc3@ zCyHt77gZiiUE(D|T4~LdpLfsl(Pz@@Cfe%i*+SwGwIA=h06DxW& zgaV*eW_QRC`YnfabA=ITK(~E{2g-K_D|GfklCgR~v7Ovw+E5!EywzUvsu`Ew%zm5) ziX)rB9z>3EtjF9QYZ7uVle*s{{~l_23tWJ~7xz(tsYvrv+Rw(N*VdIdfq>{lE#5Bk z100g`k7$E|g47%;s-ro!^b>u0UYTq=npxr$15J{9Ux?^Iu?`?)BI6gTyTZL|+`Vgm z(d|Hd^&`oJgkMB9CGA37@;hNUXA1)UnfD26tcjE-^xDjjT5c%r0U~ygdA_J8ymSf% zpzs!1yLriwXR%hX*#4J45R;;-?Qq@`Ow`D2ZV zB-CoH*l>g=q0l=7^5qH0IiHjd^#vn64?(<}d_oBg*-fBdqa9_7I<8!iv`ikkKtCkX z;hCM)C#ENE!>*n2Rm{ZMj{`i#WcR+R&baa2;Nr7@StX>qN2`f40gxfySQuS9%A+@hKGBcsWDG(A?u7iZvp+#rAEE zt^&Wr;xZJDUCmdTx2$)IBaz1hpq}A6f9!q(aV5&2H(LX$={~;+na|}P zI)Q^p>OqX6UAL$~e9Jf!_ODD7_vN&J7pS+UsSj5SUOn$0@G~`e83N!$0+l0UQ_U0C zi|asBaVPo`M>|iH_X31p@B@tZ;jfzpS<^^w(I0xZbpgJAKZ!h_!QN&yeWQrP=}F%U zUg%+g^pArulzeh2lEjyIO=gdchQwm{?4}_K!-K~{z9!@C8iZ@0ida>!VcAOtEL6mi z*=s<-bkAubVxU5CmK|OV>M@sP*-5EEa+=eUb(9;&JL#orm|aG-)E^lhT_e}vylcnm zI!7*sIfnQB8|_tOTlhR=lfDMJWtdjHzL?}bb3ZtSOeX59-$8h6WOFm0NxL1un5iCW z_VNb&lb&&NyI0M%)OUk`ETo?>M)eF=ol!XtL2+67Uu64tsL}(hp3~EN!8DZP3pw82 zGHiAa`FZj?qK&uu+?^oM?c@SMdBFVwQr3`x#>7Pu6$Z=vP6MjW_2ONB=!?_6j1M@N z^CZKLjwj018qHZZKrM`&X};j8d*Lxfd!u<^+fEXVhMDJM<_={Rn_O^dEll?|ZM+{K7dT$h19=t21~kLg~$e!1+o|yZfSK?^fK0p;*+o zm1csy!`oF=;+T8+`X|;zJ4{gemj1^NA(Q`Pw)%eoZvFd(dQwqKXMmB7={LXB)JfUZ z&h8%%|8>j0M0M?(*M`WK)x^&9OX^DScQP`e6oY($ZWJOJn(|LDwCc#g1Hc~biFzzv z^@ZvO(Pn~0xyLrhGv#0v4qNyk*=`>X4-1d;-^stPOIHK}K(u>O@Lal$hCA(>f3({I zxnMYynjBzSADl*np-fTGQ0~alF{{*VHC|)zs2;I~_3&9$DRJb(TqJNbu%bOQ#D}N{ zcFTFBS1%NY$EfJ2+&tFY6PqW=^iRj+ z66E8-9{oOwproePs9fl2GOeygV6QXfu+>7A+0s&pBxqxvHH~{>nrl=nL~|?aA4`0* zf6|z^Vv@060#*_Z1rPcKM2ULuGfgrzt9X1H`pQA|9=fPPnF;Ng5}m3p%?&7Bs3jK9PPxo{Bmm$(>?9iVp|}eG9UzHeF!~ zZLUc%#`N-rZFCB8zVhl-!6Y}7&v%u@!9RozB-?YA?&X)-AdBxyap{V*Ol-fz{U{CJ zC-{e3BvVDe-trp;umt*lE$)8@0{rJx$bSO@{0lo6qdX=*z=(=FC!C3x-*nESj8H-g z6fy`j_*0B9MJ&L}9jB5FTK<6ZT2GP|8G=6`PM9}My0U~^UY!YV-Fk^i7GQIDsP1X6cEXrdbAmHI zn@dCaV&0G87jW za%*1i5FQPP&5RJIj@E2~G49jZBRVd?(x15(0**U-rd=!Mr#vUR5)+9c7}%PUNoa1Z~^d=dDMUZDR$%lhw6{ol|B(*Fj+DgRgStFhZgTMb)8-a^YN zyJYk>Iia-Fu}p=cq)u7l)7T{bLyHk;^ZO>U8+^ zInKF2&V*lrH)QTTQ(@U&JnBNI6v_|X5%;|Ce4Ob|+kl|~Z`x@t`3>le#PS^p-G_IA zjc!O~r%%|A$zE4Sgf2LCzT?9iQ0Slf{@B zQ@+q9(!@ZOo_nI;M?uAgz+4ELLw?BSRvQueM}&;aIWv_o_iePwtr6vv>q-(K@sb?BKC2NfiQ zQ(?B!1;bW10IN7kGlS@SpyH8x$DHvDby25?c7R`OFGuNPsMg`I%yyZSBSIs@^uAu2 z!6CPRWx{Yr*>#t>W_s%v2V^8WEapbJw*No(K#&LxRP*1(^AFSc{~qo3pSkV-+v54x zwnt4zWlbFQb020{To;%=K3-57s#z@ZH)%*RD-@IBIi@gUJ&diiiB15vmXS$@Aj4eG zbQmv_=c$arYS>?glO~oApbtJ@JMUQ1wP~iD#f9jp+zr0B9Q!H1j?as@Jby68*b73h z`cd*e^07n5a9Qe*3C-KD6F(r@FvLNWTmz_WOUS}Gt%Ek!T213CEbk1&hUZa)Hx$34 z0#|k%ARpXb3Sc;4+2eMjVYc6@%F@8vX~+{gfxEoN$~T8JqN$~X>DYDoi>=&nb_ZArU~J9ojHt;)-k$AOtB z|59c8C`Q1S@+Up*r<0$p)h{&EOmN9%aG@L!vTmrjF0?ajTal8Tfz2tx)OQx>MA{AQ zu3ze~%tZe%ST~%0Os=4rI53iDTEbKmG#?+G&=zM`yX*+&x0Wa&Uat{O9q;G}wH$i1 z8`3ZTX*&eARGmzOq3Y{B#M&ZPqUuGOHOLh2&J5G$LqrASPH(20L#b1Np4CjN@+XCk zteP|HW`b4t{q>V5*3ImgmH5a#xj!>O?E!dc0tXOKS1?8OcRt7xl_u%pmon>Pa$A)p z7uQ!J^RwG|<2BlRHJz38-}12+-V0X?8yn%?4M`EP)$l}2-Zx{LVe9z4FA!!dxy1l- z%(B@G+#=q&m;&Z0#Z}5IPg5aN+j|2{p79_wrf4E0j^)l6A*8E13P9o?=UG({($Hbg zn^NLUv0|YRC?q9OQQ4i?@D7__c=jv-7{n&~qWemS1p)A04S}e@HLB{r3y#Q3ag@D- z7FLhPW@d9GyEHr=7E1S>=h&m_%eMA;4zR{Tin*>mOWEi+8N+YNabJE81 zhI67=7MFb84sW&Y4pr*SiDRs4$mZ|gcMh-Xf-_Rx*(<*}p-A}gW`a;gowrBlBlL72 zgFK3Y+_h~KViBOsdhq3vO@`4S|5 z_fHV1Wd&t^<@cu95&A!MM2Y{nwNm-NoeG7FjlUOEOCw90Zyu?rsg0>Qz~x`Z!fK5O zZyX7lWTo_Q z(~9{JPa6(tMT-4O7K;TxXPs2?*A=(@fi`u<5_761j^cdsKC+$;bM6lROrDnb3%v0L zY&>g#)=CHs@uvf_RcGLn%p<7}2|ZtvrO&%2Q~N0^>kL^`0G!qRfjHtR8JW;%cd+Km z`}}B1v~~R-w7xuVUV=kfE$dP|6gzhu~eCVU6XpU(KXf$Fo z#nptiitW&Fbi6kTJg4LGpx?5W$bdTJ`g zLt^KaZb5Re5eeSFz*tff-ObBd+x3o*0ehboI(3|g&Tv)$fZ zcj=7=-Rjr)qPsFfyw+2ieo=LhZHwzXuO7>W)n*g45Z5M3{2pMWMoqj%_>uzkzVrgEJmK2a34wFkweUzf66L{D&udaHN6qS;hQT$Hv1*q zf$VsnU*5Hxkvs|~ckQ7%4uS(hK7oI|w^K?00^+dmR!|Ka+V$x?EBGCK-%-MKHu0=u#n0Vs|tUZ7jte&C#Dt63qKaONSf_Bm-KO@!r z{!lY8J>dNEo0z{!_sS^WVtIi0^*K79m;TD4;tx2jmHmimeB;rdxkmW)8KHq1{khdz z6vS7_CYA5kMOTIe{+lIex3;?PIDWZNO;343z=uuS@3=xY3t)8%7OcZF9+ORfqRw<7 zAWd3ydU($~#tsKB*E0B0A@V?O{D-Zw+fL7VVw<^SGW&A>rMm%kPCy4qxrU%*!468f z-L9FfepnfAFInRQJFhMWZ9=7vW%{m?7bJU8b?>*PLM+RKKG>?4SM_|!$_%x6F5ES{ za%)a%wP+1d&kA#`5W;vP1LYKLTD}ScD)WPei-(*$YlgJDZ0ZDg#xP}$NK<4`R< ztEWTC6cs#_eJ-9{;0bS{_gZ?#7FrT@g8*ki|8q#M-uf zfn%*c>seQ$r&w6E1^%oX!`xyd4R&pq)>?(~tnn{v&IaWa_Jf5z@F|I69=jU}Y&2=I z9P&o__Kd`0!A}U?uC6RvC<>dR!H8h+ly|h% zs~X~dw^yzDIKSqmf~-8|{K_Z-zD%Thf5cYdK3h@KV+~oH7`}*oG0F(BCbC?Sw@G4Q zjG3FJE5l?(({GAzxWx$3E*moi33Fb)(hfw!r6Lx2SPrW@yDJoNnj|~}akeCq8@zXT zF}v_X-QVC;X)n#Z&Jegak(=qLaDI7}n`xMEuVZOmkfCoDzQmjU42c(aZm(VLDH4AB zQy9ukU0BS~%*fuayYS(G0-0kernR?t#oYI)iRwWL#G=80W5gUy3gU1mG(O=0_Ii8} z;>eKW{uts=q?stDnXv5Rk?8QfXOx&1^6$cL zKPL){r>R1zq*vn-%XHX^TvU=#{F3c@2yOYyKF&1JhR*dP z?prz_{xCZK{&VRJC2XxB)QS-cXic0?qm#X|RcVCTUCvMdN;=e!%$rCwC8+g{@KQ zo4MEWA9JV_|MTi?3UD&E_=h6$-=Ncfd+~oJar^_m_unVvYBfFkSw&1g`4dV*w9udo z=f4Q5lu34Wnd#*ig%f5KQGgvI_mXVEv{@sa-Vb;b6oz+*&2&z=&TEM0qUbB2UE*ao5U&FO1B@HLu2$suj$J!)2~I!Qd<{8t zc;~Ix@2lN54ucb%0o3Q*BD^+hLIABk=7Ij=qhCk2z7uDxE!=uxJ1>^-e8@7m@6&D< z*GvOzMlN+TCMBxo@s;{XEX8nZ2Mpdh;7{(8p(2S@J6gX~IDB=^M})OZ5`bXEP12~U z6jRN*1}LqD@f_aldMS2$cpTy(tX?rmF}^;b>PJ?Uu0Lj23WKr33L#FS|03BvhA zDh?lfqU@Jc>i`1sE*uO-9uDNu0% zX>|%hZ&L|~@X)5@Kt=N5?;+*TR2zvC)sN(06(Ew)LHorw)`FJb_6Qm zNhIKX)B=`JJ*{5Qi#*d1dVZ30K8#8+N~8=^Pk-59z%|n}@)3LpZguQlp?o_!n^X%7 zOIjYch$4{rauB8GpQrRxE~F^UZ>cZof5gfByTl{?|E;PO?37$hojg@dJzV~u;z6oa zW$eGF6`#Y7d*p22j622tO4gs85V)j+C6Mst)M}BGWNPqTw%KY8DFl6P*v|^OoP_ug zem?}Dna)BaL}<`vCcMmgGVG7CZZ2D|47!0mKug1U?NF75{*bNrUjU;!jP&cloP`Ka zt4mRfV4;j(kT}xn8iatj*SeE-xkSbLR|u!@lkA_$rx~^sc9YV!s!{N{CqRU>fwvGpUoR-E;J-n4(h_On!=DG=5i^e>-WPg@6L*r zD58|#*c-VNeSlzg*@R3hC#_+sr)4Zpomf9Ty}zof~j@g z9|ND-WV$P;3PN66$=B zte`XwAtWra^D@*Rr;?y1d_MC~L)0!msHzEZ7a0z> z96!6k54pE8c(=&yn(=XUxLQ1GI_c|Mb6y00-yqFDgBIOjae)vRb|2}1u-B$>f!`yO zUlfVfIz&93TcR76M0Z73vJ6wav$@z^ZZL#)#*!zP*2vFj{c2HH1Z3m5z{hUG##&>A z1)gQJ4qLgpf>+iWt&1lrIRZc%7+dQ$}fBb9)!`4k1{G?$vG(_fk%i&$R!VBmzCs} z(w?5$59VLF=|k8Kb6QVwflf-LDni(B9`pA%cb_8v&IbEtl_J#V43qK78-pnnds6>l zvCNfer2YeAxmc{FQCGfQ5~Kk;<~qmzAs6bw-Z~Ob$sKBlS)JbEF~?g0{RC30{p}>+ zyEIp)~;A^ z*3>quHyJ0r`&`U-9OJUJ^-Krr7-QBC-JI|bD7VPW$|)S?}D?A9Johjk8pTcp@7 zY#-wH_iK-LR6=Nan7ph@>ZLS?ZVsu>w_tf85#uF2)peAPIzF73?cW#YC5BO*8@T}?W=jAr$BG>I4874&$4$UX< zQk3M}a(-1tB~oQs60br`+=`-+v{h|4M@q?-x5eU6e~X`yJerD*7*DGE`^<4ckz}+q zl+0CM3XM$BVk)MZ9~?#j9k?5s?VQm@MxzG0ah{_LKwbX#TA05G)Z)~OSm!KESm6)+ z1AI%RV2w?Z`VRSr$0`bbV98F8nvC)Mtz;eEZxqIT*=7XeV8SRvlXi;@kYyLm<3uqaal}3v z#460NDTg=PgEgbXHq9|&fyggo;wiJ89W;gf`I9|yCcY|wg@C#}+k|6{^pZpdU)Iet z4>yIfj){=bOTh~`%aR1`;28u&2eu|~EUhN2ZF$%s*@HR0YzN45@c2sBi@#qDn}tn{C{~Jgn}W zudPi3eW3MSRuK-7ylJ-AzFYBCv4Rj%U08En80%!i=0rH1Q1(n+2Bs)|f+ZNC73fh>5 zs&3;LWb2car?82Q!fXUA+wj}B=?p8pV8^3klKUbM8eu|q|Mk%n3f+$>YBEIa@D$RJ z@9ileF7bv{%N$7)$c%9J#Rw- zhpfI!=br5eMr3JFbZJIpTL z>4uY#E;|i~gt;w8@L^Ubs~`yd4*H>O%o|}E$NdxeqU$`hN6bWolEfL~Q1_wVRf-iX zq!sN_NOT>_5ldb2BA^hRJ4q%B3;0iGyzyqd$mE4B#Q}W|{^W5jR268xyXw_T$D`qZ z>SO#{es`Z5ZFxHAVylakO%_@o#?;{qriY$L<@p2B8Tj;qI>RXJ+ju?6iCi~ay zFk+Hh{LZ1frbv^5X5K1JARhDHBCHOiw+$%wuCb)4Yn_@TIrlr(zsa-8n*LAq>Y7t91`-LcEIPAl1w#C3R6K7XI{m1DCUcIIxz; z3kQ%8^y$Aqs2*_a(s{B6y3z{nM@KiJ(_CQ(6 zzR=;( z8MIUn!PW{rc0kp%G4niXblcb@H5H23OXUy0*P^;rt$L-^popaeMEVc%74oJ>vqp6s zrJL2Kw;P=`2V>@Rsk+>2zHS<}r}fsOj5m&GkLeAPPp@OWALBPPG-Nqr_L!zo5rgGqk3UY7;-vwkD5yNnV=JPwf9B-qO95BHp^y%?8;@ zlAYUH%>Gj`L|7tj@V^L0Za9WgO(DR|%;1U}n5Q5B9(Y$B-$05`=`UinN(K z=%GZhZcfUfn6HJlFyAB{pR`b64AvX3Y<`@y9d>M|#P8Ogq{uP%!BsX}cu#mdKHQxmP-UP5^>< z9Si1(LWH!Fhq}~IOIJsejn=6WU_l?8gogUJv7CC|6Y(>WS-eELQoJO~l@M6LU>KiP ztl6xMDt+`+lL$Nd-Yk^W$ll*t@>-fU7ligSJwd35_OUY#h8`j?T$gUK49xflY?vz7|z{#Y@=0IZZ`a^ME3M zg;Af8?mT>RxwJSkrHyY-y>z1cCCNT>gcXO1erb=xu^!nHj6Ur~8s>4F^>;*sORiSm zZhX527iuhBm_I%APE7>JO$-RkIICYippm$`A*WxkA>jL+e{;i#*pdU{b~Nm4p=;RlmW-Oc07D`Zo`+Y&XIkZsjC7?1R#Se~#x zs+=v<(ZAL3uaj~m7j>TVEBB_jQZ`<;I2SKeae^Mpctr?Y$sn9;OmrD5b1fsG0@x@^ zqZ5!&OOtLXo9Nr>Oj}LbZ-xOH6QOSvD>W8|N4GNU4$r91NT1sU=1O87M!756Jl{CfTT`8xIhnGx3v@CHJeRYd~D{*8#rC$~)-)*R8} z^yAX2$(K2g8yQ}upTb%H*QAj=36bSMAfx#DWj%0o3?ECRRjyn}6mN|kVAc#}g5maL z4+^-kEIMXj$IyWbmmiu3Zt#0meo8E#8m?g7K_r?YAb)Ru31;tv-46*l@gL5;RL=Q| zn*QW=REHsFvJ_P!oh?7d2P0Wk)&m-MjT^!=EMv+san)ibIx(=AubDLiqzqT3=vq@+ z^uw0fRwATZOf$0})l8@h6ZO$4e)Z0P8Xvr;a6wl@01Z^a?lLQetX)J}U=^+pCALOV z%t{G|hZG+PJIAw#rp3cU8ObWid61-qlwN|K2Q!ADLod)#?xb!d_NtX{OenW9Tvx++ z+dtGIK;A@_uH|b4b5gQCLxBMW2-nABA(@qHWkR`YrrDfq$+=x++|$z&+Xw9>+D+3>?4lu2c8N<>sAgLA9OgHT^!8_=q$Jql}}q zjP9|=+dM%g0VDZt9km^9%vBQ4&f9Bn6@{>~I)^S?qV+$qzw3qBJM>B?H$3qS4-;@_ z=MxE+B0|S01j|xE8+5tCIx)h85Ht}?8g`{ItAHh85UB=Gj1U21P546p5yD;7q|Jxy%>}{LbJdLR{c|I$Bialy5RZ6Typ13eZ!@ji zfa96aR!ig+P-l)DcnQ3WO5Aw}P)7h_CHWtUc^}Lkv8q;YNoxHfRVs zY6%{cVU^BS_}XY z?>vlJQYgLfH#ZjZ8TlE)-2ihDo@!>o?sY2Qtyt`$qA!3*Hg7g*`&7|zlvVF?bvn4! z{qb{~{PE5eBircO4I6C1O?7YQC(Icq=l%`^HnZ!>zFv4RjoZrM4jc>z=lN~TaK8!~ z=hU`E(7n}oQwLB`*X;tcK;0>$RFM2e-6Y6{f6$5bNhC8DS{X;s=H`-C__Tkp*j4DF zUW@kfMbVk6ROLJur=z9}N7{Ur+N9U~JTug?S+i90DJJIWW|`4dx^+L(!y#w?Z@wM| znPgha1S8`9TCVxW26CL}PPdoc5&CSiHY=>-tb-NxNbUAuX^kgLm+yk=iac|TP1aWy zXOYE4JF((J*9x>HwX0}hOR0j8C|`-#0-L85vOhUwCW!szy|sMIqw&^aIWWWQQwsT& z+N;_T;`1KuN2&YS{KZ$fsMg%e7wODw0;7uCv%Vsn(PN8*dAtYAYU3JIFC6*R5GD<< zvlt?VY=PL;&fD@}Axo9hrQ`MRt-W}~uv0Ivd~h@OeU0u`eZ4#Orky{~pyF*t_K(Eb zM2KnPQA6pz>4c3WX&I6tZ$Zp@tZ8$u?yHuiC&xo~kJL7Y{skyITY}lXJaww^rBI! z+Bcjk#(v$F2uO*qC+T^-h~cB{>XZ3K5_~4dB1(-$%C#a{?lr-W1C?}gE#x0pyO>^< zFE%lsrH8t%!7;)F`E*KbKi?900SFN1cXvP)!-RZ(3eyQ2K<}l1j#!A!x$|azLKJSr zu2f29=Uj;(0&?@+CV#^^v9>EDJDkLU1c~dNB3BNM9VmVa%K$p7W7(qjF|TY1X15WI zl-xZ+dKd82B6st8pMj#@Y*E=@cQhim#k=n&{qHBD-ho+fp8nujd9~Sh!$TwqhA^$k zNAV~`3#7eBv8Gcxn1s8>0-l6%PX_*}N*CM1k9jyfb(PX6O>~vSJT0FcMRG zKb8ac{kk>9lL`#Q{yLGx>>s1&B8E=OGwZyAq#d~GWWlM-i3^WD%7SXNh(&rzsJfoV z7XS&V%N76yp1&d^u7gsNKC7y3A0zOa`C7w|fjWlEDx+q=Kz;@Qe8`n|8Ox56y`JPuM6k_7|r&4&vT^8TMf^7z4+>-(Bm$Ck{@RD z2#kv&DDzf7FYBZix&^+}pbmMnM$8)3wsp;hU(LD*{vu0ALLa^p`m(;Dalr@|nLP=t zT2yBLs(HUl}ej?x>*U)#7>I{8VXZ`Xqr;y>rI z|8_q3{!z}6wXt=wl`^t+`nP4wujgR&|E~Rq@gct@gZ|w#75F?8SD6n;!omUpz88ds zSQux9JE16aluU}SgQljJY54NMd%L?(hS=*EXB)>TgQK@#SU~EvhJj;i>S=Pq7(3hh z>!)qV2L5fypOvPYUg1pLO!CS+n*h)HMG{J<2~qeZ&B6mCPPCC65@2isq-Ds!WfWiW zU9=WNt@0SzPip>`@#k6}JSR`?8!rA6O$#(fPPm{rg(=Nk5nnk1k_fLYz*q(@d+SA0 zN`j-rRXPM6!APJ+X1#C(A3*(e1}z}JNuD^%C-$5)>S;7HB2=-Gr zsWGl24%0s~7;35?tPb7-4=eze122h6HE$)#2okJRyi(b~Lg7qn@p24!st0Lm{kH&h zD=TlIVA%VQFr65j_&k$_Se!Ub!h^D`%dAVAHjgf>muwUtu3y*Kmqc^{tAJ74e|`wt zYMJ6dTm->7@FNDKpy>032)=U8biHBpU0H)uupwX3oCg?WKAD zxcxU-jj{>T{&f#jnRD5TPI4MNe85b=MG8Dj)>aFk_+~Fc=9ASo(a2N5X?Hona$0Lc*TmYgJ}I zTQS9_XlrjpEjwrrX-2Q=y|zt|JTw%vg&*DT zkqlDg?Ev!0lWHnv3 z+<6J^MK}pA0(7w}!C+r*kVl(G)dg{ceh9RZ=(Y}rWZ2}<`0>DP#IEiU&LjTv3?}U& zS-`Q4tB6%b&U8SJ`GY12OH9C@4N+^O5HvCYYk3JHC^DRO9IcPSO2+41@XI?cheTt? zY6fzXFR3ShSxi0P9&;-ATBQK0fd83TACA-9e|Z0J8eY{3D5&RtU5^}a)a5s6Y!tW; z(eJG`04V_o-@`t>B7qzRsew24vDHI=^bOGS?EGi5 zsu`a|&j2nl&oF;Q2CI&3mA3CWLF*p{KFNQK4F6vi_&=^#ey54rI63|mApVLNf6p0} z3L4+u6XGYZYSON`2Ib-|l!X$w)iU}PEiwO`D8J=A^D}1+fn@!JwKE91PZEu}=k+S% zC-GitV2;#{?=kTay~)(eRK~dW`!}!M!<}^$+n>pKxtpc;1m&Tt$`&2G(ok!(R~tzJ zxtc65_7R4swR%ZwnC44@nzSY#+MKVaB3RsU7GF36?Y@3>Et+<>kTUxVjUhqW^F(Zs zXIK2$>Jtz3WQq13gOeDixG*6kjXTucl_b8@fGFO+9QEduHxRWi{Px$u{=uMWD4NO4aFaXNj6-^lao#)kKw!2 z8>8ni1z}=4sf%h4z5?p6+H4$dU!qOHw$HAXAa67kqJE$HvW#4UW3+PLKYMq4B>^}4 ze!L%Z7-vXWd1_Js4k5I-x2POp`5y%gh!_|2j{%DS}CPTt@9&^JR06Ona32Ao_I`=If~shCtmZ^J2`*`o}SSy0;` z&$(eoitnO5TXUQp+*KRQkNQ^fMTN{D!tSjr?2Gu z)1k>L)mRXJa_$GvT+>5EZX2F@HdhZUK*O`T>?D|UzS_Ypw1ZmljnY+E)x@_6bcrXJc*jNopcnZ@LGN$q}t7Y{i_Lply+LVr@B z)$L~Yfn4u1Q*-9gl!BH|k&Zoq-l|zoy@k8S4nKz0(r9&WfcY8VK?Yq< zJ54#p;7EYv*fE0OYN4Sfkm~iCL^BLSuw9zib$IR=l(ja2gdMU`cX5KU znx~QekkL^__Ul$oh3G+Y>X^hP!);SVK4}LOoH#Bh>tg9`Qct^nu0W0HHW+|7usA~T z4`kfx&E97~1Ci}e0qqDuo3TeoKrp0(ZO8;!=vj)U%J}}47X>ZHRYBvma{WdtIk_klj1@+8QKRm}7BjiI2wLRc6+0v?@&YXGitmd3)7Kqg zd+6G~3wPul&7L{67iy4b%3Q_z$2r}Ac$TlxDwJ=^f|jq_f^@c_plo)jpt=XZpa`Dp zf|^s?ftt--ht=K^gIsPbpt|*LHI}+FYuBgtp^07e1H-n=Tw$&t26)`^z$FjXDr8QV zbiGWrh}EDi!ZK(OW0D-n^W$gGQXQwP^Fc+^KH97t)ump{C7s;k=(S+gEYiimL&^qh zlfnh{GA)kK8B+J%1=Pf4RGrm<@-aDA8xRYJ5Yq|yTY-<$TZu`)k-E!7Imd5D6ZMuz zj_Dok9JBW*=4`0N7tlEo?=%n9Pli+B^zSZSAB3C8Qqkss%1CNA$4W)A62=xB=0-Ir z>go0m?QQ-{9>#g99VikD#5=KbYnq!lQ6wk09F#lpzSv9ql~w8c0>uYQ)q6+IZdtDD zqOZo&;E~e!@_@h>=!so)e9aRQ%hf?1%`T7HzYdX!AW;v1gL zD1K+2r-+zt((84_9hMVMXqZX2ig*T``D2#Ck8p`wu*n;b-^jZZ>?aW<05#ZpJc&8P7M@@hV-a!jYR>i6Plq(rXg4JLT~$5y7))>_WDK+Aq<2Czx)C)*JOC+-Ee{ttLSG+^mSm9$hM~zcFvZddM6puk1qU$#nFG(;QW@itRGLS1`7JuyX|zk%DIq;cTA#VsIsH2Mz+7#M zwcHSFYC>*I#KVlL3_q6M=i=}-V^mDMTme~Z$I+hN1A_1-b2Tc(DJ zkdc>Y9P4QsSyeU|VPhtIDl@G%9>z|%?N`CV)Mn=r@tjU z9Kx5`QvhdXN{TN*e~20w1M#yzF2_a_pvqU^%A%XlxU#xdF)!qBCKw1;7=qo3j;xin zJ;GKT;*V|fxN>nGJCH`8Y1O#9)0oO_?bx@@jNbwuuf(l48en&~DBSE!88z5Skc!~M ztS0c3+X6ic4}{s%6mgDXY(QD8ojLK-Q<3E_OLW$%{8bE*d=Pll-shmX^CA>5e%E)D zf$u2|rw2kqht!+-M$2-#6JV(OZyo~fFDvUL=+X) z%1Vs9jb_K4g;H*(dA|#!w@swCXJm(<4d=3}R0~rb`pZ=dvmaxZsDn&;o9YHnI>cw! zYB1a-fpk;Jc!$dfdsF4~#&<4ci$dx-zYg6;p1Lp9e!Dgo1?A$ev2l^mg4Bzy*IA4mw#NK5wqlan{N?#7EBQ zB(JPh&Qp@9DBPTv|J|2d3WP~@?8%b~_foh`=ymSfG$n4emmylvFgl1L$FQxhSXUCK z>Eg|RSsW{T#&4A1F^&z^$zw{KnlY)+$ettYS4!{iIWwH|YdaxWB$#KbB4@t2MMaJZ z<`r!U>6T;p;F#*;*=HKWLJIU_>IWKKpS1Q!#rtW8kXvoG{47UbHMcUNoTtq!wbRyR z{g^>Vxr@IWFH|tAgK{_gZlJ1(0y*Uj7rP&4r^w_O+T$Z9E-c{pnF9{Q5D3!P7cSHn zT-ZkwTjhL?6vK=h!wf$M9oi5Z<19*paf8$h$2>-ICl{J6yt9S3)@v1r>=nM2XTdsI zBEfPk8tG0Jy->c|{iFHpPR4ARUm!HauM|JP3_qfNZ~^S1t>|}M(3hHM0@M2we_qAT z7b?6F)YmL-0#U;67i1Oz@n5HKnzo=0s}(6TCdhCfX#w`jU;kp)ySNCbjJ|Uz9sZY7 z@Zahh!~f4c)W0#k#0V+yK3dqot!I@=pmzIbXfwtSmH`oCKT)* zfl#>Qs*K@|VS}Knmo}as6S0CJ_yYl~^-8JZjdO9d6AkcVh#=PcNn4f&CMMbreY!^W zR$8nV1w3kSxiTsC1mfj@4vPo+64R$Z?c{Qz)84FmY(E1G4I(I$(>O@5@IGcz4~ul) z_S6ouXkUJ%MFG_LUNQQ^szY4FP&xWN^$qO=b5mV({rqcJc}!12RQvsZKfgc!12C%m zmv_SSk9Xw%X^Vf0O%i5~5_*n*uj~`$r6j(wP%kr!X00=ok56UU5^PAMUjN-f{E%`a z%Fbe|lGrrL_SHw56QN#z*GG}i`bMNuKlBkvdYjFOj+o`X?}5&ml5os-y7 zTxxn^xE0k`34#pu%Ew~JQ-cgq?-G(wX04=vk>o7o2(MDxOqGOkc0FiP>Xyk3N!|Hb z0P@i}BRsbNlbWAgMVQj&ZYB0aK3f;$M%Q2avdBD$&wuta`VRY=Dod^=|53XVi4{_t}l_~X|cV0~+UA-r_ayL1F;Ma0n|ZfuYP?KJuN zVW%&&6-L{lLJWR-D>!(I?2YM7Qgjd#)K9x?!(PH13`fau?ZXY(|GX^=t&FDL1Y34J+#gW*EQ2VBR= z0}_ITqCxo*7xx0MJGTgD|%&Ux~gI*tWUyIoBEe8dLl>3-Nx;FmDzCN9o-Yq~!jR~+pTa%n6! zf%Scmlfy`cqdn^%49IkXsEddht`<5}ut$j3LS}zB0iJ3+RPYl!V%>nqfvljR2^I^m z`YEjQoz?)fRSTn-Ze&Q~vm-?hWlvXAQgjK%hze8I>Ep9y1gKSatNDHbcgx=WG2>Gs z|H|1JTg|I8I{nZcUDXueSHlh}_PpVt$fHU+d|`d8+;x_pe}uRIO&A<>l^QYNIt^TF zRHB_g)O_{xOhdqc41zi|{HF$f_hQ!?hVj$cFHf0HETmH)MiSm{SVn@UN1%rhqNh#D zaCWDe8KL27RGLVVP7Bt2rs*-9FpGc$`}J+G!A3Il#Bmc${h|yqZ8i$PgEx-W>!eGg z&4YWm84y}q`6XOu6;qymMoywLl!d)a;B{K4bZ>~TebB|rJ90=tzu^(I0_i3&cEiAA zYS9}3M!b4m>cs(+Hxm*8*e|R@o9iN+FUdVjLM@+!J;i@`542#?wBTB;7|yn030j0*4h9ZTH74mBOLsAqTiPLme3t45}VjMGAJ< zP|Lh4BlmJC^4jJhotk5bsO2Oen-CAQptG=5*`Qfj6R^7HaFDZ@=mPDKH3NN|`|rIK z$z*7QpScU~j2X0jP`&}!5X5=6lW21IEI0^~fogWcYGs`MWW~)|?mF#o$*BjcrI7+- z;x>&4RjLfWnrCy|#$+q@kSerS`e(xbHd{)H0$5okN-9=yll`PO4w3g#Gd4kqZAjWOx)<>a-9dc| zv^kFm)#6W@j1p!R2@dK3tOxn3JwZq(hM30^EFUj24Amd0++82=SP2tz0Au*f7sKG1Rj|=#g z+SWk7z)!m7UcbuYi^NA(Bab}{-z?w!`XP$YGZb|iH{IBQ{H;wBrW7^=T}P+fbP|BkH*2TI#WfnOmwh*koqnY{$}oIJzvgrvuHle?DvlpZBVxf=1ZK=qi9vlA~_ZY ziCmWik=V@$snpUsHVQA#G+N$;GLu2^3}K*qrFQM+Rhv6ziaK&_^ceNDNEXg63pVPQ zAXnfU-!QyuI`;0mcq4-in-DAXV4M*1&!diY;J8ncFRfu5w1oShi?i%)-YCNkqhv%* zZum-JaiFKCYqWiP4!)1PPfJ*p>1oZ5A5L=tmD!Swt(}FncgLm{_fRz_)_Pz0Ub`hU zJ4TV#iOXxp#F5s;9E@!W?k=+%=o|f99lr_Cy+_mny2Ltmg+@ti#P86x7q8h_?yY8p zZdz`2@;y#C&@WIRwn!o_kASO3!a!`J!?72Re_RkzW~o2l4l$|iPKhI8IF2fUZAdP9 z%4g^&Z6|0SV)(G(YQzVlFcn8dDWL_PKlkrVh;gSr@GWP#^5dM(84w7EAiVU2J{v(= zopKF#ILs7xbV@#)cP~_MMz~4{g3oa~h3syae#lv-DUV5`<@JS7NE2`6uzM7xR9t(V z#t}L};g=XoIcFKcEu3sjq)mA%0oD^%9*!&Dd6dCUFdjTBRM^nZ&ezN1Pc@MbQFDt& zSLcJ8NZFd`-lT5R>y;^?QxtfMOSB9`KN9-^mz!>qfThCQNHfB3vkz?NKfk;ReiOcJ z2y9{c^Zl)>k5I)n=@Dj}Mbv;Ce*SGMlmxtKAbz#fa$bZ56adss*3IC}@LPGcjZ8QT zbt10Z9Pit*`q6I5GnPZ=LHEQ2B#}b#bcXI@sr>CLbW)CmYV{XygMH5_Zf8;W6$xqb z#C9NinM+)}=kvocg(n8KcD8dSguT8a>~!VoY&6o_Jf~sBHw-8j0rSx(ky=Z3ImUA% zqEZJR9|-<;uQ{V zbZ=hqWtjl6iu9T9qShBVk)>y$@2>1X(-CI~8TCZ(cd1(Bu_%KNwJbjdZ*E|XX;E5r zV};W351qO)`kE z;PjQk*!u*2^?r9SaO)-))k0Ubknanu|IEeP>cZ0_Dz=dTn`ekiGL&Ip5r4E>!VSaw zF)!<@7xCK`yPIvBuMktAMF$^5@S&r}UE7rFrJy9s6J0@u`=qqdllJ>tum8 z;9pO&-he`sLlc$W=z|pkq{+4Z%q9Fnt|*$I`G|0X73-Ro4COtMVQ4$V>z1{ylk%I? z#41UGgWQOsSG43dLe^71mjo7n)j1=4X};f)KBQmWYVIA8ExxB`4rDZbp2|&BQs1lt zB|GqBuz{p3F}fj1-H{ymVt!iqYfp3mG})4^HD>Ho=$BAIJ|ZrO!&n%Aobj7j-81O^ z+Nxn%@e6!s&Kp=W3U7vJ*3E{GhM7uob-6y*^ro(cM+8cW5of$aA=j{w4@zJ;+5}QLs}4D`oe07 z|M{YNu3?M90lQv|m3s-?dYF<4)ND$Q`71kG{YWL!m5LP9OvI$@ojMN@xgg8Et77f^t}W zB)qY#eaBOf-Qq(D(>4Oe11P(@EoJBjQ{sn3%MAwb8#BivM~bhDT;vn$823m>ULf;x zAo4T+M4xw|Ww2(ks^}{fA(Ik}x?Yd@Tgun9Ly+sa9Z2E>N>pS~w48WG0~v|GS>$BH zP?K$>kzTOo(n{``>|L=6*3b>cVCgAzzY0qbkdz2DQtt0C235&sHA$5KHyORVkbcnc zUrm}cYF!&zla%bInPQY>K8T-$<{wHAVhcCbpLUeQ&|&hIEG3l9h8Cl9a+Drzn~q<* zgh?c|d7re>suvZuW4cQ46le3SAMm$~$#(8Lx#)=V022j!J0v*DvRr8;Kfjy*WHwL| zz_wYTwOKJaX_${4?BmVt=R|%S;X#v=L~}>@Cuy!FX7p%|YuDGEGlfmpwhGspSCB8) zH>Sz*VbH&OR6!Y30rlg#$Rg)=*CMVE>*EX^tsSU&pq6L%gm!3D>_Fj$Hoj{t_l9wb zA+iN?oPkZ}*frKKNg|0c63upe?ddFl=Vde?%oDemF@%*s)R$n?mx557FgDCFYsl3l zat2-10vzi7gtj9M`PHCSveD5Su}hnu8A#-cxn*)MqsnIz_0C&*I+}2LOr@PYJl)a1 zQd1k1+qgg$ZTg^6i%N1=eE}-|0w>DWPqqu`L>WpEsxT??#(lOX{6G~NOA&$u_@(!q$uth@Ie#FO0p`JU{K zSg~4;Gz!4`xQu=|r#*5tBFm%;wKka>*>pyuRGZOM-8x~@cwYzM)Cg#k1ZxBDQNI`p zem1p!x@LrZ8zjWBJ#WKo zw`1#dv8QeBS7huwn?1TV7@64**DUOw@q4WfKA1f!_7I(U0@rNp!R%u?`#C(LJEtNi zdF@fId5X+^*(7IM(}-O%?D1ZW4jIl#E)o&}8jtl5a^S3k%%1yARv)`thb|=I#8tCO zZ$y)^s-fw6=m@aHVK&7qUL>wk-WMr)=aPwL0%vX;wnJ);Z2tqB#m8HKDAgZ-DmqT( znhx)q3?{Jori~06Cn^u!!n;J|kWfBzsg{6}RGk)K)J=0>D~@!K_IX~e=M&B>iFDw5 zYi~P$o4dzGzS#$PIx&B-Yjpj6pjZ*2+@x3BYluc={}78T$lLri7er5y4zDIwO&_&P z7wrv*(;4eKXk&1*ruxo|+#Pv9)M2UTw$@iy{|Mx2t`zZyNK!|5tG)J8?f8wh`V#FJ zD`Uw;y8T7kRaNZ6T)9(n_3I|xNkrb_`AAy7r{Zw}g@8%~0fj3^M<4wo%%yb8{?I2~ z;rvQg;HpmYDmQC$SpD^P{N7cqFZaOcJxGSQ&w%hNL({wn>-E zE$V|O2|kVh&o2fYz2{$Ia_=VIUtlPX^q=1gNUp7YTHe_7`WYI^lyWMCeK5)4UP}bq zldQw^V4vFO!yTPKn)w%&_jVzZdZcY@h7dDLy;gDp*>z^3W-+k`Z!@4UjBa_~-9yOK zvb>{GwhVP+UK#vb)OUGxdEk%6jz^ZTBOhDnL|Lb8P42d^28Nf^-+MHFX@9U*8J)dw zKYqxN|EEOs-`d|lCx-u3t>a(%pNg5aq0PUG)cmIcm?^Jifxw5z#UfQdnU>~lTG_aS z=qXC!2!|M0LIcOwj@k>GP0}vFZp2YPF-7b%-lcfW=lLiic2!WRE05S#<6tt)<#D*) z|Ni>%0rIZFS-d- zwQwo?I^UWxA00m>mjdvKO7TAjWhyxxhqVNK;rOXgsq+e{+ zzfeDVAXsDtcvo8G+qi3ilWsz;--Y22l#N9|XYkKISz!CdA0zWMGYN77$#r;$$+J?JqU(zen_;^oR(x_~Gg^tC4XGdqktz>~) zYR1$AJ(T*hUv5)BQLNv*d#LW9)7xXf%vLN;|4RVY2}}CS_|^#-{}DHo`bVAcKOmyN z86v{}xbh!ZkvPAU{J+KWN=2!^D!O=K4BJ_(1FNfxkBf*wNc~|f3i%}u8?0`QgeYq& zce&=8NNI0raZ#{qf``Y832X8RFRynlh)0@>4yU%u>B)i61Bxl z9}5H6dRm}g3n9J5Bu7^_9Pdf-mELul%l=kEY5=;Ob>3JpLDO`QaNs8+J54-?n<@TNQYL zg-9nYq@v{$&f3wORrm__9@>nhPM@ZcYOHrQg5Pl8iRd&JoE6$Lq_kZU;UZiM&0yIVtrLFNZO~I|Aln2+i_Ol@Fko>= z8DlvsU3ASGYBKA{c4X&TlN?Ju9HgMVFGn;;k*_Jo5rR0wkGe?Q91jM>DcYkkYya^AswH8tKViXGt6}Gk!K@GptRhORd@TEj-LQpD z5KQ~!h{gBg+4c!(z@iV8-K+#otB#1Bzu4Td;%EeT8Zk?_%#7oW3?DY4b+6_wC>Rgp zgg!VZ(=>klK(a7N?jGas#$BB6Xzu>CN&iTrti?@6QLVmy@TRi;1T_A2e z-jX$URO_e2Z(>Ujshy9M^P4i!9wJ<^R`?Nm(JE$x*eBSW5K#h4_0l2~xt_G%*Y>dkxW?DKM?KOLw08UFX;^N38pmUl+5O~R}#3(V8C zEe*`mi|rRDX5X*(TPYgs`~K+u_ggBO?+O#1oC7p4^%E|x&(tu{*Vm*l(QbAF!NVV_ zAy;lU0XPpWMYy%~3ilDt!caoldgP^#T;(olFFcME<1CWKU#pFA2;#>+7PC}}`jhosh8 zFP@{1l$^jZQORy{BhG^?jsktrj^7W(sq^!m;}i5-sm+I!z15q)=KOYP;Yy!EC0w0B zn@2DckYFScHNZ`hORton0_fUt7GPQYW!$Bjk?dH%`nk~8ls{x@D9|1|0euFD0#|}c zeSeHU%uAduj%HTxw*P)8M@3hX#;mJ>pG3cSe_NVn*lq8s-eV&3)W#chf4IhHy%0xC z0VH$cM^v9Utz1sqe8_NIXKlmK)nnco=G@51P-{}g?)8vECh;x+ zN>)&M`^vOi?K?FO76Tl!LK_PjMgi!026LH~ruSNsGJ~N&P6YnQMfPCt(5f@61iG3s zIT-WY(DfYufMPHZGB81;o6-e(i+bdp^=)B9#E?<5ttu=3#t!k#WW#cheyVl+Jf@go z!K_x&thN*uk|~5Rrj4*^VQR8Q5sj5N#;T%(0h}6nPe_knp3b2hvYExIYL+4;)w~=} zyq7uZt);*pQ7c+uCyDX$^86)*FEhoXcp-T{RfSnDyLQX2pHeca7Rf*+600PCh{ZMS zRjOE~K&QyH^a)FAJ||2m6X#idkR#RpR73zwrjinrw;qAF>v9PT3P{mgSzP9|I~td1Uhf|8$l5S*4(k0dG>MME@kSj92nmKOSeePf^Pi}beX95yg8Td&5H$|JS4c&*hfK7AT2>Ty+`>nW^?zNGk zJ#sYz;!OU~BYS>CLAzi-Z_UyiAPc05ej;${!(wGkapl*>0F-KqXR=M%YqSQqgUn5` zaZwv`)o5qm@FR2mKSBYO?~=X1j-;*-JSx`^@A7<@U_jk{)kyEaX+5d&g;9j@r@EA4 zp2lTZAiL&cd7Vt2o`CcM!py0lsP4DA-;>G=S-c{G?<}4YOp3rgwH8>+Ht3c;>T5HA zQ~Xe6luq_yTpj3l?~{zKIY>whf~Yn#Kzm0F*=y#_ogFQp?tTw&Nkb&e9zGy~cSou! zg=-J$5ggVg9(zll-DRFVXqwNwZF<2DSDjvv7P;R4!`U|nNxE(McB#v@ZQHhO+qS!^ z%eL(<+g-M8n_aeEopbNZ+;e7b&wDQ-BO@}ui2P&a-fOSD)(;|9c^m1gf!{Mfiz&l%)40g3vO_&qSzv|>D z%HyPX#YP-~-|?xYsSTj*&(_ve*He3Cv1C3gB)1t|My;~DUa@bgs!EPJn>)*m+VPZE z@VKjL%SSjALr6E!oi}QZ32ZwjQztlDKA^2;KmzMxoW1ZDci-wVMHU=~7Alm=^wpQ9 zbk!4ksy1B0qo$tMO*+YBrENL!$B{*nMnc^g3aVt&e|O(3+Aj*S8D81ILSzTlnWwVW83O!LfcZ{bs{<`A62cdF$pfwauSu*pL`J7FKsxl!+|?VK&l3$EH5D60>B z&^^v2+vLj1*qIUfx-T_HYr5mfj%YrbYNk5T$K^o6k=Fu{E?xbDUN9?2DPP;yNsusQA0pR0%nh?xr{Dk@xqrRNAJ-D(^^WCn zOszL;NJ^8e2Jt*(h@b5u4^>IPL$_mtflklAu*S5w6e0=JeaZvqY7W1rDRy0^_Dz%6 zVQ9uN#u94}12Z+dGRG@PtdG*VkJ747D?&01Z(S1MK|bQ)5PuwnkXM_S@uCRGt0{9F zOJP64{;BYnU`bc6yI3NOLg9C%V?5;*dg)2Z$7?-d@`ap)cfjD}<|;?TuDF>~O~GIE z30Qu#N&=3v;-k57kn6cc^v!~h$Cl<~Twh_iaRl5I8(aZ-P{jtAgKCKj7ZZ5`7zIhU zF7n65G4p}5x?VeC*rKlKm9V;BW444bD3-dyrf%e9415qL5lfu>a460K!@!kV=u$(* zONy@G-LA+A-{>i>cS{Bl)q+Uj`{Xmii_P-6q^;kf0zD!WUa9W4*$XbYYT0C_49?dUZ;-rPO#SjjmAuO8D`_}mBZttFWBA?$$AoF!8QC}@ zplO~9LNX1L8>V}ty9{ih}Y9nkC{DK=+;n+BxE9T|ch7lKD}VO{NObKV&uY~r@0 zAie=`mo=Ei`O+C-_i;HiVZ8yeYmNh}N3wJrx4`7I2B?Of=o~pXl>KHkCB4iN2LrY3 zJ~$VzUD_5ijm$q^6=rMxwClBYPWz39%O;LR(QNT`I@LEqbkU^VFkzF+8$1y!tE-1O zQx!UST7srYfwk#GZi~u+J-cj{koNlOv%nK5?h!;yk!F6P<==I+{3YzoH~duh`BcUE zT9x2!y>$d2->>v$tAh*F-w)_apXn3A3}3rKKwg{6V{nsa0c&bFy%3U@^0oyipgEN= zAXc5Em9XQac%qO+$@mUzNW65|ip?1^F^3&PWFGra!m1#V4KPtc&edr0n)z<^Dwh0I zro(A!;?wROh=g(P!`IpHD*GCCDAw@qw@Bz?lH=1eGu9$#hccApcB+~juZ7q2NPW4- zwQ{a6PcN0LxBzL9@zvDK2&0Kdut)b@8bLY&Fs(h;S;Xh%88Bq?GKw#O1!%C+N7m!a z`>p2|n-q07Q$ghpzszlqHj4v#1@=^bVHth^Ta0es4F5sGSEGlKF{~C?NZD7-H-RMw;-4L8!P_re09|CrSl?64m3w+dl?xb9x z3;BrgtJ?ZJ4jIsYPiz>Us?O{k>a>|d6;4qls65$(A6iAjP8)&NFxCx(vft932h>^! z^;g2~qJ3@w3Tx*0;WYI?@Dr17TF0etnwHQF#?DK&o7cymw8Ud7Z+3=HO5zjxzqShg z?%*W++hY8$6zhL#Oc^`;12ptk)=7hkq#~v$+`Gv%q&NzLP^~>)BO+pWFf}Ls9zbJv zAB2O^?zc#Q!)@aRf9DF9AM40^FfDs=k~B{MEzfZh{p@_o3W+1+!LKDs9wy2B<;39> z6mm`vQm(#l(vyZyhnt%pz;@V};zstgQ7__TDTg}%sJeDFUHt^8uq|$V{RpVhEouh_ zf#LIP9TB@_Y#k;c(&$Os>qbWuP_*-PCYdq;&_iLD;Rw#yNzOUB z3RW@fK~yc^>KKbPI|Tl$KqDzJuY(>`w*ivpfl|+XgBl}VuV?P{+#vbUH&rY@hzSav zRW+}b+1j;sAQR9Su~eWX>&)frPoSxnd>o8hof1N{Q0_&C=Of`947uZ6DP1Whql6h{ zMlM)yg0aBStJn63M_gN&KH8DT5!?5aDsuo zlltA;W>!hUYqpj<|K4lDB|@8nyVN}xqdBK6jSbLL6BT8>6g_F=>EQ)TvUL|-gKQIa z#|z3eD+T05Aj@W@NZ}ivHG~w+3bg2~`_A@k8))}dd;70E_qkvF@Ex^#4-_LV=sex ziU;{)4X32E`*97|<9=gg6HSw$`|7_p7?Kn2^s%&g^aM0AaQO;#uHEZmKgj6qlfKNIZ@as(%jH<(Tmknv(rYz%m#o4BSCzkL;h z97W{09cX6XMeK@h<~xiS2o$IoB0yZ+GjYIG3AkV^T38=iEOu$k0k*UQ%frBZ4BK8j z(o3-rfBsjgt+=vX(|fNmEWxGYe;FrS_0zV?d>U&MaZXo8`|`E(5kx25rmGwF$oWR8qJ9A`$L);` zXMq&j@!%o>`EAGbBgD_^SIB~?pWgm;d%V)m>1sQFYVj%aRy@^xwkwvP{xwVf9djr6 z+bsEa>MqeAT)hAK@?YrNikq^CpY-iUYU>|(A%HuwN^^}6q$1KtO7#kkMf^ZPpqq`Z zlAe1@mcJT>-_pINND*;gfnM_?>O7_KU5V!(?V9QsH@$Ag*Vg`&gjDN)L#S<5>~a90 z1W|)}a+dWtK^JV)S~eb<2UMk#V&)=mYz38u?>Lms=3%Z~yTD&vwauodHEKPq5p?jsOQ_$>G0+98Z@vEHed-E&p)KF;0T2FRYr; zg?0^6&cO9ng=~-_!_sy6h)WjlR2(05vKg-rkN%8k-g>JUH7m$HQ^A)cOgfu&;#zHM zWF%MMy1|x>b}0nK2OjSfhahzqk2{?@&3w? zp-)z7Z^zed2UABP^Ag~$_-&g@y|oiWOH5+aTl{iCCI;mb+tXLbGbp%=OK^TiA6Cy4 zG}=5UA0X?DV46QNYktuP&j&ekivhB4g8 z8F$VyayyY@V57XkIHhAYshvSkgq8Vl-T&um*U?b9^!{wn$^2GV_V>Pj|7g&Om|K1J z=ZOCGgP@i9rw80W>49?6vVinR8Nrm0A=lf|+!#QpnE9x^(g=u%2nI=Rv~9Gb1m-oX z0ZkH3CG+=lvtGkB8Ev3IkRr_)7bZ zsNg>bK~#^7E*%Lfs&$1tz@vryaNEMi?q4hF3T0v4Wo5JwL@n2keNwtWy| z+Mcv9DN$SvQi**CYOI^rNZ!;3Mi5qfu@|xvH0VwKWw~X0>EOI+h{<#DII4SkzCfb*M@C8@izQMR^>rN( z70)Rfh&Im7bPjaEZi(VsaVSB7g<}3X-uUT?i<@nG@uku(#elXyM&IbxP}Jp3s7lAl zJ)f)h>d6T|Ic`xwRm-i+$=UPjT9Gp=n1tS_$Eh(Vv{cZZKy1a}z1)nMMVj*M=X5=d zRJ`thA2|$Kz+547>0YI!rXjcP#$_S}<)`1$!?IPITWJQVv5uuA5N&ua4pgjnD!Y22dSI?GASKW051n^ z=;t_-Ww5=;a_0J0mHQ>oE17*B-dEXUL1#tn{+CBDPf)wae5`z|-~hxsZq5d*LN66l z+`^eH@cpNVpVs~wvo6lqX=cxubt;ofq-anA3~*Xa z$X!nY?4GM!8g{ZABfy(DyC&Y*ehsE|%-LX8-=WF=OfGU-Yn(xdVpZE+`c#uMCmt1R zUh~Ta2moLa6zstXI>ylZ&}2k1M+v$a*8au@EIw`-^P;lx3T<-Vx^+K zi?NZS(|?*-WhQ9KBFg`v?0)XDT03P&4(6Zt+1gZqZ*R<#qgj}fG$Y==n!*{eSSMb! z#_R}5D+%Q(xtcDCG1~#X6huFylH}(ju$f)vW^_DYO|JWNi)_OEGGNadphEP0%1%Da zo}4C-&QILDnW`VTrM+}V1B_oQ8HQDIxk@~2i!u^&hXTC(B7Q&I*s1aNRp#(oa;)=Ao3yfqJLlQj_`6{vLE6N? z%(V%&LDsP}?DYydW??X24OXXgiHj&~-~y2(G%xhh0Q`(uX#384Ct)=ZaFe5ok1Z=qme)_LV_)2T~Xlu(Vi^7C0LIfPWWd;|V zQ}@LJAer}mgs=p6yWcWpxX~rmdtETZ=m96lumWih>b)K}EtU{FQkez!rV{LeHqKR^ zsUDAHd%v}Fta~OqULzfg56xRlrqCuPZv zIf$>jLmK9J1lT7=+D8`{aSTXAJyOug)pd`YHM-b<3F4Q4nwV9Gf|nr3r*T*o79pDH zgl!2w2@)t_eUY<$&?AtR0zRZW(>t1KNfEuAfdv~xeAAReyrR9dBB+Kmi#OTFejV|w zC&$g``o5}}=GTj6f1NCAZ&3^iKty*!5R}36E$IS`#uon;otlBmvFBxb8bXe_X?hoS2FrE_#lQ29tl1a$Jv37J@)4$Zx+#2%F zqV~dx;JN?=z5!$H5O(8#wNL5QtCEJo2W8uW!+Z7PRpRHjfBoi95#^7|_mIB49N8}O zqa4?EbGqu~wCcrK_V~m%+ZUiq;+4x^1dFC{TMSs*tttwXK<*0ff~&9h#m&tZ7snNA>;k^*_ z&8n`YGzsd`J!38sj1QP*D2$e7)4!Uhd&Z6AZZvLcLrE z$zFCgv?oEC&Cdz_Vos&V$i%Vs{C*_BKzXtrcrlbiI0v| zgWiO@Pt6i)i@hjxK%R7yQ;PEj?@eNnHiX)pJCN)emWx^5me4eqHIbS}#c{@hdn5qh z0dCt1I1XD>8Lh<#umrLq7w6Lr`Y|h3llc*3p?fgA{8Y;M31K@an^;fTD~m*bPc5^; zb5@|mI6Mf1r8iPxAj2Zx@*|RT{3^7^Yh<$%hINlvTgz^|AD{Ak#l8cDe%GE-(AWe7 zIqj~F8e_4;%%pA)?>GdCBmTH~-q10(gsiD`%k1E_R^Jz9y)Q zK@=cVG$oW|q%|KPaqF#BF^r{NiL60mpv`Vq==N_H=x(v+?E%Tq?fw^-j{vk)mzNYi zW?Q0OyA(lA?Iv4;ZtGpLm#zNutV5yxiFFlO&`+G(uTIBjP@@_O1*Y~Lm@Wf|cNEH3 zRwOOyN5lgUhr&NvIEKX+Avmo1OU@vz5;kUGma{QTPjTkyR>tOeU?s|HewgW3rDTZ7 zHQZZ4djxv&Acq)qk&jYVE|WkEr|7!;IGu_w8`yqirL9OW0c^a`39$F%FnXwFW zu^5qB0S6D#CYNHx=2f(_q_<@$&KwR+y=$DCxO@o8#2|*bU;YsQYPIAt2v~b4Uqc}w zlS;MFQme+57SL%?pVHai|Dy~XVYB~dS=!!OfihYN&0^JL0+BJI%)q)C@wlMR6K$N+ zY5^Yk9s{QtZsX&wKUn--D*@v#Ia_oh3gef}eXUM~xU>_t#k+zt{46$Rs9$P09eUXw zia5hCiUZzjGEZGi*CSjdyU-wabs_NZ%32WN$N5d69cIc(4x#z#;HvD;6??6qLit(} z=Gy$aCD>}hyA~Qh<81XU2aJV7kYeQ`45A=dnyuj^V-PQeAhQVs7qAm+Ub}ExHeEu)vH1}h4LkL zW$t}-mZn(H?x=KDV5KX5;?n1VjTJt=luA_9H>(m)3?e-%Q@V6 zU%N6`wKxMeVIYIzXxe%Osbt1KU*-g^BPL2= z;IY1uPyc3S5t$+aooxiKjT{wtityf;P>Fv9fiW5tJILXgaVIvEM-gpJt~u=klKX~{ zxMEwa_ClRjznQE3!p+gZnwFK_=n*Xb;ori)z1=wR;xzkSNk;1g8%Q%h*=F0PT2 zwAAHS(}0Ffy{LOtB{Sc6xAdRs0F4q*FH00xFrm~^IOj#hh))w4Eb5>fL2I#+}p1M@LhjceRY&f(+}!o&RGgn+Q*B`Wq2MCW{$h+i{L zg1_OiutzX%cy_cfCPUOZl`9yY*tbVoD>5BCG|CCs1!(bT)w}jG8IxrOK8;29=JkDz z!#MDy@{nAw3mKS0Tp~g>t;W~Qvbj-wgNbr&E}Vdre!B#e{<%e7^yLcjvIyEen^Rtf zXHrmYE=OdnSdF?1p$5)U2)nh9zzQ{dJIsR%596{#&3~|8fr}W!UV>?ty+-PqiSI`f zurgY_{0ZKI)$jyR0{E-aBQK4q7fKtMP1c$VN8KB#GsMI2q0aX~vM_N2g>E(lpS@;X z`!Puq6up|(9JVB2dy1>wf-dkp-?;iu2z-e$u99p%7ivg{IU4)Ui$;|jRD*_=HokYN^GCb=n&JDU%{eplLoWWs6uHcxhSjwg! z=6Y{W8{pr=r=N97m89K(Cw~++hh$$rfBXT_%J2IU2Kq^--$DA_ZCLiV73cp5ASL<- zg7k0C{;T&{q4*EF4Q6lXvLaS9}G$t>;3jt7&2iq}7V4YP98`N2Jr&+>n5MSX7zxQ4{GxQUbF z;=qBEI3H3CNGlV(qrrq#o=NWg#<*&;H>`(;Xx(`@9LK&$uHRWEt%{*qeBg~_dL@ee zJYCNi1tidb7(`(X${>v_*j5SkMl{nQR>u~FKu9v#r}RQ-+y~f+9cgHumTb`k=Bblc zAa5Fqb(gPGE&!>hHOc=y_$cs=>}JB36x=p?4U#>UAZANIu=?aXKas-Y7H;?LS&eD3kyei|PCb4`6Vgv@JtT~Dr6c#M= z!-Q~qyj7#hs8ogGT*qN&3xE4Ey9gnxYI($p!e1?3bV=jnD>Ty6L$$1*t_v1$u&cjn zZE8Gi&g9e8*FlFYq@_KzOaQrVW}RW3*$l6Nqdehkp69ThVvzgUjP(@!1FN>x0T~~i z0qHdZ5r8Jg0~%GplL*?KFRJQ4f?k^CH}(c#?O-wgp(Tdpf>-$S^WJ~@Thyue|HsPt zw`(R*R$8+66LG3&*;p~};|6al0PA57-@cCqPvHlK!d*3t&{WVS$@8HJ`~Jl@p&8yo z9C8QCBeaSE2 zN}&zID38pD->ns9F%N|ckz;@QMPr~47b0^{gt%R$cDst^iS=bEkMJB(gtlnJ@Tr7B zyxA($)R6L}$jKnB%c`8rcGVI}QQ#BBNnt6ibN!sfN+E7M3~NKfapYjg*z?5iv~t%+ zN2v97?AP`2gsk6Kd;$=Fvy#KJ4L0V?4drtK7d5cv?47Z_gxR_bKd`a&=K%NCy94L> zGn}ixZMOVg4&YDmHU(o72V+OGf8ux42zApN%w8sLj5s5mhfC6~a&&e>%j(jb3JyPW*28j0-AB=f~S8l1hhV4j7m zkWWTKT7V0FaAUPYntO>AMaxh?q3=;P627ZEX^6jUftseKyDt~K@XX5d>;a5^v0m4N zNwHa?rrK^S#f_7EMG|vFA-Yao$+h5}+KM3g;$vh*Rn7p4ckkFC7W3c-ME*C}OGY7@ zm*yaifnX3S8Mc*(3AXkD)TuSs1er>-_Ou|o@(1++hzpo# zUb;!kL~57;-PDE$^g0%v_pg8Cbt_LsqS4QV!uDI}E!+RPJO5}P{M}pXp9@Aw+ZIz9 zj=OCmdTE_0q1rrytuO(>YOpe$iEWC6JaiTAJ0>zhIf`-~=0%)V{k_Pk^CyPI3%n1A z*87K0Brrmi*eh9IOIzdjl>-2EjLES~Pm_ZT%a6Co3tvFBzI7-nq*=D$Kqv_^Nk{7M z5S5a)@@d58HbZN*w;S~G%r$vkRu}BseyHR_EE!RlUwbMtz>-rX1fBAWE@f=U=~RS8 zg-#(Ho*2s@q(L;O?YKb@p{K80JkGso*BtM?O?0e*sRwO2a$~OWeh3HWmFc+yFP~#$ zgXk-<>-gY!=c9tORnT3&Sx@p_3$QCPp}l&s@`&9py-N6HRW0r_1)V;{-thS;;C_Wg zj_}3rv2o%(3KIjy203O+l17q>5@9#dLbutxlDYRM1gWDgj;}`_LkQS8%|T@Em~7PO z(0Pn-s|5S0;-BgLOJEj~a9Uzy(93j*g_@vB8`1;YCf*zyViOxUshk~~xeoKTC#i{; z$kWl(-tk=WaH)pQ&y_l2w>|WMYORkNvP_M!=F>P(UrMRs3TpbqJ52i-QD6sid!v(-QPFd<&4gU^|ft4e%_g&8(YNXSKlBM-z2ZwI3Ev;H}G}= zPrqqUxhH@LWK^H;3R-So@5luc_x0Sv?h%}{M1thvBZ}f2+P`9k{3KtvQr;yf0?qNg z%p(7Q4C@qFCx3`7wP-AQ2Rk=spAU9XoILTRA3E_qVsElYupVc5rjyY`U50ZDuQ*)Z zvF<65(_tSBpjgwbFw@gpWTsS1*7GCtcmi0srxaiR_YrJyXFVZ zvVw(Dj&C~Fj9GC$%WjQI%Lc}=*5P#%`76m_W$ZUjEQjzpoA?P1)aRJxXgk!0lx2RP zhbwws*h_F6L)4c?BpjTbFVQ>mxUtp91UkgtBxMZru?oQSd4f>;f9&{NG%>-5&$C$Nx3j$eWv=nJITF#|2TOmoU5%Tx z`6Pf0bdKY;p(P7QkOiU$m`l!tX^3gb!GrqCefBxc65DpmSA?%BjcpO0RqXP1x_~ap zu$sF7XhPIEB}&PZDd*!{2RJuhP2QF_KfK?*ZlPnqP;uE^!ZFuzF^mR9N@Hq5ElA=A z`t-|{vvNQc7M<7!6*k7auH&6t@6jFIn-|Zh=uce$htf^%j>qw!koS%Nz{XuR6F!#w z$YY!GNqLrEGqv+3cb_=}H6IawEW#er$rGBC1hp?mIET*mB%J2lSxGmx$^u$9RZH+< zs$e*qCtZ^hA1}O5Bk`Ggi4->$QXD{5Ts->2E*ItCy;*sALm(lm*z!JrVC!As1fPXD%}n& z@jUZrvjo!9x963ad2HMP@ptceS)1r(No6Ed;YXCqRFJMU5*8*MZ(J7UNzcJ0zO)4! zlO-VK#_Ole{51mV=+QM|I2uSzHJ7-5tg)IlCB9#ur;5REPZj>(o+^Kx_n3c56&wFg zZlr~A(zYvna6y{@pr8VPPi8Y-z7z!9bER_`X0t%Z2nZ0M1iv6Rh%nJHmmy1d%Zeqq zZ$WRfl}>Vlu^dV{EU}d2DF}p7XfG)q1vKQ1?8g35wMG6WWWL_tB z;1x)kQu`}|Yl)N1CDPKqtT#ec39T9$7veYtEF$DGY=)X0YkmS{(n?ov_6FskjMY?Q zlRBWlpVB5fc0$SGu1dIENw3wy$*4QS%0_Mr(0|JNmFcueM=YUHQl5nmfad3|i7K*Q+eX!K8 z{D*`pBPnMEMn@_xZ6mA_El9jJl6&30PyVpCAJ4&cF;Y$ip!ryTJmsW^b05Pu+)a`5 z8E6I*26E)0={K*xFbZzt@+GiCXka4G;DI*6Cg^X91npL}jpBA4SU8{!=0?ApN1Za& zDWIEVK@8`OF;2$?!3!3?*8+hMzXtW06-k$RMJL6HV2Ky1qcC9KIMj?#p4j3ILIpqL zGLiCo3)4T%ANSSs;x-}tWs1jg>437c%^M8MV1>?w2lkRTm6GIZC+MD^Kzd zZ-h#2+^(6=1@!orOT*uX-T#Zv%iofen5~VmyP>VM!9VJfhU6#5SrMec&Jlg}C^iEL zz&_%7!ESK41uOH*y1u78xP*NAHu$7zV@aosW7|`(I>Y* z8w{}2C5q5{pxP|YJvZOZR@a--ec#`1Y`>6RNkT>MWjJ>dUFstfkcaClHYWwM?shxL;GNeY~HOVng{VE9?RJ zR$Aj&U>M%8Xct0q=~$u0syW$;v55@nC?Ca_5-o}l3mKQ}D7(IhqDLnaMVWO86oSB1 zdemu>(o7a+jO<7(*aaH6F2CGXhk3bJ}D3|5L1}(PQw~_KA8v` z4}Ec{t1R9ePBFboZ#Ie{qCJT91Ve>=Z#l6KR(0!bvp#xwk4+=Xi1FmyDbXnogl!j! zoE}M2tzIzevP`|mL!>dGGF^H9+}^8q?EaQ0WTd{W^=Ju`tj1=SJC1ZCLW9qznhI#{ zpz-ShHamzxSq&t2Yqx#6$6oJLfKiSYVpv>WM5aF?e{fzZO(yGEgjy*W<*0{z@pc*n zmn?pkBi8jqVe4Us-CKxaDs7sRTLSxtt>t%Z)+a9Lw`>4olTk_DB=kZ;Gny2F;v7~n zk?S8t^#naMv*y=F;7~JK-k2stmxW=cN#&F%#b2)F`ZX-8j)67KbkkR*YxqK&#Kd!_ zQGa+U=17r_6@|YJMxIzR9v%oDFpW6Qgo!j*sR;YUH8MynQz@1%soT#Ry?xJJwFv1g z-KEPSn45a-`-*$=2!?wzGCWDaGkrzQW9eWiuEfDJh{~bx7*~6(a{nrh^GLb!GuMcp zJ>c4@OBMU@@(zVPD0LST1PIgq5oVKS6BXOst8AB{W7Zyd^AxQYmV@LfKPvrEe2}Th zq}e%Lvu-V|cM?Lz+E1<9#&<`a?kQw8%72W-$QvXSdIQ2sHr~tQ+$gM}#E^dN}Js9}2 zrQe71tnWzL?HG?hg`(1II%ei~U%sbI3~M$CV%{6S??-sOL=CsC@L%b~8iEYjHsH*X zy;pS2(urg5H!%p{m+6;?a<+kkj52#>v-nbhIZ9-pc=%QyuP``vGMR;N_%hjicGRG! zG3tZ$?9Dla$jB|Sg>Zuk-}SV=cR-D*lYpHuMNWn4WOOs`VHb;YhaZ|TK~L@ms=T7@ zx;|Y^miOXztE*@Cy31}cs5_QB4e;K7@qp%hwU^2dKT|6%wvkLhB`T5$LlqP64R2lw ztB;R$d5W!kilG_izz(Z#3$o#zffh(x0X}A^bPMajzs*tRlFsdAgX^HLko zqrp5+Lr|?Z0BPZfrVXBGQMFg6bB#NWQDCnqBx>J=01>MxOV`_e6lB1f1F3j1I-Zo3 z5%@4Em=Q6kZZcXCtgi(-tZp+}k)){*E`t+i!U}ByfHw*=gfUoE!0!2#P1!*cy1PZP z&Hufl-*V>AdBp_^DK{gT&zC5Sw8SUwBy)yGBJ56s^wdD8*QWG5Q$W z9ra00|Mw^xiQiTV|AMLc4^Hx*<$|2Pjj`1q4~_rm6#bWhc}1MIma;p*=!e{m$gI#AOfemM=VTx8#)+1~Str0Tuq? zScdy1DLbR%jhi#H9=4?M-qm5T9!j$ex8~IIs(N@n&UX4JdwJ(Yk-TO zZi~wtBp`3Z`FoIe(OPAM^{!H@C0P{PgXh&`r+!n)>FFYezR5nwn(FnKjr~$-dQg~O zEIbJ#a6s(PBc`ZmYy`LxX++VMNSCey_&ilD057Cv7B0Ge%ke``RQacp^}OqNd1gpQ zNlr*ypm5K|#}a5ybM8vkly=)RPb{{L!6D-w)q#+T{T-qb72#l0L=~uR3!te@T7Exc zI-@ z@n?8a`W%7QBoRn5&{SD=qX7d$C$(O2_AlvmxNxUb;vXuIszxx{8eEG)-OhZ(7kPoK8y zXOo+o9YA1&@{wPGz08ElU`^qS%nZ#;*+!?jbDrS@QVPK&Goj>FCTpCs3Tc9Df^dQ$ zp?>OoN)*STCL=4ckG7t}k{^Xwip((F6=5ittVA&n6a8z_L>X8)suQb~XVWtj3&ZNztC>Z^SP6wxEu2APV1<4N% zSNZ}%V1hP-A!go4J&fRxxa^xXQd!OLRsUPrrF0rPC4R88%uM}y?rv;jo_wO92!ZiR zYYh`grZMAjKe8VQ77|;4BB1It=~Og;A3qd0)NWdrb04q>-HEW49uzCEje&q3f+Aqk zvN;ALpsSs#9?Apo0Ud=ME-Wz4b-TOV3XJO-(wu#Zg#=^LTsma5QBST5iZmj6?@&|S zy0qR&T#}gB>it6i0R#aJs%N8fBigoB2+K;w>Ur(#t^KH0-jhqG$sLNLvm?!-reiZ2 zo(9aiepGca9RAucvsA*kt8j8zsmW0^vnVTcgRS5RwKzO^xQP`1jf^^3D0OCcgz^-Z zAH0t#3!|tYJ}nB;+3Ib`X(QqBol?x}MaJ7|tsE*wNmr-Q1w;a3)UdLG^b9$E>S_(_ z2WmQhY7DtJbRvCktjda%dDO6w1-a!9asI7rtj1=CY39a!b(!JThO;r=!{(aVwv;^` z0>(<>c&8ER)Z;a9bV_rfkV7jA{RI^5Mq-s;r9x{jxv4f&BCT{Vd_T%|d(&tZv~PI> zdX2aR6cU^oAN{R$bAUSy7K_(1@&lBaK;5DY0|-c8?663?RHwulpCr$gfw0-e5v)Q)`P{97Vaq0^wdl;YzwyBD<+{WrxrC&)(in zsRET0^Kma@#C$}~iVjqip8SbQMTE?9;{4p0O<=#v-@g|X{>x2I%GS_Q+Scfwh||bF z@xXB2Ao})!WbnLG-$^i{SV%V5(5HZFzXDB%7uRZv+glIYxPtqRf9LJ`v@B!B>x(f< z7uVgCGTk^GJY41cCW*yf!p>%AH?##Kh46H(5*U}e64j?9l9iI$rxPJefp+pHqM!-n+^!J^dhbh~2 zI;=@hSEp8!+f-5~ICSJowp1x8Bh@ySdh5|c6M&nBFIE5!Fegy2uHm;~vdVOENmV|5 zEvB!@oQN^uGYCnX8lxr1VQfhSrl#gqtXPtp3>oFl?N0pJ*SrAG3Q<_X@0zb)t!w!z z!<q zJy-r781^@fXQKc7{9i-4NSRRyAbKS3rUh|L%@;mizM~!+DF3az(J(nQ^zI#=i2(Z% zCU9|+XIq-rFT4^`fiCnkC)ydFzfRX~?%uAzw@?s+7=r+|8Is?-!@LR+36-_jXcOz9 z1bgV@DYXkPUPy8~mGEgLwlkapUQXSpExILh9kSXhj86{h)Jn!q2zH(En_ii_>T?-M zZ*`oE6`#}+;_R-Mxv13H&O86tYV|4b^2m|nPfjQagxDKhD*$krGE^ zI+33x>rJt9o}<*iw}lP3!u<(`S6>Zjfhf}jXqkHxt{p&6;@4mwHCuw|;&~*R`Ddv@ zk^fF{^;w7%f5!LUmn#1^Aozc(R1itK3+X%QD;hh=8aNs|xcsMXh0>_atQ;KoZVDT{ z&2CW817QLmVlh+X95jW1zmixYAXS+E+`6>4d87hos|%nP3PK?QB+oZ)gz7IH!1SyI zxy0INEH}+rj$Eb#i@3fWA764pjWJOw_m>l__w2Z%LDs65mFio}x03>e1z47$cSay` z7f^Dm^15vMzWeYhh#NMqxS>CCGMLwYrHGpI*1bjiv4G~p3if>uNB>6}hVm)gn981{ zKrVK`^_5-~<-Fqb`IUGLwsp9UXbIopuApL*NQ&pJhc=OcB8hBkjgsIGun7?~iTRUI zwj{0Eq{i?OB-FBDQGH9*0L~dwqte#NRI)X&;5^hvg4m8g3V;C9~FS&YrFz>5*V$dhKI^EArz4(|}-|K_$u9nU{eN`jcrl*A$B=V0CXrfJ=j04)k2wn(8Q9iT}ma+|DSsx((D1WMYU4kJ# zw{y&IducqsuaN(&hyNmxLiESPM&MJ)=|5IoVr1tZ=<|Wj(5s0IQnlwVd^)o=>t zd|+TGen`h8%lKAm4^itsN88jNzwjh9Tgp*cWf;7BF>bzY@ak-SS=%b;lMgi%z$T)J zI76}G#MjE^t(onh*SHf`c4vNyWfIk~hhskXGJ7?0sUcFjDY~(AXJUDpJUA$9sNLMO zw8?)gqkhoJBU$t2h0tDQ;VFGrIgi*7Q}TTrK!4ZEK*=WS4E8w4c>J*sM+7Is$fxdt zdDp%&!ht~ZAxr@l0N^kcWA{z}wj|+u27NuoO~hiEMBedHip`-*F#fJ`OgN(ND8_aKvSEq zHwS!;Lx{U3+r47TWXK8~*d;oL(b6LQ zl`{%B)?uQ>b>gYxBI_jv_x0`En}9=FB`N4=o=Q9a(}jKaz}e=YMSbglgVolqZfHDx zjmo}mY#iEVW9PuyW9O-8=!FT!VjPsRlqY z@$Rvya#M_nyzNylD$?C<>b8C}qwZVo!J1d|sum02`GZo&eiv1$&I3)6%vcp?Z7-(? zl~IA`vGVN&@5##3iu;q&L(u1yfDW5Q)pEYgC?_k?EpZV~DPX^b)B&@O@-FE~Xe!pJ z;+9P?lKEifRgFdHMH>vi^A-=}>^J2}dcetStjwR*<>;-3&6Lkt=Z(f+^~6*0f%CVs zj?@Z&f`m+8X8m-b8QcCD{BxhH+L*5xFQ@?dY5X%6q0WMsK6+ z6&}5k;%uJHFX<`K%ey)s|2oNxK@F)r)BxBE+rxfaAZd;4`^rWvOrlhCa`5G~=J_k@ z7WY!V3R3Z@wQhZceBQR+ru~e^{%G7|+CEhv4A)iB`L+D)k{X2Q=r-7|As8`yl^)GH zH^D&Bew_TEIuCnCTu&zGz+f%fYD`xXuFa0{S$(!-`}#xbUL;Mg9L|~}m0lOnR_Mz`E|Egtcn=g1M5lNAa2ZYQxKU*^d}@z z)P9A74IFCH89)#g(G9e*kf0}CJL8f!3m_bLkCALU8U~AoT^ZyF{s>ObLjLlw#R+If zA*K9{9eju|QzrBb%ZDffK{F%Y6s}*`>8rc|oUGW6vtHrWOF42_ zjutpuua*j>Ca)nTZY=0aN?3|R&{Qyxl&}&Hr53N@@&K1t5kiIA@A5ZQr`dW<+D!`| zc>_=2ePFM3TO*#6HgeQQpALsHmv7e1Ia38-g(snCj?nNHso)Vz-alb90I~O~x+NMF z9rgiQzVIHFp{%70JM$+>KlUho5W2X<^~O*-f0j6p?0H=VJ+M$s@s>~NbO{KZrX=u9 zg6W3E$0%?;#?w&#Rz*Df56cvw2N%WiKTet7a$5fv%as3q(){zDt!nP6IEd^c8s}Vi z8g2~*IGTc&95WObDV7s7RPKVOvb%+X$;y|cGrHIq;#6oxALEVBDV|m+9bYdkVV+rU z4oKYyQ~;bdXFmHT_yYNSOIp9VlEtVI>+B8@nLWtpXgYD7WjulI{eDq*2(b38v*f7j zyUpVj94ze3Wr##?zSkw1FV94;JhJT8u!qz34-c+LQ!O`@ZbvCMsqP!D&YUe_kWHoO zh-9Vq2vw!_Fx#ucCT+Lzz>CXkXXNm!pfJ`eZRE(uEdPr#H%Qx?L0BcK9($GhUJqb9 ze}IgwN!*$N+?zut*b6c@)oxj&S0z1nU7AesqTqPJWv8)>Bgr&H5e~}&kopjFjN^{x ztYI{CkPGkkb&S<`5@!*TqSTP(zX)-6K2j!>m`mBQDjN~!n#M61 z&xcbsG=?$5OpHR^LoCUfywZ?D73r$41yjNcV7(0SQt2zPqfd|vCs?Hr&LyDllUQXI z#KT>@X;QSV69GrtYdX~8=VHm6$=w9ci$5r)O0cyqNW_%NNa@T}po>P$9-BoZL5K83 z8fs>*X8xl;ssA#iM{Mu(dsv=>xKs&cs3GD>9wDU`6g1rg3wXvpd;(WBvbJ%^d!M6* zK2_IJWyl{de=CM~gj2+=Su2`sSN7}<2eOKO4>K)Ms|x_`MjtG8H7RfAbhGMt{R>y+ zs~giADqNrJv?*r9lUlN^CO46K2H@g+J*y+8s9wj?PUFl_J6*hXiAC(;;vli#tM6&L z8bWoqBoB}2dK%MgX-|$p&NAbL03Fjmc94LX%~?YJ3AJuBY|^rc&ilD}fT}2&r0X;o zYMWg{x~1mlT!AS)4y(&ZXGh!0!=0Ad3gVwRmff&dtRB$?i_M@cR@2zszz0@mqoOdx z1&U9>K8c*=E2m%KUUL}c6jZ>0LE<77OiZ#_wRP#fosY1ADyAO^9y{6NE5fpCu?wrD zU`t?6hepl>FmaCZZDANQNA+G#Sp2Ot?8zM?=1sJz&k~_eXS~tDzpR5vxpPf@6?Wg^ zF!{8_82iVF_>a8$Fn1Om14~04m0N1q{5@sZzQ4Tb0Ck$uC{xz2Fn#m4+CFvr?yo&z zu)mBz7ACCkfLyHavB5F{x>w|HnmJd|^q`3X)-OC_;$pp##s}yQH=yjg)@EoIeOc;b zo*fU?n0qi9y*c8_;uv%-_nX8q4E=Kn@o6=!OCI94!M^JzTff5RFVvT!bCrHwswW^k zFooiM<#BT8tO@eqV(?fBR$O#-CqKnS;(mY0y93z+o0^Rxa;(P76=ajYO8&B@a=fWb zub%Tq^@;~*HmKM5jGay6O@uAg{|=%)WEHdbbR0?_UH(SgT9=Svvv!f)_tBt^#E=a| z!Ld?qKbM`=Dw7{U)Ko%tMRk+!_Lk1|coSX5fReyy5El9P>+iRn!zR%w#*~K(6G^*< zIDOq3czH189_m!noB-LTTf!1sl;dmSK041qg0E_8akdjI+Wb4GF{dJSDl3BdF4mGY zCPv+7@G=-Rd-qCw&0(pB0@>_5CID*1Tm#za#9RZ`8->APnJK(ZL1_;Ct0vhC3st$? zkn2ZqEdcH12>afUD%W~Ef;i$<>4KX3k|d?~gvgMsvmKKQ5}@7%ks@4YNBHV`ny!Or ziNy;D0QsVZg?XJVQaHCYWd5V_#>D1J_xjGa8;h8Y|s7;b>T9`?;$RAd*Iy|} zZ=X=}QwtnQ6XQu|avh#JLd*9cpb$XmxQ}wr8Mw=#~#?U7O86h3iEq2cQ7w=LhCnj`jY+ zsD^S1qu3Lw2ZL57M=akqT=h`F|MZlF!yn{<;^_&t^`{7v={N0@e2lpP!TOja ztACpiaD*?Lwlm!xa8Vq1u|V@{iGr_0%s?FtB;6NuV+6UK4d^NG34i98BQ7{x@w9@@ z+8+_I!pD|BQ11p|X}l$J0jK*)Z%+Kv7}&Ix!LjMOgIQT)@K_RaJ-}ad00l`*^+hDG z7jQvtmQ@&$1)+^`YsB7-Hx?ET}m4jV-#V)ADC zGw;f$?*sCrU^t#kU>@`GVf3C{d;>J} z69}OYk_}f@+Wy^CVl-^7>iPY(NZDwtTAQK2r-B@cok?*lrGvYiC5xXUpDLNDrF7mu zuVPw>zEIkl=r*ADV@(DH3>na~ZnY-OH5QlPb1E#M8@_YdpF%GC;ZAmBV7tvV(*Ut5 z#O(}~8`Ep&_?!z*y2k#m{ZK=RQEB*n+K=Ds|6iix`H%bY|5ZtZEe!3$5I%dLLm*tST~)dWNoMKlpY7Wh=4A8g}tn~AREQ*sCS_o52WP<&Mp^zXsL z+`n;N_5{RRNY*FB3tH+W=?`m1#FkTf*ruc|#S`2D8ldi1*FDA>Y z?*Cg0YtxG?tSF4~)XR)m@_dZ>r;>#QRMSzo|IZ7Sy+N$~#a|EN36cR(%|(>1Si@Y+ z%xz;ZZLNReaiUBqYEv`c(Ozh5l*tHxTteYQ{rDlcn8C%5lPYi)jNGHf5zYDf&Zo-v z0l4A|b7xXG1y0d#R1}`vQ)drtPJL>gJ>)UhnIQ!SB3i@gkRz7acn~&kJ4@Zqdsx8{ z_5BTgfm#FqN5V%MO2_~Z}BF`*mH^f*kK+@4f?SI$T=^S6U86m zTZyo{@4pJ^*tnr}_g5@(`;TXi^#8Gt{$Jhvzhlq-yA8_ybweZlW~2)ThF-On=39N0 z6rok=S}PVC7(->*tfl=$LW+&lG!QD+bYuSz^pBVCweq!Sj{L8qjc)BgEi0vi$(#=N z8{U_#4(8vKf){*%m0OXp7#SqVEzD7pYcfapNu(wwqcMrG@dP2AM2CFCR-(_S{hKwp zJsU^rIj*?z0*kbf-=sPZycdizcG&oQ$i&+KLn8|6D%-15m|2%0tBzKSO1(Xf){E-x zZZ85Y+w1D!n51n-7=Gul!hQsLDCt*h7~{!xF2=M=H1mvw(2=%ax!^9=V#6eJv9|0m zO?Dl`4PNu5UE~rs)5mue$Gk1mRg2Zjsv%lk55Dph(h8MUtL4jrj#YOi9^I9f*t){3 zuw}LCSl^vT=yk!4x;=2K+_WhLqEtz)uZhA}XA+o5qs7Z7I@gX1$W0>ytl(~IaJ%F_ zG{b0TVc42587MP`YJyNpP<02{!K@(H5=^}qz6gK4;K9?k6FUfDw?mt-rQ66k&7Tw6 zqy%#beGX*EcucyNAshK^n2_~}CHh_2$U)K~K*a?UZxGKYn7;Aw zh{Ik(nxI+WwAb-;_g|NCdmMHMF%M%Guv5~GoQJi<@Z7`Y6NFcGof z-^yOl1t1=BU(f@Zq&irur=tR;l=Cejd5k`nrX4c=gyL?DGkkJTqM`tTI^ISYi(Op ztre}UTdK9J(W{rw-DiB=cVvWw9&S!gyECkeE7;Pa99c|xo@5CUkac~K=o=r#=`cnYEBBr6 zl=Q?}DCzi8<%=s9Eze=9a>Xd7N{(r)^5j~as;0|~;I0_b-;Wg;^P@mjXqq3Oxb+W% zIJf@oMW3}LMUlek9qlcv)H)8>=v^F0zcF#wI}alD=BU*Xv_Gk^Al#<1%t-)OS8xP_ zWo_MZ@5lhts%XmsTUTgEk8lBX+7)eifT*NEWz51a*J4NAwD?U7 z*xldbwmf))^9u~tKixy;e5FGd@uZ#Z%m{N+zCr@;TN<{vBl>g-asowF zSGrTBdPa;=?|5DQ#L9A_WxTQ`nZB@iyrA>r{Q(Q?35<%R^CRwyv|?X8g;jY}Xv_z* zBUETpx?;N{O(Nf$r0*kX>CSzJL#W_}_{?qI6x4c_rMfN(>}sisPGr^S3Xjr5?@Rap zZJ|#NULL?JJQ8j{*id&11H&uaBBH`8-yqJ;427;BP<@x&Q_^sYH;R{DbgA%&N&3Wj zymG+u9B#>RKPkcev%vb~N0{kweA1#$E8IJzcpwujQ4PV=ehmO zOSpR{@Sofdnx|L`_nyxy`f4Y3=Nrd&J5vLHp~kcr7IFVvxc$Qg-JC1_R1-%ew}KZx z6>9KAe5}27!7PA3f5ioMk0W)lz~DS3uGGRN0swsg1M3c&5@=DSGuM6?-lxteN+)z;6U6Uc+NfyIW zU#>ApSXO9DV$;!HY%VNpf@~vwjmC_rsH?2i(cNt-?5L`&GZa=e_BBR6=&33*8woql zdY^b=xq%xF23SHe!d_V-IPFBkGSoLtP}J1lZFduveNu9kCwY_s167?oKd;WVa#-y& za~9j4NXsg#%2K6;5o=|stJ7*N?C5nwMe1(qs4KOD6&fyW*(ll`CI)V^)7fq+Y$`3S z%mn1GhBI`_lZvc5|JoN|L4uNrc6E0ZExNPZG?U%L6H5GBPH8Cpgvrl>kYZqFE=*w~ zXMZccDP*V;J#)NbQSpar0Wq>DVp`2Oy$@AgtGN2J&>=^#E>uK&X?GdVDpod`7-Idj z2Hq|%xwjP*G42NClnljNv!R$8gS6+|2CAin9KBppL$W8ITW16Ox95{%HzW_l%soab zy`GurZ0N`evl5=y;F%X;NeM*Y0->5uBak#&F2n$ev#Ez34W3^yQ17Pn&~rzKr3=t9 zm|(_&QGXk%r3e;~F6nB?ZIxLg4PGB2t?d&eHpGnZpuoF#XAwCll|;-1rI{ z`-P0%kxSDDD12pe1v$}INl0czqa@bNq$zX@HxjUq(5ke26i(Di@S(ufU0!dY#Izz{9byvIe#fzXTSRPB zDMz=3&#|V#BwI$L_AGD32<{|!6rhBOEnuC-g>#ju{+&m+JC6g;4kr8V#P>!h4N{&m zW;pQ=(ig|(02-K{zRMNq;YENMEm7Uz65eMWfIHNt!B9V^F%9dc#EeTJJ$=m3Nj@Eh z-I!Vg487h((ay3sC3SV`#e@BOuF$yXu&9z>n3^$EYsNe|NLhLO5Jue;=tZYFXE-1k zSSynlR$Eo8+lf*_f>(JSG2CDs(sIY<0=Mu|AYgMRVXU6et1@UKis&@BIhg7; z+lHM1#X8ZRGxi=QWtxS+@4mro7EGRa>><0rGHI^a4g|7@^Bfj#>`N1 zjyR!v5gLYx#fMX!Tn`WqQZdsS{g`rA)zcv)t`OwSBArO*4J#>4+H7f+ni3pNn@!NZ z*yEt^Xd&%nDG=J@Bu6Yt^gI_BGbR;LHpnwES&nI_RV`v%U8id{v0_|YB+rd2770Av zh!^N{aTYJ54T06^1{`Z>q($LPY|W5i7I(506mm$Ssg;+D;GD*ce>acgr}06ioPvxu z(O4x{+gvlYHV@-Lsku8hzC7GQxV~%;X%0PWILw;lLzVHA5!FD0wSTunnMblQykiT` zI^HII!^S#QqXdi_7;)GZ0!_|-z!(TpCvK(As|pEkZhiytTuG^{YH+Y0fB-KNEH!eo zVSQV03w~rtX)zV6P{Vb?@hmo^_EjUSpLO$)P82x9F09sR?vS?=FpTJ*Ad1lUoHHUa z*KeD8Ii+Ak>|*SKEKn_VWp!6%59Z03OC8>E5rYR_x98q?`&_q*Ti~|Ek#6IKoD6&YN-E|5i zB@f#_3~hlYWt^aHY35DI-6WJq80Z953y5kNAY_L5uKDfOSR-1l@8Ik&irppWjhUY@ zg9QWg0j1`WxOjGs*GFYv7^b zK#uz1ggqa$TsPqNChemZ#dn;bQoDE}ney0892Kij^Vz7qne(ydh8Xyde}Tl3*-iGa z*DUoqUUNFx%)>T0)P;3o*JZXB@f%|j?c*+>u7-=)l@K)i522cr3S~R)~e2j|YX1b09VUj8r&id1|q z8xU)>4s_FO&hRt6?!NNFrj0kjd^2jB-1^_i!+cZzv<>hqy}iwaAqJAjjX1VgpPCK5Iw z$`?)3^?+dv>Ip6T=GQ@lWs9e{Hi!koo+ZPuAwnb4_JCzfdhC}s0k6c6lo=OXhg`r) z4EH6%UnhoI!w#bm$wd=o;fewiQ`Tp+W?nO+8O8`1ZEdIx!;o%~Lt`7}$ccHujv;M+ z&)PsUkx|}WFr{^4+(AHIvkTT00&0)ZwL(XRRUA~qGGapIdj_*IqY@m+-Tuw^FEel~ z$E*gIIW85sR<>SIRcl$Q&$o(DN@=1Xroj`}Mp2Has#K8?hDBVgWDAa3Tmu3tmPcxF zaiDa(_+q!;xwuwJWdR_ zA$gl-9|mfiGq9{sED|b6q9G%#M3KHMnm|}?E)ny%Dq2C1mSk~Hwn$TS$3>kSfeQAG z-Zqc$T4(^HQi~E3t|^*luCNe#Ey}c_RjDBZS()o@G0N4gVIR&spb^fQ&TEQxhH_<5*b-;2+M?E=~^HU<<$}CuO-;C(Ir(ez77u=se(+&@tqd;bXHKH$~+}`g^L5lN@!jcVT8B^^>eIT zAhkWz7r8>&Gs@6dr6Dru0~6_xuWd07;QNio9NpX^cham8cUULLbUp5~@{Y&Fw(Whx zDgn9J-ylb&nluVJQFImLG6`OT<0T{-tieuyb6lF)Ne!Y9NplEC2 z+HJ;-l9?%xj15jV1P(O%DxzFnKb9>a9lce_p>GEt0S$f^H`JHukx=38t2zvuc>|U4 zdBMPpQ%NB5+$b2z1rXZeh`wum z5;sUsd7Gbib9`Gd$bxy+?39_ zK5dm!CJMRQLy1?0%$g~9n74cfLhZ-Cv3VVgP0Yy~3oFK3ZsQw*jA)I*Ut7HU!v(S90OecX7OXj_SUp7WA2 zIJ@+e*Vn5}ZJ?@hIaXAVcu~ut)2l+yBc3wz`oMT>pGQ_ZbuJ4J`w;uKr5XZ0T8DS)ONvnC0v zsF5Sd>yv*SOgWa$;=(aX}$=Q&MO=A*~%Dw5uyvTs6bc$ga z9`~72bwk4L8X+sC*CFlGCWc%S?Jilj2RksK$B3~lujI*OzfH%mcyEEHVve9gw~*yY zZA|@}TauWU%rYF}d#exvp-q$ue!^Hz3}r+P9RA&mxmkC3AK-#qa`>Y%Ww?-#YBF&Z z%5Cpp{?=5PkCaMpmAP&W?~*QJ1`9YI_lndAF1u#A_hzj>je4bGiEfr~)k93oiNd49 z1(NkHnY*c*tdk^uVk{E$iIHO=gDrIyA>FGD`9v!jHuWmtIfSN$wtFz73#X5sLgeq` zZfAQ_DYQM=@Mwq~gqF=Dzn&l5`k$N#3zsut@pSC@@F_7qNT0O z|5P)074VCOctmlZBFwYI1hVhR0%SnE-2#4sV)#hp%MY@R1@{e#t9{t7eS1rN;IDm~ zOMMvI{8;yY%7ab)H1B@;yt+$$Fx&X&Ew~we@KavVH+-2kO#|Fx8uOU;`H(4X{Pef} zb+PV+-E=$d?+kAmYMPC`JzZ7kv*gJ4Tht88Ngr=ItQY@^Gg!Z0rS|6}1wOKeyO!?j zIA@oCI;q|TTGp@di(aF6e48{3V%Z-c_f9+qmziK!JO2q;+h zExn|$2tO3b|Lo1_Nsu`}%;7CIlyWq1I>4}v?dq`iu@CHMM3yc(1v{kp2 zyZ<&7FK~R!Pe0K(UARTMGPlH)rr>LDMve`b$x)vkiYq=BZlnf>tYKZ^K_{|)c57g8 zHT=t%w3kn+nHWqCW9V4g2eJ(ms!er`>`Ce+5ewx}5OczMLcp{ph(#^8DCTU1@64v~ z5kZCd#jqxbR%y<>T3BEfLbAaUZH+~( zSfNIa0Tpw$^!-u}@fBBspUKdRz67&kqt$ z7hw!Ha)eo>XHI_E$9 z7HfE5I<3jH;u;%433o*T(p|fIz1Bmxj!O=d#uH^3%jVEAi*e!@0Y$EdR7%zcu@+wq zTm4h&tKjqft1l?4>uQQ({elY*Slv8yP`= zUpj6e)-*oj;^#R4knf1$AIwO9_<`Pds29Mh@o-8d3}ZqDF+}+mG9GV9RVP|iOEX%C zmnEeNPl|!ajc|p>FT^((#5Z`Ndr+x;=`m4asskSnC4=g5PXZ)si;P;+iGBnPB><$m!TBOGP2n} zC+qM-OfRq>iEV4@tI&As#s=}hUTNO8?W0k^3VRP5as5y>GQ4rU*#6zE;)Qv_NUw{WIw>TAws@!NPvV<1z zHL%M?gdylPv6?dmbS)H~f^z**4{`_G5zFaPvT&>kIALMSvaxa(jTJ*f3=7^qj2 zjDGoGB|hY`J57e@S+OwMkdba6t2ZKz0d!$x_V{7V2qW4&_}Yb^)Ik!o1QVhSH14ca zUrvKi6Es{^!RRURRNv*2qz?S!6if2N^{sfBq6QT)X%S^;I{h9t$u&y@16N9J-wXqefW*+j-YQKVue z6{cse;)bySfaX;E=$AggRi*qRVB#8^F$$XswYWo+8)PQ7&U`aucCkuZTAY4R8xUC$ zZWa@-#0^vGT)prsa1Nq80X7gqXuC08VFcm!g76KjBdD=WZuq8Gd{S4}0{Q}nN-Pbb zwk>tQGF2^IERG1YAFVBwu>iLYQe%6qY!2jX1@-tS4XhLOrrP~gXku85IpzE>MGckVydOa1qZ4|87gzyMaMMJxwZUDMgptCUAM?ek!p_e(BJFJTw zqOrvU%81M6U+0#ybt&13-CcEp8W|c62*#*Fm7bGHh$yd=^E8M5*`eQ+bX+eUOTXPN zc#!VjOE2oD3!e9Zj~RF-@#_dp1834uIj_K-P0hGxN=B{X0%LPr1aGvH_SEZlJ#0ot zgkM=Tay08WUVfHaYl`1`-no0Ve%R>tD%jFHryi-et-*8fxH@g4Uy0R-gQ z4gc(fO6y;Qx?K9lGx$I)T&d z^{A(z#mO|Cr$s^C+wEClOdx1$Lj}?J2A9(5RSM{Oc7Cx#5n{)#11-ldV$w6 z0Mrr)U7zXaiHdhx)(ej1k0U=vu0%j;M~>x7!~#(w8!YtBC*%c2$jePp!W&r~EFo@Y zT3~QP%K=u48mf_EtpS^I5vsBg#Ut2F=fNs}3xN0I+t2}ijOw|;P<0DJ?L}A&VGLel z+Q_72j^*GPbY$_bxO>BIte7j-5FklRu(dpw$TDC3rKl`iq$8K5Y>RLrSFe2am!a_B znOnkK$D@vKGfr~+!UWE0(tq%*=xPl=^>preJv4_{(8Rn4i5Kk9vEQP|OvK%#Vy=}p zY3;H2zSphip+rZ26WG(F6nh>KeW_=x4xhpgrg#B|FjTQ?jT6kF3)oq?CN|%ws`fO@cjh85Uw|1bV{D#_?xO(9L=8wE`t3QzWNxL?@8wU679n<#>viX+3PxOtaGqW3R{ia_K?hny+ z-#5VfiGPdx&B!y!ABg<9d#nA8`5EdDmw!)>@lU@=Q>a1A&{%Na#Bkr}1d_cgxo^}< zv}~ydd~Pdmr1*;30v=3EL#`Fw+VYmt<)10S$E^(3bX@@-+VDJeV;bBlQ#^}3`WA5h z_|RNzdZ*+RM@>d1l z&!?Qpo}SRGBz#@pDx%)CvQDO)3-c5Z8Lc@S*2VtBF7y7rzo~m{iZAKhC+nPm)3eD3 zHR`#qU2jUyCR;BzHS&&Ky%*W8N9t~KT$tFjomc{j+3d9hVvkEEzp=fR=C$(#ud1f% zbdNH3WICVX0TWKR^wtY;e`M8tt8aG)dCJ*kjUuxy*zTUNkTlo+Ek^?#X|fDuixTSs zM!E~g$-0bJUQAc+(9|Q&aZm8-#fP{c$gCaZ=}|m;AvhQ<>n3DY93(l#Zw(s*J(D0H z?8M-8cOG&&&y~$2nsnN?<6Z)tH6t5QAlt71#th`{)bOo!jRumboD3O!D^V%s9Q%4i z1&o2|dJNEt38jq%0wqHK6XBCV1ZB{T3Gyt$s2avtqaqVfkqOBi1W%7tYS&8{5M)G! zi?qCL=YZ8i`Lh>75k5PjbBy|+S*I~97CBD>Qss?XqtrsCF=02H1zuzW+XZQDw>FNoKD|Hy--rWx%!AA!Hs2vyVkfq=w8nyr*OB&g@5htvCF4_ zfP6#olQ3m}B_()P0fW(PF6fD5rmR{oHwJy1wWtV!_^*+a6|2_W6OOIVuM4cMVx5>l z$8$4$|2viH=2NxPXYt04g$5?@nH2GkP*^}jA+r-9^MOED#4sgd0Hh{8%1)&WSAo`T zkjXL7wQvXnr3dZEC6__1DT$_OCW^LN)kbptxXa}AxF}w{Haj7+cuLr)u8N))P7}jI zZ@Sikn{?+HVRVE}B#O;xh@#t*>n4lES9JE(vE|9R$yogUe?oN zSZ@`0(swCv)QR-VZ@U^_gdXZo!>Ws4$C59vR|`x17hQw*;shhlv(gE>N%_BmOP5Q> z;)FWtr;X56L5$}CSZm)>Q{%Y7*rPfnE>(M>LS0EZBT_@naN4$$W8KUSbfhA0ON1fE zA#0Q4>jY!oF1PeWS&m$wh%X4w`pt_q=>|(Cu3T-eebyRTKDgRmCge@#%5Ctrw5~}A z>!GQYEw#MkXDsg?OYb3x$Eylu=hI%Ub?dzvV2r|ccB7*>zV>7X9!d zq>t1EKRtCNW4th?l&>QLWOae8b|kSVUj>S~AjSi$43fG)%mb|q>Rzzy;U@$Xb|H~1 zkj>#~hse`FUL*cXM7NexH z<2w#+!aM`}=yHi-O)?Y!J>B)Mg|4fi4d5m=^qE90yMjWo(#j4)Bpou?DNy<$o9BW{ zZ|I4&w$k`dfT+VE0jz8Y>NR(ZlvF|39X$#kPF%DGVW(y^dwFUs#`I7t6@GTjMNH9?-NBSIzm zL&XFYk0Bs0ePX-pG*t?jQ#*#;OHOm>Sxdfn{Fm?;8a+&6O>7m*kVLB4SgR924DWcJ z66V5H!8rGsbNkUY^!P18y!RNvsXP0&4D`*=UG>0cyp9dx_h#r1+dRG8MQ*XN=M7Fa zy*NM6?)}kPT)!`5TjC9~KK9Ge+ML#PdSR|C^(sY{M?e&~w;`3Rp!)3<9)`GllJ709 zm&0(r-tC*9rvt zJ0-FAsj$T|f7FzXTTIpS}yw&=bg_7VO)y}L-) z*t!7GOUt()4Or*(m&~_}kDQVBlQrf`O_Lrt`Nk8H3+KJfOOE18MZT?BzkZ1Wm{eKF zK=g?apnmeGA9(6-{+J&;%?ec%vw`%kYi7_}uPB13JN?*mZ$T)b$4LJ_| z+N;6r#rV>H9T*$y@@q_%F8LZ<50ML)^xej1Q=6w5?JTS4>(Ue2HOh+8t@V2pIHlkd z;80%ugqU1=wz5MQlGNboY}gAeoD4$Q=?BS54~hKAfaJye8wy=hN*zepM~(Pcw|>>M zV(qDvg+)(((*Cf;TN6@qrcAbdr}=vuX%Y^Ke$qQHHcZQ*iBnc2B)qe37;#tS8f9sn zv%?&e^6bGOK5uVAdDktYmZt*vJe}T#^oL6Bj(Kw7o=yC-VNtF!W>dWzyTvFYp<`A8ky)zv% zX}a}Dw=up73zKHJ&;O+4rr^`=!v6!~8%a}AJM0=)*C@fE_w87j40Qxa8+VV^%g7wd zH+MOjRTTU7#LOTajt<$Cie4DBzp4MeI%F0(W=(FB=pf!1`xQ?XXG zm@~2{+eTP*8-%;^p{C@+9&&sV2)vYFFf5y4l;;YG=pUcpS)dL4?ey{9e#w$DALVL%FDO9;#W20vsEa{%fkHfEFU~5F^Z3dre0V}*gpX(mswlqaH+FMl1%M8jfUr$@ooGp(img#~T5A_X39W{Vb6# zdR8WR5+!*eeI(+SCtNfhcxlk5VuFpHLPpEvM$Lr&nKj9>%o!jOy`m*~U6r`qqy(XF zM$ocA^f~B5{2U$!@ecs`0fqcVfc&<|0C9eg9{+gx`&ne zAdmBf345l0T+i>fxKhRlzLMNHQPaqQmV09HIA^Db?HS)`k`tJo`r!wYUUBwA$&=|d z8H3O_5AH?!%=!`&v{2rqou=`{N_!MQ1EdlSiW^k!u~?TMS{$D#j~{&T9-!40-_H!x zUJp}PYFoD_-MDFRuZ=IAy6v~N%i0%qn9ak%%{E|G>i42;&;v~)r0r8SpiWgQLky#+ zI6=6)3)C=!zq>;9jS3IP`bw<;V%I(@Szrh`84d5JV-M|vbjbOBfq)uQm2#X=LNSkd z^N`FpG!RG>>yszhrT1sP{ZgU_(WM6x#s|goWruHLFSfO7;{cnjPqD;MUWO~me=(X{h{*VM zxWdD2^ntJDFS>jS25vI;f?RtV-&^tBTb?Ws$Ol4xtYpCTpL{xFkk1ES=+d-ZF&!T8ni z?om^4L-Awofj_Q~{pC!koE24@k-r1>Od~sNgkL%#^Sq?L6h3?XwzBo;csD9YVZ)J* z63mx3Nr3oxo{YFESEf--r0C|@Q>McGr__U_^Nxg3sV>;77rdZjCAk3lc1iryB2pQu z@?T3xs<@9wO=7z;AuF2gT?yE;KOZ+VKOHwL{mdKnUG#>6|ABzVTyd8Ao>;V|d*g>& z^i8dLl{gAEp^ROqwHGStk=Y<-2L$0`5dLwnbzf`>FE;x-ikB& zE7_N3{tNv>1avz~MLA%4tXF@DAB;Yc-Ltk(AAqlK7uvZ4re%~Q*fFXPd(JUMvGg3G zdkb0)Q?Q2o^XFQP{ajin4~O7#4!*v3q#i!X7^+?PUyz0h;pAPR2))kfI) zI-K+)Ld{&;pcIb%Jh4OT4k#e6m2S;wu~(Mh15bBahTwxlMT5}MblUpcdU+E3S%ci2 zAqb0h;eFq_xm199MLpUilzs5ypf+K?ha-1P!Y*zq5$TLELm@iOF*sLgsB+vOJ-AP5 z(Msjlf@HhKp9DENKCsKcpQeoaeYiSpI>+uql$p8S6D@k4dUigbgE;^ld+?cY zTPM5lwp;e7g_a@gTk5e8$JY<*0(+C)fZYPpqrIEWv61xKm$vpB?$?jH%p{#ZMQ`~c)X-1yT!g`96_y(%(5CqMt!96w^@ z*fm540N`NopGJci{-Zhmf2Umkw?V!(U0WSl9cA=~JVb^LxCnyC$TpR#0LiA2y^#u$ zlr;z|Dyj`G88}AP%*YI=@a5wP`mqJxR{y=A)w-j?y2bYyy1D)f?#h_{BL@UzPta0f@LF<;=e2Et#2<4%V9(OZ=JBK3%U$To8* zV@PF`<1hwNLmNXJ!-+u}s6Qk!q+zDrg?rN+T#WU5wH%!yA8t6?MZV$#T~Is5rx`5D zo|DIzLvHQk(v;N-OE_Sxwo&EXW}91Tw|qk@k`FeS>1pL2Bb6^ZNk>|e`WbAmN!%$b zS1yGa=4*OCW?M{eO?Iee+b_CLH-F?bdzEehhs@yB!9o|yXH78TOj(%Kn__ep=+L9p z#wF?C$kSuCc-)ho0(<;Qgkcg9hgfpbF}>ccShkrgUFDcaH=>*?{IkkrG&yG)2#qs* zigYrLN-1sGce<`=YBK1|3^JR8BC)8p9S>7)xN^K@#@mr}V+R+9FDuxjOY` zVkJmz`WDN??wW|G*oBt$sB0>47=y6uGZcFXbu4~)Z!=JEXu@meh;8CToYPGKQo zn2P?7amCy`BCme!ysYnir+KZDUIJz<|22=$GV6e)fkFbm5~zy(c;(| z`zLJ99e|Q+=PWCLmiHr53=a<|;mr-wjGUesS1hg#i(CVaZw@Pxp+v9;d6O3{+wGJ} zed?o=JieO>_Y!}t0d$v2wI>ZXr)HZ&=blC5lcuwA$j(;lp36Js)dghb=C-Hn$IXUt zKMtT6zfr|F<$7E~smC6cruaNKW$dC>&pkMywhH7yza~e^XQ!U31K z{mdv>$g8DMSY-HQM)tw5H3gI**{pgZ-G|vKPca(3F&k4ycxR#-(Sb9`OOc^+{S3)^ zz`s;~z^$5&h@{paks*-j9ulfP)d;|Pv-k#se5g6)x%gUVshBuuHK`KGCb`R?>;?>5 z-qF2~;ZD{D7;}=(Gb)Y&&vYz9e})G1fdS}~h5||8gZ_MNA`HH`ez?!N{}N85tRAG^ zV@ba72+oXD7i1DjV)Z2bU!^)xC@hoJ7xGEY>H#FvtCQ+LB&}Yg-Z#}3miwVQ*NG{Y zVmv622+p$F3v3m;{|{^599;R@beox&6Wg|J+qP}nwv&k`b~3ST+qUfqZw}t~e&^JE z&v%twsZ^zE??3j_zt!FA>0S$@0^%%A;mh_aeuyAmMOaSfs@xd=Pj~Zp5X`oy=!S)# z)6OWFD3`jU-*h+iiclqox~b9E$U!wOa?`OJrh6;UThh0>Izwlmup-~#7)lo@BlVDT z!0qknGA=-iSI7u+KskEo)DB(bSH;e${JcE~fep}v? z6F*Lh`qY%wg8i>h|97<~zJG@L|4!}c5A2Wnv^GGXgB{=zNY6JD6OhO;^Sil>)l|i^ z8wD2bU7}R#lOuRA0bOpeMpgU#dl|bI^eQ#s9b>rOq^}c(`0$_7h z6JDgmX<`aS()_)sN3Ej3fYl7gfx%um3SKYj`v6J1{|~Rn?*^57N z%r7cVoug@fWssz$i_x=oCib|XoseHrA^YAUIA^ki=kd+lI7Hf zU#;v5NONSY#kJR8rHatn2PVjOmCd2l7$+T485nI;hNs>)^O1bFVZ!G%4VogDe4C=h zb&=}3qK4R+0UL8au+igI{iN1n*1*^L1G>04p*#_raqcTzFZlRc2KAn}2N?7-t%YX; z^Tf|dehZbWtVW}@&ppq7)|UNm#MM3(hRv)^ep4I%Q-1i5KeBrEdR7j9#7Sn7l?{f_ zr$6=S?Jxb86@P^I1~NQGvM0RZYgtpXnMB4dUEA5>X#eb=%nu9NduwWkPV$}nZGhl} zvAkai`+8YOrv&*!zjcN1k5zsvlG}-8rZIN8F!uh)OugT~^m%`R>>5>->h8A?%fD{f z(3(CdWwtpoS(Hy1dk=vsGPgf{3%;`1Y+Xb~WDtBu|ITeSncS=c38;2^f@i~ISbv_%avP`_+o2c% zrOe#e4XXoV-p8Sk+@X4IX%%kUUKC3PsXwJJ?L9AjeUl68n7tLV@gXqpRwtmgLR>2n2RCb4}1- zs7X_n*NwGVJ;lqf`7V_nm5mzh%d%hZ5z(K15n?5>*3OB=U`F(6N!x2(hG_srQ084v zbeOre!NUTHvUTnE))I5cJ+UrimZmu?kr!H}`UCQb&-_u?SBV=^ z776o(TRVu-9ImTEa1<~bc5*$f)Em7i0rb7|BPMcb-5~2t!`R+dFJY^4zrj|6 z?hV>TpP9Ksz9W+End3j=_-UjwJGkqX6eHA@ggu6@k zo6-at7nu?V!rBNqfb1l22FT*e*xD4nx{R&v^byo;qM`j9_>beogMUh~C&N(q)iZ`| znJ1g_3n@&Cwd|J~MSBFEJ7a6aUdNUjq3BhJ=~o{8zISkhhsh?>5B2Ms~c0}YaRt0)zrE3%~)66i(q9bQ~&kcGnH{M>RmMl zOXIH|5Ya7-X67XTl}yr!Tu<*xm*02uKr7bEAsL2`S;e;oW3FO1eI%Sy|0r2+gv)2puUK9 zp|pa6p%X1k&1>K53CC&{RIM8PS)|jP`Z=UiE)=ybG)i|!*Oek*5qiQY^c=}jtkQ)s z23w$8lX7FD-&m2!z63sHCo-yyS0p9JdXAMJlimL32#1s|FdEO$3Nyu0UPU2b#+Hc8@=Cg(B8)6(>Bh5 zU(cS9{txskP+a}Z0ElZf-_8Ov4Oz4~Si_V$h+Qh&lVS5E2HUCm zIpV#_6C@!u+&52v-+UYifU#Zak~y<7*SQYICdz%@pWgwy*wt@SdYv$CoAh?k#Rt~v z>>wMXTn1BGkw=g()Kv9``a|f+Sx~W^n{J#)y;#t(a6;IfWti8#&ESMCS%r`zlV1d` zeK)@n4gsXfJz`s21-cR>N8>SADlgEC897qVe08Z9g9v+QL-mpwKvK=S7jzn9$SLyk%qn^OKN9-1I zA6QS&!2_Qg$_o++^l*!H$Y7Zdi3!xHT)pXX>&pUWlPRlWA#tWFc|8~5oVcINvBM-m=b9z#ymCw0gLyldY}vHvCT4r*%sNk$KAoZJov`|B zG$0$I2R)c1hwQa;QU2*ij`t$KJ^`GI5#bAc>@^vamQ&F}fd-=pN`z?_1h9f}i#@~L zfn8QEgaw37ALX(Xd{YplYb1O_wSSS%loGKcnx?d~R=3i#@$q*6 zP02l4aauR;-#c+!#)^dB1WjfCaZUZ7MLPZ$lK*h6RDRXRzn6RlcJi(CUUPWMUd=`&t`@g&_% zJ(n+4jK9g5O|3nAeLtjc?ezBf0LKmU1jA}V_V+*a%vndY1{!7_k74;`C)`s3Yq)lB zkQm4Te?cDzp)N&(j5$7ymY897;@nWKMD8B+1uFMbNPb2N^&1lDa}PWfxRq z5p&cSb;81Ux*;;xTxrf|d}D5OMOZDy9fmAex0^IIO`%@Q;LY{Yao4V(rQT>cT0LF9 zF-l*|WsZND6y4ZNjp4rSVWpIPx_3_jZ3b>O*o+k|*iY3WX>JK!0M`PEEN<4VcMeBI z$NK1j+-G1ap^>@%Ce0Y*^$ZPg!Xdz&&S9plxF0cRRXc*9T5rq_HaM(9R(+%7CnK|d}hg#}S*@IIj-8nSwGqmpS&)^?d#2O-)Va~|5>o$+#d z8qa`Uj=xfYATspE+f`h47>c@-f-N%2(+rKCcK26gB*z>LKEzM2@_>tW(6M%LQZ{D_6KM^RGYFvsC5z7yJz_F z6b7uuQ^mrw4Z=m(&}J6m>0t2$;XK9Qj$|j@zz!Y=uX@kByqxKk$yO1gVHVqI18;p>F^H*JQeJCZ%aLM`4k&#% zt3$dlMEzXAo?P%SYh=1*&SLuB1G%>y5O~(MLhRu3`ix!|++K?iMdCvH5CUFc5w5Yo zK)-s#z9TL9k)GjGo;80ZxStB<1^TY_rK8m!)l;jD%1*{SOY}XUp-P};h#;_0s_!6~ zkTW;547CUh4MCP`r&t4b>KgFoncH6nZbx+?@J*OHp;9qk9Ds;migEUcF!l^&^r)Y5 zB9t#O4oi!EoISt;?EUw=7JWMacJ=vWmH)-s?eC4xKXY8a$pU|hK$wUcS=t)e|62@5 zPD-Vw5?8^$|x8)e`-h`u465mBHVU5+?HtLAW~uw;iSHKpqanDJf6HYQN0 z1cWHpv#0rVZ~YP}Iyxx_jB#S9ICuNtA2l*6Pf*9kKr8Z>3de4!X^x(x2a$dH`dd>X z_{O+n_Suxk{|1s0fIx@Tu7_ft#9u-tp-%7T=c?-#vH3&5!y9!7F&}kC(0rdpf46c8*sB9eH z(DM5j29;uj#qnHx+Tk(GXvY>5^J48Coj7woV5nuNUA*k<@C2S3&_@HF6R+bW&kG$i z;^fn!iNa448ly+d6@Xh%hpLbwxk^OLLK;}FRE(R~sEH1A=_0UrYdV$aSCMfxJj1rO z?Hrw_|HX~q7phH5xlqf_;*54G`P7r0Rr;+9F; zySLdy#os1ZL&8~!D#-!Xq<))8yJz^qZlGN6Q+wQ?P`M-Br=s~iBxebsBUHLB4C_oH zSjDN8j#N|TieU8D>>#?RYC>iuf?UdWmaLrQB8kYVfi82Voc)Wulk%GAkgr~w^(soY zp=rf{-{I~4fW}E!!b&2h6Re9XtQ_6|2r9~T;uk1Rhszq}`b@`FR_o(}@v2y?F4>Lb zYWrUlIVO7gvCFR1#mbT&Qwqxp?hUAj8UoV4X1Cbg5`Z^5&zqv}w> znp!B1-01{KRX@}!)^nxr=o{a{4_-JUfHV7rA1Fb-aT_0DsN~yVmnl0vijDS8_3{!} z&sc{!gACg{JTOEaklEvyndqi0d|mE(3O>zGS10L&i!?_cuw@|PlmRa|AVF0y8S-fY zdWr+EevFd$U9g@;Yd2Wyb`4)C+`A#905^BPfLh$p@qd%l9q(8ME|2f2V~z_h{q*`6 zQgT{wnFXLZ{+?mXWFpfIvguf8W7kc+g-tXHZw2z0u*xmUiL(PTEH?vjw0iL=?-p-L|5$ncosj>x#T%iFwSc9K!@rGx{*Ykew>L91`B!}) zOBeo?54QZlQRNYF445E*!H)GpI~y0G2c!r1dsJ&wbUDN5Sn(4RAkJ3ao-q?QAjgq) zY0FV=W#cVy7YRFE8r=qX^>jiHD{-3_ln?mu%$e1If)Y@1r=eNxc+Adj-m#A0`PvbV_4{K89on{tUjorfbKQr&-dD{}H9dlfrHD0wx#b`+{h{5fac84D z`uSaneB#D`#*F`ClN_c$>5D&As}y3X9L>n&t~C@XaVpOIi|Lq%3#S7EOU*DMz3g?1 zXrVKSS|R&3w*m%y^mjn7f6oLPUnr%XbsN&hGE*5GF4-I|CtlxgZ&7?9um`F`Ex`Ni zxcthRa>k{sYF5@}4jTM8K zbDtTrs{ zWlnxUMViM!>C&ExgMZc%UOKS)A^Hr4tQcEtLkk<9+aw2x5kkdvdgLg2R36%#v#XR`OV-i8Ho4sPbu(CwBAI+VwC( z9NC^@IhlU)v!0fL;F5!T=M7hHYX<3pN&?CjolQJ3S3?bxvX|@v@eA4xgE^QN&2M7w z;96-x6-y0P*#lM2lEVbpqAE=JIAG*V0SL(#t}n9Tas3}cbhS;d$| zu)XRfE$es_2^#XM_~>IVpGsj!?rKryzB6W+w@Cg-tfLwRWTD*xk*>b)zoWIQXA zXWi&vsS6=A56yZcXc%n;>8e3f;eON7oHMJCU^TNm#zx&k-g21?7XidRa~6O#qa8!} z^IQ4U_{dm%2YIY&L}Hy|Ce--08Na^kiRT4QUoT_4 zO_GwCRWQgZi9X?1O`)!<8~GC}q@T0!{4-lL+dt|6l;!~EWKCS1OW2_#8bmfwo4CEhxvLJ0Aj(d7ZMYo^rlK83ix_cwWu&?1pifB#rDpBt^gEex1x{wSe*|JPFi=Z)&UNr69zkfm)D44rn z=gP?^obCKYgYWO5ME4m~de(;aHfDx24oT+n~}A5)xyu={9{|2a!lVFI??^Dw1q7-RX9H5J77_jYnl&&d)p^ z^I)(!IDL5o>;i_dLaa8?+Z2Y8f~0~31uC$B1M?Dyy>ui23i7*S>?#fsBW#B%UT}O9&JAHRz=YK*{>-fc*bJ81;gr`= zVhtalS_1x9Kyin_SGzm59543+n1MZQqPgs49gmM~nb((&9Cb=at^P7(=2eJr|wlw{uzP+*f1! zJQu(}%TtKoAM3w&8EF6ObFnfqG}HUED*9Jd`}eo~2d&aS-lk};XYKIY2}}LFtU)`Xu82d>{O$iy~( zd`kp~eTtlx_F#Fme>A=T=aTd58K*#wWkecDX4*ar2J|tovc+)eZJL1wMi!MPa7Bq3 zZoAP<>oFKfQ@`#$h+W3AVQA$Lx(O;7hd+#>D6$LfkaZUNkMd3M{`No$#aa=&u zv3S@u4LhsN!$3sP&~z=rVKFl7tG8Br8CuCbajnPX-bYGxH7h$f%1KV6DVJZ~8iW*d zeNF1Rs2?Gqy|zP|$@&)SyWD280$XAMdZcv=Y1Uheb9TfI1s_7uN=6F(^w^_?D*KO^ z`w480Sv%3|HDp0$xhLYAa2ghzOUX=Fx5QAGbb9*TefZR=sy#+nDw3K)1AR<}M}?rn z7y{z`HJTchYBA&-ZRkf$6SVWUP|HZGP87~g-|?Z;OLTgEA#CQ z=6vMkgAbpZ-kdJD60|eR+%vIsIeLo`^`1D!abt6}=m~suPpk*s4*+KG9^e&!id89! zYk_hNqcR}~1i~cL14VIn4NZCjjQaRLWErCi7st$EZ?Vbegw#Ms?x4;=q6!rDR)v9i zbzO%|hPLss`v5rm9tmy}=-a?WwY@}K3JtNWKOA3?S!AF?Rv@s7Vc*fW&{@wGKUjn; zX}=E?IxW{xr!N?#pNZJDecw^>qTmiHk&b*}6!swZ#;Vz0E#pG^K`e1`BR19@PU7=BUir9pF#3Hy6E2@ukN-2kmHw9c{=;3;e+Y1KBTGv+ zeIq?;xBAw;tSMPY*uojA=K>|M(0 z6GA8Xckr*fK(FLNmtz}br@8wUCN46rv$z;I-hZ9Gd;^eLqcHfQ;)!TCKWL=sVBFv9 z^o@mc4W86kAZY;yoYPtYOCxWG7VG>HBRyzWxk;otUT;!7lf8I%ZET4pkr0O+~d-f%y3|h1QS2la`1xh18|#vIhk1Fi=r{uKvXT}AeYSF0B@b9hNl1K0;~=i zXdskOHCbp9)*>hFEZMN}MsnI9&ae{?LHPr5DMKc^YiCc@&7@0CO+`8>Jbi6asKe=7 zuDo6UF7xE=mEFMo*PrS`*Q27l-6)|0EPLG5-+R>>tVyQ2@K<$P9;yS$HE}XUtOlxv zYa^1-f8cfC`_ygzpy%0}UHsS~#j@9A4a>95$Q#DQ_}CsYaC_bt(%fn8>ZGuZ7D=iG zes$xl>@lx?{hf+u8vBMn_lc|ff5~_McL4btCI5$A(Z4DuDH#kp*kGLmsjqlePo#u* z2-al$YIt^eCw{nuvVsIeBRMQ2sg_bG95wBtuawfFm``8chEj5Ek%y!MK@jD{XUJL_8J3V{j zZlun5v$Zjm*(QrLS0Z`z(aY4;?W&31>*tD+l>(q9e81^}GvVr=vLZa?Zb?)EGecA&YWAy7-24Bm zigQ31&!D=%d18+>X&Wx;d;|V1jbi5>l*N1=ck7>N^beNj?{M)SXz>3HxcIYkQvvrx z+(-KG88#+amc#`DBlJU!?J>^F=jCJ#4t`I3($Rej| zD6W`WDZQ^W1l&+R)$-VU^jdwfw)(Jfc6P2^*3$2Zx%3)*+4#`fOmCd*yxGbFNG?7A zSlIRrJ_Ri93bC*S;r_Ht0#Hirheo%C%4V-^66+NKEFP!iChi@l$Bf_JrC-DEC1G4c z?{dTh+e&y!9J4MPIRCQdCo{SujdlS)(8{!i(1p215%FT^+!;IxG!+b3bL%?>14`@f z2$08$-z&%FO53%Kr^Zd$OW=QNYQ!}TzD37LO(|pQO7AP}sT^En_>^JE^Euk%svLYM zIB;9@=ufGGm^`_-L*&U9OfzyLLGP*d)PYZ_leBF?@2U0BfmghV*kxn()DV1W`cxTw zNx{o^Sxw2XjKv^N#!w)Obt$dd;1*XgRX1FPKP<>NgO*G+df^zOOg`7Y2ql~wHXdwr zmo65>hHbMJDHt{Js!+2y;1OlmX?7W!_JUaGF(#ntGD7TzzSAz&D-KN<@7xF%agVkQ ziP*xqFt_E4=>+4{42%6}thN$n_<(FA6=lQFYwS2ASqZ*69Vm31{(vqZY%*5$%+a_y zTs+ScY^B9$9D!A_Yk6TOdXS+~=V~mV=M1h)KOT7*sUFwY!PHS{v8R)pc<{T7m_K)xTFpsa6SIdm%Nxgf2kEWeigbOLygFsb@`UDH zxr_2dwA;`VaSj39Idg6CDje-yw(HVUht)pzzVid~dUurFc_)h9JBH`VLGyy5aM$u| z>RP0&d|QV7J+jmEsVus4`;z_L&*vmm|7Y}Dli=W|WA0|nBhITzF9rMiV4wic1L+ut zF;l*}_;D$}(#c3ssiUTEO5tnEjA5(#{85vpEPUuOdA7OJ#e$i6cxB-Zgx35n`EqJu z8HiHRu6j-Bv3YQ%@lBz5K9nYjN9~-Y7Lyo$7H2am`5cNeOweq!8FnYLP$}Pq1k)qx zp#_P*Y+LSLU>#O^fdze3P|uB6BPaxk)CtCT79s2M&#=TXHKL9m<&LlBmIV>TU8%xr zl&|Wp&^bS%09FBl5CV2%1~+YWZbs<9>%3AH`kIlVWJ8L%+PX#0hdtFyKn8tsSC$dR zz#kG3w5>?!HGtu3+^6q&M;K(c19L~dpD9~JiW068%V3~5Hk?}TX5n~qf9QJr0*Q}5 zOg7TR5#5VFM#<0=pxiJWPtahTRF+Y6t(KODJs|w09x^6BGKt}#sTlH{zf2QhSn0uS z;t9#x;YIxcSsh=s*28(nfCXNXC2&Bc7~2dYfREj79Jz%hG9$ zDU_cPXm4a>CSG%ddixmd`ZdB4!w#SoHQOmaIB2k@gFW$<$Ab{uUi2$@ELHUwf|)b? zoQk{LEqS>4BM%#>m zzD!scRmNmf3l5OwM8io!XVUsVPlXYrAe-MrW&3H)xinp&px<2eG=&YFtn zxdBlbrqoh6qEh9haQG`vs57(;p6|(FTuxwgds>fvBr`^nq$Ur1h1WsK zNFKY>1P6`jGF9x%UJU6_1;NMO5mBinEmB!X(Rw@ty(D$`L*RQxgv8O*Kgqdye!%z+4klP1vADg@UpD%)R7Vw;V=)1I{V#0l=ILQ1nn5vMmF6Mq1z%)H}=} z&dGQQuGmp9DiaGb3-S-pzEd;DGpJ$Vg22M);P_>g2Z)I1;pgF~}YAP#| zVl%?L?VFP;kMRzA;e9>S**m_UlHwr*O8F>of-f^>KSWR~*C42gWcWwpJ)gx}`IUy}(04Yh3o`?`nH5K+}HWE$_u6^bSw-|i{3TW7b-F8+v>)0LMJ z6><~E;@0!?HZZ-?)@`kfVR)GwVAMY5>b|+CxscWbhiJ<{GGI^*Bx}pT6&~_h5ql5+ zn|&u}^I{MbygbCrPLZ8v19ic4CLcRjem<(5s^Zhd54?lgKF{cPPi%+lubb}?g6?GB zSdMm-w*n@f@VuG#X61T4QajDRD>v8m6to_9IJ`2wsz&Z`&VXG@&fJ$1Z4#{WJ_GuU zfBb&u?0#3Br1ePwfnxmEuJ`X<%YR_${#M4y8rd7$*jxSUIx^t-K0qsFOtikB2%&87l437ls+6{zrB0241Ufft-QO*Y}aKh&v z2@N|0QB9zau%3+F3bl|sKds*`Ar5ZF$Clr2uN!&3HiheBf{zVO#{lyo12^Lh$z!4! z8p!U3;*l_p`tKR2hHX;?C#0%NQyh+(SIFxOn-YN((q+gtpS!o5TOB3akS6-mWpL@M z|Ln*lQ>xpSS3(s;CC)OJ)frtYKQuontx{~MMIKEGzhU88NBcxQzX=={lOyKhvQ&8v zK(+V&DGr;J!p5O&LK+)dL8T2wQk&_zsQAql`i#;Jqd4Q@A&i##9FD?RK%===EaHOoRRADb8sZFe8$b^5fztV;HlbBOttZA*tDBUT3}I%^fq_3J%rtw$}0c?w6* z81<2Jq~6hA(HE&}$xRSYz4B$x(FRK!>@MREdN^)q1J+3h$%cH0Q} zji}OMhvl8^R;+<}e0XHuKhk`Xrm3B+k`Z0KkPy{m7h0HEOKjrQP)+U~$5)R#ZUFKI?sBDE3 z(nzJMe|^#7I1&DEeqz<$=0-|l=@%7#U%gJ{c<#vRA{~HFf!)i+P4LgBMG8pf{qnt7 zYOn_}x(qzuj>u0olQTWAD8Z}Z=^dxMoA{shA9YLCjEubu5CuvVHR9rV&!f$b}nxfdmzZ6BerEWw; zxdkqlV?CpD8Ky~d55*FQCqf_dvHiUWq_V!#2HtRLw#6Z5#hqgK?xU*NvPP0O)^ zm{e;EVY%k6+y$iE5un^A*t?>;c>=O{LR9h$cDZU6^v;Q*=B0L4+288BK;nnbd9y4^ zE67f>U2w+f027LE%oSpv#?LhUxqXkjq7tZbhhIcFbO9By5ynGz-R;*3Y4AvU57xds zx8xGKj)|i(kQj30;cLSD!!*~AxZ~F)RT?kO^rhIdAO5=}$}LKZdnbIyCfN9;>~%ER6=?uSvF)|6-zr1!$|AkZ2YMIP5{YnQ_<@DDCztQ4ZEGY4&|4J1MV~6b?h?&V>(?jZ3*+Q!iZ8o;r*?v38wDKBSf&xW2$oai-W%TZ68mjNc*-Ncdli^oI#@ z-4q#l5FB_=)&~2I?C73@P`U7gWx@~0reEb5JK-aBMqSkh7~paF%wqZ(YuR!KcGWfg zc~&g@;8)PV!D~6@RF@d)@~yZ55} zB~cIDso>Gpb4seCw4xRkIPO^2b5hsbn=8murwE{>3QM9Puu+f#@48dcMAH}#34bzK z6zclcXM!7*Ey6c&p3t+H<{^mS>h&`=FyIL_#Y0zkjb~C-tgwmdaux8p#O9CE6E zsB^If2XE-3GOB7-_gH07t6@`2C6j;z9vwWo(=D*PnJpXxMrhj^Zpyis824w=;a37F zt00?eZ?C8=YaHH~22Utpsn1%YQZ+Y2rA2JR&&6Iq$Hu&%WtAOSDHPSEL%{y9MPOGzXr5W+^l)$Cb;t$^*w zZnenfG&G6r8K(a6gHNbGJNalPSD4@7M#4ex(2f4xU!wg+)^15m1%ZS{PkM@jSUDnK za`sFpNp0Z@By}ZQ6#jtkm%kVu>p3O?^Il97*k}=p(K&ph(aRugi=g77<8jm_iYCm7Sd_NF`l(> zi&o0snzPQ%82Do4C<})$73L@k7Umi7p zF{bFax`lz!gAHG$yDzUnfy=6eyRUW0#}xVj1qN`CI71HIK5BS)5ZiD_hFtl&Bc2i> zzazFq@=%!eu%r3NT|sCoO+_N3`6yhWGmELZxn4q45Brds3Z?tYWt43FaMkL@a8>B; z6uh-Li<_by*HyXtY_PkVpYr`1uNrzDH&$y1$>d=wii?+UI6m2o& zvgt6QRL9-)AL-M@_aDL2-9!}f4uRM< ztc4R+j+ToZ|B$1;Snh*t3Mb=y!Dym~{ABiVbL6o38S_&K+<9omc68P0z=$L_#^$r` zbH>W#ulW&bRAPdlS5#AtlZ{%&vu#TT>oQ$6>b!gF8dbB%F52=@Jen?XO;|AGl&QbM z#yBKwtV^_+Hw+RRmBg}{=$F9RsD7U#*iOq@sFd{}xs1&~4^n5gwAq}a(o>;56>D2v z?A=y+5|c41qn1Xr1}`$ESPF4pm3rvkLyIeSn738MOk`o%-19I9gn8`0XXv+}(NjfJ z=BI5M7w9vHrZexOm)N=~S<9ZQuWO?p3^n>0=``yqS$&39{h&Bc&Y(}?p4i5=;FzqR zgtOMtp`}WMQ5{>{xL{gKT5lN6W{`rzf-G3t^*n5QV%prFrb#@?HJKzm2Bq&^{j;a~ z6`53^x|nsxK>!h}%!I7kUHMy?$##{yu~(Ui)gGu@>(gDg`wXQU=H!5|<&I|&Q)lWO z=*$uIOb%m9`du<(ONgTlx)=R%2ctX1v6a~!Sw2sS@DFi!5A-*@8FTdZ07oBmtipB5 zR!o(iZ&*cfwFz@cXKFsQjEBgfJW-u!uiz!#?+vV8F|&{CZ^P1?hj$v8-s!VH_U~FV z-Z7_N9`-M4%fqUu{GXUH3XO330TzYC$Qr0Zr|qv}a6x`GWS(xT&1JZtn`bpEPl?@a{} z=uA)UoE+gc0TddBIhGWxdH4w!eL&~PN-M344#)@~vUpJY3{xW*jzJ29g7dZ|3eBK8 z60RaPm)3eZ8tk_mfNw?Hz?y9U+|q~OZ8C=a=`7%va64Sjm9A_%1xH)Ztgev28>|PH zd|8g^3>_$t?3hfD9;fnI<-FLdgQ1VCT)%)2x)Pucie?AH9e$ZXel?ay4Jy{j}=-A?NNB7x1ao?gOMAZ~< z+Ym5k|CjQHD3~P|=TxiXX#{n8%#m;CshbQ!^4KH4rs>mvP&oX`iJwtCH*a}@O+&Yo zx*RSnNl7!7Qy^nXl2c$~QgStK*@I0>UQI)_OZTKz=;&2=M}OQ> zDIC7-Q!#cofQ)Gx1SALvlB-+XVWqHmKEisT**peKSp~W6|Db+D@)7Cg_^leo4Q;Nk z`s|)p(Eq7>{y!Xw_;VR4DbY&dbL(dCLj*F%%=fE2qAYCb!xu2zr>+EkGpuY<2Hc4! zYAYCY(FE!Enys2Mdq=>(_wy$rVU!1T1=;nwN$1^}@$Yr4r=+7`c5UR!9E(jC?mw?jJ-moQbfSN@cpTSz4QfgGBT!}79Mw$P* z2rb3s$T*6W%SCr*X%cj%3_W_afHr5!5nN3G;xn_rCZID=^)x7tH<~FxWf5zMRqpTja$cTCbXQuG}LQv&Hv}vW9%wx^}`_HAdy!-smXNGOS-)?l?!!($lDu zW^53s(;w|S%&l}&T8YlSSAA`xs~53jsEPY_7N4+dCSXYFNwBu8P*E-yte`wWC~;~S z3lB*j}Tc|3PSTO zk!znVMsNE)FyA;09}epJ1w(08)a-{1@nxDjab4pYoz}fjo89MhUSYxhD zGfVFzdc;g$U&kx}A`0((X^e~9=?BMPgTmI1CDDp(k%EB+3&pjcmDiSb%^vHXdhJe& z)v51otw8$r@JC)3&^i%)W(%$=DPd`FWs3B(`?Sam>^<@{9}Vsx0#DZt&-8VsFxF8~ zLxiKR5tQtwPaZu8Trlfkud6Ca{z+h#;4AzYd2_n=PMq2=)|;(b-% z3&kT;l$(yD2QPecfuD8He@Gl9#D+8j>;8uA8^VuSgoP_5sZOxWc33-k=urE|ni|2{ zPkn3(X7VOwA;3k8CckuKWvaCr+w`3HD8m)cp{uz=a`C#zHbx%SDX{}A=eFul!bfL> zN_jx&$h2cajlSz5URx&D#%3YR$%6Q0$l!{Fa>7#&sQt=lpx#`XB-iv9z__y;T;jfa zr=eZ0EYUof?i#y{FHq7tWO0rLS%vRVJb35-gSTA*h5?-K^SC;Ghv2W<`Y1=U}gx+`$e_FT;v$(t@B|> zD8{Mn>K3QZwxw|1JNtXV86z{JV&fo4tA_J}YF_7vrg4z$JQ$^ci&F~h*7cLrx((AV z(u+9_`ZPGXVS;kL4o$HMfX7r6yQZ5o>Z=yI=Bj3tyYGH1_mFFqLeysgEB{P?p4Ot6 zu99Pb7LyOT`)X$6`NhIV=-8q9kaK(h-Zct1Et9{Y8Vsc{l}6ueWGbDWvM#18nzr!< zdLRD1W~u)KBmT|b%&o>_#4ukXP%g`^xvJT}?2cxZ06;T)8=g64*hCL{T>PHpH~c++ zjfp?~yo6`|%edRH$GbMA1GavvTTzGe6DPkB#5-*R}X0T2?nE}EW$q;SDKW#rohG7h)N#Rs}jtb%O@-qP${qZ)h-gU$t8yShGfrq(my%bfW?+xYB<= zbZ0_Y&6P;IK`eo^iMWxa*<{#B04*tu!Iw|N4s(0o>f*(p5mM@amRq8rPt!yzrKeOO z@XU;<@D!*A{H`tI(SOYcgJK&od7Au$kp3}R-_fVC{F@I(mYrCa7HvrDOa zihI_JU$sg2d6zvFz5H07D%2ZFA>WinPH@g;ZX)U&w96nvzl1~&vpX3GS}J0Fm#yUL zJylT)v45I|+?A{VNu}9Q59a;`SP~mVR*oWPmKxJW2Ltox!dy22^sVcd?X4ydBPDK; zu3RqytXVKMpnuK_p`Kd(;Y!05BIoQCrbOS0vBx;=4UO(-)+hzBkPU5@L5jr$mjEGI z$&`b)Oz5-{T-(7MqDK63>=T_N;iRoT!4=rM=1G1<<%hJRE$BbPp21ovZ06K$A+U#sEzPkM+raRXw4?HR5cB~6e}R+l zhd+C~;btc(j!47TIA;}qVHjy(j+{4Nx!mvKPa zzQZe%!cD;1bNM;J2@1v>6XrktiOJ7@8F>3UmB;i?gP{MO==^h3N)}5nKeWu2$Fh>j0t}_y_7gH)stE!5Q?`i4$+3B1Pb|_ zu^kS{V}^&#&9D3SFWFIf0B&=mtfafKIgUkj_K#4%29$o}Owm;v76*%u4lWzwTFF4c z^Pl8|3C^G>|MCP!UK1^VI+s0KLPxrFWX?oCeR@rkF)RnVRLfEL=9FnmuUL|xzM>JF zHa!{UD(Ak02F{g8H_Z5+GfTIkmOx0ja|oTQG%>XjIcaNtHyPo`Bt6B%fH4fZ&%*WM z5x1Z^CIk$Oi1rj5!)vp(%$ei;YDSwJ*9&Za$M(MWX~(ti*Xl;^$Jg)f#hPgC@Tj8CgDGk1xat@HM;~cp_|xAm7RAiZ+o( zbL;$ySbxzKFeiasoa-m4O4?U$(FZ7xt#3xnamwal?EJ8JiNo`SvpYJ%ZH`OPcD0wP zT*GOwJ2*fJR0Ar>l5lpwAh;byrFxnkX6E`=GqW1)GW3KXrP~yXW&!hD{itL*3%(e4 zpnuuL^{haTD_+u=Ha#Y@3Ggx+ZQ?3BGSukjGWY7W8mZ)u5O5)LEUat8uBf_GeAR|N zw63jAW$_f}o>@iNJzZfKXpNC@<;#Nb`~JA-0W*)jdD%Wk)!ROLP1I|~Oo#1;;8A23rH=VpylfIRQYB<2(E4Wqk-I7>m~>)LUg*-H|ZYPK1|~3#(}c* z!s>p!U?-YlEFp~s|VIUi%>Rn_<9K(BW&+$|H4^;7tenjx-dWjWjk3hGWIiX zSAr);U%YL@XcB9X{0Y}2E}yr=NzDW5V)t|BkLs&eclq+@Gp73fGMf1JG|BqE^`!rc zv=`8`wA9x#u=pcEIz_jO1M(pTO-e14hy4%I-Z?lEt;-(nbZpyBI<{@wwrzK8+qRu_ zY}>YNcITJA_r5dp-f!m4RDG37Ri0Em|D3bWKI`ng*4kZoss%Nhj4)xDi9mqD1HALz zbq=A3Lzza-&H~yKy`a~*{i(>9JsRuT4pX2r!8DE=83vp=-q7&aUHGqbpZ;Ka>TMRL zo_sDA-{+G4W(xoJ40@FRemQL%{tJCxnYpYMAhCjt{5@wDP zdX9gtexhuT^dIux#6%}xAz&#^G#TBz$WWFD)I3yXch$ZQ-ueVesuPq>2^kF7&s1xa z0UXJ<*F%zd(w_QsSZH%aQ~hPK7Pnh~svE}H>-?pJA%Qwk`7$hb+42FcJqles$h@GT zJyYs+b~D^tT$G9)F!nJ($?Ye&yLACQ2o5+`gD|uk^XH?$$YOwl2Q!SrVzAY+M zGVtu%5^|N)Yp7!_gEA4lb8qat9Ro&q>-Ok1X5y%`g<26mDW|jYNq{MiSp?d*@_Z;h zOJireyRe<>=tdJZ@_r0)ZVY^WOZtpoW2}9P&82O>RAIo%e8ehlZ376roV_6&%_z`3 z-R(vxMWnO3aZoRu!U}mb`2X3EKer-MNy-6H1kTFb0S2g}u$^}#C=5?YopH_8;%0IOY#b>BC$AxOKswi?* zp$DQ#7Hw(5vY{$4mvzxL)wc9QP_u4Gnz^W-F6th&TDy8}sq+nUTIZ23nSf5#S}W>* z?aR^WP+p**3oC1#oHF%_7JY+?jVOyT7!A}5@@$vj`C#V$h=jiVYx_EmV@VH$50X|!A0 z=%yoAZ5)QGaH0gUR^IjZvtp<{QuoV1l+Jw|K*E|*M9Sg>4>@F~i*I5#vF;q_??a_% z5k=R4_PM6PJ(T4^I>5 z4HOqOUh1uOl~iKh$Cc+Q&S>VoD?-!9O-Xpn3N2&4#_Sug<^*mm-Kf~dNyO0X%~HYjQLogb30S{JK_^&K*~c`x5akJ~%4-mW~*;f^Z9 zM(-S~cH{XOzb9&kq5%G4TD4y-&V_75>vfuX?gT^0C3=$C77%?sPbFIz#$j0yMLPWw zK`ygETQk2*010x*j75^00m&iWQV>l?9tX}kB(|VkK(sMj1`&Y_HQy%y3O~9N^fzLq z`@$in_IZbW`?o5B?B9~8!2ft=KP|lsj4bu^Esg%np#t_szhy}OAv^w5X(%{4>Hm3> z3l+3J)rv@5)@?zCfss9f&uEt2eS?7Tb2#4dA;*CahacxqT|LG1^t$}(*WMV*muOp>Pd$=r3wlnF1`adly0K|fVO&$6 z?AGRriD|z(9$L~5`OxM8TKJ-=_y__Dt;}1?Y|N9xc-=nl1h&3AY8Alz1HAF@8Bt73 zoU1@~*e!?nuyH;EE-X7t%$`c->IQ^8Mc8;2TxX9aQGy_$Qv0#Q#B~VRbf`_Bv1#|p z1X{bnJ5AY2{|g@qlsifZ*H`jrXK&)k+$)*y^MTpYJy6l*NqVa3$>yACqYo7XCT&~M z>{VS^oQmrxK`nz9zveFCc@Fgk7xbQ~*$_%2*_9U9C~ias@fyLD^jTsK;N-b+HyJ4KD!oIABysSO3;5`J3v9MP@Y z!mBNs6szTWjeg#s`6%%nvI;-P=M3t*&@HbRs$Hrq^$YOnLD~m$BOpOZ_H+TaKn=IR zwgIrpuy$s6MUs)`iUs4M#1(te2uMI{0EepiE6*R)rd-1PypGQdFaK}Ffxkz~|G?1y zeNF%O(ef|g^Dj}Wtdv9_FPxW##oS_b);lP_yB&PLf2HHDS8POe9DrI>fAAtfrcpo;7WnY zMm>o;R*d2(4FuGsX?Ln|bfJ0t$ENR8-q}=w)`USl6&Wgqm{e%bK52!e22T_>p5;s( zv>8DzdqY}?U$d8$gIP`5`E zpj2>Ar4*LLH9CL1tMA)1ah%HlbAbfGyq`IuKTbQjZV}#N!AyVj1DaH_^!GgSc>Zx5 zi@oA9pFR)UkH2uxpAv|_FEG#lpX2!FQOr!R`oq}bV=XD^QM#Le3PM~ifqMj;KrS4* z2)tIz%MV27IQ`U&)Mc6hK zE23_L*2;{pgL0KBl+!toHTI&6-cpH!o;$rw?Talepr!^BR;rdHjAp~E&x$S+(8X8m zAV;xj1-~iBm!(#n6g`%$nVULm8PXD2B#lM_TA%4(VGCzOvp42Avh6~S&AXQ^n76O5 z!D-1(rKMsN-LDoGWZu9RW3Qq&(|G~RWTGpzG-$1vKg6RcPbqqp%2zq}N4M(R-pRUc zu+Az5KjUv0ra*@nr@$iNQwp#RGvVpbxfUzbyDHTC*UI%d(HGDR>&sI2*_NjmE z5J-#Q)!I0bTdJTEHhTWr01Y;l>NXs9B{M*{L1Q*5s3jxxHwq#(fF+!mezEAk4#9ux zQqco586dNcWEq2U@Fn`O1mtypTzZ_0q*BDhr_%>VBsiR87kEz2ZZ?gP#}xYko<#G` zdyIL}n^N>auI@`bIvmqWZ)}=;Dzf+Oq_@#n>%l^xlWmLiWgkh+Y}{j=YZhh3{uc*7 zu(O{nnvPdp3AQRa-YB=+pws$wNF64rM?beo&jF=-25bS^BijJ4^x}cxs~sVh-bO#w zY+Fc+pb4WG&Q0Z#oERLcG#q&3mvBJTc+Z@GwH5|PIy10(ehe>*L~#@gm?zC@*JG#k z$iY8(lXUi#c+sEG@!{XDqQApO_WyJ26aCwb^jFyb<-7K&6hvr4RmV^lCr_R}hB1B~S`Ova^^+&0-E!(!}CW=MXw5=lz;{`-fIgjnv5jvFuiN%GKm3W5q%F*WJ^S z%@+?c61V|rECQHsCghTZk-LB6cNfHL13Uy|yxpLZs*?O1+ zHscV*OlGNiRTir~r|LOIK>=r4%B4({=BQTMgC||OT`xv4zZZC3kV@mVpc3`ZQvEm7 zYBpJOAmP)wA8~AKqduD*8M%yzuZ5O0CQ9Y7c*Gj!BXM?Q8PZ*$dPfjU-@h517QaWF zp)||fvrH)DABe4K7Kl)sj71*BTP2PZj^G#2meNrniu_W8kun=QZTapNTE^Fx6@<16k!7wr)EU&aEHA4| zHoi+Z!oywZX9AV}k(q*@k+g_xa+j4$Kaq^T@!qE6;<^Sm=e5;|!*Ig-fY&0zQ%p82 z>7G=Og@ky22f-(lVh??nKr<~KuOFgM@P?mIF2Lo%CZC@UnBD0~NGUX~S511yc+4FWI!08ko^RLT*d5Yz zY4IqzLKjIQ4?8ehKreU>79_+m?}Hq9>Q53XB+YFmqJaK(h_uhN-cJSG%w(w-s`q4h zUS~i=oHSWu*VF-3DyD|CuBZCb!VIDbJxL~z6UwSM(~4`;M)B#?5x^%JBRZ?2YB3$E zLR{ok$DZdwv)sfT`_rOWS|9+VFXIBludVmcuYpq9r}d;*@}ri2)}W5E0$;e=_uaUA zUrerg=A2qh*tzKwiWzKuB6MQNifISAZqCRCJ~)&Zg7j`SO1S_a*Fe#&0{{7G*-nSy9m8I)myD5o@=EdB{RDd-m3raH+-{p=}-Mv0#@Mx&H!LLn*< zF}te$Ad^G;n8}1ip*p`~Ff)BX>Dy-v{>yjd&yvdDJ+nSJ>i?Ztgu$N%mj9)$^7lMU z`p;kdZGHK#vUQ=#i3{Qq@&}hj(%@&K%5t0lP@h4a)|yNTv;8~WG%KBiJ|J)$Goe`w zs4&CmcnC4LRT@%V9Gu@A|C*!JNnF#kery0qgA|7QYvI--?}-yHhABd|xLTM8 zHt#d9t~ZaTO_!@%oI z`bKYpZRZ8B_=D}l1(bf-jJv+TL)n#&aqj9%A8T*zO~1N5^k{$a{$c}Ki^K!A8~hv_ zfO|J0<9eq6es%rJgimu|ium2{sVm`{VzY~4XQ}-oGGI%*WiWV&_+7g93a|yf+wqG~ zP*ulk3ciVOgr>HFrIBQ#rI3nb&~%CP&kz!gBz<7pc)bzoK1qtI25I@n&4j`f(iU3- zYsS8AVe~Wy;t(o>x-2?qra2SjTerT3H)+dDi8hlr)+qg|%F52{?}G~!)N8;Bddu!p zynu)tufbqaqih*6D^L<#HRwRK2O*Jbb!HUr^ug$Utvg8InCv>&M>tB9fnQebcYhJa z*JT}OT(o)>#VS)uEYx2Tgu<5mFo&gc96D4)03~_P6lp7p7TbpD{zh$VLd0Yi5Fh=usxH+C(@mx-5SKC?)KG;K zAMN#eyk*4E2^31J25jxtuJHDNDGp7*WOevJvCY1IjFFLwxHwwHnv(H;v=AQ1Q}|rX=kR43(ot`>e#!N4evqszi8; zT1ml~OnFuDu1POx@hLXNYg&=~`ZZcH`-uAfNa~=(-TYC5YU7+N)o4W1{rFxCGy{Q8 zDzjgkxqd$*3S*W02I_oS-fA~jU5t>`8i_246(Ee5D_j#HcJCJu0kqu-z05S&^&4 z4GDC4j|B)^W*80J{@DCMTQ6ibByJ87EEqOO1?208A%fC(eP6gCc9?&OE?h{0`SfNB zu!7%q(Ucj3yz~wMcp~)bJO_Fz&Vs%?3(&jIm!CG=lRMwB)5HZ6Is}{RHsn#l#GU0U z1_UncCIS_fXlRape_tUNkd0P-da0BulrS+e=6$~@!PV6@45TPaq#!z8?HPr zq=pk>m=}kA97xzmlZRj0^ArY;D}_#|Uux4!HjUcyg{^Z>V~!ZgV5F;0-UoyCKx@J} zlUQa^e+YiukN12W@AyYZ=7VtZQW*i7WX=Z7!G?O5A2)}3FP|jOtX!bwI)hGV6GecW zdLXd$AVkiYZc7>TvOweFGTjVji=x1%1UY6BVb;d4F2LjyUgv^Ns75RIPy4ba;rSl8 zLY-Z+I>!nohey%u@dXRO3Wrkl2{6LQU0rfXa`mA($1|EZWi(tnV25Iw{z9s3mmt~_ zsevbksGJ8>10u5uAh$@EcXB;tuL1Q4{4u-Px4FqZ6%##uEEfS;52Y|Q!W3(Kl2$x> zMR|y=MEypRdz!08ap^@;(*?5b=R&b9y$J5|1vJoYa>mX3$$E*Csu_+Q$+|UkaV->j z&aiZt5hdY#UI?w*!LayfCaRv1Cm2lIwn116Yf5|L83GvHK{%Lf9AlJn=|U~)ii_8x z>HsGG9p1im?4sRPE5o6Uu%(f0-4y=?Mn}z+Y~34iXANA~QbI5}mhbyg=rJ&Xd#pEb zXDCxj-mrW5c&lBs<$A8_<$8+<-KA`X-Q^zR>$gtjK1}GuP1iPQ8%{aIs#=6g^GsWN zDOMfg^~N9DtFip*-CTT2M;@8)VjR(HN1fLM?B5Lb4a|A?Vn%f^7aCyJ$>$c;3M&;% z?{2NwSn zxyyP4sQFt@QtHbY>A$kbJ;NRhekAFEme=^>OpLskc`K7jHG)WGpWRhKq>V?Dpzt!p zpBA`TYNu7yOQ#KSkts}T@Rk;R6``*SL9#;G=Xq8C6!bQP@M6BYD5!L1|3jp z7x@S!{zBeVYIv!xE1fLgZ$IK7ztutI+A0D_e$U0c7Rf5a6coQ=lLYE+ig|d0Hv~L3 z^fwZ#k~lWcYpy`-xb<5(Fk@9*w zpr5RWQZBBOeAH+kB?(8p<$@&XLfYCDHWqs4k{}6pUA8~W0vY0NKb~}EP|}gEyh2{M zeHRg42Zir8CbG9e9Q|fg)^L$!5FBG>3Q_NSJ%M~2PGzlNoGEc11zRQ2hcX#~JMGD= z>OeZ1R$Stk7dlGwOv8K2sTjp+{Zdr0e zCl#Od;3KME=6vqX`s#}Z>{uUd2omj>xygjr~#TE2Wf5k}Zz`(eUpx=_j zQ_U6qVpyLT{`7H(4IBe*XtEyxAL>_+P`@3c3jOMB@5gV#D{feZ)qHxWy0t8}QCj`P z&Leb##!vEDS4G#1S#}Y$feg<-49dto0jJoxv+};XMdjrfmXYg~3GWOY-B1NWhk8)$u{B%eeUpFa2zLUYaPy^&chf>fH1@#92Ir{49P(!2S5_bglcg-da2I6ju zpszu4+Zn_^W=J1pq{er4a&>(vG2jUVa#mOt=nw1E-+oPlCP5i-QS2u1Dhh0??ha^$#|OBeWt$g=GGoo2NMLrf;|C;$P7Z3ypO&9P zXSl#SKXv!d;WTP)9}76Y0f&v4J@SQz)Vl;rOPoxhLd&FO%j3!q#9~^EJuTjs!CvD) z^gb&ssP9ykj(O8TmpoCSojvlp4lOf1D@vt<~PXBK3I>E{avg3$CelWKV#+px?x2B z^@Es|ttG#n!(aZKg^GVNri!Sn$RP_8B>)o3$gI?U5ajU20%3+qt)|&VM)x@@pfUpV+dPIu ztx3@u%RvM6EQx-M{vKY7g1PROMT0kufUtB`b#7MMA4uJyk~$ zE9yj%QQPQ2TAq4V`D}O%Em&1I?dJB8df?e%)#+*Sk2haEhB*K$LU5KbqS8@Jb^NvF zD}TiGl2wZl+7D2&vc$_1ba|HiqE$W|)1aasNgL44qzc@7$(nR6YAP_A8Z2jl-V;>t z(QI5PN#tp>N76>-8py5X3smVT#X_=gX?yl-RznWMnGUCNd&%yDFcpv*3y+R78-g~t zw|-*1XuD7f{)C1pR#y8z`43uAO*-o|${?1Qz|TbK3Vaw8G<*-o+C&z1)0f^5vi1T4 z%nFDsbs7Aqf-XMTxD*qu3pcZ}|ADfRU3g-K&1>!Eqf3M(U#v~ob&yep%<^uhg8t?^yF^KEn zYaF9^C%~m{m@&!gg1s_)0c^@kSa+M@HAZe&yJKK3A{%-q|Gwa_c>qcG_V9aJqhTfq zJT_R)3&4i%Kt_Kxzi7DthZc!Vs3+Slq2UqrZ6cr@gd3$~Bff@pVvM^lDs&M{eyUHR z_MHmBM80kW###5@3%;m{aQ(nD!*#yp$iwzUnUYhU3CqChAzvBDZoHha&F3>?H{`B0 z78GU#aC2ahC#uj(AZNPAKZ%6zzf7#Nb*^x~MAaG)L`orQkOc_L@Q!pd_sp`PYHGm| zQ7ka?l~Hp<;H_=@F$HJ!y`wn2ve#|KP+v5cPW8RW&=zL7^4iYki zkeP4HIG7N<_?asx3w5?t&nu@R)rtb`4s_^`^-A5gy8}N~`^IxV3*T4+)W^Hhi$RZa zI}C^Q^NHkMC_vpgJ51zl@`PRm9%(l^)T`j0B8aNAtqR7^=wf9R!DeMuI3Ow^eQX%UOEpPg%73M@;>+Pp^9HI>#4k)C zp@O!Ow=`!`9FVGOfIP9@u>AJ$#;5a+IFC-nAg$xdi(8NnNHcjHLDN~vz&`mLU2N)U;raBX+suLfyP=ZE0 zML@m39hAnc25-lxy%(FFpvpd92)ufi30C`Q8)Io}`^PSyGCzgA=SaA$kfw=gDCuF9 zkit#tieN?$kAr}kLNBn84n#4P!dx-|l!tzhb_3Fex-0~7Vo#se?#v6B|M0-djU5P0 zG6^CB;z<}*_+SwU+IoIkm6`$6r0&*Ne>jF)q&zF(xdlZt;_|dR@ur;Haban4O0uHC zhtVQkDhr{Y>4>}|DS@%z@WKV9zJ^|lzMYI*jWX*%gLjXyFm#IYFd@@5urf0thoq(= zwKVZd6Mv--kmBLprucxLq4!#ayY@yDL6g{kF^R@kvRRYZ`E-(8z(J>-a!}F9_nv%I zee}vyk?g(GoBe*1ON#ZPAW)P&cvPi}mduz-lG6K=WUnY=l}i!V1;#^msHH#KAuA(E z-^dR8sU(=33cH)b4vzCVM7Fq<*Y3ad@hxnr^t=3PT@>YVpXm4%_q15g4(0Wcs z88YypqU`u%%SqkU?_MFOs_G~r@m!&kEWyIGxwVMNBJJ*?a#K5~b4YV@&}>Ub;VhuD zC^bkM=T}wQT4EEFg4*s=IEGou+5F~qlPIY3u-Mesz#n=0*76|ti`Siu&9_X_TpOQe948=}tfD?zy2m6F z0HF<87+y3d!RGfUv#?9Y-m}@IGk|bnMIwQV1`UWsG<$CRPu-nOQtoC>Yw04k8Op7e z-#^_Tb!fQQy^xQhW@iOmt1rm9274UpX-$5p8 zak6aysd9h$Qi1hm;^>Tl6v%#{X!c?sNNyDYnoi`1(-FBvhLExnuUTeuulSG z)3etJYcqI~Jd5756*t+!zr`nV=TLpYwD53M6B&{^=_ zYzL#Gbc0hcZbHYeeFUbUMnIH^0Ti*~$`*Jpt#Z9d*xo)%w9_#?apTTrX64f6l?6Sl z`B=ydPt>1<(eHsvFxm3+m!t6c(X@imvHx1mhd8-6;c*w@hL5bt2T|GwKbFthbTBx- z3-FJ4=MLmhUZoQmc`;86;8&Lf)E&I?JEd6`iUOT7!j4SQrv$Mrk%A|A@Ld>UAexU)Y%|%eaGt?CufXMs-*6rk04_2wac4$dK%N(U_eH3iUan{WqqkT4CZc+K zqH_Ho^3t(Ia5;SOoe_>quLvMlVv5P^K%sAecju*O34q=R61Q`ETz$Vo+~YtIipPZm z7QkcFw!szhQzLkSR@$|Rf|8t{$G7n5giazjrZT$z`C7pTiGpnXyv!w`{_AVy?}cLC zf4&ri%`E?8<^qv|*(c&PlGSrGRdBTb99(1K_E+aa<>hw;`PZS^?C>qx8U$+y)mJRS zcELj801SS>Dsp|ge&bRzF@~hUSy?mT2;u(8*&<>yj9E%8(Ot%XAj$?Q(;R?QVt_bi z{9Lhg=8fjAT%N~_thvWc^c7Qodw0*tIgh6em#fd8Ew4R^4{isTZiIKP?>Gg9#{ggj zr#EKjhdW~c1+lSu&w3zugqYoy=dpSt!@xOs2f-6vZa9y(wy5Qib%}I~9qA@djN97l zOW&)v%Q@F+_RgTe^s*yBRgZeUtX@Oo;N0$|dvlJ@{p95AHQ$Q6G5r#~W5@gfG}TG9 z#{nR?{Py(x^aWPt_8JLRrhbw&+b1aa>h4x;&~7^VXn6-8o#%S*zGQ(JX|eq&838x^X|C869Q>5~8!))JFCGplg(;^72y3o!_}Q1l?_7%shY}K@+%lEL8Wv;5~bW`u@vn(^m-xLldb*@c!~G=ntg2E*Rz+>u3Z!5}b0f=eiaCX3lZhk@F|hqQvyCWpaH|Bckl36b zNl8`_SdriZV%Lr&w@EPc91N_59#wqf(6U^$pUU;OjV6pl{GHd)gvyaKvtII@!NzYp z(g9WsmS$`W9V(DRN_~uu`b6WFfg+L=729Oqy?quCQ9G<0@1=fAcKkhJ+9~vg-B$s=~h3XcvP-oHWR14(APq&iFzG-gzt$O zBLq{*=`D*D(*v8zFk5Nq5S46WWx9f&kTvx|ClYn)hYD2t|>b2 zkJay9C||>SSLy=7cJ1sKyes!yp*??!{hfb`0Q=~_`3&kDOWQECBvhmMrLQwRmj|p6 z%Qm`ZwF!XxX97}lfF~zxyhtV;_N}IwvAS{g!@S|PIv>L6dhn19@7B9zuLC*8?E+u%?uy8LMo zrKn|^oi<@E><3Z0_$EvI&Aua#e@m)c>EUP7Nm$8;P#LmV{$5zeMy#cj+M$*vnRIyd z*dh7On8o)N_KLg`0xs*jM+?sj5GML{dhnUnIHFx|H4;3hj^(z{3i^k*ES!oY1b=d- zC7A$r#jAbN5w(P3BM4IiH4D6EAkVh6NyKb=DXnAQj7oK9>)^@oG#Rd!n?feS5r}=} z!+>!a^b@LhrRJRg-i&kgAMV zlEaG`y>~27?~zy0uq|!_i#g&)*^jXg@Wmi?bA(nr0u%2OR!V5TYXa_}5o({H**;0G8hP};~s9Q6ouED@b zo2wVwGZCwUb|L~cc9i5jWrd_;^!*Wk?dX^l@YLc^Fh#eUd$MsIBF7l&L94YM-biHQ z1iR;;3d>p#y`P{>WZ7So7oP8!ByHeyME*QDe( zRT7*bt6gwVV^DyUK(^x{amqlMKnO%1mHM(gGGm z{0qledq#O40V>@=vxZrQeQ-DFJ$LXu)uH-S1ZuqbJ!m%>1C%KfRNCU9CFEOVS{JOl zwygomtf@2VmEwc&>%jJ(BEKB+-Utp8-Me}w6clDWPUs%7p-^dkuqL$d{TQpi0|Rx9 zXt`eQ8_mFEY78H(O795QEn-pSbWosi2MSeL&4$Np?&^vFWFqA>f2X!z)9RKQ%4l~B z^#>XKc2}DP0lX{bI>7qAOFkc7JVTNt)W#a}u*(J&D$pXs8T~c@xlF3vE3j*Xg;Kqp z;)-n2FQ30{)!cnuCku45Ad_eD+E@&a#5!tCg-VNWlKM6GZ| zdN=N}a^8<-8r;|U-M``jk79^+SM^3$rS`j)g-Z;R${EaT+%@sKT7@6LY$1D}9s$RX z(sDL&vG@Km>Z$dwNg2JQ9-LYZnF+I=h{<0_UljU*;3t6x`XbKxzmAk*)61JUKHPT$e`IwTlURPmGWINB+ht59`W#*ID0{>n;j~X4 zP_5Tio%Kt^2WqQu0V1yJ{O$wwcM&20UTsqt?8}#+f1HH;zhIU>o7+UfHlN(r-+%w{ zu(fuS(RVPicm7w`J5xdHx4@CBo@%46qAn-t6(T(zNE!#8$4{z8N9)_((bClyoIK{puhwfVd)>WxfS3|6 zNp?$vVUZ95_-wIu2LOHI>E(E{^w)dd)y4V!xR%dal?b^AU6pQlc~pKZ1#x2WdX=xR z&#T-5orQosv};M?=l5Gqf(=6)_(q3oKgRmJaKsQzM%rWhWH%S(RM3(ZV{Vj4QD%4r zp)Mr~1?M5$ups%FNybXvLqDe{Wuo46vLM`A(%TqZy(l~Uq}e~<4TxLUg2%Zy7Q`8$ zmMKss;!vr?rblZ0?8Z1*f>h(AS+UXSiLeR7nW#LK_B1i(83#o!ZQTO6$n`T?*%2uW z{erv|fN!;}G0$Sce9}~`9j$r!(9l=KKnCU9!N!67_!@AC{{Xp{k2WS&t?Q=m0}|at zCkc%TH~oTgtP61HW~_c|pOdH?q@A3{f}~-1bo#{OztGjg&MI_?^b$>ekI<1k@)a|s zm(bN!lCC5nm0(;y>pamRwY&(sDmS6gG>&Pj;ysvQl0R+bJ#y?vw^61YRZfOo2Z_Z# z%2{@Ir>=R$tk|85>2fi-g;~g$YNQJ`ONslq&iFIcy5yEd!RGZejd)jcaO)rJ3jr)? zyw}fy$=82l%KjZ23;#1Vmb5X@v*fq`j4%T|2S+JAYdw?C0d)WI4|yX48+*gQ3Mqd@ z+guWLrG!SfX9z)wXbuJ{!WJG`ObU{+R5#q#u%nASXwr(Yb2B*47^r?P;3u2YsD+_0 zGUax9yKj=q!})OC;nKM3LsJ_-b;uswAcZFPJF2mo?e%OAMNpn%sVsS4#gtNs0lGV% zC3&^k7>IyaIPY-PG!I&Xtxw3E2|~!ss-Up!p&5{pEB+e<2t`0!xaep zX)N;qTtxQ5G#1G{7S+8AVEafH)Zq_;Z_(_PP6$A04VSUw+~ChCM8>r)P%^a8s*C~` z?z{C348g?#8vqLUMJ9StStcl4Lje~teT1_PCmz11NTYw0+XS2&O0KJ1;OJAya=Qi}-`^jO?NM zv@j>wo0sR?k9y%)Vmh&#Yf>WU*w2~!%$oC$}&)Fh8FSB#d;u5-}8tvI%INQ(rn zUR?d?glGV3&|tZdUQ%l7d#Huz@2FnYPTV{;$2kSm8S9*vkD1K6BWCQc(vI|G3*}!( zX?h0;%cWKRE=ylF%@J5@4s~LYJH>e=8w7Q5<2@Rwv3XRbco}O6zPoZ%hWgsOjuzI% z(qY7kUZAU{I-v_;fj*wwU-R?oh0c%=kP1h$&1AFky7cWGtr?19G8=H5UErrKHu$T~ zc-S1tkZwxOc;PS^3B{CdbV7ej)R!XF04WpWFWp2&c(X`FJR?l}Lr_2JUILa`)}qQR z`pJbL!U2(tVT`CXy)~bMo3(+Wo`VI^Z~3s(UxfNhMTa-ZWU6hFenXPj-`;nJc(F zU7tkt-g+WNBzZD@&7qj6VDftdevGkh-Y~ytL*Wr#;nyLMx>=di6#Z!(9swD9#}LLI7cKNR z|A52vhXB+GIw-B2T=nIg)8kB$J5nnf4LAwWOnoO&Bcyr81lJGy9f!42y^{}@RS)$^OtM12 zJ38jxO*3vy2pI!M*OvPU@;ADQR0bz9`fL$A{#)MqdnEra=<4s0{JSG+Z>?u3`Z?6f z@;}g(qLj@XFH%NiJUh5G=4=dqY0mT)F^toOhI_(7`2`4gasVJ=RB6m1aZSy(y3DUW z0bSj`i1NT8fV<e~o?o^KwpzXMy6#P(YvkkY2} z!Xz7N!qa8*A_3DO#kWMT(IpsaCelsO*6FDRHILvOKtcx{H*L(K4_X8jZe3ooIGH4~ zNR1X)G!0IGxIopy#K~0~v?yvda&FYNxP@y_DY&2|lo_2&HjQYh6#GSDc-dO!7yj7r z2VA?E?;}>KFCDv`XQyLdOnRH2b#8qlWBH=2hj#Hi_v7+MyHrE`3wPE<8Q%|reTg^g zbbN+$2CIdcjjEH_P41NrJVfzrUKgRD(Jw)Po@fccI=1^_se0U+xB|DG8%~Tri}0!O z8D#0YhG1L20_W3@LagY^4Kf8id~D_V5mQpML?Hv0t18q)h513Rg9W>f6QA%@m1a{0 zvW0iiy@JG^A7<55u!1k_D{FMjtIzo z-q@z35G^szW@u2yLpJp;7u#b=FOwT-xL~(Q3A^B8HMEGB#7@BGQZv#5-sHnY2ZY!{ zvbjbme-o->&>vU|X)h21+GC6gA$kiznn=_JkR|}sdsi3+nV15T%xhtA0XpHza|)|P z<%U%DquFbH?*;3qYj_5^IYN7D^bYK|xg^&IeG6cHi{O0oGkQcWKgVoZanYHQ zjAoc7G>&JL;mvfTz-;Zs2n`Ea}IUW@v~tFv@Ga2FKy9D zzConBGh&qyS!Llc0un3W&l!sVb9$$e;ecosYf-!D5Xp?ZsS)Mhv-Rb&w7n$;&-Tj- z_?>bEX=()e>D3~N-55LCQ^vWxvyv28R-fDu(I3&JFuX8)@8OD*C%Q!8zhDu#sl*`mb;VA-Un(-Ld&k9c#)723FOmKA%PUL1+1ZGvSj(k}Ygx zHUcK99Mnl5ZtObj&UZw4LELo%JigT-cvw$NHJwI^fM@5wSms2j2XEA^PEi6kC2 zJmAPoS#9TgPAbtC1kU~I+b`f{m3?mgO&d-9OLlo=hX#_CK%{guJxG(~p5V~oO(jFv z^8S3^KC82?AdZHkOG}{ek^6v;}&mqqv3+`6v63&RfE;iFZf)4Ypd1r#Gf|5bHW{yTL{YMuEl=- z{^y`Gg}gsk;OTbKf;d%50?t|#$5D0^g`Su1B z)G(;jH0m@$eo@k-{gn*DX9N$nN!C`Rk0#FA&)43@D87R%dKuR2<_9Rj8o?q5op;WT z;?NeHVX8o-CY^`{y+qC4TDmSJ&J-R8^&_#9!0jZ4DAs)tF+3^{K(%4#dc?|c;lP3d zBC2t(?)lCrn~!OLZ>}Y^VuE>m>$}dS2(*@uUJe_^0a1=jP>S=EKGhNCDNA4Kl3s;L z(`gTVnUQ_sUy-zT?P-b0<(!FE9HpE8!C4DXI^O*`m|W>SAJgAQFGvnAT8TdHbj!`< zRiEfKg?~|iDVlQ;4dWvVqmO^LPaxOk*{zud5JELACfaxDgN6B%ID<>%CVxL`#CLKM zj#wA4;tAs6I5gK_jIG8WwfL_31(zX!ZFR~UrFn!=>e$NKiU#~g+xvrEwd{s4w zZM==cRkb^>{y~;Eb{q8TlN-8yaoSi~pcRA&UfWg~SK$r%OSd4p~LgW>>$nu(&9a zjhoBx6Xe&-spR>5>S8Iwg(MFjj{uKgaaUV_B0hPhG0D@q$0gfQ)*Z)DR$JG{!=B6+ zn4L2)=RHj>=N&G#f?ihK9$+XTTlhY`2vK*jJ|pOSctKn0h=u|Kc+H-c3@Jg`=yLe; zZbP_VS5uhwOvrqgRbm=fV=JH-RT7U4n(JVFUF|bljN{_J*q|LStiOf8Xk%ku zWM>_B(Xw(e(%b5>I|YsBY7Dl=j$=G((qFVDaV_QR-hDSf ziCEJgrn5msI>(|vk2q6JHJquh8*$vUh0NP>iX=W=Dz0Q(yAGpv>MIwAxKFTxbiuPg zg771GHBURPJZBBuCpO`0L4{sRLA=~lGT`#!6dr>P7otg&%PBw#aHm?keMJI7xY&c3 z2O#a+!wjO-fI@X(=*4C*uHzRzPZ4%rx20;OW>C5+5=xFzf}uvba~pbyyAz2oGVthq zjJrKw(SK|>Lqne4{Ru z|F-DpvUF)Yi2+NDLud)fgevvNqPp8jTw-NDq!{*Fjm{9C zBmLqnyw(AfOJek?dQK{(KqEZ{C3dr|hJdmNOp~9kwqIT!fZUcgAmwF6heUC>GBcrz z->iFc6o)MnlA|lxX-ab6SCr4IOl>ImS#)TqrF;+3vuqFNk|M+=0Sz10&=d9s9ltsd zs5vOJWoK)r<(`NdFj6D+8Rum72%~fQhPX3Nvy!58d-$UT1H!p-!W22xYN38I;V67_ zJMRbsf*tV;Q_1|NRq6clBL?v(_5RkvC^45@+c9&yR-{9(1PwB0Y%D~iPvMM1% zbHIrX5@9x~bCJ8@#hL1Xc%J@QmwRE38MB4!I-0{QOKK6aQyt=2faT=%$|5~uc zufWCur=%ePChdqthCg39IKP!c4yxn11iv5-#v|h8LW`o9jZgoAl%D4fo^D_cULBh> zEz57A&+KPgTd=}0spb8hVNS$5ZUY`~*AQnO z1>ySQ+8d0YuSmJ>B6D)hJ3FSuQFVxO(oYS&bHnB6yvg$4jX%lkA?*6$Tn+fGogG3- z5#mXPc=`}w4VH@uBRmVf%*TsR&ZhKQGLWw@2(5P0XNJB+&?su$5)}zXV;e`0+ds^C z?&w42>@f*r9%)-7-oQmw~cKd|&|6!qIy&vZUkui)p*<@Yf(OqB3?Y z$L%gC*k8sgQ2dLq2Y)Nxeg=?>zF*D!%U7@U{}%6mZRr1v@dq#4$W8cxPMqgw}}@H$&OdNFOOWzu(MJ+HGXbEO6XAN%pm zC&86;01~7ZvYqir^DxVU{qf`J`5dVS);hU1-~fSYUOYeWLR_bSUK0lsed$<+#Q+~08*?A%k6IX;C)T(9);u}c$A@~PW z1l*(L`5o$qK(*oP#p{VTdd)o`7q9Ggty(hAr>WRp(i17Jv1k?cas%$rXkb?lkb}nk z`ZmTLc?S8tfJS7oznPRwWYaLrvZvx3+5*-9uoI<=eb zXPvg%%Pm5;D$Xhjq4b5}s~9Q8FEwBlmUr$4bIol(co*%qCw0nf?u8k6@HD?u*fdOn zD+bM{{^lISF$9)DHy){=!W7r0u|8akjH|F5O=lNSpmYb;P@IT=!FKA*&v%f)Ik|D? zV{}{n;Gm>R_KL4KSTZ+F8fmW5(Am5Oo32Q0#$#^ncmt^%^ z4xKyinFv|Q<`n9Op!<|)0z2JVXp>3hF!)X+2RPX@>v!7&4pEs1tM{N~3iFm-bf$_z zeGR^7xGxoKWs`+aP;@z4jHTdX(_7wm3YV}Fn8(2f%Asj-G%CBY}zyTHsj*f z_TUF=xEP62jeX@cXR3;WeRi1IWL3Udo6fyZ^%y2fHpk@{zVDja*tAdrP;xkcJP>KV za#c~=Vwlg9Ho{>VhIw(9oL(aGL$`x7V~wP25tkWfIu{Y;h>U)Hk_qu%9R?tDE)MIE zy5~oKMjRidoL;krZvNS`F-TCx_z_1Hv(FkeN0RjR) zKY@QLh#0Hp-4ZN&VP|kr2tVC93J1^X)hf(}ZtGPO@H+lX($=#yB4K}qinGB#?-JgJ zi+Bq=WgK@AG!<(;gp|FUKJ$4&B2Fj`Ahm2&=O#{?u1j3}rvl(y|F z|7T!8b^ez>9G6rxBG&R0OMShdH;N1q*VB(T%n!J|Olf*@;-MS5Ru@3$SJ2Pp+1s1f z^N(NHnE2u)fmd=+H7L5=J&Zv)pMe&e0Q4l-wc)n}5porgnWKwZQOOCqZrW%h)N3=(&;&5-^RcqX5O(o#)XZ zHdJy=>`PCUmOot{9;-tO-#I)8Xyp-E_r3wpdt|pVf|_vFD&4kp7%gQ~hGUpBLR{h> z4-_|kno9G-l1E5dH5W{;vRGa-ImLfu#^A35ATvWAXRBl)$`KSE>3gW~QGzynfYzQpRD7b5jjo7twzlRS>#%Mt|WH)E}L#*mT!#;hb!Jemp_-5Ok^70*$|^kLLbP zXHa$+(WMU7P(3WY_3tR>&;3aBu7)gz3dQ})p3VjP1J zz)Cs=ld)t}P0Bgr2>#M{0Fq)h*K&}bTX%q?*b?x#<6>$x`KnUcSfDe6R~!S;-Lt6u z><3|lYIb-~nF;A|6>M2t&z|O>5Dv|QYPgna$Gn#<+q7l9og)c$syd>;e!g#K|m6z)YH$NYz?zy(u$U})sx2@gz4{$ov#5+yasu=~ zb@3p~mB81^nV`3tM;+d=o{MEY9wE+|oE06$!J)-2c9IqyNe}$^JLWQFh#`Ct3bZ9wG_cFm_$Dbu=L$O1(@EJ=bNJYS z#(?GChqdYEk_E1rsoGhc!4LNFmCh$RB)@h)K*MQJmf4n5i^$NcDZn8l4DKp7Ec&W8 zOhPrm_8FRVyOJ4Qg90a~N*@|k$UinZt<6_yiHKK;m@rixFonkp7B+tJ5zMQ`g8Mu?LAkH(0 zEV2m{I#g(}2@AXV)ISkZaT#pr9HCE`-DaN>Hd{@TK|yr38S50oj-VA%itLI^4j?1D zZ53ppk6Z-_MNl2zT?*7ka0EysycdGI0^l{Hr^By5fHN!Ajsvzv6+~|aim7MF4@1;4 zE>-xY=GaD0?&P8R4MnNRy79XcQyhG{qwL8P8K)U>BI(l!f{wl7JuMQBP}~+vv`@7r zNY*Au=y8?2iiTYZ&(lpQHT?o^^qKNt^oHx%GSs)V6hVJFq~lMvE8*Yx?qy_haz ztHqI6%(RKa9^3a*Ifwy@{L+2NRur5GzFuzJUJ$;#lQhmY0!3m@QcMxbIJ5CjhypzZuvxtJ-oteHA92FEQ%BFHC~}dH3~S z8`}R(*Z5zRsfF@?_q8^&5V7#;&TjeX$qD|Ip@R+&l}|(QrShIXW+G2**w#4_x7z`G zlG~kBE#yJTW0btejCYvoY~6o8xQ6HfHHI3|EBGxJ;g)hmHyX1QE551~bhbOoE-DgTU9(8B-oMQ@2YR>8^!&%F6mKTCCr_VenznZxwWn(Ty^!SymS!WZ1Y8U12Hi z(O=V!rhQHFXi!z=y@F9%wzd^p7>&b&N^-ebFsVT4a%f{8^x>l1Q(0mzkO*b8K^M!G zU`_JlytA6qpMWFgkxomH_JwOgw)`{wNB^P@Ow@OdMVakYTI?-O)hA+HhmqMr2bmzA zG+;EYG0(6G{P9O!mlJ2w%4a0#86k`7$lu@H$rxC>lAeAqs|{pz@HvU0M#@#MMVG+RJ=D+i=H4!SF@n?<+{)P zBh^Xvj_ejSPohNGc=;};)U8HG4=*N(+u?ASVKenS#ftiQdx`4V zU<{>ZZouY)VPykxOqE0AuPOUP&FD+3ab1OBU{I>9+D>Xt+xxek)WtUtycjJdaZo1! ztbiC`0Kzmr0An^3+Xr6Z zKs3$^heq^V63l-xvuBGthIZ~kJjbU0>m~{Nfl!5|qer}`SGf$&JORTCi`BYoz7d?Y zq-?VLtfm}w6kKIqHEKF+gZ9K0&KF^5hw)=oeM%oB+t3cX{5z^n73wI?A?uYHN_HT_oJ-BZshWjPEt-kh48YTFmKr_Y?9c>z6)4R%8_@$GPSRCbn{W?3zi?e%8~ly z;mj4MIM(0^?OPbWy#_3SYaVgweVjL8l?25Xh>#IT?XF1jQlkRQid5JxyHaa*hG^6pf(#lvbH-qSrw>OCq0UQ(X| zRZl?_o)UR*t$#RY-?GZRe}VAor*)~l1+c$G5WmGSb^d~orhi>SGr}y^(}ljAZtLkV zXpt=MJ4Op@I9zrPU1>19|B<@7dv;WUHPj$!7D3v6O+yk_8#X$?8Te=$l_cg!6N~tF zQ#~VEz_jDn``illUoUdLe?g}H2SZcS`rc;AnzHJ4qGsfEMl&vB-b%<_k z=cp4qUNlir@fgn-fdl(;qLE+?-bP7C2sYR-@`BpzJ`PxL=?`W;zeb(gSL5V%W7ua9 zZge~L`2oFWfV3R{#5($`;H1R|I@`_E;49I^T$lJ6BM(8jEh z3qRk&M!podDZY$fTzDr-$sMTtDAoI!Ys$P^NBSHG#KD9nHI#JU6XhI$*Wd6dA%}rY z_pj^vzthJ4bp-eymQDgr_6|1ofA9bQeyEiy;XZ$b#*(a@mCrFr%@*Yj%Bvq6vyS?G z!A}T&UZyWOCqE#0NZRKdS0^Po7}J}!q4+>_$PjXK{0LBl3X$uqO8J#6;ce^Q(iWah;-ye9UI*&NFxWDY@NO9j@&t1N)M?TIS50^4Y?@5N`ixjvirqPPu5}S2p z45?f#2#xI0r+P~XM~AN>GQ6~nbm7n06w&`C6?#aB=t}HynLX}vF*^5{<)WT^EPVF0 zbQKonO_-@SliU*#<05^(70Zy?1L+`($0favC-P1kkPz$07yt|`1B`Z%h6UL~pl7Ax(zIvoS#Pqm z{7zgR;9HulX(+Qw_s$}qp-x*q;uxOvvte%vstOj4!c-9MGF;w!mfLDPv%3(JiAXD4 zq0W@!T(#f~TDOxaz53>{k=H^+4<9o>y_V1&6ot@wS$D|{NjjueY>CQTF>yzo^ApoK z%yBIaew^hofpkdn@i)CPLtvf)op>{Ob3s{EQmW2H5 zI`#_b0Xi0H3}oDD$yDUkNyy=yt=BScjaSW_4<$A&T~CR&17qO3`tY3bN@lCI!7%N= zu!MPbmK~eKTn2`vbc}3Nv>4`ZST6#{H&Wfo#~>F@89mjCXc>mxezU(OnGiHV~xGO3Dit8TZ#+GL5QRy-@{Efv-3yXnjK_ktt(4%pwURmQnxpCD^m z%$me0AH23q@}8;l+;)z-?ZsEQ&2v=d9+2(T<)IU?X34X0SrT!DV*Fup;BIn})a+{Q z70OjSYtHDhu%0P3KT|!XfO9iB>jUcNwCnF92eFmNpAsuwlz z8D!?`tTMplDa|bw6LiGtgM~S@sgt%C+4RJqo9~e5uP9Vx;ImsEb1n!BI?_e9N&om0(VootkRF~tr5M7f;IgjpB zDvjmf2IE47%`x5)$FWX01DM~qu(y+)zhlcw=j`-nG;R}Gss-TrR0x!rkjuXp*>K^h-L^Fg>6h(!unx`#?Y@60u*J&TNlB;+1kpD5N!z zgR(zD4#p2$E&6~{l@hiXC6!>o9NE`yETYmyd#u%o#PJN1bmbsdz>juVpBwWI;kv6g zE$&1*r(U%6JzRA$abPq(T8*n0HFiLqnel<)es5KoS@A)aVD>&Le(^t768BdfaK_Yf zh7%D`75|>ev>{MmUK7vcg6|LCX2$Arrle>CB^sb;gd}^uV~zX)1Dbv8 z3=U|WP~-zcqWXddxB^Gm5B%5Q#NrWtKNpzrx>=Q)2zbqp@6kOg zPDE^{rS!1!C6YV}s(n60HiPJOUW&EzKN@0;B(rL#XF(5Gr-6_w*fa$sC=a6%Z$mi( zTtjk3`wmoY@| z)VA*+z8Zl%;n#4dD{8G6qN-l$2=w$V4t<2qf2P`FjdXH_^>XdHkX-qbilgfdqI{dH zvJcz5XlCPq8m`BDOP-fB_U{3 zLT&^bq8no(c*a%2YheP^QioEA*jIsQtjIgjyx5UMQG&f095E&Yw`2~L^q(uZ?g6;D zKuJvj?FWBkOdQ^Sbk>Hevd5I`F8n&GoD~OExyqGo;6NIr*=d4Y447RLFw>A~U_lx@ zveZNsM`WJC&MoOQ-k*|f=<<`?^SHs0e{uw3K2TNz-*2ys?vfzU~t;Y#6Fb#S_K#q}Voj3`Gigjw|Wo zZ}#O}HnDkZU%PB^r2pD&{wtLFKQPe#kKD+=_a=>M5S|%Esh`~rhF#A$Qc-5blL-Zx ztNs}UmCTfL@}je|!g1hIrVzushBwUEDHDb!B#nIRnv^xJROJ;YT29TBg1L~?R$~~s zR8FP4jX3Q&-?dLEDEz|wpd=nXJGKntSmM=tq`ch#NAB6LuLmK7t9MG;CK#> zY=fa)Ug(T>=bj?4wv2Yaub=mOBZ6KeodU+L*l{oD_1H-t$839o{r#M>Lm{!^;`@0b z(o>=d{oK2MeTG-?(3V3WN?d`U(rMUVVxf!2xJ z8E4?4=vRUETnMgCEg9Yb?V`D5g??-IwHdq7VDMZUaJj+-{g~@9;D510@3PqT==*pD z&7!*|%3`3?-v$HSG}-P1^)}rW;dxsYr1aL`?Y>e#|Ik3XVT3+20R5w$knZ zxih6|ju$Tt%`|*KmS{1h6Pv)!G?=D8;gAx!k1%>jU3)fFwM@tN#vR(LNW~h5U!1%0 z^VCEx`&nJeeFM5;QIdpZHFf0Bc+cthISNc8%#p+~pcD(6nw6@sXWNm44esZ3R>KKAbCbx-FC$Wki_zW_1V(IXa z5YQoD=zbrn{jm5^e%8{_!#khbNhRH0?Y7_-|LY_tGo55ciL)4Uu@mJ_*2CSm(IgiV zdFRIw+3w7f$a_*Nw+LO!a3h2|0Pf4K!i;PkPptSp3z=dze~wi__F8I=7bU|39(A!6 zUwc5`&`OAq=10ONHMF??Y9l!&fDvN!2L)gHh_zzwy^{wu`Q`MP=*kGvfQ~c9tO5s^ zlHPTxPF~HnpjR}k%*k8aXSJ@P>zu_H*dSe-PBE;sC-wj)Nd9Eg*f2ciyJ*dxmaso4T5mfKZS6;6w0*|gRq57XF(H~~L z>miE*C8kYw?C)xqQA6>dd_pOyE&H8|-c%~*7f`&zw;*nhsG)z$@H{#VwN1Zt2J&u$ zsCAm|L_gs|(e4;QeTJ)0N!G>d=X&(Y)2w{(wWco0Bmz@){J10vvwuwxx#~=!kmHd+ zAG0A>NK_w-tN%?=ugI<)`=Tu=9T-R&EV(91z>dfIWv^?=(HbrS4{;GvNTEo)L9h#K z9}q|%w+V08r?>@5%`D^QW!_cDZw}-THg_i&$0U|;rKA-{6`*TLm!vBc$u`QazoV{c zQW|)yq>2#AX2bQBnm5Q$(HW~6cVeu|gn)@wQ#!7pi2TD9k}8iehP#Gow_-}Iajm#7 zNqvAUFc!dEAz(yUTCQ-?Tuh))T3+@`50Cz*SfK-K7r6W8DU4v6TIPEwR#oCZopKN!F8=V%Wld#%anIjI-rtWExM}E7)u88auf<4W{wP zSOpJZ;NUN&hwEmNV6%Ej&np6F7)^&2i^#X~TL4z4d&ek}MwI;j5^{Sw%O`VM`D@+vL*5iHm$gIB54O3a?L=XROvD8WAZ*G)sg) zuH|AP+fY+j{a+nf@x=d(vI6fWoHM%njg>Y}9z#O+Wn@Rd7#D6~;TUTvo0erxx;4=~ zdp2DVJrM}=qHm5AW)cP+&OTXj*O0`af!(d zrm9G1hkYJ*=%h*5)Vj!Y+AL(8%gzA!Au6}eXzArQ(8rx?-*x#%IQT}$N@G4O=B90} znS6vEM+%vl16Nna!&D1L&^h~EXQN_AXL(cUk9AHIz4L3FFW?GV(|=I~f}vjhm>(d} z3<+12Y_dP%$A08Kraq$;mc@Xn@}Et-dXx9^M*s4`UDoO4ZjbBxuqxq)eh1;O+pJ&N zc8_I}O=I*RoAUn94lIXA-KT+J-S2lDyKSzz`mz6;_O*77L_iwRB}Ucr#%`kQ9E~ z_Ck2IAk%Zq`TbKbWo}%ahMML_u$=OiE!x4l%H0BMME(u9UoidUFTQ}mD?3SfKqpx- zEUKIarK^Grex9YRyt?EhEP5q`TBxl2YW)a1e<>DuO2?Xp54f?;V?Scb*3z;qaBhi+ z^oV<}Kuz9e%_CcxAO`@RD#HC|D=gkF9TQgPJ%Op$g?(K*ONK5X(f+D}Vy# z^@b>-<|~o)J4AmgG-g^5`~!F_H?g^;ecs73+C)kBiR!Y?-M6jn{#QFnqYmWela)$l zTOJDb&5^Zq)Aw|^2_L}6&X0hX z5XW_O1r5EQ*381kClz zhRN>l-Jsa!t?`(_ZnXv!pDa2!ZGhSc#34LHHF8dOI#$a|>o1D-$jrE$dp33<+|q{R z>ft=n_~++$gKLQXEKr~l${um{ZL%kPfU~q|yy177rU5GlM8@bSr1*fx264(AVo_~$ z4fD1R%e?az;qylIAQhSq)8KCI?XazuR2s10K&3ZCrGI57bVqdnj@@`K7U~TOt-$Tx zka912xYk1h(dJ?(?NIN%SXq8LGxCf}Ua=27a5v0$&ffz4ImKgkgtKx_X~G;H27i?q z!0ZRU=tpf>pfR!3@fAMHje0MbO>f>Byo-D^eXT5nW;K7UG{y_l>L|&L4w2$cIAXC9 z8wC%BOyWvt-cNYPGS}w?`_KwdnT_FiaEOjK0O_~q+w^YOz-+^8A;%rAv!jZ3cdaA% zbI`(|-giAw5^Z1=Xt!~GJaeGTtp8@3q)Yao({xAxQk7!Z@2ix@6uiu!OiI)@;7f z&m6liy{Oh`&7SiRVn5l>skb|(pPnnHm&`h)3+(~qbm;mp=@;1*y(L%Z;YtBI6;99IKdtp-cz zh2DFHK)<6AMU-{Ccv@HM221tdxBGHNbL)=@Wwk2as4TdA&H1Pb!6SV&?1iYT2R}NZz;(Jz2Df|G1ac4AVYtV# zRT|5Pj`4p%)+s{e9^1V}7M@#5A@7=E_5K0#M6$TIcK0xR+#bzH&=v0W#A9#*vCAC_ zc8%mcvX#9j;tI+;6#kS7xow6#Ks&GgCY~8-qKKKLWYg_nuFm=2c}7RxeOkGN6b`gLNh=LvFUrj$!qsmLv8ae{myYlodqg0Hi9{YO}pd)(49 zc3=6PX>)k}d=T;;@$fhttrg~vnDMnnY4-h}@(Ga6h=J32Y7T){;)^1JWJ+&@Lqb;m zHrQ&+k?~wROf$9=)}IQsu%2u>X`EhNOxa&@Xk*tnew!rySu9+Bn{=AksJ{k2n9p9Igf8kJu ziL)Mj53^v=mPug?uF()r6R*^TB1)1R(4QY=*CBLtGW^iO=51$rBMiA?vZ*D&S2kU7 z#N4o!)_1!~UXHNPl9}XOZ_n~){j`_F{+*1mB^`UDbrnuz1;Ruh^ zL-tHzc`{~YLL=f$wisL+{%6%Z@8{n}K3(*i&1jf!-{7$S)5!O4!gc>iVfv3q@!vEirL>#*gor0=- zJ4v;N*J?bpgMsgNBTNpFERasGJac8zk`?13WIhUIl%LFZK7u>17k^b!6&Yf#voTDD zeiy8kq`)yEL6c?;_%pg+Md|;O6xt=SN((uVB`UeOn~EhOe1l*reBx8CojD{C!8k6q zvF`T-w2;Z*BU zhKmVJmG>L)6>RkvK+ggP<#3qNTx+^VjPEjwa*f(2E>U8Q^rFQo?cPZ@dvQ{B8YnJN zxFMsbB5Y2`qmZRnonA|w3zBO;&4E(f2NS^I=)y5PJNL%YeS}Mq8!w7*=HHZS?^3Zt zsly6^Yo4F7v2$gdt!u>)Eo=EK?kz3N!C)RP-IHlgc_&yyOR&WSmzKnHV_>{Bb}_~V z!PL8=EH0ex8)7gTFa$oD6g03HDb*%fo=#Kz;u2TCDV0_U*2461YFW4TI`goM%hax6 zjn?vTsh{rRHQA?~BAE4doPHcHP-ipw`v+JxRz$D!6}TIwL_p)KPOL0O6yM0AVZtk*ME>dP2=-BwGYP%MA} z%FnwuZ);=@H)4)h!Y^``UQ!o9bVi{mA4zG2&Yyfpsmg1y9;kc_p244Pu3|<6Kp($| zT4GCG6Ez5HgjDr6Uh-_Gac%$C!!q&zC!+t)v}>g`X+%D>k051~qyw_u=Vb~jzNGIs zKLvqiVtyl-(*0Se$xH}5mt<_0_@yI`D6|_0w=IDFX$BQ$-@9sf$UEVaWmC-S?fnXy z6B6j$u-62G>0)U}XG$2{5&1o6qPJ#dgLy3kWT}r#z@p(KSWQ1DxrNH&AbEqXY9S$N zJriO{fdPTRK3Pf4lpXUzta_mToct#Jp%8bHuBDYI>e(sij*A?f#OZi^_53sKav z(T#+LXK*`EGVh1%&;xTffg6&AxY5x~p%VO%Fa4Q&kV5c|i6pTF#bTE0Mf&!;kBh$eR~B`Qb`HOea*|L(=@`lo zmZSbU9~f5uhJ!6G92J)%U8o335tig$tv@=K-4#+j>>-`ZlbAgwbo}QAdH>3m051l! zz|I{!x_s+fTc8Q_Akoz%%IUYJ)}v6miKxg~ms=9_56s`8guHYt+7*rTd$DCNS)3ZA z4&oqw5^ddYrIDrivVs8<>lzArTY6#?jw%fd3k-L0LS_n3+S)T+v)&CRXQ+{#N>(|+ z#;+GdqArOGc^P|~&O+s?N$8*sq|2Fa%uK<|)p3pdMa^;dcW42K zOZ?@CT6cYph>w1T`6p!1UO<#J)uzva`jFfW&2jKG{@SaV99zCT8H60Rk`9|hJs_Gy zyoe3_^BG2v*}bqa;+KRQ2DsZ1vFYVbxQjrmJUGOs1dwO)J&!~_PlRTN*#)V_vl0!n z1+5X3_fu7I^V?MlM?sqdm2Fa>YIjTA@=UQqfHy`>iM5mx39G+rYh%gVFRQ-9e9HeZ zl}qS9lbZgI+exB-%KHARB~PJ()tC0;r#DMzr-Z%LESiP}v#*rA!2y%!uT)#x1uUB|v;eB}@RMM@^R)g@~|W~mn_{d*IG=O1}| z55MsnOqPHJD)iNN)n2WX*l67v`CD zyOt9ldzwslELgKx4KHvG0>M>Z{GL#-zHYNU1gI3OB<^)p?d;`Rmswo4M->Y*#8+lq z!7gF0mz{bm9xAOF=abYj5)QY2scQ*do!97r&4d&tKaytiCKh7`ykHPR%t8#}^j_eY ziEBhPUmZH;YQmV!#0NOe0d-<7Pul%b1;|{w%O5g{XuAR|fO674TXaA4OLa!0)`)9k z1yx|pkqC2UiY?h}2iNYqz^6hVY!EYdgT1>ezXHlpiS`ynv>S#q zM5`x7_{WC|ZNRamcKgw3lx{+6X%hN9FQELiN`jvSTQ0#od3T?+1bJbO3vyz#M368A ztq_-L0@s#>aiVMdu%lNKw#r1P!@gU?2gx~3l{3ny{R$w!NTLfL`I2>mft$VvsVjax z#+Cn#`und-_J5O;_|J~(zuB(-?}n?9(qD``zMmCQcC1yQ(K0`QCkOdPs73JcfT4kT zb=R#HA;u+- g)aNfT0if63gnMyz8hF4XUT>z>d;l4ex0p#{mev&Ys*0%`71X`rn zI<>DaPhp@+5**GI-X{X9paabF?7JQdjF^P-9Q9?ZQtt5lSAmMD~4y$K`WhD0vaa4^=I))8o4L@-V*Ztv=L zFMh9oz37JjUplG( z*tLoZ{Jn3@{D;$0{$iSyk?}(&H?SJtmwpbJ4?S0xTk(#k>W5TYeH|y{d$~J>`!U#E zejaCekfLG(ox{bZ$JENWp3YX5&bKpN;z0a;`IO#@)ZAjc@&9kHXh9In%C;_9I0hr0cOl_1#Xwjh%drHOyy+M2{g~z;iq9s=1CIJ&O+qy z329u=Aa<~2nhQU47Bg!$%%6RoIohL6Mfgo*yI&S8v+>WbgV^@uv0K%h3%U%*Po9KNTBFPJ=_t76daKQqfb*|~*%tp^1&(C?=lE{-eA!~+e9z-CNV{$$L zTy`7@;AnA*>;VzBrhD*bzF}y>1b${X_(IJa#JWg(0TTnuh^P<-#!X*tOYfxDVnkC; z5Ztw;B(b4g?Dv&YZ}n2oBI#&#@IDv@0qA82DaDcT11ZA@ahHFcz1tEISk%|K|Nf6n z(f`1k`LFNKKMwi}n?gEr`s`jYFjgV_1@*lWNq5i)pNP6R0@V&2TUeD6LQFS+UcUfa z!lK%FvA+KM?6_6w23BQ!QE)VqbSO4)lYs$V934!7ogZSeodTLQYSN#2ydCwkjT~R(U*U^w&JAsHQ z18?b&UBoXo9(G98?k&&71d4mvLbqutT{L?-hHvG5m#*}_SQ)AHerX|9W7zag0}`Bys_6?kRQY0;+k?-3cUwDgDao6yPwyL z_?Ji8SiQ7{Z}L>#)QE-zfkd?CqxkXhE~CWpYvGYCyTqwTv~DBivazT-q)NH^MFWWh zX(G3+@NHSB@gR^{DkTBLG12UE{DCN;dxenHDDMb?V;%d&_QsOPke$P|zbA{Q{U#i_{-@{jj!CS61gIr|mYHaE9-=hLq< zFiXcHGdE+ITA0_mF(xH;ml3 z)c(9!zVgDzyDn+;-!4)2_`Pk(Kv41W_F$@cDH;iVY+TLqb1qOJf{)ty7h}GDmYSn_ zzud#;YAd9PTNu0zgHw{V1ef5IdD0+?Rrr?C&n6WkHK|M+gm*iOwTj3AQQNR;whpNh zTDYQ8hz|<}{l@&Jnla3}eLBq9%6H?21-e0Q@be`(+a`VJa%YEpxW2~QVDa^H^k2#gNde4>%{TN$+TpzwOv{ye0`c1aEH^D5S^r6GG%SV%1 zIb{;g!1GWrPN_|Tf+ccd$owIJOEY$$#6m^y5J$QDxWUZO^DPw|m`e1&RNc<#)1&5` z!`3SXM{h=op;sXZi=Ey(K{CsPO3z@AFszYa1iMdR+o&J~n>6jK%RIuWtrdlLgKrAn zOxp8z=O2)fFX9LycfP!9Ho3~&KgzJPATdQal~0?zXqu`}?{HCQ*MkL#jvhcLRi$EU z!*{hMS{xMUA{v(FDIA}2l+F!UPV zO6oG0;K**PC!YA;z;!ddLbLPFJ)#t5AiF`xXwyGl>~^fV``%3R#nXYa6X(c-C28Wm zPte3nPsWR}@s7z8=<+>wtEc-zjtDCRNzw|+Gy~mm|z|TqF zg|{f47_XMiQX}okUdRY zf914~Zo(DBalkMdaAq9stlN6n^vL!{IDJen3EERpv%vu0HNif;LQ~nBaVvMOh>^&Z;r7Q zD~uo|$`}Qq?~i4!Ksx(e$kAd9ost+ZS7SLPM~syI`h~6(SZ6}11QdJkzr|hPi$UnG zrs+Xv43bQltR=HJBnWYm_YSY+{N`v$4lX@IM zQZNfxK0-2NO1($!<>M6r*hbn#Qs9f!GU<2+>osDOx)RY|7~7@D5i`O{_aabw9%DrR zKs|!8GTn90p#+oE3{=@@kwj5yS>9*x>?Y%&tX7*i@G3cZEMk(AlU5-0-}v%^nGeE# zcx@{w(MDg#iYjmV3cl<*A|3Yg@D+<#F+Q#}S#;D6_cSlv%qic83V2zQk}V^B}7D zMc;ENOJqc=@@7oPUf4J~AxjxR{Nd$0s3|3t%S-UpTS~6bQzJOzIt$|}LevCJqe;0( zXWpxD;L#s;_%Mo%i8Vv@+xCnW1RlV(5OW z^Nc#WTgcF`1%{$O?TL)Dm2}2Os6nK0NjwDJ^>k9_0VSO#`*Vu5n!2HKaEWY?Fu&l( zgl0zb?V@Zi&wR+J4SnOoh+sjCQ0agmSjd7E{mH8`R3|8N2N+IsBUZt-i zdP6-Lq0JkjiB1*Q7jJx#3Jx<9>PVkY@f>b`*k1AKO5C@lL5MORZM&ikqHdqvwvudj z4M5!xrh*7j(QUB1lI*-wh1r+U_)mDk^+dYpCmuL< zv71%4gz|=aWF&>d>A5sP;v8@weY`DOs;!AyO}mvP&dAcs*rU1*nC#?`vbqi6cF#VC zr+4Rl<=6Ko^V~3~0NL?>@^8R$PXkOEl$n$Pa!ohfkR-rcEwlqXL2vt*QF()(@zorm z_`~uy6%cP;I#Exl zd-%HsMRI3{YkuSO6L17Vz5pvv@2N`3=z@76c$h+G-jUzU6~h;j#^w~;;$CjZ0CxE} zB7={iaf<6*!=_f6Ji%|-gIxCDR{RD_`rx@n)QCO^bK!9Ng4wGV_r86Eh?Lc6F6INa z37-ts4guRTPXUI}9|^5&XEWK?X>&N-0~RzqUSkiDn8==A=JtuTeqOiWI7T{^#&F&V zMy^+E;~x&55gL64Pp%~VQ*)t z(!kI2NoxjI;w!$DPI+zIEx?_`B zH>rGV7RR)k=1HG{^`NuIY`G`qtEiTgKw7%29X2wG+F(`a({3_Z_c(U}3#5#32$F=Z z2}edz3d^qd{V|yawjB1l2~&&ZScNtRVzdD9zdp@I;t!%Dj?DzIa`@LNylv}ts2|z{ODZ-%a_oe%O#l$l58mo`WgD2C+BUJnkKuw ziGCEUo=vN+kR!@pbA2>4h^ehu+x39im(VVc=y=Ij+nyrWx#Jv~ zx4~V;(Zk=l48Kv!iX3QA#3$W8h-O^aHFP<%e~3#LXY%JVU^`h(Tcj}&k}a16MUb*$V=gLYU1)hKt<+;=6mcf9_Pz8}^7jm*}2dzL6Q%5iNr^!+RHaGujz zQok$TTHluoa8Z`+mel!l1y z%)sd20^{BX*2U5FZjZxdi#=7_m>bNLUyd`9>s>O3u(e|A!T~qjHxj(x30?+SR&iNk zhUZ^Ebt5Y&IhSH_PRGOVfTAACSP-3lX|d|=9S;Dqm>bz@{>GiI$D@np@THJj8PT?q z8Ra7`zumgL@-Xb~vynt+5Km8LultW*{A8OST)%PCS`34mh^Z2YTW3i<(#K2i@}oo? z=Vln)e(eGE7;ZkIrd1CuL+=)K7??M+IdXTsjnWZe zbh9=w1Nw7c)y5^D1cy01SbRmE5sBv8r-U2({u$k!Hooi2c_$hgk#7cALbrOx03Ilh#~ub^&!x z?<!zRmhN_$`mzQb*mF-(^Kyj+yu3K~a$O&V2zC9`O>VmFkI=dpeGFJSxs#^yr%MuUd=yPTdTX_>9;mc$DE-H++y!b8 z7LfV=kFCCWBtBev-b^{+BGl3i4${d?-oEt&(Bd(lntw9EQ-1yc)$BQojlntE&M=y)!`mb4X% z?*U*3=~42K_4*Lr{DOG%BnYJyp@Y>$yi4%Aj(mQSV0YC;`BgD=I8XHOshwh{XV>N9 zI@Gp2fS2@YJ$~0#Jw0-_kb1z-_5B=y(AoQEUCuoZ>4}~kKagDVVJ3!OwJ_2XUJNmG z$a_K%Jn(4aHi3)Z@Sjz?*--jT{i>}b@s6fzJ|ovk=bJ8E#-@*9s{2K^-?^g{H{ZYe z9___iotdxgEr{FemIw&1Fw}%wae%o|8pm!1K;_}29Y0Z2IK|Rw;}e~lwv}kI23SzB z&!mn48RAcw@U#|FE2ReL()R975Eu#Uw)_CJn2!D|!wn?&NzE}euzt#{nK@+@IgVpf zgu-!$jaH)yGP+5)4LVj_p;?oPMlIQd%Jf0DW z6-V`mZf1N9F#=Dck&LN^81XB7CpRRi7ci8g?ZvcEjs~!}L!p@3UO7qm)k*3-7#Tn1 zY9$H3z+q6lh)uBgnZ`GDRU`Rpk<@3~VTw2UL8@`8IYz`W3~v=kk}oD3Vd_e>b+nSFL4!Q06L&A z`lgMt#cOX^XC*S4kQFsL?)N?+-p+(to=D@WBvvQzj5jAsK;hcm!ZXAa7vwazMT9AH z2NC!&TjG?E8d;3h1+&y+5iXZv+kUm8f7ym=R$?*_%n|J2D4nhRWUlTPq$q4yZ)P&! z275o$VR@jaW{YHlEX_N0AznIFDalk8|BbhQ71QenBc@ldYR^NG|GbS#4|^+azbh=! zU`<5`5))rd8RplGY=00KvxlaGM;IsbMqeISYlvUa>|%OiJt>XY{hF9-{VIN%6=68A zPqz4>x@He3Yk-%P0E0R?A8ZKNA0l)9p}O1JKRj00bZJVfwv8RpRhe4fjhc?INYjo= zb|1hd#qRa-cuSz5%b`Dhd4Oz4w$44)ZVY&-EE;2(n&T%bFHmq_$P=>iv<T5b_{jk0+Q^M8AHC0>=0ikItI|{c8c{6bDW0XpNu8Xh$Wb` zsdT$N^e!5~BWPw?Z_kb2g|BM5xwkkwudQR8pC1FK_T884Wf(}Dk=U2xkJHWqot|9s zdCT3$Rh(erv549o2S#ng(0$-Z$iWNDWI zC>|HlpJClgqQ>$bAVhD3x(AKWXf*4k0P|yQWFce`?Bk}V4r&3TR<6(ozq%s``X?)( ztJz*jF~YgVAehgZXp*}D_gp|X2&}|bJT0`3!Y|K)4$|x9i>9lGgNw~KoV?Q6+A-rs z@@!;Fj&(ghLA@SWu8$c))fW4q*PYBz`79MLlwUJVBn zhXS1U3wMj<{il=6$%@j*vzX)%%v(R8lyt=+_>M=*|A5sh5NvmJ&O*Mw-YT%AE#f!_ zWzml*sRz}5K%RAc8g8q>y+?9obn_Gx_tnzAt@=eoo~HXg9+5w=);V*E29L|H-erga z?(NCMK6?H}JcdKgpoy1QHh|i%Y*D|)iWPm|%i59rSx&F4xTF^C@~vn(Tl1^DSI zMXOexBi*?b1~YuAK0_F?XrpzU?#JGKdq$5@%n{?0nVKzIvII}RAZTSqX&SnlN^%UYm`*h!~ zNz$8i8Hv|0)w<6v(CcA|f;VF7YMZQTi?Dcpj0^=a-0PX08a_xa%E2a4bZkR?GgYw6 z4a?DW1`d_5B_`;@IK%3G;@N!C*|n5&I*q$Gta}uLbv4mf#x`pJ#5ugq`6uMPk|#=hGU{8=QiI&cL}^4(eS{bsU@U(x6GAv=|q zC?-`R9K8EXEktl=6Nn?G{xJhI!T=?RZ#o3w%Zr(vc=GyIy_OQ1%k#mTrOfN(n zl~a^26DX7i@{5=?!r8Y2jfh3mkb?Wq0X8K_S+Hu}W0Wj}2_f(&9P+30q zC~1G%Dz)DaK8SAN5w5=dx&4X~k^6e~3D%Kl8K%V%mnmD0CDo~57K&(h<(yLoog9I@ zApgau*w2}!TqciWx41jf9Ln)IQwZ6nqrVNymYAqm>8oeL(I%DV{H>m z&rP&0j9=D_H3@7zQr?kGp3uNP|8$dF6ihN$E$r<=aKlu>h+foI(=jQ>obW;rR~Eg$ zAIQkUB#K2MI%AcU0irOLy2Zj^&S2$r#~6du8Ec4%wiw$wm>+19(vZZsP@XdcPEm zG5xY1964uR&B!t>`eB}`K1YV3gQ@2*;OpKsSPGrn2=Zqp{->}S)b>BJ?pu>t%A|MF z&*ooAzyD=S@h_PyS*zcF{8mP{06GArOzj zB*au^H6+(H;*(PG89mhvYeEIlab?jW0;+3zXa$-X%4lX3m22d!E0`fY>B}F!=d`nq z=(6s|ZD&{ePJZ)ytuacSpJLyI=;@F|D353s`6%#tQ$E4Q|Le8A5suL4oqA{p4r!yI z6oQe$P0r3A!=JY?cce$}+okzmY4rc4midQ%-Jfjg?~{JmK$N#{O-9ZPmeWkIKYdyB zzFP{U)KiEq)kc#pJ4u!s#l+W|C0XSU)u$xUwJfs)|A3+--}2@|_!uSlF)p78fe;@w z8~+E?n#+c#?gq`{+UUv2iP5xS$ld)2>ov~#%ld8Gz0uPS6&%+`y}ZK6N#D;di94G$ zUYNK$?@p`x8vw7T)KEW{-Uw8W^nwTp7by`6+^CCpBajDBS{{PU5QgCkl60=2Wm)lu zYTp8&(gxM&5eCM@R!Qh3GluSfJr~zR539=qskO&Q1oK0^6yJK(g*IM0**0?PM$bLQ z(`S#Z0I$-42#HHVuhHp!mj_5V-d!TzmRATn6#8dbcDfyqrLDc~TiYGw%Er=(WaHj$5v3*!l6~){vS&_Xwzc1J)kT z*opX2b2DfDWKm@LPbuv%OO;#iL?elZ5I%9XEYj#+L9_Fv+L8uf44>@SK8F(;G=VqpGmNhCL>4WaSBqeiH%7+od*ehkuiO7;>SNR8KiALua9R~S_ zDw-#iFVpFlZq4P!&*bMV!!r^-iGd#@PyXteDs{Sdu*^=Q z!z$wIM03_6{kbAzosWQH5=bU00>e02`HdNj1U;_@9shGnmt4xO4Jd6$gQ>d`R8%bA z&I5o`?&I8E4<}=DpyR-$BI~_VNj?X*?y~tn1yIk_#bD}gnxe_l%$kvtLz{OxX-{gc zsM2~=)GQ_NAP$foaP!j7W2vWM!wi5CC4!}yGXV1|$v+a(LY~cm^zQDQvSczPfoV=T zmDfI&`f@%us`FGIKTy|;teb|JNYI)HbZtS9H&|9;98Se{62`>II$j&yI5tg34~~8` z-pk?%(n%U}b0F^Xvd8t9T03J2<5vtZer&Vr4J12pHIXfdvMFn&+h_{WZn-y$^3Ah; zuhYh*w8nWzg2BwVderqlYZoGC@|oh_j<@bGHFh30eXs|J_2l|;h&dJ7oa*&rahxb~ z$fbW0Cwlr^CqxM|0Y%MS&X>xm=X(QdX1JbdO6)jw7TP(k4%LQV$+!y&G>94)-!iebGhbBu){=UT)-M)(BeO@LCc;tvNid`L5Wiy;J=h%J(YZBw2l(xC2_ zp$hBgW^Crz>5UGo6R5&o=(_gnIVz019NmHN`$C2`yycL5B9#ugQ~Lv(3w=@qQNGv; z@s)J*ycYRl!N5^(gbAF2qx5!CJDHRavDT6pQq_V0BxWuwBcG))mH1gO)5@r`)*(9H zPD;|MW8bkwQl!)-bI^fE5dQ@7eWH>i;~ZiwuOMdGkCCK7wIYk1sP~P39tpI`4IH9KI!&@;t4D%sv7s(lhgljY*5=@Yd&m;Dvr8fYtc=>EZw9zeKXVKo&4P_BNIx5 z^UzT+B5VqNGM+L!mfMS+f(luSB8VNzs%t>qo?(#F1m2z<^U8Kc0zB;i5n?A4|A?=M zclhA}z`Rd!(63@f9e%0apP^rbOc}%=JUSpPrCFYd=J~5naE=waMx9UD_73~1X2{Gt zfBV%c>*r95Y0l9Rf@2jKn_^iA%SO=Hicv$D^k*(I*_3+oOrBo*@a1u*9`sGxcE9xc z7)%xSq^ICBJ!8#6`xrh!FF!v9t9@I;Q;QNod0k8h zoRXBmleL0!1%Y7mN4|>5l4KS4CPV)T*+;tySiC?|LP4A(v9g}Zxyb^jw<8VFjHScu zd_Cj9XZ=Jl`DSbtXzbxfVmq%AfMs5K`?$==w<(*3>6tW-(eZ%b?S469@>ceReptuA zrk#AT+pJzrY>U$)3utJV&jMLVOLL3QJd7#pUTW2GzkG#GC9)}s`H@gT69a@zgt0#U zc;1F$dADk1X}N|UYjD}ypKe`cJkMkY%Dd_I21U)em)_FJY#ADtS&wjZtTJ|d-&5K+ z^n^}uc8j+ka{Sfmy{9C;+7t|{bzf#bgQNERvf#tdK`&IJ;daHljvhQ9U;RS&R_;$8 z#vl*oP5{7@KgpZSH_0WNMxMvtbX)x zG`PU?(_#&pdW9qxl^3e8e>62elON5wuYPTAexkDmy^hFE-GriP6eiE27q`)rmzXQ* z^-2wvtPBoz!EBHEh?%u7j6s!8!sIB;RLz%jvy(B53NJUwhFV(E4)WUk2#IVZ3l@)r zY(wMG7_O!*dyPe%iJ3A3veiHwByjKD%kkZ(H@S<7=9t>1^HedXJZ4So+e`=hmX^ex zQF_P_iEvEeK?Ri?JoFRvaSu`<_5dV~ark!cqr3Ldo<@OncTgk7tkUkZ0*zCi#)+6C zVbbZCi=@9&h;|XGv6v&|UJSLhW9!^j^9#?Q=>?+sWjRcO@p9|JC-P<(Yoh&v1znL( zZ7ZBHYzNC`$c^+!5}X!e8n&PV6h)*7Si?G+NUT159YZlcclsdFh1B zG?#fPI$9Ypd+_p9)IF%yWj|LqQ~S6QY2Gq4H7C3QaZ~cA<~AWw-Mdbd7MniBT1uzQ z;F?vev3c$p#OT%#{v?T?;<1i#pp)aYx~j!LY+sqaIR%WLf~+`B>VM*39y zl#T@n8O4%}^xN98$Ykt;j+B34$V-9K6l1W;9nm@HisxS7Spu9yupO|*Tv~OBuIf=b zz_5KP^1=?O>Drz~znCjsxNYg`b;q;!Ib`{f14sV(418{pl&PZ(7no6PQcc5SQMoTSTBi*!qa&BoNvFd}z@U7K$1EVZL zMAnSUT>A>5^kM3LdiZTiUTlk=8d27TOKq1@g_-0@sp&`w2+RO|RqjIA(ckY^uE7tG z(-7rXbS7IxaGQ$}9fY>ih?bC`ftQUYmIb7{V4`ecCHoW*CtZwkLS#AywGUP*fGWTbXGlBBm_4VHxlTO(3i! zgvfSna{a;{8x!5>3$S`@OsNZC+dEu$jZqV^oVg-0N$d@NWpD+hiqM-S#(eTr8l@mt zjR4G|W0Km;A*6B#*+2Gu9OwSAMW1?FYfpG8kt#jel)koHnaZ(9dL#mkQy{g$ICt&E zG;I$iUgLkaxP)?}Wjx8eSttCgJ0Z;m_nfgRy=bH)!0&ka!+JsUFxs5*=bazx+J`6i3vpVrOtD~G-kEuxbCp)6AM6u!|| zlT|lPt~Xh=Vod&d4~_1bAFUZ;M@&C~B+%S@Qs+U|tFVLRCmZ%7_n7cnesU)ZjU%h~ z5OlZ^7Iyg`?->t#zNB@ca(WPt=lrmNh4K5B1)mFdU;e z0Zwq1c3x`4(6xYwIFG}*-paIkzu4*Pw_>?=k{f@Ex!eLF&BVDp+){d}$n|fDyAFv0 zN^@81!MXB>%Y2@L%$0mS@dd9qS;|bpx!%~B!qR+$u+cgMf{1d3cb&y#=nEq^bPp&= z6G2Dlr%w9SQo&T{WJBVxHb@Nse*;iwnKWh-ld!WHNdG${naI`SF3P=T^l~r$eCU=C zDs47yt(Ti+cb3cgWEWh?GFfh{!>?zPFZiTLFHgSTU8JVHr~v)s{MWmGnmfRP3!|yN z&)Zx5HE;i?CEGs=IL1D{h+n^v!_0Q8}13zYu-p)>Ruv-udd*r4j^i9_%(nb z0aWyzRbkFfmr&N74x^tFFDMlUmsyTUmXo|j9PSWWAP_aup9K$Yn!$kk5+BQ>R<^}z zMedk0AhRvA;nLh_dIerGu{;HXSn>&w95%pWd##w#zdB{#7I^rJ**5^pd+BZbnPW7` ziEY~pVK>%cyVqZ=rx296Znz6& z)Jk2UpmnGL?m6ae4i5_(lZ4eP;u~K9=s4734|b?==y;lwkFS5YD3c_e^%K5#Cf@$F zJ3;j?3nyv^_-%yucN4rcWld`=VdU5ThTFI$Z_DFa@A_OOaazgbcscATj`|d zcrCuUB^?q?OQ*53r9Nw}PB30DmkmF(VZk_&EgUbUSw;in=^3bE!jXLs<2|i*d!zo> z^VyMaAEMWM{;i7$bm7^U{M86lswb_^Ey_yy?0$>)e;w*u{7(K>{?o@&P?!d7l z_WDW175)xu&UA*>92nS_Bs*#&FG|610!^y8YuGw9;INh zo@RN0x{e~_XE%6WP?$|OB3*MEqCt3S&(sN3ezn*XTHF==@_SeNK^cYgO(BaqraMU0AAQSwaK46w`kYA<+S$*cnbFOlcmB+Q7E6mC?QRv8j>rPQg#U26c3 znaV)pI>97kCkNVfTTA-$JB5Wvv?l1WfGd3{MBoG^_qI-?i;x5>N7{(cpWn5DtI!ae4YA!wx*xaUNV@$Qu z_sx{z_~ny+aleiABe7si<%Ox&1{&xkw*4|HQbDVb=McEvQqe49Dtul(Yn0+uqKF z+IA{ah@f=aKwzi}Y0oy!AvEKjxa&TWoFvjUyz|5_gtdl%y)`1!w;|@mm&prtXl?*R z4POV|M4oQPBuI`g^SIGFlaCeB?_;xY3qW2cDfZ2;l-$%+K_~xeF_8L{=-qVc0t@!S znLmr=%N4~S5BOpM{u8pHhlDwScRVn{XI;S#cEq4@+14NZ<+&IED<{DG)&|{ z;_9kY6__dNhD377eS4`GsfkvN773obFZW$`!&uAE!dNbU+qfE2ytl~WdsAE|lDMx^ z8SRbko+2vNKa_5IL!m4pD-4bSK&U862`e_@gW0N~tV-kr+Hx{GBbS|a-52Y7TZ$dl zG}=0M+ey;uZMYG0cq=iOdTf0)>zeinWs_oxpqa$Lxf-51f6Mw{TL7 z7?@4%TE?`gZU$oLzs+aEmXB#5@3u`LdBp@~FK=*<9M&1?ov~Q5>#5O5xxD!+1%E=Z z3eP`qkqt2tvr4>kNikFWR8CP}R{0uZ?4_ma8Ufej4>N8qww>x<(wM(d?*By2*qT}g zZrsQark+%=O7Y24gjkScrQXWEpy1r$&R1OV?Y5cXXVGOx;M6oL*vQ%5@`Mg^SQ>}V z)v}ot_cwzXO_)%Pv{!dXyBjrSw^mFG{PS1BM`zo+CY&DQvvbNcJy!XN?HSmriiShBo<+IAd6tV zQ}%d~JOa4@8V}@)b7ueAuf7d29qDTzk~l3S&J&W4*BPj0)^gmSdi+hiy%Hh*IaIYZ2}l) zo}ivl&DUBuVDe2rY1;wVgIqu3h{!goMDtMkI~vp0Q(x@Lt-anrDkE4ixVo=loG!Y3 z6G&sFU4Y$IP;tmQjKmSS(XaG93UyB7@YW`xbfr$Yi01=2&W(0lG&oQCC(TROr$gS{QClgV*`7tp_JpzPKZz2a#?~Sw&m#$*gemux zBzK`J%CIlf04;6+t00DhqNW$6Go=sNR#>U;*;1(Wa6}r5dOfW#aadpq+4A* zUQ;9=lt3wl2$bMCrSAi3uo5+D&>`zl97Z#@TPXSoQAYxDZS2bU0k;>Auv}T!OlhM# z)WYnV_H43(GPn~)wp+Y}scGP;-4-&0!xXd|$nuXPD^$ce9m=kHXUKx~=!Nyxf1K$b zG3{yW`<>PN2b1;Bz{UTLn0LQ)J8M%zT6;$u8*4iUS|=vj|4J-H?W`Sb{>m+wZ9Cy;H@@GKTVB7TXj4oGCk70V?? zuFqE9+BuU(chYMp;*n)185Fo#ICb_oSN5%?Wb+kq4YPy``cQ;;&iz3fyU=xbY&R5b zr3*yxE#&>CD<@qBm!PZ|4=fHZW)wgQ-pkgVN{TPyZ)(IC9Z(0jLMBu>ks8WBWy8qMA1#^;EP9F7gqP$f11^^YFR?$40-aEgus?SU5;YTjX4OT zzbfZxNLZ!f6H96@X^lc-`1AKj+>YC1?4H?;P~mQ;+RV2)=g}{@sc64BahUXvSocqS zk5D<+6^MM3ZIhw^C=R6|h15x~O1-w+Q2;CbGn z8-v7j5<5f*t;+rmh=kXotAl^Z(zUQF&m(rgDbz4sU^U{+U_sR ziwi3L&!7I@0mOgFT-3#`zsp>_$IY5DZA}#ojovpxjXGpQgb}~V#K=$YN+|u&{mZ7D z-UQ2wM$VdBREdRXIuF>SnUm0XodFE#rsf11#ECch#^a-lztR}jQ1b-}`YW4UzsWHPXo>+boTyDdi)v%i2vnc8-RGZWN zTpcFdy&}@2p=ft5ywL!JZ_}ABCL!b{e=4gFWYMsUD8kYh$vg?7izUcXL1@N!C_eO0 zb6SQYY|yl88MTS{yekW1aOGB78=MZW;dkkaPBP#T22cAW9Z#h#ufcO(d&IDC1f5v+ z0J}LWlsW1`hrxPyD%?Ns8FA&vjL0vP$gTuL&&g=VK(r%T@f{+{bX+Bt z!bu{BUXAqVE-GG!#JnnEcuL{sX(J)RhpsEfO2?yYdyx|1^qTJCre;s%TjEEg_>9rW z5|8s$bG{1-*Jd(QlmhkWLW=dcrMgQXP6nwYyIai8b(tKYzCViOxUL{OZH=OwIrPML ztFVTvoXY@w+UV`BI)s)JKo~oD?g>vxwD^`IPWw1~$lL|%m2c6GZwvr3q%i*22_d z!O*wOpgQY$3}&Nhh11BKV6zWQW{NtXiN5)w?zS#Cev<$j+20&W1w*2R)2-_MQRmTE z1uq=mBrua;YiTGj;!UX6rtSWXn#wHJo^GJ!0})LBIHGe zuR;cb$SYl-?FRV8>r09;ks4)TX;rUUIyEq-&!E47zJa#6T!P|4M5A*b&9>m)R?v-` zCuE!=rr0DUv0ASg8?B9-Kfat7OnmUK+zM%$V(hfaf|#)(XY{y9%?Q2yyJyuw zv%Wv`Vm0!6m@Xtjs?LK*1eowr26tfv(FkE|$*apI`6s`dJdzqD*2iK+*%eSGf zBRhv?nQ6@`KcNZ=S6T;M`G&=I%i$?I0(nw&R7Qne)rn*cX4InUNEVfTE!n!Al2JOc zX*ns!Hd-lHK`)DIvRHy3NGM=W(7~_t?I%eR8%YtRP)shV;mLDp_-A#53f>Gkg(OWW zDy2APvV1B^#Uy+tG@p8!V5F3+{jzhBcYpHT48;jCm~`1phN9s(z`=P&po_gIc{sQX zlY_ksaop{+vS3k(T5yCyIBRyBDwz@QU7@?IbvlEodM}uv>G3?_)PV4K}DuG|eKy>N^alBOB z@Z6!tVq{&NoModx9CIM(9>(LV`;U*k7#dF9u#(Ax#Tv!Nrj${ky+On$>O(_K15v+( zF_Whp%+BaOYu`LA^K}fw`b>bTdsUk^dL+ENel(R2q(u@#L)8M)t@n3#8%m`|W?(7?XMyxJ32CX3h@qvNr2J6UHMl`{Xl zK=rl^gkzC^LP)ik zJc0gt;{3Twg-q>$e>~5BPrdxPP5tElm>ct4t}wAEQmCDS3YLiY#NT>DTqYoxJEc#X zUVlodIkg&TLHP16xAESywj~Thp>Rk5thFblC9(eDp;B&RvDqom(~aQ6J!8v;a6g3x zGaH3$jl&Js*pzzd%gFSpiox!y2t%}i?h0idEUQ9E;O2~^J$6QkYQWp4RBt+gyuvX# zsYX1-%{l)W(bJKkA3U-CF9rPj;aN=-phSXB+ehK`Z#l0vEVhHx?=ZIKPZ3Pj1$sMX*O+!u4<;p5SrL^?jST~U_;XdKn zzVr~xFBB$<-vM~H@h`By<0o8@tRC}wazOeYIoCh=1d)GP9!a3<-^wN8KkKFc`%e|1 zo&9^__221mUX1*2j$z-Y)o1C>jnU(h1;9$kg7 zcnCNRsx)ra6eZP>7D3pZPO@vJ12zWaK2&jAjY8B|D zPQqgT#tfOrY1~=$g18Dedu~6Dh$-`yc+PE>ch|~as;g+RJ>#?PG5Vh#7;{tT7kZ&Q zm79)P$Z7pqeWH)7)7isIQ>8acg>|XRe2EN2$^8$n6P2bi-A}bTu<{F8l}IU%>%V1U zS5e&NhGtluSAVIE6zT7MXQ`uV=)A?DUA5|LU=>Mm>9}6j)d6Z)h*jfYlW386l?M88 zfTQ(1eR4Qwk9$ybWH$=I+k-~bz*9}`bF`aYC}ZA&@b{pmaAMX_%9QFSWX3cjnzt?utRQd?H5R_1bVdO9#+ zy$-@9;EC(HLSxVp`UK?CBj-+#NJfMCrO`GZXL9JRr* zQf$f5j5?7BgR%5B_u+nh0$f8*Q_Rd4Mx9VhsFFEF=O3r^%&@y?Csl|3Ko&Iv& zc1_(S$7@gyTLZo4R^61mmp8iWdzPDw$W^d-)|xJ<@j{@VYfjkAuzE8Adzey>Cy>?` zaV@#&UeLX*Z-EjW-O>O+E)|e*;2U^1K5r~>Y#AIbD>@-F<8*GalZ{TX-@*~(ajCF` zRukQ{5HR2|N=2TnBodbOE92Y;Fa+B6y(H_t{u{N&lEpS&7Lwkr*6}zVLzN%)3mXUg zqnGf!L@nj?Xik*+$eC&-Ez=Mn{4tu5r;p@_D(1tefwzc1m6}vvg`#2k1$&OiUTh1J zb#ZMCiI(FlcD#Jv+PI3%7)nEMUF>phd_z+;I5Uou`Btj_BC_N<2&-6^4bm~i31rw; zc^*x}kx7+lhHBxdDykIYwbiKL<>W5$f|ugE z>-!T;Am97@(a0oSO!5`^r@7Q$TMV5vV+*FR#F!pG@PG!PwFh2~Iw?w((I5AXC$YQl z-KVkJzc>A4bwOg~>j9hXeyL$FS1eMPgV`0(48yCAM&so(RAwe zp1)e{e?}hVnYf%Jm4i!f&idKia@b-{reh(VXivtKt%?bqj9C3@S5lVs&D!~fA8Xca zUDRpG4%ok-lZ%@6+;Px$-I;M+K(H)Aoq!D4g#r{85l^rx+f))MDZ2U2H}Q}{q@_0~ zETd^}x^!D}R_W8g(-cwuQVK3ju=VU7g$MZ>iN*+N{|$jC^w*V%HpON71zkhjw-}XG zh*g7fY)b^A?U#K4TFj?vj6<09I0*A1GrCv>($Mo}OI;zHzT|;#BCsRv75V3FnAq6C zg~it7a>|>ou#+BG<@ubq?-KgbKLH2%CGMu#c=g$eTevG1DLU}YUhbMA?)+3CwhO4( z0`y_gYbwKAl;uErA4%Uhhtz=m};)%CDYVR!ik!;4^n!Vk7ag#(PI;OdcI{Z7)h#0aE}aePz(6uJDE+{|2qEaMr}mpk`GeVZm@s)Rpp z^=YZn?&Yo*N$o`bHf`GsM>mvU&>vc*`#Z7%t%2rd?^w?L4=n#PPZ0c4xv7$7X^;t+}sjG|qR4D{nLe1b*aac`>hb$`ucF$+>|S+p`>OUI4>nm2!F}&Y5$N-TYR0Atw5u>_0urB<|lbsujOaz zP*kJ)lB6qd*o4c|j!!Q|L8Emy>D-&8w#XXEXjLvc_6QK$Z|Y?4L*LR4&Awm`-h(~< zRT&oc!P|o{VRsPfQ%`>gr~N7y!&v@(r~b7m^KYE$A2C4*ps(m)XKM3TD@zU9BW4zb zH^D=E>4u7iA}gZy%8WqT@4LS6aE|4YKrY;zKa`Yrq%YI^L7$xOih6>atOY3+Yyh4` z(iDcYn0%?!;T3;->wVlKkCUwNfqW|@N4Ui|kM#smU9rcJru$U)Gxqz}^QQfkn<2P& z_nko0;IBw!dE2B%dD|jx3ql-^Iy}S?=!f!17)pEeq-2R68AIDrUY$DurEf$?X}M%l zHwJDD8D0XsahO;^xhR$6l)N#Rc#7`43CZ_`ZMtI88s`a8UL?%s!?H;S^EXT}>vT_= zI?LyY&*?*qQt7}e>=<4;*YqLi(&y|ToorsrLs`<|9A3t2G}I1@Tve$Zy&(;^xFOx7 z*8XG9Gd!yyjRi_hy2>04i$b5g4Q9XIKD&G6@y zC)So%xcgW0?6=7PDH%c1g>-lu3ev-ao5N|+EF{Dlw+}QhTxPMUEsGWWJC}Uz@`<6@ zeDILb+EIbLdoZqBw%@cO$5(3=BAYx@j61g>TnRx$WeHJ3KVp7F;mC<{=|&R2aT5^# zmL3U?(!!ysHBRcRdY`XcRvuTf^21j$faXXqr)RdwR9aCoq{MzVfA4EUONoyt%nzs) z>9IouR21{T>c6D3{=E=|W6==Po{7fuFH9qIA{$+t+}Su}L99%)OwDN{nzXm`zocr$_+TgJ+n z7}LxhTztF`&YapT;C|fDC4|?1)%O`&L%xD+<~RsEY2H^Mn>KJGC50YC_U>NP0CJ#{ zaDeY;2hLA$WN4^|4+96vo{*Fo?^>2$Q(eN6ybTG_?U+dPoFy5$HYi5s-SNAEOO1c_ zPV!P?_svR_cdwjV{~p91ME+y zB&Y9zL!&xh2!jtk<&eksAp=-~5!IzoP;(MVr*9qNqzF`?8H4B!jjLnCV_7hTi>QZ% zny4vFGNf7-5>dG2hjN35*tsr*AET-B?ax1~;)h^3h@mp}QRgJmgqU&oHu97(DYix4 zYY>I7XRDw((I1zRrIUql*p^f8fl$!vvKdzKbuR2zVm?BxQcmNnw8RXp)=rRTers1V zL`ECTPEYV80dvYyqYeq-J3xXNoyFG=GKuU{pqE4)acLOogUT_96-HtlYgHwa?T9!_ z5QfIGii?_39o9#oYWx7rEhY-Ir3Yh@Ek#wbSHXH54Eu~k(2=jsW=3kISD_#XU$+FD z5EL_8or1ioaWkHF{UFaXt-?u~K%~vVK-oyHY^=l=wU3PudLO{W$@#37hE{#Z?i7d2 zs{o=>W{i&NFdkU@6Z!{^1?;D2`Up1^N09b!u*QY)r^YN@6i6&?a?CI7sS;f5krW?K zCC+F^p;k)eVs~3+KPsfg<>Ikh0EK`X3bx{O$VZ{1Gsy9HI!M=WjiM;ar~G(E9BQLf zR)g%r@`7v#Pe$Dq18H*TF}6dS>I}&q(z& zb9O=W3{0&23>1o(8t(xj&Ei;mtWT~TCd%rNX|lAW^a)5AuOS(?T2hP0b0RgMcbpdq zEulAnpo)Y}=H5)A3lBzA;k_n`n+eocRm-N@oX5o@`WWhs8rACOp#C*2^P`!gjwh{b zL)|9hgGLOI~@*_9&_v$QHusGyU@QaZUkqXEQshW?YofQ#xgJEwPvSr9jqGkQd@c zlm|#&$g)WtGJkQdOmZ)YU%y7SWEkYoPKB+Li$&&t)(J^iNAkcDS)6dpCb9{+MbkMA z>o}j$Nmt{Mtv&*x{ly~6LA1BwcNYtO9uf>U9QzOU=5|`~N?gICWKV8uCT0&gQcz0B zU&<#>8L_6A*C$EVYw-#xo*GFu^Nv}4EnD=LNm|uPM^#zab(l9}Rn31=zH2sckO|I* zn}liM7G}Im^Efbgjw<0;sEnm(d!`zWE>Q9*uYZQ z;3OQHHjrMJ9&2DIV`|=uYmjcg==C6JG2FID{5&in5{`gqXQa&wG=_}`!_ZH4w@4S zdfb@^C{P=bT4X}(eIWBR%BHtUlX*C?2TdiWauGCWSSKy>@Ww_|DSs$a7El{2TIG7A zDg^b!wXEZ#$^i*9Y0=`Bf~BH%Pe@o?ISStzk5a-FNU`}V^UF~$l_w}5nIs8w+O*ydedFAK-Tpu&kY%+V1v3~WnA1kH=Qed$_1tVlv6a16fS*7P_Sp#St0a+%oEMN zY1WXpmv2W%n$JC`?}6s7X_7Bj?#?t>`f=lA+(l599a`5MGYG!n*>+kZTFgvGnXSuN z=5hY&_}p>nq~z@!dL3Z8mU@HVb!xNT0#-!;lF6hlO5Fi)DUb@jKn4aYuraLN9$|Bd z`YI4PZuJw;)cF?PK6;t>#Hiqf3kW0}2w)Cz98EMuxIFIF5Yd&14@ou??u;vK3R4(f z3opWqL@qy%Q9?^C1ncv`%FU-suExsVd_#MEgdnx}KBdp$_v9fHfuTdg(o*0T$yZBXt_*6UXI&gLIQ(g{OOM=Rn1#ava$R?Ol+;&UB%4`8td4rcJbXa%St(Q8^ZZSC(1=kORcfNMM}=t>>tAulbvD?0TB)%4gu5E*9AeO zg2L?0fGiDUj0(Vp4*Unx0U=15H~FIiocQ?r-*HObf2gK^;gbK=hPU{|OwqBl7qqhF z(bF@qvop~(G5?_4{#R>cO7w&0%%OKQUm(w)f{K91*#OwS6sFum<(so3CbiA_FP`(8 zDzpbTHsTuLILI(+AdB5ZhTAy{c9zxorwW^`pOZXu-L!ry-$W2X8{~a;jBxtRM#T$O zH6vU`P)pkR)mUHwP)Bp%B+4Up711#1(;aFsq-4q4!x85SH2sIF|ASEx>Q4s01H^IGJU{;nr@@qtUt9=d|M%W}> zdIf_aY2v2)tFr@K5JpCXl}eomAt?2>*sYwYTWnp8($WfEMkyk0PD!1NivQAJe}8JdL@|4uyv9*!VQ>Rh2{GCraeE?NCX<8BOO-SD&dTue#y>Y-oyaF)mp2~Imjr{LA#D+T_XN^c1nXB*Ynn* z@^1VvNWAT)#4-n4?R51b(d;{d)Esf~DRt4T?EyQ3DbUXRIoC1EW~fV3uDOS3(cKsU z_DI7Oa*cayU#S=^B4fNv$P^C7`^3Dzf|M9Tn23}0Fg;x49=uWQQSI)4Iu;tqN7MoP{iQ7E%03IP5bsF0A>mkf?tol70I>4)UKC^6ORJR>#uL(8|{0zqAknB-p@u zxDnEk^>S%FS%0p z!+;=-#Yhx&S0o2Kp<_DF-D|T`rAl6Z{RJ9om2QzXfBf%={|I#bFT+az?b-k8{TkTH zyIB8s$5-Rm_y))K!@UA!ee8KYnN7Jm!1hN3#cYtkL~4!**RU7|!=;S1#m;#?u54^X z4L&(u>%h@;mir&=`(q3DgT&ru7%WB1%+}TuWx1+yCSu>u4m+DM?jz%TDsNLZX7)MxgZkNYJ1h5MCs?Y<)oMbXX>8$zY zT|z?($$Y7huDEsI164w8LvvxSmo#OqiGE6M7MJ9?T>(?GJAPW_VE;e ze)D8uo4kI1A&~$4>Tw0Bk?+hDJdGhToJ&YpSVJs zG@_MT86~`3nuzV}&ROm=Q$|a#!9STPlj(K@D?wNV*u&m$>WuPNZ)Gy|MyJO;%Zhk4 zWJKRVtdwpvAa+_nc6rcAlhHa6VU9Rz$mAl?~{4;49{@F_eZ`; zG{19F{b984zsU?N9p^I+rqF9nrz|Z!dRiJb-d``= z!+#oG6vg-BMPs!jsVy6mFi?zFQP@kQGaFfz)WHv6gBX@D5p@dVNz-E14z^Nb?2aZE zlVi7>C-3=?$O19|8dXd{2VPAyJtf{gi?K%ubR>^D*##igG*`O?auT}@?2e{PDX40M zJY)6^ogZB-TS_cDl&qbqGFP%HKcbvI;Mg<=DH@7qL9k3w@~_rgg22DlkX6!DCz1JP zDzfHp4&VD2M~gN`ly!bcdBxFe(iaXD=7TWQ8$Y^4)DtKtPm%wWqoh zaVp2v4^vIzzN1cHE+J7wgqR?OUeZ9gbZtHBd41iyPKcO!i8O&1=7Ydgi!vaLgiMp! zPe5frTb@X7%2JxkVoO zES>QX$^}5KyrXH4TM1lQd2veOVyh;9?CVo!)rLtT`2^INat-L)fy!`m= zYi2H0JuI~B2HdR%!7be>*^&LhP{_}rb9})}P;3@d^D}(Ld(xU_^0%Sdobi0$agPvV zODcpJX$y>=djI_{V~ zfiQ&rb`mKW-@7FCI|qmu>^zbPhbs^H>PWmN&p((jgxcn6p*~ zfFHadO^0_i^j4Tb4+PFBYgaK=ZNHh&&MZ)E!bZ%b#~fZBoguI3-5q|qZT=C&PYu;_ z+{P?Z4Y|o7MvYq829#R$A{Npk{lx$s$k}5lkVjLi`X^!_l$Sbo+^jgi=y6TKlaU;l z-%lk4(o+R~jU@ZPGZ~2ls)72Y!_b%v{9LMpdR6NL9SP~%K1kC`4dD<|Je=b|{$!-K zkxA9hGcb1;h4p}jeJoSu!KTxgbkjAd7=~4Dj0)fQ=YoSp1$7U=B7nZrN|Eec2EKM* zE;dnbv5j}VK*pQG*r;^AE1%fYFb}w)_8!$}O5q%(fL%($_p8jK-UbQj>1^mH->0E6 zCEmLE`FI=Q?Wo=0duqi)TjmWW3Y7g!+glYbYOlrx1Fmk@SShOr;oWFdRklT=XINOXeA+G!&p(-%*b z@Z%u%HaATUCgd(Z2u@8y38fBL(s~K84603iJ>kn^Ob`KX6`u{E*CwSM3vMT-VSA1+DRXOA!BDxG%^=oRi08KrbfKry zF;2qWqZZ$zd)6eGi@6_1v8&@*jjLB90_Wyyxhe`@liH2cp^^9XAyjOD>j+*Igf|O`5Z0ctt6Y!@v@lD|tl^`oh?wVA zY6N>K=7k85+u!JqabZynpKMt_DODCmF=_KqH|V0j0%7lRu`N#domwNmVD6k#Tsp;c zw)SoCy{*G}VLwJCJUma0*TvqVFN)B_YPQ^>Q}9f ztT!T^-_f>4;C!PbI#zakRiwIdsVQb(;*Kl}h_le({tnv6f|!yBv`QsiKWSaXlWUvp zXF-yKN-_!26$S5-8aFyAjUwTKMpvG|;1*(tJ#|va13x6hHzAj47(Q@OceiVNl5Y5! zDN#>_ySCU@-(R@R*r+2`<8U-i8Mcof>xp7~3;aMUmBa^z?F5r@<2&OKneKjrer#1C ziFfUR!M>>P0X5)MlpJ#gB%Z%@=Arx?&PUUrCWKs+EWkWJ6GoKjCN12w+^`bF=S^7siBK;vBA{t(ursKJ)ki6j5w5&I+V#~b1t5ZdO zW)^_=?DyB~(l7GgQZdLP&FkS)T6!M|6=CJM($A?CIWnoz^4FJEgC^aT4kccs->+>a!k=9xie*+)c8;%kV1YGDrK`G=-~|pxMBnqTT0ISZjym1$ z^4M>(?A*1sVl$^fY1n7cnc0=uk$y;{JagdHvM(z_2lPZyYd0t*PKQ4h&o~q-t$>;K zfv>E`+c+JNgd2@6UAZe8&&E!7ML88zU%zj?Yyrt|q;QYga)xQTxg+dfA%!9Q8kCEv zf=yz%`=yZ*ygL-eaJX+_)7ce)cH(%e`Vb}$^Q~LX3+dK>2jM9Mg%g0{L z15*gG+hcX!^YlGrf1zMD$`bYE+g6fR#uQQKxGZP@uLrv-{J?YG{ACfWL0X?mrRZiK6wV;QAGuCXaT$nR^A zvPddK?RFd89Wg^)*^HIxr6e<^5CGQjL@GqB=>(N>_KJcFL_kCC97*j3HHCq&A`SA5 zGBW4aO?+g0se*~}>@wNh%}lf^b0y89p57-~WpFCmem4bV9V`%%VM#Mv2J#9v#b+@i zWD3224EaPNyYaCwE?;f9d>(i`$YL20`2%oDT=QwX9kKM$zc0$*U<|1fl!{&x!^9yw({bWI@8pO5e*`x0T__PSQWCm&OeKly*b5+LM-B|HWr;c5k#C@}){ z4J(mr{v%t>%^{=f|F|F8zhN(bcOuIFaL4|)!5D)7?ZO|fAveQ~z_G&1 zCkDtb(C?e=O{wrD6dU9Sz%zmL=+g|ahs{cbLkh#8`84Z8n){{50I-)g*T|)1>SxgI zX;duR`?EE-AMM0$aT{KqZ(pkXjZh(Sqq{9urwn<}#nJ>U66=~v$2lw#A=zmzCcE$h zXH)I--s5poMw3vV=GRiSQK&?O+DsV9cuy}vC1R#x)pi|I$cyiFswUnkI06qPDvqW} zFF6`_JGVo>wK+6S?RZvC)qNvNGY#pcV2zYMX1ZtRiOzs?G95`^95rK1tGFt^tC>sO z3Uh#45MRJ6h2V48bh>KrsBi~BK<9wcS02J-fRU$+bID&-q%RmV?HG!#N`nZ%;wE^^ zPC=H8aJ`Pa8PL9+=9Ag@p}noe{=Gr`V|kqY_9S+U=Dxnz;%bt`RO!+E&6zMS@q;>< z%x(U$^kf())XLOQGF+xvV}JGRSi_2}!lmpHY%24iDzc+XS{ic@E`S-)fb|@|Vj8G; zYV!OZk)in5(PH}g9*xOQ(BAo_D5Q3YwMYZILd*8@lURhnar*M!=+}+v&rgEag&iD$ z^_s0KFb(ZWu&baqRCi#7;8EvLa+6%dsR~bW`G+~=`D-*TNaf-4Z;#m88^a$97|qE* zEH~LzYU8|R)N>OKSwOnU>xgbtbg)CLV69m`MLEFnR^1KQP!^>`qMqlFensCD z1&-2Xz&?P8W)gQtUhLEPE2Qep8dV2>_>YKxDHZ&wKlAs~K=co%LFeB)EB~fO^Y`yC z`G5Y7-@r1-k5QJ7F-u1i{SUwNp^B?x|2vrW@7MprP|BmKO~3HK1isU{8c_kc`!ICl znbZJIs}vL92qVa>D681Tx%vet&#i^8#@0_lR_i zWb669eacN5IYkl9ICnNz{N?l!Fm(kkG^jr>Qf zpr^)2$veBsuqqh&nyff7xuQarwELrk^ox#p?2!g{8^&iARzL?tvHjbD<7qf7sxdab zeYnvP6c)Ia_jmj@t$rgQ7&K-eM$m7@1rTV}$dZe;}4ug{P$pANTU$ zH~*#ZH^frzKfl`|mWEdUhF|`f4*hFjwOn@eLxC8917PU;7Wn0>I%#&b=&Fu*a7YLc ztxT_{svw4(>NFCBS3bIgI?94){H0_uY&|$K)8T3g+kK|pgvrKw*2ltG9SuIXYf=j1 zU>zAsF;a@cs-9@}=!P3;)U5zrKU|v~hOfQ+63e;k7U(_gTY&;8>f^M{b3ZHO_i0it ztnvn}HMbpS9Q5VxTQVZIpIoi9&P8kr?Pd@%i6KoyIxCfeq#W>At1C0`3)eQ^imS>x zaGN~#63HRxGcV8qt*6^yGG`nlWcDraRw-sJU80VW8r7bfZOFwt>EfGjG)x-Fd|*Tt zO;5CL^O}*ly*eS?LRt~W+hMyk!oN&X`Bmr@Q!KxIKfwGNF92o|xF*H+ex!r6tvrqw z#TZ!Y^@;=$$0ZQQ7hpVb9RR{r6$$(FJPTi#1n7&)$CiQjomtlPi(9q?1X}qp4vU|R zYOUXwP(1|tJX<{T3Rws7UD3*53l6-uui0Obuls6YyvLxxXhVv%Lm_OFp|r2~>AlH= zYV#0R@!{^d20k_v6Jz4h@+vCW{gEJ-qCEAdeb|N3Z(WzapG2Mi%r^d9KmI?R!9TD3 zJ_1so#Ac1IfWUn&T4OM5o4#0$3F7~WXed&T5T<8vU?4^hhB>l2!b=3Fbj`>uW3Hmc zYIg$S>t8Rv^4n0&(^8DY9(qJ4kuTcFA#db^dWRvAe;}G&&YsXYW*2#o-y6*#Z!=Cal6#84P0_O5CbM&Gd(S`R!`L z7SW9QDp$fyYIjs~xd@Mve^Ps6sX|gxbX}RSn~c4!Ak+ZeZ~CHF^pC zgr!1qJ}o5z)Z=j?0=HJ=a?H-C49r`a_&xCG9Da`)j7O#{A@;HaPa~(V@cO8LR#)hmqY=p8b6HU zUZR_d!Z|?mZsIqg8)NQv8|vn%{7NLDi+OIUivTuIaQ^eQeia>03C7oi5howPeO%ii z3v|jH2^Lxzf&|-a9ms^e5G{-5TJftyH;#d`MsHpn_w~ia-r;l)YiN+etd7M-EKPYL zlIDUbY)6;Cb0kfq5qrfSRm{K)^{YJj&cjC2nndNUTBQR9y#!tTJNP_y= zh_ND7^wNQ9BGw2^uE-l{%1aTM+l=nWP&d%WW-T*vt&-Qt7IgrvuwIOL%Ec#Vq3B4@ zjOey9QSVZEn*@EA_c326AM{9rupzj9EVrR*Qa+fYz97U$*}(Y46XPK5<3wzrYJFPX zgyF14{#hlD6+1$^E9tk#%T13o$&SZJ{gWQ4r1`|;?x|H)F1#gsh3%B&hJkLY5gla# zM3DL>#&Hz~We|_X-q%J7Z~&;g=^HP*xUUWSm+#^9yY3T#w{!_eekgNP38yXw*CkEgKGs%VXEQXeAo5Rb6KLFaG15&!i!bmO9&QA zQ3NM0CQIOT23#>!>2+n?YIpRYZZfKOaFEXd{t{w~255KWplLBx!D1(u84rouj7Gc05SWN9#m_7c5K znDo92rD@kUyn_GA+ja}s=+r)HzF4GxfSh(icu7w+NIUul>qbfvYivaU-6C)qEITIC(*F zR@WRG!{J!qYjjADp{|m6;b9^w1Vk;N>nyEFVv(cT-Bot~1jW~I*1|i7arW$sQ`4=X z<}%In!qa(P+yycb{vj^j?PZ55mtv+_IpH@wHlh&7rvy>Br$KJwbU-S#`)Ds;&d|cX z6WF^JX=CLWfG7=~iU^E)wkIEeJ97mz0@q0Q1Us`&Gr|?(I->hIH4-!M2Nz@(E*A>~ z&~a2)6xjKA@Wxm^_z6A_xIh~BN=%F+J3tQvBkCM5#V2W3Yc@N2wyg6ps{7N0q{>eX z*5m^4O0w$x^?={t>_N((M~W`ItExI^2^gLmV*Pi0=&pA4<%RDB5mNEV0o1@a5G4E0 zU8+zyNu&-q$;1xZ$>J4t&g&`4OEbmF@3F*muBMdXmzzHZEb1>bZ3Spy3Tzb>QnJDa z=L5`JG9(gSl0!OWmT-S|U`7ZudBp2SRqYroR>LdV7NQ^fY0x63AnkeFl`JM09AMr^ zgG0Lg7)Me|aalG`Sc} z`uyQJ1`>7kujvouGBkG>3wSoF`#jwmK9l~a%6Im=-pXKMXtrytjT*?hVknt}t~)S_ zSWLG_!_Res+BY-zMJ$`=AZ+pugE0RoJKj9j^V8f zdigDX{JYSQ=znHMzr4m@wZ(@9(ZA4;#1Jod0ffPg#0HZY3m@BHZ`H53+>GAdcuDzR zA?pxH6uG4v(Kl4)xLmKF*j#Pk3w_pxdx7^St)d4BxcD+0_Sre4f;z5^_lj)T?DL|)!h*;; z&XPn;(2hiGqwrm9o5U5=a4W%i%n80rmOj_;=U8ZAPJ+ka9UKwl;X#5RVW>C^+(-W% zx!4Ke$XItt+wdLmSZa|DyvNiX^w@2JjaYXfTi*|%w)@WyxSt9UNHR@S3%;rOc;?uQ zgCWc>%kcTU-4+-y6fCPk7!}XQc4dyZsx82cr|L~x&8r;Lr&fHqK4v68S~O%hDTozW zx$MD|>%lCjW-2>u*=#WkOQC81VJ&f1DX31O+kc|kN?GgzyO!b8y-1m9s0s!F6;Y~H z?qIy>Z`j}at+9;B9(r&vutn+Wa-4+TpFT{3ZTA3W3&)4ghc+jZ2)A&u560x)w_27G zt$d1OX23fL%o|qJxO%{l1oo@wq|AybQ7)K2Akfqvj7(l3r2_3tD45;Bk5hHivTKB7 zqFh6_RQAETt(1%cc6!)~ZyH`%ndg-!EU1k?Q7p-PzUNCAu1>eb`?+XL7A6?pF^mr& z`r7o08No@-z{pt8xB%EptFsvhtOeH#+d+Wimz+_C*$9a>q_&`IZsF6!dUiA@)M%4ZY{)~a55@z2h(KB>dpE48EhNR0)oyVSg`|?{b|+Zp059X4 z6N0bEV217pn%on0?&=LiO1GX~J97-}qVsIxnlCqGOE7q&SJMozPNB)(EC-q_E%+4xbsaKq zcjHpT7IXw>v~CW#)2&HPPxN~`tvm_~R5(<|LeM8qpsiL%=c1&>19|mgYFH@f+bhLh z2c^7kn_4f#=fTl0A)pG@ke*F58~iVWtxyO}NNPH5WX_am@3bVqRWhFza*&=g@O4;A zQZqj-^g^^HZb5zvOA&g){}d3Et<9yGfN^f{Hnzl($O8C!XEz!?qGkxS+Lc(Wvo}1Z zPWOgFsnGX4xc4BYO*Q-U#+p3%!pPj}{WQdt3m#hg4Dkd2KdE@i7g#_{2U5S+8xc&} zA0)=_pEmjRGZwPoDnF>@=d(y_@Eoi`kVcTo*9+BdYeLAm!EAf3!F1ouV$NDJj@C4l z&ybS`^kF{@Psq9PT#)r9;EdsRtH6EFZCTQ(#x`Y}1ZocHJZEYrnbc|y4V&hmty2&R zubR-fLf36Zb-wnFZ;`40z>aZ&o3$uwAvXvq`3a8*OJs_;N_BU?k8c9=bRPW(eDT)L z`<_Af&b{sxHdz^B)j(CW^Ew*vhP3qL=lo8Vqm{JlMU&+vaS-K;dk4Mw8aRm^_ZW2L zDR&Sx`htA<#+1{ku!lYHyb|Ckx7V3`U+DifNB3^MzCn6Z8S^M~@#g0L=0C<2d(VY) z(>VN+bnzC!+evt>HS&xN|70O7iY1VA=}kOwnQM~7Nl^L_v||{q9R|2x6_iKbukmBM z0oU@G#Tp9>=Thw!466~qhK;ZZO8IzuUc~0R^Qu^|n~LwTe$%aWl78)XmsPXi6~gYd zh{Aa5d(rQ$v4f|At5~3CoJec0(+2|=P3^&MYQApX0{7VrE!FI29DS#8Ke2SDETXq~ z+0Q<0aYp}SqFe2iU1i2{g0aznTg8XCFGBd1IfyB^3JZEh8|bF48VbsOM&E~-@H108 zf05voxopoy3+GG>^i1T=<{{p`R_U_I3dTv@*DclJ4wdxG6wB$04KZQUI7FjBDEM`g zT=27uuUq0~gQ(rNn88=yrWv?ZjKo%p=@H2-8zY$eR=|ZWvR2GYy(W`K>cC<4Q)-Yd zmF`gJksqzjMA}xwaCJ7Y?w>heJ_NVD1J?AdnD3dLqSnSkDh)S3 z#6Y(OM8kpuoB(Z;- zf$ol2v?Zd?fNnkjcj}KuJdAMMVj#1oH?mv%kmeYuxfz)vGI^Z4%lGD^g|m~tc~*M9 zI@XMy&ij)nzSMtnh|Ama`dSE{)=;tyLjVKS*is^v*P_;#i=XoZe2#$=UPUjQ0zLP5j7~{`Xe&|Bw3XuT1IpTmD~J)W5Z=>HbQ* z+v8R&XFk>hzB{BdqwwK!SX1N$WWpi^qs#lt3-AKw7xR~{R-O`?@0Q`OfF7xJBO)Su ze8Tbpw_M)m9I8+*djhn(l5S_&1#YXkJ9JQ3_6qxea1|NcfBSkV|{@!fMlrr|yXZ7Iwzt@ZnSbW$(~5AmjF%3scS2;8i{p&> zavf_cu7nN^CG#}rUs^v;J2D@lGZ(h*RYmqy%&oQ{Ho#2K12bu8eyEmK3cW~n&1G7t z^N%yWR5_3_`(bLS|5)JZ{by(V|0?i4j{QgP@-HK+kDK^qWCNY!*sXv`yf~!s4S*!k zb#RJ=R7D{Ecrb~w(W>$?1pZ7vO3Zf`V@?5`iK)_ym@huD1Hd6uS$luu9$Q2LgkR=U z5X(%-$TEoSx8Jw`Q_`Y3lTCl0!sqS8I|p~Q>_u}6(D-E@ zDbO+dx=JjlXAMNoM2#rAImw@*R$_sv3o11Tos%(LJsJxNGI_1bGndDZyFfY0zjocU9pnT zb`|PBzM3mQ2gZ319cw^W2A}PuHxCygmx1dcC%2PujD)7O<0EFD8W_0S$yj9fkdz0a$1msQCpi~H#Bb@r$0j^Pdj||Z2sq5(Y5UptMn9uGMbnJ|l#td~ z8hAqIbJfZ#lXv7&bP$#as@|p<=u<@g*uqc%f1@Lo8Fe{w%6(&wcIC`LqRA>krs3-l zjqxE&&mN^2*6N-8=<5N4s2aY*-Fz6~=ij&nf8TH_@t+ytfBCgPBhA0BJ}sA>pa%HZ zM^VsOJ|C4^B9M`XL9r!BfQK6)K`4Aab6OPR*tnFT_##C`MF6#R5(Q^904CbgO>n)Q z_U-(6{n_yTad#883n-ByPg-2>2QLJn#fZsRVRcvZa!jUtE5zl|$JUhU^G3klCVUQ= zbEh;s=IwDPgR98%D@i|K*{tvSyc$E%IeXTXhz~UeL9dz<(D59LHNdj!OREk7C?f?Q z^kIv056-z_nQ^xJ`&Y}TQvBk`re(vS`T*M8;-z~61!pG)idi#3+!*y0i_K} zrn9PWiczHR23 zwL{-~tRJML25D%^rrhOT_kZ47j zo)x({g*^QWu%o)tV3}*5{1-8|zVSUw6T1V!Co?>-7vQ~MDGb_6ZjU+%yF+NFgbDa6 zK!|LX)8I`_F&K(J`*x3Y{2|)Z+pyT=_wn@4ew&o|JI3@Mx}e|EjNb#^zb^d^XH?Mo z#gTuvaI>~32O}X1_VrelX5q;tA_Odpo|X3?+3fB+xNC{;Ki05oq>Mcfx;69VC%I%1p56=ux(}%dr9lqNdsJ4Ve9ActK6d(! zp6uQ98to?K=muw%%0&OxF)<{MLsDjxh>og^Q zHThfF4%J$eX_plw%O6{r#6wROJ}U+bF$TS*3#O5!;RE4Q(Yn1q$7uxFCe!80Z5Ug$ z+9-OfD4E_;9*_k36NbudTJgZ9<$PbnmGkH{ z6XpYoi?aO@QE7+hNBwpDlSYA2>D||f_M=_&CnCoeAY2)5^pja_a~bd}idZ3SXdrtL zbC4|F)$6Q@Rs$IT_yUcD_Q|j%_%%dEFJwrH&lGS+2rWCb*2_W&!;}t`tJ(Q#NXVI# z9F$Iym-K>C*L)W@PXh>1Pmjh{N+lg5Z7~QruNn%Q>Z$RYzZWhAMn@3~v51s=OshE_ z?JaKwrS3MViws5z`snPT6i>|-gi5Y4_Q&3wFLk#|_2g*@pk+)tunW&Ha+Po6_NK|T z>!G%&T9F1i6~fsHG+|Al3VxLEP+=peYZMUeE8B5)#sdEzZ6{%V0QvopKfh*mX5c?u`a)dVG(v9#3cuVDk#ryEdC*m)E%!W-<6ag-L zoH5uBD#l-#<=-cgYNh43mJ0m*W!Yf|X?R6A z@}h|GzEMkS%5w90CzfjN*Ks!@(!bQdZ5-QiLbv!#a8g7JZTIwvu3xS$0JQ8#nX~$W$0)}rI+n6U;(E;#3w7wmJtyha_&72nE?4Ja^o+c*|7lev_JV(<0n8k zp~jN$vhp2yThi>5%7&;uk08CFHgd3%D%SV5v)&ujd2xvcB*kh=mZ&#(Bvv5SsZpK= zDH@F)2~X8ODACPBn-X`N2`7OZmLfq%`R{9-gI6@5A|)KW9lc$qrX^qjYd+z-tn8Y` zIW_It%vD967FhFcnJk{Gw|UCy3}qfQoCouvCg_}YW*<+1+YaeQhtBJDpu?VF@Rc_< zK?Ize7#ZJDFF>?(c9unc%`0mD9+NH7pUX5J(;yP-iUd%4ukBRrLgE;_YIrz}5hya+ z&Vn2DWf($G`UOyUpkWLjZXYnV?G=z#xAzL!8$ys4X=QNR;fqPEz%&Gy0ooxmMYQK1 zhCpAStP}L%aO3|m=M(zR4dJg607zg+nSCS}B-<}TMNN1{LcG=Xd)X|1VezrvUGo}o{XXI6wZ|XM1YW0fc3TA6g zu0PzY4A*xkpF9G%nD5i=COGb$CODkj_^_UJ7TP~q$I~R#-ZE*Q*rS{48tvfR+u<4Q z^+=phlrX0?*#*D&4mI<8itMoCb>dx_;qAjWdk{1;6;z zaxH5!u=)9O?bdMBiiM~P?$}Oi@aO}?kcXHP*doT1hN$!D!^fC~s0;15;(6iP0>q$) ztn%yA$E1b4Bn(mVH^3~3>Z8Y~g{%q^@a#C^t%R)d>`3A{!5$LV_zg+o0q{G*E=lZI z;@!hECk=V<-@!Cz4FT|DF)BE*c3xmJMa%Z@R=_W?y}cX&2rV!*fd+=?pnRB-0|?Uf{oD1+@x3IhXGs zt!XTJ2^v~2xXQwF3mS0}xWh_#hg*7^9`!h230d0$>6K9SqvgkRdn zd*<~o$0Oihr0U7Qy9uk3^Vh&zrR-_PJAvK&42uP)Qwj3SzewGqhsTcFGlTa`7v$03 zv3G)wu0HbP=ZPA+y5z1C(<1loJ=3D_E;Lh9>WCi%5wi!U7X#V>2p~Z9E##(TC)+Gy z1!SLTJFSzIRMfNweTOm~ODT}IEY>0~U3pc*o7!}*vkUhtmDP;}(Mrtyp zsG0J+zAa4oiLcr;q8om*t6LRTC3;mQKhTfD{Q)u%r<}F4nBhv5>05Orx;h(rN-foL zj)xJ?POk@u(C=i2yOzbi00^y-t~0KOW`CR2m|C<6-9YXYZJn9hvNSi=T0JnmrO~zo za;dN;LAwsrwOH3)%?eNh=^Y5oD6LptqEM5I@ZJ-RC~T=%p5qk-_uE9>vqc<{Cof=g zm}}Ok&m-5CE;=|uLpPm9?1vB}N0dw|UEa1)YCc}29Gw9{q9gfnFxGX30ThSO8h8Y+ zwwytEdK+OecRL43dCEBcBXFM8h@OdCF8qtQoOoJl>B?$EITpNK>TZnbgqZ5l@v=>y ze%LKiHapsmWpqR^lfW=@ODg*D5sdRSozXR38HKk!d%_4=VX0y<<-qc){wK6FkSSi_ zpr+wNlVZU&mZDn1an))mK>*Ce)K;Wh0#JFS*l;&HiBbmh_RGdrbX7X~QTQ-G-n9fg z_B1HxkpS1l)67IeC%y;}VEd;YX2ow5qI#y4rsjQ17BHIvn2jd%Qem~t0o)-Mbbk2Z zki)I|cVK~1qHqXlsx~xy2Bi2ADB%m3?PejhsLw@~0|6CgRb|yKF)|t%tvSm>HtUTc>6qL1ukRcB){Rw7(!JWk8aO*v!S{|2 z_>}9B*;#ZrC)YqLZ84vQL+RKkZX?ECxJf>wI#?=#${=3{T)#9qwL(D-dDpF7T6&4E zKLjR-FRVPlXpW(S&@xvO%vH{+pvUqdRGkGMP*^U8{eiI#G-sI-%=GX3@~;_W~-USHH{c~Q*x{% zZM<4c8}uDf;ZoXYQcHx9WnI{*Z2>z}V9q7Iq5B$IPYYXfoA`Tb@HYhLElC*gNe_xj zHaV;%3u9Grxoq@F$Tnb*hgq1%RFRLo5D4gwXg7`gMN%hIZ zfKV;E%R>YzL+m+VHF&k8FP#eULjc+%A8pu;p-#Y6b4<*k_FC{c*s;kk0ha)iCs+6J!MAGBEWzkd!4kFuc0h~yUJ$} z1X+6nvZ~CImG>aEzIDdOdN;A*(#)oLy!!4}HW-hBDtEPWS8O4K_FO+BDM_ucBpYci z+Ba0-+|oXzh80EBjAx1o)o)EXX@UiMGmP#mBd>LSaY({~#c}L0Vrv|SK0|tNW_~xC zgow%=vyR0#ID|H=Eckta=DH!jE*`qRr3=lgwo{EWAUCBZU#Ueklw;jE%6)WfpvlEg z#!n5uVv3?oYl{dg@^;b`Mo*`iKHcT9s1$56q@QienKQPZ1hRsxxkMH#!X3wT{@&4_ zRxM7)`WQ+mJ!+J@V|IB*ZE)+;*ZM_$t_%@R6z2Eyh$X1=-p-gRD7MuvYA4q8FLO}u zh{>4ifnIRLI6hG!qcy$Xd;@~#pf6Zu%vaF+i+*4{C? z(skP!jcuo5+pMr+TQjzeifvWQiYm5Uv2EM7o!qRw&pCUqb?&!sYwLcQt<4{Ewl?$Q zdB=Fh=%e@1)iYy+dQD6bP(q+_qd#tmb|QsaPmc1cYl(@HVVzrI25L?P+ZlW5(W-Q~ z(?T<9C3f9V+%k#LmY1A}jfIE9MhRPBy7W!OP&v|?zV_k?t!i!WBXeXm?Syh?HU;&5 z4J#$KLAIakokMC2Y|8JQLs65{0=1Xv&G?oshGk(|-p$CZDZ2`@ElX^JZeJQ^NiiN_ zZ^D;7IQ~0u%Xwa?3tFC4Ha|NGNpx8~=59O6GDh8be&F|6H>EynLEO1Qh`qj&eYq-z zi&47sO?dGV7To+Vizllzwa6A*<7$hYE{M?{jiNb#mQG?{@mioo5{u_@cw(Ou74Z{k zTu5%LNyM+^Ic3XI+N1?8^WT8RQ&u=F7^)bi>7>dExtuDp2#Rzn>Esj8({u6k1l*DtP(Z9&UNB2xl8qhiBj_qktD z11+xo7rS%4aBI`C&>GDv^79vg4Z~Hf6n}=W$XQ|C_?410URSKGa`rJdjJe^gEm(-O z9^_6v)VD~G+@q+_^Z@!uK$L%Z6}+WwK7suvdjcx;lXF62=`Oc?yAs((kVA*$y5F^I zB9HGiePS!lUW>{#FXcvQ+=Y-^v}8NM9;EVh040B39D%4?rKC65o)`6#LIQ!(P;~BV zprkj--W&B3RYI2P(8RA-TAt*%EU_nFNpIjiOqFXX%8s(QkKk(>>L-;1T^zKF1<1aa z9|Cti1j--#zn)wzCp}+D4Ed6L#chFSTLZpOi1R;o#!R>AZNOW(9U&m0&=O&HM6ePZ zCYLx=0ZhJS=7X#YWoX-ge8iyyPo)XjH)3f*1C}RcRLz&P^_sn63Js@bv<9n3<9Xnd z%Rgr-NZ+>k1ha0rS9~@N`%HsKK><=1U{YTI>{N8HD!ygmX}F$So;j?1qR;3Egtpub z1in_lwXulKilq*5kXhZP;qepb6e@&o*WgdPMx#KX>h3y8rJ@Oly5c&aFN!eyPcM>J z9O}o=9>PALF+FkXDZ^=U7FYGt2ARx}{$~zY5S<0waWNL8;8-JwWR)A8jm1w2KfvA+ z;J?{mJM;IH94( zXw!l+!jn|lm^{cAVrm{E^Qhn>gywS>u+3TE2_y<&MTnk_&fbn``ZVe5o7882ja}Yi z=-uLm-$YQ^L|{oxR#YQz+IMNqJ#wv2m+HaS1p-zO4fJsiRtNL0llPxSVcis zG1FBMIQiijLX>HN(sCnS*WAGS;*|oWS%O#vLjdmWwDoRAeaB`&()>FMz5taf`;Kt{ zt7e0$Gt4qhkeSmx8sz2I0OEBi?5PcCN!% z9Qxf^^7%vaAh0A=e4u*t;ETkldi*mWnuV}s%W#XhbX7OVi{KEQ7&M(0(!O}P;Lc(6 zRb-$4VGd*^u(N^P?*bdhQq|WD5J6P61CHf%F#Ha{ z1khNr@bzL^_~8ZeAV72`Ril#WjmY?ZW$SDzg0%|5uA+u#j_ZE)I_FXrvtX24>ZouriJy^YKg_x$Zk=11aiXU_CYsCYwO)!5%0Uy zQ>V)Pd&J&J4J+~-ZBO6b0%p;k(8m~85`h3XvmV>3_g-jC&sD8>6JDkZwnnFK&e}|- z@{6hYl8j!x6`coInYyObOLjZl$C|j{629J@gWSCX?Y$tf2B8xD_a!?rZ1ripi7rl{ z4urB-_sv&`!99-cL-rnVZ43@j-dE zWvF_@u(?s00Iwl+3@x)Cl>m$l_#clAHYGGPYrqt@LN_&Qn*t(IUgmE6bxBlnQS4=c zeKp>kv5`d%ZY2&PCdR3TWEfbX@z46`lBLGQ+DWoWWR&%F-? zs0gJB2d9f`&=T@>)M17c0ZGqBN381MgNn*Y1~q8O`D`_Hs!8(_iVjvM#(PIa((o5> zRA6tHH{d($--?Y_WjP(!a7UVmBka!AVTZ$MxwmL*IwdtzcdQIJ2t12N?W1PDwB@PI zG;>;ay7&&d2oi08=RU46W^RBwK6=RyJ@|(31L?dI20jVdk^5lL?|SHiZa}6z<=SET zz~S#k_prP|y9V$>6I{Pt()on%T^24uy~CyTWf?j?-IRqB=t(_&K7jAUnnStYfF(sN8ZU~PDscIJS)r(R4Dt%ngh6-pKoKS{(XDkkTWMgcTYj?L zK!f_>ZZ1amhy?EmptpIjIGbEn9bZe|_b(8eT-PBVHbBotz*Xv!y1ts18-lNm@P`*F zzRq|@u+Ml7j)%!T zR&3jT@~{!KCN=_ao?h%&K7bl7qc>IGnO4X7{kWe@s{(w0TOQTy5I-R9FE8wBynl6s z1&E0NXCl#ECZxbmgddZ<__6|{ow618803PqdvU)u>m7cVufn148*M#BsIm#>Qsg4t z+be1nRKyn=29an6PE?Z|4$B)&PQX!cOUxTxfmh45gNJDpx(*3bTm=X`!U=CVQlhl` z+IJ_*Q+tBf23B6t-@<3AYzRhN@|IyB_;=1Lnk{mf%N_uSNKK8@bMht|y74CARK3C` z;Z(N*kCaxoB9Ek1t)|n}R0fg+O2pjo|1s*TEb_gFMEmrM;rdS?^xx!^{4whLKY-AG z9{v3HOz=;flDM%?fEu@#qTzm|L_%zY}+hio1X_QNDs3uLYAPmRZNlJ)C z9(0tZehY`m*W9?`KtA{Z9tS-CwS=@-_IR7!Kvgh`a>i38bR0T^5;}Nhbg6ao4wUq$ z!0?4_YeuiFi>S@k`UECB(W1QC!Ljt1I*L=;dM>0e1A3P9O_O-;#?rM5o9eInt=`qu6N%wfl4OT3b_MjNWy}cB{Sgw@Nd?QCKXqrcE;)vi6r7YUmzEcx zBSTR)DxV595fiV!4VCRB{krnd@qhnFq5}rgOeq(P{pCx%`5h;}IZ5Hld#**Z=&6l` ze{Skh<0k5ZYmq_4`ycwjicXquyq~c0AF9uP%@_VU$J7760W1H%pXR@a1o^K z*jEnaZiqkLCdNm{XU^ZA7A|~%I`I~1x=K+#&EgVPCj{wvnv^xITcKaFvx14QbWc0< z6&m)t?lefys^fU>U()fO>0UJ*Ep$qMNM(exC69C#Ys}MH4rhj^u;I+u_03=F-E9;@ zh&Fn5inLPYW;P5(Ej5FtePzUu!6+&EL94%H=|qAUuoxhsMg)RrqENcNZ?2Wh8|%iX zZKoA%FFgVyxsV$vW@)nGIVVo!M2KSlonU)z3gJSIOq ziiRn{#Mu^E=pA6m4J(rw%6LMR9%TA4H1uYl3)#=KUyDa=;%)#@0buy$395;H@(ryf zEuNf4LBDZ~6e6gj zgN7$a&#d;9L7N9oEG>0`qBNj8r+9o5)s1oIR+hQ9jQ;fEJsmqjy>BF!yJvEoStxN6 zR)pi=m>6OHMYcLtsV#w7Dq=_^65R8cawL9b^KM0J(b$>?a6@Hu;b(0Tp4KaVw zI4Jy>!St&z_pTf9JK=TKx>0>^V0XZ$$x96ZD3xGNFbW9}PNffdeJE|*UY1b*4a#bN;v z4=3pU!(lq4=@zbUUn5i@loUo`wltuc6I3OlHqg;-eVbuAUw~-nT*WGKg0nA zcrt+{pTYpnKMf}T$}^Pudx_)UIY|HH8~qoBFiu8p<&)61AtQ(q>310m6m*SDNcvSz z;SNGjut+%;BoRi?Zk4mNDi&4DlA_aRyBnMo0o~MFxvz|gm`(UBJIUGE#5r?;JJ;*^ z?Gm;VgB>pK>T8e)C=;!DZP{2j`{!OvC4iy$`C!AX3-)&3G?kFSMmcQoRf$zZu1zWV zEOh19gw(R%>@Kp+aa;)T&>w>Ca2utq+G-VLnmUa$_KCK4?HasP^mH~W-8V)uT+g&fCmyzCyI=C7VPdH8CmJI5LJXRfCTlC+G*n-Y%lc}97 z(I=lZF2+fy570b(O7{8W%MZ_gsOqAZ3J>1AgW%z|Xd6d>7K>HiC-1Z05y-&x=q-BU zEp&_x3PYTb7t{~s=ouh@2itxa@57}YQu-HuYoiEfMWrPXsTB7Ssylqv!y=l<$vCol z!aq$)$C9r3lpaSY)a*+E_cP-E!j=xaOh%GTCO~cxdL{3kc(^i`HlW@tguDu)?6@V$ z5~1IHDB>z`{F&9!GpPwGY8OLc#fCK0h89e`oR)o$b>;}V7pKq+GGq-G^MW?Wbga$- zJMl*qVGfGq+5CCcwEssr$={q{{+qYr|7c0_mAd|5rg_DavrEWmDpCevh-ZI`3$OT< zPAM1;A|6Xj4SeinSUId(Y`r8)`OynZUpy<+ml`cNx~xh`B?t|;9(Q$KUrFUSx!{+b z0OAqN1;J^gZu-H^ZqaX(vRCoLgPk3E-tp{Y7hJz$eUSof#jg-5Li?%I3i_<#wvBQ!GZa!EOE?UR4_&C759a7Mb<}schws-Cb>lv5 zU#R)bA;q$#xoldc0G#qentKqj3kVROVXjDUBP-Ida)=~3+yur%lC(L)qBfoJBWLtpHwB0~@=a%Iil9=r%?W$r~?S>ySR5>1eu3l`W; zNHbPsGxjo&L%z_yuZ$|~CeMLQ`0{ooEhhb>_*Hp|#yC-$2w~f~H8+G}hYf2r!sDM0 zyNL{wMbUZE;aB0N8)PGAi=M$)xorwg_T$N|g)cEO_&VWzYL*D|K)KD>2l4}jFog3mwbNB1{nmjRquSV>|_~sfHxtlt{B;Kcz-Lcj1OG zNp<7W$-atRqYo{R9!Su~cnV$94T;1_k#59#$~mO&!VDpj^2ceBHH%&=fq6%Deh0rE zph0k2Q8o;T)JDp<)YWL{JRoM5>ZsJqaWK>l#kY3V~Ns+c>g zI{_SVjyQk+T7h|?gMHC3n%QK7MQ*4%JPgp$ZDrQ7WP~4(p-3O6Uz7S$1}9{%m}#>F zBRv;x`Ea=A&Xc=hef2zxKXZBcMtruVsz2blV5&6f--x;*UCErmZhu;KM#U%-D6{{p zl3E^R$)4J_Xgfp_ELV48liSQ;xf~qUQ)DJ*O zD`>g4BH~P9;#7Lsyq3eX!al<;aUB9#uKyTgjcpW;PN@F;2qpn0*Q1IaAp#MHu?d8f zH6=s#VUo7DDu2o@L)yfnsYb|;QYD@CH+rbvR}LK5z1rBjGU?WN1J!IQfO++4-AsIMVw48$l+71B6OEc*+;4m*)<1zxb2ZAy(}wio z3c^Z}Y8NrIO7MLaHe0l=n`Q93)@DuRC7}9+SYm&yDv0=dOB`d(2(={`jbpDHN`cER zMLu>a5Aq1LV;gdgPrinBuSl?hQ%D$-G+569S0B8qD$eE$}iqDEJ=VbqWG+oQuMR3-&Po?)dq_`Ff`6CEH zBM=_%D+ZT?z)h6a{MHzjVYXxfe3rCz-Ro;h6L#MOT^4vIl|MqWc(AN`uZMj2o@hz6 z+3r)W_TC635_*z=R?tDVuAebUu-h(&pB9HQ0JNh>9)Uxph)`XsCTf{lqC_0UPAce5 zxrAuxTMe?e3K29YwN-%yo&@izsy>Ybs04`w>JWQ)H8_OIB6vq}70!84OpfBuyhNQk zr8JRz1Zv|VqaJN^trF%E6A5?m=OSx@RV96XIBNO3kB$gelgIBWdd;d@FRqT^CqJk0 z7j6h3x^$6U%g3fgpBTqycQ^7AqhkSh?}`%3%I3bgAOPUd? zKvcI`!dJXi^fGrkfCq5`ncg0i1=pLsC*}ku_PQ8%q|SR51qM$JL^Y7UnDev(F+7u$ z`!UD*0QGC{yha4QJGe@mP8zhAZb1Wk6xCix^x_|#A8Qr!%= z`lL?klHJH{zF7vngDFS6QD^xG9_ljS_z?5ILu7Y|?)&&Z*rGgh48DT5cIX^#P_BP~ zGKNibC>+Xlk1R@UW{tjRg1yUlXKCzOCG9B;9#l(ViDiuP2R&S1JfG-CEb=El;0S)G zruuxjutj~wF?uIn-ypi>7=E2`>ma%17Uz!P32g08@KB1n!CeISkIj%*@9Nk9Nz`Q{(!V8nDBQb z>u+$LbDnK_ak~rwC-zLh)iC|8Jtne?g#U?u8{c>$`3qchOJoxbik4vvZ9I8P=zzA! zDjW1T>?f9BAK|w8z4uPaZVk9XEPTdwRi<|>Zqpr9E6eFT+-=pm7hclN7R<2`v6As> zIO(#fCA5X2s}0=trRiSAB-`hj!glok)L|R^ zy+Zl_n<@KQ4gIUdZcBc%oe{+v=tw5FM{N}t=^vpCNQ$bL=|Y3S$!o1MhZXR9i-9pW zD|NDux(zoJYlz1%kAD<3x3F`uNI|9G$i9 z1;iK>Vt&ZTswF`ZT+I5%cH~0Fa?u49M#cp-bGL3oAR!0Q<>}Abl7sy{kSNn}*ni7RV0qiVO#|f|g+ZN_ z1z;y_!@E_X{4iy-sv8@qPH)$8%2i|KdZ#gF@0H7B&6)>baV=#MrI>M$t?z%EvMw8E zj$AZ2iwH!ad|t(DMz>KD7I1GT%wml}#N^QD5)WF&ddK6|i*KAw#A7JChTx!eH+ogj zKrfI(xYLY93OG$AgTr)fZjEQ`DXr{U%Ewz;7rCJdP=!}xmOfjOU;YP^w%QR(l)78D zYEINPBGnFO8V(G5{{g?$vySAry$()J6VT7lmF=4m?OC!o$XsGT~=R2<#7Z{K?j zJ?;LqU1f|FIZf3gTS}CI|K^^B!Xv~AH{W&Fdg5Td0eR?bZ4?3csnA1`qdhZeJx+;3 z4P)LiX~#jA%ef96tKdQZ%h|HiRB=lIAc5LGbLCm8sjPL<9u71CfXGrAB}+x;!nQiY z6yb&k3z)UXc=!%iY66Do6sfNz1`+=SpYip3%0A<(7v*D)E<@03_8EbidqNKuAHLI_ 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/k+ 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 w+jTz#EWX5_5YyoKR`w$kwP`E(nSTNLWi8KN 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%0AEkcx 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 b-;+{*nGO`iNluswDR-BKTh&qeu1; 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 HrBwYtY{WkL diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java index 0327a9a060..b9b5cd24fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java @@ -20,7 +20,7 @@ public final class RealmUtils { */ public static List toXVals(RealmResults result, String xValuesField) { - List xVals = new ArrayList<>(); + List xVals = new ArrayList(); for (RealmObject object : result) { From aa6bb7418d20db0c1fbab617559bb2f58b19572c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Apr 2016 13:01:52 +0200 Subject: [PATCH 0836/1390] Fix #1637 --- .../src/com/github/mikephil/charting/components/Legend.java | 2 +- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 3a64b3a622..0d1cd4d23d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -108,7 +108,7 @@ public Legend() { mTextSize = Utils.convertDpToPixel(10f); mStackSpace = Utils.convertDpToPixel(3f); this.mXOffset = Utils.convertDpToPixel(5f); - this.mYOffset = Utils.convertDpToPixel(4f); // 2 + this.mYOffset = Utils.convertDpToPixel(3f); // 2 } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 45ae8b1939..b6b3a3f3ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -243,7 +243,7 @@ public void renderLegend(Canvas c) { if (legendPosition == Legend.LegendPosition.ABOVE_CHART_LEFT || legendPosition == Legend.LegendPosition.ABOVE_CHART_RIGHT || legendPosition == Legend.LegendPosition.ABOVE_CHART_CENTER) { - posY = 0.f; + posY = yoffset; } else { posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight; } From 56e59d87768dd2cfe5baf8fa95eefd9f562f2750 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 Apr 2016 16:57:16 +0300 Subject: [PATCH 0837/1390] Support for lines drawn to pie values --- MPChartExample/AndroidManifest.xml | 1 + .../PiePolylineChartActivity.java | 285 ++++++++++++++++++ .../notimportant/MainActivity.java | 48 +-- .../mikephil/charting/data/PieDataSet.java | 108 +++++++ .../realm/implementation/RealmPieDataSet.java | 103 +++++++ .../interfaces/datasets/IPieDataSet.java | 35 +++ .../charting/renderer/PieChartRenderer.java | 170 +++++++++-- 7 files changed, 697 insertions(+), 53 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 250757b885..9efb9639b9 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -29,6 +29,7 @@ + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java new file mode 100644 index 0000000000..ce1e0ed060 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -0,0 +1,285 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.formatter.PercentFormatter; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + private PieChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + private Typeface tf; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_piechart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + + mSeekBarY.setProgress(10); + + mSeekBarX.setOnSeekBarChangeListener(this); + mSeekBarY.setOnSeekBarChangeListener(this); + + mChart = (PieChart) findViewById(R.id.chart1); + mChart.setUsePercentValues(true); + mChart.setDescription(""); + mChart.setExtraOffsets(5, 10, 5, 5); + + mChart.setDragDecelerationFrictionCoef(0.95f); + + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); + mChart.setCenterText(generateCenterSpannableText()); + + mChart.setExtraOffsets(0.f, 50.f, 0.f, 50.f); + + mChart.setDrawHoleEnabled(true); + mChart.setHoleColor(Color.WHITE); + + mChart.setTransparentCircleColor(Color.WHITE); + mChart.setTransparentCircleAlpha(110); + + mChart.setHoleRadius(58f); + mChart.setTransparentCircleRadius(61f); + + mChart.setDrawCenterText(true); + + mChart.setRotationAngle(0); + // enable rotation of the chart by touch + mChart.setRotationEnabled(true); + mChart.setHighlightPerTapEnabled(true); + + // mChart.setUnit(" €"); + // mChart.setDrawUnitsInChart(true); + + // add a selection listener + mChart.setOnChartValueSelectedListener(this); + + setData(3, 100); + + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); + // mChart.spin(2000, 0, 360); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setEnabled(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.pie, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHole: { + if (mChart.isDrawHoleEnabled()) + mChart.setDrawHoleEnabled(false); + else + mChart.setDrawHoleEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionDrawCenter: { + if (mChart.isDrawCenterTextEnabled()) + mChart.setDrawCenterText(false); + else + mChart.setDrawCenterText(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleXVals: { + + mChart.setDrawSliceText(!mChart.isDrawSliceTextEnabled()); + mChart.invalidate(); + break; + } + case R.id.actionSave: { + // mChart.saveToGallery("title"+System.currentTimeMillis()); + mChart.saveToPath("title" + System.currentTimeMillis(), ""); + break; + } + case R.id.actionTogglePercent: + mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); + mChart.invalidate(); + break; + case R.id.animateX: { + mChart.animateX(1400); + break; + } + case R.id.animateY: { + mChart.animateY(1400); + break; + } + case R.id.animateXY: { + mChart.animateXY(1400, 1400); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); + } + + private void setData(int count, float range) { + + float mult = range; + + ArrayList yVals1 = new ArrayList(); + + // IMPORTANT: In a PieChart, no values (Entry) should have the same + // xIndex (even if from different DataSets), since no values can be + // drawn above each other. + for (int i = 0; i < count + 1; i++) { + yVals1.add(new Entry((float) (Math.random() * mult) + mult / 5, i)); + } + + ArrayList xVals = new ArrayList(); + + for (int i = 0; i < count + 1; i++) + xVals.add(mParties[i % mParties.length]); + + PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); + dataSet.setSliceSpace(3f); + dataSet.setSelectionShift(5f); + + // add a lot of colors + + ArrayList colors = new ArrayList(); + + for (int c : ColorTemplate.VORDIPLOM_COLORS) + colors.add(c); + + for (int c : ColorTemplate.JOYFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.COLORFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.LIBERTY_COLORS) + colors.add(c); + + for (int c : ColorTemplate.PASTEL_COLORS) + colors.add(c); + + colors.add(ColorTemplate.getHoloBlue()); + + dataSet.setColors(colors); + //dataSet.setSelectionShift(0f); + + + dataSet.setValueLinePart1OffsetPercentage(80.f); + dataSet.setValueLinePart1Length(0.4f); + dataSet.setValueLinePart2Length(0.5f); + // dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); + dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); + + PieData data = new PieData(xVals, dataSet); + data.setValueFormatter(new PercentFormatter()); + data.setValueTextSize(11f); + data.setValueTextColor(Color.BLACK); + data.setValueTypeface(tf); + mChart.setData(data); + + // undo all highlights + mChart.highlightValues(null); + + mChart.invalidate(); + } + + private SpannableString generateCenterSpannableText() { + + SpannableString s = new SpannableString("MPAndroidChart\ndeveloped by Philipp Jahoda"); + s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); + s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); + s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); + s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); + s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0); + return s; + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + + if (e == null) + return; + Log.i("VAL SELECTED", + "Value: " + e.getVal() + ", xIndex: " + e.getXIndex() + + ", DataSet index: " + dataSetIndex); + } + + @Override + public void onNothingSelected() { + Log.i("PieChart", "nothing selected"); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index bd6139c63a..a3569dcaaf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -34,6 +34,7 @@ import com.xxmassdeveloper.mpchartexample.MultiLineChartActivity; import com.xxmassdeveloper.mpchartexample.PerformanceLineChart; import com.xxmassdeveloper.mpchartexample.PieChartActivity; +import com.xxmassdeveloper.mpchartexample.PiePolylineChartActivity; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; @@ -73,6 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Combined Chart", "Demonstrates how to create a combined chart (bar and line in this case).")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); + objects.add(new ContentItem("Pie Chart with value lines", "A simple demonstration of the pie chart with polyline notes.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); objects.add(new ContentItem("Stacked Bar Chart", @@ -173,90 +175,94 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 6: - i = new Intent(this, ScatterChartActivity.class); + i = new Intent(this, PiePolylineChartActivity.class); startActivity(i); break; case 7: - i = new Intent(this, BubbleChartActivity.class); + i = new Intent(this, ScatterChartActivity.class); startActivity(i); break; case 8: - i = new Intent(this, StackedBarActivity.class); + i = new Intent(this, BubbleChartActivity.class); startActivity(i); break; case 9: - i = new Intent(this, StackedBarActivityNegative.class); + i = new Intent(this, StackedBarActivity.class); startActivity(i); break; case 10: - i = new Intent(this, AnotherBarActivity.class); + i = new Intent(this, StackedBarActivityNegative.class); startActivity(i); break; case 11: - i = new Intent(this, MultiLineChartActivity.class); + i = new Intent(this, AnotherBarActivity.class); startActivity(i); break; case 12: - i = new Intent(this, BarChartActivityMultiDataset.class); + i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; case 13: - i = new Intent(this, SimpleChartDemo.class); + i = new Intent(this, BarChartActivityMultiDataset.class); startActivity(i); break; case 14: - i = new Intent(this, ListViewBarChartActivity.class); + i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; case 15: - i = new Intent(this, ListViewMultiChartActivity.class); + i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; case 16: - i = new Intent(this, InvertedLineChartActivity.class); + i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; case 17: - i = new Intent(this, CandleStickChartActivity.class); + i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; case 18: - i = new Intent(this, CubicLineChartActivity.class); + i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; case 19: - i = new Intent(this, RadarChartActivitry.class); + i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; case 20: - i = new Intent(this, LineChartActivityColored.class); + i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; case 21: - i = new Intent(this, RealtimeLineChartActivity.class); + i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; case 22: - i = new Intent(this, DynamicalAddingActivity.class); + i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; case 23: - i = new Intent(this, PerformanceLineChart.class); + i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; case 24: - i = new Intent(this, BarChartActivitySinus.class); + i = new Intent(this, PerformanceLineChart.class); startActivity(i); break; case 25: - i = new Intent(this, ScrollViewActivity.class); + i = new Intent(this, BarChartActivitySinus.class); startActivity(i); break; case 26: - i = new Intent(this, BarChartPositiveNegative.class); + i = new Intent(this, ScrollViewActivity.class); startActivity(i); break; case 27: + i = new Intent(this, BarChartPositiveNegative.class); + startActivity(i); + break; + case 28: i = new Intent(this, RealmMainActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index 3f4b555da4..d5c311b6af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -15,6 +15,15 @@ public class PieDataSet extends DataSet implements IPieDataSet { /** indicates the selection distance of a pie slice */ private float mShift = 18f; + private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; + private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; + private int mValueLineColor = 0xff000000; + private float mValueLineWidth = 1.0f; + private float mValueLinePart1OffsetPercentage = 50.f; + private float mValueLinePart1Length = 0.1f; + private float mValueLinePart2Length = 0.2f; + private boolean mValueLineVariableLength = true; + public PieDataSet(List yVals, String label) { super(yVals, label); // mShift = Utils.convertDpToPixel(12f); @@ -71,4 +80,103 @@ public void setSelectionShift(float shift) { public float getSelectionShift() { return mShift; } + + @Override + public ValuePosition getXValuePosition() + { + return mXValuePosition; + } + + public void setXValuePosition(ValuePosition xValuePosition) + { + this.mXValuePosition = xValuePosition; + } + + @Override + public ValuePosition getYValuePosition() + { + return mYValuePosition; + } + + public void setYValuePosition(ValuePosition yValuePosition) + { + this.mYValuePosition = yValuePosition; + } + + /** When valuePosition is OutsideSlice, indicates line color */ + @Override + public int getValueLineColor() + { + return mValueLineColor; + } + + public void setValueLineColor(int valueLineColor) + { + this.mValueLineColor = valueLineColor; + } + + /** When valuePosition is OutsideSlice, indicates line width */ + @Override + public float getValueLineWidth() + { + return mValueLineWidth; + } + + public void setValueLineWidth(float valueLineWidth) + { + this.mValueLineWidth = valueLineWidth; + } + + /** When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size */ + @Override + public float getValueLinePart1OffsetPercentage() + { + return mValueLinePart1OffsetPercentage; + } + + public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) + { + this.mValueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage; + } + + /** When valuePosition is OutsideSlice, indicates length of first half of the line */ + @Override + public float getValueLinePart1Length() + { + return mValueLinePart1Length; + } + + public void setValueLinePart1Length(float valueLinePart1Length) + { + this.mValueLinePart1Length = valueLinePart1Length; + } + + /** When valuePosition is OutsideSlice, indicates length of second half of the line */ + @Override + public float getValueLinePart2Length() + { + return mValueLinePart2Length; + } + + public void setValueLinePart2Length(float valueLinePart2Length) + { + this.mValueLinePart2Length = valueLinePart2Length; + } + + /** When valuePosition is OutsideSlice, this allows variable line length */ + @Override + public boolean isValueLineVariableLength() + { + return mValueLineVariableLength; + } + + public void setValueLineVariableLength(boolean valueLineVariableLength) + { + this.mValueLineVariableLength = valueLineVariableLength; + } + + public enum ValuePosition { + INSIDE_SLICE, + OUTSIDE_SLICE + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index c11518bc54..a80d50d2ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.realm.base.RealmBaseDataSet; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; @@ -24,6 +25,14 @@ public class RealmPieDataSet extends RealmBaseDataSet { * @return */ float getSelectionShift(); + + PieDataSet.ValuePosition getXValuePosition(); + PieDataSet.ValuePosition getYValuePosition(); + + /** + * When valuePosition is OutsideSlice, indicates line color + * */ + int getValueLineColor(); + + /** + * When valuePosition is OutsideSlice, indicates line width + * */ + float getValueLineWidth(); + + /** + * When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size + * */ + float getValueLinePart1OffsetPercentage(); + + /** + * When valuePosition is OutsideSlice, indicates length of first half of the line + * */ + float getValueLinePart1Length(); + + /** + * When valuePosition is OutsideSlice, indicates length of second half of the line + * */ + float getValueLinePart2Length(); + + /** + * When valuePosition is OutsideSlice, this allows variable line length + * */ + boolean isValueLineVariableLength(); + } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 227337e517..269b767c87 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -20,9 +20,11 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -39,6 +41,7 @@ public class PieChartRenderer extends DataRenderer { */ protected Paint mHolePaint; protected Paint mTransparentCirclePaint; + protected Paint mValueLinePaint; /** * paint object for the text that can be displayed in the center of the @@ -79,6 +82,9 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); mValuePaint.setColor(Color.WHITE); mValuePaint.setTextAlign(Align.CENTER); + + mValueLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mValueLinePaint.setStyle(Style.STROKE); } public Paint getPaintHole() { @@ -351,7 +357,7 @@ public void drawValues(Canvas c) { PointF center = mChart.getCenterCircleBox(); // get whole the radius - float r = mChart.getRadius(); + float radius = mChart.getRadius(); float rotationAngle = mChart.getRotationAngle(); float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); @@ -359,13 +365,14 @@ public void drawValues(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - float off = r / 10f * 3.6f; + final float holeRadiusPercent = mChart.getHoleRadius() / 100.f; + float labelRadiusOffset = radius / 10f * 3.6f; if (mChart.isDrawHoleEnabled()) { - off = (r - (r / 100f * mChart.getHoleRadius())) / 2f; + labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f; } - r -= off; // offset to keep things inside the chart + final float labelRadius = radius - labelRadiusOffset; PieData data = mChart.getData(); List dataSets = data.getDataSets(); @@ -377,23 +384,34 @@ public void drawValues(Canvas c) { float angle; int xIndex = 0; + c.save(); + for (int i = 0; i < dataSets.size(); i++) { IPieDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() && !drawXVals) + final boolean drawYVals = dataSet.isDrawValuesEnabled(); + + if (!drawYVals && !drawXVals) continue; + final PieDataSet.ValuePosition xValuePosition = dataSet.getXValuePosition(); + final PieDataSet.ValuePosition yValuePosition = dataSet.getYValuePosition(); + // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); + ValueFormatter formatter = dataSet.getValueFormatter(); + int entryCount = dataSet.getEntryCount(); - for (int j = 0, maxEntry = Math.min( - (int) Math.ceil(entryCount * phaseX), entryCount); j < maxEntry; j++) { + mValueLinePaint.setColor(dataSet.getValueLineColor()); + mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); + + for (int j = 0; j < entryCount; j++) { Entry entry = dataSet.getEntryForIndex(j); @@ -404,51 +422,139 @@ public void drawValues(Canvas c) { final float sliceAngle = drawAngles[xIndex]; final float sliceSpace = dataSet.getSliceSpace(); - final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * r); + final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius); // offset needed to center the drawn text in the slice - final float offset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f; + final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle / 2.f) / 2.f; - angle = angle + offset; + angle = angle + angleOffset; - // calculate the text position - float x = (float) (r - * Math.cos(Math.toRadians(rotationAngle + angle)) - + center.x); - float y = (float) (r - * Math.sin(Math.toRadians(rotationAngle + angle)) - + center.y); + final float transformedAngle = rotationAngle + angle * phaseY; float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() / yValueSum * 100f : entry.getVal(); - ValueFormatter formatter = dataSet.getValueFormatter(); + final float sliceXBase = (float)Math.cos(transformedAngle * Utils.FDEG2RAD); + final float sliceYBase = (float)Math.sin(transformedAngle * Utils.FDEG2RAD); + + final boolean drawXOutside = drawXVals && + xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE; + final boolean drawYOutside = drawYVals && + yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE; + final boolean drawXInside = drawXVals && + xValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE; + final boolean drawYInside = drawYVals && + yValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE; + + if (drawXOutside || drawYOutside) { + + final float valueLineLength1 = dataSet.getValueLinePart1Length(); + final float valueLineLength2 = dataSet.getValueLinePart2Length(); + final float valueLinePart1OffsetPercentage = dataSet.getValueLinePart1OffsetPercentage() / 100.f; + + float pt2x, pt2y; + float labelPtx, labelPty; + + float line1Radius; + + if (mChart.isDrawHoleEnabled()) + line1Radius = (radius - (radius * holeRadiusPercent)) + * valueLinePart1OffsetPercentage + + (radius * holeRadiusPercent); + else + line1Radius = radius * valueLinePart1OffsetPercentage; + + final float polyline2Width = dataSet.isValueLineVariableLength() + ? labelRadius * valueLineLength2 * (float)Math.abs(Math.sin( + transformedAngle * Utils.FDEG2RAD)) + : labelRadius * valueLineLength2; + + final float pt0x = line1Radius * sliceXBase + center.x; + final float pt0y = line1Radius * sliceYBase + center.y; + + final float pt1x = labelRadius * (1 + valueLineLength1) * sliceXBase + center.x; + final float pt1y = labelRadius * (1 + valueLineLength1) * sliceYBase + center.y; + + if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) { + pt2x = pt1x - polyline2Width; + pt2y = pt1y; + mValuePaint.setTextAlign(Align.RIGHT); + labelPtx = pt2x - Utils.convertDpToPixel(5.f); + labelPty = pt2y; + } else { + pt2x = pt1x + polyline2Width; + pt2y = pt1y; + mValuePaint.setTextAlign(Align.LEFT); + labelPtx = pt2x + Utils.convertDpToPixel(5.f); + labelPty = pt2y; + } - boolean drawYVals = dataSet.isDrawValuesEnabled(); + if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint); + c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint); + } - // draw everything, depending on settings - if (drawXVals && drawYVals) { + // draw everything, depending on settings + if (drawXOutside && drawYOutside) { + + drawValue(c, + formatter, + value, + entry, + 0, + labelPtx, + labelPty, + dataSet.getValueTextColor(j)); + + if (j < data.getXValCount()) { + c.drawText(data.getXVals().get(j), labelPtx, labelPty + lineHeight, + mValuePaint); + } - drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); + } else if (drawXOutside) { + if (j < data.getXValCount()) { + mValuePaint.setColor(dataSet.getValueTextColor(j)); + c.drawText(data.getXVals().get(j), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); + } + } else if (drawYOutside) { - if (j < data.getXValCount()) { - c.drawText(data.getXVals().get(j), x, y + lineHeight, - mValuePaint); + drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet.getValueTextColor(j)); } + } - } else if (drawXVals) { - if (j < data.getXValCount()) { - mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); - } - } else if (drawYVals) { + if (drawXInside || drawYInside) { + // calculate the text position + float x = labelRadius * sliceXBase + center.x; + float y = labelRadius * sliceYBase + center.y; + + mValuePaint.setTextAlign(Align.CENTER); + + // draw everything, depending on settings + if (drawXInside && drawYInside) { + + drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); - drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); + if (j < data.getXValCount()) { + c.drawText(data.getXVals().get(j), x, y + lineHeight, + mValuePaint); + } + + } else if (drawXInside) { + if (j < data.getXValCount()) { + mValuePaint.setColor(dataSet.getValueTextColor(j)); + c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); + } + } else if (drawYInside) { + + drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); + } } xIndex++; } } + + c.restore(); } @Override From 122ba413ef646055aaf70a627f736d409ffa1d7e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 1 Apr 2016 16:57:39 +0300 Subject: [PATCH 0838/1390] Take into account extra offsets for pie/radar charts --- .../github/mikephil/charting/charts/PieRadarChartBase.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index a5c3bf130a..a7cb8f73ef 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -400,6 +400,10 @@ public void setMinOffset(float minOffset) { */ public float getDiameter() { RectF content = mViewPortHandler.getContentRect(); + content.left += getExtraLeftOffset(); + content.top += getExtraTopOffset(); + content.right -= getExtraRightOffset(); + content.bottom -= getExtraBottomOffset(); return Math.min(content.width(), content.height()); } From ae7df476372044e20211712b2f228a50da22227b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Apr 2016 16:28:18 +0200 Subject: [PATCH 0839/1390] Modify gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 70e3dabbf8..31581642ab 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,9 @@ # generated files bin/ gen/ -generatedJar/ +generated/ docs/ +finalOutput/ build.xml From d976b79ed0df0a3c6e2e286331a6e8f6b6d8406f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Apr 2016 18:11:37 +0200 Subject: [PATCH 0840/1390] Change pie value line default values --- .../mpchartexample/PiePolylineChartActivity.java | 4 ++-- .../src/com/github/mikephil/charting/data/PieDataSet.java | 6 +++--- .../charting/data/realm/implementation/RealmPieDataSet.java | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index ce1e0ed060..b475cd4abb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -226,8 +226,8 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); - dataSet.setValueLinePart1Length(0.4f); - dataSet.setValueLinePart2Length(0.5f); + dataSet.setValueLinePart1Length(0.3f); + dataSet.setValueLinePart2Length(0.4f); // dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index d5c311b6af..3c2b9ba589 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -19,9 +19,9 @@ public class PieDataSet extends DataSet implements IPieDataSet { private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; private int mValueLineColor = 0xff000000; private float mValueLineWidth = 1.0f; - private float mValueLinePart1OffsetPercentage = 50.f; - private float mValueLinePart1Length = 0.1f; - private float mValueLinePart2Length = 0.2f; + private float mValueLinePart1OffsetPercentage = 75.f; + private float mValueLinePart1Length = 0.3f; + private float mValueLinePart2Length = 0.4f; private boolean mValueLineVariableLength = true; public PieDataSet(List yVals, String label) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index a80d50d2ca..7be50e7c64 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -29,9 +29,9 @@ public class RealmPieDataSet extends RealmBaseDataSet Date: Sun, 3 Apr 2016 17:51:21 +0200 Subject: [PATCH 0841/1390] Brush up example --- .../mpchartexample/LineChartActivityColored.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 5d1e212d78..b4d5a5ce81 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -35,12 +35,14 @@ protected void onCreate(Bundle savedInstanceState) { mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); - LineData data = getData(36, 100); - data.setValueTypeface(mTf); + for (int i = 0; i < mCharts.length; i++) { + + LineData data = getData(36, 100); + data.setValueTypeface(mTf); - for (int i = 0; i < mCharts.length; i++) // add some transparency to the color with "& 0x90FFFFFF" setupChart(mCharts[i], data, mColors[i % mColors.length]); + } } private int[] mColors = new int[] { @@ -52,6 +54,8 @@ protected void onCreate(Bundle savedInstanceState) { private void setupChart(LineChart chart, LineData data, int color) { + ((LineDataSet) data.getDataSetByIndex(0)).setCircleColor(color); + // no description text chart.setDescription(""); chart.setNoDataTextDescription("You need to provide data for the chart."); @@ -85,6 +89,8 @@ private void setupChart(LineChart chart, LineData data, int color) { l.setEnabled(false); chart.getAxisLeft().setEnabled(false); + chart.getAxisLeft().setSpaceTop(40); + chart.getAxisLeft().setSpaceBottom(40); chart.getAxisRight().setEnabled(false); chart.getXAxis().setEnabled(false); @@ -113,9 +119,9 @@ private LineData getData(int count, float range) { // set1.setFillColor(Color.RED); set1.setLineWidth(1.75f); - set1.setCircleRadius(3f); + set1.setCircleRadius(5f); set1.setColor(Color.WHITE); - set1.setCircleColor(Color.WHITE); + set1.setCircleColorHole(Color.WHITE); set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); From 727b860f11cce4c2fc7ef4ae6b836041db640a6e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Apr 2016 18:42:44 +0200 Subject: [PATCH 0842/1390] Add auto calculation of granularity --- .../charting/charts/BarLineChartBase.java | 6 +- .../mikephil/charting/charts/RadarChart.java | 3 +- .../mikephil/charting/components/YAxis.java | 89 ++++++++++++++----- .../mikephil/charting/data/BubbleDataSet.java | 2 +- .../mikephil/charting/data/CandleDataSet.java | 2 +- .../github/mikephil/charting/utils/Utils.java | 82 ++++++++++++----- 6 files changed, 131 insertions(+), 53 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 3313bd10bf..1f66c92e5f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -15,7 +15,6 @@ import android.view.MotionEvent; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; @@ -351,8 +350,9 @@ protected void calcMinMax() { mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); // calculate axis range (min / max) according to provided data - mAxisLeft.calcMinMax(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); - mAxisRight.calcMinMax(mData.getYMin(AxisDependency.RIGHT), mData.getYMax(AxisDependency.RIGHT)); + mAxisLeft.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); + mAxisRight.calculate(mData.getYMin(AxisDependency.RIGHT), mData.getYMax(AxisDependency + .RIGHT)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 8f6c1cb982..f188a4c10a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -8,7 +8,6 @@ import android.graphics.RectF; import android.util.AttributeSet; -import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.Entry; @@ -105,7 +104,7 @@ protected void calcMinMax() { mXAxis.mAxisMaximum = mData.getXVals().size() - 1; mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - mYAxis.calcMinMax(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); + mYAxis.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 6e8c0486f4..bbbedda8c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -9,9 +9,12 @@ import com.github.mikephil.charting.utils.Utils; /** - * Class representing the y-axis labels settings and its entries. Only use the setter methods to modify it. Do not - * access public variables directly. Be aware that not all features the YLabels class provides are suitable for the - * RadarChart. Customizations that affect the value range of the axis need to be applied before setting data for the + * Class representing the y-axis labels settings and its entries. Only use the setter methods to + * modify it. Do not + * access public variables directly. Be aware that not all features the YLabels class provides + * are suitable for the + * RadarChart. Customizations that affect the value range of the axis need to be applied before + * setting data for the * chart. * * @author Philipp Jahoda @@ -107,7 +110,7 @@ public enum YAxisLabelPosition { /** * the minimum width that the axis should take (in dp). - * + *

    * default: 0.0 */ protected float mMinWidth = 0.f; @@ -132,6 +135,11 @@ public enum YAxisLabelPosition { */ protected float mGranularity = 1.0f; + /** + * flag indicating if a custom-granularity was set - if false, granularity is auto calculated + */ + protected boolean mCustomGranularity = false; + /** * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. * @@ -166,6 +174,7 @@ public float getMinWidth() { /** * Sets the minimum width that the axis should take (in dp). + * * @param minWidth */ public void setMinWidth(float minWidth) { @@ -181,6 +190,7 @@ public float getMaxWidth() { /** * Sets the maximum width that the axis can take (in dp). + * * @param maxWidth */ public void setMaxWidth(float maxWidth) { @@ -195,7 +205,10 @@ public boolean isGranularityEnabled() { } /** - * Enabled/disable granularity control on axis value intervals + * Enabled/disable granularity control on axis value intervals. If enabled, the axis + * interval is not allowed to go below a certain granularity (which is either + * auto-calculated, or custom set) + * * @param enabled */ public void setGranularityEnabled(boolean enabled) { @@ -210,11 +223,24 @@ public float getGranularity() { } /** - * Set the minimum interval between axis values. This can be used to avoid label duplicating when zooming in. + * Set a custom minimum interval between axis values (instead of auto-calculation). The axis + * interval can then not go below + * the specified limit. Use resetGranularity() to re-enable auto calculation. + * This can be used to avoid label duplicating when zooming in. + * * @param granularity */ public void setGranularity(float granularity) { mGranularity = granularity; + mCustomGranularity = true; + } + + /** + * Reset the custom-set granularity. If this method is called, granularity + * is again auto calculated. + */ + public void resetGranularity() { + mCustomGranularity = false; } /** @@ -243,7 +269,8 @@ public boolean isDrawTopYLabelEntryEnabled() { } /** - * set this to true to enable drawing the top y-label entry. Disabling this can be helpful when the top y-label and + * set this to true to enable drawing the top y-label entry. Disabling this can be helpful + * when the top y-label and * left x-label interfere with each other. default: true * * @param enabled @@ -253,12 +280,15 @@ public void setDrawTopYLabelEntry(boolean enabled) { } /** - * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware that this number is not + * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware + * that this number is not * fixed (if force == false) and can only be approximated. * * @param count the number of y-axis labels that sould be displayed - * @param force if enabled, the set label count will be forced, meaning that the exact specified count of labels will - * be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values + * @param force if enabled, the set label count will be forced, meaning that the exact + * specified count of labels will + * be drawn and evenly distributed alongside the axis - this might cause labels + * to have uneven values */ public void setLabelCount(int count, boolean force) { @@ -290,7 +320,8 @@ public boolean isForceLabelsEnabled() { } /** - * If enabled, the YLabels will only show the minimum and maximum value of the chart. This will ignore/override the + * If enabled, the YLabels will only show the minimum and maximum value of the chart. This + * will ignore/override the * set label count. * * @param enabled @@ -309,7 +340,8 @@ public boolean isShowOnlyMinMaxEnabled() { } /** - * If this is set to true, the y-axis is inverted which means that low values are on top of the chart, high values + * If this is set to true, the y-axis is inverted which means that low values are on top of + * the chart, high values * on bottom. * * @param enabled @@ -440,7 +472,7 @@ public float getRequiredWidthSpace(Paint p) { maxWidth = Utils.convertDpToPixel(maxWidth); width = Math.max(minWidth, Math.min(width, maxWidth > 0.0 ? maxWidth : width)); - + return width; } @@ -474,7 +506,8 @@ public String getLongestLabel() { } /** - * Returns the formatted y-label at the specified index. This will either use the auto-formatter or the custom + * Returns the formatted y-label at the specified index. This will either use the + * auto-formatter or the custom * formatter (if one is set). * * @param index @@ -489,8 +522,10 @@ public String getFormattedLabel(int index) { } /** - * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the chart will - * automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside + * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the + * chart will + * automatically determine a reasonable formatting (concerning decimals) for all the values + * that are drawn inside * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. * * @param f @@ -517,7 +552,8 @@ public YAxisValueFormatter getValueFormatter() { } /** - * If this component has no YAxisValueFormatter or is only equipped with the default one (no custom set), return true. + * If this component has no YAxisValueFormatter or is only equipped with the default one (no + * custom set), return true. * * @return */ @@ -536,19 +572,21 @@ public boolean needsDefaultFormatter() { * @return */ public boolean needsOffset() { - if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition.OUTSIDE_CHART) + if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition + .OUTSIDE_CHART) return true; else return false; } /** - * Calculates the minimum, maximum and range values of the YAxis with the given + * Calculates the minimum, maximum, granularity and range values of the YAxis with the given * minimum and maximum values from the chart data. + * * @param dataMin the y-min value according to chart data * @param dataMax the y-max value according to chart data */ - public void calcMinMax(float dataMin, float dataMax) { + public void calculate(float dataMin, float dataMax) { // if custom, use value as is, else use data value float min = mCustomAxisMin ? mAxisMinimum : dataMin; @@ -564,14 +602,14 @@ public void calcMinMax(float dataMin, float dataMax) { } // bottom-space only effects non-custom min - if(!mCustomAxisMin) { + if (!mCustomAxisMin) { float bottomSpace = range / 100f * getSpaceBottom(); this.mAxisMinimum = (min - bottomSpace); } // top-space only effects non-custom max - if(!mCustomAxisMax) { + if (!mCustomAxisMax) { float topSpace = range / 100f * getSpaceTop(); this.mAxisMaximum = (max + topSpace); @@ -579,5 +617,12 @@ public void calcMinMax(float dataMin, float dataMax) { // calc actual range this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); + + // in case granularity is not customized, auto-calculate it + if (!mCustomGranularity && mGranularityEnabled) { + + double granularity = Utils.granularity(mAxisRange, mLabelCount); + this.mGranularity = (float) granularity; + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 96396d3241..5672ecb0bb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -11,7 +11,7 @@ public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet implements IBubbleDataSet { - // NOTE: Do not initialize these, as the calcMinMax is called by the super, + // NOTE: Do not initialize these, as the calculate is called by the super, // and the initializers are called after that and can reset the values protected float mXMax; protected float mXMin; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index c63ccee1df..939014105c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -101,7 +101,7 @@ public DataSet copy() { @Override public void calcMinMax(int start, int end) { - // super.calcMinMax(); + // super.calculate(); if (mYVals == null) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index ca19784347..012477c704 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -39,7 +39,7 @@ public abstract class Utils { private static int mMinimumFlingVelocity = 50; private static int mMaximumFlingVelocity = 8000; public final static double DEG2RAD = (Math.PI / 180.0); - public final static float FDEG2RAD = ((float)Math.PI / 180.f); + public final static float FDEG2RAD = ((float) Math.PI / 180.f); /** * initialize method, called inside the Chart.init() method. @@ -99,10 +99,13 @@ public static float convertDpToPixel(float dp) { if (mMetrics == null) { Log.e("MPChartLib-Utils", - "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before calling Utils.convertDpToPixel(...). Otherwise conversion does not take place."); + "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before" + + " calling Utils.convertDpToPixel(...). Otherwise conversion does not " + + "take place."); return dp; // throw new IllegalStateException( - // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before calling Utils.convertDpToPixel(...)."); + // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before + // calling Utils.convertDpToPixel(...)."); } DisplayMetrics metrics = mMetrics; @@ -122,10 +125,13 @@ public static float convertPixelsToDp(float px) { if (mMetrics == null) { Log.e("MPChartLib-Utils", - "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before calling Utils.convertPixelsToDp(...). Otherwise conversion does not take place."); + "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before" + + " calling Utils.convertPixelsToDp(...). Otherwise conversion does not" + + " take place."); return px; // throw new IllegalStateException( - // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before calling Utils.convertPixelsToDp(...)."); + // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before + // calling Utils.convertPixelsToDp(...)."); } DisplayMetrics metrics = mMetrics; @@ -195,7 +201,8 @@ public static FSize calcTextSize(Paint paint, String demoText) { /** * Formats the given number to the given number of decimals, and returns the - * number as a string, maximum 35 characters. If thousands are separated, the separating character is a dot ("."). + * number as a string, maximum 35 characters. If thousands are separated, the separating + * character is a dot ("."). * * @param number * @param digitCount @@ -216,7 +223,8 @@ public static String formatNumber(float number, int digitCount, boolean separate * @param separateChar a caracter to be paced between the "thousands" * @return */ - public static String formatNumber(float number, int digitCount, boolean separateThousands, char separateChar) { + public static String formatNumber(float number, int digitCount, boolean separateThousands, + char separateChar) { char[] out = new char[35]; @@ -536,7 +544,7 @@ public static void drawText(Canvas c, String text, float x, float y, final float lineHeight = mDrawTextRectBuffer.height(); - // Android sometimes has pre-padding + // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; // Android does not snap the bounds to line boundaries, @@ -575,8 +583,7 @@ public static void drawText(Canvas c, String text, float x, float y, c.drawText(text, drawOffsetX, drawOffsetY, paint); c.restore(); - } - else { + } else { if (anchor.x != 0.f || anchor.y != 0.f) { drawOffsetX -= mDrawTextRectBuffer.width() * anchor.x; @@ -647,8 +654,7 @@ public static void drawMultilineText(Canvas c, StaticLayout textLayout, textLayout.draw(c); c.restore(); - } - else { + } else { if (anchor.x != 0.f || anchor.y != 0.f) { drawOffsetX -= drawWidth * anchor.x; @@ -685,32 +691,60 @@ public static void drawMultilineText(Canvas c, String text, drawMultilineText(c, textLayout, x, y, paint, anchor, angleDegrees); } - public static FSize getSizeOfRotatedRectangleByDegrees(FSize rectangleSize, float degrees) - { + public static FSize getSizeOfRotatedRectangleByDegrees(FSize rectangleSize, float degrees) { final float radians = degrees * FDEG2RAD; - return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); + return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, + radians); } - public static FSize getSizeOfRotatedRectangleByRadians(FSize rectangleSize, float radians) - { - return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); + public static FSize getSizeOfRotatedRectangleByRadians(FSize rectangleSize, float radians) { + return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, + radians); } - public static FSize getSizeOfRotatedRectangleByDegrees(float rectangleWidth, float rectangleHeight, float degrees) - { + public static FSize getSizeOfRotatedRectangleByDegrees(float rectangleWidth, float + rectangleHeight, float degrees) { final float radians = degrees * FDEG2RAD; return getSizeOfRotatedRectangleByRadians(rectangleWidth, rectangleHeight, radians); } - public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, float rectangleHeight, float radians) - { + public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, float + rectangleHeight, float radians) { return new FSize( - Math.abs(rectangleWidth * (float)Math.cos(radians)) + Math.abs(rectangleHeight * (float)Math.sin(radians)), - Math.abs(rectangleWidth * (float)Math.sin(radians)) + Math.abs(rectangleHeight * (float)Math.cos(radians)) + Math.abs(rectangleWidth * (float) Math.cos(radians)) + Math.abs(rectangleHeight * + (float) Math.sin(radians)), + Math.abs(rectangleWidth * (float) Math.sin(radians)) + Math.abs(rectangleHeight * + (float) Math.cos(radians)) ); } public static int getSDKInt() { return android.os.Build.VERSION.SDK_INT; } + + /** + * Calculates the granularity (minimum axis interval) based on axis range and labelcount. + * Default granularity is 1/10th of interval. + * + * @param range + * @param labelCount + * @return + */ + public static double granularity(float range, int labelCount) { + + // Find out how much spacing (in y value space) between axis values + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + + // Normalize interval + double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10 + (interval))); + int intervalSigDigit = (int) (interval / intervalMagnitude); + + if (intervalSigDigit > 5) { + interval = Math.floor(10 * intervalMagnitude); + } + + return interval * 0.1; // granularity is 1/10th of interval + } } From 937ea040625f0d00fb34aacfca33785982084116 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Apr 2016 18:50:31 +0200 Subject: [PATCH 0843/1390] Disable granularity calculation per default --- .../github/mikephil/charting/components/YAxis.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index bbbedda8c4..bbb38516f2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -128,7 +128,7 @@ public enum YAxisLabelPosition { * This could happen if two adjacent axis values are rounded to same value. * If using granularity this could be avoided by having fewer axis values visible. */ - protected boolean mGranularityEnabled = true; + protected boolean mGranularityEnabled = false; /** * the minimum interval between axis values @@ -207,7 +207,7 @@ public boolean isGranularityEnabled() { /** * Enabled/disable granularity control on axis value intervals. If enabled, the axis * interval is not allowed to go below a certain granularity (which is either - * auto-calculated, or custom set) + * auto-calculated, or custom set). Default: false * * @param enabled */ @@ -224,20 +224,21 @@ public float getGranularity() { /** * Set a custom minimum interval between axis values (instead of auto-calculation). The axis - * interval can then not go below - * the specified limit. Use resetGranularity() to re-enable auto calculation. + * interval can then not go below the specified limit. Use resetGranularity() to re-enable + * auto calculation. This will automatically enable granularity. * This can be used to avoid label duplicating when zooming in. * * @param granularity */ public void setGranularity(float granularity) { mGranularity = granularity; + mGranularityEnabled = true; mCustomGranularity = true; } /** * Reset the custom-set granularity. If this method is called, granularity - * is again auto calculated. + * is again auto calculated (if enabled). */ public void resetGranularity() { mCustomGranularity = false; From 995538cf0b58af99c28d5878e0583d7c44e67069 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Apr 2016 22:36:23 +0200 Subject: [PATCH 0844/1390] Remove granularity auto-calc feature --- .../mikephil/charting/components/YAxis.java | 38 ++++++------------- 1 file changed, 12 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index bbb38516f2..0846a670a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -135,11 +135,6 @@ public enum YAxisLabelPosition { */ protected float mGranularity = 1.0f; - /** - * flag indicating if a custom-granularity was set - if false, granularity is auto calculated - */ - protected boolean mCustomGranularity = false; - /** * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. * @@ -151,6 +146,8 @@ public enum AxisDependency { public YAxis() { super(); + + // default left this.mAxisDependency = AxisDependency.LEFT; this.mYOffset = 0f; } @@ -206,8 +203,7 @@ public boolean isGranularityEnabled() { /** * Enabled/disable granularity control on axis value intervals. If enabled, the axis - * interval is not allowed to go below a certain granularity (which is either - * auto-calculated, or custom set). Default: false + * interval is not allowed to go below a certain granularity. Default: false * * @param enabled */ @@ -223,25 +219,15 @@ public float getGranularity() { } /** - * Set a custom minimum interval between axis values (instead of auto-calculation). The axis - * interval can then not go below the specified limit. Use resetGranularity() to re-enable - * auto calculation. This will automatically enable granularity. - * This can be used to avoid label duplicating when zooming in. + * Set a minimum interval for the axis when zooming in. The axis is not allowed to go below + * that limit. This can be used to avoid label duplicating when zooming in. * * @param granularity */ public void setGranularity(float granularity) { mGranularity = granularity; + // set this to true if it was disabled, as it makes no sense to call this method with granularity disabled mGranularityEnabled = true; - mCustomGranularity = true; - } - - /** - * Reset the custom-set granularity. If this method is called, granularity - * is again auto calculated (if enabled). - */ - public void resetGranularity() { - mCustomGranularity = false; } /** @@ -619,11 +605,11 @@ public void calculate(float dataMin, float dataMax) { // calc actual range this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); - // in case granularity is not customized, auto-calculate it - if (!mCustomGranularity && mGranularityEnabled) { - - double granularity = Utils.granularity(mAxisRange, mLabelCount); - this.mGranularity = (float) granularity; - } +// // in case granularity is not customized, auto-calculate it +// if (!mCustomGranularity && mGranularityEnabled) { +// +// double granularity = Utils.granularity(mAxisRange, mLabelCount); +// this.mGranularity = (float) granularity; +// } } } From 00f3e422789006bcd457b1ed30c5927c85eef4cd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Apr 2016 22:50:33 +0200 Subject: [PATCH 0845/1390] Create XAxisValue class --- .../mikephil/charting/data/XAxisValue.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java b/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java new file mode 100644 index 0000000000..a14f7ab41f --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java @@ -0,0 +1,57 @@ +package com.github.mikephil.charting.data; + +/** + * Created by Philipp Jahoda on 03/04/16. + */ +public class XAxisValue { + + /** + * the label that describes this value + */ + private String mLabel = ""; + + /** + * the position of this value on the x-axis + */ + private double mPosition; + + /** + * Constructor. + * + * @param xPosition the position of this value on the x-axis + * @param label the x-axis label of this value + */ + public XAxisValue(double xPosition, String label) { + this.mLabel = label; + this.mPosition = xPosition; + } + + /** + * Sets both x-position and label. + * + * @param xPosition + * @param label + */ + public void set(double xPosition, String label) { + this.mLabel = label; + this.mPosition = xPosition; + } + + /** + * Returns the position (x) of the value on the x-axis. + * + * @return + */ + public double getPosition() { + return mPosition; + } + + /** + * Returns the x-axis label of this value. + * + * @return + */ + public String getLabel() { + return mLabel; + } +} From 31f15a941dafef1dae9c132081a36faed606f671 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 4 Apr 2016 14:52:43 +0300 Subject: [PATCH 0846/1390] Turn on granularity for this example For the value to take effect --- .../xxmassdeveloper/mpchartexample/BarChartActivitySinus.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 6ed4009640..e200f2e9b1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -89,6 +89,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setLabelCount(6, false); leftAxis.setAxisMinValue(-2.5f); leftAxis.setAxisMaxValue(2.5f); + leftAxis.setGranularityEnabled(true); leftAxis.setGranularity(0.1f); YAxis rightAxis = mChart.getAxisRight(); From 4c5a2b94a4de3064afe1b692461d43c984ab489e Mon Sep 17 00:00:00 2001 From: = Date: Mon, 4 Apr 2016 21:46:53 +0200 Subject: [PATCH 0847/1390] Introduce XAxisValue to ChartData object --- .../mikephil/charting/charts/Chart.java | 3 ++- .../mikephil/charting/components/XAxis.java | 9 +++---- .../mikephil/charting/data/BarData.java | 12 +++++----- .../data/BarLineScatterCandleBubbleData.java | 8 +++---- .../mikephil/charting/data/BubbleData.java | 12 +++++----- .../mikephil/charting/data/CandleData.java | 12 +++++----- .../mikephil/charting/data/ChartData.java | 24 +++++++++---------- .../mikephil/charting/data/CombinedData.java | 4 ++-- .../mikephil/charting/data/LineData.java | 12 +++++----- .../mikephil/charting/data/PieData.java | 8 +++---- .../mikephil/charting/data/RadarData.java | 12 +++++----- .../mikephil/charting/data/ScatterData.java | 12 +++++----- .../charting/data/realm/base/RealmUtils.java | 13 ++++++---- .../realm/implementation/RealmBarData.java | 4 ++-- .../realm/implementation/RealmBubbleData.java | 4 ++-- .../realm/implementation/RealmCandleData.java | 4 ++-- .../realm/implementation/RealmLineData.java | 4 ++-- .../realm/implementation/RealmPieData.java | 4 ++-- .../realm/implementation/RealmRadarData.java | 4 ++-- .../implementation/RealmScatterData.java | 4 ++-- .../charting/renderer/LegendRenderer.java | 5 ++-- .../charting/renderer/PieChartRenderer.java | 8 +++---- .../charting/renderer/XAxisRenderer.java | 5 ++-- .../renderer/XAxisRendererBarChart.java | 2 +- .../XAxisRendererHorizontalBarChart.java | 5 ++-- .../renderer/XAxisRendererRadarChart.java | 2 +- 26 files changed, 103 insertions(+), 93 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 055bdf7312..096b67c121 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -33,6 +33,7 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; @@ -1375,7 +1376,7 @@ public void setDrawMarkerViews(boolean enabled) { * @param index * @return */ - public String getXValue(int index) { + public XAxisValue getXValue(int index) { if (mData == null || mData.getXValCount() <= index) return null; else diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 7343baaef8..18b6e55141 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.components; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; import com.github.mikephil.charting.formatter.XAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -18,7 +19,7 @@ public class XAxis extends AxisBase { /** the arraylist containing all the x-axis labels */ - protected List mValues = new ArrayList(); + protected List mValues = new ArrayList(); /** * width of the x-axis labels in pixels - this is automatically @@ -204,7 +205,7 @@ public boolean isAvoidFirstLastClippingEnabled() { * * @param values */ - public void setValues(List values) { + public void setValues(List values) { mValues = values; } @@ -213,7 +214,7 @@ public void setValues(List values) { * * @return */ - public List getValues() { + public List getValues() { return mValues; } @@ -246,7 +247,7 @@ public String getLongestLabel() { String longest = ""; for (int i = 0; i < mValues.size(); i++) { - String text = mValues.get(i); + String text = mValues.get(i).getLabel(); if (longest.length() < text.length()) longest = text; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 43b6e88e86..a0528153be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -25,27 +25,27 @@ public BarData() { super(); } - public BarData(List xVals) { + public BarData(List xVals) { super(xVals); } - public BarData(String[] xVals) { + public BarData(XAxisValue[] xVals) { super(xVals); } - public BarData(List xVals, List dataSets) { + public BarData(List xVals, List dataSets) { super(xVals, dataSets); } - public BarData(String[] xVals, List dataSets) { + public BarData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public BarData(List xVals, IBarDataSet dataSet) { + public BarData(List xVals, IBarDataSet dataSet) { super(xVals, toList(dataSet)); } - public BarData(String[] xVals, IBarDataSet dataSet) { + public BarData(XAxisValue[] xVals, IBarDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 84dc3df67e..801f2fc87d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -17,19 +17,19 @@ public BarLineScatterCandleBubbleData() { super(); } - public BarLineScatterCandleBubbleData(List xVals) { + public BarLineScatterCandleBubbleData(List xVals) { super(xVals); } - public BarLineScatterCandleBubbleData(String[] xVals) { + public BarLineScatterCandleBubbleData(XAxisValue[] xVals) { super(xVals); } - public BarLineScatterCandleBubbleData(List xVals, List sets) { + public BarLineScatterCandleBubbleData(List xVals, List sets) { super(xVals, sets); } - public BarLineScatterCandleBubbleData(String[] xVals, List sets) { + public BarLineScatterCandleBubbleData(XAxisValue[] xVals, List sets) { super(xVals, sets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index 53945ac0e5..28e317b306 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -12,27 +12,27 @@ public BubbleData() { super(); } - public BubbleData(List xVals) { + public BubbleData(List xVals) { super(xVals); } - public BubbleData(String[] xVals) { + public BubbleData(XAxisValue[] xVals) { super(xVals); } - public BubbleData(List xVals, List dataSets) { + public BubbleData(List xVals, List dataSets) { super(xVals, dataSets); } - public BubbleData(String[] xVals, List dataSets) { + public BubbleData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public BubbleData(List xVals, IBubbleDataSet dataSet) { + public BubbleData(List xVals, IBubbleDataSet dataSet) { super(xVals, toList(dataSet)); } - public BubbleData(String[] xVals, IBubbleDataSet dataSet) { + public BubbleData(XAxisValue[] xVals, IBubbleDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index a1c797b4fa..17e79c0748 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -11,27 +11,27 @@ public CandleData() { super(); } - public CandleData(List xVals) { + public CandleData(List xVals) { super(xVals); } - public CandleData(String[] xVals) { + public CandleData(XAxisValue[] xVals) { super(xVals); } - public CandleData(List xVals, List dataSets) { + public CandleData(List xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(String[] xVals, List dataSets) { + public CandleData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(List xVals, ICandleDataSet dataSet) { + public CandleData(List xVals, ICandleDataSet dataSet) { super(xVals, toList(dataSet)); } - public CandleData(String[] xVals, ICandleDataSet dataSet) { + public CandleData(XAxisValue[] xVals, ICandleDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 71663eb2cd..eb39dc794b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -53,7 +53,7 @@ public abstract class ChartData> { /** * holds all x-values the chart represents */ - protected List mXVals; + protected List mXVals; /** * array that holds all DataSets the ChartData object represents @@ -61,7 +61,7 @@ public abstract class ChartData> { protected List mDataSets; public ChartData() { - mXVals = new ArrayList(); + mXVals = new ArrayList(); mDataSets = new ArrayList(); } @@ -71,7 +71,7 @@ public ChartData() { * * @param xVals */ - public ChartData(List xVals) { + public ChartData(List xVals) { this.mXVals = xVals; this.mDataSets = new ArrayList(); init(); @@ -83,7 +83,7 @@ public ChartData(List xVals) { * * @param xVals */ - public ChartData(String[] xVals) { + public ChartData(XAxisValue[] xVals) { this.mXVals = arrayToList(xVals); this.mDataSets = new ArrayList(); init(); @@ -97,7 +97,7 @@ public ChartData(String[] xVals) { * DataSets. * @param sets the dataset array */ - public ChartData(List xVals, List sets) { + public ChartData(List xVals, List sets) { this.mXVals = xVals; this.mDataSets = sets; @@ -112,7 +112,7 @@ public ChartData(List xVals, List sets) { * DataSets. * @param sets the dataset array */ - public ChartData(String[] xVals, List sets) { + public ChartData(XAxisValue[] xVals, List sets) { this.mXVals = arrayToList(xVals); this.mDataSets = sets; @@ -125,7 +125,7 @@ public ChartData(String[] xVals, List sets) { * @param array * @return */ - private List arrayToList(String[] array) { + private List arrayToList(XAxisValue[] array) { return Arrays.asList(array); } @@ -156,7 +156,7 @@ private void calcXValMaximumLength() { for (int i = 0; i < mXVals.size(); i++) { - int length = mXVals.get(i).length(); + int length = mXVals.get(i).getLabel().length(); if (length > max) max = length; @@ -372,7 +372,7 @@ public int getYValCount() { * * @return */ - public List getXVals() { + public List getXVals() { return mXVals; } @@ -381,10 +381,10 @@ public List getXVals() { * * @param xVal */ - public void addXValue(String xVal) { + public void addXValue(XAxisValue xVal) { - if (xVal != null && xVal.length() > mXValMaximumLength) - mXValMaximumLength = xVal.length(); + if (xVal != null && xVal.getLabel().length() > mXValMaximumLength) + mXValMaximumLength = xVal.getLabel().length(); mXVals.add(xVal); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 2d7982265d..c03db11a60 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -24,11 +24,11 @@ public CombinedData() { super(); } - public CombinedData(List xVals) { + public CombinedData(List xVals) { super(xVals); } - public CombinedData(String[] xVals) { + public CombinedData(XAxisValue[] xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 9adb07b60d..53ba9a28d5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -17,27 +17,27 @@ public LineData() { super(); } - public LineData(List xVals) { + public LineData(List xVals) { super(xVals); } - public LineData(String[] xVals) { + public LineData(XAxisValue[] xVals) { super(xVals); } - public LineData(List xVals, List dataSets) { + public LineData(List xVals, List dataSets) { super(xVals, dataSets); } - public LineData(String[] xVals, List dataSets) { + public LineData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public LineData(List xVals, ILineDataSet dataSet) { + public LineData(List xVals, ILineDataSet dataSet) { super(xVals, toList(dataSet)); } - public LineData(String[] xVals, ILineDataSet dataSet) { + public LineData(XAxisValue[] xVals, ILineDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 9a3151e6c4..c2fb239b42 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -20,19 +20,19 @@ public PieData() { super(); } - public PieData(List xVals) { + public PieData(List xVals) { super(xVals); } - public PieData(String[] xVals) { + public PieData(XAxisValue[] xVals) { super(xVals); } - public PieData(List xVals, IPieDataSet dataSet) { + public PieData(List xVals, IPieDataSet dataSet) { super(xVals, toList(dataSet)); } - public PieData(String[] xVals, IPieDataSet dataSet) { + public PieData(XAxisValue[] xVals, IPieDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 48494d3d65..ff18c0d8e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -17,27 +17,27 @@ public RadarData() { super(); } - public RadarData(List xVals) { + public RadarData(List xVals) { super(xVals); } - public RadarData(String[] xVals) { + public RadarData(XAxisValue[] xVals) { super(xVals); } - public RadarData(List xVals, List dataSets) { + public RadarData(List xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(String[] xVals, List dataSets) { + public RadarData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(List xVals, IRadarDataSet dataSet) { + public RadarData(List xVals, IRadarDataSet dataSet) { super(xVals, toList(dataSet)); } - public RadarData(String[] xVals, IRadarDataSet dataSet) { + public RadarData(XAxisValue[] xVals, IRadarDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index 99422dd916..713fa7f2e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -12,27 +12,27 @@ public ScatterData() { super(); } - public ScatterData(List xVals) { + public ScatterData(List xVals) { super(xVals); } - public ScatterData(String[] xVals) { + public ScatterData(XAxisValue[] xVals) { super(xVals); } - public ScatterData(List xVals, List dataSets) { + public ScatterData(List xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(String[] xVals, List dataSets) { + public ScatterData(XAxisValue[] xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(List xVals, IScatterDataSet dataSet) { + public ScatterData(List xVals, IScatterDataSet dataSet) { super(xVals, toList(dataSet)); } - public ScatterData(String[] xVals, IScatterDataSet dataSet) { + public ScatterData(XAxisValue[] xVals, IScatterDataSet dataSet) { super(xVals, toList(dataSet)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java index b9b5cd24fd..8f9b8d5310 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.data.realm.base; +import com.github.mikephil.charting.data.XAxisValue; + import java.util.ArrayList; import java.util.List; @@ -15,17 +17,20 @@ public final class RealmUtils { * Transforms the given Realm-ResultSet into a String array by using the provided xValuesField. * * @param result - * @param xValuesField + * @param xPositionField + * @param xLabelField * @return */ - public static List toXVals(RealmResults result, String xValuesField) { + public static List toXVals(RealmResults result, String xPositionField, String xLabelField) { - List xVals = new ArrayList(); + List xVals = new ArrayList(); for (RealmObject object : result) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - xVals.add(dynamicObject.getString(xValuesField)); + + XAxisValue val = new XAxisValue(dynamicObject.getDouble(xPositionField), dynamicObject.getString(xLabelField)); + xVals.add(val); } return xVals; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java index ec124e6dee..8a46ff618a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java @@ -14,7 +14,7 @@ */ public class RealmBarData extends BarData { - public RealmBarData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmBarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java index 617f098dd2..e21017f6f9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java @@ -14,7 +14,7 @@ */ public class RealmBubbleData extends BubbleData { - public RealmBubbleData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmBubbleData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java index 769c1801c2..5cc2757498 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java @@ -14,7 +14,7 @@ */ public class RealmCandleData extends CandleData { - public RealmCandleData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmCandleData(RealmResults result,String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java index bcacb98952..97357e034d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java @@ -14,7 +14,7 @@ */ public class RealmLineData extends LineData { - public RealmLineData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmLineData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java index 665725118c..d407e67864 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java @@ -12,7 +12,7 @@ */ public class RealmPieData extends PieData { - public RealmPieData(RealmResults result, String xValuesField, IPieDataSet dataSet) { - super(RealmUtils.toXVals(result, xValuesField), dataSet); + public RealmPieData(RealmResults result,String xPositionField, String xLabelField, IPieDataSet dataSet) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSet); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java index a098a6d2a5..61dbf2b86d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java @@ -14,7 +14,7 @@ */ public class RealmRadarData extends RadarData{ - public RealmRadarData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmRadarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java index 2838a86f11..8ae94aaac3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java @@ -14,7 +14,7 @@ */ public class RealmScatterData extends ScatterData { - public RealmScatterData(RealmResults result, String xValuesField, List dataSets) { - super(RealmUtils.toXVals(result, xValuesField), dataSets); + public RealmScatterData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { + super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index b6b3a3f3ac..bf16d5b695 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -110,12 +111,12 @@ public void computeLegend(ChartData data) { } else if (dataSet instanceof IPieDataSet) { - List xVals = data.getXVals(); + List xVals = data.getXVals(); IPieDataSet pds = (IPieDataSet) dataSet; for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { - labels.add(xVals.get(j)); + labels.add(xVals.get(j).getLabel()); colors.add(clrs.get(j)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 269b767c87..fd7931f714 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -507,14 +507,14 @@ public void drawValues(Canvas c) { dataSet.getValueTextColor(j)); if (j < data.getXValCount()) { - c.drawText(data.getXVals().get(j), labelPtx, labelPty + lineHeight, + c.drawText(data.getXVals().get(j).getLabel(), labelPtx, labelPty + lineHeight, mValuePaint); } } else if (drawXOutside) { if (j < data.getXValCount()) { mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(data.getXVals().get(j), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); + c.drawText(data.getXVals().get(j).getLabel(), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); } } else if (drawYOutside) { @@ -535,14 +535,14 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); if (j < data.getXValCount()) { - c.drawText(data.getXVals().get(j), x, y + lineHeight, + c.drawText(data.getXVals().get(j).getLabel(), x, y + lineHeight, mValuePaint); } } else if (drawXInside) { if (j < data.getXValCount()) { mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); + c.drawText(data.getXVals().get(j).getLabel(), x, y + lineHeight / 2f, mValuePaint); } } else if (drawYInside) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index a0a2bff642..6de6112508 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -33,7 +34,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } - public void computeAxis(float xValMaximumLength, List xValues) { + public void computeAxis(float xValMaximumLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -162,7 +163,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { if (mViewPortHandler.isInBoundsX(position[0])) { - String label = mXAxis.getValues().get(i); + String label = mXAxis.getValues().get(i).getLabel(); if (mXAxis.isAvoidFirstLastClippingEnabled()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index c869bec352..d58c3842b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -55,7 +55,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 && i < mXAxis.getValues().size()) { - String label = mXAxis.getValues().get(i); + String label = mXAxis.getValues().get(i).getLabel(); if (mXAxis.isAvoidFirstLastClippingEnabled()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index e862263520..01b17f3904 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -27,7 +28,7 @@ public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xA } @Override - public void computeAxis(float xValAverageLength, List xValues) { + public void computeAxis(float xValAverageLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -124,7 +125,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { if (mViewPortHandler.isInBoundsY(position[1])) { - String label = mXAxis.getValues().get(i); + String label = mXAxis.getValues().get(i).getLabel(); drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 50a2fc7dd4..8d926ddfcb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -42,7 +42,7 @@ public void renderAxisLabels(Canvas c) { int mod = mXAxis.mAxisLabelModulus; for (int i = 0; i < mXAxis.getValues().size(); i += mod) { - String label = mXAxis.getValues().get(i); + String label = mXAxis.getValues().get(i).getLabel(); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; From d771bf4467761467b6113987d7bce2a5b19de89e Mon Sep 17 00:00:00 2001 From: = Date: Mon, 4 Apr 2016 21:51:06 +0200 Subject: [PATCH 0848/1390] Start fixing example --- .../mpchartexample/AnotherBarActivity.java | 7 +++++-- .../mpchartexample/BarChartActivitySinus.java | 9 ++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index cabd72e9dd..0990f4144d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -174,9 +175,11 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new BarEntry((int) val1, i)); } - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add((int) yVals1.get(i).getVal() + ""); + + XAxisValue xValue = new XAxisValue(i, (int) yVals1.get(i).getVal() + ""); + xVals.add(xValue); } BarDataSet set1 = new BarDataSet(yVals1, "Data Set"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index e200f2e9b1..08ce038e6e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -79,9 +80,6 @@ protected void onCreate(Bundle savedInstanceState) { mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xAxis = mChart.getXAxis(); - xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTf); - xAxis.setDrawGridLines(false); xAxis.setEnabled(false); YAxis leftAxis = mChart.getAxisLeft(); @@ -208,12 +206,9 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count) { - ArrayList xVals = new ArrayList(); - ArrayList entries = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add(i+""); entries.add(mSinusData.get(i)); } @@ -221,7 +216,7 @@ private void setData(int count) { set.setBarSpacePercent(40f); set.setColor(Color.rgb(240, 120, 124)); - BarData data = new BarData(xVals, set); + BarData data = new BarData(null, set); data.setValueTextSize(10f); data.setValueTypeface(mTf); data.setDrawValues(false); From a9bd0c619128eaa7bef61b12a9fb60ce9069f87d Mon Sep 17 00:00:00 2001 From: = Date: Mon, 4 Apr 2016 22:32:47 +0200 Subject: [PATCH 0849/1390] Adjust example according to XAxisValue --- .../mpchartexample/BarChartActivity.java | 10 ++-- .../BarChartActivityMultiDataset.java | 7 ++- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 5 +- .../mpchartexample/BubbleChartActivity.java | 6 +- .../CandleStickChartActivity.java | 8 +-- .../mpchartexample/CombinedChartActivity.java | 11 +++- .../CubicLineChartActivity.java | 8 +-- .../mpchartexample/DrawChartActivity.java | 9 +-- .../DynamicalAddingActivity.java | 5 +- .../HorizontalBarChartActivity.java | 5 +- .../InvertedLineChartActivity.java | 8 +-- .../mpchartexample/LineChartActivity1.java | 8 +-- .../mpchartexample/LineChartActivity2.java | 5 +- .../LineChartActivityColored.java | 10 +--- .../ListViewBarChartActivity.java | 20 +------ .../ListViewMultiChartActivity.java | 30 ---------- .../MultiLineChartActivity.java | 5 +- .../mpchartexample/PerformanceLineChart.java | 5 +- .../mpchartexample/PieChartActivity.java | 5 +- .../PiePolylineChartActivity.java | 5 +- .../mpchartexample/RadarChartActivitry.java | 5 +- .../RealtimeLineChartActivity.java | 5 +- .../mpchartexample/ScatterChartActivity.java | 5 +- .../mpchartexample/ScrollViewActivity.java | 5 +- .../mpchartexample/StackedBarActivity.java | 8 +-- .../StackedBarActivityNegative.java | 8 ++- .../mpchartexample/custom/RealmDemoData.java | 55 ++++++++++++------- .../fragments/SimpleFragment.java | 13 ++--- .../mpchartexample/notimportant/DemoBase.java | 50 +++++++++++++++++ .../realm/RealmBaseActivity.java | 8 +-- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityCandle.java | 2 +- .../RealmDatabaseActivityHorizontalBar.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../realm/RealmWikiExample.java | 4 +- .../mikephil/charting/data/BarData.java | 5 ++ .../data/BarLineScatterCandleBubbleData.java | 4 ++ .../mikephil/charting/data/ChartData.java | 11 +++- .../mikephil/charting/data/LineData.java | 4 ++ .../mikephil/charting/data/XAxisValue.java | 9 +++ 45 files changed, 221 insertions(+), 171 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 99d3d027fd..be76bebdf7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -28,6 +28,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.YAxisValueFormatter; @@ -225,17 +226,16 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add(mMonths[i % 12]); - } - + ArrayList xVals = new ArrayList(); ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); yVals1.add(new BarEntry(val, i)); + + XAxisValue value = new XAxisValue(i, mMonths[i % 12]); + xVals.add(value); } BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 4f869ecc3a..f00c4d3631 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -178,9 +179,11 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() * 3)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add((i+1990) + ""); + + XAxisValue value = new XAxisValue(i, (i+1990) + ""); + xVals.add(value); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 08ce038e6e..a82399de8b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -216,7 +216,7 @@ private void setData(int count) { set.setBarSpacePercent(40f); set.setColor(Color.rgb(240, 120, 124)); - BarData data = new BarData(null, set); + BarData data = new BarData(set); data.setValueTextSize(10f); data.setValueTypeface(mTf); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 26f8e6fceb..7e852c0b58 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -87,7 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { private void setData(List dataList) { ArrayList values = new ArrayList(); - String[] dates = new String[dataList.size()]; + XAxisValue[] dates = new XAxisValue[dataList.size()]; List colors = new ArrayList(); int green = Color.rgb(110, 190, 102); @@ -99,7 +100,7 @@ private void setData(List dataList) { BarEntry entry = new BarEntry(d.yValue, d.xIndex); values.add(entry); - dates[i] = dataList.get(i).xAxisValue; + dates[i] = new XAxisValue(i, dataList.get(i).xAxisValue); // specific colors if (d.yValue >= 0) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 03d97ed812..0002668c09 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; @@ -164,9 +165,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + count); tvY.setText("" + range); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add((i) + ""); + XAxisValue xVal = new XAxisValue(i,(i) + ""); + xVals.add(xVal); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 36211e175c..9cbcfd9247 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -166,6 +167,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.resetTracking(); + ArrayList xVals = new ArrayList(); ArrayList yVals1 = new ArrayList(); for (int i = 0; i < prog; i++) { @@ -182,11 +184,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new CandleEntry(i, val + high, val - low, even ? val + open : val - open, even ? val - close : val + close)); - } - ArrayList xVals = new ArrayList(); - for (int i = 0; i < prog; i++) { - xVals.add("" + (1990 + i)); + XAxisValue xVal = new XAxisValue(i,(i) + ""); + xVals.add(xVal); } CandleDataSet set1 = new CandleDataSet(yVals1, "Data Set"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 1cc5a5d9ab..67a4de9529 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -27,6 +27,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -52,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); // draw bars behind lines - mChart.setDrawOrder(new DrawOrder[] { + mChart.setDrawOrder(new DrawOrder[]{ DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); @@ -67,7 +68,13 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); - CombinedData data = new CombinedData(mMonths); + XAxisValue[] xVals = new XAxisValue[mMonths.length]; + + for(int i = 0; i < mMonths.length; i++) { + xVals[i] = new XAxisValue(i, mMonths[i]); + } + + CombinedData data = new CombinedData(xVals); data.setData(generateLineData()); data.setData(generateBarData()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 26220e5309..015055138c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.FillFormatter; @@ -241,11 +242,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add((1990 +i) + ""); - } - ArrayList vals1 = new ArrayList(); for (int i = 0; i < count; i++) { @@ -278,7 +274,7 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv }); // create a data object with the datasets - LineData data = new LineData(xVals, set1); + LineData data = new LineData(set1); data.setValueTypeface(tf); data.setValueTextSize(9f); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index d12b3ecbd7..2e944e13c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -74,10 +74,6 @@ protected void onCreate(Bundle savedInstanceState) { } private void initWithDummyData() { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < 24; i++) { - xVals.add((i) + ":00"); - } ArrayList yVals = new ArrayList(); @@ -86,11 +82,8 @@ private void initWithDummyData() { set1.setLineWidth(3f); set1.setCircleRadius(5f); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(set1); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 0c19b2032d..af3e744b91 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; @@ -62,7 +63,7 @@ private void addEntry() { } // add a new x-value first - data.addXValue(set.getEntryCount() + ""); + data.addXValue(new XAxisValue(set.getEntryCount(), set.getEntryCount() + "")); // choose a random dataSet int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); @@ -116,7 +117,7 @@ private void addDataSet() { if(data.getXValCount() == 0) { // add 10 x-entries for (int i = 0; i < 10; i++) { - data.addXValue("" + (i+1)); + data.addXValue(new XAxisValue(i, i + "")); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 3027188cf5..5e026ee07b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -25,6 +25,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -228,10 +229,10 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { ArrayList yVals1 = new ArrayList(); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add(mMonths[i % 12]); + xVals.add(new XAxisValue(i, mMonths[i % 12])); yVals1.add(new BarEntry((float) (Math.random() * range), i)); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 2f92912e60..ee4273b838 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; @@ -255,11 +256,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add((i % 30) + "/" + (i % 12) + "/14"); - } - + ArrayList xVals = new ArrayList(); ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -268,6 +265,7 @@ private void setData(int count, float range) { // ((mult * // 0.1) / 10); yVals.add(new Entry(val, i)); + xVals.add(new XAxisValue(i, (i % 30) + "/" + (i % 12) + "/14")); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 836afcd7f2..9c5d522f68 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -27,6 +27,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; @@ -325,11 +326,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add((i) + ""); - } - + ArrayList xVals = new ArrayList(); ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -339,6 +336,7 @@ private void setData(int count, float range) { // ((mult * // 0.1) / 10); yVals.add(new Entry(val, i)); + xVals.add(new XAxisValue(i, i + "")); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index d7df678923..cf01559137 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -273,9 +274,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add((i) + ""); + xVals.add(new XAxisValue(i, i + "")); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index b4d5a5ce81..77c25bec29 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -101,11 +101,6 @@ private void setupChart(LineChart chart, LineData data, int color) { private LineData getData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add(mMonths[i % 12]); - } - ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -125,11 +120,8 @@ private LineData getData(int count, float range) { set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(set1); return data; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index e1c69086bc..7ede89d56d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -147,23 +148,4 @@ private BarData generateData(int cnt) { BarData cd = new BarData(getMonths(), sets); return cd; } - - private ArrayList getMonths() { - - ArrayList m = new ArrayList(); - m.add("Jan"); - m.add("Feb"); - m.add("Mar"); - m.add("Apr"); - m.add("May"); - m.add("Jun"); - m.add("Jul"); - m.add("Aug"); - m.add("Sep"); - m.add("Okt"); - m.add("Nov"); - m.add("Dec"); - - return m; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index ad242e99ec..7c90a9142f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -173,34 +173,4 @@ private PieData generateDataPie(int cnt) { PieData cd = new PieData(getQuarters(), d); return cd; } - - private ArrayList getQuarters() { - - ArrayList q = new ArrayList(); - q.add("1st Quarter"); - q.add("2nd Quarter"); - q.add("3rd Quarter"); - q.add("4th Quarter"); - - return q; - } - - private ArrayList getMonths() { - - ArrayList m = new ArrayList(); - m.add("Jan"); - m.add("Feb"); - m.add("Mar"); - m.add("Apr"); - m.add("May"); - m.add("Jun"); - m.add("Jul"); - m.add("Aug"); - m.add("Sep"); - m.add("Okt"); - m.add("Nov"); - m.add("Dec"); - - return m; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 05e25fae64..cc385d6216 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; @@ -191,9 +192,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress())); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add((i) + ""); + xVals.add(new XAxisValue(i, i+"")); } ArrayList dataSets = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 9a195cb4b4..cec5d5669c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -92,9 +93,9 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add((i) + ""); + xVals.add(new XAxisValue(i, i + "")); } ArrayList yVals = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index bab7dcb525..5d3e306c4d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; @@ -191,10 +192,10 @@ private void setData(int count, float range) { yVals1.add(new Entry((float) (Math.random() * mult) + mult / 5, i)); } - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count + 1; i++) - xVals.add(mParties[i % mParties.length]); + xVals.add(new XAxisValue(mParties[i % mParties.length])); PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); dataSet.setSliceSpace(3f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index b475cd4abb..7ce05f371a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.PercentFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -191,10 +192,10 @@ private void setData(int count, float range) { yVals1.add(new Entry((float) (Math.random() * mult) + mult / 5, i)); } - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count + 1; i++) - xVals.add(mParties[i % mParties.length]); + xVals.add(new XAxisValue(mParties[i % mParties.length])); PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); dataSet.setSliceSpace(3f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index e637a37efe..6402e0e60d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -200,10 +201,10 @@ public void setData() { yVals2.add(new Entry((float) (Math.random() * mult) + mult / 2, i)); } - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < cnt; i++) - xVals.add(mParties[i % mParties.length]); + xVals.add(new XAxisValue(mParties[i % mParties.length])); RadarDataSet set1 = new RadarDataSet(yVals1, "Set 1"); set1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index a1f31d1043..6dda2d1d38 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; @@ -139,8 +140,8 @@ private void addEntry() { } // add a new x-value first - data.addXValue(mMonths[data.getXValCount() % 12] + " " - + (year + data.getXValCount() / 12)); + data.addXValue(new XAxisValue(data.getXValCount() ,mMonths[data.getXValCount() % 12] + " " + + (year + data.getXValCount() / 12))); data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index e716f7ff47..6e7d1c7443 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; @@ -165,9 +166,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add((i) + ""); + xVals.add(new XAxisValue(i, i + "")); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 61244bad2e..34f2140a04 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -51,12 +52,12 @@ protected void onCreate(Bundle savedInstanceState) { private void setData(int count) { ArrayList yVals = new ArrayList(); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * count) + 15; yVals.add(new BarEntry((int) val, i)); - xVals.add((int) val + ""); + xVals.add(new XAxisValue(i, (int) val + "")); } BarDataSet set = new BarDataSet(yVals, "Data Set"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 77c6d1f23f..8d672bf853 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; @@ -178,11 +179,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add(mMonths[i % mMonths.length]); - } - + ArrayList xVals = new ArrayList(); ArrayList yVals1 = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { @@ -192,6 +189,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float val3 = (float) (Math.random() * mult) + mult / 3; yVals1.add(new BarEntry(new float[] { val1, val2, val3 }, i)); + xVals.add(new XAxisValue(i, mMonths[i % mMonths.length])); } BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index d25ee39f2b..4f9c908754 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -103,7 +104,12 @@ protected void onCreate(Bundle savedInstanceState) { "Men", "Women" }); - String []xVals = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; + String []xLabels = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; + List xVals = new ArrayList(); + + for(int i = 0; i < xLabels.length; i++) { + xVals.add(new XAxisValue(i, xLabels[i])); + } BarData data = new BarData(xVals, set); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index 58767447fe..a84c65d003 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -20,7 +20,8 @@ public class RealmDemoData extends RealmObject { private int xIndex; - private String xValue; + private String xAxisLabel; + private double xAxisPosition; private String someStringField; @@ -30,10 +31,11 @@ public RealmDemoData() { } - public RealmDemoData(float value, int xIndex, String xValue) { + public RealmDemoData(float value, int xIndex, double xAxisPosition, String xAxisLabel) { this.value = value; this.xIndex = xIndex; - this.xValue = xValue; + this.xAxisPosition = xAxisPosition; + this.xAxisLabel = xAxisLabel; } /** @@ -41,11 +43,13 @@ public RealmDemoData(float value, int xIndex, String xValue) { * * @param stackValues * @param xIndex - * @param xValue + * @param xAxisPosition + * @param xAxisLabel */ - public RealmDemoData(float[] stackValues, int xIndex, String xValue) { + public RealmDemoData(float[] stackValues, int xIndex, double xAxisPosition, String xAxisLabel) { this.xIndex = xIndex; - this.xValue = xValue; + this.xAxisPosition = xAxisPosition; + this.xAxisLabel = xAxisLabel; this.stackValues = new RealmList(); for (float val : stackValues) { @@ -61,15 +65,18 @@ public RealmDemoData(float[] stackValues, int xIndex, String xValue) { * @param open * @param close * @param xIndex + * @param xAxisPosition + * @param xAxisLabel */ - public RealmDemoData(float high, float low, float open, float close, int xIndex, String xValue) { + public RealmDemoData(float high, float low, float open, float close, int xIndex, double xAxisPosition, String xAxisLabel) { this.value = (high + low) / 2f; this.high = high; this.low = low; this.open = open; this.close = close; this.xIndex = xIndex; - this.xValue = xValue; + this.xAxisPosition = xAxisPosition; + this.xAxisLabel = xAxisLabel; } /** @@ -78,13 +85,15 @@ public RealmDemoData(float high, float low, float open, float close, int xIndex, * @param value * @param xIndex * @param bubbleSize - * @param xValue + * @param xAxisPosition + * @param xAxisLabel */ - public RealmDemoData(float value, int xIndex, float bubbleSize, String xValue) { + public RealmDemoData(float value, int xIndex, float bubbleSize, double xAxisPosition, String xAxisLabel) { this.value = value; this.xIndex = xIndex; this.bubbleSize = bubbleSize; - this.xValue = xValue; + this.xAxisPosition = xAxisPosition; + this.xAxisLabel = xAxisLabel; } public float getValue() { @@ -111,14 +120,6 @@ public void setxIndex(int xIndex) { this.xIndex = xIndex; } - public String getxValue() { - return xValue; - } - - public void setxValue(String xValue) { - this.xValue = xValue; - } - public float getOpen() { return open; } @@ -166,4 +167,20 @@ public String getSomeStringField() { public void setSomeStringField(String someStringField) { this.someStringField = someStringField; } + + public double getxAxisPosition() { + return xAxisPosition; + } + + public void setxAxisPosition(double xAxisPosition) { + this.xAxisPosition = xAxisPosition; + } + + public String getxAxisLabel() { + return xAxisLabel; + } + + public void setxAxisLabel(String xAxisLabel) { + this.xAxisLabel = xAxisLabel; + } } \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 25d103e8ce..29bd091c6e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -103,16 +104,14 @@ protected PieData generatePieData() { int count = 4; ArrayList entries1 = new ArrayList(); - ArrayList xVals = new ArrayList(); + ArrayList xVals = new ArrayList(); - xVals.add("Quarter 1"); - xVals.add("Quarter 2"); - xVals.add("Quarter 3"); - xVals.add("Quarter 4"); + xVals.add(new XAxisValue("Quarter 1")); + xVals.add(new XAxisValue("Quarter 2")); + xVals.add(new XAxisValue("Quarter 3")); + xVals.add(new XAxisValue("Quarter 4")); for(int i = 0; i < count; i++) { - xVals.add("entry" + (i+1)); - entries1.add(new Entry((float) (Math.random() * 60) + 40, i)); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index 774aff1f75..25d9dd450f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -3,8 +3,12 @@ import android.support.v4.app.FragmentActivity; +import com.github.mikephil.charting.data.XAxisValue; import com.xxmassdeveloper.mpchartexample.R; +import java.util.ArrayList; +import java.util.List; + /** * Baseclass of all Activities of the Demo Application. * @@ -23,6 +27,52 @@ public abstract class DemoBase extends FragmentActivity { "Party Y", "Party Z" }; + + protected ArrayList getMonths() { + + ArrayList m = new ArrayList(); + m.add(new XAxisValue(0, "Jan")); + m.add(new XAxisValue(1, "Feb")); + m.add(new XAxisValue(2, "Mar")); + m.add(new XAxisValue(3, "Apr")); + m.add(new XAxisValue(4, "May")); + m.add(new XAxisValue(5, "Jun")); + m.add(new XAxisValue(6, "Jul")); + m.add(new XAxisValue(7, "Aug")); + m.add(new XAxisValue(8, "Sep")); + m.add(new XAxisValue(9, "Okt")); + m.add(new XAxisValue(10, "Nov")); + m.add(new XAxisValue(11, "Dec")); + + return m; + } + + + protected ArrayList getQuarters() { + + ArrayList q = new ArrayList(); + q.add(new XAxisValue(0, "Quarter 1")); + q.add(new XAxisValue(1, "Quarter 2")); + q.add(new XAxisValue(2, "Quarter 3")); + q.add(new XAxisValue(3, "Quarter 4")); + + return q; + } + + protected List getYears() { + ArrayList years = new ArrayList(); + + years.add(new XAxisValue(0, "2013")); + years.add(new XAxisValue(1, "2014")); + years.add(new XAxisValue(2, "2015")); + years.add(new XAxisValue(3, "2016")); + years.add(new XAxisValue(4, "2017")); + years.add(new XAxisValue(5, "2018")); + years.add(new XAxisValue(6, "2019")); + + return years; + } + @Override public void onBackPressed() { super.onBackPressed(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 09bcc59e1e..1f51281e35 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -113,7 +113,7 @@ protected void writeToDB(int objectCount) { float value = 40f + (float) (Math.random() * 60f); - RealmDemoData d = new RealmDemoData(value, i, "" + i); + RealmDemoData d = new RealmDemoData(value, i, i, "" + i); mRealm.copyToRealm(d); } @@ -132,7 +132,7 @@ protected void writeToDBStack(int objectCount) { float val2 = 34f + (float) (Math.random() * 12.0f); float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - RealmDemoData d = new RealmDemoData(stack, i, "" + i); + RealmDemoData d = new RealmDemoData(stack, i, i, "" + i); mRealm.copyToRealm(d); } @@ -159,7 +159,7 @@ protected void writeToDBCandle(int objectCount) { boolean even = i % 2 == 0; RealmDemoData d = new RealmDemoData(val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close, i, i + ""); + even ? val - close : val + close, i, i, i + ""); mRealm.copyToRealm(d); } @@ -201,7 +201,7 @@ protected void writeToDBPie() { String[] xValues = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], i, xValues[i]); + RealmDemoData d = new RealmDemoData(values[i], i, i, xValues[i]); mRealm.copyToRealm(d); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 4387035191..ecde642f4f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -58,7 +58,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBarData data = new RealmBarData(result, "xValue", dataSets); + RealmBarData data = new RealmBarData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index b98ca0b746..2f23561622 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -61,7 +61,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBubbleData data = new RealmBubbleData(result, "xValue", dataSets); + RealmBubbleData data = new RealmBubbleData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 70e324d4dd..97a0036567 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmCandleData data = new RealmCandleData(result, "xValue", dataSets); + RealmCandleData data = new RealmCandleData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 7a2ef39c18..40bbf10910 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -63,7 +63,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBarData data = new RealmBarData(result, "xValue", dataSets); + RealmBarData data = new RealmBarData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 057662d057..c2f8803b85 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmLineData data = new RealmLineData(result, "xValue", dataSets); + RealmLineData data = new RealmLineData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index de6767d145..489399bc9e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -60,7 +60,7 @@ private void setData() { set.setSliceSpace(2); // create a data object with the dataset list - RealmPieData data = new RealmPieData(result, "xValue", set); + RealmPieData data = new RealmPieData(result, "xAxisPosition", "xAxisLabel", set); styleData(data); data.setValueTextColor(Color.WHITE); data.setValueTextSize(12f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 7aae4ae377..3e1c688f6c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RadarData data = new RadarData(new String[] {"2013", "2014", "2015", "2016", "2017", "2018", "2019"}, dataSets); + RadarData data = new RadarData(getYears(), dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index b28bf137a8..135667a4bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -63,7 +63,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmScatterData data = new RealmScatterData(result, "xValue", dataSets); + RealmScatterData data = new RealmScatterData(result, "xAxisPosition", "xAxisLabel", dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 7066d8167b..2d5e3a90a5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -89,7 +89,7 @@ private void setData() { ArrayList dataSets = new ArrayList(); dataSets.add(lineDataSet); - RealmLineData lineData = new RealmLineData(results, "playerName", dataSets); + RealmLineData lineData = new RealmLineData(results, "scoreNr", "playerName", dataSets); styleData(lineData); // set data @@ -105,7 +105,7 @@ private void setData() { ArrayList barDataSets = new ArrayList(); barDataSets.add(barDataSet); - RealmBarData barData = new RealmBarData(results, "playerName", barDataSets); + RealmBarData barData = new RealmBarData(results, "scoreNr", "playerName", barDataSets); styleData(barData); barChart.setData(barData); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index a0528153be..bc87fcc24d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -25,6 +26,10 @@ public BarData() { super(); } + public BarData(IBarDataSet... dataSets) { + super(dataSets); + } + public BarData(List xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 801f2fc87d..c16c2c72a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -16,6 +16,10 @@ public abstract class BarLineScatterCandleBubbleData xVals) { super(xVals); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index eb39dc794b..d5ea74e835 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -65,6 +65,11 @@ public ChartData() { mDataSets = new ArrayList(); } + public ChartData(T... dataSets) { + mDataSets = Arrays.asList(dataSets); + init(); + } + /** * Constructor for only x-values. This constructor can be used for setting * up an empty chart without data. @@ -821,12 +826,12 @@ public T getFirstRight() { * * @return */ - public static List generateXVals(int from, int to) { + public static List generateXVals(int from, int to) { - List xvals = new ArrayList(); + List xvals = new ArrayList(); for (int i = from; i < to; i++) { - xvals.add("" + i); + xvals.add(new XAxisValue(i, i + "")); } return xvals; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 53ba9a28d5..b4ef3b1d53 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -17,6 +17,10 @@ public LineData() { super(); } + public LineData(ILineDataSet... dataSets) { + super(dataSets); + } + public LineData(List xVals) { super(xVals); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java b/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java index a14f7ab41f..eef5f638e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java @@ -15,6 +15,15 @@ public class XAxisValue { */ private double mPosition; + /** + * Constructor only with label. This is relevant for pie and radarchart. + * + * @param label the x-axis label of this value + */ + public XAxisValue(String label) { + this.mLabel = label; + } + /** * Constructor. * From a599fb79f965b8b3cf06467cc2d832126bcda76f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 Apr 2016 11:04:57 +0200 Subject: [PATCH 0850/1390] Implement min/max calculation for x values --- .../mikephil/charting/data/BarDataSet.java | 19 +++- .../mikephil/charting/data/BubbleDataSet.java | 34 ++---- .../mikephil/charting/data/CandleDataSet.java | 23 ++-- .../mikephil/charting/data/ChartData.java | 47 +++++++- .../mikephil/charting/data/DataSet.java | 107 +++++++++++------- .../mikephil/charting/data/LineDataSet.java | 5 +- .../mikephil/charting/data/PieDataSet.java | 4 +- .../mikephil/charting/data/RadarDataSet.java | 4 +- .../charting/data/ScatterDataSet.java | 4 +- .../data/realm/base/RealmBaseDataSet.java | 29 +++++ .../realm/implementation/RealmBarDataSet.java | 9 ++ .../implementation/RealmBubbleDataSet.java | 12 -- .../implementation/RealmCandleDataSet.java | 9 ++ .../interfaces/datasets/IBubbleDataSet.java | 4 - .../interfaces/datasets/IDataSet.java | 14 +++ 15 files changed, 220 insertions(+), 104 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index fb1dccccf8..d71cb7d8cd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -57,8 +57,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(((BarEntry) mYVals.get(i)).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(((BarEntry) mValues.get(i)).copy()); } BarDataSet copied = new BarDataSet(yVals, getLabel()); @@ -110,10 +110,10 @@ private void calcStackSize(List yVals) { @Override public void calcMinMax(int start, int end) { - if (mYVals == null) + if (mValues == null) return; - final int yValCount = mYVals.size(); + final int yValCount = mValues.size(); if (yValCount == 0) return; @@ -128,9 +128,12 @@ public void calcMinMax(int start, int end) { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { - BarEntry e = mYVals.get(i); + BarEntry e = mValues.get(i); if (e != null && !Float.isNaN(e.getVal())) { @@ -149,6 +152,12 @@ public void calcMinMax(int start, int end) { if (e.getPositiveSum() > mYMax) mYMax = e.getPositiveSum(); } + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 5672ecb0bb..5ed9b28810 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -1,8 +1,6 @@ package com.github.mikephil.charting.data; -import android.graphics.Color; - import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Utils; @@ -11,10 +9,6 @@ public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet implements IBubbleDataSet { - // NOTE: Do not initialize these, as the calculate is called by the super, - // and the initializers are called after that and can reset the values - protected float mXMax; - protected float mXMin; protected float mMaxSize; private float mHighlightCircleWidth = 2.5f; @@ -36,27 +30,27 @@ public float getHighlightCircleWidth() { @Override public void calcMinMax(int start, int end) { - if (mYVals == null) + if (mValues == null) return; - if (mYVals.size() == 0) + if (mValues.size() == 0) return; int endValue; - if (end == 0 || end >= mYVals.size()) - endValue = mYVals.size() - 1; + if (end == 0 || end >= mValues.size()) + endValue = mValues.size() - 1; else endValue = end; - mYMin = yMin(mYVals.get(start)); - mYMax = yMax(mYVals.get(start)); + mYMin = yMin(mValues.get(start)); + mYMax = yMax(mValues.get(start)); // need chart width to guess this properly for (int i = start; i <= endValue; i++) { - final BubbleEntry entry = mYVals.get(i); + final BubbleEntry entry = mValues.get(i); float ymin = yMin(entry); float ymax = yMax(entry); @@ -93,8 +87,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(mYVals.get(i).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(mValues.get(i).copy()); } BubbleDataSet copied = new BubbleDataSet(yVals, getLabel()); @@ -104,16 +98,6 @@ public DataSet copy() { return copied; } - @Override - public float getXMax() { - return mXMax; - } - - @Override - public float getXMin() { - return mXMin; - } - @Override public float getMaxSize() { return mMaxSize; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 939014105c..b434d76fa2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -82,8 +82,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(((CandleEntry) mYVals.get(i)).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(((CandleEntry) mValues.get(i)).copy()); } CandleDataSet copied = new CandleDataSet(yVals, getLabel()); @@ -103,31 +103,40 @@ public DataSet copy() { public void calcMinMax(int start, int end) { // super.calculate(); - if (mYVals == null) + if (mValues == null) return; - if (mYVals.size() == 0) + if (mValues.size() == 0) return; int endValue; - if (end == 0 || end >= mYVals.size()) - endValue = mYVals.size() - 1; + if (end == 0 || end >= mValues.size()) + endValue = mValues.size() - 1; else endValue = end; mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { - CandleEntry e = mYVals.get(i); + CandleEntry e = mValues.get(i); if (e.getLow() < mYMin) mYMin = e.getLow(); if (e.getHigh() > mYMax) mYMax = e.getHigh(); + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index d5ea74e835..232ac837c1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -22,15 +22,25 @@ public abstract class ChartData> { /** - * maximum y-value in the y-value array across all axes + * maximum y-value in the value array across all axes */ protected float mYMax = 0.0f; /** - * the minimum y-value in the y-value array across all axes + * the minimum y-value in the value array across all axes */ protected float mYMin = 0.0f; + /** + * maximum x-value in the value array + */ + protected float mXMax = 0f; + + /** + * minimum x-value in the value array + */ + protected float mXMin = 0f; + protected float mLeftAxisMax = 0.0f; protected float mLeftAxisMin = 0.0f; @@ -200,7 +210,7 @@ public void notifyDataChanged() { } /** - * calc minimum and maximum y value over all datasets + * calc minimum and maximum values (both x and y) over all DataSets */ public void calcMinMax(int start, int end) { @@ -208,11 +218,18 @@ public void calcMinMax(int start, int end) { mYMax = 0f; mYMin = 0f; + + mXMax = 0f; + mXMin = 0f; + } else { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = 0; i < mDataSets.size(); i++) { IDataSet set = mDataSets.get(i); @@ -223,6 +240,12 @@ public void calcMinMax(int start, int end) { if (set.getYMax() > mYMax) mYMax = set.getYMax(); + + if (set.getXMin() < mXMin) + mXMin = set.getXMin(); + + if (set.getXMax() > mXMax) + mXMax = set.getXMax(); } if (mYMin == Float.MAX_VALUE) { @@ -352,6 +375,24 @@ public float getYMax(AxisDependency axis) { return mRightAxisMax; } + /** + * Returns the minimum x-value this data object contains. + * + * @return + */ + public float getXMin() { + return mXMin; + } + + /** + * Returns the maximum x-value this data object contains. + * + * @return + */ + public float getXMax() { + return mXMax; + } + /** * returns the maximum length (in characters) across all values in the * x-vals array diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 29f5f69c28..b2fab18a7b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -17,18 +17,28 @@ public abstract class DataSet extends BaseDataSet { /** * the entries that this dataset represents / holds together */ - protected List mYVals = null; + protected List mValues = null; /** - * maximum y-value in the y-value array + * maximum y-value in the value array */ protected float mYMax = 0.0f; /** - * the minimum y-value in the y-value array + * minimum y-value in the value array */ protected float mYMin = 0.0f; + /** + * maximum x-value in the value array + */ + protected float mXMax = 0.0f; + + /** + * minimum x-value in the value array + */ + protected float mXMin = 0.0f; + /** * Creates a new DataSet object with the given values it represents. Also, a @@ -40,21 +50,21 @@ public abstract class DataSet extends BaseDataSet { */ public DataSet(List yVals, String label) { super(label); - this.mYVals = yVals; + this.mValues = yVals; - if (mYVals == null) - mYVals = new ArrayList(); + if (mValues == null) + mValues = new ArrayList(); - calcMinMax(0, mYVals.size()); + calcMinMax(0, mValues.size()); } @Override public void calcMinMax(int start, int end) { - if (mYVals == null) + if (mValues == null) return; - final int yValCount = mYVals.size(); + final int yValCount = mValues.size(); if (yValCount == 0) return; @@ -69,9 +79,12 @@ public void calcMinMax(int start, int end) { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { - T e = mYVals.get(i); + T e = mValues.get(i); if (e != null && !Float.isNaN(e.getVal())) { @@ -80,6 +93,12 @@ public void calcMinMax(int start, int end) { if (e.getVal() > mYMax) mYMax = e.getVal(); + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } @@ -91,7 +110,7 @@ public void calcMinMax(int start, int end) { @Override public int getEntryCount() { - return mYVals.size(); + return mValues.size(); } /** @@ -100,7 +119,7 @@ public int getEntryCount() { * @return */ public List getYVals() { - return mYVals; + return mValues; } /** @@ -114,8 +133,8 @@ public List getYVals() { public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(toSimpleString()); - for (int i = 0; i < mYVals.size(); i++) { - buffer.append(mYVals.get(i).toString() + " "); + for (int i = 0; i < mValues.size(); i++) { + buffer.append(mValues.get(i).toString() + " "); } return buffer.toString(); } @@ -128,7 +147,7 @@ public String toString() { */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); - buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mYVals.size() + "\n"); + buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mValues.size() + "\n"); return buffer.toString(); } @@ -142,6 +161,16 @@ public float getYMax() { return mYMax; } + @Override + public float getXMin() { + return mXMin; + } + + @Override + public float getXMax() { + return mXMax; + } + @Override public void addEntryOrdered(T e) { @@ -150,11 +179,11 @@ public void addEntryOrdered(T e) { float val = e.getVal(); - if (mYVals == null) { - mYVals = new ArrayList(); + if (mValues == null) { + mValues = new ArrayList(); } - if (mYVals.size() == 0) { + if (mValues.size() == 0) { mYMax = val; mYMin = val; } else { @@ -164,18 +193,18 @@ public void addEntryOrdered(T e) { mYMin = val; } - if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) { + if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getXIndex() > e.getXIndex()) { int closestIndex = getEntryIndex(e.getXIndex(), Rounding.UP); - mYVals.add(closestIndex, e); + mValues.add(closestIndex, e); return; } - mYVals.add(e); + mValues.add(e); } @Override public void clear() { - mYVals.clear(); + mValues.clear(); notifyDataSetChanged(); } @@ -213,14 +242,14 @@ public boolean removeEntry(T e) { if (e == null) return false; - if (mYVals == null) + if (mValues == null) return false; // remove the entry - boolean removed = mYVals.remove(e); + boolean removed = mValues.remove(e); if (removed) { - calcMinMax(0, mYVals.size()); + calcMinMax(0, mValues.size()); } return removed; @@ -228,7 +257,7 @@ public boolean removeEntry(T e) { @Override public int getEntryIndex(Entry e) { - return mYVals.indexOf(e); + return mValues.indexOf(e); } @Override @@ -236,7 +265,7 @@ public T getEntryForXIndex(int xIndex, Rounding rounding) { int index = getEntryIndex(xIndex, rounding); if (index > -1) - return mYVals.get(index); + return mValues.get(index); return null; } @@ -247,27 +276,27 @@ public T getEntryForXIndex(int xIndex) { @Override public T getEntryForIndex(int index) { - return mYVals.get(index); + return mValues.get(index); } @Override public int getEntryIndex(int xIndex, Rounding rounding) { int low = 0; - int high = mYVals.size() - 1; + int high = mValues.size() - 1; int closest = -1; while (low <= high) { int m = (high + low) / 2; - if (xIndex == mYVals.get(m).getXIndex()) { - while (m > 0 && mYVals.get(m - 1).getXIndex() == xIndex) + if (xIndex == mValues.get(m).getXIndex()) { + while (m > 0 && mValues.get(m - 1).getXIndex() == xIndex) m--; return m; } - if (xIndex > mYVals.get(m).getXIndex()) + if (xIndex > mValues.get(m).getXIndex()) low = m + 1; else high = m - 1; @@ -276,9 +305,9 @@ public int getEntryIndex(int xIndex, Rounding rounding) { } if (closest != -1) { - int closestXIndex = mYVals.get(closest).getXIndex(); + int closestXIndex = mValues.get(closest).getXIndex(); if (rounding == Rounding.UP) { - if (closestXIndex < xIndex && closest < mYVals.size() - 1) { + if (closestXIndex < xIndex && closest < mValues.size() - 1) { ++closest; } } else if (rounding == Rounding.DOWN) { @@ -315,19 +344,19 @@ public List getEntriesForXIndex(int xIndex) { List entries = new ArrayList(); int low = 0; - int high = mYVals.size() - 1; + int high = mValues.size() - 1; while (low <= high) { int m = (high + low) / 2; - T entry = mYVals.get(m); + T entry = mValues.get(m); if (xIndex == entry.getXIndex()) { - while (m > 0 && mYVals.get(m - 1).getXIndex() == xIndex) + while (m > 0 && mValues.get(m - 1).getXIndex() == xIndex) m--; - high = mYVals.size(); + high = mValues.size(); for (; m < high; m++) { - entry = mYVals.get(m); + entry = mValues.get(m); if (entry.getXIndex() == xIndex) { entries.add(entry); } else { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 7d9da1ac55..e07c8cbd5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -4,7 +4,6 @@ import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; -import android.graphics.drawable.Drawable; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -66,8 +65,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(mYVals.get(i).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(mValues.get(i).copy()); } LineDataSet copied = new LineDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index 3c2b9ba589..5e1f0b8732 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -34,8 +34,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(mYVals.get(i).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(mValues.get(i).copy()); } PieDataSet copied = new PieDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java index 61ea26d5a7..baa81340e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java @@ -118,8 +118,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(mYVals.get(i).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(mValues.get(i).copy()); } RadarDataSet copied = new RadarDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 199a20638b..4c9cbe8c6f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -48,8 +48,8 @@ public DataSet copy() { List yVals = new ArrayList(); - for (int i = 0; i < mYVals.size(); i++) { - yVals.add(mYVals.get(i).copy()); + for (int i = 0; i < mValues.size(); i++) { + yVals.add(mValues.get(i).copy()); } ScatterDataSet copied = new ScatterDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 02b769e8ac..5df853bf5c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -36,6 +36,16 @@ public abstract class RealmBaseDataSet e */ protected float mYMin = 0.0f; + /** + * maximum x-value in the value array + */ + protected float mXMax = 0.0f; + + /** + * minimum x-value in the value array + */ + protected float mXMin = 0.0f; + /** * fieldname of the column that contains the y-values of this dataset */ @@ -89,6 +99,16 @@ public float getYMax() { return mYMax; } + @Override + public float getXMin() { + return mXMin; + } + + @Override + public float getXMax() { + return mXMax; + } + @Override public int getEntryCount() { return mValues.size(); @@ -115,6 +135,9 @@ public void calcMinMax(int start, int end) { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { S e = mValues.get(i); @@ -126,6 +149,12 @@ public void calcMinMax(int start, int end) { if (e.getVal() > mYMax) mYMax = e.getVal(); + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 1b78c278cb..afbe57ca2b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -122,6 +122,9 @@ public void calcMinMax(int start, int end) { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { BarEntry e = mValues.get(i); @@ -143,6 +146,12 @@ public void calcMinMax(int start, int end) { if (e.getPositiveSum() > mYMax) mYMax = e.getPositiveSum(); } + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 7a8ae13f08..ceed5aaf47 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -16,8 +16,6 @@ public class RealmBubbleDataSet extends RealmBarLineScatt private String mSizeField; - protected float mXMax; - protected float mXMin; protected float mMaxSize; private float mHighlightCircleWidth = 2.5f; @@ -131,16 +129,6 @@ public void calcMinMax(int start, int end) { } } - @Override - public float getXMax() { - return mXMax; - } - - @Override - public float getXMin() { - return mXMin; - } - @Override public float getMaxSize() { return mMaxSize; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index def4e4e935..6921904f95 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -163,6 +163,9 @@ public void calcMinMax(int start, int end) { mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + for (int i = start; i <= endValue; i++) { CandleEntry e = mValues.get(i); @@ -172,6 +175,12 @@ public void calcMinMax(int start, int end) { if (e.getHigh() > mYMax) mYMax = e.getHigh(); + + if (e.getXIndex() < mXMin) + mXMin = e.getXIndex(); + + if (e.getXIndex() > mXMax) + mXMax = e.getXIndex(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java index 2764b56d1d..6c0afc1114 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java @@ -15,10 +15,6 @@ public interface IBubbleDataSet extends IBarLineScatterCandleBubbleDataSet { */ float getYMax(); + /** + * returns the minimum x-value this DataSet holds + * + * @return + */ + float getXMin(); + + /** + * returns the maximum x-value this DataSet holds + * + * @return + */ + float getXMax(); + /** * Returns the number of y-values this DataSet represents -> the size of the y-values array * -> yvals.size() From 34a6e3b5eb08d1e5f1c347404251d9b5a6b8504c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 Apr 2016 11:14:25 +0200 Subject: [PATCH 0851/1390] Implement axis calculate method --- .../charting/components/AxisBase.java | 9 +++++++++ .../mikephil/charting/components/XAxis.java | 20 +++++++++++++++++++ .../mikephil/charting/components/YAxis.java | 8 +------- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index caac60b999..9b43423128 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -396,4 +396,13 @@ public void setAxisMaxValue(float max) { mCustomAxisMax = true; mAxisMaximum = max; } + + /** + * Calculates the minimum / maximum and range values of the axis with the given + * minimum and maximum values from the chart data. + * + * @param dataMin the min value according to chart data + * @param dataMax the max value according to chart data + */ + public abstract void calculate(float dataMin, float dataMax); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 18b6e55141..ba7bed8955 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -255,4 +255,24 @@ public String getLongestLabel() { return longest; } + + @Override + public void calculate(float dataMin, float dataMax) { + + // if custom, use value as is, else use data value + float min = mCustomAxisMin ? mAxisMinimum : dataMin; + float max = mCustomAxisMax ? mAxisMaximum : dataMax; + + // temporary range (before calculations) + float range = Math.abs(max - min); + + // in case all values are equal + if (range == 0f) { + max = max + 1f; + min = min - 1f; + } + + // actual range + this.mAxisRange = Math.abs(max - min); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 0846a670a7..44427c28b1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -566,13 +566,7 @@ public boolean needsOffset() { return false; } - /** - * Calculates the minimum, maximum, granularity and range values of the YAxis with the given - * minimum and maximum values from the chart data. - * - * @param dataMin the y-min value according to chart data - * @param dataMax the y-max value according to chart data - */ + @Override public void calculate(float dataMin, float dataMax) { // if custom, use value as is, else use data value From d0ce8e7d5a58b9241bf908660ff4240b31af19d7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 Apr 2016 11:16:07 +0200 Subject: [PATCH 0852/1390] Improve axis calculate method --- .../charting/components/AxisBase.java | 19 +++++++++++++++++- .../mikephil/charting/components/XAxis.java | 20 ------------------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 9b43423128..7ebf9b5cec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -404,5 +404,22 @@ public void setAxisMaxValue(float max) { * @param dataMin the min value according to chart data * @param dataMax the max value according to chart data */ - public abstract void calculate(float dataMin, float dataMax); + public void calculate(float dataMin, float dataMax) { + + // if custom, use value as is, else use data value + float min = mCustomAxisMin ? mAxisMinimum : dataMin; + float max = mCustomAxisMax ? mAxisMaximum : dataMax; + + // temporary range (before calculations) + float range = Math.abs(max - min); + + // in case all values are equal + if (range == 0f) { + max = max + 1f; + min = min - 1f; + } + + // actual range + this.mAxisRange = Math.abs(max - min); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index ba7bed8955..18b6e55141 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -255,24 +255,4 @@ public String getLongestLabel() { return longest; } - - @Override - public void calculate(float dataMin, float dataMax) { - - // if custom, use value as is, else use data value - float min = mCustomAxisMin ? mAxisMinimum : dataMin; - float max = mCustomAxisMax ? mAxisMaximum : dataMax; - - // temporary range (before calculations) - float range = Math.abs(max - min); - - // in case all values are equal - if (range == 0f) { - max = max + 1f; - min = min - 1f; - } - - // actual range - this.mAxisRange = Math.abs(max - min); - } } From 0c8cc700b3b8002fd1dc73d192a96f66ba29bfe1 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 5 Apr 2016 22:27:25 +0200 Subject: [PATCH 0853/1390] Further improvements and timechart example --- MPChartExample/AndroidManifest.xml | 1 + .../mpchartexample/LineChartTime.java | 316 ++++++++++++++++++ .../notimportant/MainActivity.java | 12 + .../charting/charts/BarLineChartBase.java | 8 +- .../mikephil/charting/charts/LineChart.java | 8 - .../charting/components/AxisBase.java | 3 + 6 files changed, 337 insertions(+), 11 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 9efb9639b9..f7ee61b540 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -26,6 +26,7 @@ + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java new file mode 100644 index 0000000000..8d0a7a49e4 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -0,0 +1,316 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendForm; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { + + private LineChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + + mSeekBarX.setProgress(45); + mSeekBarY.setProgress(100); + + mSeekBarY.setOnSeekBarChangeListener(this); + mSeekBarX.setOnSeekBarChangeListener(this); + + mChart = (LineChart) findViewById(R.id.chart1); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable touch gestures + mChart.setTouchEnabled(true); + + mChart.setDragDecelerationFrictionCoef(0.9f); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + mChart.setDrawGridBackground(false); + mChart.setHighlightPerDragEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(true); + + // set an alternative background color + mChart.setBackgroundColor(Color.LTGRAY); + + // add data + setData(20, 30); + + mChart.animateX(2500); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + // get the legend (only possible after setting data) + Legend l = mChart.getLegend(); + + // modify the legend ... + // l.setPosition(LegendPosition.LEFT_OF_CHART); + l.setForm(LegendForm.LINE); + l.setTypeface(tf); + l.setTextSize(11f); + l.setTextColor(Color.WHITE); + l.setPosition(LegendPosition.BELOW_CHART_LEFT); +// l.setYOffset(11f); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(tf); + xAxis.setTextSize(12f); + xAxis.setTextColor(Color.WHITE); + xAxis.setDrawAxisLine(false); + xAxis.setSpaceBetweenLabels(1); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setTypeface(tf); + leftAxis.setTextColor(ColorTemplate.getHoloBlue()); + leftAxis.setAxisMaxValue(200f); + leftAxis.setAxisMinValue(0f); + leftAxis.setDrawGridLines(true); + leftAxis.setGranularityEnabled(true); + + YAxis rightAxis = mChart.getAxisRight(); + rightAxis.setEnabled(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.line, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } + break; + } + case R.id.actionToggleFilled: { + + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawFilledEnabled()) + set.setDrawFilled(false); + else + set.setDrawFilled(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCircles: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawCirclesEnabled()) + set.setDrawCircles(false); + else + set.setDrawCircles(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawCubicEnabled()) + set.setDrawCubic(false); + else + set.setDrawCubic(true); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleStepped: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawSteppedEnabled()) + set.setDrawStepped(false); + else + set.setDrawStepped(true); + } + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); + mChart.notifyDataSetChanged(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + mChart.animateXY(3000, 3000); + break; + } + + case R.id.actionSave: { + if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + + // mChart.saveToGallery("title"+System.currentTimeMillis()) + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + + // redraw + mChart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add(new XAxisValue(i, i + "")); + } + + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = range / 2f; + float val = (float) (Math.random() * mult) + 50;// + (float) + // ((mult * + // 0.1) / 10); + yVals1.add(new Entry(val, i)); + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(Color.WHITE); + set1.setLineWidth(2f); + set1.setCircleRadius(3f); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + + // create a data object with the datasets + LineData data = new LineData(xVals, set1); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + mChart.setData(data); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index a3569dcaaf..34362f1e4e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -29,6 +29,7 @@ import com.xxmassdeveloper.mpchartexample.LineChartActivity1; import com.xxmassdeveloper.mpchartexample.LineChartActivity2; import com.xxmassdeveloper.mpchartexample.LineChartActivityColored; +import com.xxmassdeveloper.mpchartexample.LineChartTime; import com.xxmassdeveloper.mpchartexample.ListViewBarChartActivity; import com.xxmassdeveloper.mpchartexample.ListViewMultiChartActivity; import com.xxmassdeveloper.mpchartexample.MultiLineChartActivity; @@ -136,6 +137,12 @@ protected void onCreate(Bundle savedInstanceState) { realm.isNew = true; objects.add(realm); + ContentItem time = new ContentItem( + "Time Chart", + "Simple demonstration of a time-chart."); + time.isNew = true; + objects.add(time); + MyAdapter adapter = new MyAdapter(this, objects); ListView lv = (ListView) findViewById(R.id.listView1); @@ -266,6 +273,11 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, RealmMainActivity.class); startActivity(i); break; + case 29: + i = new Intent(this, LineChartTime.class); + startActivity(i); + break; + } overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 1f66c92e5f..e5f2c2edc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -345,9 +345,11 @@ protected void calcMinMax() { if (mAutoScaleMinMaxEnabled) mData.calcMinMax(getLowestVisibleXIndex(), getHighestVisibleXIndex()); - // calculate / set x-axis range - mXAxis.mAxisMaximum = mData.getXVals().size() - 1; - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// // calculate / set x-axis range +// mXAxis.mAxisMaximum = mData.getXVals().size() - 1; +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); + + mXAxis.calculate(mData.getXMin(), mData.getXMax()); // calculate axis range (min / max) according to provided data mAxisLeft.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 9acfaafe17..c96926017f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -33,14 +33,6 @@ protected void init() { mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); } - - @Override - protected void calcMinMax() { - super.calcMinMax(); - - if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) - mXAxis.mAxisRange = 1; - } @Override public LineData getLineData() { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 7ebf9b5cec..87e701d5dd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -419,6 +419,9 @@ public void calculate(float dataMin, float dataMax) { min = min - 1f; } + this.mAxisMinimum = min; + this.mAxisMaximum = max; + // actual range this.mAxisRange = Math.abs(max - min); } From 992dd5fc85bce6dad2fe27fbfbf4cbf1d06fcad0 Mon Sep 17 00:00:00 2001 From: = Date: Tue, 5 Apr 2016 22:30:38 +0200 Subject: [PATCH 0854/1390] Work on example --- .../xxmassdeveloper/mpchartexample/LineChartTime.java | 9 ++++++++- .../com/github/mikephil/charting/charts/LineChart.java | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 8d0a7a49e4..c94a2d3fea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -39,6 +39,7 @@ public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { private LineChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + private long curTime = System.currentTimeMillis(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -107,6 +108,10 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setSpaceBetweenLabels(1); + // custom x-axis min / max + xAxis.setAxisMinValue(curTime); + xAxis.setAxisMaxValue(curTime + 100000); + YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); @@ -268,7 +273,9 @@ private void setData(int count, float range) { ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - xVals.add(new XAxisValue(i, i + "")); + + long timeLong = curTime + i * 1000; + xVals.add(new XAxisValue(timeLong, new Date(timeLong).toString())); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index c96926017f..71acbb8d01 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -33,6 +33,14 @@ protected void init() { mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); } + +// @Override +// protected void calcMinMax() { +// super.calcMinMax(); +// +// if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) +// mXAxis.mAxisRange = 1; +// } @Override public LineData getLineData() { From 545c6339180fd92bb9d9afc3eed18b229bef840f Mon Sep 17 00:00:00 2001 From: = Date: Tue, 5 Apr 2016 22:47:09 +0200 Subject: [PATCH 0855/1390] Work on timechart --- .../mpchartexample/LineChartTime.java | 14 +++++++------- .../github/mikephil/charting/data/ChartData.java | 4 ++-- .../mikephil/charting/renderer/XAxisRenderer.java | 8 +++++--- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index c94a2d3fea..bd22874f99 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -60,6 +60,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); mChart = (LineChart) findViewById(R.id.chart1); + mChart.setLogEnabled(true); // no description text mChart.setDescription(""); @@ -84,8 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { // add data setData(20, 30); - - mChart.animateX(2500); + mChart.invalidate(); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -109,8 +109,8 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setSpaceBetweenLabels(1); // custom x-axis min / max - xAxis.setAxisMinValue(curTime); - xAxis.setAxisMaxValue(curTime + 100000); + xAxis.setAxisMinValue(5000); + xAxis.setAxisMaxValue(30000); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -272,10 +272,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { private void setData(int count, float range) { ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < 10; i++) { - long timeLong = curTime + i * 1000; - xVals.add(new XAxisValue(timeLong, new Date(timeLong).toString())); + long timeLong = 10000 + i * 1000; + xVals.add(new XAxisValue(timeLong, i + "")); } ArrayList yVals1 = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 232ac837c1..e5995d36b1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -194,8 +194,8 @@ private void checkLegal() { for (int i = 0; i < mDataSets.size(); i++) { if (mDataSets.get(i).getEntryCount() > mXVals.size()) { - throw new IllegalArgumentException( - "One or more of the DataSet Entry arrays are longer than the x-values array of this ChartData object."); +// throw new IllegalArgumentException( +// "One or more of the DataSet Entry arrays are longer than the x-values array of this ChartData object."); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 6de6112508..a12d10204f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -155,15 +155,17 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { 0f, 0f }; - for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { + for (int i = 0; i < mXAxis.getValues().size(); i++) { - position[0] = i; + XAxisValue xVal = mXAxis.getValues().get(i); + + position[0] = (float) xVal.getPosition(); mTrans.pointValuesToPixel(position); if (mViewPortHandler.isInBoundsX(position[0])) { - String label = mXAxis.getValues().get(i).getLabel(); + String label = xVal.getLabel(); if (mXAxis.isAvoidFirstLastClippingEnabled()) { From a0b49fc8c4758940b2e6e1c8d191a0c21f722e1a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 9 Apr 2016 11:19:33 +0200 Subject: [PATCH 0856/1390] Include offset in position calculation --- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index b6b3a3f3ac..9a24030dcd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -232,7 +232,7 @@ public void renderLegend(Canvas c) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) originPosX -= mLegend.mNeededWidth; } else // BELOW_CHART_CENTER || ABOVE_CHART_CENTER - originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f; + originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f + xoffset; FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); From 986874866dee500c17bb232ed76332a4a834809d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 21:36:55 +0300 Subject: [PATCH 0857/1390] Added horizontal cubic (not exaggerating vertical control points) --- .../CubicLineChartActivity.java | 7 +- .../mpchartexample/LineChartActivity1.java | 14 ++- .../mpchartexample/LineChartActivity2.java | 14 ++- .../mikephil/charting/data/LineDataSet.java | 64 +++++++------ .../implementation/RealmLineDataSet.java | 59 ++++++------ .../interfaces/datasets/ILineDataSet.java | 18 ++-- .../charting/renderer/LineChartRenderer.java | 90 +++++++++++++++++-- 7 files changed, 175 insertions(+), 91 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 26220e5309..3d904854e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -166,10 +166,9 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCubicEnabled()) - set.setDrawCubic(false); - else - set.setDrawCubic(true); + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); } mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 836afcd7f2..00e32ade6c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -235,10 +235,9 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCubicEnabled()) - set.setDrawCubic(false); - else - set.setDrawCubic(true); + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); } mChart.invalidate(); break; @@ -250,10 +249,9 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawSteppedEnabled()) - set.setDrawStepped(false); - else - set.setDrawStepped(true); + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); } mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index d7df678923..479a0154fb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -194,10 +194,9 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCubicEnabled()) - set.setDrawCubic(false); - else - set.setDrawCubic(true); + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); } mChart.invalidate(); break; @@ -209,10 +208,9 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawSteppedEnabled()) - set.setDrawStepped(false); - else - set.setDrawStepped(true); + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); } mChart.invalidate(); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 7d9da1ac55..1fb380eeaa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -17,6 +17,9 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet { + /** Drawing mode for this line dataset **/ + private LineDataSet.Mode mMode = Mode.LINEAR; + /** List representing all colors that are used for the circles */ private List mCircleColors = null; @@ -38,12 +41,6 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** if true, drawing circles is enabled */ private boolean mDrawCircles = true; - /** if true, cubic lines are drawn instead of linear */ - private boolean mDrawCubic = false; - - /** if true, stepped lines are drawn instead of linear */ - private boolean mDrawStepped = false; - private boolean mDrawCircleHole = true; @@ -71,17 +68,37 @@ public DataSet copy() { } LineDataSet copied = new LineDataSet(yVals, getLabel()); + copied.mMode = mMode; copied.mColors = mColors; copied.mCircleRadius = mCircleRadius; copied.mCircleColors = mCircleColors; copied.mDashPathEffect = mDashPathEffect; copied.mDrawCircles = mDrawCircles; - copied.mDrawCubic = mDrawCubic; + copied.mDrawCircleHole = mDrawCircleHole; copied.mHighLightColor = mHighLightColor; return copied; } + /** + * Returns the drawing mode for this line dataset + * + * @return + */ + @Override + public LineDataSet.Mode getMode() { + return mMode; + } + + /** + * Returns the drawing mode for this line dataset + * + * @return + */ + public void setMode(LineDataSet.Mode mode) { + mMode = mode; + } + /** * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, * Min = 0.05f = low cubic effect, Default: 0.2f @@ -189,36 +206,26 @@ public boolean isDrawCirclesEnabled() { return mDrawCircles; } - /** - * If set to true, the linechart lines are drawn in cubic-style instead of - * linear. This affects performance! Default: false - * - * @param enabled - */ + @Deprecated public void setDrawCubic(boolean enabled) { - mDrawCubic = enabled; + mMode = enabled ? Mode.CUBIC_BEZIER : Mode.LINEAR; } + @Deprecated @Override public boolean isDrawCubicEnabled() { - return mDrawCubic; + return mMode == Mode.CUBIC_BEZIER; } - /** - * If set to true, the linechart lines are drawn in stepped-style instead of - * linear. - * This does not work with cubic lines, of course. - * Default: false - * - * @param enabled - */ + @Deprecated public void setDrawStepped(boolean enabled) { - mDrawStepped = enabled; + mMode = enabled ? Mode.STEPPED : Mode.LINEAR; } + @Deprecated @Override public boolean isDrawSteppedEnabled() { - return mDrawStepped; + return mMode == Mode.STEPPED; } /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ @@ -348,4 +355,11 @@ public void setFillFormatter(FillFormatter formatter) { public FillFormatter getFillFormatter() { return mFillFormatter; } + + public enum Mode { + LINEAR, + STEPPED, + CUBIC_BEZIER, + HORIZONTAL_BEZIER + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index ccea3823d4..c1ab855b0e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -5,6 +5,7 @@ import android.graphics.DashPathEffect; import android.graphics.drawable.Drawable; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -23,6 +24,9 @@ */ public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { + /** Drawing mode for this line dataset **/ + private LineDataSet.Mode mMode = LineDataSet.Mode.LINEAR; + /** * List representing all colors that are used for the circles */ @@ -58,16 +62,6 @@ public class RealmLineDataSet extends RealmLineRadarDataS */ private boolean mDrawCircles = true; - /** - * if true, cubic lines are drawn instead of linear - */ - private boolean mDrawCubic = false; - - /** - * if true, stepped lines are drawn instead of linear - */ - private boolean mDrawStepped = false; - private boolean mDrawCircleHole = true; /** @@ -110,6 +104,25 @@ public void build(RealmResults results) { super.build(results); } + /** + * Returns the drawing mode for this line dataset + * + * @return + */ + @Override + public LineDataSet.Mode getMode() { + return mMode; + } + + /** + * Returns the drawing mode for this line dataset + * + * @return + */ + public void setMode(LineDataSet.Mode mode) { + mMode = mode; + } + /** * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, * Min = 0.05f = low cubic effect, Default: 0.2f @@ -193,36 +206,26 @@ public boolean isDrawCirclesEnabled() { return mDrawCircles; } - /** - * If set to true, the linechart lines are drawn in cubic-style instead of - * linear. This affects performance! Default: false - * - * @param enabled - */ + @Deprecated public void setDrawCubic(boolean enabled) { - mDrawCubic = enabled; + mMode = enabled ? LineDataSet.Mode.CUBIC_BEZIER : LineDataSet.Mode.LINEAR; } + @Deprecated @Override public boolean isDrawCubicEnabled() { - return mDrawCubic; + return mMode == LineDataSet.Mode.CUBIC_BEZIER; } - /** - * If set to true, the linechart lines are drawn in stepped-style instead of - * linear. - * This does not work with cubic lines, of course. - * Default: false - * - * @param enabled - */ + @Deprecated public void setDrawStepped(boolean enabled) { - mDrawStepped = enabled; + mMode = enabled ? LineDataSet.Mode.STEPPED : LineDataSet.Mode.LINEAR; } + @Deprecated @Override public boolean isDrawSteppedEnabled() { - return mDrawStepped; + return mMode == LineDataSet.Mode.STEPPED; } /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 16a8f061cb..fb7ba45536 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -4,6 +4,7 @@ import android.graphics.drawable.Drawable; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.FillFormatter; /** @@ -12,25 +13,24 @@ public interface ILineDataSet extends ILineRadarDataSet { /** - * Returns the intensity of the cubic lines (the effect intensity). - * Max = 1f = very cubic, Min = 0.05f = low cubic effect, Default: 0.2f + * Returns the drawing mode for this line dataset * * @return */ - float getCubicIntensity(); + LineDataSet.Mode getMode(); /** - * Returns true if drawing cubic lines is enabled, false if not. + * Returns the intensity of the cubic lines (the effect intensity). + * Max = 1f = very cubic, Min = 0.05f = low cubic effect, Default: 0.2f * * @return */ + float getCubicIntensity(); + + @Deprecated boolean isDrawCubicEnabled(); - /** - * Returns true if drawing stepped lines is enabled, false if not. - * - * @return - */ + @Deprecated boolean isDrawSteppedEnabled(); /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index edf3b99b73..2af2a1f7e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -104,14 +104,20 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); mRenderPaint.setPathEffect(dataSet.getDashPathEffect()); - // if drawing cubic lines is enabled - if (dataSet.isDrawCubicEnabled()) { - - drawCubic(c, dataSet); - - // draw normal (straight) lines - } else { - drawLinear(c, dataSet); + switch (dataSet.getMode()) { + default: + case LINEAR: + case STEPPED: + drawLinear(c, dataSet); + break; + + case CUBIC_BEZIER: + drawCubicBezier(c, dataSet); + break; + + case HORIZONTAL_BEZIER: + drawHorizontalBezier(c, dataSet); + break; } mRenderPaint.setPathEffect(null); @@ -123,7 +129,73 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { * @param c * @param dataSet */ - protected void drawCubic(Canvas c, ILineDataSet dataSet) { + protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { + + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + int entryCount = dataSet.getEntryCount(); + + Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + float intensity = dataSet.getCubicIntensity(); + + cubicPath.reset(); + + int size = (int) Math.ceil((maxx - minx) * phaseX + minx); + + if (size - minx >= 2) { + + Entry prev = dataSet.getEntryForIndex(minx); + Entry cur = prev; + + // let the spline start + cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); + + for (int j = minx + 1, count = Math.min(size, entryCount); j < count; j++) { + + prev = dataSet.getEntryForIndex(j - 1); + cur = dataSet.getEntryForIndex(j); + + final float cpx = (float)(prev.getXIndex()) + + (float)(cur.getXIndex() - prev.getXIndex()) / 2.0f; + + cubicPath.cubicTo( + cpx, prev.getVal() * phaseY, + cpx, cur.getVal() * phaseY, + cur.getXIndex(), cur.getVal() * phaseY); + } + } + + // if filled is enabled, close the path + if (dataSet.isDrawFilledEnabled()) { + + cubicFillPath.reset(); + cubicFillPath.addPath(cubicPath); + // create a new path, this is bad for performance + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, + minx, size); + } + + mRenderPaint.setColor(dataSet.getColor()); + + mRenderPaint.setStyle(Paint.Style.STROKE); + + trans.pathValueToPixel(cubicPath); + + mBitmapCanvas.drawPath(cubicPath, mRenderPaint); + + mRenderPaint.setPathEffect(null); + } + + protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); From e0250bda49e849f72146836cef12f78da903bf80 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 21:45:59 +0300 Subject: [PATCH 0858/1390] Add horizontal bezier to the demo --- MPChartExample/res/menu/line.xml | 4 +++ .../CubicLineChartActivity.java | 28 +++++++++++++++++++ .../mpchartexample/LineChartActivity1.java | 14 ++++++++++ .../mpchartexample/LineChartActivity2.java | 14 ++++++++++ 4 files changed, 60 insertions(+) diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index 8d1437029b..aea6845249 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -21,6 +21,10 @@ android:id="@+id/actionToggleStepped" android:title="Toggle Stepped"> + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 3d904854e0..799838a83f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -173,6 +173,34 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleStepped: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); + } + mChart.invalidate(); + break; + } + case R.id.actionToggleHorizontalCubic: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + mChart.invalidate(); + break; + } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 00e32ade6c..1d4a8bae08 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -256,6 +256,20 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleHorizontalCubic: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + mChart.invalidate(); + break; + } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 479a0154fb..619d019109 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -215,6 +215,20 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleHorizontalCubic: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + mChart.invalidate(); + break; + } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); From f74cead4e76abef1f89df3e5ff41459717af757a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 21:48:53 +0300 Subject: [PATCH 0859/1390] Make yVals settable --- .../src/com/github/mikephil/charting/data/DataSet.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 29f5f69c28..3e2926cf9e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -103,6 +103,16 @@ public List getYVals() { return mYVals; } + /** + * Sets the array of y-values that this DataSet represents, and calls notifyDataSetChanged() + * + * @return + */ + public void setYVals(List yVals) { + mYVals = yVals; + notifyDataSetChanged(); + } + /** * Provides an exact copy of the DataSet this method is used on. * From e762b59a2820b3d542df5907494bb4b688d57a25 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 21:57:13 +0300 Subject: [PATCH 0860/1390] Made these line demos reuse the dataset and keep styling --- .../CubicLineChartActivity.java | 70 ++++++++------ .../mpchartexample/LineChartActivity1.java | 67 ++++++++------ .../mpchartexample/LineChartActivity2.java | 92 +++++++++++-------- 3 files changed, 131 insertions(+), 98 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 799838a83f..86ce89677c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -273,44 +273,54 @@ private void setData(int count, float range) { xVals.add((1990 +i) + ""); } - ArrayList vals1 = new ArrayList(); + ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * // 0.1) / 10); - vals1.add(new Entry(val, i)); + yVals.add(new Entry(val, i)); } - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(vals1, "DataSet 1"); - set1.setDrawCubic(true); - set1.setCubicIntensity(0.2f); - //set1.setDrawFilled(true); - set1.setDrawCircles(false); - set1.setLineWidth(1.8f); - set1.setCircleRadius(4f); - set1.setCircleColor(Color.WHITE); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setColor(Color.WHITE); - set1.setFillColor(Color.WHITE); - set1.setFillAlpha(100); - set1.setDrawHorizontalHighlightIndicator(false); - set1.setFillFormatter(new FillFormatter() { - @Override - public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return -10; - } - }); - // create a data object with the datasets - LineData data = new LineData(xVals, set1); - data.setValueTypeface(tf); - data.setValueTextSize(9f); - data.setDrawValues(false); + LineDataSet set1; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals); + mChart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(yVals, "DataSet 1"); + + set1.setDrawCubic(true); + set1.setCubicIntensity(0.2f); + //set1.setDrawFilled(true); + set1.setDrawCircles(false); + set1.setLineWidth(1.8f); + set1.setCircleRadius(4f); + set1.setCircleColor(Color.WHITE); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setColor(Color.WHITE); + set1.setFillColor(Color.WHITE); + set1.setFillAlpha(100); + set1.setDrawHorizontalHighlightIndicator(false); + set1.setFillFormatter(new FillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return -10; + } + }); - // set data - mChart.setData(data); + // create a data object with the datasets + LineData data = new LineData(xVals, set1); + data.setValueTypeface(tf); + data.setValueTextSize(9f); + data.setDrawValues(false); + + // set data + mChart.setData(data); + } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 1d4a8bae08..82e1961304 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -353,38 +353,49 @@ private void setData(int count, float range) { yVals.add(new Entry(val, i)); } - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); - // set1.setFillAlpha(110); - // set1.setFillColor(Color.RED); - - // set the line to be drawn like this "- - - - - -" - set1.enableDashedLine(10f, 5f, 0f); - set1.enableDashedHighlightLine(10f, 5f, 0f); - set1.setColor(Color.BLACK); - set1.setCircleColor(Color.BLACK); - set1.setLineWidth(1f); - set1.setCircleRadius(3f); - set1.setDrawCircleHole(false); - set1.setValueTextSize(9f); - set1.setDrawFilled(true); - - if(Utils.getSDKInt() >= 18) { - // fill drawable only supported on api level 18 and above - Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); - set1.setFillDrawable(drawable); + LineDataSet set1; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals); + mChart.notifyDataSetChanged(); } else { - set1.setFillColor(Color.BLACK); - } + // create a dataset and give it a type + set1 = new LineDataSet(yVals, "DataSet 1"); + + // set1.setFillAlpha(110); + // set1.setFillColor(Color.RED); + + // set the line to be drawn like this "- - - - - -" + set1.enableDashedLine(10f, 5f, 0f); + set1.enableDashedHighlightLine(10f, 5f, 0f); + set1.setColor(Color.BLACK); + set1.setCircleColor(Color.BLACK); + set1.setLineWidth(1f); + set1.setCircleRadius(3f); + set1.setDrawCircleHole(false); + set1.setValueTextSize(9f); + set1.setDrawFilled(true); + + if (Utils.getSDKInt() >= 18) { + // fill drawable only supported on api level 18 and above + Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); + set1.setFillDrawable(drawable); + } + else { + set1.setFillColor(Color.BLACK); + } - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); // add the datasets - // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + // create a data object with the datasets + LineData data = new LineData(xVals, dataSets); - // set data - mChart.setData(data); + // set data + mChart.setData(data); + } } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 619d019109..42773b649a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -300,22 +300,6 @@ private void setData(int count, float range) { yVals1.add(new Entry(val, i)); } - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); - set1.setAxisDependency(AxisDependency.LEFT); - set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(Color.WHITE); - set1.setLineWidth(2f); - set1.setCircleRadius(3f); - set1.setFillAlpha(65); - set1.setFillColor(ColorTemplate.getHoloBlue()); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setDrawCircleHole(false); - //set1.setFillFormatter(new MyFillFormatter(0f)); -// set1.setDrawHorizontalHighlightIndicator(false); -// set1.setVisible(false); -// set1.setCircleHoleColor(Color.WHITE); - ArrayList yVals2 = new ArrayList(); for (int i = 0; i < count; i++) { @@ -326,30 +310,58 @@ private void setData(int count, float range) { yVals2.add(new Entry(val, i)); } - // create a dataset and give it a type - LineDataSet set2 = new LineDataSet(yVals2, "DataSet 2"); - set2.setAxisDependency(AxisDependency.RIGHT); - set2.setColor(Color.RED); - set2.setCircleColor(Color.WHITE); - set2.setLineWidth(2f); - set2.setCircleRadius(3f); - set2.setFillAlpha(65); - set2.setFillColor(Color.RED); - set2.setDrawCircleHole(false); - set2.setHighLightColor(Color.rgb(244, 117, 117)); - //set2.setFillFormatter(new MyFillFormatter(900f)); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set2); - dataSets.add(set1); // add the datasets - - // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(9f); - - // set data - mChart.setData(data); + LineDataSet set1, set2; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); + set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); + set1.setYVals(yVals1); + set2.setYVals(yVals2); + mChart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(yVals1, "DataSet 1"); + + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(Color.WHITE); + set1.setLineWidth(2f); + set1.setCircleRadius(3f); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + //set1.setFillFormatter(new MyFillFormatter(0f)); + //set1.setDrawHorizontalHighlightIndicator(false); + //set1.setVisible(false); + //set1.setCircleHoleColor(Color.WHITE); + + // create a dataset and give it a type + set2 = new LineDataSet(yVals2, "DataSet 2"); + set2.setAxisDependency(AxisDependency.RIGHT); + set2.setColor(Color.RED); + set2.setCircleColor(Color.WHITE); + set2.setLineWidth(2f); + set2.setCircleRadius(3f); + set2.setFillAlpha(65); + set2.setFillColor(Color.RED); + set2.setDrawCircleHole(false); + set2.setHighLightColor(Color.rgb(244, 117, 117)); + //set2.setFillFormatter(new MyFillFormatter(900f)); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set2); + dataSets.add(set1); // add the datasets + + // create a data object with the datasets + LineData data = new LineData(xVals, dataSets); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + mChart.setData(data); + } } @Override From 215be8ac7553188aa4acf6610660fd9e517ae9f8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 9 Apr 2016 22:07:06 +0300 Subject: [PATCH 0861/1390] DRYed some code here... --- .../charting/renderer/LineChartRenderer.java | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 2af2a1f7e6..430aa3edfe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -232,37 +232,18 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { // let the spline start cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); - for (int j = minx + 1, count = Math.min(size, entryCount - 1); j < count; j++) { + for (int j = minx + 1, count = Math.min(size, entryCount); j < count; j++) { prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); - next = dataSet.getEntryForIndex(j + 1); - - prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; - prevDy = (cur.getVal() - prevPrev.getVal()) * intensity; - curDx = (next.getXIndex() - prev.getXIndex()) * intensity; - curDy = (next.getVal() - prev.getVal()) * intensity; - - cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, - cur.getXIndex() - curDx, - (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); - } - - if (size > entryCount - 1) { - - prevPrev = dataSet.getEntryForIndex((entryCount >= 3) ? entryCount - 3 - : entryCount - 2); - prev = dataSet.getEntryForIndex(entryCount - 2); - cur = dataSet.getEntryForIndex(entryCount - 1); - next = cur; + next = entryCount > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; prevDy = (cur.getVal() - prevPrev.getVal()) * intensity; curDx = (next.getXIndex() - prev.getXIndex()) * intensity; curDy = (next.getVal() - prev.getVal()) * intensity; - // the last cubic cubicPath.cubicTo(prev.getXIndex() + prevDx, (prev.getVal() + prevDy) * phaseY, cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); From 0ab3dbfae10e0fc2c5b21a1a0752512c326b230a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 10:23:26 +0300 Subject: [PATCH 0862/1390] Added Xamarin links --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 197c1b4881..1e58a84f48 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,10 @@ As an additional feature, this library allows cross-platform development between Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). +## 3rd party bindings + +Xamarin (by @Flash3001): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). + Spread the word ----- From 18e39237de56ad597e41ebcc8dc8e822d5d28cce Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 13:14:38 +0300 Subject: [PATCH 0863/1390] Added feature for drawing bar borders --- .../mikephil/charting/data/BarDataSet.java | 44 +++++++++++++++++++ .../realm/implementation/RealmBarDataSet.java | 44 +++++++++++++++++++ .../interfaces/datasets/IBarDataSet.java | 15 +++++++ .../charting/renderer/BarChartRenderer.java | 21 ++++++++- .../renderer/HorizontalBarChartRenderer.java | 12 ++++- 5 files changed, 132 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index fb1dccccf8..eed5785bb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -26,6 +26,10 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl */ private int mBarShadowColor = Color.rgb(215, 215, 215); + private float mBarBorderWidth = 0.0f; + + private int mBarBorderColor = Color.BLACK; + /** * the alpha value used to draw the highlight indicator bar */ @@ -217,6 +221,46 @@ public int getBarShadowColor() { return mBarShadowColor; } + /** + * Sets the width used for drawing borders around the bars. + * If borderWidth == 0, no border will be drawn. + * + * @return + */ + public void setBarBorderWidth(float width) { + mBarBorderWidth = width; + } + + /** + * Returns the width used for drawing borders around the bars. + * If borderWidth == 0, no border will be drawn. + * + * @return + */ + @Override + public float getBarBorderWidth() { + return mBarBorderWidth; + } + + /** + * Sets the color drawing borders around the bars. + * + * @return + */ + public void setBarBorderColor(int color) { + mBarBorderColor = color; + } + + /** + * Returns the color drawing borders around the bars. + * + * @return + */ + @Override + public int getBarBorderColor() { + return mBarBorderColor; + } + /** * Set the alpha value (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 1b78c278cb..5fde69a4bd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -34,6 +34,10 @@ public class RealmBarDataSet extends RealmBarLineScatterC */ private int mBarShadowColor = Color.rgb(215, 215, 215); + private float mBarBorderWidth = 0.0f; + + private int mBarBorderColor = Color.BLACK; + /** * the alpha value used to draw the highlight indicator bar */ @@ -212,6 +216,46 @@ public int getBarShadowColor() { return mBarShadowColor; } + /** + * Sets the width used for drawing borders around the bars. + * If borderWidth == 0, no border will be drawn. + * + * @return + */ + public void setBarBorderWidth(float width) { + mBarBorderWidth = width; + } + + /** + * Returns the width used for drawing borders around the bars. + * If borderWidth == 0, no border will be drawn. + * + * @return + */ + @Override + public float getBarBorderWidth() { + return mBarBorderWidth; + } + + /** + * Sets the color drawing borders around the bars. + * + * @return + */ + public void setBarBorderColor(int color) { + mBarBorderColor = color; + } + + /** + * Returns the color drawing borders around the bars. + * + * @return + */ + @Override + public int getBarBorderColor() { + return mBarBorderColor; + } + /** * Set the alpha value (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index bc3bb9b3ea..e7c2f64355 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -37,6 +37,21 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet 0.f; float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -125,11 +133,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { break; // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. + // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); + + if (drawBorder) { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mBarBorderPaint); + } } } else { @@ -145,6 +157,11 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); + + if (drawBorder) { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mBarBorderPaint); + } } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index facccc945c..41e1514d5d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -52,6 +52,10 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); mShadowPaint.setColor(dataSet.getBarShadowColor()); + mBarBorderPaint.setColor(dataSet.getBarBorderColor()); + mBarBorderPaint.setStrokeWidth(dataSet.getBarBorderWidth()); + + final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f; float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -82,11 +86,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { } // Set the color for the currently drawn value. If the index - // is - // out of bounds, reuse colors. + // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); + + if (drawBorder) { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mBarBorderPaint); + } } } From 58b640dc0b968525b24c47d2e01ca63543e8d652 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 13:15:46 +0300 Subject: [PATCH 0864/1390] Added bar borders to the demo --- MPChartExample/res/menu/bar.xml | 4 ++++ .../xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 7 +++++++ .../xxmassdeveloper/mpchartexample/BarChartActivity.java | 7 +++++++ .../mpchartexample/BarChartActivityMultiDataset.java | 7 +++++++ .../mpchartexample/BarChartActivitySinus.java | 7 +++++++ .../mpchartexample/HorizontalBarChartActivity.java | 7 +++++++ .../xxmassdeveloper/mpchartexample/StackedBarActivity.java | 7 +++++++ .../mpchartexample/StackedBarActivityNegative.java | 7 +++++++ 8 files changed, 53 insertions(+) diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index 2cce21aacf..4b35e2ff5d 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -41,5 +41,9 @@ android:id="@+id/actionToggleAutoScaleMinMax" android:title="Toggle auto scale min/max"> + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index cabd72e9dd..fe4f7a8381 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -126,6 +126,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 99d3d027fd..d097d5da9c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -167,6 +167,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 4f869ecc3a..aa734146d8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -135,6 +135,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index e200f2e9b1..d335fe7095 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -151,6 +151,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 3027188cf5..70a64eb7fc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -169,6 +169,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 77c6d1f23f..6934711bb8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -140,6 +140,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index d25ee39f2b..ea33423354 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -154,6 +154,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlightArrow: { if (mChart.isDrawHighlightArrowEnabled()) mChart.setDrawHighlightArrow(false); From e6915e25e2a78cc4e2f4d523be7e987736f9d2bd Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 13:16:16 +0300 Subject: [PATCH 0865/1390] Made these bar demos reuse the dataset and keep styling --- .../mpchartexample/AnotherBarActivity.java | 25 +++++--- .../mpchartexample/BarChartActivity.java | 25 +++++--- .../BarChartActivityMultiDataset.java | 57 ++++++++++++------- .../mpchartexample/BarChartActivitySinus.java | 27 ++++++--- .../BarChartPositiveNegative.java | 33 +++++++---- .../HorizontalBarChartActivity.java | 23 +++++--- .../mpchartexample/StackedBarActivity.java | 28 ++++++--- 7 files changed, 143 insertions(+), 75 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index fe4f7a8381..5d5b933f57 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -186,17 +186,26 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { xVals.add((int) yVals1.get(i).getVal() + ""); } - BarDataSet set1 = new BarDataSet(yVals1, "Data Set"); - set1.setColors(ColorTemplate.VORDIPLOM_COLORS); - set1.setDrawValues(false); + BarDataSet set1; - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals1); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "Data Set"); + set1.setColors(ColorTemplate.VORDIPLOM_COLORS); + set1.setDrawValues(false); - BarData data = new BarData(xVals, dataSets); + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - mChart.setData(data); - mChart.invalidate(); + BarData data = new BarData(xVals, dataSets); + + mChart.setData(data); + mChart.invalidate(); + } } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index d097d5da9c..626890aa03 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -245,17 +245,26 @@ private void setData(int count, float range) { yVals1.add(new BarEntry(val, i)); } - BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); - set1.setBarSpacePercent(35f); + BarDataSet set1; - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals1); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "DataSet"); + set1.setBarSpacePercent(35f); - BarData data = new BarData(xVals, dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTf); + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - mChart.setData(data); + BarData data = new BarData(xVals, dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); + + mChart.setData(data); + } } @SuppressLint("NewApi") diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index aa734146d8..1229828c4d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -211,30 +211,43 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals3.add(new BarEntry(val, i)); } - // create 3 datasets with different types - BarDataSet set1 = new BarDataSet(yVals1, "Company A"); - // set1.setColors(ColorTemplate.createColors(getApplicationContext(), - // ColorTemplate.FRESH_COLORS)); - set1.setColor(Color.rgb(104, 241, 175)); - BarDataSet set2 = new BarDataSet(yVals2, "Company B"); - set2.setColor(Color.rgb(164, 228, 251)); - BarDataSet set3 = new BarDataSet(yVals3, "Company C"); - set3.setColor(Color.rgb(242, 247, 158)); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - dataSets.add(set2); - dataSets.add(set3); - - BarData data = new BarData(xVals, dataSets); + BarDataSet set1, set2, set3; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set2 = (BarDataSet)mChart.getData().getDataSetByIndex(1); + set3 = (BarDataSet)mChart.getData().getDataSetByIndex(2); + set1.setYVals(yVals1); + set2.setYVals(yVals2); + set3.setYVals(yVals3); + mChart.notifyDataSetChanged(); + } else { + // create 3 datasets with different types + set1 = new BarDataSet(yVals1, "Company A"); + // set1.setColors(ColorTemplate.createColors(getApplicationContext(), + // ColorTemplate.FRESH_COLORS)); + set1.setColor(Color.rgb(104, 241, 175)); + set2 = new BarDataSet(yVals2, "Company B"); + set2.setColor(Color.rgb(164, 228, 251)); + set3 = new BarDataSet(yVals3, "Company C"); + set3.setColor(Color.rgb(242, 247, 158)); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); + dataSets.add(set2); + dataSets.add(set3); + + BarData data = new BarData(xVals, dataSets); // data.setValueFormatter(new LargeValueFormatter()); - - // add space between the dataset groups in percent of bar-width - data.setGroupSpace(80f); - data.setValueTypeface(tf); - mChart.setData(data); - mChart.invalidate(); + // add space between the dataset groups in percent of bar-width + data.setGroupSpace(80f); + data.setValueTypeface(tf); + + mChart.setData(data); + mChart.invalidate(); + } } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index d335fe7095..b7d6dfd5aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -223,16 +223,25 @@ private void setData(int count) { xVals.add(i+""); entries.add(mSinusData.get(i)); } - - BarDataSet set = new BarDataSet(entries, "Sinus Function"); - set.setBarSpacePercent(40f); - set.setColor(Color.rgb(240, 120, 124)); - BarData data = new BarData(xVals, set); - data.setValueTextSize(10f); - data.setValueTypeface(mTf); - data.setDrawValues(false); + BarDataSet set; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set.setYVals(entries); + mChart.notifyDataSetChanged(); + } else { + set = new BarDataSet(entries, "Sinus Function"); + set.setBarSpacePercent(40f); + set.setColor(Color.rgb(240, 120, 124)); - mChart.setData(data); + BarData data = new BarData(xVals, set); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); + data.setDrawValues(false); + + mChart.setData(data); + } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 26f8e6fceb..e028d5d2d7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -108,18 +108,27 @@ private void setData(List dataList) { colors.add(green); } - BarDataSet set = new BarDataSet(values, "Values"); - set.setBarSpacePercent(40f); - set.setColors(colors); - set.setValueTextColors(colors); - - BarData data = new BarData(dates, set); - data.setValueTextSize(13f); - data.setValueTypeface(mTf); - data.setValueFormatter(new ValueFormatter()); - - mChart.setData(data); - mChart.invalidate(); + BarDataSet set; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set.setYVals(values); + mChart.notifyDataSetChanged(); + } else { + set = new BarDataSet(values, "Values"); + set.setBarSpacePercent(40f); + set.setColors(colors); + set.setValueTextColors(colors); + + BarData data = new BarData(dates, set); + data.setValueTextSize(13f); + data.setValueTypeface(mTf); + data.setValueFormatter(new ValueFormatter()); + + mChart.setData(data); + mChart.invalidate(); + } } /** diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 70a64eb7fc..1dc016ac60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -242,16 +242,25 @@ private void setData(int count, float range) { yVals1.add(new BarEntry((float) (Math.random() * range), i)); } - BarDataSet set1 = new BarDataSet(yVals1, "DataSet 1"); + BarDataSet set1; - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals1); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "DataSet 1"); - BarData data = new BarData(xVals, dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(tf); + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - mChart.setData(data); + BarData data = new BarData(xVals, dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tf); + + mChart.setData(data); + } } @SuppressLint("NewApi") diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 6934711bb8..1f8ef92129 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; @@ -201,18 +202,27 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new BarEntry(new float[] { val1, val2, val3 }, i)); } - BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setColors(getColors()); - set1.setStackLabels(new String[] { "Births", "Divorces", "Marriages" }); + BarDataSet set1; - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals1); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); + set1.setColors(getColors()); + set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); - data.setValueFormatter(new MyValueFormatter()); + BarData data = new BarData(xVals, dataSets); + data.setValueFormatter(new MyValueFormatter()); - mChart.setData(data); - mChart.invalidate(); + mChart.setData(data); + mChart.invalidate(); + } } @Override From 9a9ae5141c6773f2522d545c9e9a47ad126b8769 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 14:10:03 +0300 Subject: [PATCH 0866/1390] Avoid division by zero when calculating huge zooms --- .../com/github/mikephil/charting/renderer/YAxisRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index f1d8f8288e..cbc883e8aa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -134,8 +134,8 @@ protected void computeAxisValues(float min, float max) { } else { - double first = Math.ceil(yMin / interval) * interval; - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; + double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); double f; int i; From a1fa7ad5b250dee719897ca7384184a19c5b1e40 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Apr 2016 20:02:55 +0300 Subject: [PATCH 0867/1390] Exploded the Legend-Position enum to support more combinations --- .../charting/charts/BarLineChartBase.java | 141 ++++-- .../charting/charts/HorizontalBarChart.java | 43 +- .../charting/charts/PieRadarChartBase.java | 200 ++++---- .../mikephil/charting/components/Legend.java | 447 +++++++++++++----- .../charting/renderer/LegendRenderer.java | 192 ++++---- 5 files changed, 637 insertions(+), 386 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 1f66c92e5f..9bba9d5886 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -10,10 +10,12 @@ import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.PointF; +import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; +import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -299,9 +301,13 @@ protected void prepareValuePxMatrix() { Log.i(LOG_TAG, "Preparing Value-Px Matrix, xmin: " + mXAxis.mAxisMinimum + ", xmax: " + mXAxis.mAxisMaximum + ", xdelta: " + mXAxis.mAxisRange); - mRightAxisTransformer.prepareMatrixValuePx(mXAxis.mAxisMinimum, mXAxis.mAxisRange, mAxisRight.mAxisRange, + mRightAxisTransformer.prepareMatrixValuePx(mXAxis.mAxisMinimum, + mXAxis.mAxisRange, + mAxisRight.mAxisRange, mAxisRight.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mXAxis.mAxisMinimum, mXAxis.mAxisRange, mAxisLeft.mAxisRange, + mLeftAxisTransformer.prepareMatrixValuePx(mXAxis.mAxisMinimum, + mXAxis.mAxisRange, + mAxisLeft.mAxisRange, mAxisLeft.mAxisMinimum); } @@ -355,6 +361,90 @@ protected void calcMinMax() { .RIGHT)); } + protected void calculateLegendOffsets(RectF offsets) { + + offsets.left = 0.f; + offsets.right = 0.f; + offsets.top = 0.f; + offsets.bottom = 0.f; + + // setup offsets for legend + if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) { + switch (mLegend.getOrientation()) { + case VERTICAL: + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + offsets.left += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case RIGHT: + offsets.right += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case CENTER: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) + offsets.top += getXAxis().mLabelRotatedHeight; + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) + offsets.bottom += getXAxis().mLabelRotatedHeight; + break; + + default: + break; + } + } + + break; + + case HORIZONTAL: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) + offsets.top += getXAxis().mLabelRotatedHeight; + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) + offsets.bottom += getXAxis().mLabelRotatedHeight; + break; + + default: + break; + } + break; + } + } + } + + private RectF mOffsetsBuffer = new RectF(); + @Override public void calculateOffsets() { @@ -362,49 +452,12 @@ public void calculateOffsets() { float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; - // setup offsets for legend - if (mLegend != null && mLegend.isEnabled()) { - - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART - || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - - offsetRight += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() - * mLegend.getMaxSizePercent()) - + mLegend.getXOffset() * 2f; - - } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART - || mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) { - - offsetLeft += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() - * mLegend.getMaxSizePercent()) - + mLegend.getXOffset() * 2f; + calculateLegendOffsets(mOffsetsBuffer); - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = mLegend.mTextHeightMax; - - offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - - } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { - - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = mLegend.mTextHeightMax; - - offsetTop += Math.min(mLegend.mNeededHeight + yOffset, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - - } - } + offsetLeft += mOffsetsBuffer.left; + offsetTop += mOffsetsBuffer.top; + offsetRight += mOffsetsBuffer.right; + offsetBottom += mOffsetsBuffer.bottom; // offsets for y-labels if (mAxisLeft.needsOffset()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 2ff098b1ad..593ce6c7fb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -56,48 +56,19 @@ protected void init() { mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); } + private RectF mOffsetsBuffer = new RectF(); + @Override public void calculateOffsets() { float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; - // setup offsets for legend - if (mLegend != null && mLegend.isEnabled()) { - - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - - offsetRight += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) - + mLegend.getXOffset() * 2f; - - } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART - || mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) { - - offsetLeft += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) - + mLegend.getXOffset() * 2f; - - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + calculateLegendOffsets(mOffsetsBuffer); - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = mLegend.mTextHeightMax; - - offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - - } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { - - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = mLegend.mTextHeightMax * 2.f; - - offsetTop += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - } - } + offsetLeft += mOffsetsBuffer.left; + offsetTop += mOffsetsBuffer.top; + offsetRight += mOffsetsBuffer.right; + offsetBottom += mOffsetsBuffer.bottom; // offsets for y-labels if (mAxisLeft.needsOffset()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index a7cb8f73ef..5a938872cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -13,6 +13,7 @@ import android.view.MotionEvent; import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; @@ -103,119 +104,118 @@ public void calculateOffsets() { float legendLeft = 0f, legendRight = 0f, legendBottom = 0f, legendTop = 0f; - if (mLegend != null && mLegend.isEnabled()) { - - float fullLegendWidth = Math.min(mLegend.mNeededWidth, - mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + - mLegend.getFormSize() + mLegend.getFormToTextSpace(); - - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { - - // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(13f); - - legendRight = fullLegendWidth + spacing; - - } else if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART) { - - // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(8f); - - float legendWidth = fullLegendWidth + spacing; - - float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax; - - PointF c = getCenter(); - - PointF bottomRight = new PointF(getWidth() - legendWidth + 15, legendHeight + 15); - float distLegend = distanceToCenter(bottomRight.x, bottomRight.y); - - PointF reference = getPosition(c, getRadius(), - getAngleForPoint(bottomRight.x, bottomRight.y)); - - float distReference = distanceToCenter(reference.x, reference.y); - float min = Utils.convertDpToPixel(5f); - - if (distLegend < distReference) { - - float diff = distReference - distLegend; - legendRight = min + diff; - } - - if (bottomRight.y >= c.y && getHeight() - legendWidth > getWidth()) { - legendRight = legendWidth; - } - - } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) { - - // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(13f); + if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) { - legendLeft = fullLegendWidth + spacing; - - } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART) { - - // this is the space between the legend and the chart - float spacing = Utils.convertDpToPixel(8f); - - float legendWidth = fullLegendWidth + spacing; - - float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax; - - PointF c = getCenter(); - - PointF bottomLeft = new PointF(legendWidth - 15, legendHeight + 15); - float distLegend = distanceToCenter(bottomLeft.x, bottomLeft.y); - - PointF reference = getPosition(c, getRadius(), - getAngleForPoint(bottomLeft.x, bottomLeft.y)); - - float distReference = distanceToCenter(reference.x, reference.y); - float min = Utils.convertDpToPixel(5f); - - if (distLegend < distReference) { - - float diff = distReference - distLegend; - legendLeft = min + diff; - } + float fullLegendWidth = Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getFormSize() + mLegend.getFormToTextSpace(); - if (bottomLeft.y >= c.y && getHeight() - legendWidth > getWidth()) { - legendLeft = legendWidth; + switch (mLegend.getOrientation()) { + case VERTICAL: + { + float xLegendOffset = 0.f; + + if (mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.LEFT + || mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.RIGHT) { + if (mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.CENTER) { + // this is the space between the legend and the chart + final float spacing = Utils.convertDpToPixel(13f); + + xLegendOffset = fullLegendWidth + spacing; + + } else { + // this is the space between the legend and the chart + float spacing = Utils.convertDpToPixel(8f); + + float legendWidth = fullLegendWidth + spacing; + float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax; + + PointF c = getCenter(); + + float bottomX = mLegend.getHorizontalAlignment() == + Legend.LegendHorizontalAlignment.RIGHT + ? getWidth() - legendWidth + 15.f + : legendWidth - 15.f; + float bottomY = legendHeight + 15.f; + float distLegend = distanceToCenter(bottomX, bottomY); + + PointF reference = getPosition(c, getRadius(), + getAngleForPoint(bottomX, bottomY)); + + float distReference = distanceToCenter(reference.x, reference.y); + float minOffset = Utils.convertDpToPixel(5f); + + if (bottomY >= c.y && getHeight() - legendWidth > getWidth()) { + xLegendOffset = legendWidth; + } else if (distLegend < distReference) { + + float diff = distReference - distLegend; + xLegendOffset = minOffset + diff; + } + } + } + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + legendLeft = xLegendOffset; + break; + + case RIGHT: + legendRight = xLegendOffset; + break; + + case CENTER: + switch (mLegend.getVerticalAlignment()) { + case TOP: + legendTop = Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + break; + case BOTTOM: + legendBottom = Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + break; + } + break; + } } - - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = getRequiredLegendOffset(); - - legendBottom = Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - - } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { - - // It's possible that we do not need this offset anymore as it - // is available through the extraOffsets, but changing it can mean - // changing default visibility for existing apps. - float yOffset = getRequiredLegendOffset(); - - legendTop = Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - + break; + + case HORIZONTAL: + float yLegendOffset = 0.f; + + if (mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.TOP || + mLegend.getVerticalAlignment() == Legend.LegendVerticalAlignment.BOTTOM) { + + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = getRequiredLegendOffset(); + + yLegendOffset = Math.min(mLegend.mNeededHeight + yOffset, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + + switch (mLegend.getVerticalAlignment()) { + case TOP: + legendTop = yLegendOffset; + break; + case BOTTOM: + legendBottom = yLegendOffset; + break; + } + } + break; } legendLeft += getRequiredBaseOffset(); legendRight += getRequiredBaseOffset(); legendTop += getRequiredBaseOffset(); + legendBottom += getRequiredBaseOffset(); } float minOffset = Utils.convertDpToPixel(mMinOffset); if (this instanceof RadarChart) { - XAxis x = ((RadarChart) this).getXAxis(); + XAxis x = this.getXAxis(); if (x.isEnabled() && x.isDrawLabelsEnabled()) { minOffset = Math.max(minOffset, x.mLabelRotatedWidth); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 0d1cd4d23d..77f1710f27 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -20,6 +20,9 @@ */ public class Legend extends ComponentBase { + /** + * This property is deprecated - Use `position`, `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, `direction`. + */ public enum LegendPosition { RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, @@ -32,6 +35,21 @@ public enum LegendForm { SQUARE, CIRCLE, LINE } + public enum LegendHorizontalAlignment + { + LEFT, CENTER, RIGHT + } + + public enum LegendVerticalAlignment + { + TOP, CENTER, BOTTOM + } + + public enum LegendOrientation + { + HORIZONTAL, VERTICAL + } + public enum LegendDirection { LEFT_TO_RIGHT, RIGHT_TO_LEFT } @@ -63,8 +81,10 @@ public enum LegendDirection { */ private boolean mIsLegendCustom = false; - /** the position relative to the chart the legend is drawn on */ - private LegendPosition mPosition = LegendPosition.BELOW_CHART_LEFT; + private LegendHorizontalAlignment mHorizontalAlignment = LegendHorizontalAlignment.LEFT; + private LegendVerticalAlignment mVerticalAlignment = LegendVerticalAlignment.BOTTOM; + private LegendOrientation mOrientation = LegendOrientation.HORIZONTAL; + private boolean mDrawInside = false; /** the text direction for the legend */ private LegendDirection mDirection = LegendDirection.LEFT_TO_RIGHT; @@ -351,16 +371,175 @@ public boolean isLegendCustom() { * @return */ public LegendPosition getPosition() { - return mPosition; + + if (mOrientation == LegendOrientation.VERTICAL + && mHorizontalAlignment == LegendHorizontalAlignment.CENTER + && mVerticalAlignment == LegendVerticalAlignment.CENTER) { + return LegendPosition.PIECHART_CENTER; + } + else if (mOrientation == LegendOrientation.HORIZONTAL) { + if (mVerticalAlignment == LegendVerticalAlignment.TOP) + return mHorizontalAlignment == LegendHorizontalAlignment.LEFT + ? LegendPosition.ABOVE_CHART_LEFT + : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT + ? LegendPosition.ABOVE_CHART_RIGHT + : LegendPosition.ABOVE_CHART_CENTER); + else + return mHorizontalAlignment == LegendHorizontalAlignment.LEFT + ? LegendPosition.BELOW_CHART_LEFT + : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT + ? LegendPosition.BELOW_CHART_RIGHT + : LegendPosition.BELOW_CHART_CENTER); + } + else { + if (mHorizontalAlignment == LegendHorizontalAlignment.LEFT) + return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside + ? LegendPosition.LEFT_OF_CHART_INSIDE + : (mVerticalAlignment == LegendVerticalAlignment.CENTER + ? LegendPosition.LEFT_OF_CHART_CENTER + : LegendPosition.LEFT_OF_CHART); + else + return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside + ? LegendPosition.RIGHT_OF_CHART_INSIDE + : (mVerticalAlignment == LegendVerticalAlignment.CENTER + ? LegendPosition.RIGHT_OF_CHART_CENTER + : LegendPosition.RIGHT_OF_CHART); + } } /** * sets the position of the legend relative to the whole chart * - * @param pos + * @param newValue + */ + public void setPosition(LegendPosition newValue) { + + switch (newValue) { + case LEFT_OF_CHART: + case LEFT_OF_CHART_INSIDE: + case LEFT_OF_CHART_CENTER: + mHorizontalAlignment = LegendHorizontalAlignment.LEFT; + mVerticalAlignment = newValue == LegendPosition.LEFT_OF_CHART_CENTER + ? LegendVerticalAlignment.CENTER + : LegendVerticalAlignment.TOP; + mOrientation = LegendOrientation.VERTICAL; + break; + + case RIGHT_OF_CHART: + case RIGHT_OF_CHART_INSIDE: + case RIGHT_OF_CHART_CENTER: + mHorizontalAlignment = LegendHorizontalAlignment.RIGHT; + mVerticalAlignment = newValue == LegendPosition.RIGHT_OF_CHART_CENTER + ? LegendVerticalAlignment.CENTER + : LegendVerticalAlignment.TOP; + mOrientation = LegendOrientation.VERTICAL; + break; + + case ABOVE_CHART_LEFT: + case ABOVE_CHART_CENTER: + case ABOVE_CHART_RIGHT: + mHorizontalAlignment = newValue == LegendPosition.ABOVE_CHART_LEFT + ? LegendHorizontalAlignment.LEFT + : (newValue == LegendPosition.ABOVE_CHART_RIGHT + ? LegendHorizontalAlignment.RIGHT + : LegendHorizontalAlignment.CENTER); + mVerticalAlignment = LegendVerticalAlignment.TOP; + mOrientation = LegendOrientation.HORIZONTAL; + break; + + case BELOW_CHART_LEFT: + case BELOW_CHART_CENTER: + case BELOW_CHART_RIGHT: + mHorizontalAlignment = newValue == LegendPosition.BELOW_CHART_LEFT + ? LegendHorizontalAlignment.LEFT + : (newValue == LegendPosition.BELOW_CHART_RIGHT + ? LegendHorizontalAlignment.RIGHT + : LegendHorizontalAlignment.CENTER); + mVerticalAlignment = LegendVerticalAlignment.BOTTOM; + mOrientation = LegendOrientation.HORIZONTAL; + break; + + case PIECHART_CENTER: + mHorizontalAlignment = LegendHorizontalAlignment.CENTER; + mVerticalAlignment = LegendVerticalAlignment.CENTER; + mOrientation = LegendOrientation.VERTICAL; + break; + } + + mDrawInside = newValue == LegendPosition.LEFT_OF_CHART_INSIDE + || newValue == LegendPosition.RIGHT_OF_CHART_INSIDE; + } + + /** + * returns the horizontal alignment of the legend + * + * @return + */ + public LegendHorizontalAlignment getHorizontalAlignment() { + return mHorizontalAlignment; + } + + /** + * sets the horizontal alignment of the legend + * + * @param value + */ + public void setHorizontalAlignment(LegendHorizontalAlignment value) { + mHorizontalAlignment = value; + } + + /** + * returns the vertical alignment of the legend + * + * @return + */ + public LegendVerticalAlignment getVerticalAlignment() { + return mVerticalAlignment; + } + + /** + * sets the vertical alignment of the legend + * + * @param value + */ + public void setVerticalAlignment(LegendVerticalAlignment value) { + mVerticalAlignment = value; + } + + /** + * returns the orientation of the legend + * + * @return */ - public void setPosition(LegendPosition pos) { - mPosition = pos; + public LegendOrientation getOrientation() { + return mOrientation; + } + + /** + * sets the orientation of the legend + * + * @param value + */ + public void setOrientation(LegendOrientation value) { + mOrientation = value; + } + + /** + * returns whether the legend will draw inside the chart or outside + * + * @return + */ + public boolean isDrawInsideEnabled() { + return mDrawInside; + } + + /** + * sets whether the legend will draw inside the chart or outside + * + * @param value + */ + public void setDrawInside(boolean value) { + mDrawInside = value; } /** @@ -605,9 +784,7 @@ public float getMaxSizePercent() { * The maximum relative size out of the whole chart view. / If * the legend is to the right/left of the chart, then this affects the width * of the legend. / If the legend is to the top/bottom of the chart, then - * this affects the height of the legend. / If the legend is the center of - * the PieChart, then this defines the size of the rectangular bounds out of - * the size of the "hole". / default: 0.95f (95%) + * this affects the height of the legend. / default: 0.95f (95%) * * @param maxSize */ @@ -640,132 +817,168 @@ public FSize[] getCalculatedLineSizes() { */ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { - if (mPosition == LegendPosition.RIGHT_OF_CHART - || mPosition == LegendPosition.RIGHT_OF_CHART_CENTER - || mPosition == LegendPosition.LEFT_OF_CHART - || mPosition == LegendPosition.LEFT_OF_CHART_CENTER - || mPosition == LegendPosition.PIECHART_CENTER) { - mNeededWidth = getMaximumEntryWidth(labelpaint); - mNeededHeight = getFullHeight(labelpaint); - mTextWidthMax = mNeededWidth; - mTextHeightMax = getMaximumEntryHeight(labelpaint); - - } else if (mPosition == LegendPosition.BELOW_CHART_LEFT - || mPosition == LegendPosition.BELOW_CHART_RIGHT - || mPosition == LegendPosition.BELOW_CHART_CENTER - || mPosition == LegendPosition.ABOVE_CHART_LEFT - || mPosition == LegendPosition.ABOVE_CHART_RIGHT - || mPosition == LegendPosition.ABOVE_CHART_CENTER) { - - int labelCount = mLabels.length; - float labelLineHeight = Utils.getLineHeight(labelpaint); - float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace; - float contentWidth = viewPortHandler.contentWidth(); - - // Prepare arrays for calculated layout - ArrayList calculatedLabelSizes = new ArrayList(labelCount); - ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); - ArrayList calculatedLineSizes = new ArrayList(); - - // Start calculating layout - float maxLineWidth = 0.f; - float currentLineWidth = 0.f; - float requiredWidth = 0.f; - int stackedStartIndex = -1; - - for (int i = 0; i < labelCount; i++) { - - boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; - - calculatedLabelBreakPoints.add(false); - - if (stackedStartIndex == -1) - { - // we are not stacking, so required width is for this label - // only - requiredWidth = 0.f; - } else { - // add the spacing appropriate for stacked labels/forms - requiredWidth += mStackSpace; - } + mTextWidthMax = getMaximumEntryWidth(labelpaint); + mTextHeightMax = getMaximumEntryHeight(labelpaint); - // grouped forms have null labels - if (mLabels[i] != null) { + switch (mOrientation) { + case VERTICAL: { - calculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i])); - requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f; - requiredWidth += calculatedLabelSizes.get(i).width; - } else { + float maxWidth = 0f, maxHeight = 0f, width = 0f; + float labelLineHeight = Utils.getLineHeight(labelpaint); + final int count = mLabels.length; + boolean wasStacked = false; - calculatedLabelSizes.add(new FSize(0.f, 0.f)); - requiredWidth += drawingForm ? mFormSize : 0.f; + for (int i = 0; i < count; i++) { - if (stackedStartIndex == -1) { - // mark this index as we might want to break here later - stackedStartIndex = i; + boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; + + if (!wasStacked) + width = 0.f; + + if (drawingForm) { + if (wasStacked) + width += mStackSpace; + width += mFormSize; } + + // grouped forms have null labels + if (mLabels[i] != null) { + + // make a step to the left + if (drawingForm && !wasStacked) + width += mFormToTextSpace; + else if (wasStacked) { + maxWidth = Math.max(maxWidth, width); + maxHeight += labelLineHeight + mYEntrySpace; + width = 0.f; + wasStacked = false; + } + + width += Utils.calcTextWidth(labelpaint, mLabels[i]); + + if (i < count - 1) + maxHeight += labelLineHeight + mYEntrySpace; + } + else { + wasStacked = true; + width += mFormSize; + if (i < count - 1) + width += mStackSpace; + } + + maxWidth = Math.max(maxWidth, width); } - if (mLabels[i] != null || i == labelCount - 1) { + mNeededWidth = maxWidth; + mNeededHeight = maxHeight; + + break; + } + case HORIZONTAL: { + + int labelCount = mLabels.length; + float labelLineHeight = Utils.getLineHeight(labelpaint); + float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace; + float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent; + + // Prepare arrays for calculated layout + ArrayList calculatedLabelSizes = new ArrayList(labelCount); + ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); + ArrayList calculatedLineSizes = new ArrayList(); - float requiredSpacing = currentLineWidth == 0.f ? 0.f : mXEntrySpace; + // Start calculating layout + float maxLineWidth = 0.f; + float currentLineWidth = 0.f; + float requiredWidth = 0.f; + int stackedStartIndex = -1; - if (!mWordWrapEnabled || // No word wrapping, it must fit. - currentLineWidth == 0.f || // The line is empty, it - // must fit. - (contentWidth - currentLineWidth >= requiredSpacing + requiredWidth)) // It - // simply - // fits - { - // Expand current line - currentLineWidth += requiredSpacing + requiredWidth; + for (int i = 0; i < labelCount; i++) { - } else { // It doesn't fit, we need to wrap a line + boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; - // Add current line size to array - calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); - maxLineWidth = Math.max(maxLineWidth, currentLineWidth); + calculatedLabelBreakPoints.add(false); - // Start a new line - calculatedLabelBreakPoints.set(stackedStartIndex > -1 ? stackedStartIndex - : i, true); - currentLineWidth = requiredWidth; + if (stackedStartIndex == -1) { + // we are not stacking, so required width is for this label + // only + requiredWidth = 0.f; + } + else { + // add the spacing appropriate for stacked labels/forms + requiredWidth += mStackSpace; + } + + // grouped forms have null labels + if (mLabels[i] != null) { + + calculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i])); + requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f; + requiredWidth += calculatedLabelSizes.get(i).width; } + else { - if (i == labelCount - 1) { - // Add last line size to array - calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); - maxLineWidth = Math.max(maxLineWidth, currentLineWidth); + calculatedLabelSizes.add(new FSize(0.f, 0.f)); + requiredWidth += drawingForm ? mFormSize : 0.f; + + if (stackedStartIndex == -1) { + // mark this index as we might want to break here later + stackedStartIndex = i; + } + } + + if (mLabels[i] != null || i == labelCount - 1) { + + float requiredSpacing = currentLineWidth == 0.f ? 0.f : mXEntrySpace; + + if (!mWordWrapEnabled // No word wrapping, it must fit. + // The line is empty, it must fit + || currentLineWidth == 0.f + // It simply fits + || (contentWidth - currentLineWidth >= + requiredSpacing + requiredWidth)) { + // Expand current line + currentLineWidth += requiredSpacing + requiredWidth; + } + else { // It doesn't fit, we need to wrap a line + + // Add current line size to array + calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); + maxLineWidth = Math.max(maxLineWidth, currentLineWidth); + + // Start a new line + calculatedLabelBreakPoints.set( + stackedStartIndex > -1 ? stackedStartIndex + : i, true); + currentLineWidth = requiredWidth; + } + + if (i == labelCount - 1) { + // Add last line size to array + calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); + maxLineWidth = Math.max(maxLineWidth, currentLineWidth); + } } + + stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; } - stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; + mCalculatedLabelSizes = calculatedLabelSizes.toArray( + new FSize[calculatedLabelSizes.size()]); + mCalculatedLabelBreakPoints = calculatedLabelBreakPoints + .toArray(new Boolean[calculatedLabelBreakPoints.size()]); + mCalculatedLineSizes = calculatedLineSizes + .toArray(new FSize[calculatedLineSizes.size()]); + + mNeededWidth = maxLineWidth; + mNeededHeight = labelLineHeight + * (float) (mCalculatedLineSizes.length) + + labelLineSpacing * + (float) (mCalculatedLineSizes.length == 0 + ? 0 + : (mCalculatedLineSizes.length - 1)); + + break; } - - mCalculatedLabelSizes = calculatedLabelSizes.toArray( - new FSize[calculatedLabelSizes.size()]); - mCalculatedLabelBreakPoints = calculatedLabelBreakPoints - .toArray(new Boolean[calculatedLabelBreakPoints.size()]); - mCalculatedLineSizes = calculatedLineSizes - .toArray(new FSize[calculatedLineSizes.size()]); - - mTextWidthMax = getMaximumEntryWidth(labelpaint); - mTextHeightMax = getMaximumEntryHeight(labelpaint); - mNeededWidth = maxLineWidth; - mNeededHeight = labelLineHeight - * (float) (mCalculatedLineSizes.length) - + labelLineSpacing * - (float) (mCalculatedLineSizes.length == 0 - ? 0 - : (mCalculatedLineSizes.length - 1)); - - } else { - /* RIGHT_OF_CHART_INSIDE, LEFT_OF_CHART_INSIDE */ - - mNeededWidth = getFullWidth(labelpaint); - mNeededHeight = getMaximumEntryHeight(labelpaint); - mTextWidthMax = getMaximumEntryWidth(labelpaint); - mTextHeightMax = mNeededHeight; } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 9a24030dcd..f005a1f2ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -195,57 +195,89 @@ public void renderLegend(Canvas c) { float formToTextSpace = mLegend.getFormToTextSpace(); float xEntrySpace = mLegend.getXEntrySpace(); + Legend.LegendOrientation orientation = mLegend.getOrientation(); + Legend.LegendHorizontalAlignment horizontalAlignment = mLegend.getHorizontalAlignment(); + Legend.LegendVerticalAlignment verticalAlignment = mLegend.getVerticalAlignment(); Legend.LegendDirection direction = mLegend.getDirection(); float formSize = mLegend.getFormSize(); // space between the entries float stackSpace = mLegend.getStackSpace(); - float posX, posY; - float yoffset = mLegend.getYOffset(); float xoffset = mLegend.getXOffset(); + float originPosX = 0.f; - Legend.LegendPosition legendPosition = mLegend.getPosition(); + switch (horizontalAlignment) { + case LEFT: - switch (legendPosition) { - case BELOW_CHART_LEFT: - case BELOW_CHART_RIGHT: - case BELOW_CHART_CENTER: - case ABOVE_CHART_LEFT: - case ABOVE_CHART_RIGHT: - case ABOVE_CHART_CENTER: { - float contentWidth = mViewPortHandler.contentWidth(); + if (orientation == Legend.LegendOrientation.VERTICAL) + originPosX = xoffset; + else + originPosX = mViewPortHandler.contentLeft() + xoffset; - float originPosX; + if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) + originPosX += mLegend.mNeededWidth; - if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT - || legendPosition == Legend.LegendPosition.ABOVE_CHART_LEFT) { - originPosX = mViewPortHandler.contentLeft() + xoffset; + break; + + case RIGHT: - if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) - originPosX += mLegend.mNeededWidth; - } else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT - || legendPosition == Legend.LegendPosition.ABOVE_CHART_RIGHT) { + if (orientation == Legend.LegendOrientation.VERTICAL) + originPosX = mViewPortHandler.getChartWidth() - xoffset; + else originPosX = mViewPortHandler.contentRight() - xoffset; - if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) - originPosX -= mLegend.mNeededWidth; - } else // BELOW_CHART_CENTER || ABOVE_CHART_CENTER - originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f + xoffset; + if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) + originPosX -= mLegend.mNeededWidth; + + break; + + case CENTER: + + if (orientation == Legend.LegendOrientation.VERTICAL) + originPosX = mViewPortHandler.getChartWidth() / 2.f; + else + originPosX = mViewPortHandler.contentLeft() + + mViewPortHandler.contentWidth() / 2.f; + + originPosX += (direction == Legend.LegendDirection.LEFT_TO_RIGHT + ? +xoffset + : -xoffset); + + // Horizontally layed out legends do the center offset on a line basis, + // So here we offset the vertical ones only. + if (orientation == Legend.LegendOrientation.VERTICAL) { + originPosX += (direction == Legend.LegendDirection.LEFT_TO_RIGHT + ? -mLegend.mNeededWidth / 2.0 + xoffset + : mLegend.mNeededWidth / 2.0 - xoffset); + } + + break; + } + + switch (orientation) { + case HORIZONTAL: { FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); Boolean[] calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints(); - posX = originPosX; + float posX = originPosX; + float posY = 0.f; + + switch (verticalAlignment) { + case TOP: + posY = yoffset; + break; - if (legendPosition == Legend.LegendPosition.ABOVE_CHART_LEFT || - legendPosition == Legend.LegendPosition.ABOVE_CHART_RIGHT || - legendPosition == Legend.LegendPosition.ABOVE_CHART_CENTER) { - posY = yoffset; - } else { - posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight; + case BOTTOM: + posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight; + break; + + case CENTER: + posY = (mViewPortHandler.getChartHeight() - mLegend.mNeededHeight) / 2.f + yoffset; + break; } int lineIndex = 0; @@ -257,10 +289,11 @@ public void renderLegend(Canvas c) { } if (posX == originPosX && - (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER || - legendPosition == Legend.LegendPosition.ABOVE_CHART_CENTER) && + horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER && lineIndex < calculatedLineSizes.length) { - posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT ? calculatedLineSizes[lineIndex].width : -calculatedLineSizes[lineIndex].width) / 2.f; + posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT + ? calculatedLineSizes[lineIndex].width + : -calculatedLineSizes[lineIndex].width) / 2.f; lineIndex++; } @@ -294,91 +327,70 @@ public void renderLegend(Canvas c) { posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -stackSpace : stackSpace; } + break; } - break; - case PIECHART_CENTER: - case RIGHT_OF_CHART: - case RIGHT_OF_CHART_CENTER: - case RIGHT_OF_CHART_INSIDE: - case LEFT_OF_CHART: - case LEFT_OF_CHART_CENTER: - case LEFT_OF_CHART_INSIDE: { + case VERTICAL: { // contains the stacked legend size in pixels float stack = 0f; boolean wasStacked = false; - - if (legendPosition == Legend.LegendPosition.PIECHART_CENTER) { - posX = mViewPortHandler.getChartWidth() / 2f - + (direction == Legend.LegendDirection.LEFT_TO_RIGHT ? -mLegend.mTextWidthMax / 2f - : mLegend.mTextWidthMax / 2f); - posY = mViewPortHandler.getChartHeight() / 2f - mLegend.mNeededHeight / 2f - + mLegend.getYOffset(); - } else { - boolean isRightAligned = legendPosition == Legend.LegendPosition.RIGHT_OF_CHART - || - legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_CENTER || - legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_INSIDE; - - if (isRightAligned) { - posX = mViewPortHandler.getChartWidth() - xoffset; - if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) - posX -= mLegend.mTextWidthMax; - } else { - posX = xoffset; - if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) - posX += mLegend.mTextWidthMax; - } - - if (legendPosition == Legend.LegendPosition.RIGHT_OF_CHART || - legendPosition == Legend.LegendPosition.LEFT_OF_CHART) { - posY = mViewPortHandler.contentTop() + yoffset; - } else if (legendPosition == Legend.LegendPosition.RIGHT_OF_CHART_CENTER || - legendPosition == Legend.LegendPosition.LEFT_OF_CHART_CENTER) { - posY = mViewPortHandler.getChartHeight() / 2f - mLegend.mNeededHeight / 2f; - } else /* - * if (legendPosition == - * Legend.LegendPosition.RIGHT_OF_CHART_INSIDE || - * legendPosition == - * Legend.LegendPosition.LEFT_OF_CHART_INSIDE) - */ { - posY = mViewPortHandler.contentTop() + yoffset; - } + float posY = 0.f; + + switch (verticalAlignment) { + case TOP: + posY = (horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER + ? 0.f + : mViewPortHandler.contentTop()); + posY += yoffset; + break; + + case BOTTOM: + posY = (horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER + ? mViewPortHandler.getChartHeight() + : mViewPortHandler.contentBottom()); + posY -= mLegend.mNeededHeight + yoffset; + break; + + case CENTER: + posY = mViewPortHandler.getChartHeight() / 2.f + - mLegend.mNeededHeight / 2.f + + mLegend.getYOffset(); + break; } for (int i = 0; i < labels.length; i++) { Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP; - float x = posX; + float posX = originPosX; if (drawingForm) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) - x += stack; + posX += stack; else - x -= formSize - stack; + posX -= formSize - stack; - drawForm(c, x, posY + formYOffset, i, mLegend); + drawForm(c, posX, posY + formYOffset, i, mLegend); if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) - x += formSize; + posX += formSize; } if (labels[i] != null) { if (drawingForm && !wasStacked) - x += direction == Legend.LegendDirection.LEFT_TO_RIGHT ? formToTextSpace + posX += direction == Legend.LegendDirection.LEFT_TO_RIGHT ? formToTextSpace : -formToTextSpace; else if (wasStacked) - x = posX; + posX = originPosX; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) - x -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]); + posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]); if (!wasStacked) { - drawLabel(c, x, posY + labelLineHeight, labels[i]); + drawLabel(c, posX, posY + labelLineHeight, labels[i]); } else { posY += labelLineHeight + labelLineSpacing; - drawLabel(c, x, posY + labelLineHeight, labels[i]); + drawLabel(c, posX, posY + labelLineHeight, labels[i]); } // make a step down @@ -389,8 +401,10 @@ else if (wasStacked) wasStacked = true; } } + + break; + } - break; } } From 42981cc98d0c950d9c56695457629aa4d66d8a11 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 11 Apr 2016 10:23:11 +0300 Subject: [PATCH 0868/1390] Protect loop from infinite loop in the highest of zooms --- .../github/mikephil/charting/renderer/YAxisRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index cbc883e8aa..fdae353e4b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -140,8 +140,10 @@ protected void computeAxisValues(float min, float max) { double f; int i; int n = 0; - for (f = first; f <= last; f += interval) { - ++n; + if (interval != 0.0) { + for (f = first; f <= last; f += interval) { + ++n; + } } mYAxis.mEntryCount = n; From f7eabd0718422f73e34c597cd4b4d12ca8a82582 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 12 Apr 2016 10:42:51 +0200 Subject: [PATCH 0869/1390] Update gradle --- MPChartExample/build.gradle | 2 +- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 623e709748..5cef000d7c 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -37,7 +37,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:2.0.0' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/build.gradle b/build.gradle index 1dbeb8610c..66dbb5af3c 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:2.0.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af18b88f2..f39a959361 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Nov 19 21:53:09 CST 2015 +#Tue Apr 12 10:33:07 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip From 055b5a6c4c850077017c4027de60ed3cd34acd20 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 12 Apr 2016 11:34:58 +0200 Subject: [PATCH 0870/1390] Add material colors --- .../mpchartexample/BarChartActivity.java | 17 ++++++++++------- .../mikephil/charting/utils/ColorTemplate.java | 3 +++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 626890aa03..1a25a35cf6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -35,6 +35,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -255,16 +256,18 @@ private void setData(int count, float range) { } else { set1 = new BarDataSet(yVals1, "DataSet"); set1.setBarSpacePercent(35f); + set1.setColors(ColorTemplate.MATERIAL_COLORS); + } - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTf); + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - mChart.setData(data); - } + BarData data = new BarData(xVals, dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); + + mChart.setData(data); } @SuppressLint("NewApi") diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java index 0818d05a9f..106671ad13 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java @@ -51,6 +51,9 @@ public class ColorTemplate { Color.rgb(192, 255, 140), Color.rgb(255, 247, 140), Color.rgb(255, 208, 140), Color.rgb(140, 234, 255), Color.rgb(255, 140, 157) }; + public static final int[] MATERIAL_COLORS = { + rgb("#2ecc71"), rgb("#f1c40f"), rgb("#e74c3c"), rgb("#3498db") + }; /** * Converts the given hex-color-string to rgb. From bef8db1af1f2c888ddeff9bf31301233c5c5e10e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 12 Apr 2016 14:06:13 +0300 Subject: [PATCH 0871/1390] Fixed a null exception when using markers with pie chart --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 055bdf7312..0c837bb1ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -670,7 +670,9 @@ protected void drawMarkers(Canvas canvas) { int xIndex = highlight.getXIndex(); int dataSetIndex = highlight.getDataSetIndex(); - float deltaX = mXAxis.mAxisRange; + float deltaX = mXAxis != null + ? mXAxis.mAxisRange + : ((mData == null ? 0.f : mData.getXValCount()) - 1.f); if (xIndex <= deltaX && xIndex <= deltaX * mAnimator.getPhaseX()) { From cfb3fdf0a946f313124cb98e96e5683966f10960 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 16:56:31 +0300 Subject: [PATCH 0872/1390] Fixed dataset update in demo --- .../mpchartexample/BarChartActivity.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 1a25a35cf6..083d016e64 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -257,17 +257,16 @@ private void setData(int count, float range) { set1 = new BarDataSet(yVals1, "DataSet"); set1.setBarSpacePercent(35f); set1.setColors(ColorTemplate.MATERIAL_COLORS); - } - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTf); + BarData data = new BarData(xVals, dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(mTf); - mChart.setData(data); + mChart.setData(data); + } } @SuppressLint("NewApi") From 4e50305dd3618ad12ef9c5a2e271df90bc7f2b12 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 16:57:52 +0300 Subject: [PATCH 0873/1390] Avoid division by zeros --- .../github/mikephil/charting/utils/ViewPortHandler.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 44797c3f40..6cd677f772 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -442,6 +442,9 @@ public void setMinimumScaleX(float xScale) { */ public void setMaximumScaleX(float xScale) { + if (xScale == 0.f) + xScale = Float.MAX_VALUE; + mMaxScaleX = xScale; limitTransAndScale(mMatrixTouch, mContentRect); @@ -458,6 +461,9 @@ public void setMinMaxScaleX(float minScaleX, float maxScaleX) { if (minScaleX < 1f) minScaleX = 1f; + if (maxScaleX == 0.f) + maxScaleX = Float.MAX_VALUE; + mMinScaleX = minScaleX; mMaxScaleX = maxScaleX; @@ -486,6 +492,9 @@ public void setMinimumScaleY(float yScale) { */ public void setMaximumScaleY(float yScale) { + if (yScale == 0.f) + yScale = Float.MAX_VALUE; + mMaxScaleY = yScale; limitTransAndScale(mMatrixTouch, mContentRect); From 0b43eeaf2d9b60d3d3a033e3b6a7f39a4241daba Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 16:57:57 +0300 Subject: [PATCH 0874/1390] Removed unnecessary ternary expression --- .../src/com/github/mikephil/charting/utils/ViewPortHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 6cd677f772..955e39cf2d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -667,7 +667,7 @@ public void setDragOffsetY(float offset) { * @return */ public boolean hasNoDragOffset() { - return mTransOffsetX <= 0 && mTransOffsetY <= 0 ? true : false; + return mTransOffsetX <= 0 && mTransOffsetY <= 0; } /** From ff0b8c375f59fbe8010a0df9a1809db65f940ab6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 17:20:33 +0300 Subject: [PATCH 0875/1390] Make these a little clearer --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 9bba9d5886..2c70824d12 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1345,7 +1345,7 @@ public int getLowestVisibleXIndex() { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (pts[0] <= 0) ? 0 : (int) (pts[0] + 1.0f); + return (pts[0] <= 0) ? 0 : (int)Math.ceil(pts[0]); } /** @@ -1360,7 +1360,7 @@ public int getHighestVisibleXIndex() { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (pts[0] >= mData.getXValCount()) ? mData.getXValCount() - 1 : (int) pts[0]; + return Math.min(mData.getXValCount() - 1, (int)Math.floor(pts[0])); } /** From 1c312e85a9c6f868f76e886386621ebd3555a7d7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 18:05:00 +0300 Subject: [PATCH 0876/1390] Allow bubble sizes to not be normalized against the dataset max --- .../mikephil/charting/data/BubbleDataSet.java | 10 ++++++++++ .../implementation/RealmBubbleDataSet.java | 10 ++++++++++ .../interfaces/datasets/IBubbleDataSet.java | 2 ++ .../charting/renderer/BubbleChartRenderer.java | 17 +++++++++++++---- 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 5672ecb0bb..42be25b61b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -16,6 +16,7 @@ public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet extends RealmBarLineScatt protected float mXMax; protected float mXMin; protected float mMaxSize; + protected boolean mNormalizeSize = true; private float mHighlightCircleWidth = 2.5f; @@ -146,6 +147,15 @@ public float getMaxSize() { return mMaxSize; } + @Override + public boolean isNormalizeSizeEnabled() { + return mNormalizeSize; + } + + public void setNormalizeSizeEnabled(boolean normalizeSize) { + mNormalizeSize = normalizeSize; + } + private float yMin(BubbleEntry entry) { return entry.getVal(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java index 2764b56d1d..89991f718d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java @@ -21,6 +21,8 @@ public interface IBubbleDataSet extends IBarLineScatterCandleBubbleDataSet Date: Wed, 13 Apr 2016 18:50:46 +0300 Subject: [PATCH 0877/1390] Fixed crash when phaseX causes entryForIndex to go out of bounds --- .../charting/renderer/BubbleChartRenderer.java | 6 +++--- .../charting/renderer/CandleStickChartRenderer.java | 2 +- .../mikephil/charting/renderer/LineChartRenderer.java | 10 +++++----- .../charting/renderer/ScatterChartRenderer.java | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 0cdb145a46..1988aa7692 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -71,7 +71,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); @@ -145,7 +145,7 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - final float phaseX = mAnimator.getPhaseX(); + final float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); final float phaseY = mAnimator.getPhaseY(); BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); @@ -194,7 +194,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { BubbleData bubbleData = mChart.getBubbleData(); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); for (Highlight indice : indices) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 2ef6c0962c..790d83ae92 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -54,7 +54,7 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float barSpace = dataSet.getBarSpace(); boolean showCandleBar = dataSet.getShowCandleBar(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 430aa3edfe..83ca529815 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -142,7 +142,7 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float intensity = dataSet.getCubicIntensity(); @@ -208,7 +208,7 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float intensity = dataSet.getCubicIntensity(); @@ -322,7 +322,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); mRenderPaint.setStyle(Paint.Style.STROKE); @@ -488,7 +488,7 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); @@ -593,7 +593,7 @@ protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float[] circlesBuffer = new float[2]; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 37a1672ac6..05f15c7e8b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -61,7 +61,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = mAnimator.getPhaseX(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); final float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); From fcd696a979f7358d1d2d1bcb1520e3863c2fa92a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 19:36:43 +0300 Subject: [PATCH 0878/1390] Allow setting xVals on Data --- .../src/com/github/mikephil/charting/data/ChartData.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 71663eb2cd..7a01996bc6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -376,6 +376,14 @@ public List getXVals() { return mXVals; } + /** + * sets the x-values the chart represents + * + */ + public void setXVals(List xVals) { + mXVals = xVals; + } + /** * Adds a new x-value to the chart data. * From b8ce47a78db5df0df17ece732fab00e7c460db7e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 19:41:13 +0300 Subject: [PATCH 0879/1390] Fixed dataset updates in demos --- .../com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 1 + .../src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java | 1 + .../mpchartexample/BarChartActivityMultiDataset.java | 1 + .../xxmassdeveloper/mpchartexample/BarChartActivitySinus.java | 1 + .../xxmassdeveloper/mpchartexample/CubicLineChartActivity.java | 1 + .../mpchartexample/HorizontalBarChartActivity.java | 1 + .../com/xxmassdeveloper/mpchartexample/LineChartActivity1.java | 1 + .../com/xxmassdeveloper/mpchartexample/LineChartActivity2.java | 1 + .../com/xxmassdeveloper/mpchartexample/StackedBarActivity.java | 1 + 9 files changed, 9 insertions(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 5d5b933f57..7e9d4b7fe3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -192,6 +192,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "Data Set"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 083d016e64..e3e0c5c9c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -252,6 +252,7 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "DataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 1229828c4d..b47103b2b2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -221,6 +221,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setYVals(yVals1); set2.setYVals(yVals2); set3.setYVals(yVals3); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { // create 3 datasets with different types diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index b7d6dfd5aa..dac4ccd2b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -230,6 +230,7 @@ private void setData(int count) { mChart.getData().getDataSetCount() > 0) { set = (BarDataSet)mChart.getData().getDataSetByIndex(0); set.setYVals(entries); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { set = new BarDataSet(entries, "Sinus Function"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 86ce89677c..a50171e710 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -289,6 +289,7 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 1dc016ac60..f186896d11 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -248,6 +248,7 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "DataSet 1"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 82e1961304..5a32612b5f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -359,6 +359,7 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 42773b649a..0d76e71813 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -318,6 +318,7 @@ private void setData(int count, float range) { set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); set1.setYVals(yVals1); set2.setYVals(yVals2); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 1f8ef92129..da46393202 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -208,6 +208,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); + mChart.getData().setXVals(xVals); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); From 215ce2d82e6530d59b046305698d852eea0e585f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 13 Apr 2016 21:50:12 +0300 Subject: [PATCH 0880/1390] Minor improvements for line rendering --- .../charting/renderer/LineChartRenderer.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 83ca529815..51fe4887d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -145,8 +145,6 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - float intensity = dataSet.getCubicIntensity(); - cubicPath.reset(); int size = (int) Math.ceil((maxx - minx) * phaseX + minx); @@ -420,7 +418,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (e1 != null) { - for (int x = count > 1 ? minx + 1 : minx, j = 0; x < count; x++) { + int j = 0; + for (int x = count > 1 ? minx + 1 : minx; x < count; x++) { e1 = dataSet.getEntryForIndex(x == 0 ? 0 : (x - 1)); e2 = dataSet.getEntryForIndex(x); @@ -441,14 +440,18 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[j++] = e2.getVal() * phaseY; } - trans.pointValuesToPixel(mLineBuffer); + if (j > 0) { + trans.pointValuesToPixel(mLineBuffer); - final int size = Math.max((count - minx - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; + final int size = + Math.max((count - minx - 1) * pointsPerEntryPair, pointsPerEntryPair) * + 2; - mRenderPaint.setColor(dataSet.getColor()); + mRenderPaint.setColor(dataSet.getColor()); - canvas.drawLines(mLineBuffer, 0, size, - mRenderPaint); + canvas.drawLines(mLineBuffer, 0, size, + mRenderPaint); + } } } From ab424e69d853a53cc39dfe48dcb7cf90d8936316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Br=C4=8Di=C4=87?= Date: Wed, 13 Apr 2016 23:54:37 +0200 Subject: [PATCH 0881/1390] potential solution to rare out of memory problems --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 5 +++++ .../github/mikephil/charting/renderer/PieChartRenderer.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 51fe4887d1..c5a7d19380 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -727,10 +727,15 @@ public Bitmap.Config getBitmapConfig() { * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. */ public void releaseBitmap() { + if (mBitmapCanvas != null) { + mBitmapCanvas.setBitmap(null); + mBitmapCanvas = null; + } if (mDrawBitmap != null) { mDrawBitmap.get().recycle(); mDrawBitmap.clear(); mDrawBitmap = null; } + System.gc(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 269b767c87..324da1441e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -919,10 +919,15 @@ protected void drawRoundedSlices(Canvas c) { * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. */ public void releaseBitmap() { + if (mBitmapCanvas != null) { + mBitmapCanvas.setBitmap(null); + mBitmapCanvas = null; + } if (mDrawBitmap != null) { mDrawBitmap.get().recycle(); mDrawBitmap.clear(); mDrawBitmap = null; } + System.gc(); } } From 6358f27f79b0b61e76370c24b8e4e5651de482cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Br=C4=8Di=C4=87?= Date: Thu, 14 Apr 2016 10:56:02 +0200 Subject: [PATCH 0882/1390] Seems that System.gc() call is not necessary --- .../com/github/mikephil/charting/renderer/LineChartRenderer.java | 1 - .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 1 - 2 files changed, 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index c5a7d19380..0691efdfb7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -736,6 +736,5 @@ public void releaseBitmap() { mDrawBitmap.clear(); mDrawBitmap = null; } - System.gc(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 324da1441e..226b925371 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -928,6 +928,5 @@ public void releaseBitmap() { mDrawBitmap.clear(); mDrawBitmap = null; } - System.gc(); } } From 6d3faca19c6a4a396404adb7f0b093d5b781a9ba Mon Sep 17 00:00:00 2001 From: "thadeu.batista" Date: Thu, 14 Apr 2016 21:28:32 -0300 Subject: [PATCH 0883/1390] teste primeiro commit --- .../com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 7e9d4b7fe3..4c25b91e7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -30,6 +30,7 @@ public class AnotherBarActivity extends DemoBase implements OnSeekBarChangeListe private BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; + private TextView teste; @Override protected void onCreate(Bundle savedInstanceState) { From 66068f5242ffe8b03c7ef28fe920d8ac39c40230 Mon Sep 17 00:00:00 2001 From: "thadeu.batista" Date: Thu, 14 Apr 2016 21:29:47 -0300 Subject: [PATCH 0884/1390] projeto pronto para ajustes --- .../com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 4c25b91e7f..7e9d4b7fe3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -30,7 +30,6 @@ public class AnotherBarActivity extends DemoBase implements OnSeekBarChangeListe private BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - private TextView teste; @Override protected void onCreate(Bundle savedInstanceState) { From 3f483b90dbc2f98084f530b39faef1501247bf6d Mon Sep 17 00:00:00 2001 From: "thadeu.batista" Date: Fri, 15 Apr 2016 23:10:20 -0300 Subject: [PATCH 0885/1390] =?UTF-8?q?ajuste=20alinhamento=20de=20labels=20?= =?UTF-8?q?da=20parte=20inferior=20do=20gr=C3=A1fico=20LineChart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/com/github/mikephil/charting/utils/Utils.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 012477c704..7a562a1546 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -532,6 +532,7 @@ public static float getNormalizedAngle(float angle) { private static Rect mDrawTextRectBuffer = new Rect(); private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics(); + private static float mLineHeight = 9999.0f; public static void drawText(Canvas c, String text, float x, float y, Paint paint, @@ -542,7 +543,10 @@ public static void drawText(Canvas c, String text, float x, float y, paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); - final float lineHeight = mDrawTextRectBuffer.height(); + if(mDrawTextRectBuffer.height() < mLineHeight){ + mLineHeight = mDrawTextRectBuffer.height(); + } + final float lineHeight = mLineHeight; // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; From 10676ea964449804723f37184e89506da1f30496 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 17 Apr 2016 23:15:42 +0200 Subject: [PATCH 0886/1390] Fixes related to example --- .../xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 1 + .../com/xxmassdeveloper/mpchartexample/BarChartActivity.java | 1 + .../mpchartexample/BarChartActivityMultiDataset.java | 4 +++- .../xxmassdeveloper/mpchartexample/BarChartActivitySinus.java | 1 + .../mpchartexample/BarChartPositiveNegative.java | 1 + .../mpchartexample/HorizontalBarChartActivity.java | 1 + .../mpchartexample/PiePolylineChartActivity.java | 2 +- .../xxmassdeveloper/mpchartexample/StackedBarActivity.java | 1 + MPChartLib/src/com/github/mikephil/charting/utils/Utils.java | 1 + 9 files changed, 11 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 7e9d4b7fe3..3918072671 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -193,6 +193,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "Data Set"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index e3e0c5c9c6..e1f266d218 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -253,6 +253,7 @@ private void setData(int count, float range) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "DataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index b47103b2b2..21990a7661 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -222,6 +222,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set2.setYVals(yVals2); set3.setYVals(yVals3); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { // create 3 datasets with different types @@ -247,8 +248,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { data.setValueTypeface(tf); mChart.setData(data); - mChart.invalidate(); } + + mChart.invalidate(); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index dac4ccd2b5..ec96bc5dfe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -231,6 +231,7 @@ private void setData(int count) { set = (BarDataSet)mChart.getData().getDataSetByIndex(0); set.setYVals(entries); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set = new BarDataSet(entries, "Sinus Function"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index e028d5d2d7..00036099cc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -114,6 +114,7 @@ private void setData(List dataList) { mChart.getData().getDataSetCount() > 0) { set = (BarDataSet)mChart.getData().getDataSetByIndex(0); set.setYVals(values); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set = new BarDataSet(values, "Values"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index f186896d11..21e5a4ef3c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -249,6 +249,7 @@ private void setData(int count, float range) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "DataSet 1"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index b475cd4abb..58f1e085ea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -71,7 +71,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); mChart.setCenterText(generateCenterSpannableText()); - mChart.setExtraOffsets(0.f, 50.f, 0.f, 50.f); + mChart.setExtraOffsets(5.f, 5.f, 5.f, 5.f); mChart.setDrawHoleEnabled(true); mChart.setHoleColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index da46393202..f0ed75bac0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -209,6 +209,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 7a562a1546..294ab5ca2e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -546,6 +546,7 @@ public static void drawText(Canvas c, String text, float x, float y, if(mDrawTextRectBuffer.height() < mLineHeight){ mLineHeight = mDrawTextRectBuffer.height(); } + final float lineHeight = mLineHeight; // Android sometimes has pre-padding From 4b3825c68d2c21e61a1f852f054b935d3dbe39a9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 17 Apr 2016 23:21:03 +0200 Subject: [PATCH 0887/1390] Revert #1684 --- .../mikephil/charting/renderer/XAxisRenderer.java | 3 +-- .../com/github/mikephil/charting/utils/Utils.java | 13 ++++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index a0a2bff642..f3e0ac40b3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -7,7 +7,6 @@ import android.graphics.Paint.Align; import android.graphics.Path; import android.graphics.PointF; -import android.util.Size; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; @@ -189,7 +188,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { protected void drawLabel(Canvas c, String label, int xIndex, float x, float y, PointF anchor, float angleDegrees) { String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex, mViewPortHandler); - Utils.drawText(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); + Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 294ab5ca2e..fa2532a30e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -532,22 +532,17 @@ public static float getNormalizedAngle(float angle) { private static Rect mDrawTextRectBuffer = new Rect(); private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics(); - private static float mLineHeight = 9999.0f; - public static void drawText(Canvas c, String text, float x, float y, - Paint paint, - PointF anchor, float angleDegrees) { + public static void drawXAxisValue(Canvas c, String text, float x, float y, + Paint paint, + PointF anchor, float angleDegrees) { float drawOffsetX = 0.f; float drawOffsetY = 0.f; paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); - if(mDrawTextRectBuffer.height() < mLineHeight){ - mLineHeight = mDrawTextRectBuffer.height(); - } - - final float lineHeight = mLineHeight; + final float lineHeight = mDrawTextRectBuffer.height(); // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; From 69d1b4d81108f3b8fca83625badaa05b90205eb8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 17 Apr 2016 23:26:01 +0200 Subject: [PATCH 0888/1390] Minor fix --- .../com/xxmassdeveloper/mpchartexample/StackedBarActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index f0ed75bac0..5e9da82af3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -223,8 +223,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { data.setValueFormatter(new MyValueFormatter()); mChart.setData(data); - mChart.invalidate(); } + + mChart.invalidate(); } @Override From a3e4450c74329306cc8c86a73215944e485dad5e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 1 May 2016 21:45:53 +0300 Subject: [PATCH 0889/1390] More reusable Realm data builder --- .../data/realm/base/RealmBaseDataSet.java | 23 +++++++++-- .../realm/base/RealmLineRadarDataSet.java | 24 ----------- .../realm/implementation/RealmBarDataSet.java | 40 ++++++++++--------- .../implementation/RealmBubbleDataSet.java | 26 ++++-------- .../implementation/RealmCandleDataSet.java | 31 +++++--------- .../implementation/RealmLineDataSet.java | 5 --- .../realm/implementation/RealmPieDataSet.java | 24 ----------- .../implementation/RealmRadarDataSet.java | 5 --- .../implementation/RealmScatterDataSet.java | 24 ----------- 9 files changed, 58 insertions(+), 144 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 02b769e8ac..20673e62e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.data.realm.base; +import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -7,6 +8,7 @@ import java.util.ArrayList; import java.util.List; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; import io.realm.Sort; @@ -75,7 +77,20 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn /** * Rebuilds the DataSet based on the given RealmResults. */ - public abstract void build(RealmResults results); + public void build(RealmResults results) { + + int xIndex = 0; + for (T object : results) { + mValues.add(buildEntryFromResultObject(object, xIndex++)); + } + } + + public S buildEntryFromResultObject(T realmObject, int xIndex) { + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); + + return (S)new Entry(dynamicObject.getFloat(mValuesField), + mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + } @Override public float getYMin() { @@ -167,14 +182,16 @@ public int getEntryIndex(int x, DataSet.Rounding rounding) { while (low <= high) { int m = (high + low) / 2; - if (x == mValues.get(m).getXIndex()) { + S entry = mValues.get(m); + + if (x == entry.getXIndex()) { while (m > 0 && mValues.get(m - 1).getXIndex() == x) m--; return m; } - if (x > mValues.get(m).getXIndex()) + if (x > entry.getXIndex()) low = m + 1; else high = m - 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index f8ea4df17d..31010f2489 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -47,30 +47,6 @@ public RealmLineRadarDataSet(RealmResults results, String yValuesField, Strin super(results, yValuesField, xIndexField); } - @Override - public void build(RealmResults results) { - - if (mIndexField == null) { // x-index not available - - int xIndex = 0; - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), xIndex)); - xIndex++; - } - - } else { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); - } - } - } - @Override public int getFillColor() { return mFillColor; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 5fde69a4bd..f062db7be3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -3,10 +3,12 @@ import android.graphics.Color; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import io.realm.DynamicRealmObject; +import io.realm.RealmFieldType; import io.realm.RealmList; import io.realm.RealmObject; import io.realm.RealmResults; @@ -78,31 +80,33 @@ public RealmBarDataSet(RealmResults results, String yValuesField, String xInd @Override public void build(RealmResults results) { - for (T realmObject : results) { + super.build(results); - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - try { // normal entry + calcStackSize(); + } - float value = dynamicObject.getFloat(mValuesField); - mValues.add(new BarEntry(value, dynamicObject.getInt(mIndexField))); + @Override + public BarEntry buildEntryFromResultObject(T realmObject, int xIndex) { + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - } catch (IllegalArgumentException e) { // stacked entry + if (dynamicObject.getFieldType(mValuesField) == RealmFieldType.LIST) { - RealmList list = dynamicObject.getList(mValuesField); - float[] values = new float[list.size()]; + RealmList list = dynamicObject.getList(mValuesField); + float[] values = new float[list.size()]; - int i = 0; - for (DynamicRealmObject o : list) { - values[i] = o.getFloat(mStackValueFieldName); - i++; - } - - mValues.add(new BarEntry(values, dynamicObject.getInt(mIndexField))); + int i = 0; + for (DynamicRealmObject o : list) { + values[i] = o.getFloat(mStackValueFieldName); + i++; } - } - calcStackSize(); + return new BarEntry(values, + mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + } else { + float value = dynamicObject.getFloat(mValuesField); + return new BarEntry(value, + mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index d6e50ab85b..a69276ade4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Utils; @@ -55,26 +56,13 @@ public RealmBubbleDataSet(RealmResults result, String yValuesField, String xI } @Override - public void build(RealmResults results) { + public BubbleEntry buildEntryFromResultObject(T realmObject, int xIndex) { + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - if(mIndexField == null) { - - int xIndex = 0; - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new BubbleEntry(xIndex, dynamicObject.getFloat(mValuesField), dynamicObject.getFloat(mSizeField))); - xIndex++; - } - } else { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new BubbleEntry(dynamicObject.getInt(mIndexField), dynamicObject.getFloat(mValuesField), dynamicObject.getFloat(mSizeField))); - } - } + return new BubbleEntry( + mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField), + dynamicObject.getFloat(mValuesField), + dynamicObject.getFloat(mSizeField)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index def4e4e935..9cc1d3c4c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -3,6 +3,7 @@ import android.graphics.Paint; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -119,29 +120,15 @@ public RealmCandleDataSet(RealmResults result, String highField, String lowFi calcMinMax(0, this.results.size()); } - @Override - public void build(RealmResults results) { - - if (mIndexField == null) { - - int xIndex = 0; - - for (T object : results) { + public CandleEntry buildEntryFromResultObject(T realmObject, int xIndex) { + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new CandleEntry(xIndex, dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), - dynamicObject.getFloat(mOpenField), dynamicObject.getFloat(mCloseField))); - xIndex++; - } - } else { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new CandleEntry(dynamicObject.getInt(mIndexField), dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), - dynamicObject.getFloat(mOpenField), dynamicObject.getFloat(mCloseField))); - } - } + return new CandleEntry( + mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField), + dynamicObject.getFloat(mHighField), + dynamicObject.getFloat(mLowField), + dynamicObject.getFloat(mOpenField), + dynamicObject.getFloat(mCloseField)); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index c1ab855b0e..b8832271af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -99,11 +99,6 @@ public RealmLineDataSet(RealmResults result, String yValuesField, String xInd calcMinMax(0, results.size()); } - @Override - public void build(RealmResults results) { - super.build(results); - } - /** * Returns the drawing mode for this line dataset * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 7be50e7c64..35479f3637 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -61,30 +61,6 @@ public RealmPieDataSet(RealmResults result, String yValuesField, String xInde calcMinMax(0, results.size()); } - @Override - public void build(RealmResults results) { - - if (mIndexField == null) { // x-index not available - - int xIndex = 0; - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), xIndex)); - xIndex++; - } - - } else { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); - } - } - } - /** * Sets the space that is left out between the piechart-slices in dp. * Default: 0 --> no space, maximum 20f diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index aa2dc2fdfc..31957f93e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -138,9 +138,4 @@ public void setHighlightCircleStrokeWidth(float strokeWidth) { mHighlightCircleStrokeWidth = strokeWidth; } - - @Override - public void build(RealmResults results) { - super.build(results); - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index c895bc09ec..88bbc01dc6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -67,30 +67,6 @@ public RealmScatterDataSet(RealmResults result, String yValuesField, String x calcMinMax(0, results.size()); } - @Override - public void build(RealmResults results) { - - if (mIndexField == null) { // x-index not available - - int xIndex = 0; - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), xIndex)); - xIndex++; - } - - } else { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); - } - } - } - /** * Sets the size in density pixels the drawn scattershape will have. This * only applies for non custom shapes. From a002634d490e15e94984735b27a3afe11c4435c2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 1 May 2016 21:46:04 +0300 Subject: [PATCH 0890/1390] Highlight enhancements There are certain cases (ie. bubbles) which make sense to have multiple values per xIndex. This fixes that - and adds more granular highlight for Combined Chart. --- .../mikephil/charting/charts/Chart.java | 22 +++- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/data/ChartData.java | 16 ++- .../mikephil/charting/data/CombinedData.java | 34 ++++++ .../mikephil/charting/data/DataSet.java | 27 ++++- .../data/realm/base/RealmBaseDataSet.java | 33 +++++ .../charting/highlight/BarHighlighter.java | 113 ++++++++++++------ .../charting/highlight/ChartHighlighter.java | 54 +++++---- .../highlight/CombinedHighlighter.java | 24 ++-- .../charting/highlight/Highlight.java | 75 +++++++++--- .../highlight/HorizontalBarHighlighter.java | 47 +++++--- .../interfaces/datasets/IDataSet.java | 28 ++++- .../charting/listener/ChartTouchListener.java | 4 +- .../listener/PieRadarChartTouchListener.java | 6 +- .../renderer/BubbleChartRenderer.java | 8 +- .../renderer/CombinedChartRenderer.java | 41 ++++++- .../charting/renderer/LineChartRenderer.java | 2 +- .../renderer/ScatterChartRenderer.java | 2 +- .../charting/utils/SelectionDetail.java | 18 ++- .../github/mikephil/charting/utils/Utils.java | 87 ++++++++++++-- 20 files changed, 499 insertions(+), 144 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 0c837bb1ff..82a277f8ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -556,15 +556,24 @@ public void highlightValues(Highlight[] highs) { * @param dataSetIndex */ public void highlightValue(int xIndex, int dataSetIndex) { + highlightValue(xIndex, dataSetIndex, true); + } + + /** + * Highlights the value at the given x-index in the given DataSet. Provide + * -1 as the x-index or dataSetIndex to undo all highlighting. + * + * @param xIndex + * @param dataSetIndex + */ + public void highlightValue(int xIndex, int dataSetIndex, boolean callListener) { if (xIndex < 0 || dataSetIndex < 0 || xIndex >= mData.getXValCount() || dataSetIndex >= mData.getDataSetCount()) { - highlightValues(null); + highlightValue(null, callListener); } else { - highlightValues(new Highlight[]{ - new Highlight(xIndex, dataSetIndex) - }); + highlightValue(new Highlight(xIndex, dataSetIndex), callListener); } } @@ -598,7 +607,10 @@ public void highlightValue(Highlight high, boolean callListener) { Log.i(LOG_TAG, "Highlighted: " + high.toString()); e = mData.getEntryForHighlight(high); - if (e == null || e.getXIndex() != high.getXIndex()) { + if (e == null || + e.getXIndex() != high.getXIndex() || + (!Float.isNaN(high.getValue()) && + e.getVal() != high.getValue())) { mIndicesToHighlight = null; high = null; } else { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 5a938872cf..9c31414ced 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -459,7 +459,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { // extract all y-values from all DataSets at the given x-index final float yVal = dataSet.getYValForXIndex(xIndex); - if (yVal == Float.NaN) + if (Float.isNaN(yVal)) continue; vals.add(new SelectionDetail(yVal, i, dataSet)); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 7a01996bc6..770afd5808 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -472,9 +472,19 @@ protected String[] getDataSetLabels() { public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= mDataSets.size()) return null; - else - return mDataSets.get(highlight.getDataSetIndex()).getEntryForXIndex( - highlight.getXIndex()); + else { + // The value of the highlighted entry could be NaN - + // if we are not interested in highlighting a specific value. + + List entries = mDataSets.get(highlight.getDataSetIndex()) + .getEntriesForXIndex(highlight.getXIndex()); + for (Object entry : entries) + if (((Entry)entry).getVal() == highlight.getValue() || + Float.isNaN(highlight.getValue())) + return (Entry)entry; + + return null; + } } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 2d7982265d..507e14434b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import java.util.ArrayList; @@ -118,4 +119,37 @@ public void notifyDataChanged() { init(); // recalculate everything } + + /** + * Get the Entry for a corresponding highlight object + * + * @param highlight + * @return the entry that is highlighted + */ + @Override + public Entry getEntryForHighlight(Highlight highlight) { + + List dataObjects = getAllData(); + + if (highlight.getDataIndex() >= dataObjects.size()) + return null; + + ChartData data = dataObjects.get(highlight.getDataIndex()); + + if (highlight.getDataSetIndex() >= data.getDataSetCount()) + return null; + else { + // The value of the highlighted entry could be NaN - + // if we are not interested in highlighting a specific value. + + List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) + .getEntriesForXIndex(highlight.getXIndex()); + for (Object entry : entries) + if (((Entry)entry).getVal() == highlight.getValue() || + Float.isNaN(highlight.getValue())) + return (Entry)entry; + + return null; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 3e2926cf9e..5b37a296ce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -312,6 +312,20 @@ public float getYValForXIndex(int xIndex) { return Float.NaN; } + @Override + public float[] getYValsForXIndex(int xIndex) { + + List entries = getEntriesForXIndex(xIndex); + + float[] yVals = new float[entries.size()]; + int i = 0; + + for (T e : entries) + yVals[i++] = e.getVal(); + + return yVals; + } + /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical @@ -320,6 +334,7 @@ public float getYValForXIndex(int xIndex) { * @param xIndex * @return */ + @Override public List getEntriesForXIndex(int xIndex) { List entries = new ArrayList(); @@ -344,12 +359,14 @@ public List getEntriesForXIndex(int xIndex) { break; } } - } - if (xIndex > entry.getXIndex()) - low = m + 1; - else - high = m - 1; + break; + } else { + if (xIndex > entry.getXIndex()) + low = m + 1; + else + high = m - 1; + } } return entries; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 20673e62e5..3fa603778d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -165,6 +165,25 @@ public S getEntryForXIndex(int xIndex, DataSet.Rounding rounding) { return null; } + @Override + public List getEntriesForXIndex(int xIndex) { + + List entries = new ArrayList<>(); + + if (mIndexField == null) { + T object = results.get(xIndex); + if (object != null) + entries.add(buildEntryFromResultObject(object, xIndex)); + } else { + RealmResults foundObjects = results.where().equalTo(mIndexField, xIndex).findAll(); + + for (T e : foundObjects) + entries.add(buildEntryFromResultObject(e, xIndex)); + } + + return entries; + } + @Override public S getEntryForIndex(int index) { //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); @@ -231,6 +250,20 @@ public float getYValForXIndex(int xIndex) { return Float.NaN; } + @Override + public float[] getYValsForXIndex(int xIndex) { + + List entries = getEntriesForXIndex(xIndex); + + float[] yVals = new float[entries.size()]; + int i = 0; + + for (S e : entries) + yVals[i++] = e.getVal(); + + return yVals; + } + @Override public boolean addEntry(S e) { diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index a852aa041c..4017e3eb1d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -1,9 +1,12 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.SelectionDetail; /** * Created by Philipp Jahoda on 22/07/15. @@ -17,27 +20,44 @@ public BarHighlighter(BarDataProvider chart) { @Override public Highlight getHighlight(float x, float y) { - Highlight h = super.getHighlight(x, y); + BarData barData = mChart.getBarData(); - if (h == null) - return h; - else { + final int xIndex = getXIndex(x); + final float baseNoSpace = getBase(x); + final int setCount = barData.getDataSetCount(); + int dataSetIndex = ((int)baseNoSpace) % setCount; - IBarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + if (dataSetIndex < 0) { + dataSetIndex = 0; + } else if (dataSetIndex >= setCount) { + dataSetIndex = setCount - 1; + } + + SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, dataSetIndex); + if (selectionDetail == null) + return null; - if (set.isStacked()) { + IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + if (set.isStacked()) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = y; + float[] pts = new float[2]; + pts[1] = y; - // take any transformer to determine the x-axis value - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[1]); - } else - return h; + return getStackedHighlight(selectionDetail, + set, + xIndex, + pts[1]); } + + return new Highlight( + xIndex, + selectionDetail.value, + selectionDetail.dataIndex, + selectionDetail.dataSetIndex, + -1); } @Override @@ -64,51 +84,68 @@ else if (xIndex >= valCount) } @Override - protected int getDataSetIndex(int xIndex, float x, float y) { + protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetIndex) { - if (!mChart.getBarData().isGrouped()) { - return 0; - } else { + dataSetIndex = Math.max(dataSetIndex, 0); - float baseNoSpace = getBase(x); + BarData barData = mChart.getBarData(); + IDataSet dataSet = barData.getDataSetCount() > dataSetIndex + ? barData.getDataSetByIndex(dataSetIndex) + : null; + if (dataSet == null) + return null; - int setCount = mChart.getBarData().getDataSetCount(); - int dataSetIndex = (int) baseNoSpace % setCount; + final float yValue = dataSet.getYValForXIndex(xIndex); - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; + if (yValue == Double.NaN) return null; - return dataSetIndex; - } + return new SelectionDetail( + yValue, + dataSetIndex, + dataSet); } /** * This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected. * - * @param old - * the old highlight object before looking for stacked values + * @param selectionDetail the selection detail to work with looking for stacked values * @param set * @param xIndex - * @param dataSetIndex * @param yValue * @return */ - protected Highlight getStackedHighlight(Highlight old, IBarDataSet set, int xIndex, int dataSetIndex, double yValue) { + protected Highlight getStackedHighlight( + SelectionDetail selectionDetail, + IBarDataSet set, + int xIndex, + double yValue) { BarEntry entry = set.getEntryForXIndex(xIndex); - if (entry == null || entry.getVals() == null) - return old; + if (entry == null) + return null; + + if (entry.getVals() == null) { + return new Highlight(xIndex, + entry.getVal(), + selectionDetail.dataIndex, + selectionDetail.dataSetIndex); + } Range[] ranges = getRanges(entry); - int stackIndex = getClosestStackIndex(ranges, (float) yValue); + if (ranges.length > 0) { + int stackIndex = getClosestStackIndex(ranges, (float)yValue); + return new Highlight( + xIndex, + entry.getPositiveSum() - entry.getNegativeSum(), + selectionDetail.dataIndex, + selectionDetail.dataSetIndex, + stackIndex, + ranges[stackIndex] + ); + } - if(ranges.length > 0) - return new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); - else - return null; + return null; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index 04ee9bec11..6195abe810 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -31,14 +31,15 @@ public ChartHighlighter(T chart) { public Highlight getHighlight(float x, float y) { int xIndex = getXIndex(x); - if (xIndex == -Integer.MAX_VALUE) - return null; - int dataSetIndex = getDataSetIndex(xIndex, x, y); - if (dataSetIndex == -Integer.MAX_VALUE) + SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, -1); + if (selectionDetail == null) return null; - return new Highlight(xIndex, dataSetIndex); + return new Highlight(xIndex, + selectionDetail.value, + selectionDetail.dataIndex, + selectionDetail.dataSetIndex); } /** @@ -60,40 +61,48 @@ protected int getXIndex(float x) { } /** - * Returns the corresponding dataset-index for a given xIndex and xy-touch position in pixels. + * Returns the corresponding SelectionDetail for a given xIndex and y-touch position in pixels. * * @param xIndex - * @param x * @param y + * @param dataSetIndex * @return */ - protected int getDataSetIndex(int xIndex, float x, float y) { + protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetIndex) { - List valsAtIndex = getSelectionDetailsAtIndex(xIndex); + List valsAtIndex = getSelectionDetailsAtIndex(xIndex, dataSetIndex); float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); + SelectionDetail detail = Utils.getClosestSelectionDetailByPixelY(valsAtIndex, y, axis); - return dataSetIndex; + return detail; } /** * Returns a list of SelectionDetail object corresponding to the given xIndex. - * + * * @param xIndex + * @param dataSetIndex dataSet index to look at. -1 if unspecified. * @return */ - protected List getSelectionDetailsAtIndex(int xIndex) { + protected List getSelectionDetailsAtIndex(int xIndex, int dataSetIndex) { List vals = new ArrayList(); + if (mChart.getData() == null) return vals; + float[] pts = new float[2]; - for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); + i < dataSetCount; + i++) { + + if (dataSetIndex > -1 && dataSetIndex != i) + continue; IDataSet dataSet = mChart.getData().getDataSetByIndex(i); @@ -102,16 +111,19 @@ protected List getSelectionDetailsAtIndex(int xIndex) { continue; // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValForXIndex(xIndex); - if (yVal == Float.NaN) - continue; + final float[] yVals = dataSet.getYValsForXIndex(xIndex); + for (float yVal : yVals) { + if (Float.isNaN(yVal)) + continue; - pts[1] = yVal; + pts[1] = yVal; - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], i, dataSet)); + if (!Float.isNaN(pts[1])) + { + vals.add(new SelectionDetail(pts[1], yVal, i, dataSet)); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 25ffb1f334..4957028efe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -25,17 +25,16 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { * @return */ @Override - protected List getSelectionDetailsAtIndex(int xIndex) { + protected List getSelectionDetailsAtIndex(int xIndex, int dataSetIndex) { + + List vals = new ArrayList(); + float[] pts = new float[2]; CombinedData data = (CombinedData) mChart.getData(); // get all chartdata objects List dataObjects = data.getAllData(); - List vals = new ArrayList(); - - float[] pts = new float[2]; - for (int i = 0; i < dataObjects.size(); i++) { for(int j = 0; j < dataObjects.get(i).getDataSetCount(); j++) { @@ -47,16 +46,15 @@ protected List getSelectionDetailsAtIndex(int xIndex) { continue; // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValForXIndex(xIndex); - if (yVal == Float.NaN) - continue; - - pts[1] = yVal; + final float yVals[] = dataSet.getYValsForXIndex(xIndex); + for (float yVal : yVals) { + pts[1] = yVal; - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], j, dataSet)); + if (!Float.isNaN(pts[1])) { + vals.add(new SelectionDetail(pts[1], yVal, i, j, dataSet)); + } } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java index 07ae315eb1..7ebd5d0193 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java @@ -11,6 +11,12 @@ public class Highlight { /** the x-index of the highlighted value */ private int mXIndex; + /** the y-value of the highlighted value */ + private float mValue = Float.NaN; + + /** the index of the data object - in case it refers to more than one */ + private int mDataIndex; + /** the index of the dataset the highlighted value is in */ private int mDataSetIndex; @@ -22,25 +28,30 @@ public class Highlight { /** * constructor - * + * * @param x the index of the highlighted value on the x-axis - * @param dataSet the index of the DataSet the highlighted value belongs to + * @param value the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ - public Highlight(int x, int dataSet) { + public Highlight(int x, float value, int dataIndex, int dataSetIndex) { this.mXIndex = x; - this.mDataSetIndex = dataSet; + this.mValue = value; + this.mDataIndex = dataIndex; + this.mDataSetIndex = dataSetIndex; } - /** * Constructor, only used for stacked-barchart. * * @param x the index of the highlighted value on the x-axis - * @param dataSet the index of the DataSet the highlighted value belongs to + * @param value the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected */ - public Highlight(int x, int dataSet, int stackIndex) { - this(x, dataSet); + public Highlight(int x, float value, int dataIndex, int dataSetIndex, int stackIndex) { + this(x, value, dataIndex, dataSetIndex); mStackIndex = stackIndex; } @@ -48,34 +59,64 @@ public Highlight(int x, int dataSet, int stackIndex) { * Constructor, only used for stacked-barchart. * * @param x the index of the highlighted value on the x-axis - * @param dataSet the index of the DataSet the highlighted value belongs to + * @param value the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected * @param range the range the selected stack-value is in */ - public Highlight(int x, int dataSet, int stackIndex, Range range) { - this(x, dataSet, stackIndex); + public Highlight(int x, float value, int dataIndex, int dataSetIndex, int stackIndex, Range range) { + this(x, value, dataIndex, dataSetIndex, stackIndex); this.mRange = range; } /** - * returns the index of the DataSet the highlighted value is in - * - * @return + * Constructor, only used for stacked-barchart. + * + * @param x the index of the highlighted value on the x-axis + * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ - public int getDataSetIndex() { - return mDataSetIndex; + public Highlight(int x, int dataSetIndex) { + this(x, Float.NaN, 0, dataSetIndex, -1); } /** * returns the index of the highlighted value on the x-axis - * + * * @return */ public int getXIndex() { return mXIndex; } + /** + * returns the y-value of the highlighted value + * + * @return + */ + public float getValue() { + return mValue; + } + + /** + * the index of the data object - in case it refers to more than one + * + * @return + */ + public int getDataIndex() { + return mDataIndex; + } + + /** + * returns the index of the DataSet the highlighted value is in + * + * @return + */ + public int getDataSetIndex() { + return mDataSetIndex; + } + /** * Only needed if a stacked-barchart entry was highlighted. References the * selected value within the stacked-entry. diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 1930409a1b..cdd6387cd8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,8 +1,10 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.utils.SelectionDetail; /** * Created by Philipp Jahoda on 22/07/15. @@ -16,27 +18,44 @@ public HorizontalBarHighlighter(BarDataProvider chart) { @Override public Highlight getHighlight(float x, float y) { - Highlight h = super.getHighlight(x, y); + BarData barData = mChart.getBarData(); - if (h == null) - return h; - else { + final int xIndex = getXIndex(x); + final float baseNoSpace = getBase(x); + final int setCount = barData.getDataSetCount(); + int dataSetIndex = ((int)baseNoSpace) % setCount; - IBarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + if (dataSetIndex < 0) { + dataSetIndex = 0; + } else if (dataSetIndex >= setCount) { + dataSetIndex = setCount - 1; + } - if (set.isStacked()) { + SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, dataSetIndex); + if (selectionDetail == null) + return null; - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = y; + IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + if (set.isStacked()) { - // take any transformer to determine the x-axis value - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + float[] pts = new float[2]; + pts[0] = y; - return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[0]); - } else - return h; + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + + return getStackedHighlight(selectionDetail, + set, + xIndex, + pts[0]); } + + return new Highlight( + xIndex, + selectionDetail.value, + selectionDetail.dataIndex, + selectionDetail.dataSetIndex, + -1); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 38ea9484c2..ab237f647f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -54,9 +54,10 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xIndex + * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - T getEntryForXIndex(int xIndex); + T getEntryForXIndex(int xIndex, DataSet.Rounding rounding); /** * Returns the first Entry object found at the given xIndex with binary @@ -66,10 +67,20 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xIndex - * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - T getEntryForXIndex(int xIndex, DataSet.Rounding rounding); + T getEntryForXIndex(int xIndex); + + /** + * Returns all Entry objects found at the given xIndex with binary + * search. An empty array if no Entry object at that index. + * INFORMATION: This method does calculations at runtime. Do + * not over-use in performance critical situations. + * + * @param xIndex + * @return + */ + List getEntriesForXIndex(int xIndex); /** * Returns the Entry object found at the given index (NOT xIndex) in the values array. @@ -112,6 +123,17 @@ public interface IDataSet { */ float getYValForXIndex(int xIndex); + /** + * Returns all of the y values of the Entry objects at the given xIndex. Returns + * Float.NaN if no value is at the given x-index. INFORMATION: This method + * does calculations at runtime. Do not over-use in performance critical + * situations. + * + * @param xIndex + * @return + */ + float[] getYValsForXIndex(int xIndex); + /** * This method returns the actual * index in the Entry array of the DataSet for a given xIndex. IMPORTANT: This method does diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java index eef16c8460..75c8e864b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -118,11 +118,11 @@ public ChartGesture getLastGesture() { protected void performHighlight(Highlight h, MotionEvent e) { if (h == null || h.equalTo(mLastHighlighted)) { - mChart.highlightTouch(null); + mChart.highlightValue(null, true); mLastHighlighted = null; } else { + mChart.highlightValue(h, true); mLastHighlighted = h; - mChart.highlightTouch(h); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 9163c823d8..d40e2fdb4e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -192,8 +192,10 @@ public boolean onSingleTapUp(MotionEvent e) { // has one DataSet) if (mChart instanceof RadarChart) { - dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, distance - / ((RadarChart) mChart).getFactor(), null); + dataSetIndex = Utils.getClosestDataSetIndexByValue( + valsAtIndex, + distance / ((RadarChart) mChart).getFactor(), + null); } if (dataSetIndex < 0) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 1988aa7692..cb978c6fbc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -204,16 +204,16 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (dataSet == null || !dataSet.isHighlightEnabled()) continue; + final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); + if (entry == null || entry.getXIndex() != indice.getXIndex()) + continue; + BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = dataSet.getEntryIndex(entryFrom); int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); - final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); - if (entry == null || entry.getXIndex() != indice.getXIndex()) - continue; - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); sizeBuffer[0] = 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 6a1b2e518a..4b01d48753 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -3,12 +3,16 @@ import android.graphics.Canvas; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -22,9 +26,11 @@ public class CombinedChartRenderer extends DataRenderer { */ protected List mRenderers; + protected WeakReference mChart; + public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); - + mChart = new WeakReference(chart); createRenderers(chart, animator, viewPortHandler); } @@ -99,8 +105,37 @@ public void drawExtras(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - for (DataRenderer renderer : mRenderers) - renderer.drawHighlighted(c, indices); + + Chart chart = mChart.get(); + if (chart == null) return; + + for (DataRenderer renderer : mRenderers) { + ChartData data = null; + + if (renderer instanceof BarChartRenderer) + data = ((BarChartRenderer)renderer).mChart.getBarData(); + else if (renderer instanceof LineChartRenderer) + data = ((LineChartRenderer)renderer).mChart.getLineData(); + else if (renderer instanceof CandleStickChartRenderer) + data = ((CandleStickChartRenderer)renderer).mChart.getCandleData(); + else if (renderer instanceof ScatterChartRenderer) + data = ((ScatterChartRenderer)renderer).mChart.getScatterData(); + else if (renderer instanceof BubbleChartRenderer) + data = ((BubbleChartRenderer)renderer).mChart.getBubbleData(); + + int dataIndex = data == null + ? -1 + : ((CombinedData)chart.getData()).getAllData().indexOf(data); + + ArrayList dataIndices = new ArrayList<>(); + for (Highlight h : indices) { + if (h.getDataIndex() == dataIndex) + dataIndices.add(h); + } + + renderer.drawHighlighted(c, dataIndices.toArray(new Highlight[dataIndices.size()])); + + } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 0691efdfb7..442fe541dd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -684,7 +684,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; final float yVal = set.getYValForXIndex(xIndex); - if (yVal == Float.NaN) + if (Float.isNaN(yVal)) continue; float y = yVal * mAnimator.getPhaseY(); // get diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 05f15c7e8b..684c6701f7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -392,7 +392,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; final float yVal = set.getYValForXIndex(xIndex); - if (yVal == Float.NaN) + if (Float.isNaN(yVal)) continue; float y = yVal * mAnimator.getPhaseY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java index 1704eefeb8..5f78528f4c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java @@ -12,13 +12,25 @@ */ public class SelectionDetail { - public float val; + public float y; + public float value; + public int dataIndex; public int dataSetIndex; public IDataSet dataSet; - public SelectionDetail(float val, int dataSetIndex, IDataSet set) { - this.val = val; + public SelectionDetail(float y, float value, int dataIndex, int dataSetIndex, IDataSet set) { + this.y = y; + this.value = value; + this.dataIndex = dataIndex; this.dataSetIndex = dataSetIndex; this.dataSet = set; } + + public SelectionDetail(float y, float value, int dataSetIndex, IDataSet set) { + this(y, value, 0, dataSetIndex, set); + } + + public SelectionDetail(float value, int dataSetIndex, IDataSet set) { + this(Float.NaN, value, 0, dataSetIndex, set); + } } \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index fa2532a30e..9f342c7dce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -388,10 +388,80 @@ public static double nextUp(double d) { * @param valsAtIndex all the values at a specific index * @return */ - public static int getClosestDataSetIndex(List valsAtIndex, float val, + public static int getClosestDataSetIndexByValue(List valsAtIndex, float value, AxisDependency axis) { - int index = -Integer.MAX_VALUE; + SelectionDetail sel = getClosestSelectionDetailByValue(valsAtIndex, value, axis); + + if (sel == null) + return -Integer.MAX_VALUE; + + return sel.dataSetIndex; + } + + /** + * Returns the index of the DataSet that contains the closest value on the + * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. + * + * @param valsAtIndex all the values at a specific index + * @return + */ + public static int getClosestDataSetIndexByPixelY(List valsAtIndex, float y, + AxisDependency axis) { + + SelectionDetail sel = getClosestSelectionDetailByPixelY(valsAtIndex, y, axis); + + if (sel == null) + return -Integer.MAX_VALUE; + + return sel.dataSetIndex; + } + + /** + * Returns the SelectionDetail of the DataSet that contains the closest value on the + * y-axis. + * + * @param valsAtIndex all the values at a specific index + * @return + */ + public static SelectionDetail getClosestSelectionDetailByValue( + List valsAtIndex, + float value, + AxisDependency axis) { + + SelectionDetail closest = null; + float distance = Float.MAX_VALUE; + + for (int i = 0; i < valsAtIndex.size(); i++) { + + SelectionDetail sel = valsAtIndex.get(i); + + if (axis == null || sel.dataSet.getAxisDependency() == axis) { + + float cdistance = Math.abs(sel.value - value); + if (cdistance < distance) { + closest = sel; + distance = cdistance; + } + } + } + + return closest; + } + + /** + * Returns the SelectionDetail of the DataSet that contains the closest value on the + * y-axis. + * + * @param valsAtIndex all the values at a specific index + * @return + */ + public static SelectionDetail getClosestSelectionDetailByPixelY( + List valsAtIndex, + float y, + AxisDependency axis) { + + SelectionDetail closest = null; float distance = Float.MAX_VALUE; for (int i = 0; i < valsAtIndex.size(); i++) { @@ -400,15 +470,15 @@ public static int getClosestDataSetIndex(List valsAtIndex, floa if (axis == null || sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs((float) sel.val - val); + float cdistance = Math.abs(sel.y - y); if (cdistance < distance) { - index = valsAtIndex.get(i).dataSetIndex; + closest = sel; distance = cdistance; } } } - return index; + return closest; } /** @@ -416,11 +486,12 @@ public static int getClosestDataSetIndex(List valsAtIndex, floa * closest y-value (in pixels) that is displayed in the chart. * * @param valsAtIndex - * @param val + * @param y * @param axis * @return */ - public static float getMinimumDistance(List valsAtIndex, float val, + public static float getMinimumDistance(List valsAtIndex, + float y, AxisDependency axis) { float distance = Float.MAX_VALUE; @@ -431,7 +502,7 @@ public static float getMinimumDistance(List valsAtIndex, float if (sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs(sel.val - val); + float cdistance = Math.abs(sel.y - y); if (cdistance < distance) { distance = cdistance; } From 6a72ab8c189608536045568fff85d22e2149be04 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 8 May 2016 20:43:15 +0300 Subject: [PATCH 0891/1390] Added feature `highlightFullBar` for highlighting all values at xIndex This also provides backwards-compatibility for old behaviour of Combined chart NOTE: The drawHighlight code was just indented and wrapped in a loop over datasets. --- .../charting/charts/BarLineChartBase.java | 22 ++++ .../mikephil/charting/charts/Chart.java | 9 +- .../charting/charts/CombinedChart.java | 3 + .../charting/renderer/BarChartRenderer.java | 115 ++++++++++-------- .../renderer/BubbleChartRenderer.java | 100 ++++++++------- .../renderer/CandleStickChartRenderer.java | 52 ++++---- .../renderer/CombinedChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 57 +++++---- .../renderer/ScatterChartRenderer.java | 52 +++++--- 9 files changed, 254 insertions(+), 158 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 2c70824d12..0a7030f901 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -80,6 +80,11 @@ public abstract class BarLineChartBase= 0 - && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { + Transformer trans = mChart.getTransformer(set.getAxisDependency()); - BarEntry e = set.getEntryForXIndex(index); + mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setAlpha(set.getHighLightAlpha()); - if (e == null || e.getXIndex() != index) - continue; + int index = high.getXIndex(); - float groupspace = mChart.getBarData().getGroupSpace(); - boolean isStack = h.getStackIndex() < 0 ? false : true; + // check outofbounds + if (index >= 0 + && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { - // calculate the correct x-position - float x = index * setCount + dataSetIndex + groupspace / 2f - + groupspace * index; + BarEntry e = set.getEntryForXIndex(index); - final float y1; - final float y2; + if (e == null || e.getXIndex() != index) + continue; - if (isStack) { - y1 = h.getRange().from; - y2 = h.getRange().to; - } else { - y1 = e.getVal(); - y2 = 0.f; - } + float groupspace = barData.getGroupSpace(); + boolean isStack = high.getStackIndex() < 0 ? false : true; - prepareBarHighlight(x, y1, y2, barspaceHalf, trans); + // calculate the correct x-position + float x = index * setCount + dataSetIndex + groupspace / 2f + + groupspace * index; - c.drawRect(mBarRect, mHighlightPaint); + final float y1; + final float y2; - if (mChart.isDrawHighlightArrowEnabled()) { + if (isStack) { + y1 = high.getRange().from; + y2 = high.getRange().to; + } else { + y1 = e.getVal(); + y2 = 0.f; + } + + prepareBarHighlight(x, y1, y2, barspaceHalf, trans); + + c.drawRect(mBarRect, mHighlightPaint); - mHighlightPaint.setAlpha(255); + if (mChart.isDrawHighlightArrowEnabled()) { - // distance between highlight arrow and bar - float offsetY = mAnimator.getPhaseY() * 0.07f; + mHighlightPaint.setAlpha(255); - float[] values = new float[9]; - trans.getPixelToValueMatrix().getValues(values); - final float xToYRel = Math.abs(values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); + // distance between highlight arrow and bar + float offsetY = mAnimator.getPhaseY() * 0.07f; - final float arrowWidth = set.getBarSpace() / 2.f; - final float arrowHeight = arrowWidth * xToYRel; + float[] values = new float[9]; + trans.getPixelToValueMatrix().getValues(values); + final float xToYRel = Math.abs( + values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); - final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); + final float arrowWidth = set.getBarSpace() / 2.f; + final float arrowHeight = arrowWidth * xToYRel; - Path arrow = new Path(); - arrow.moveTo(x + 0.4f, yArrow + offsetY); - arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); - arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); + final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); - trans.pathValueToPixel(arrow); - c.drawPath(arrow, mHighlightPaint); + Path arrow = new Path(); + arrow.moveTo(x + 0.4f, yArrow + offsetY); + arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); + arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); + + trans.pathValueToPixel(arrow); + c.drawPath(arrow, mHighlightPaint); + } } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index cb978c6fbc..3289a6bc6a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -197,66 +198,83 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - for (Highlight indice : indices) { + for (Highlight high : indices) { - IBubbleDataSet dataSet = bubbleData.getDataSetByIndex(indice.getDataSetIndex()); + final int minDataSetIndex = high.getDataSetIndex() == -1 + ? 0 + : high.getDataSetIndex(); + final int maxDataSetIndex = high.getDataSetIndex() == -1 + ? bubbleData.getDataSetCount() + : (high.getDataSetIndex() + 1); + if (maxDataSetIndex - minDataSetIndex < 1) continue; - if (dataSet == null || !dataSet.isHighlightEnabled()) - continue; + for (int dataSetIndex = minDataSetIndex; + dataSetIndex < maxDataSetIndex; + dataSetIndex++) { - final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); - if (entry == null || entry.getXIndex() != indice.getXIndex()) - continue; + IBubbleDataSet dataSet = bubbleData.getDataSetByIndex(dataSetIndex); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); - BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); + if (dataSet == null || !dataSet.isHighlightEnabled()) + continue; - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); + final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(high); + if (entry == null || entry.getXIndex() != high.getXIndex()) + continue; - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); + BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); - sizeBuffer[0] = 0f; - sizeBuffer[2] = 1f; + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); - trans.pointValuesToPixel(sizeBuffer); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); + sizeBuffer[0] = 0f; + sizeBuffer[2] = 1f; - // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); - final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); + trans.pointValuesToPixel(sizeBuffer); - pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; - pointBuffer[1] = (float) (entry.getVal()) * phaseY; - trans.pointValuesToPixel(pointBuffer); + boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); - float shapeHalf = getShapeSize(entry.getSize(), dataSet.getMaxSize(), referenceSize, normalizeSize) / 2f; + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); + final float maxBubbleHeight = Math.abs( + mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) - || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) - continue; + pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; + pointBuffer[1] = (float) (entry.getVal()) * phaseY; + trans.pointValuesToPixel(pointBuffer); - if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) - continue; + float shapeHalf = getShapeSize(entry.getSize(), + dataSet.getMaxSize(), + referenceSize, + normalizeSize) / 2f; - if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) - break; + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; - if (indice.getXIndex() < minx || indice.getXIndex() >= maxx) - continue; + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) + continue; + + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; - final int originalColor = dataSet.getColor(entry.getXIndex()); + if (high.getXIndex() < minx || high.getXIndex() >= maxx) + continue; + + final int originalColor = dataSet.getColor(entry.getXIndex()); - Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), - Color.blue(originalColor), _hsvBuffer); - _hsvBuffer[2] *= 0.5f; - final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), + Color.blue(originalColor), _hsvBuffer); + _hsvBuffer[2] *= 0.5f; + final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); - mHighlightPaint.setColor(color); - mHighlightPaint.setStrokeWidth(dataSet.getHighlightCircleWidth()); - c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); + mHighlightPaint.setColor(color); + mHighlightPaint.setStrokeWidth(dataSet.getHighlightCircleWidth()); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); + } } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 790d83ae92..ff4deed981 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -309,38 +309,48 @@ public void drawExtras(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - for (int i = 0; i < indices.length; i++) { + CandleData candleData = mChart.getCandleData(); - int xIndex = indices[i].getXIndex(); // get the - // x-position + for (Highlight high : indices) { - ICandleDataSet set = mChart.getCandleData().getDataSetByIndex( - indices[i].getDataSetIndex()); + final int minDataSetIndex = high.getDataSetIndex() == -1 + ? 0 + : high.getDataSetIndex(); + final int maxDataSetIndex = high.getDataSetIndex() == -1 + ? candleData.getDataSetCount() + : (high.getDataSetIndex() + 1); + if (maxDataSetIndex - minDataSetIndex < 1) continue; - if (set == null || !set.isHighlightEnabled()) - continue; + for (int dataSetIndex = minDataSetIndex; + dataSetIndex < maxDataSetIndex; + dataSetIndex++) { - CandleEntry e = set.getEntryForXIndex(xIndex); + int xIndex = high.getXIndex(); // get the + // x-position - if (e == null || e.getXIndex() != xIndex) - continue; + ICandleDataSet set = mChart.getCandleData().getDataSetByIndex(dataSetIndex); - float low = e.getLow() * mAnimator.getPhaseY(); - float high = e.getHigh() * mAnimator.getPhaseY(); - float y = (low + high) / 2f; + if (set == null || !set.isHighlightEnabled()) + continue; - float min = mChart.getYChartMin(); - float max = mChart.getYChartMax(); + CandleEntry e = set.getEntryForXIndex(xIndex); + if (e == null || e.getXIndex() != xIndex) + continue; + + float lowValue = e.getLow() * mAnimator.getPhaseY(); + float highValue = e.getHigh() * mAnimator.getPhaseY(); + float y = (lowValue + highValue) / 2f; - float[] pts = new float[]{ - xIndex, y - }; + float[] pts = new float[]{ + xIndex, y + }; - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); - // draw the lines - drawHighlightLines(c, pts, set); + // draw the lines + drawHighlightLines(c, pts, set); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 4b01d48753..982e22e36a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -129,7 +129,7 @@ else if (renderer instanceof BubbleChartRenderer) ArrayList dataIndices = new ArrayList<>(); for (Highlight h : indices) { - if (h.getDataIndex() == dataIndex) + if (h.getDataIndex() == dataIndex || h.getDataIndex() == -1) dataIndices.add(h); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 442fe541dd..1334461831 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; @@ -669,36 +670,50 @@ protected void drawCircles(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - for (int i = 0; i < indices.length; i++) { + LineData lineData = mChart.getLineData(); - ILineDataSet set = mChart.getLineData().getDataSetByIndex(indices[i] - .getDataSetIndex()); + for (Highlight high : indices) { - if (set == null || !set.isHighlightEnabled()) - continue; + final int minDataSetIndex = high.getDataSetIndex() == -1 + ? 0 + : high.getDataSetIndex(); + final int maxDataSetIndex = high.getDataSetIndex() == -1 + ? lineData.getDataSetCount() + : (high.getDataSetIndex() + 1); + if (maxDataSetIndex - minDataSetIndex < 1) continue; - int xIndex = indices[i].getXIndex(); // get the - // x-position + for (int dataSetIndex = minDataSetIndex; + dataSetIndex < maxDataSetIndex; + dataSetIndex++) { - if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) - continue; + ILineDataSet set = lineData.getDataSetByIndex(dataSetIndex); - final float yVal = set.getYValForXIndex(xIndex); - if (Float.isNaN(yVal)) - continue; + if (set == null || !set.isHighlightEnabled()) + continue; - float y = yVal * mAnimator.getPhaseY(); // get - // the - // y-position + int xIndex = high.getXIndex(); // get the + // x-position - float[] pts = new float[]{ - xIndex, y - }; + if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) + continue; - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + final float yVal = set.getYValForXIndex(xIndex); + if (Float.isNaN(yVal)) + continue; + + float y = yVal * mAnimator.getPhaseY(); // get + // the + // y-position + + float[] pts = new float[]{ + xIndex, y + }; - // draw the lines - drawHighlightLines(c, pts, set); + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + + // draw the lines + drawHighlightLines(c, pts, set); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 684c6701f7..754b260a20 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -376,35 +376,49 @@ public void drawExtras(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - for (int i = 0; i < indices.length; i++) { + ScatterData scatterData = mChart.getScatterData(); + + for (Highlight high : indices) { + + final int minDataSetIndex = high.getDataSetIndex() == -1 + ? 0 + : high.getDataSetIndex(); + final int maxDataSetIndex = high.getDataSetIndex() == -1 + ? scatterData.getDataSetCount() + : (high.getDataSetIndex() + 1); + if (maxDataSetIndex - minDataSetIndex < 1) continue; + + for (int dataSetIndex = minDataSetIndex; + dataSetIndex < maxDataSetIndex; + dataSetIndex++) { - IScatterDataSet set = mChart.getScatterData().getDataSetByIndex(indices[i] - .getDataSetIndex()); + IScatterDataSet set = scatterData.getDataSetByIndex(dataSetIndex); - if (set == null || !set.isHighlightEnabled()) - continue; + if (set == null || !set.isHighlightEnabled()) + continue; - int xIndex = indices[i].getXIndex(); // get the - // x-position + int xIndex = high.getXIndex(); // get the + // x-position - if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) - continue; + if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) + continue; - final float yVal = set.getYValForXIndex(xIndex); - if (Float.isNaN(yVal)) - continue; + final float yVal = set.getYValForXIndex(xIndex); + if (Float.isNaN(yVal)) + continue; - float y = yVal * mAnimator.getPhaseY(); + float y = yVal * mAnimator.getPhaseY(); - float[] pts = new float[]{ - xIndex, y - }; + float[] pts = new float[]{ + xIndex, y + }; - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); - // draw the lines - drawHighlightLines(c, pts, set); + // draw the lines + drawHighlightLines(c, pts, set); + } } } } From ea89dfef0443b44a153b600626d3b50e5cc5b6b7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 8 May 2016 21:04:33 +0300 Subject: [PATCH 0892/1390] Supress false-positive inspection warning --- .../mikephil/charting/renderer/CandleStickChartRenderer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index ff4deed981..dd7c49481c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -50,6 +50,7 @@ public void drawData(Canvas c) { } } + @SuppressWarnings("ResourceAsColor") protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); From db19fdcb94cd74bdb1d654bd6aaee456bb7f1420 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 10 May 2016 19:27:08 +0300 Subject: [PATCH 0893/1390] These DPs must be converted to pixels --- .../mikephil/charting/renderer/HorizontalBarChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 41e1514d5d..46ab01b6e9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -53,7 +53,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); - mBarBorderPaint.setStrokeWidth(dataSet.getBarBorderWidth()); + mBarBorderPaint.setStrokeWidth(Util.convertDpToPixel(dataSet.getBarBorderWidth())); final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f; From 4cf9f5965434ccf72c3cccde1b661272cfa5405b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 10 May 2016 19:27:37 +0300 Subject: [PATCH 0894/1390] These DPs must be converted to pixels --- .../com/github/mikephil/charting/renderer/BarChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index dac3a5ba7d..473a721f89 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -86,7 +86,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); - mBarBorderPaint.setStrokeWidth(dataSet.getBarBorderWidth()); + mBarBorderPaint.setStrokeWidth(Util.convertDpToPixel(dataSet.getBarBorderWidth())); final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f; From 92810c8d9ab55903271626864b92c3524e38388d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 15 May 2016 09:59:06 +0300 Subject: [PATCH 0895/1390] Fixed typo in Util/Utils --- .../com/github/mikephil/charting/renderer/BarChartRenderer.java | 2 +- .../mikephil/charting/renderer/HorizontalBarChartRenderer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 473a721f89..8179ebd2d4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -86,7 +86,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); - mBarBorderPaint.setStrokeWidth(Util.convertDpToPixel(dataSet.getBarBorderWidth())); + mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth())); final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 46ab01b6e9..cadc706ae4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -53,7 +53,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); - mBarBorderPaint.setStrokeWidth(Util.convertDpToPixel(dataSet.getBarBorderWidth())); + mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth())); final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f; From 4393b2710ac30f858dea6369da249945bbbed591 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 15 May 2016 10:36:45 +0300 Subject: [PATCH 0896/1390] I hope this will position x-labels correctly vertically And without any weird hack. But by just finally figuring out how to correctly offset the drawing from the font glyph size --- MPChartLib/src/com/github/mikephil/charting/utils/Utils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 9f342c7dce..caaef8153c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -611,17 +611,16 @@ public static void drawXAxisValue(Canvas c, String text, float x, float y, float drawOffsetX = 0.f; float drawOffsetY = 0.f; + final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer); paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); - final float lineHeight = mDrawTextRectBuffer.height(); - // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; // Android does not snap the bounds to line boundaries, // and draws from bottom to top. // And we want to normalize it. - drawOffsetY += lineHeight; + drawOffsetY += -mFontMetricsBuffer.ascent; // To have a consistent point of reference, we always draw left-aligned Paint.Align originalTextAlign = paint.getTextAlign(); From 2cb255a9f425c44e0dd74858cad7d099a3217ac6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 22 May 2016 15:23:18 +0300 Subject: [PATCH 0897/1390] Clip drawing area of limit lines when !isDrawLimitLinesBehindDataEnabled --- .../github/mikephil/charting/charts/BarLineChartBase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 0a7030f901..304ae6cc1f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -261,6 +261,9 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(canvas); + clipRestoreCount = canvas.save(); + canvas.clipRect(mViewPortHandler.getContentRect()); + if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); @@ -270,6 +273,8 @@ protected void onDraw(Canvas canvas) { if (!mAxisRight.isDrawLimitLinesBehindDataEnabled()) mAxisRendererRight.renderLimitLines(canvas); + canvas.restoreToCount(clipRestoreCount); + mXAxisRenderer.renderAxisLabels(canvas); mAxisRendererLeft.renderAxisLabels(canvas); mAxisRendererRight.renderAxisLabels(canvas); From 17f919aa437042ebd2594c6b789613019f0ccf3f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 22 May 2016 17:15:22 +0300 Subject: [PATCH 0898/1390] Allow more control over circle hole radius --- .../LineChartActivityColored.java | 1 + .../mikephil/charting/data/LineDataSet.java | 19 ++++++++++++++ .../implementation/RealmLineDataSet.java | 25 ++++++++++++++++--- .../interfaces/datasets/ILineDataSet.java | 5 ++++ .../charting/renderer/LineChartRenderer.java | 11 +++++--- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index b4d5a5ce81..e12d8907f8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -120,6 +120,7 @@ private LineData getData(int count, float range) { set1.setLineWidth(1.75f); set1.setCircleRadius(5f); + set1.setCircleHoleRadius(2.5f); set1.setColor(Color.WHITE); set1.setCircleColorHole(Color.WHITE); set1.setHighLightColor(Color.WHITE); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 1fb380eeaa..10e098712e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -29,6 +29,9 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** the radius of the circle-shaped value indicators */ private float mCircleRadius = 8f; + /** the hole radius of the circle-shaped value indicators */ + private float mCircleHoleRadius = 4f; + /** sets the intensity of the cubic lines */ private float mCubicIntensity = 0.2f; @@ -71,6 +74,7 @@ public DataSet copy() { copied.mMode = mMode; copied.mColors = mColors; copied.mCircleRadius = mCircleRadius; + copied.mCircleHoleRadius = mCircleHoleRadius; copied.mCircleColors = mCircleColors; copied.mDashPathEffect = mDashPathEffect; copied.mDrawCircles = mDrawCircles; @@ -136,6 +140,21 @@ public float getCircleRadius() { return mCircleRadius; } + /** + * sets the hole radius of the drawn circles. + * Default radius = 2f + * + * @param holeRadius + */ + public void setCircleHoleRadius(float holeRadius) { + mCircleHoleRadius = Utils.convertDpToPixel(holeRadius); + } + + @Override + public float getCircleHoleRadius() { + return mCircleHoleRadius; + } + /** * sets the size (radius) of the circle shpaed value indicators, * default size = 4f diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index b8832271af..4734a9e39c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -3,7 +3,6 @@ import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; -import android.graphics.drawable.Drawable; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; @@ -40,7 +39,10 @@ public class RealmLineDataSet extends RealmLineRadarDataS /** * the radius of the circle-shaped value indicators */ - private float mCircleSize = 8f; + private float mCircleRadius = 8f; + + /** the hole radius of the circle-shaped value indicators */ + private float mCircleHoleRadius = 4f; /** * sets the intensity of the cubic lines @@ -146,12 +148,27 @@ public float getCubicIntensity() { * @param size */ public void setCircleSize(float size) { - mCircleSize = Utils.convertDpToPixel(size); + mCircleRadius = Utils.convertDpToPixel(size); } @Override public float getCircleRadius() { - return mCircleSize; + return mCircleRadius; + } + + /** + * sets the hole radius of the drawn circles. + * Default radius = 2f + * + * @param holeRadius + */ + public void setCircleHoleRadius(float holeRadius) { + mCircleHoleRadius = Utils.convertDpToPixel(holeRadius); + } + + @Override + public float getCircleHoleRadius() { + return mCircleHoleRadius; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index fb7ba45536..6f62274b8e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -38,6 +38,11 @@ public interface ILineDataSet extends ILineRadarDataSet { */ float getCircleRadius(); + /** + * Returns the hole radius of the drawn circles. + */ + float getCircleHoleRadius(); + /** * Returns the color at the given index of the DataSet's circle-color array. * Performs a IndexOutOfBounds check by modulus. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1334461831..ebc1215c3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -626,7 +626,9 @@ protected void drawCircles(Canvas c) { int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - float halfsize = dataSet.getCircleRadius() / 2f; + float circleRadius = dataSet.getCircleRadius(); + float circleHoleRadius = dataSet.getCircleHoleRadius(); + boolean isDrawCircleHoleEnabled = dataSet.isDrawCircleHoleEnabled(); for (int j = minx, count = (int) Math.ceil((maxx - minx) * phaseX + minx); @@ -658,10 +660,11 @@ protected void drawCircles(Canvas c) { c.drawCircle(circlesBuffer[0], circlesBuffer[1], dataSet.getCircleRadius(), mRenderPaint); - if (dataSet.isDrawCircleHoleEnabled() - && circleColor != mCirclePaintInner.getColor()) + if (isDrawCircleHoleEnabled && + circleHoleRadius < circleRadius && + circleHoleRadius > 0.f) c.drawCircle(circlesBuffer[0], circlesBuffer[1], - halfsize, + circleHoleRadius, mCirclePaintInner); } } From 881581fa2d04b53cdae3ff0bc8a3f9d560db68f2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 22 May 2016 17:55:07 +0300 Subject: [PATCH 0899/1390] Allow transparent circle hole color --- .../charting/renderer/LineChartRenderer.java | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index ebc1215c3e..64e136bfdd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -593,6 +594,8 @@ public void drawExtras(Canvas c) { drawCircles(c); } + private Path mCirclePathBuffer = new Path(); + protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); @@ -628,7 +631,11 @@ protected void drawCircles(Canvas c) { float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); - boolean isDrawCircleHoleEnabled = dataSet.isDrawCircleHoleEnabled(); + boolean drawCircleHole = dataSet.isDrawCircleHoleEnabled() && + circleHoleRadius < circleRadius && + circleHoleRadius > 0.f; + boolean drawTransparentCircleHole = drawCircleHole && + dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; for (int j = minx, count = (int) Math.ceil((maxx - minx) * phaseX + minx); @@ -653,19 +660,37 @@ protected void drawCircles(Canvas c) { !mViewPortHandler.isInBoundsY(circlesBuffer[1])) continue; - int circleColor = dataSet.getCircleColor(j); + mRenderPaint.setColor(dataSet.getCircleColor(j)); - mRenderPaint.setColor(circleColor); + if (drawTransparentCircleHole) { - c.drawCircle(circlesBuffer[0], circlesBuffer[1], dataSet.getCircleRadius(), - mRenderPaint); + // Begin path for circle with hole + mCirclePathBuffer.reset(); - if (isDrawCircleHoleEnabled && - circleHoleRadius < circleRadius && - circleHoleRadius > 0.f) - c.drawCircle(circlesBuffer[0], circlesBuffer[1], + mCirclePathBuffer.addCircle(circlesBuffer[0], circlesBuffer[1], + circleRadius, + Path.Direction.CW); + + // Cut hole in path + mCirclePathBuffer.addCircle(circlesBuffer[0], circlesBuffer[1], circleHoleRadius, - mCirclePaintInner); + Path.Direction.CCW); + + // Fill in-between + c.drawPath(mCirclePathBuffer, mRenderPaint); + + } else { + + c.drawCircle(circlesBuffer[0], circlesBuffer[1], + circleRadius, + mRenderPaint); + + if (drawCircleHole) { + c.drawCircle(circlesBuffer[0], circlesBuffer[1], + circleHoleRadius, + mCirclePaintInner); + } + } } } } From b59cf564a085a937120e8eba509396261156a6b4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 22 May 2016 17:55:54 +0300 Subject: [PATCH 0900/1390] Updated coloured line circle colors for correct transparent hole --- .../mpchartexample/LineChartActivityColored.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index e12d8907f8..49491eaa8b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -54,7 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { private void setupChart(LineChart chart, LineData data, int color) { - ((LineDataSet) data.getDataSetByIndex(0)).setCircleColor(color); + ((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color); // no description text chart.setDescription(""); @@ -122,7 +123,7 @@ private LineData getData(int count, float range) { set1.setCircleRadius(5f); set1.setCircleHoleRadius(2.5f); set1.setColor(Color.WHITE); - set1.setCircleColorHole(Color.WHITE); + set1.setCircleColor(Color.WHITE); set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); From 87193a3d2e179af7dd8d606eecd844130d69ebb9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 26 May 2016 15:26:14 +0300 Subject: [PATCH 0901/1390] Add extra control point when rendering cubic bezier out of range --- .../mikephil/charting/renderer/LineChartRenderer.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 64e136bfdd..3d4c359776 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; @@ -205,7 +206,7 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff - 1, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); @@ -563,6 +564,9 @@ public void drawValues(Canvas c) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; + if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) + diff += 1; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); @@ -626,6 +630,9 @@ protected void drawCircles(Canvas c) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; + if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) + diff += 1; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); From 43bc45b7185de6e55ee4f79ef314818360434098 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 May 2016 13:27:55 +0200 Subject: [PATCH 0902/1390] Minor fixes in example --- MPChartExample/build.gradle | 2 +- .../xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 3 ++- .../mpchartexample/CubicLineChartActivity.java | 1 + .../xxmassdeveloper/mpchartexample/LineChartActivity1.java | 3 ++- .../xxmassdeveloper/mpchartexample/LineChartActivity2.java | 3 ++- .../mpchartexample/ListViewBarChartActivity.java | 2 +- .../mpchartexample/MultiLineChartActivity.java | 3 +-- .../xxmassdeveloper/mpchartexample/ScatterChartActivity.java | 4 ++-- build.gradle | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 5cef000d7c..ad4fc88ba2 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -37,7 +37,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0' + classpath 'com.android.tools.build:gradle:2.1.0' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 3918072671..a516854faf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -206,8 +206,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BarData data = new BarData(xVals, dataSets); mChart.setData(data); - mChart.invalidate(); } + + mChart.invalidate(); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index a50171e710..0c25904f48 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -290,6 +290,7 @@ private void setData(int count, float range) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 5a32612b5f..13efdb1503 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -349,7 +349,7 @@ private void setData(int count, float range) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * - // 0.1) / 10); + // 0.1) / 10);x yVals.add(new Entry(val, i)); } @@ -360,6 +360,7 @@ private void setData(int count, float range) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 0d76e71813..c50edff816 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -319,6 +319,7 @@ private void setData(int count, float range) { set1.setYVals(yVals1); set2.setYVals(yVals2); mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type @@ -352,8 +353,8 @@ private void setData(int count, float range) { //set2.setFillFormatter(new MyFillFormatter(900f)); ArrayList dataSets = new ArrayList(); - dataSets.add(set2); dataSets.add(set1); // add the datasets + dataSets.add(set2); // create a data object with the datasets LineData data = new LineData(xVals, dataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index e1c69086bc..f430675338 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -112,7 +112,7 @@ public View getView(int position, View convertView, ViewGroup parent) { // do not forget to refresh the chart // holder.chart.invalidate(); - holder.chart.animateY(700, Easing.EasingOption.EaseInCubic); + holder.chart.animateY(700); return convertView; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 05e25fae64..09f5a7ac68 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -57,8 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setDrawBorders(false); - mChart.getAxisLeft().setDrawAxisLine(false); - mChart.getAxisLeft().setDrawGridLines(false); + mChart.getAxisLeft().setEnabled(false); mChart.getAxisRight().setDrawAxisLine(false); mChart.getAxisRight().setDrawGridLines(false); mChart.getXAxis().setDrawAxisLine(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index e716f7ff47..95b3954fb8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -195,8 +195,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); set2.setScatterShape(ScatterShape.CIRCLE); - set2.setScatterShapeHoleColor(Color.WHITE); - set2.setScatterShapeHoleRadius(5f); + set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); + set2.setScatterShapeHoleRadius(4f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); set3.setScatterShape(ScatterShape.CROSS); diff --git a/build.gradle b/build.gradle index 66dbb5af3c..564d957cc5 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.0.0' + classpath 'com.android.tools.build:gradle:2.1.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From 98fe348b216413b728ebf1d85606eaf8916e3a0f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 May 2016 14:15:38 +0200 Subject: [PATCH 0903/1390] Update README.md --- README.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1e58a84f48..177b50abe3 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,22 @@ As an additional feature, this library allows cross-platform development between Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). +Donations +----- + +**This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! + +**PayPal** + + - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! + - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! + - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! + - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! + - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! + - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! + - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! + + ## 3rd party bindings Xamarin (by @Flash3001): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). @@ -31,21 +47,6 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: - Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) -Donations ------ - -**This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! - -**PayPal** - - - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! - Demo ----- From 77f83cddc5ae9e4a7094bc4f692aeb2179c9ca6c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 May 2016 17:46:48 +0200 Subject: [PATCH 0904/1390] Update gradle --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 9efb9639b9..be66731b50 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="51" + android:versionName="2.2.5" > Date: Fri, 27 May 2016 22:36:23 +0200 Subject: [PATCH 0905/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 177b50abe3..6390228dae 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.4/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.5/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -104,7 +104,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.2.4' + compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } ``` @@ -119,7 +119,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.2.4 + v2.2.5 ``` @@ -139,7 +139,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.4/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.5/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 02704708979a2634b817dcc54615a48e6035552d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 May 2016 15:47:02 +0200 Subject: [PATCH 0906/1390] Minor fixes related to polyline example --- .../PiePolylineChartActivity.java | 8 ++-- .../charting/renderer/PieChartRenderer.java | 45 +++++++++---------- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 58f1e085ea..0e9a816869 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -71,7 +71,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); mChart.setCenterText(generateCenterSpannableText()); - mChart.setExtraOffsets(5.f, 5.f, 5.f, 5.f); + mChart.setExtraOffsets(20.f, 0.f, 20.f, 0.f); mChart.setDrawHoleEnabled(true); mChart.setHoleColor(Color.WHITE); @@ -226,7 +226,7 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); - dataSet.setValueLinePart1Length(0.3f); + dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); // dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); @@ -247,10 +247,10 @@ private void setData(int count, float range) { private SpannableString generateCenterSpannableText() { SpannableString s = new SpannableString("MPAndroidChart\ndeveloped by Philipp Jahoda"); - s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); + s.setSpan(new RelativeSizeSpan(1.5f), 0, 14, 0); s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); - s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); + s.setSpan(new RelativeSizeSpan(.65f), 14, s.length() - 15, 0); s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0); return s; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 226b925371..6f570d3d2b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -143,8 +143,7 @@ protected float calculateMinimumRadiusForSpacedSlice( float arcStartPointX, float arcStartPointY, float startAngle, - float sweepAngle) - { + float sweepAngle) { final float angleMiddle = startAngle + sweepAngle / 2.f; // Other point of the arc @@ -163,7 +162,7 @@ protected float calculateMinimumRadiusForSpacedSlice( // After reducing space from both sides of the "slice", // the angle of the contained triangle should stay the same. // So let's find out the height of that triangle. - float containedTriangleHeight = (float)(basePointsDistance / 2.0 * + float containedTriangleHeight = (float) (basePointsDistance / 2.0 * Math.tan((180.0 - angle) / 2.0 * Utils.DEG2RAD)); // Now we subtract that from the radius @@ -228,8 +227,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { sliceSpace / (Utils.FDEG2RAD * radius); final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; - if (sweepAngleOuter < 0.f) - { + if (sweepAngleOuter < 0.f) { sweepAngleOuter = 0.f; } @@ -284,8 +282,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { sliceSpace / (Utils.FDEG2RAD * innerRadius); final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; - if (sweepAngleInner < 0.f) - { + if (sweepAngleInner < 0.f) { sweepAngleInner = 0.f; } final float endAngleInner = startAngleInner + sweepAngleInner; @@ -305,8 +302,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { -sweepAngleInner ); } - } - else { + } else { if (sweepAngleOuter % 360f != 0.f) { if (accountForSliceSpacing) { @@ -411,6 +407,8 @@ public void drawValues(Canvas c) { mValueLinePaint.setColor(dataSet.getValueLineColor()); mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); + float offset = Utils.convertDpToPixel(5.f); + for (int j = 0; j < entryCount; j++) { Entry entry = dataSet.getEntryForIndex(j); @@ -434,8 +432,8 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() / yValueSum * 100f : entry.getVal(); - final float sliceXBase = (float)Math.cos(transformedAngle * Utils.FDEG2RAD); - final float sliceYBase = (float)Math.sin(transformedAngle * Utils.FDEG2RAD); + final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); + final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD); final boolean drawXOutside = drawXVals && xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE; @@ -465,9 +463,9 @@ public void drawValues(Canvas c) { line1Radius = radius * valueLinePart1OffsetPercentage; final float polyline2Width = dataSet.isValueLineVariableLength() - ? labelRadius * valueLineLength2 * (float)Math.abs(Math.sin( + ? labelRadius * valueLineLength2 * (float) Math.abs(Math.sin( transformedAngle * Utils.FDEG2RAD)) - : labelRadius * valueLineLength2; + : labelRadius * valueLineLength2; final float pt0x = line1Radius * sliceXBase + center.x; final float pt0y = line1Radius * sliceYBase + center.y; @@ -479,13 +477,13 @@ public void drawValues(Canvas c) { pt2x = pt1x - polyline2Width; pt2y = pt1y; mValuePaint.setTextAlign(Align.RIGHT); - labelPtx = pt2x - Utils.convertDpToPixel(5.f); + labelPtx = pt2x - offset; labelPty = pt2y; } else { pt2x = pt1x + polyline2Width; pt2y = pt1y; mValuePaint.setTextAlign(Align.LEFT); - labelPtx = pt2x + Utils.convertDpToPixel(5.f); + labelPtx = pt2x + offset; labelPty = pt2y; } @@ -518,7 +516,8 @@ public void drawValues(Canvas c) { } } else if (drawYOutside) { - drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet.getValueTextColor(j)); + drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet + .getValueTextColor(j)); } } @@ -743,20 +742,18 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; - if (sweepAngleOuter < 0.f) - { + if (sweepAngleOuter < 0.f) { sweepAngleOuter = 0.f; } final float startAngleShifted = rotationAngle + (angle + sliceSpaceAngleShifted / 2.f) * phaseY; float sweepAngleShifted = (sliceAngle - sliceSpaceAngleShifted) * phaseY; - if (sweepAngleShifted < 0.f) - { + if (sweepAngleShifted < 0.f) { sweepAngleShifted = 0.f; } mPathBuffer.reset(); - + if (sweepAngleOuter % 360f == 0.f) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, highlightedRadius, Path.Direction.CW); @@ -809,8 +806,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { sliceSpace / (Utils.FDEG2RAD * innerRadius); final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; - if (sweepAngleInner < 0.f) - { + if (sweepAngleInner < 0.f) { sweepAngleInner = 0.f; } final float endAngleInner = startAngleInner + sweepAngleInner; @@ -830,8 +826,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { -sweepAngleInner ); } - } - else { + } else { if (sweepAngleOuter % 360f != 0.f) { From 1b9b3da3deaea37114e1fe9423445dac4a97c2a5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 May 2016 15:52:56 +0200 Subject: [PATCH 0907/1390] Add spin animation to pie example --- .../com/xxmassdeveloper/mpchartexample/PieChartActivity.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index bab7dcb525..a7350e9cac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -165,6 +165,10 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.animateXY(1400, 1400); break; } + case R.id.actionToggleSpin: { + mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption.EaseInCubic); + break; + } } return true; } From d2cc49b525eb69c506e7b46210f548b03828f76d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 30 May 2016 10:54:11 +0200 Subject: [PATCH 0908/1390] Work on changing xaxis, WIP --- .../mpchartexample/AnotherBarActivity.java | 4 +- .../mpchartexample/BarChartActivity.java | 2 +- .../BarChartActivityMultiDataset.java | 6 +- .../BarChartPositiveNegative.java | 8 +- .../DynamicalAddingActivity.java | 2 +- .../HorizontalBarChartActivity.java | 3 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 4 +- .../mpchartexample/PerformanceLineChart.java | 2 +- .../charting/charts/BarLineChartBase.java | 14 +- .../mikephil/charting/charts/Chart.java | 2 +- .../mikephil/charting/charts/PieChart.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 5 +- .../charting/components/AxisBase.java | 45 ++++++ .../mikephil/charting/components/YAxis.java | 36 +---- .../mikephil/charting/data/BaseDataSet.java | 2 +- .../mikephil/charting/data/ChartData.java | 4 +- .../mikephil/charting/data/DataSet.java | 26 ++-- .../data/realm/base/RealmBaseDataSet.java | 26 ++-- .../charting/highlight/BarHighlighter.java | 2 +- .../interfaces/datasets/IDataSet.java | 36 ++--- .../charting/renderer/AxisRenderer.java | 37 +++++ .../charting/renderer/BarChartRenderer.java | 2 +- .../renderer/BubbleChartRenderer.java | 27 +++- .../renderer/CandleStickChartRenderer.java | 38 ++--- .../charting/renderer/LineChartRenderer.java | 41 ++++-- .../charting/renderer/PieChartRenderer.java | 2 +- .../charting/renderer/RadarChartRenderer.java | 2 +- .../charting/renderer/XAxisRenderer.java | 137 +++++++++++------- .../renderer/XAxisRendererBarChart.java | 102 ++++++------- .../XAxisRendererHorizontalBarChart.java | 63 ++++---- .../charting/renderer/YAxisRenderer.java | 35 +---- .../YAxisRendererHorizontalBarChart.java | 5 +- .../renderer/YAxisRendererRadarChart.java | 2 +- .../charting/utils/EntryXIndexComparator.java | 8 +- .../mikephil/charting/utils/FileUtils.java | 4 +- .../mikephil/charting/utils/Transformer.java | 4 +- 37 files changed, 408 insertions(+), 336 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 3a15b09d4c..4a06e62c3c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -176,8 +176,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { float mult = (mSeekBarY.getProgress() + 1); - float val1 = (float) (Math.random() * mult) + mult / 3; - yVals1.add(new BarEntry((int) val1, i)); + float val = (float) (Math.random() * mult) + mult / 3; + yVals1.add(new BarEntry(i, val)); } ArrayList xVals = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 8b3e59a549..48d8fe02a3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -238,7 +238,7 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(val, i)); + yVals1.add(new BarEntry(i, val)); XAxisValue value = new XAxisValue(i, mMonths[i % 12]); xVals.add(value); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 9fce121636..ef53cd5e86 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -201,17 +201,17 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mult) + 3; - yVals1.add(new BarEntry(val, i)); + yVals1.add(new BarEntry(i, val)); } for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mult) + 3; - yVals2.add(new BarEntry(val, i)); + yVals2.add(new BarEntry(i, val)); } for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mult) + 3; - yVals3.add(new BarEntry(val, i)); + yVals3.add(new BarEntry(i, val)); } BarDataSet set1, set2, set3; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index c41e30fccd..b795e80a9d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -97,7 +97,7 @@ private void setData(List dataList) { for (int i = 0; i < dataList.size(); i++) { Data d = dataList.get(i); - BarEntry entry = new BarEntry(d.yValue, d.xIndex); + BarEntry entry = new BarEntry(d.xValue, d.yValue); values.add(entry); dates[i] = new XAxisValue(i, dataList.get(i).xAxisValue); @@ -140,12 +140,12 @@ private class Data { public String xAxisValue; public float yValue; - public int xIndex; + public float xValue; - public Data(int xIndex, float yValue, String xAxisValue) { + public Data(float xValue, float yValue, String xAxisValue) { this.xAxisValue = xAxisValue; this.yValue = yValue; - this.xIndex = xIndex; + this.xValue = xValue; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index af3e744b91..3f5d4d152a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -91,7 +91,7 @@ private void removeLastEntry() { if (set != null) { - Entry e = set.getEntryForXIndex(set.getEntryCount() - 1); + Entry e = set.getEntryForXPos(set.getEntryCount() - 1); data.removeEntry(e, 0); // or remove by index diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 2d52ffbc45..0acda456f8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -240,7 +240,8 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { xVals.add(new XAxisValue(i, mMonths[i % 12])); - yVals1.add(new BarEntry((float) (Math.random() * range), i)); + float val = (float) (Math.random() * range); + yVals1.add(new BarEntry(i, val)); } BarDataSet set1; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index d788ebed15..946e23b14d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -347,7 +347,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * // 0.1) / 10);x - yVals.add(new Entry(val, i)); + yVals.add(new Entry(i, val)); xVals.add(new XAxisValue(i, i + "")); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 2aec85977c..84ad55ac9c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -298,7 +298,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 50;// + (float) // ((mult * // 0.1) / 10); - yVals1.add(new Entry(val, i)); + yVals1.add(new Entry(i, val)); } ArrayList yVals2 = new ArrayList(); @@ -308,7 +308,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 450;// + (float) // ((mult * // 0.1) / 10); - yVals2.add(new Entry(val, i)); + yVals2.add(new Entry(i, val)); } LineDataSet set1, set2; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index cec5d5669c..935f91721a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -105,7 +105,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * // 0.1) / 10); - yVals.add(new Entry(val, i)); + yVals.add(new Entry(i, val)); } // create a dataset and give it a type diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 501629581b..c5df174efe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -205,9 +205,11 @@ protected void onDraw(Canvas canvas) { drawGridBackground(canvas); if (mAxisLeft.isEnabled()) - mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); + mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted()); if (mAxisRight.isEnabled()) - mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted()); + if (mXAxis.isEnabled()) + mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); mXAxisRenderer.renderAxisLine(canvas); mAxisRendererLeft.renderAxisLine(canvas); @@ -342,10 +344,10 @@ public void notifyDataSetChanged() { calcMinMax(); - mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); - mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); + mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted()); + mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted()); - mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); + //mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null) mLegendRenderer.computeLegend(mData); @@ -565,7 +567,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { BarData bd = (BarData) mData; float space = bd.getGroupSpace(); int setCount = mData.getDataSetCount(); - int i = e.getX(); + float i = e.getX(); if (this instanceof HorizontalBarChart) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f97af317dd..37a24ad1bd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1414,7 +1414,7 @@ public List getEntriesAtIndex(int xIndex) { IDataSet set = mData.getDataSetByIndex(i); - Entry e = set.getEntryForXIndex(xIndex); + Entry e = set.getEntryForXPos(xIndex); if (e != null) { vals.add(e); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index d98efd2a30..74fbd2549d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -180,7 +180,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { float rotationAngle = getRotationAngle(); - int i = e.getX(); + int i = highlight.getXIndex(); // offset needed to center the drawn text in the slice float offset = mDrawAngles[i] / 2; @@ -311,7 +311,7 @@ public int getDataSetIndexForIndex(int xIndex) { List dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - if (dataSets.get(i).getEntryForXIndex(xIndex) != null) + if (dataSets.get(i).getEntryForXPos(xIndex) != null) return i; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 1a037ff2b6..13d0ac9c1d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -133,8 +133,9 @@ public void notifyDataSetChanged() { // mYAxis.setValueFormatter(mDefaultFormatter); // } - mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum); - mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); + mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); + mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); + //mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null && !mLegend.isLegendCustom()) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index 87e701d5dd..f078ed00c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -25,6 +25,26 @@ public abstract class AxisBase extends ComponentBase { private float mAxisLineWidth = 1f; + /** + * the actual array of entries + */ + public float[] mEntries = new float[]{}; + + /** + * the number of entries the legend contains + */ + public int mEntryCount; + + /** + * the number of decimal digits to use + */ + public int mDecimals; + + /** + * the number of label entries the axis should have, default 6 + */ + private int mLabelCount = 6; + /** * flag indicating if the grid lines for this axis should be drawn */ @@ -221,6 +241,31 @@ public boolean isDrawLabelsEnabled() { return mDrawLabels; } + /** + * Sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware + * that this number is not fixed. + * + * @param count the number of y-axis labels that sould be displayed + */ + public void setLabelCount(int count) { + + if (count > 25) + count = 25; + if (count < 2) + count = 2; + + mLabelCount = count; + } + + /** + * Returns the number of label entries the y-axis should have + * + * @return + */ + public int getLabelCount() { + return mLabelCount; + } + /** * Adds a new LimitLine to this axis. * diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 44427c28b1..82c4c10e6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -26,26 +26,6 @@ public class YAxis extends AxisBase { */ protected YAxisValueFormatter mYAxisValueFormatter; - /** - * the actual array of entries - */ - public float[] mEntries = new float[]{}; - - /** - * the number of entries the legend contains - */ - public int mEntryCount; - - /** - * the number of decimal digits to use - */ - public int mDecimals; - - /** - * the number of y-label entries the y-labels should have, default 6 - */ - private int mLabelCount = 6; - /** * indicates if the top y-label entry is drawn or not */ @@ -279,24 +259,10 @@ public void setDrawTopYLabelEntry(boolean enabled) { */ public void setLabelCount(int count, boolean force) { - if (count > 25) - count = 25; - if (count < 2) - count = 2; - - mLabelCount = count; + setLabelCount(count); mForceLabels = force; } - /** - * Returns the number of label entries the y-axis should have - * - * @return - */ - public int getLabelCount() { - return mLabelCount; - } - /** * Returns true if focing the y-label count is enabled. Default: false * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index e26a4d2edd..e218dec225 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -365,7 +365,7 @@ public boolean removeLast() { @Override public boolean removeEntry(int xIndex) { - T e = getEntryForXIndex(xIndex); + T e = getEntryForXPos(xIndex); return removeEntry(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 042a7f6425..0fff111552 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -774,7 +774,7 @@ public boolean removeEntry(int xIndex, int dataSetIndex) { return false; IDataSet dataSet = mDataSets.get(dataSetIndex); - Entry e = dataSet.getEntryForXIndex(xIndex); + Entry e = dataSet.getEntryForXPos(xIndex); if (e == null || e.getX() != xIndex) return false; @@ -799,7 +799,7 @@ public T getDataSetForEntry(Entry e) { T set = mDataSets.get(i); for (int j = 0; j < set.getEntryCount(); j++) { - if (e.equalTo(set.getEntryForXIndex(e.getX()))) + if (e.equalTo(set.getEntryForXPos(e.getX()))) return set; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 46e71d5865..e85c93e0ef 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -266,17 +266,17 @@ public int getEntryIndex(Entry e) { } @Override - public T getEntryForXIndex(int xIndex, Rounding rounding) { + public T getEntryForXPos(float xPos, Rounding rounding) { - int index = getEntryIndex(xIndex, rounding); + int index = getEntryIndex(xPos, rounding); if (index > -1) return mValues.get(index); return null; } @Override - public T getEntryForXIndex(int xIndex) { - return getEntryForXIndex(xIndex, Rounding.CLOSEST); + public T getEntryForXPos(float xPos) { + return getEntryForXPos(xPos, Rounding.CLOSEST); } @Override @@ -285,7 +285,7 @@ public T getEntryForIndex(int index) { } @Override - public int getEntryIndex(int xIndex, Rounding rounding) { + public int getEntryIndex(float xPos, Rounding rounding) { int low = 0; int high = mValues.size() - 1; @@ -294,14 +294,14 @@ public int getEntryIndex(int xIndex, Rounding rounding) { while (low <= high) { int m = (high + low) / 2; - if (xIndex == mValues.get(m).getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xIndex) + if (xPos == mValues.get(m).getX()) { + while (m > 0 && mValues.get(m - 1).getX() == xPos) m--; return m; } - if (xIndex > mValues.get(m).getX()) + if (xPos > mValues.get(m).getX()) low = m + 1; else high = m - 1; @@ -310,13 +310,13 @@ public int getEntryIndex(int xIndex, Rounding rounding) { } if (closest != -1) { - int closestXIndex = mValues.get(closest).getX(); + float closestXPos = mValues.get(closest).getX(); if (rounding == Rounding.UP) { - if (closestXIndex < xIndex && closest < mValues.size() - 1) { + if (closestXPos < xPos && closest < mValues.size() - 1) { ++closest; } } else if (rounding == Rounding.DOWN) { - if (closestXIndex > xIndex && closest > 0) { + if (closestXPos > xPos && closest > 0) { --closest; } } @@ -328,7 +328,7 @@ public int getEntryIndex(int xIndex, Rounding rounding) { @Override public float getYValForXIndex(int xIndex) { - Entry e = getEntryForXIndex(xIndex); + Entry e = getEntryForXPos(xIndex); if (e != null && e.getX() == xIndex) return e.getY(); @@ -398,7 +398,7 @@ public List getEntriesForXIndex(int xIndex) { /** * Determines how to round DataSet index values for - * {@link DataSet#getEntryIndex(int, Rounding)} DataSet.getEntryIndex()} + * {@link DataSet#getEntryIndex(float, Rounding)} DataSet.getEntryIndex()} * when an exact x-index is not found. */ public enum Rounding { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index a90ce4b8a9..49399fa3c6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -173,15 +173,15 @@ public void calcMinMax() { } @Override - public S getEntryForXIndex(int xIndex) { + public S getEntryForXPos(float xPos) { //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mIndexField, xIndex).findFirst()); //return new Entry(o.getFloat(mValuesField), o.getInt(mIndexField)); - return getEntryForXIndex(xIndex, DataSet.Rounding.CLOSEST); + return getEntryForXPos(xPos, DataSet.Rounding.CLOSEST); } @Override - public S getEntryForXIndex(int xIndex, DataSet.Rounding rounding) { - int index = getEntryIndex(xIndex, rounding); + public S getEntryForXPos(float xPos, DataSet.Rounding rounding) { + int index = getEntryIndex(xPos, rounding); if (index > -1) return mValues.get(index); return null; @@ -214,7 +214,7 @@ public S getEntryForIndex(int index) { } @Override - public int getEntryIndex(int x, DataSet.Rounding rounding) { + public int getEntryIndex(float xPos, DataSet.Rounding rounding) { int low = 0; int high = mValues.size() - 1; @@ -223,16 +223,14 @@ public int getEntryIndex(int x, DataSet.Rounding rounding) { while (low <= high) { int m = (high + low) / 2; - S entry = mValues.get(m); - - if (x == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == x) + if (xPos == mValues.get(m).getX()) { + while (m > 0 && mValues.get(m - 1).getX() == xPos) m--; return m; } - if (x > entry.getX()) + if (xPos > mValues.get(m).getX()) low = m + 1; else high = m - 1; @@ -241,13 +239,13 @@ public int getEntryIndex(int x, DataSet.Rounding rounding) { } if (closest != -1) { - int closestXIndex = mValues.get(closest).getX(); + float closestXPos = mValues.get(closest).getX(); if (rounding == DataSet.Rounding.UP) { - if (closestXIndex < x && closest < mValues.size() - 1) { + if (closestXPos < xPos && closest < mValues.size() - 1) { ++closest; } } else if (rounding == DataSet.Rounding.DOWN) { - if (closestXIndex > x && closest > 0) { + if (closestXPos > xPos && closest > 0) { --closest; } } @@ -265,7 +263,7 @@ public int getEntryIndex(S e) { public float getYValForXIndex(int xIndex) { //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(mIndexField, xIndex).findFirst()) // .getFloat(mValuesField); - Entry e = getEntryForXIndex(xIndex); + Entry e = getEntryForXPos(xIndex); if (e != null && e.getX() == xIndex) return e.getY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 155db6e88e..07e8256c42 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -120,7 +120,7 @@ protected Highlight getStackedHighlight( int xIndex, double yValue) { - BarEntry entry = set.getEntryForXIndex(xIndex); + BarEntry entry = set.getEntryForXPos(xIndex); if (entry == null) return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 7d52f3a30f..3c8cf5b119 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -58,29 +58,29 @@ public interface IDataSet { void calcMinMax(); /** - * Returns the first Entry object found at the given xIndex with binary - * search. If the no Entry at the specified x-index is found, this method - * returns the index at the closest x-index. Returns null if no Entry object - * at that index. INFORMATION: This method does calculations at runtime. Do + * Returns the first Entry object found at the given xPos with binary + * search. If the no Entry at the specified xPos is found, this method + * returns the Entry at the xPos according to the rounding. + * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xIndex + * @param xPos * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - T getEntryForXIndex(int xIndex, DataSet.Rounding rounding); + T getEntryForXPos(float xPos, DataSet.Rounding rounding); /** - * Returns the first Entry object found at the given xIndex with binary - * search. If the no Entry at the specified x-index is found, this method - * returns the index at the closest x-index. Returns null if no Entry object - * at that index. INFORMATION: This method does calculations at runtime. Do + * Returns the first Entry object found at the given xPos with binary + * search. If the no Entry at the specified xPos is found, this method + * returns the index at the closest xPos. + * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xIndex + * @param xPos * @return */ - T getEntryForXIndex(int xIndex); + T getEntryForXPos(float xPos); /** * Returns all Entry objects found at the given xIndex with binary @@ -102,17 +102,17 @@ public interface IDataSet { T getEntryForIndex(int index); /** - * Returns the first Entry index found at the given xIndex with binary - * search. If the no Entry at the specified x-index is found, this method - * returns the index at the closest x-index. Returns -1 if no Entry object - * at that index. INFORMATION: This method does calculations at runtime. Do + * Returns the first Entry index found at the given xPos with binary + * search. If the no Entry at the specified xPos is found, this method + * returns the Entry at the closest xPos. + * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xIndex + * @param xPos * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - int getEntryIndex(int xIndex, DataSet.Rounding rounding); + int getEntryIndex(float xPos, DataSet.Rounding rounding); /** * Returns the position of the provided entry in the DataSets Entry array. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index 6dac9de21c..48da4be2c3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.graphics.Paint.Style; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -90,6 +91,42 @@ public Transformer getTransformer() { return mTrans; } + /** + * Computes the axis values. + * + * @param min - the minimum value in the data object for this axis + * @param max - the maximum value in the data object for this axis + */ + public void computeAxis(float min, float max, boolean inverted) { + + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + + if (!inverted) { + + min = (float) p2.y; + max = (float) p1.y; + } else { + + min = (float) p1.y; + max = (float) p2.y; + } + } + + computeAxisValues(min, max); + } + + /** + * Sets up the axis values. Computes the desired number of labels between the two given extremes. + * + * @return + */ + protected abstract void computeAxisValues(float min, float max); + /** * Draws the axis labels to the screen. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 0e66797572..9e522272fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -360,7 +360,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (index >= 0 && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { - BarEntry e = set.getEntryForXIndex(index); + BarEntry e = set.getEntryForXPos(index); if (e == null || e.getX() != index) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 412d8f3e05..384e1e5825 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -8,6 +8,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -74,8 +76,11 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); - BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + BubbleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); @@ -112,7 +117,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - final int color = dataSet.getColor(entry.getX()); + final int color = dataSet.getColor((int) entry.getX()); mRenderPaint.setColor(color); c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint); @@ -148,8 +153,11 @@ public void drawValues(Canvas c) { final float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); final float phaseY = mAnimator.getPhaseY(); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); - BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + BubbleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int minx = dataSet.getEntryIndex(entryFrom); int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); @@ -220,8 +228,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (entry == null || entry.getX() != high.getXIndex()) continue; - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); - BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); + float low = mChart.getLowestVisibleX(); + float highX = mChart.getHighestVisibleX(); + + BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + BubbleEntry entryTo = dataSet.getEntryForXPos(highX, DataSet.Rounding.UP); int minx = dataSet.getEntryIndex(entryFrom); int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); @@ -263,7 +274,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (high.getXIndex() < minx || high.getXIndex() >= maxx) continue; - final int originalColor = dataSet.getColor(entry.getX()); + final int originalColor = dataSet.getColor((int) entry.getX()); Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), Color.blue(originalColor), _hsvBuffer); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 7fc01fd518..ccef5a608d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -60,8 +60,8 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { float barSpace = dataSet.getBarSpace(); boolean showCandleBar = dataSet.getShowCandleBar(); - int minx = Math.max(mMinX, 0); - int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); + int minx = Math.max((int) mChart.getLowestVisibleX(), 0); + int maxx = Math.min((int) mChart.getHighestVisibleX(), dataSet.getEntryCount()); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); @@ -74,9 +74,9 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { // get the entry CandleEntry e = dataSet.getEntryForIndex(j); - final int xIndex = e.getX(); + final float xPos = e.getX(); - if (xIndex < minx || xIndex >= maxx) + if (xPos < minx || xPos >= maxx) continue; final float open = e.getOpen(); @@ -87,10 +87,10 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { if (showCandleBar) { // calculate the shadow - mShadowBuffers[0] = xIndex; - mShadowBuffers[2] = xIndex; - mShadowBuffers[4] = xIndex; - mShadowBuffers[6] = xIndex; + mShadowBuffers[0] = xPos; + mShadowBuffers[2] = xPos; + mShadowBuffers[4] = xPos; + mShadowBuffers[6] = xPos; if (open > close) { mShadowBuffers[1] = high * phaseY; @@ -150,9 +150,9 @@ else if (open < close) // calculate the body - mBodyBuffers[0] = xIndex - 0.5f + barSpace; + mBodyBuffers[0] = xPos - 0.5f + barSpace; mBodyBuffers[1] = close * phaseY; - mBodyBuffers[2] = (xIndex + 0.5f - barSpace); + mBodyBuffers[2] = (xPos + 0.5f - barSpace); mBodyBuffers[3] = open * phaseY; trans.pointValuesToPixel(mBodyBuffers); @@ -202,19 +202,19 @@ else if (open < close) } } else { - mRangeBuffers[0] = xIndex; + mRangeBuffers[0] = xPos; mRangeBuffers[1] = high * phaseY; - mRangeBuffers[2] = xIndex; + mRangeBuffers[2] = xPos; mRangeBuffers[3] = low * phaseY; - mOpenBuffers[0] = xIndex - 0.5f + barSpace; + mOpenBuffers[0] = xPos - 0.5f + barSpace; mOpenBuffers[1] = open * phaseY; - mOpenBuffers[2] = xIndex; + mOpenBuffers[2] = xPos; mOpenBuffers[3] = open * phaseY; - mCloseBuffers[0] = xIndex + 0.5f - barSpace; + mCloseBuffers[0] = xPos + 0.5f - barSpace; mCloseBuffers[1] = close * phaseY; - mCloseBuffers[2] = xIndex; + mCloseBuffers[2] = xPos; mCloseBuffers[3] = close * phaseY; trans.pointValuesToPixel(mRangeBuffers); @@ -276,8 +276,8 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - int minx = Math.max(mMinX, 0); - int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); + int minx = Math.max((int) mChart.getLowestVisibleX(), 0); + int maxx = Math.min((int) mChart.getHighestVisibleX() + 1, dataSet.getEntryCount()); float[] positions = trans.generateTransformedValuesCandle( dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -334,7 +334,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - CandleEntry e = set.getEntryForXIndex(xIndex); + CandleEntry e = set.getEntryForXPos(xIndex); if (e == null || e.getX() != xIndex) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9dccd96d9b..da1dfba60a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -137,8 +137,11 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); @@ -164,8 +167,8 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); - final float cpx = (float)(prev.getX()) - + (float)(cur.getX() - prev.getX()) / 2.0f; + final float cpx = (prev.getX()) + + (cur.getX() - prev.getX()) / 2.0f; cubicPath.cubicTo( cpx, prev.getY() * phaseY, @@ -201,8 +204,11 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff - 1, 0); @@ -336,8 +342,11 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { canvas = c; } - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); @@ -558,9 +567,11 @@ public void drawValues(Canvas c) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, - DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) @@ -624,9 +635,11 @@ protected void drawCircles(Canvas c) { int entryCount = dataSet.getEntryCount(); - Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX, - DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX, DataSet.Rounding.UP); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); int diff = (entryFrom == entryTo) ? 1 : 0; if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 850401978c..840e0a7007 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -215,7 +215,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { // draw only if the value is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { - if (!mChart.needsHighlight(e.getX(), + if (!mChart.needsHighlight((int) e.getX(), mChart.getData().getIndexOfDataSet(dataSet))) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index a9f7337db9..b0717a2322 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -272,7 +272,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // get the index to highlight int xIndex = indices[i].getXIndex(); - Entry e = set.getEntryForXIndex(xIndex); + Entry e = set.getEntryForXPos(xIndex); if (e == null || e.getX() != xIndex) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index e297c4d5ab..bd2c64f7ba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -33,20 +33,44 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } - public void computeAxis(float xValMaximumLength, List xValues) { + @Override + protected void computeAxisValues(float min, float max) { - mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); - mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + int labelCount = mXAxis.getLabelCount(); + float range = Math.abs(max - min); + + float interval = range / (labelCount - 1); - StringBuilder widthText = new StringBuilder(); + if (mXAxis.mEntries == null || mXAxis.mEntries.length != labelCount) { + mXAxis.mEntries = new float[labelCount]; + } + + mXAxis.mEntries[0] = 0f; - int xValChars = Math.round(xValMaximumLength); + for (int i = 1; i < labelCount; i++) { + mXAxis.mEntries[i] = interval * (float) i; + } - for (int i = 0; i < xValChars; i++) { - widthText.append('h'); + // set decimals + if (interval < 1) { + mXAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mXAxis.mDecimals = 0; } - final FSize labelSize = Utils.calcTextSize(mAxisLabelPaint, widthText.toString()); + if (mXAxis.getValues() != null && !mXAxis.getValues().isEmpty()) { + computeAxis(); + } + } + + protected void computeAxis() { + + String longest = mXAxis.getLongestLabel(); + + mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); + mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + + final FSize labelSize = Utils.calcTextSize(mAxisLabelPaint, longest); final float labelWidth = labelSize.width; final float labelHeight = Utils.calcTextHeight(mAxisLabelPaint, "Q"); @@ -69,8 +93,6 @@ public void computeAxis(float xValMaximumLength, List xValues) { mXAxis.mLabelHeight = Math.round(labelHeight); mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width + spaceSize.width); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); - - mXAxis.setValues(xValues); } @Override @@ -149,22 +171,22 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; + float[] positions = new float[mXAxis.mEntryCount * 2]; - for (int i = 0; i < mXAxis.getValues().size(); i++) { + for (int i = 0; i < positions.length; i += 2) { + // only fill x values + positions[i] = mXAxis.mEntries[i / 2]; + } - XAxisValue xVal = mXAxis.getValues().get(i); + mTrans.pointValuesToPixel(positions); - position[0] = (float) xVal.getPosition(); + for (int i = 0; i < positions.length; i += 2) { - mTrans.pointValuesToPixel(position); + float x = positions[i]; - if (mViewPortHandler.isInBoundsX(position[0])) { + if (mViewPortHandler.isInBoundsX(x)) { - String label = xVal.getLabel(); + String label = String.valueOf(mXAxis.mEntries[i / 2]); if (mXAxis.isAvoidFirstLastClippingEnabled()) { @@ -173,18 +195,18 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 - && position[0] + width > mViewPortHandler.getChartWidth()) - position[0] -= width / 2; + && x + width > mViewPortHandler.getChartWidth()) + x -= width / 2; // avoid clipping of the first } else if (i == 0) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); - position[0] += width / 2; + x += width / 2; } } - drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); + drawLabel(c, label, i, x, pos, anchor, labelRotationAngleDegrees); } } } @@ -200,10 +222,14 @@ public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; - // pre alloc - float[] position = new float[] { - 0f, 0f - }; + float[] positions = new float[mXAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + // only fill x values + positions[i] = mXAxis.mEntries[i / 2]; + } + + mTrans.pointValuesToPixel(positions); mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); @@ -211,16 +237,15 @@ public void renderGridLines(Canvas c) { Path gridLinePath = new Path(); - for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { + for (int i = 0; i < positions.length; i += 2) { - position[0] = i; - mTrans.pointValuesToPixel(position); + float x = positions[i]; - if (position[0] >= mViewPortHandler.offsetLeft() - && position[0] <= mViewPortHandler.getChartWidth()) { + if (x >= mViewPortHandler.offsetLeft() + && x <= mViewPortHandler.getChartWidth()) { - gridLinePath.moveTo(position[0], mViewPortHandler.contentBottom()); - gridLinePath.lineTo(position[0], mViewPortHandler.contentTop()); + gridLinePath.moveTo(x, mViewPortHandler.contentBottom()); + gridLinePath.lineTo(x, mViewPortHandler.contentTop()); // draw a path because lines don't support dashing on lower android versions c.drawPath(gridLinePath, mGridPaint); @@ -230,26 +255,26 @@ public void renderGridLines(Canvas c) { } } - /** - * Draws the LimitLines associated with this axis to the screen. - * - * @param c - */ - @Override - public void renderLimitLines(Canvas c) { + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + @Override + public void renderLimitLines(Canvas c) { - List limitLines = mXAxis.getLimitLines(); + List limitLines = mXAxis.getLimitLines(); - if (limitLines == null || limitLines.size() <= 0) - return; + if (limitLines == null || limitLines.size() <= 0) + return; float[] position = new float[2]; - for (int i = 0; i < limitLines.size(); i++) { + for (int i = 0; i < limitLines.size(); i++) { - LimitLine l = limitLines.get(i); + LimitLine l = limitLines.get(i); - if(!l.isEnabled()) + if (!l.isEnabled()) continue; position[0] = l.getLimit(); @@ -259,14 +284,13 @@ public void renderLimitLines(Canvas c) { renderLimitLineLine(c, l, position); renderLimitLineLabel(c, l, position, 2.f + l.getYOffset()); - } - } + } + } float[] mLimitLineSegmentsBuffer = new float[4]; private Path mLimitLinePath = new Path(); - public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) - { + public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) { mLimitLineSegmentsBuffer[0] = position[0]; mLimitLineSegmentsBuffer[1] = mViewPortHandler.contentTop(); mLimitLineSegmentsBuffer[2] = position[0]; @@ -284,8 +308,7 @@ public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) c.drawPath(mLimitLinePath, mLimitLinePaint); } - public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position, float yOffset) - { + public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position, float yOffset) { String label = limitLine.getLabel(); // if drawing the limit-value label is enabled @@ -305,7 +328,8 @@ public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, position[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + c.drawText(label, position[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, + mLimitLinePaint); } else if (labelPosition == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { mLimitLinePaint.setTextAlign(Align.LEFT); @@ -314,7 +338,8 @@ public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position mLimitLinePaint.setTextAlign(Align.RIGHT); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - c.drawText(label, position[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + c.drawText(label, position[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, + mLimitLinePaint); } else { mLimitLinePaint.setTextAlign(Align.RIGHT); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index d58c3842b5..8398301463 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -40,45 +40,45 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { - - position[0] = i * step + i * bd.getGroupSpace() - + bd.getGroupSpace() / 2f; - - // consider groups (center label for each group) - if (step > 1) { - position[0] += ((float) step - 1f) / 2f; - } - - mTrans.pointValuesToPixel(position); - - if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 - && i < mXAxis.getValues().size()) { - - String label = mXAxis.getValues().get(i).getLabel(); - - if (mXAxis.isAvoidFirstLastClippingEnabled()) { - - // avoid clipping of the last - if (i == mXAxis.getValues().size() - 1) { - float width = Utils.calcTextWidth(mAxisLabelPaint, label); - - if (position[0] + width / 2.f > mViewPortHandler.contentRight()) - position[0] = mViewPortHandler.contentRight() - (width / 2.f); - - // avoid clipping of the first - } else if (i == 0) { - - float width = Utils.calcTextWidth(mAxisLabelPaint, label); - - if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) - position[0] = mViewPortHandler.contentLeft() + (width / 2.f); - } - } - - drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); - } - } +// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { +// +// position[0] = i * step + i * bd.getGroupSpace() +// + bd.getGroupSpace() / 2f; +// +// // consider groups (center label for each group) +// if (step > 1) { +// position[0] += ((float) step - 1f) / 2f; +// } +// +// mTrans.pointValuesToPixel(position); +// +// if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 +// && i < mXAxis.getValues().size()) { +// +// String label = mXAxis.getValues().get(i).getLabel(); +// +// if (mXAxis.isAvoidFirstLastClippingEnabled()) { +// +// // avoid clipping of the last +// if (i == mXAxis.getValues().size() - 1) { +// float width = Utils.calcTextWidth(mAxisLabelPaint, label); +// +// if (position[0] + width / 2.f > mViewPortHandler.contentRight()) +// position[0] = mViewPortHandler.contentRight() - (width / 2.f); +// +// // avoid clipping of the first +// } else if (i == 0) { +// +// float width = Utils.calcTextWidth(mAxisLabelPaint, label); +// +// if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) +// position[0] = mViewPortHandler.contentLeft() + (width / 2.f); +// } +// } +// +// drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); +// } +// } } @Override @@ -97,17 +97,17 @@ public void renderGridLines(Canvas c) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - for (int i = mMinX; i < mMaxX; i += mXAxis.mAxisLabelModulus) { - - position[0] = i * step + i * bd.getGroupSpace() - 0.5f; - - mTrans.pointValuesToPixel(position); - - if (mViewPortHandler.isInBoundsX(position[0])) { - - c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], - mViewPortHandler.contentBottom(), mGridPaint); - } - } +// for (int i = mMinX; i < mMaxX; i += mXAxis.mAxisLabelModulus) { +// +// position[0] = i * step + i * bd.getGroupSpace() - 0.5f; +// +// mTrans.pointValuesToPixel(position); +// +// if (mViewPortHandler.isInBoundsX(position[0])) { +// +// c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], +// mViewPortHandler.contentBottom(), mGridPaint); +// } +// } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 01b17f3904..ed45549050 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -28,11 +28,10 @@ public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xA } @Override - public void computeAxis(float xValAverageLength, List xValues) { + protected void computeAxis() { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mXAxis.setValues(xValues); String longest = mXAxis.getLongestLabel(); @@ -111,24 +110,24 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { BarData bd = mChart.getData(); int step = bd.getDataSetCount(); - for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { - - position[1] = i * step + i * bd.getGroupSpace() - + bd.getGroupSpace() / 2f; - - // consider groups (center label for each group) - if (step > 1) { - position[1] += ((float) step - 1f) / 2f; - } - - mTrans.pointValuesToPixel(position); - - if (mViewPortHandler.isInBoundsY(position[1])) { - - String label = mXAxis.getValues().get(i).getLabel(); - drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); - } - } +// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { +// +// position[1] = i * step + i * bd.getGroupSpace() +// + bd.getGroupSpace() / 2f; +// +// // consider groups (center label for each group) +// if (step > 1) { +// position[1] += ((float) step - 1f) / 2f; +// } +// +// mTrans.pointValuesToPixel(position); +// +// if (mViewPortHandler.isInBoundsY(position[1])) { +// +// String label = mXAxis.getValues().get(i).getLabel(); +// drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); +// } +// } } @Override @@ -148,18 +147,18 @@ public void renderGridLines(Canvas c) { // take into consideration that multiple DataSets increase mDeltaX int step = bd.getDataSetCount(); - for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { - - position[1] = i * step + i * bd.getGroupSpace() - 0.5f; - - mTrans.pointValuesToPixel(position); - - if (mViewPortHandler.isInBoundsY(position[1])) { - - c.drawLine(mViewPortHandler.contentLeft(), position[1], - mViewPortHandler.contentRight(), position[1], mGridPaint); - } - } +// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { +// +// position[1] = i * step + i * bd.getGroupSpace() - 0.5f; +// +// mTrans.pointValuesToPixel(position); +// +// if (mViewPortHandler.isInBoundsY(position[1])) { +// +// c.drawLine(mViewPortHandler.contentLeft(), position[1], +// mViewPortHandler.contentRight(), position[1], mGridPaint); +// } +// } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index fdae353e4b..94b7673205 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -37,40 +37,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mZeroLinePaint.setStyle(Paint.Style.STROKE); } - /** - * Computes the axis values. - * - * @param yMin - the minimum y-value in the data object for this axis - * @param yMax - the maximum y-value in the data object for this axis - */ - public void computeAxis(float yMin, float yMax) { - - // calculate the starting and entry point of the y-labels (depending on - // zoom / contentrect bounds) - if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { - - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); - - if (!mYAxis.isInverted()) { - yMin = (float) p2.y; - yMax = (float) p1.y; - } else { - - yMin = (float) p1.y; - yMax = (float) p2.y; - } - } - - computeAxisValues(yMin, yMax); - } - - /** - * Sets up the y-axis labels. Computes the desired number of labels between the two given extremes. Unlike the - * papareXLabels() method, this method needs to be called upon every refresh of the view. - * - * @return - */ + @Override protected void computeAxisValues(float min, float max) { float yMin = min; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index bcd63778a0..4ce4879e3b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -33,7 +33,8 @@ public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yA * @param yMin - the minimum y-value in the data object for this axis * @param yMax - the maximum y-value in the data object for this axis */ - public void computeAxis(float yMin, float yMax) { + @Override + public void computeAxis(float yMin, float yMax, boolean inverted) { // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) @@ -44,7 +45,7 @@ public void computeAxis(float yMin, float yMax) { PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); - if (!mYAxis.isInverted()) { + if (!inverted) { yMin = (float) p1.x; yMax = (float) p2.x; } else { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 66ddd3ceea..68415ba67f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -23,7 +23,7 @@ public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, Rad } @Override - public void computeAxis(float yMin, float yMax) { + public void computeAxis(float yMin, float yMax, boolean inverted) { computeAxisValues(yMin, yMax); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java b/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java index e8d815e717..cf62492390 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java @@ -11,6 +11,12 @@ public class EntryXIndexComparator implements Comparator { @Override public int compare(Entry entry1, Entry entry2) { - return entry1.getX() - entry2.getX(); + float diff = entry1.getX() - entry2.getX(); + + if (diff == 0f) return 0; + else { + if (diff > 0f) return 1; + else return -1; + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java index 56f54d3175..6632c23d60 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java @@ -191,7 +191,7 @@ public static List loadEntriesFromAssets(AssetManager am, String path) { /** * Saves an Array of Entries to the specified location on the sdcard * - * @param ds + * @param entries * @param path */ public static void saveToSdCard(List entries, String path) { @@ -242,7 +242,7 @@ public static List loadBarEntriesFromAssets(AssetManager am, String pa // process line String[] split = line.split("#"); - entries.add(new BarEntry(Float.parseFloat(split[0]), Integer.parseInt(split[1]))); + entries.add(new BarEntry(Float.parseFloat(split[1]), Integer.parseInt(split[0]))); line = reader.readLine(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index cb0e083880..15f71cc3a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -232,7 +232,7 @@ public float[] generateTransformedValuesBarChart(IBarDataSet data, for (int j = 0; j < valuePoints.length; j += 2) { Entry e = data.getEntryForIndex(j / 2); - int i = e.getX(); + float i = e.getX(); // calculate the x-position, depending on datasetcount float x = e.getX() + i * (setCount - 1) + dataSetIndex + space * i @@ -267,7 +267,7 @@ public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, for (int j = 0; j < valuePoints.length; j += 2) { Entry e = data.getEntryForIndex(j / 2); - int i = e.getX(); + float i = e.getX(); // calculate the x-position, depending on datasetcount float x = i + i * (setCount - 1) + dataSet + space * i From ec6752567b52bd558cdf31b1a051481868a25260 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 30 May 2016 14:52:17 +0200 Subject: [PATCH 0909/1390] Work on barcharts with new x-value --- .../mpchartexample/RadarChartActivitry.java | 10 +++-- .../mikephil/charting/buffer/BarBuffer.java | 41 ++++++++++++------ .../mikephil/charting/charts/BarChart.java | 22 +++++----- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 2 +- .../mikephil/charting/components/XAxis.java | 8 ++-- .../charting/renderer/BarChartRenderer.java | 2 + .../charting/renderer/RadarChartRenderer.java | 2 +- .../charting/renderer/XAxisRenderer.java | 42 ++++++++++++++----- .../XAxisRendererHorizontalBarChart.java | 2 +- .../renderer/YAxisRendererRadarChart.java | 5 --- 11 files changed, 87 insertions(+), 51 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 6402e0e60d..e843e09f08 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -170,7 +170,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleSpin: { - mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption.EaseInCubic); + mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption + .EaseInCubic); break; } } @@ -194,11 +195,13 @@ public void setData() { // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < cnt; i++) { - yVals1.add(new Entry((float) (Math.random() * mult) + mult / 2, i)); + float val = (float) (Math.random() * mult) + mult / 2; + yVals1.add(new Entry(i, val)); } for (int i = 0; i < cnt; i++) { - yVals2.add(new Entry((float) (Math.random() * mult) + mult / 2, i)); + float val = (float) (Math.random() * mult) + mult / 2; + yVals2.add(new Entry(i, val)); } ArrayList xVals = new ArrayList(); @@ -228,7 +231,6 @@ public void setData() { data.setDrawValues(false); mChart.setData(data); - mChart.invalidate(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 95e1336d9a..3b001c466d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -13,6 +13,9 @@ public class BarBuffer extends AbstractBuffer { protected boolean mContainsStacks = false; protected boolean mInverted = false; + /** interval on the x-axis per group */ + protected float mInterval = 0f; + public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { super(size); this.mGroupSpace = groupspace; @@ -20,6 +23,10 @@ public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsS this.mContainsStacks = containsStacks; } + public void setInterval(float interval) { + this.mInterval = interval; + } + public void setBarSpace(float barspace) { this.mBarSpace = barspace; } @@ -27,7 +34,7 @@ public void setBarSpace(float barspace) { public void setDataSet(int index) { this.mDataSetIndex = index; } - + public void setInverted(boolean inverted) { this.mInverted = inverted; } @@ -45,25 +52,33 @@ public void feed(IBarDataSet data) { float size = data.getEntryCount() * phaseX; - int dataSetOffset = (mDataSetCount - 1); - float barSpaceHalf = mBarSpace / 2f; - float groupSpaceHalf = mGroupSpace / 2f; - float barWidth = 0.5f; + float barWidth = mInterval / mDataSetCount; + + float groupSpaceWidth = mDataSetCount <= 1 ? 0 : barWidth * mGroupSpace; + float newInterval = (mInterval - groupSpaceWidth); + float newBarWidth = newInterval / mDataSetCount; + + float barSpaceWidth = newBarWidth * mBarSpace; + float barSpaceWidthHalf = barSpaceWidth / 2f; + + float groupSpaceWidthHalf = groupSpaceWidth / 2f; + float dataSetSpace = mDataSetCount <= 1 ? 0 : (newInterval / mDataSetCount) * mDataSetIndex; + for (int i = 0; i < size; i++) { BarEntry e = data.getEntryForIndex(i); - // calculate the x-position, depending on datasetcount - float x = e.getX() + e.getX() * dataSetOffset + mDataSetIndex - + mGroupSpace * e.getX() + groupSpaceHalf; + // calculate the x-position, depending on interval + float x = mInterval * i + dataSetSpace; + float y = e.getY(); float [] vals = e.getYVals(); - + if (!mContainsStacks || vals == null) { - float left = x - barWidth + barSpaceHalf; - float right = x + barWidth - barSpaceHalf; + float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; + float right = left + newBarWidth - barSpaceWidth; float bottom, top; if (mInverted) { bottom = y >= 0 ? y : 0; @@ -102,8 +117,8 @@ public void feed(IBarDataSet data) { negY += Math.abs(value); } - float left = x - barWidth + barSpaceHalf; - float right = x + barWidth - barSpaceHalf; + float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; + float right = left + newBarWidth - barSpaceWidth; float bottom, top; if (mInverted) { bottom = y >= yStart ? y : yStart; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 4cef155a59..9eed5a3f8d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -56,22 +56,22 @@ protected void init() { setHighlighter(new BarHighlighter(this)); - mXAxis.mAxisMinimum = -0.5f; + //mXAxis.mAxisMinimum = -0.5f; } @Override protected void calcMinMax() { super.calcMinMax(); - - // increase deltax by 1 because the bars have a width of 1 - mXAxis.mAxisRange += 0.5f; - - // extend xDelta to make space for multiple datasets (if ther are one) - mXAxis.mAxisRange *= mData.getDataSetCount(); - - float groupSpace = mData.getGroupSpace(); - mXAxis.mAxisRange += mData.getXValCount() * groupSpace; - mXAxis.mAxisMaximum = mXAxis.mAxisRange - mXAxis.mAxisMinimum; +// +// // increase deltax by 1 because the bars have a width of 1 +// mXAxis.mAxisRange += 0.5f; +// +// // extend xDelta to make space for multiple datasets (if ther are one) +// mXAxis.mAxisRange *= mData.getDataSetCount(); +// +// float groupSpace = mData.getGroupSpace(); +// mXAxis.mAxisRange += mData.getXValCount() * groupSpace; +// mXAxis.mAxisMaximum = mXAxis.mAxisRange - mXAxis.mAxisMinimum; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c5df174efe..64a22aa107 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -347,7 +347,7 @@ public void notifyDataSetChanged() { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted()); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted()); - //mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); + //mXAxisRenderer.computeSize(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 13d0ac9c1d..e80066d6b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -135,7 +135,7 @@ public void notifyDataSetChanged() { mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); - //mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); + //mXAxisRenderer.computeSize(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null && !mLegend.isLegendCustom()) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 5089f1cbad..d49605c3b8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -23,25 +23,25 @@ public class XAxis extends AxisBase { /** * width of the x-axis labels in pixels - this is automatically - * calculated by the computeAxis() methods in the renderers + * calculated by the computeSize() methods in the renderers */ public int mLabelWidth = 1; /** * height of the x-axis labels in pixels - this is automatically - * calculated by the computeAxis() methods in the renderers + * calculated by the computeSize() methods in the renderers */ public int mLabelHeight = 1; /** * width of the (rotated) x-axis labels in pixels - this is automatically - * calculated by the computeAxis() methods in the renderers + * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedWidth = 1; /** * height of the (rotated) x-axis labels in pixels - this is automatically - * calculated by the computeAxis() methods in the renderers + * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedHeight = 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 9e522272fd..51bb35a7b7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -99,6 +99,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setBarSpace(dataSet.getBarSpace()); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); + buffer.setInterval(mChart.getXChartMax() / dataSet.getEntryCount()); buffer.feed(dataSet); @@ -192,6 +193,7 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHa @Override public void drawValues(Canvas c) { + // if values are drawn if (passesCheck()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index b0717a2322..206a85add2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -233,7 +233,7 @@ protected void drawWeb(Canvas c) { mWebPaint.setColor(mChart.getWebColorInner()); mWebPaint.setAlpha(mChart.getWebAlpha()); - int labelCount = mChart.getYAxis().mEntryCount; + int labelCount = mChart.getYAxis().mEntries.length; for (int j = 0; j < labelCount; j++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index bd2c64f7ba..3f28571f10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -33,6 +33,30 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } + @Override + public void computeAxis(float min, float max, boolean inverted) { + + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); + + if (inverted) { + + min = (float) p2.x; + max = (float) p1.x; + } else { + + min = (float) p1.x; + max = (float) p2.x; + } + } + + computeAxisValues(min, max); + } + @Override protected void computeAxisValues(float min, float max) { @@ -43,12 +67,13 @@ protected void computeAxisValues(float min, float max) { if (mXAxis.mEntries == null || mXAxis.mEntries.length != labelCount) { mXAxis.mEntries = new float[labelCount]; + mXAxis.mEntryCount = labelCount; } - mXAxis.mEntries[0] = 0f; + mXAxis.mEntries[0] = min; for (int i = 1; i < labelCount; i++) { - mXAxis.mEntries[i] = interval * (float) i; + mXAxis.mEntries[i] = min + interval * (float) i; } // set decimals @@ -58,12 +83,10 @@ protected void computeAxisValues(float min, float max) { mXAxis.mDecimals = 0; } - if (mXAxis.getValues() != null && !mXAxis.getValues().isEmpty()) { - computeAxis(); - } + computeSize(); } - protected void computeAxis() { + protected void computeSize() { String longest = mXAxis.getLongestLabel(); @@ -171,7 +194,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - float[] positions = new float[mXAxis.mEntryCount * 2]; + float[] positions = new float[mXAxis.mEntries.length * 2]; for (int i = 0; i < positions.length; i += 2) { // only fill x values @@ -222,7 +245,7 @@ public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; - float[] positions = new float[mXAxis.mEntryCount * 2]; + float[] positions = new float[mXAxis.mEntries.length * 2]; for (int i = 0; i < positions.length; i += 2) { // only fill x values @@ -347,5 +370,4 @@ public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position } } } - } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index ed45549050..44107750ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -28,7 +28,7 @@ public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xA } @Override - protected void computeAxis() { + protected void computeSize() { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 68415ba67f..e06d2fcbf8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -22,11 +22,6 @@ public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, Rad this.mChart = chart; } - @Override - public void computeAxis(float yMin, float yMax, boolean inverted) { - computeAxisValues(yMin, yMax); - } - @Override protected void computeAxisValues(float min, float max) { float yMin = min; From 7db6b7ea4af0cd914bf5671e204c6411619350d7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 30 May 2016 15:44:03 +0200 Subject: [PATCH 0910/1390] Work on barchart rendering --- .../mpchartexample/StackedBarActivity.java | 7 +- .../mikephil/charting/buffer/BarBuffer.java | 10 ++- .../mikephil/charting/charts/Chart.java | 5 ++ .../dataprovider/ChartInterface.java | 2 + .../charting/renderer/BarChartRenderer.java | 84 +++++++++++-------- .../mikephil/charting/utils/Transformer.java | 37 -------- 6 files changed, 69 insertions(+), 76 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 76267ccac5..ce9419e5dc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -24,6 +24,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -59,7 +60,7 @@ protected void onCreate(Bundle savedInstanceState) { // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + mChart.setMaxVisibleValueCount(40); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); @@ -261,6 +262,10 @@ private int[] getColors() { // have as many colors as stack-values per entry int[] colors = new int[stacksize]; + for(int i = 0; i < colors.length; i++) { + colors[i] = ColorTemplate.MATERIAL_COLORS[i]; + } + return colors; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 3b001c466d..91fc8c769a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -13,7 +13,9 @@ public class BarBuffer extends AbstractBuffer { protected boolean mContainsStacks = false; protected boolean mInverted = false; - /** interval on the x-axis per group */ + /** + * interval on the x-axis per group + */ protected float mInterval = 0f; public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { @@ -73,13 +75,14 @@ public void feed(IBarDataSet data) { float x = mInterval * i + dataSetSpace; float y = e.getY(); - float [] vals = e.getYVals(); + float[] vals = e.getYVals(); if (!mContainsStacks || vals == null) { float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; float right = left + newBarWidth - barSpaceWidth; float bottom, top; + if (mInverted) { bottom = y >= 0 ? y : 0; top = y <= 0 ? y : 0; @@ -107,7 +110,7 @@ public void feed(IBarDataSet data) { float value = vals[k]; - if(value >= 0f) { + if (value >= 0f) { y = posY; yStart = posY + value; posY = yStart; @@ -120,6 +123,7 @@ public void feed(IBarDataSet data) { float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; float right = left + newBarWidth - barSpaceWidth; float bottom, top; + if (mInverted) { bottom = y >= yStart ? y : yStart; top = y <= yStart ? y : yStart; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 37a24ad1bd..2b3ffde109 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1018,6 +1018,11 @@ public float getXChartMin() { return mXAxis.mAxisMinimum; } + @Override + public float getXRange() { + return mXAxis.mAxisRange; + } + @Override public int getXValCount() { return mData.getXValCount(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 350d35e644..a7f9544ed8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -28,6 +28,8 @@ public interface ChartInterface { */ float getXChartMax(); + float getXRange(); + /** * Returns the minimum y-value of the chart, regardless of zoom or translation. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 51bb35a7b7..ecc30e9f84 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -25,7 +25,9 @@ public class BarChartRenderer extends DataRenderer { protected BarDataProvider mChart; - /** the rect object that is used for drawing the bars */ + /** + * the rect object that is used for drawing the bars + */ protected RectF mBarRect = new RectF(); protected BarBuffer[] mBarBuffers; @@ -34,7 +36,7 @@ public class BarChartRenderer extends DataRenderer { protected Paint mBarBorderPaint; public BarChartRenderer(BarDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); this.mChart = chart; @@ -99,7 +101,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setBarSpace(dataSet.getBarSpace()); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); - buffer.setInterval(mChart.getXChartMax() / dataSet.getEntryCount()); + buffer.setInterval(mChart.getXRange() / dataSet.getEntryCount()); buffer.feed(dataSet); @@ -169,15 +171,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { /** * Prepares a bar for being highlighted. - * - * @param x the x-position - * @param y1 the y1-position - * @param y2 the y2-position + * + * @param x the x-position + * @param y1 the y1-position + * @param y2 the y2-position * @param barspaceHalf the space between bars * @param trans */ protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, - Transformer trans) { + Transformer trans) { float barWidth = 0.5f; @@ -227,58 +229,66 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextHeight; } - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - - float[] valuePoints = getTransformedValues(trans, dataSet, i); + // get the buffer + BarBuffer buffer = mBarBuffers[i]; // if only single values are drawn (sum) if (!dataSet.isStacked()) { - for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) { - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + float x = (buffer.buffer[j] + buffer.buffer[j + 2]) / 2f; + + if (!mViewPortHandler.isInBoundsRight(x)) break; - if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) - || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + if (!mViewPortHandler.isInBoundsY(buffer.buffer[j + 1]) + || !mViewPortHandler.isInBoundsLeft(x)) continue; - BarEntry entry = dataSet.getEntryForIndex(j / 2); + BarEntry entry = dataSet.getEntryForIndex(j / 4); float val = entry.getY(); - drawValue(c, dataSet.getValueFormatter(), val, entry, i, valuePoints[j], - valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset), dataSet.getValueTextColor(j / 2)); + drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, + buffer.buffer[j + 1] + (val >= 0 ? posOffset : negOffset), dataSet.getValueTextColor + (j / 4)); } // if we have stacks } else { - for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + int bufferIndex = 0; + int index = 0; - BarEntry entry = dataSet.getEntryForIndex(j / 2); + while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) { + + BarEntry entry = dataSet.getEntryForIndex(index); float[] vals = entry.getYVals(); + float x = (buffer.buffer[bufferIndex] + buffer.buffer[bufferIndex + 2]) / 2f; + + int color = dataSet.getValueTextColor(index); // we still draw stacked bars, but there is one // non-stacked // in between if (vals == null) { - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + if (!mViewPortHandler.isInBoundsRight(x)) break; - if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) - || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + if (!mViewPortHandler.isInBoundsY(buffer.buffer[bufferIndex + 1]) + || !mViewPortHandler.isInBoundsLeft(x)) continue; - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, valuePoints[j], - valuePoints[j + 1] + (entry.getY() >= 0 ? posOffset : negOffset), dataSet.getValueTextColor(j / 2)); + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), color); // draw stack values } else { - int color = dataSet.getValueTextColor(j / 2); - float[] transformed = new float[vals.length * 2]; float posY = 0f; @@ -304,7 +314,6 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { - float x = valuePoints[j]; float y = transformed[k + 1] + (vals[k / 2] >= 0 ? posOffset : negOffset); @@ -318,6 +327,9 @@ public void drawValues(Canvas c) { drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y, color); } } + + bufferIndex = vals == null ? bufferIndex + 4 : bufferIndex + 4 * vals.length; + index++; } } } @@ -341,8 +353,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (maxDataSetIndex - minDataSetIndex < 1) continue; for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { + dataSetIndex < maxDataSetIndex; + dataSetIndex++) { IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); @@ -420,10 +432,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } public float[] getTransformedValues(Transformer trans, IBarDataSet data, - int dataSetIndex) { - return trans.generateTransformedValuesBarChart(data, dataSetIndex, - mChart.getBarData(), - mAnimator.getPhaseY()); + int dataSetIndex) { +// return trans.generateTransformedValuesBarChart(data, dataSetIndex, +// mChart.getBarData(), +// mAnimator.getPhaseY()); + return null; } protected boolean passesCheck() { @@ -432,5 +445,6 @@ protected boolean passesCheck() { } @Override - public void drawExtras(Canvas c) { } + public void drawExtras(Canvas c) { + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 15f71cc3a8..d7f19d3992 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -211,43 +211,6 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, return valuePoints; } - /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the BARCHART. - * - * @param data - * @param dataSetIndex the dataset index - * @param bd - * @param phaseY - * @return - */ - public float[] generateTransformedValuesBarChart(IBarDataSet data, - int dataSetIndex, BarData bd, float phaseY) { - - float[] valuePoints = new float[data.getEntryCount() * 2]; - - int setCount = bd.getDataSetCount(); - float space = bd.getGroupSpace(); - - for (int j = 0; j < valuePoints.length; j += 2) { - - Entry e = data.getEntryForIndex(j / 2); - float i = e.getX(); - - // calculate the x-position, depending on datasetcount - float x = e.getX() + i * (setCount - 1) + dataSetIndex + space * i - + space / 2f; - float y = e.getY(); - - valuePoints[j] = x; - valuePoints[j + 1] = y * phaseY; - } - - getValueToPixelMatrix().mapPoints(valuePoints); - - return valuePoints; - } - /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. From 690dd87a062d1d7484d6788fa7c045f884d2b614 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 30 May 2016 17:21:18 +0200 Subject: [PATCH 0911/1390] Work on highlighting --- .../mpchartexample/StackedBarActivity.java | 460 +++++++++--------- .../StackedBarActivityNegative.java | 22 +- .../mikephil/charting/charts/Chart.java | 8 +- .../mikephil/charting/charts/PieChart.java | 11 +- .../charting/charts/PieRadarChartBase.java | 3 +- .../mikephil/charting/data/BarEntry.java | 374 +++++++------- .../mikephil/charting/data/ChartData.java | 6 +- .../mikephil/charting/data/CombinedData.java | 6 +- .../mikephil/charting/data/DataSet.java | 22 +- .../data/realm/base/RealmBaseDataSet.java | 90 ++-- .../realm/implementation/RealmBarDataSet.java | 23 +- .../implementation/RealmBubbleDataSet.java | 6 +- .../implementation/RealmCandleDataSet.java | 2 +- .../charting/highlight/BarHighlighter.java | 26 +- .../charting/highlight/ChartHighlighter.java | 27 +- .../highlight/CombinedHighlighter.java | 6 +- .../charting/highlight/Highlight.java | 46 +- .../highlight/HorizontalBarHighlighter.java | 10 +- .../interfaces/datasets/IDataSet.java | 24 +- .../charting/renderer/BarChartRenderer.java | 109 ++--- .../renderer/BubbleChartRenderer.java | 5 +- .../renderer/CandleStickChartRenderer.java | 8 +- .../renderer/HorizontalBarChartRenderer.java | 1 - .../charting/renderer/LineChartRenderer.java | 8 +- .../charting/renderer/PieChartRenderer.java | 16 +- .../charting/renderer/RadarChartRenderer.java | 6 +- .../renderer/ScatterChartRenderer.java | 8 +- .../mikephil/charting/utils/FileUtils.java | 4 +- 28 files changed, 672 insertions(+), 665 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index ce9419e5dc..36fd6f1d33 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -1,5 +1,6 @@ package com.xxmassdeveloper.mpchartexample; +import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -34,237 +35,238 @@ public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart); - - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = (BarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - - mChart.setDescription(""); - - // if more than 60 entries are displayed in the chart, no values will be - // drawn - mChart.setMaxVisibleValueCount(40); - - // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - - mChart.setDrawValueAboveBar(false); - - // change the position of the y-labels - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setValueFormatter(new MyYAxisValueFormatter()); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); - - XAxis xLabels = mChart.getXAxis(); - xLabels.setPosition(XAxisPosition.TOP); - - // mChart.setDrawXLabels(false); - // mChart.setDrawYLabels(false); - - // setting data - mSeekBarX.setProgress(12); - mSeekBarY.setProgress(100); - - Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_RIGHT); - l.setFormSize(8f); - l.setFormToTextSpace(4f); - l.setXEntrySpace(6f); - - // mChart.setDrawLegend(false); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.bar, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - List sets = mChart.getData() - .getDataSets(); - - for (IBarDataSet iSet : sets) { - - BarDataSet set = (BarDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); - } - - mChart.invalidate(); - break; - } - case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); - } - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) - ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - - mChart.invalidate(); - break; - } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000); - break; - } - case R.id.animateXY: { - - mChart.animateXY(3000, 3000); - break; - } - case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT).show(); - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add(new XAxisValue(i, mMonths[i % mMonths.length])); - } - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val1 = (float) (Math.random() * mult) + mult / 3; - float val2 = (float) (Math.random() * mult) + mult / 3; - float val3 = (float) (Math.random() * mult) + mult / 3; - - yVals1.add(new BarEntry(new float[] { val1, val2, val3 }, i)); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals1); - mChart.getData().setXVals(xVals); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setColors(getColors()); - set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(xVals, dataSets); - data.setValueFormatter(new MyValueFormatter()); - - mChart.setData(data); - } - - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { - - BarEntry entry = (BarEntry) e; - - if (entry.getYVals() != null) - Log.i("VAL SELECTED", "Value: " + entry.getYVals()[h.getStackIndex()]); - else - Log.i("VAL SELECTED", "Value: " + entry.getY()); - } - - @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } - - private int[] getColors() { - - int stacksize = 3; + private BarChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; - // have as many colors as stack-values per entry - int[] colors = new int[stacksize]; + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart); - for(int i = 0; i < colors.length; i++) { - colors[i] = ColorTemplate.MATERIAL_COLORS[i]; - } + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX.setOnSeekBarChangeListener(this); + + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY.setOnSeekBarChangeListener(this); + + mChart = (BarChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + + mChart.setDescription(""); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + mChart.setMaxVisibleValueCount(40); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + mChart.setDrawGridBackground(false); + mChart.setDrawBarShadow(false); + + mChart.setDrawValueAboveBar(false); + + // change the position of the y-labels + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setValueFormatter(new MyYAxisValueFormatter()); + leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + mChart.getAxisRight().setEnabled(false); + + XAxis xLabels = mChart.getXAxis(); + xLabels.setPosition(XAxisPosition.TOP); + + // mChart.setDrawXLabels(false); + // mChart.setDrawYLabels(false); + + // setting data + mSeekBarX.setProgress(12); + mSeekBarY.setProgress(100); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.BELOW_CHART_RIGHT); + l.setFormSize(8f); + l.setFormToTextSpace(4f); + l.setXEntrySpace(6f); + + // mChart.setDrawLegend(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + BarDataSet set = (BarDataSet) iSet; + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); + mChart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlightArrow: { + if (mChart.isDrawHighlightArrowEnabled()) + mChart.setDrawHighlightArrow(false); + else + mChart.setDrawHighlightArrow(true); + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT).show(); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { + xVals.add(new XAxisValue(i, mMonths[i % mMonths.length])); + } + + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { + float mult = (mSeekBarY.getProgress() + 1); + float val1 = (float) (Math.random() * mult) + mult / 3; + float val2 = (float) (Math.random() * mult) + mult / 3; + float val3 = (float) (Math.random() * mult) + mult / 3; + + yVals1.add(new BarEntry(i, new float[]{val1, val2, val3})); + } + + BarDataSet set1; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); + set1.setYVals(yVals1); + mChart.getData().setXVals(xVals); + mChart.getData().notifyDataChanged(); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); + set1.setColors(getColors()); + set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); + + BarData data = new BarData(xVals, dataSets); + data.setValueFormatter(new MyValueFormatter()); + data.setValueTextColor(Color.WHITE); + + mChart.setData(data); + } + + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + + BarEntry entry = (BarEntry) e; + + if (entry.getYVals() != null) + Log.i("VAL SELECTED", "Value: " + entry.getYVals()[h.getStackIndex()]); + else + Log.i("VAL SELECTED", "Value: " + entry.getY()); + } + + @Override + public void onNothingSelected() { + // TODO Auto-generated method stub + + } + + private int[] getColors() { + + int stacksize = 3; + + // have as many colors as stack-values per entry + int[] colors = new int[stacksize]; + + for (int i = 0; i < colors.length; i++) { + colors[i] = ColorTemplate.MATERIAL_COLORS[i]; + } return colors; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 012065683e..ddd8ac3fcf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -80,17 +80,17 @@ protected void onCreate(Bundle savedInstanceState) { // IMPORTANT: When using negative values in stacked bars, always make sure the negative values are in the array first ArrayList yValues = new ArrayList(); - yValues.add(new BarEntry(new float[]{ -10, 10 }, 0)); - yValues.add(new BarEntry(new float[]{ -12, 13 }, 1)); - yValues.add(new BarEntry(new float[]{ -15, 15 }, 2)); - yValues.add(new BarEntry(new float[]{ -17, 17 }, 3)); - yValues.add(new BarEntry(new float[]{ -19, 20 }, 4)); - yValues.add(new BarEntry(new float[]{ -19, 19 }, 5)); - yValues.add(new BarEntry(new float[]{ -16, 16 }, 6)); - yValues.add(new BarEntry(new float[]{ -13, 14 }, 7)); - yValues.add(new BarEntry(new float[]{ -10, 11 }, 8)); - yValues.add(new BarEntry(new float[]{ -5, 6 }, 9)); - yValues.add(new BarEntry(new float[]{ -1, 2 }, 10)); + yValues.add(new BarEntry(0, new float[]{ -10, 10 })); + yValues.add(new BarEntry(1, new float[]{ -12, 13 })); + yValues.add(new BarEntry(2, new float[]{ -15, 15 })); + yValues.add(new BarEntry(3, new float[]{ -17, 17 })); + yValues.add(new BarEntry(4, new float[]{ -19, 20 })); + yValues.add(new BarEntry(5, new float[]{ -19, 19 })); + yValues.add(new BarEntry(6, new float[]{ -16, 16 })); + yValues.add(new BarEntry(7, new float[]{ -13, 14 })); + yValues.add(new BarEntry(8, new float[]{ -10, 11 })); + yValues.add(new BarEntry(9, new float[]{ -5, 6 })); + yValues.add(new BarEntry(10, new float[]{ -1, 2 })); BarDataSet set = new BarDataSet(yValues, "Age Distribution"); set.setValueFormatter(new CustomFormatter()); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 2b3ffde109..e492d74e5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -614,7 +614,7 @@ public void highlightValue(Highlight high, boolean callListener) { } else { if (this instanceof BarLineChartBase && ((BarLineChartBase)this).isHighlightFullBarEnabled()) - high = new Highlight(high.getXIndex(), Float.NaN, -1, -1, -1); + high = new Highlight(high.getX(), Float.NaN, -1, -1, -1); // set the indices to highlight mIndicesToHighlight = new Highlight[]{ @@ -681,19 +681,19 @@ protected void drawMarkers(Canvas canvas) { for (int i = 0; i < mIndicesToHighlight.length; i++) { Highlight highlight = mIndicesToHighlight[i]; - int xIndex = highlight.getXIndex(); + float xVal = highlight.getX(); int dataSetIndex = highlight.getDataSetIndex(); float deltaX = mXAxis != null ? mXAxis.mAxisRange : ((mData == null ? 0.f : mData.getXValCount()) - 1.f); - if (xIndex <= deltaX && xIndex <= deltaX * mAnimator.getPhaseX()) { + if (xVal <= deltaX && xVal <= deltaX * mAnimator.getPhaseX()) { Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); // make sure entry not null - if (e == null || e.getX() != mIndicesToHighlight[i].getXIndex()) + if (e == null || e.getX() != mIndicesToHighlight[i].getX()) continue; float[] pos = getMarkerPosition(e, highlight); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 74fbd2549d..ba8e37c8ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -10,6 +10,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.highlight.Highlight; @@ -180,17 +181,17 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { float rotationAngle = getRotationAngle(); - int i = highlight.getXIndex(); + int entryIndex = getData().getDataSet().getEntryIndex(highlight.getX(), DataSet.Rounding.CLOSEST); // offset needed to center the drawn text in the slice - float offset = mDrawAngles[i] / 2; + float offset = mDrawAngles[entryIndex] / 2; // calculate the text position float x = (float) (r - * Math.cos(Math.toRadians((rotationAngle + mAbsoluteAngles[i] - offset) + * Math.cos(Math.toRadians((rotationAngle + mAbsoluteAngles[entryIndex] - offset) * mAnimator.getPhaseY())) + center.x); float y = (float) (r - * Math.sin(Math.toRadians((rotationAngle + mAbsoluteAngles[i] - offset) + * Math.sin(Math.toRadians((rotationAngle + mAbsoluteAngles[entryIndex] - offset) * mAnimator.getPhaseY())) + center.y); return new float[]{x, y}; @@ -247,7 +248,7 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { for (int i = 0; i < mIndicesToHighlight.length; i++) // check if the xvalue for the given dataset needs highlight - if (mIndicesToHighlight[i].getXIndex() == xIndex + if (mIndicesToHighlight[i].getX() == xIndex && mIndicesToHighlight[i].getDataSetIndex() == dataSetIndex) return true; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 9c31414ced..2c55c24125 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -14,7 +14,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; @@ -458,7 +457,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { IDataSet dataSet = mData.getDataSetByIndex(i); // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValForXIndex(xIndex); + final float yVal = dataSet.getYValueForXValue(xIndex); if (Float.isNaN(yVal)) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index 6f5a8c5c47..97358ae378 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -4,195 +4,197 @@ /** * Entry class for the BarChart. (especially stacked bars) - * + * * @author Philipp Jahoda */ @SuppressLint("ParcelCreator") public class BarEntry extends Entry { - /** the values the stacked barchart holds */ - private float[] mYVals; - - /** the sum of all negative values this entry (if stacked) contains */ - private float mNegativeSum; - - /** the sum of all positive values this entry (if stacked) contains */ - private float mPositiveSum; - - /** - * Constructor for stacked bar entries. - * - * @param vals - * - the stack values, use at lest 2 - * @param x - */ - public BarEntry(float[] vals, float x) { - super(x, calcSum(vals)); - - this.mYVals = vals; - calcPosNegSum(); - } - - /** - * Constructor for normal bars (not stacked). - * - * @param x - * @param y - */ - public BarEntry(float x, float y) { - super(x, y); - } - - /** - * Constructor for stacked bar entries. - * - * @param x - * @param vals - * - the stack values, use at least 2 - * @param label - * Additional description label. - */ - public BarEntry(float x, float[] vals, String label) { - super(x, calcSum(vals), label); - - this.mYVals = vals; - calcPosNegSum(); - } - - /** - * Constructor for normal bars (not stacked). - * - * @param x - * @param y - * @param data - * Spot for additional data this Entry represents. - */ - public BarEntry(float x, float y, Object data) { - super(x, y, data); - } - - /** - * Returns an exact copy of the BarEntry. - */ - public BarEntry copy() { - - BarEntry copied = new BarEntry(getX(), getY(), getData()); - copied.setVals(mYVals); - return copied; - } - - /** - * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use - * getY()). - * - * @return - */ - public float[] getYVals() { - return mYVals; - } - - /** - * Set the array of values this BarEntry should represent. - * - * @param vals - */ - public void setVals(float[] vals) { - setY(calcSum(vals)); - mYVals = vals; - calcPosNegSum(); - } - - /** - * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. - * - * @return - */ - @Override - public float getY() { - return super.getY(); - } - - /** - * Returns true if this BarEntry is stacked (has a values array), false if not. - * - * @return - */ - public boolean isStacked() { - return mYVals != null; - } - - public float getBelowSum(int stackIndex) { - - if (mYVals == null) - return 0; - - float remainder = 0f; - int index = mYVals.length - 1; - - while (index > stackIndex && index >= 0) { - remainder += mYVals[index]; - index--; - } - - return remainder; - } - - /** - * Reuturns the sum of all positive values this entry (if stacked) contains. - * - * @return - */ - public float getPositiveSum() { - return mPositiveSum; - } - - /** - * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) - * - * @return - */ - public float getNegativeSum() { - return mNegativeSum; - } - - private void calcPosNegSum() { - - if (mYVals == null) { - mNegativeSum = 0; - mPositiveSum = 0; - return; - } - - float sumNeg = 0f; - float sumPos = 0f; - - for (float f : mYVals) { - if (f <= 0f) - sumNeg += Math.abs(f); - else - sumPos += f; - } - - mNegativeSum = sumNeg; - mPositiveSum = sumPos; - } - - /** - * Calculates the sum across all values of the given stack. - * - * @param vals - * @return - */ - private static float calcSum(float[] vals) { - - if (vals == null) - return 0f; - - float sum = 0f; - - for (float f : vals) - sum += f; - - return sum; - } + /** + * the values the stacked barchart holds + */ + private float[] mYVals; + + /** + * the sum of all negative values this entry (if stacked) contains + */ + private float mNegativeSum; + + /** + * the sum of all positive values this entry (if stacked) contains + */ + private float mPositiveSum; + + /** + * Constructor for stacked bar entries. + * + * @param x + * @param vals - the stack values, use at lest 2 + */ + public BarEntry(float x, float[] vals) { + super(x, calcSum(vals)); + + this.mYVals = vals; + calcPosNegSum(); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param x + * @param y + */ + public BarEntry(float x, float y) { + super(x, y); + } + + /** + * Constructor for stacked bar entries. + * + * @param x + * @param vals - the stack values, use at least 2 + * @param label Additional description label. + */ + public BarEntry(float x, float[] vals, String label) { + super(x, calcSum(vals), label); + + this.mYVals = vals; + calcPosNegSum(); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param x + * @param y + * @param data Spot for additional data this Entry represents. + */ + public BarEntry(float x, float y, Object data) { + super(x, y, data); + } + + /** + * Returns an exact copy of the BarEntry. + */ + public BarEntry copy() { + + BarEntry copied = new BarEntry(getX(), getY(), getData()); + copied.setVals(mYVals); + return copied; + } + + /** + * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use + * getY()). + * + * @return + */ + public float[] getYVals() { + return mYVals; + } + + /** + * Set the array of values this BarEntry should represent. + * + * @param vals + */ + public void setVals(float[] vals) { + setY(calcSum(vals)); + mYVals = vals; + calcPosNegSum(); + } + + /** + * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. + * + * @return + */ + @Override + public float getY() { + return super.getY(); + } + + /** + * Returns true if this BarEntry is stacked (has a values array), false if not. + * + * @return + */ + public boolean isStacked() { + return mYVals != null; + } + + public float getBelowSum(int stackIndex) { + + if (mYVals == null) + return 0; + + float remainder = 0f; + int index = mYVals.length - 1; + + while (index > stackIndex && index >= 0) { + remainder += mYVals[index]; + index--; + } + + return remainder; + } + + /** + * Reuturns the sum of all positive values this entry (if stacked) contains. + * + * @return + */ + public float getPositiveSum() { + return mPositiveSum; + } + + /** + * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) + * + * @return + */ + public float getNegativeSum() { + return mNegativeSum; + } + + private void calcPosNegSum() { + + if (mYVals == null) { + mNegativeSum = 0; + mPositiveSum = 0; + return; + } + + float sumNeg = 0f; + float sumPos = 0f; + + for (float f : mYVals) { + if (f <= 0f) + sumNeg += Math.abs(f); + else + sumPos += f; + } + + mNegativeSum = sumNeg; + mPositiveSum = sumPos; + } + + /** + * Calculates the sum across all values of the given stack. + * + * @param vals + * @return + */ + private static float calcSum(float[] vals) { + + if (vals == null) + return 0f; + + float sum = 0f; + + for (float f : vals) + sum += f; + + return sum; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 0fff111552..70605b3a8a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -523,10 +523,10 @@ public Entry getEntryForHighlight(Highlight highlight) { // if we are not interested in highlighting a specific value. List entries = mDataSets.get(highlight.getDataSetIndex()) - .getEntriesForXIndex(highlight.getXIndex()); + .getEntriesForXPos(highlight.getX()); for (Object entry : entries) - if (((Entry)entry).getY() == highlight.getValue() || - Float.isNaN(highlight.getValue())) + if (((Entry)entry).getY() == highlight.getY() || + Float.isNaN(highlight.getY())) return (Entry)entry; return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index f02374a7a9..845499b7db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -143,10 +143,10 @@ public Entry getEntryForHighlight(Highlight highlight) { // if we are not interested in highlighting a specific value. List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) - .getEntriesForXIndex(highlight.getXIndex()); + .getEntriesForXPos(highlight.getX()); for (Object entry : entries) - if (((Entry)entry).getY() == highlight.getValue() || - Float.isNaN(highlight.getValue())) + if (((Entry)entry).getY() == highlight.getY() || + Float.isNaN(highlight.getY())) return (Entry)entry; return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e85c93e0ef..fed5f780ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -326,20 +326,20 @@ public int getEntryIndex(float xPos, Rounding rounding) { } @Override - public float getYValForXIndex(int xIndex) { + public float getYValueForXValue(float xVal) { - Entry e = getEntryForXPos(xIndex); + Entry e = getEntryForXPos(xVal); - if (e != null && e.getX() == xIndex) + if (e != null && e.getX() == xVal) return e.getY(); else return Float.NaN; } @Override - public float[] getYValsForXIndex(int xIndex) { + public float[] getYValuesForXPos(float xVal) { - List entries = getEntriesForXIndex(xIndex); + List entries = getEntriesForXPos(xVal); float[] yVals = new float[entries.size()]; int i = 0; @@ -355,11 +355,11 @@ public float[] getYValsForXIndex(int xIndex) { * does calculations at runtime. Do not over-use in performance critical * situations. * - * @param xIndex + * @param xVal * @return */ @Override - public List getEntriesForXIndex(int xIndex) { + public List getEntriesForXPos(float xVal) { List entries = new ArrayList(); @@ -370,14 +370,14 @@ public List getEntriesForXIndex(int xIndex) { int m = (high + low) / 2; T entry = mValues.get(m); - if (xIndex == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xIndex) + if (xVal == entry.getX()) { + while (m > 0 && mValues.get(m - 1).getX() == xVal) m--; high = mValues.size(); for (; m < high; m++) { entry = mValues.get(m); - if (entry.getX() == xIndex) { + if (entry.getX() == xVal) { entries.add(entry); } else { break; @@ -386,7 +386,7 @@ public List getEntriesForXIndex(int xIndex) { break; } else { - if (xIndex > entry.getX()) + if (xVal > entry.getX()) low = m + 1; else high = m - 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 49399fa3c6..238546f83c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -50,20 +50,20 @@ public abstract class RealmBaseDataSet e /** * fieldname of the column that contains the y-values of this dataset */ - protected String mValuesField; + protected String mYValuesField; /** - * fieldname of the column that contains the x-indices of this dataset + * fieldname of the column that contains the x-values of this dataset */ - protected String mIndexField; + protected String mXValuesField; public RealmBaseDataSet(RealmResults results, String yValuesField) { this.results = results; - this.mValuesField = yValuesField; + this.mYValuesField = yValuesField; this.mValues = new ArrayList(); - if (mIndexField != null) - this.results.sort(mIndexField, Sort.ASCENDING); + if (mXValuesField != null) + this.results.sort(mXValuesField, Sort.ASCENDING); } /** @@ -75,12 +75,12 @@ public RealmBaseDataSet(RealmResults results, String yValuesField) { */ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { this.results = results; - this.mValuesField = yValuesField; - this.mIndexField = xIndexField; + this.mYValuesField = yValuesField; + this.mXValuesField = xIndexField; this.mValues = new ArrayList(); - if (mIndexField != null) - this.results.sort(mIndexField, Sort.ASCENDING); + if (mXValuesField != null) + this.results.sort(mXValuesField, Sort.ASCENDING); } /** @@ -94,22 +94,22 @@ public void build(RealmResults results) { } } - public S buildEntryFromResultObject(T realmObject, int xIndex) { + public S buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - return (S) new Entry(dynamicObject.getFloat(mValuesField), - mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + return (S) new Entry(dynamicObject.getFloat(mYValuesField), + mXValuesField == null ? x : dynamicObject.getInt(mXValuesField)); } @Override public float getYMin() { - //return results.min(mValuesField).floatValue(); + //return results.min(mYValuesField).floatValue(); return mYMin; } @Override public float getYMax() { - //return results.max(mValuesField).floatValue(); + //return results.max(mYValuesField).floatValue(); return mYMax; } @@ -174,8 +174,8 @@ public void calcMinMax() { @Override public S getEntryForXPos(float xPos) { - //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mIndexField, xIndex).findFirst()); - //return new Entry(o.getFloat(mValuesField), o.getInt(mIndexField)); + //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mXValuesField, xIndex).findFirst()); + //return new Entry(o.getFloat(mYValuesField), o.getInt(mXValuesField)); return getEntryForXPos(xPos, DataSet.Rounding.CLOSEST); } @@ -188,19 +188,21 @@ public S getEntryForXPos(float xPos, DataSet.Rounding rounding) { } @Override - public List getEntriesForXIndex(int xIndex) { + public List getEntriesForXPos(float xVal) { List entries = new ArrayList<>(); - if (mIndexField == null) { - T object = results.get(xIndex); - if (object != null) - entries.add(buildEntryFromResultObject(object, xIndex)); - } else { - RealmResults foundObjects = results.where().equalTo(mIndexField, xIndex).findAll(); +// { +// T object = results.get(xVal); +// if (object != null) +// entries.add(buildEntryFromResultObject(object, xVal)); +// } else + + if (mXValuesField != null) { + RealmResults foundObjects = results.where().equalTo(mXValuesField, xVal).findAll(); for (T e : foundObjects) - entries.add(buildEntryFromResultObject(e, xIndex)); + entries.add(buildEntryFromResultObject(e, xVal)); } return entries; @@ -209,7 +211,7 @@ public List getEntriesForXIndex(int xIndex) { @Override public S getEntryForIndex(int index) { //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); - //return new Entry(o.getFloat(mValuesField), o.getInt(mIndexField)); + //return new Entry(o.getFloat(mYValuesField), o.getInt(mXValuesField)); return mValues.get(index); } @@ -260,21 +262,21 @@ public int getEntryIndex(S e) { } @Override - public float getYValForXIndex(int xIndex) { - //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(mIndexField, xIndex).findFirst()) - // .getFloat(mValuesField); - Entry e = getEntryForXPos(xIndex); + public float getYValueForXValue(float xVal) { + //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(mXValuesField, xIndex).findFirst()) + // .getFloat(mYValuesField); + Entry e = getEntryForXPos(xVal); - if (e != null && e.getX() == xIndex) + if (e != null && e.getX() == xVal) return e.getY(); else return Float.NaN; } @Override - public float[] getYValsForXIndex(int xIndex) { + public float[] getYValuesForXPos(float xVal) { - List entries = getEntriesForXIndex(xIndex); + List entries = getEntriesForXPos(xVal); float[] yVals = new float[entries.size()]; int i = 0; @@ -387,8 +389,8 @@ public RealmResults getResults() { * * @return */ - public String getValuesField() { - return mValuesField; + public String getYValuesField() { + return mYValuesField; } /** @@ -396,25 +398,25 @@ public String getValuesField() { * * @param yValuesField */ - public void setValuesField(String yValuesField) { - this.mValuesField = yValuesField; + public void setYValuesField(String yValuesField) { + this.mYValuesField = yValuesField; } /** - * Returns the fieldname that represents the "x-index" in the realm-data. + * Returns the fieldname that represents the "x-values" in the realm-data. * * @return */ - public String getIndexField() { - return mIndexField; + public String getXValuesField() { + return mXValuesField; } /** - * Sets the field name that is used for getting the x-indices out of the RealmResultSet. + * Sets the field name that is used for getting the x-values out of the RealmResultSet. * - * @param xIndexField + * @param xValuesField */ - public void setIndexField(String xIndexField) { - this.mIndexField = xIndexField; + public void setXValuesField(String xValuesField) { + this.mXValuesField = xValuesField; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index ce111d9cdd..a11ebcdc99 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -15,7 +15,8 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBarDataSet { +public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet + implements IBarDataSet { private String mStackValueFieldName; @@ -67,7 +68,8 @@ public RealmBarDataSet(RealmResults results, String yValuesField, String xInd * @param xIndexField * @param stackValueFieldName */ - public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField, String stackValueFieldName) { + public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField, String + stackValueFieldName) { super(results, yValuesField, xIndexField); this.mStackValueFieldName = stackValueFieldName; mHighLightColor = Color.rgb(0, 0, 0); @@ -85,12 +87,12 @@ public void build(RealmResults results) { } @Override - public BarEntry buildEntryFromResultObject(T realmObject, int xIndex) { + public BarEntry buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - if (dynamicObject.getFieldType(mValuesField) == RealmFieldType.LIST) { + if (dynamicObject.getFieldType(mYValuesField) == RealmFieldType.LIST) { - RealmList list = dynamicObject.getList(mValuesField); + RealmList list = dynamicObject.getList(mYValuesField); float[] values = new float[list.size()]; int i = 0; @@ -99,12 +101,11 @@ public BarEntry buildEntryFromResultObject(T realmObject, int xIndex) { i++; } - return new BarEntry(values, - mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + return new BarEntry( + mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), values); } else { - float value = dynamicObject.getFloat(mValuesField); - return new BarEntry(value, - mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField)); + float value = dynamicObject.getFloat(mYValuesField); + return new BarEntry(mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), value); } } @@ -156,7 +157,7 @@ public void calcMinMax() { mYMax = 0.f; } - if(mXMin == Float.MAX_VALUE) { + if (mXMin == Float.MAX_VALUE) { mXMin = 0.f; mXMax = 0.f; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index a7f54e17be..196be07224 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -53,12 +53,12 @@ public RealmBubbleDataSet(RealmResults result, String yValuesField, String xI } @Override - public BubbleEntry buildEntryFromResultObject(T realmObject, int xIndex) { + public BubbleEntry buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); return new BubbleEntry( - mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField), - dynamicObject.getFloat(mValuesField), + mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), + dynamicObject.getFloat(mYValuesField), dynamicObject.getFloat(mSizeField)); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 24fd6b4704..9f0d43bfaf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -123,7 +123,7 @@ public CandleEntry buildEntryFromResultObject(T realmObject, int xIndex) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); return new CandleEntry( - mIndexField == null ? xIndex : dynamicObject.getInt(mIndexField), + mXValuesField == null ? xIndex : dynamicObject.getInt(mXValuesField), dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), dynamicObject.getFloat(mOpenField), diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 07e8256c42..0af151d3d6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -22,7 +22,7 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - final int xIndex = getXIndex(x); + final float xVal = getXForTouch(x); final float baseNoSpace = getBase(x); final int setCount = barData.getDataSetCount(); int dataSetIndex = ((int)baseNoSpace) % setCount; @@ -33,7 +33,7 @@ public Highlight getHighlight(float x, float y) { dataSetIndex = setCount - 1; } - SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail(xVal, y, dataSetIndex); if (selectionDetail == null) return null; @@ -48,12 +48,12 @@ public Highlight getHighlight(float x, float y) { return getStackedHighlight(selectionDetail, set, - xIndex, + xVal, pts[1]); } return new Highlight( - xIndex, + xVal, selectionDetail.value, selectionDetail.dataIndex, selectionDetail.dataSetIndex, @@ -61,10 +61,10 @@ public Highlight getHighlight(float x, float y) { } @Override - protected int getXIndex(float x) { + protected float getXForTouch(float x) { if (!mChart.getBarData().isGrouped()) { - return super.getXIndex(x); + return super.getXForTouch(x); } else { float baseNoSpace = getBase(x); @@ -84,7 +84,7 @@ else if (xIndex >= valCount) } @Override - protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetIndex) { + protected SelectionDetail getSelectionDetail(float xVal, float y, int dataSetIndex) { dataSetIndex = Math.max(dataSetIndex, 0); @@ -95,7 +95,7 @@ protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetInd if (dataSet == null) return null; - final float yValue = dataSet.getYValForXIndex(xIndex); + final float yValue = dataSet.getYValueForXValue(xVal); if (yValue == Double.NaN) return null; @@ -110,23 +110,23 @@ protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetInd * * @param selectionDetail the selection detail to work with looking for stacked values * @param set - * @param xIndex + * @param xVal * @param yValue * @return */ protected Highlight getStackedHighlight( SelectionDetail selectionDetail, IBarDataSet set, - int xIndex, + float xVal, double yValue) { - BarEntry entry = set.getEntryForXPos(xIndex); + BarEntry entry = set.getEntryForXPos(xVal); if (entry == null) return null; if (entry.getYVals() == null) { - return new Highlight(xIndex, + return new Highlight(xVal, entry.getY(), selectionDetail.dataIndex, selectionDetail.dataSetIndex); @@ -136,7 +136,7 @@ protected Highlight getStackedHighlight( if (ranges.length > 0) { int stackIndex = getClosestStackIndex(ranges, (float)yValue); return new Highlight( - xIndex, + xVal, entry.getPositiveSum() - entry.getNegativeSum(), selectionDetail.dataIndex, selectionDetail.dataSetIndex, diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index 6195abe810..1cd1466d25 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -30,13 +30,13 @@ public ChartHighlighter(T chart) { */ public Highlight getHighlight(float x, float y) { - int xIndex = getXIndex(x); + float xVal = getXForTouch(x); - SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, -1); + SelectionDetail selectionDetail = getSelectionDetail(xVal, y, -1); if (selectionDetail == null) return null; - return new Highlight(xIndex, + return new Highlight(xVal, selectionDetail.value, selectionDetail.dataIndex, selectionDetail.dataSetIndex); @@ -48,7 +48,7 @@ public Highlight getHighlight(float x, float y) { * @param x * @return */ - protected int getXIndex(float x) { + protected float getXForTouch(float x) { // create an array of the touch-point float[] pts = new float[2]; @@ -57,20 +57,20 @@ protected int getXIndex(float x) { // take any transformer to determine the x-axis value mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - return (int) Math.round(pts[0]); + return Math.round(pts[0]); } /** - * Returns the corresponding SelectionDetail for a given xIndex and y-touch position in pixels. + * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. * - * @param xIndex + * @param xVal * @param y * @param dataSetIndex * @return */ - protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetIndex) { + protected SelectionDetail getSelectionDetail(float xVal, float y, int dataSetIndex) { - List valsAtIndex = getSelectionDetailsAtIndex(xIndex, dataSetIndex); + List valsAtIndex = getSelectionDetailsAtIndex(xVal, dataSetIndex); float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); @@ -85,11 +85,11 @@ protected SelectionDetail getSelectionDetail(int xIndex, float y, int dataSetInd /** * Returns a list of SelectionDetail object corresponding to the given xIndex. * - * @param xIndex + * @param xVal * @param dataSetIndex dataSet index to look at. -1 if unspecified. * @return */ - protected List getSelectionDetailsAtIndex(int xIndex, int dataSetIndex) { + protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { List vals = new ArrayList(); @@ -111,7 +111,7 @@ protected List getSelectionDetailsAtIndex(int xIndex, int dataS continue; // extract all y-values from all DataSets at the given x-index - final float[] yVals = dataSet.getYValsForXIndex(xIndex); + final float[] yVals = dataSet.getYValuesForXPos(xVal); for (float yVal : yVals) { if (Float.isNaN(yVal)) continue; @@ -120,8 +120,7 @@ protected List getSelectionDetailsAtIndex(int xIndex, int dataS mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - if (!Float.isNaN(pts[1])) - { + if (!Float.isNaN(pts[1])) { vals.add(new SelectionDetail(pts[1], yVal, i, dataSet)); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 4957028efe..f752be4cfa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -21,11 +21,11 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { /** * Returns a list of SelectionDetail object corresponding to the given xIndex. * - * @param xIndex + * @param xVal * @return */ @Override - protected List getSelectionDetailsAtIndex(int xIndex, int dataSetIndex) { + protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { List vals = new ArrayList(); float[] pts = new float[2]; @@ -46,7 +46,7 @@ protected List getSelectionDetailsAtIndex(int xIndex, int dataS continue; // extract all y-values from all DataSets at the given x-index - final float yVals[] = dataSet.getYValsForXIndex(xIndex); + final float yVals[] = dataSet.getYValuesForXPos(xVal); for (float yVal : yVals) { pts[1] = yVal; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java index 7ebd5d0193..4bdd840d7c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java @@ -8,11 +8,11 @@ */ public class Highlight { - /** the x-index of the highlighted value */ - private int mXIndex; + /** the x-value of the highlighted value */ + private float mX = Float.NaN; /** the y-value of the highlighted value */ - private float mValue = Float.NaN; + private float mY = Float.NaN; /** the index of the data object - in case it refers to more than one */ private int mDataIndex; @@ -29,29 +29,29 @@ public class Highlight { /** * constructor * - * @param x the index of the highlighted value on the x-axis - * @param value the y-value of the highlighted value + * @param x the x-value of the highlighted value + * @param y the y-value of the highlighted value * @param dataIndex the index of the Data the highlighted value belongs to * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ - public Highlight(int x, float value, int dataIndex, int dataSetIndex) { - this.mXIndex = x; - this.mValue = value; + public Highlight(float x, float y, int dataIndex, int dataSetIndex) { + this.mX = x; + this.mY = y; this.mDataIndex = dataIndex; this.mDataSetIndex = dataSetIndex; } /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted value on the x-axis - * @param value the y-value of the highlighted value + * @param x the x-value of the highlighted value on the x-axis + * @param y the y-value of the highlighted value * @param dataIndex the index of the Data the highlighted value belongs to * @param dataSetIndex the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected */ - public Highlight(int x, float value, int dataIndex, int dataSetIndex, int stackIndex) { - this(x, value, dataIndex, dataSetIndex); + public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex) { + this(x, y, dataIndex, dataSetIndex); mStackIndex = stackIndex; } @@ -59,15 +59,15 @@ public Highlight(int x, float value, int dataIndex, int dataSetIndex, int stackI * Constructor, only used for stacked-barchart. * * @param x the index of the highlighted value on the x-axis - * @param value the y-value of the highlighted value + * @param y the y-value of the highlighted value * @param dataIndex the index of the Data the highlighted value belongs to * @param dataSetIndex the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected * @param range the range the selected stack-value is in */ - public Highlight(int x, float value, int dataIndex, int dataSetIndex, int stackIndex, Range range) { - this(x, value, dataIndex, dataSetIndex, stackIndex); + public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex, Range range) { + this(x, y, dataIndex, dataSetIndex, stackIndex); this.mRange = range; } @@ -82,12 +82,12 @@ public Highlight(int x, int dataSetIndex) { } /** - * returns the index of the highlighted value on the x-axis + * returns the x-value of the highlighted value * * @return */ - public int getXIndex() { - return mXIndex; + public float getX() { + return mX; } /** @@ -95,8 +95,8 @@ public int getXIndex() { * * @return */ - public float getValue() { - return mValue; + public float getY() { + return mY; } /** @@ -136,7 +136,7 @@ public Range getRange() { } /** - * returns true if this highlight object is equal to the other (compares + * Returns true if this highlight object is equal to the other (compares * xIndex and dataSetIndex) * * @param h @@ -147,7 +147,7 @@ public boolean equalTo(Highlight h) { if (h == null) return false; else { - if (this.mDataSetIndex == h.mDataSetIndex && this.mXIndex == h.mXIndex + if (this.mDataSetIndex == h.mDataSetIndex && this.mX == h.mX && this.mStackIndex == h.mStackIndex) return true; else @@ -157,7 +157,7 @@ public boolean equalTo(Highlight h) { @Override public String toString() { - return "Highlight, xIndex: " + mXIndex + ", dataSetIndex: " + mDataSetIndex + return "Highlight, x: " + mX + "y: " + mY + ", dataSetIndex: " + mDataSetIndex + ", stackIndex (only stacked barentry): " + mStackIndex; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index cdd6387cd8..ac857f3b51 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -20,7 +20,7 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - final int xIndex = getXIndex(x); + final float xVal = getXForTouch(x); final float baseNoSpace = getBase(x); final int setCount = barData.getDataSetCount(); int dataSetIndex = ((int)baseNoSpace) % setCount; @@ -31,7 +31,7 @@ public Highlight getHighlight(float x, float y) { dataSetIndex = setCount - 1; } - SelectionDetail selectionDetail = getSelectionDetail(xIndex, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail(xVal, y, dataSetIndex); if (selectionDetail == null) return null; @@ -46,12 +46,12 @@ public Highlight getHighlight(float x, float y) { return getStackedHighlight(selectionDetail, set, - xIndex, + xVal, pts[0]); } return new Highlight( - xIndex, + xVal, selectionDetail.value, selectionDetail.dataIndex, selectionDetail.dataSetIndex, @@ -59,7 +59,7 @@ public Highlight getHighlight(float x, float y) { } @Override - protected int getXIndex(float x) { + protected float getXForTouch(float x) { if (!mChart.getBarData().isGrouped()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 3c8cf5b119..5e62fc9224 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -83,15 +83,15 @@ public interface IDataSet { T getEntryForXPos(float xPos); /** - * Returns all Entry objects found at the given xIndex with binary - * search. An empty array if no Entry object at that index. + * Returns all Entry objects found at the given xPos with binary + * search. An empty array if no Entry object at that xPos. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xIndex + * @param xPos * @return */ - List getEntriesForXIndex(int xIndex); + List getEntriesForXPos(float xPos); /** * Returns the Entry object found at the given index (NOT xIndex) in the values array. @@ -124,26 +124,26 @@ public interface IDataSet { int getEntryIndex(T e); /** - * Returns the value of the Entry object at the given xIndex. Returns - * Float.NaN if no value is at the given x-index. INFORMATION: This method + * Returns the value of the Entry object at the given xVal. Returns + * Float.NaN if no value is at the given xVal. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * - * @param xIndex + * @param xVal * @return */ - float getYValForXIndex(int xIndex); + float getYValueForXValue(float xVal); /** - * Returns all of the y values of the Entry objects at the given xIndex. Returns - * Float.NaN if no value is at the given x-index. INFORMATION: This method + * Returns all of the y values of the Entry objects at the given xPos. Returns + * Float.NaN if no value is at the given xPos. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * - * @param xIndex + * @param xPos * @return */ - float[] getYValsForXIndex(int xIndex); + float[] getYValuesForXPos(float xPos); /** * This method returns the actual diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index ecc30e9f84..cfdba02418 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -3,9 +3,7 @@ import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; @@ -169,22 +167,25 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { } } - /** - * Prepares a bar for being highlighted. - * - * @param x the x-position - * @param y1 the y1-position - * @param y2 the y2-position - * @param barspaceHalf the space between bars - * @param trans - */ - protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, - Transformer trans) { + protected void prepareBarHighlight(float y1, float y2, float interval, int entryIndex, int dataSetIndex, int + dataSetCount, float barSpace, float groupSpace, Transformer trans) { + + float barWidth = interval / dataSetCount; + + float groupSpaceWidth = dataSetCount <= 1 ? 0 : barWidth * groupSpace; + float newInterval = (interval - groupSpaceWidth); + float newBarWidth = newInterval / dataSetCount; - float barWidth = 0.5f; + float barSpaceWidth = newBarWidth * barSpace; + float barSpaceWidthHalf = barSpaceWidth / 2f; - float left = x - barWidth + barspaceHalf; - float right = x + barWidth - barspaceHalf; + float groupSpaceWidthHalf = groupSpaceWidth / 2f; + float dataSetSpace = dataSetCount <= 1 ? 0 : (newInterval / dataSetCount) * dataSetIndex; + + float x = interval * entryIndex + dataSetSpace; + + float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; + float right = left + newBarWidth - barSpaceWidth; float top = y1; float bottom = y2; @@ -284,7 +285,8 @@ public void drawValues(Canvas c) { continue; drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, - buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), color); + buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), + color); // draw stack values } else { @@ -361,30 +363,27 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - float barspaceHalf = set.getBarSpace() / 2f; - Transformer trans = mChart.getTransformer(set.getAxisDependency()); mHighlightPaint.setColor(set.getHighLightColor()); mHighlightPaint.setAlpha(set.getHighLightAlpha()); - int index = high.getXIndex(); + float x = high.getX(); // check outofbounds - if (index >= 0 - && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { + if (x >= 0 + && x < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { - BarEntry e = set.getEntryForXPos(index); + BarEntry e = set.getEntryForXPos(x); + int entryIndex = set.getEntryIndex(e); - if (e == null || e.getX() != index) + if (e == null || e.getX() != x) continue; - float groupspace = barData.getGroupSpace(); + float interval = mChart.getXRange() / set.getEntryCount(); + float groupSpace = barData.getGroupSpace(); boolean isStack = high.getStackIndex() < 0 ? false : true; - - // calculate the correct x-position - float x = index * setCount + dataSetIndex + groupspace / 2f - + groupspace * index; + float barSpace = set.getBarSpace(); final float y1; final float y2; @@ -397,35 +396,35 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { y2 = 0.f; } - prepareBarHighlight(x, y1, y2, barspaceHalf, trans); + prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, trans); c.drawRect(mBarRect, mHighlightPaint); - if (mChart.isDrawHighlightArrowEnabled()) { - - mHighlightPaint.setAlpha(255); - - // distance between highlight arrow and bar - float offsetY = mAnimator.getPhaseY() * 0.07f; - - float[] values = new float[9]; - trans.getPixelToValueMatrix().getValues(values); - final float xToYRel = Math.abs( - values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); - - final float arrowWidth = set.getBarSpace() / 2.f; - final float arrowHeight = arrowWidth * xToYRel; - - final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); - - Path arrow = new Path(); - arrow.moveTo(x + 0.4f, yArrow + offsetY); - arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); - arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); - - trans.pathValueToPixel(arrow); - c.drawPath(arrow, mHighlightPaint); - } +// if (mChart.isDrawHighlightArrowEnabled()) { +// +// mHighlightPaint.setAlpha(255); +// +// // distance between highlight arrow and bar +// float offsetY = mAnimator.getPhaseY() * 0.07f; +// +// float[] values = new float[9]; +// trans.getPixelToValueMatrix().getValues(values); +// final float xToYRel = Math.abs( +// values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); +// +// final float arrowWidth = set.getBarSpace() / 2.f; +// final float arrowHeight = arrowWidth * xToYRel; +// +// final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); +// +// Path arrow = new Path(); +// arrow.moveTo(x + 0.4f, yArrow + offsetY); +// arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); +// arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); +// +// trans.pathValueToPixel(arrow); +// c.drawPath(arrow, mHighlightPaint); +// } } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 384e1e5825..a1d9521a55 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -225,7 +224,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(high); - if (entry == null || entry.getX() != high.getXIndex()) + if (entry == null || entry.getX() != high.getX()) continue; float low = mChart.getLowestVisibleX(); @@ -271,7 +270,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - if (high.getXIndex() < minx || high.getXIndex() >= maxx) + if (high.getX() < minx || high.getX() >= maxx) continue; final int originalColor = dataSet.getColor((int) entry.getX()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index ccef5a608d..b6d567797b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -326,7 +326,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { dataSetIndex < maxDataSetIndex; dataSetIndex++) { - int xIndex = high.getXIndex(); // get the + float x = high.getX(); // get the // x-position ICandleDataSet set = mChart.getCandleData().getDataSetByIndex(dataSetIndex); @@ -334,9 +334,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - CandleEntry e = set.getEntryForXPos(xIndex); + CandleEntry e = set.getEntryForXPos(x); - if (e == null || e.getX() != xIndex) + if (e == null || e.getX() != x) continue; float lowValue = e.getLow() * mAnimator.getPhaseY(); @@ -344,7 +344,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float y = (lowValue + highValue) / 2f; float[] pts = new float[]{ - xIndex, y + x, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 524b78a236..b27c5ebdab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -268,7 +268,6 @@ protected void drawValue(Canvas c, String valueText, float x, float y, int color c.drawText(valueText, x, y, mValuePaint); } - @Override protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, Transformer trans) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index da1dfba60a..1b8ab83c10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -738,13 +738,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - int xIndex = high.getXIndex(); // get the + float x = high.getX(); // get the // x-position - if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) + if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - final float yVal = set.getYValForXIndex(xIndex); + final float yVal = set.getYValueForXValue(x); if (Float.isNaN(yVal)) continue; @@ -753,7 +753,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // y-position float[] pts = new float[]{ - xIndex, y + x, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 840e0a7007..962ac88eaa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; @@ -693,14 +694,17 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { // get the index to highlight - int xIndex = indices[i].getXIndex(); - if (xIndex >= drawAngles.length) + float x = indices[i].getX(); + + if (x >= drawAngles.length) continue; IPieDataSet set = mChart.getData() .getDataSetByIndex(indices[i] .getDataSetIndex()); + int entryIndex = set.getEntryIndex(x, DataSet.Rounding.CLOSEST); + if (set == null || !set.isHighlightEnabled()) continue; @@ -713,14 +717,14 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - if (xIndex == 0) + if (x == 0) angle = 0.f; else - angle = absoluteAngles[xIndex - 1] * phaseX; + angle = absoluteAngles[entryIndex - 1] * phaseX; final float sliceSpace = visibleAngleCount <= 1 ? 0.f : set.getSliceSpace(); - float sliceAngle = drawAngles[xIndex]; + float sliceAngle = drawAngles[entryIndex]; float innerRadius = userInnerRadius; float shift = set.getSelectionShift(); @@ -730,7 +734,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(set.getColor(xIndex)); + mRenderPaint.setColor(set.getColor(entryIndex)); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 206a85add2..30f3ef33ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -270,10 +270,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; // get the index to highlight - int xIndex = indices[i].getXIndex(); + float x = indices[i].getX(); - Entry e = set.getEntryForXPos(xIndex); - if (e == null || e.getX() != xIndex) + Entry e = set.getEntryForXPos(x); + if (e == null || e.getX() != x) continue; int j = set.getEntryIndex(e); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index b5365575f3..caf9650f3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -397,21 +397,21 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - int xIndex = high.getXIndex(); // get the + float x = high.getX(); // get the // x-position - if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) + if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - final float yVal = set.getYValForXIndex(xIndex); + final float yVal = set.getYValueForXValue(x); if (Float.isNaN(yVal)) continue; float y = yVal * mAnimator.getPhaseY(); float[] pts = new float[]{ - xIndex, y + x, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java index 6632c23d60..31fbb10805 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java @@ -61,7 +61,7 @@ public static List loadEntriesFromFile(String path) { vals[i] = Float.parseFloat(split[i]); } - entries.add(new BarEntry(vals, Integer.parseInt(split[split.length - 1]))); + entries.add(new BarEntry(Integer.parseInt(split[split.length - 1]), vals)); } } } catch (IOException e) { @@ -131,7 +131,7 @@ public static List loadEntriesFromAssets(AssetManager am, String path) { vals[i] = Float.parseFloat(split[i]); } - entries.add(new BarEntry(vals, Integer.parseInt(split[split.length - 1]))); + entries.add(new BarEntry(Integer.parseInt(split[split.length - 1]), vals)); } line = reader.readLine(); } From 530ab11157799cdca486fc1ee94ab0f17e4358ff Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 08:56:40 +0200 Subject: [PATCH 0912/1390] Work on highlighting --- MPChartExample/build.gradle | 3 + .../mpchartexample/PieChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 6 +- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/test/DataSetTest.java | 33 ++++ .../charting/highlight/BarHighlighter.java | 4 +- .../charting/highlight/ChartHighlighter.java | 170 +++++++++--------- .../highlight/HorizontalBarHighlighter.java | 2 +- .../charting/utils/SelectionDetail.java | 8 +- .../github/mikephil/charting/utils/Utils.java | 29 +-- 10 files changed, 139 insertions(+), 120 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 12d3a86424..4c549106e6 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -8,6 +8,7 @@ android { targetSdkVersion 23 versionCode 51 versionName '2.2.5' + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" sourceSets { main { @@ -57,4 +58,6 @@ dependencies { compile 'com.android.support:appcompat-v7:23.1.1' compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' + + testCompile 'junit:junit:4.12' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index dc94027e12..601a4e6140 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -193,7 +193,7 @@ private void setData(int count, float range) { // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < count + 1; i++) { - yVals1.add(new Entry((float) (Math.random() * mult) + mult / 5, i)); + yVals1.add(new Entry(i, (float) (Math.random() * mult) + mult / 5)); } ArrayList xVals = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 5ff44fb5a1..2614a015fd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -174,17 +174,17 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals1.add(new Entry(val, i)); + yVals1.add(new Entry(i, val)); } for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals2.add(new Entry(val, i)); + yVals2.add(new Entry(i+0.33f, val)); } for (int i = 0; i < mSeekBarX.getProgress(); i++) { float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals3.add(new Entry(val, i)); + yVals3.add(new Entry(i+0.66f, val)); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 34f2140a04..1dcff1efe1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -56,7 +56,7 @@ private void setData(int count) { for (int i = 0; i < count; i++) { float val = (float) (Math.random() * count) + 15; - yVals.add(new BarEntry((int) val, i)); + yVals.add(new BarEntry(i, (int) val)); xVals.add(new XAxisValue(i, (int) val + "")); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java new file mode 100644 index 0000000000..8cf89a6101 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java @@ -0,0 +1,33 @@ +package com.xxmassdeveloper.mpchartexample.test; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.ScatterDataSet; + +//import org.junit.Test; +// +//import java.util.ArrayList; +//import java.util.List; +//import static org.junit.Assert.*; +// +///** +// * Created by philipp on 30/05/16. +// */ +//public class DataSetTest { +// +// +// @Test +// public void testGetEntryForXPos() { +// +// List vals = new ArrayList<>(); +// vals.add(new Entry(10, 10)); +// vals.add(new Entry(15, 5)); +// vals.add(new Entry(17, 10)); +// +// ScatterDataSet set = new ScatterDataSet(vals, ""); +// +// Entry e1 = set.getEntryForXPos(13); +// assertEquals(15, e1.getX(), 0.01f); +// assertEquals(5, e1.getY(), 0.01f); +// } +//} + diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 0af151d3d6..9ca0e66a05 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -33,7 +33,7 @@ public Highlight getHighlight(float x, float y) { dataSetIndex = setCount - 1; } - SelectionDetail selectionDetail = getSelectionDetail(xVal, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); if (selectionDetail == null) return null; @@ -84,7 +84,7 @@ else if (xIndex >= valCount) } @Override - protected SelectionDetail getSelectionDetail(float xVal, float y, int dataSetIndex) { + protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { dataSetIndex = Math.max(dataSetIndex, 0); diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index 1cd1466d25..a2e0f19deb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -4,6 +4,7 @@ import java.util.List; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; @@ -14,118 +15,115 @@ */ public class ChartHighlighter { - /** instance of the data-provider */ - protected T mChart; + /** + * instance of the data-provider + */ + protected T mChart; - public ChartHighlighter(T chart) { - this.mChart = chart; - } + public ChartHighlighter(T chart) { + this.mChart = chart; + } - /** - * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. - * - * @param x - * @param y - * @return - */ - public Highlight getHighlight(float x, float y) { + /** + * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. + * + * @param x + * @param y + * @return + */ + public Highlight getHighlight(float x, float y) { - float xVal = getXForTouch(x); + float xVal = getXForTouch(x); - SelectionDetail selectionDetail = getSelectionDetail(xVal, y, -1); - if (selectionDetail == null) - return null; + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, -1); + if (selectionDetail == null) + return null; - return new Highlight(xVal, - selectionDetail.value, - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); - } + return new Highlight(xVal, + selectionDetail.value, + selectionDetail.dataIndex, + selectionDetail.dataSetIndex); + } - /** - * Returns the corresponding x-index for a given touch-position in pixels. - * - * @param x - * @return - */ - protected float getXForTouch(float x) { + /** + * Returns the corresponding x-index for a given touch-position in pixels. + * + * @param x + * @return + */ + protected float getXForTouch(float x) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - return Math.round(pts[0]); - } + return Math.round(pts[0]); + } - /** - * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. - * - * @param xVal - * @param y - * @param dataSetIndex - * @return - */ - protected SelectionDetail getSelectionDetail(float xVal, float y, int dataSetIndex) { + /** + * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. + * + * @param xVal + * @param y + * @param dataSetIndex + * @return + */ + protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { - List valsAtIndex = getSelectionDetailsAtIndex(xVal, dataSetIndex); + List valsAtIndex = getSelectionDetailsAtIndex(xVal, dataSetIndex); - float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); - float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); + float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); + float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); - YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; + YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - SelectionDetail detail = Utils.getClosestSelectionDetailByPixelY(valsAtIndex, y, axis); + SelectionDetail detail = Utils.getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis); - return detail; - } + return detail; + } - /** - * Returns a list of SelectionDetail object corresponding to the given xIndex. - * - * @param xVal - * @param dataSetIndex dataSet index to look at. -1 if unspecified. - * @return - */ - protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { + /** + * Returns a list of SelectionDetail object corresponding to the given xIndex. + * + * @param xVal + * @param dataSetIndex dataSet index to look at. -1 if unspecified. + * @return + */ + protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { - List vals = new ArrayList(); + List vals = new ArrayList(); - if (mChart.getData() == null) return vals; + if (mChart.getData() == null) return vals; - float[] pts = new float[2]; + float[] pts = new float[2]; - for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); - i < dataSetCount; - i++) { + for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); i < dataSetCount; i++) { - if (dataSetIndex > -1 && dataSetIndex != i) - continue; + if (dataSetIndex > -1 && dataSetIndex != i) + continue; - IDataSet dataSet = mChart.getData().getDataSetByIndex(i); + IDataSet dataSet = mChart.getData().getDataSetByIndex(i); - // dont include datasets that cannot be highlighted - if (!dataSet.isHighlightEnabled()) - continue; + // dont include datasets that cannot be highlighted + if (!dataSet.isHighlightEnabled()) + continue; - // extract all y-values from all DataSets at the given x-index - final float[] yVals = dataSet.getYValuesForXPos(xVal); - for (float yVal : yVals) { - if (Float.isNaN(yVal)) - continue; + // extract all y-values from all DataSets at the given x-index + final Entry e = dataSet.getEntryForXPos(xVal); - pts[1] = yVal; + pts[0] = e.getX(); + pts[1] = e.getY(); - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], yVal, i, dataSet)); - } - } - } + if (!Float.isNaN(pts[1])) { + vals.add(new SelectionDetail(pts[0], pts[1], e.getY(), i, dataSet)); + } + } - return vals; - } + return vals; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index ac857f3b51..22a8d7356d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -31,7 +31,7 @@ public Highlight getHighlight(float x, float y) { dataSetIndex = setCount - 1; } - SelectionDetail selectionDetail = getSelectionDetail(xVal, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); if (selectionDetail == null) return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java index 5f78528f4c..2aaa786e90 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java @@ -13,12 +13,14 @@ public class SelectionDetail { public float y; + public float x; public float value; public int dataIndex; public int dataSetIndex; public IDataSet dataSet; - public SelectionDetail(float y, float value, int dataIndex, int dataSetIndex, IDataSet set) { + public SelectionDetail(float x, float y, float value, int dataIndex, int dataSetIndex, IDataSet set) { + this.x = x; this.y = y; this.value = value; this.dataIndex = dataIndex; @@ -26,8 +28,8 @@ public SelectionDetail(float y, float value, int dataIndex, int dataSetIndex, ID this.dataSet = set; } - public SelectionDetail(float y, float value, int dataSetIndex, IDataSet set) { - this(y, value, 0, dataSetIndex, set); + public SelectionDetail(float x, float y, float value, int dataSetIndex, IDataSet set) { + this(x, y, value, 0, dataSetIndex, set); } public SelectionDetail(float value, int dataSetIndex, IDataSet set) { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index caaef8153c..1abdc46b06 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -399,24 +399,6 @@ public static int getClosestDataSetIndexByValue(List valsAtInde return sel.dataSetIndex; } - /** - * Returns the index of the DataSet that contains the closest value on the - * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. - * - * @param valsAtIndex all the values at a specific index - * @return - */ - public static int getClosestDataSetIndexByPixelY(List valsAtIndex, float y, - AxisDependency axis) { - - SelectionDetail sel = getClosestSelectionDetailByPixelY(valsAtIndex, y, axis); - - if (sel == null) - return -Integer.MAX_VALUE; - - return sel.dataSetIndex; - } - /** * Returns the SelectionDetail of the DataSet that contains the closest value on the * y-axis. @@ -456,9 +438,9 @@ public static SelectionDetail getClosestSelectionDetailByValue( * @param valsAtIndex all the values at a specific index * @return */ - public static SelectionDetail getClosestSelectionDetailByPixelY( + public static SelectionDetail getClosestSelectionDetailByPixel( List valsAtIndex, - float y, + float x, float y, AxisDependency axis) { SelectionDetail closest = null; @@ -470,10 +452,11 @@ public static SelectionDetail getClosestSelectionDetailByPixelY( if (axis == null || sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs(sel.y - y); - if (cdistance < distance) { + float cDistance = (float) Math.hypot(x - sel.x, y - sel.y); + + if (cDistance < distance) { closest = sel; - distance = cdistance; + distance = cDistance; } } } From cc81a21c6415ef931a6ded7d0a76626d7c2f6b18 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 09:34:11 +0200 Subject: [PATCH 0913/1390] Restructure project from eclipse to android studio file structure --- MPChartExample/build.gradle | 2 - .../mpchartexample/test/DataSetTest.java | 33 ----------- MPChartLib/build.gradle | 14 ++--- MPChartLib/{ => src/main}/AndroidManifest.xml | 0 .../charting/animation/ChartAnimator.java | 0 .../mikephil/charting/animation/Easing.java | 0 .../charting/animation/EasingFunction.java | 0 .../charting/buffer/AbstractBuffer.java | 0 .../mikephil/charting/buffer/BarBuffer.java | 0 .../charting/buffer/HorizontalBarBuffer.java | 0 .../charting/buffer/ScatterBuffer.java | 0 .../mikephil/charting/charts/BarChart.java | 0 .../charting/charts/BarLineChartBase.java | 0 .../mikephil/charting/charts/BubbleChart.java | 0 .../charting/charts/CandleStickChart.java | 0 .../mikephil/charting/charts/Chart.java | 0 .../charting/charts/CombinedChart.java | 0 .../charting/charts/HorizontalBarChart.java | 0 .../mikephil/charting/charts/LineChart.java | 0 .../mikephil/charting/charts/PieChart.java | 0 .../charting/charts/PieRadarChartBase.java | 0 .../mikephil/charting/charts/RadarChart.java | 0 .../charting/charts/ScatterChart.java | 0 .../charting/components/AxisBase.java | 0 .../charting/components/ComponentBase.java | 0 .../mikephil/charting/components/Legend.java | 0 .../charting/components/LimitLine.java | 0 .../charting/components/MarkerView.java | 0 .../mikephil/charting/components/XAxis.java | 0 .../mikephil/charting/components/YAxis.java | 0 .../mikephil/charting/data/BarData.java | 0 .../mikephil/charting/data/BarDataSet.java | 0 .../mikephil/charting/data/BarEntry.java | 0 .../data/BarLineScatterCandleBubbleData.java | 0 .../BarLineScatterCandleBubbleDataSet.java | 0 .../mikephil/charting/data/BaseDataSet.java | 0 .../mikephil/charting/data/BubbleData.java | 0 .../mikephil/charting/data/BubbleDataSet.java | 0 .../mikephil/charting/data/BubbleEntry.java | 0 .../mikephil/charting/data/CandleData.java | 0 .../mikephil/charting/data/CandleDataSet.java | 0 .../mikephil/charting/data/CandleEntry.java | 0 .../mikephil/charting/data/ChartData.java | 0 .../mikephil/charting/data/CombinedData.java | 0 .../mikephil/charting/data/DataSet.java | 41 ++++++------- .../github/mikephil/charting/data/Entry.java | 0 .../mikephil/charting/data/LineData.java | 0 .../mikephil/charting/data/LineDataSet.java | 0 .../charting/data/LineRadarDataSet.java | 0 .../data/LineScatterCandleRadarDataSet.java | 0 .../mikephil/charting/data/PieData.java | 0 .../mikephil/charting/data/PieDataSet.java | 0 .../mikephil/charting/data/RadarData.java | 0 .../mikephil/charting/data/RadarDataSet.java | 0 .../mikephil/charting/data/ScatterData.java | 0 .../charting/data/ScatterDataSet.java | 0 .../mikephil/charting/data/XAxisValue.java | 0 .../charting/data/filter/Approximator.java | 0 ...ealmBarLineScatterCandleBubbleDataSet.java | 0 .../data/realm/base/RealmBaseDataSet.java | 0 .../realm/base/RealmLineRadarDataSet.java | 0 .../RealmLineScatterCandleRadarDataSet.java | 0 .../charting/data/realm/base/RealmUtils.java | 0 .../realm/implementation/RealmBarData.java | 0 .../realm/implementation/RealmBarDataSet.java | 0 .../realm/implementation/RealmBubbleData.java | 0 .../implementation/RealmBubbleDataSet.java | 0 .../realm/implementation/RealmCandleData.java | 0 .../implementation/RealmCandleDataSet.java | 0 .../realm/implementation/RealmLineData.java | 0 .../implementation/RealmLineDataSet.java | 0 .../realm/implementation/RealmPieData.java | 0 .../realm/implementation/RealmPieDataSet.java | 0 .../realm/implementation/RealmRadarData.java | 0 .../implementation/RealmRadarDataSet.java | 0 .../implementation/RealmScatterData.java | 0 .../implementation/RealmScatterDataSet.java | 0 .../DrawingDataSetNotCreatedException.java | 0 .../charting/formatter/ColorFormatter.java | 0 .../formatter/DefaultFillFormatter.java | 0 .../formatter/DefaultValueFormatter.java | 0 .../formatter/DefaultXAxisValueFormatter.java | 0 .../formatter/DefaultYAxisValueFormatter.java | 0 .../charting/formatter/FillFormatter.java | 0 .../formatter/LargeValueFormatter.java | 0 .../charting/formatter/PercentFormatter.java | 0 .../formatter/StackedValueFormatter.java | 0 .../charting/formatter/ValueFormatter.java | 0 .../formatter/XAxisValueFormatter.java | 0 .../formatter/YAxisValueFormatter.java | 0 .../charting/highlight/BarHighlighter.java | 0 .../charting/highlight/ChartHighlighter.java | 0 .../highlight/CombinedHighlighter.java | 0 .../charting/highlight/Highlight.java | 0 .../highlight/HorizontalBarHighlighter.java | 0 .../mikephil/charting/highlight/Range.java | 0 .../dataprovider/BarDataProvider.java | 0 ...arLineScatterCandleBubbleDataProvider.java | 0 .../dataprovider/BubbleDataProvider.java | 0 .../dataprovider/CandleDataProvider.java | 0 .../dataprovider/ChartInterface.java | 0 .../dataprovider/LineDataProvider.java | 0 .../dataprovider/ScatterDataProvider.java | 0 .../interfaces/datasets/IBarDataSet.java | 0 .../IBarLineScatterCandleBubbleDataSet.java | 0 .../interfaces/datasets/IBubbleDataSet.java | 0 .../interfaces/datasets/ICandleDataSet.java | 0 .../interfaces/datasets/IDataSet.java | 0 .../interfaces/datasets/ILineDataSet.java | 0 .../datasets/ILineRadarDataSet.java | 0 .../ILineScatterCandleRadarDataSet.java | 0 .../interfaces/datasets/IPieDataSet.java | 0 .../interfaces/datasets/IRadarDataSet.java | 0 .../interfaces/datasets/IScatterDataSet.java | 0 .../charting/jobs/AnimatedMoveViewJob.java | 0 .../charting/jobs/AnimatedViewPortJob.java | 0 .../charting/jobs/AnimatedZoomJob.java | 0 .../mikephil/charting/jobs/MoveViewJob.java | 0 .../mikephil/charting/jobs/ViewPortJob.java | 0 .../mikephil/charting/jobs/ZoomJob.java | 0 .../listener/BarLineChartTouchListener.java | 0 .../charting/listener/ChartTouchListener.java | 0 .../listener/OnChartGestureListener.java | 0 .../OnChartValueSelectedListener.java | 0 .../OnDrawLineChartTouchListener.java | 0 .../charting/listener/OnDrawListener.java | 0 .../listener/PieRadarChartTouchListener.java | 0 .../mikephil/charting/matrix/Vector3.java | 0 .../charting/renderer/AxisRenderer.java | 0 .../charting/renderer/BarChartRenderer.java | 0 .../renderer/BubbleChartRenderer.java | 0 .../renderer/CandleStickChartRenderer.java | 0 .../renderer/CombinedChartRenderer.java | 0 .../charting/renderer/DataRenderer.java | 0 .../renderer/HorizontalBarChartRenderer.java | 0 .../charting/renderer/LegendRenderer.java | 0 .../charting/renderer/LineChartRenderer.java | 0 .../charting/renderer/LineRadarRenderer.java | 0 .../LineScatterCandleRadarRenderer.java | 0 .../charting/renderer/PieChartRenderer.java | 0 .../charting/renderer/RadarChartRenderer.java | 0 .../mikephil/charting/renderer/Renderer.java | 0 .../renderer/ScatterChartRenderer.java | 0 .../charting/renderer/XAxisRenderer.java | 0 .../renderer/XAxisRendererBarChart.java | 0 .../XAxisRendererHorizontalBarChart.java | 0 .../renderer/XAxisRendererRadarChart.java | 0 .../charting/renderer/YAxisRenderer.java | 0 .../YAxisRendererHorizontalBarChart.java | 0 .../renderer/YAxisRendererRadarChart.java | 0 .../charting/utils/ColorTemplate.java | 0 .../charting/utils/EntryXIndexComparator.java | 0 .../github/mikephil/charting/utils/FSize.java | 0 .../mikephil/charting/utils/FileUtils.java | 0 .../mikephil/charting/utils/PointD.java | 0 .../charting/utils/SelectionDetail.java | 0 .../mikephil/charting/utils/Transformer.java | 0 .../utils/TransformerHorizontalBarChart.java | 0 .../github/mikephil/charting/utils/Utils.java | 0 .../charting/utils/ViewPortHandler.java | 0 .../mikephil/charting/test/DataSetTest.java | 59 +++++++++++++++++++ 161 files changed, 83 insertions(+), 66 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java rename MPChartLib/{ => src/main}/AndroidManifest.xml (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/animation/ChartAnimator.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/animation/Easing.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/animation/EasingFunction.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/buffer/AbstractBuffer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/buffer/BarBuffer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/buffer/ScatterBuffer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/BarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/BarLineChartBase.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/BubbleChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/CandleStickChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/Chart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/CombinedChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/HorizontalBarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/LineChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/PieChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/PieRadarChartBase.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/RadarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/charts/ScatterChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/AxisBase.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/ComponentBase.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/Legend.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/LimitLine.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/MarkerView.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/XAxis.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/components/YAxis.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BarData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BarEntry.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BaseDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BubbleData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/BubbleEntry.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/CandleData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/CandleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/CandleEntry.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/ChartData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/CombinedData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/DataSet.java (92%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/Entry.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/LineData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/LineDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/LineRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/PieData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/PieDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/RadarData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/RadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/ScatterData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/ScatterDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/XAxisValue.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/filter/Approximator.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/base/RealmUtils.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/exception/DrawingDataSetNotCreatedException.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/ColorFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/DefaultFillFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/DefaultValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/FillFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/LargeValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/PercentFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/StackedValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/ValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/XAxisValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/formatter/YAxisValueFormatter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/BarHighlighter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/ChartHighlighter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/CombinedHighlighter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/Highlight.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/highlight/Range.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/AnimatedZoomJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/MoveViewJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/ViewPortJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/jobs/ZoomJob.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/BarLineChartTouchListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/ChartTouchListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/OnChartGestureListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/OnDrawListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/matrix/Vector3.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/AxisRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/BarChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/BubbleChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/CombinedChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/DataRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/LegendRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/LineChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/LineRadarRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/PieChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/RadarChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/Renderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/ScatterChartRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/XAxisRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/YAxisRenderer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/ColorTemplate.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/EntryXIndexComparator.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/FSize.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/FileUtils.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/PointD.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/SelectionDetail.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/Transformer.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/Utils.java (100%) rename MPChartLib/src/{ => main/java}/com/github/mikephil/charting/utils/ViewPortHandler.java (100%) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 4c549106e6..1f6fca6575 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -58,6 +58,4 @@ dependencies { compile 'com.android.support:appcompat-v7:23.1.1' compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' - - testCompile 'junit:junit:4.12' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java deleted file mode 100644 index 8cf89a6101..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/test/DataSetTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.test; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.ScatterDataSet; - -//import org.junit.Test; -// -//import java.util.ArrayList; -//import java.util.List; -//import static org.junit.Assert.*; -// -///** -// * Created by philipp on 30/05/16. -// */ -//public class DataSetTest { -// -// -// @Test -// public void testGetEntryForXPos() { -// -// List vals = new ArrayList<>(); -// vals.add(new Entry(10, 10)); -// vals.add(new Entry(15, 5)); -// vals.add(new Entry(17, 10)); -// -// ScatterDataSet set = new ScatterDataSet(vals, ""); -// -// Entry e1 = set.getEntryForXPos(13); -// assertEquals(15, e1.getX(), 0.01f); -// assertEquals(5, e1.getY(), 0.01f); -// } -//} - diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 1c7ca0e099..af8e41792f 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -11,15 +11,6 @@ android { targetSdkVersion 23 versionCode 1 versionName '1.0' - - sourceSets { - main { - java.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - manifest.srcFile 'AndroidManifest.xml' - } - } } buildTypes { release { @@ -30,6 +21,9 @@ android { lintOptions { abortOnError false } + testOptions { + unitTests.returnDefaultValues = true // this prevents "not mocked" error + } } repositories { @@ -42,6 +36,8 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API + testCompile 'junit:junit:4.12' + testCompile "org.mockito:mockito-core:1.9.5" } android.libraryVariants.all { variant -> diff --git a/MPChartLib/AndroidManifest.xml b/MPChartLib/src/main/AndroidManifest.xml similarity index 100% rename from MPChartLib/AndroidManifest.xml rename to MPChartLib/src/main/AndroidManifest.xml diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/animation/ChartAnimator.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/animation/Easing.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/Chart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/Legend.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/XAxis.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/components/YAxis.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BarData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/BubbleEntry.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/CandleData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/CandleEntry.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/ChartData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java similarity index 92% rename from MPChartLib/src/com/github/mikephil/charting/data/DataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index fed5f780ea..f260339ca7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -96,7 +96,7 @@ public void calcMinMax() { mYMax = 0.f; } - if(mXMin == Float.MAX_VALUE) { + if (mXMin == Float.MAX_VALUE) { mXMin = 0.f; mXMax = 0.f; } @@ -287,42 +287,39 @@ public T getEntryForIndex(int index) { @Override public int getEntryIndex(float xPos, Rounding rounding) { + if (mValues == null || mValues.isEmpty()) + return -1; + int low = 0; int high = mValues.size() - 1; - int closest = -1; - while (low <= high) { - int m = (high + low) / 2; + while (low < high) { + int m = (low + high) / 2; - if (xPos == mValues.get(m).getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xPos) - m--; + float d1 = Math.abs(mValues.get(m).getX() - xPos); + float d2 = Math.abs(mValues.get(m + 1).getX() - xPos); - return m; - } - - if (xPos > mValues.get(m).getX()) + if (d2 <= d1) { low = m + 1; - else - high = m - 1; - - closest = m; + } else { + high = m; + } } - if (closest != -1) { - float closestXPos = mValues.get(closest).getX(); + if (high != -1) { + float closestXPos = mValues.get(high).getX(); if (rounding == Rounding.UP) { - if (closestXPos < xPos && closest < mValues.size() - 1) { - ++closest; + if (closestXPos < xPos && high < mValues.size() - 1) { + ++high; } } else if (rounding == Rounding.DOWN) { - if (closestXPos > xPos && closest > 0) { - --closest; + if (closestXPos > xPos && high > 0) { + --high; } } } - return closest; + return high; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/Entry.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/LineData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/PieData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/RadarData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/XAxisValue.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/filter/Approximator.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/exception/DrawingDataSetNotCreatedException.java b/MPChartLib/src/main/java/com/github/mikephil/charting/exception/DrawingDataSetNotCreatedException.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/exception/DrawingDataSetNotCreatedException.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/exception/DrawingDataSetNotCreatedException.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/ColorFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/ColorFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/DefaultValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/XAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/XAxisValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/highlight/Range.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/AnimatedZoomJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/MoveViewJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/ViewPortJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/ViewPortJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/jobs/ZoomJob.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnDrawLineChartTouchListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnDrawListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnDrawListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java diff --git a/MPChartLib/src/com/github/mikephil/charting/matrix/Vector3.java b/MPChartLib/src/main/java/com/github/mikephil/charting/matrix/Vector3.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/matrix/Vector3.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/matrix/Vector3.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/ColorTemplate.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/FSize.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/FileUtils.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/PointD.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/Utils.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java similarity index 100% rename from MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java new file mode 100644 index 0000000000..5e86a89e66 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -0,0 +1,59 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.*; + +/** + * Created by philipp on 31/05/16. + */ +public class DataSetTest { + + + @Test + public void testGetEntryForXPos() { + + List entries = new ArrayList(); + entries.add(new Entry(10, 10)); + entries.add(new Entry(15, 5)); + entries.add(new Entry(21, 5)); + + ScatterDataSet set = new ScatterDataSet(entries, ""); + + Entry closest = set.getEntryForXPos(17, DataSet.Rounding.CLOSEST); + assertEquals(15, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(17, DataSet.Rounding.DOWN); + assertEquals(15, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(15, DataSet.Rounding.DOWN); + assertEquals(15, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(14, DataSet.Rounding.DOWN); + assertEquals(10, closest.getX(), 0.01f); + assertEquals(10, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(17, DataSet.Rounding.UP); + assertEquals(21, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(21, DataSet.Rounding.UP); + assertEquals(21, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + + closest = set.getEntryForXPos(21, DataSet.Rounding.CLOSEST); + assertEquals(21, closest.getX(), 0.01f); + assertEquals(5, closest.getY(), 0.01f); + } +} From 0221ddfd24bac9a09fd6a56134334a44d73d6999 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 09:49:31 +0200 Subject: [PATCH 0914/1390] Work on getting highest and lowest visible x --- .../CubicLineChartActivity.java | 2 +- .../mikephil/charting/charts/BarChart.java | 66 ++-- .../charting/charts/BarLineChartBase.java | 30 +- .../charting/charts/HorizontalBarChart.java | 370 +++++++++--------- .../mikephil/charting/utils/Transformer.java | 15 +- 5 files changed, 251 insertions(+), 232 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index ad8d10714d..ccd15f2067 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -282,7 +282,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 20;// + (float) // ((mult * // 0.1) / 10); - yVals.add(new Entry(val, i)); + yVals.add(new Entry(i, val)); } LineDataSet set1; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 9eed5a3f8d..0a69c03748 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -185,37 +185,37 @@ public BarData getBarData() { return mData; } - /** - * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. - * - * @return - */ - @Override - public float getLowestVisibleX() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return ((pts[0] <= getXChartMin()) ? 0 : (pts[0] / div) + 1); - } - - /** - * Returns the highest x-index (value on the x-axis) that is still visible on the chart. - * - * @return - */ - @Override - public float getHighestVisibleX() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); - } +// /** +// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. +// * +// * @return +// */ +// @Override +// public float getLowestVisibleX() { +// +// float step = mData.getDataSetCount(); +// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); +// +// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; +// +// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); +// return ((pts[0] <= getXChartMin()) ? 0 : (pts[0] / div) + 1); +// } +// +// /** +// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. +// * +// * @return +// */ +// @Override +// public float getHighestVisibleX() { +// +// float step = mData.getDataSetCount(); +// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); +// +// float[] pts = new float[] { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; +// +// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); +// return ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); +// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 64a22aa107..714ff17a61 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -44,7 +44,8 @@ * @author Philipp Jahoda */ @SuppressLint("RtlHardcoded") -public abstract class BarLineChartBase>> +public abstract class BarLineChartBase>> extends Chart implements BarLineScatterCandleBubbleDataProvider { /** @@ -263,7 +264,7 @@ protected void onDraw(Canvas canvas) { clipRestoreCount = canvas.save(); canvas.clipRect(mViewPortHandler.getContentRect()); - + if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); @@ -754,13 +755,16 @@ public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDep * @param duration */ @TargetApi(11) - public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { + public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, + long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis + .getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); } else { @@ -1370,11 +1374,9 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float */ @Override public float getLowestVisibleX() { - float[] pts = new float[]{ - mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() - }; - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (pts[0] <= 0) ? 0 : (float) Math.ceil(pts[0]); + PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom()); + return (float) Math.min(mXAxis.mAxisMinimum, pos.x); } /** @@ -1385,11 +1387,9 @@ public float getLowestVisibleX() { */ @Override public float getHighestVisibleX() { - float[] pts = new float[]{ - mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() - }; - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (float) Math.min(mXAxis.mAxisMaximum, Math.floor(pts[0])); + PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom()); + return (float) Math.min(mXAxis.mAxisMaximum, pos.x); } /** @@ -1617,7 +1617,7 @@ public Paint getPaint(int which) { @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { - + // Saving current position of chart. float[] pts = new float[2]; if (mKeepPositionOnRotation) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index be59090cac..f78419ce50 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -17,217 +17,235 @@ import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.TransformerHorizontalBarChart; import com.github.mikephil.charting.utils.Utils; /** * BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched, meaning the YAxis class * represents the horizontal values and the XAxis class represents the vertical values. - * + * * @author Philipp Jahoda */ public class HorizontalBarChart extends BarChart { - public HorizontalBarChart(Context context) { - super(context); - } + public HorizontalBarChart(Context context) { + super(context); + } - public HorizontalBarChart(Context context, AttributeSet attrs) { - super(context, attrs); - } + public HorizontalBarChart(Context context, AttributeSet attrs) { + super(context, attrs); + } - public HorizontalBarChart(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } + public HorizontalBarChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } - @Override - protected void init() { - super.init(); + @Override + protected void init() { + super.init(); - mLeftAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); - mRightAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); + mLeftAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); + mRightAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); - mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler); - setHighlighter(new HorizontalBarHighlighter(this)); + mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler); + setHighlighter(new HorizontalBarHighlighter(this)); - mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); - mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, mRightAxisTransformer); - mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); - } + mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); + mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, mRightAxisTransformer); + mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + } - private RectF mOffsetsBuffer = new RectF(); + private RectF mOffsetsBuffer = new RectF(); - @Override - public void calculateOffsets() { + @Override + public void calculateOffsets() { - float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; + float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; - calculateLegendOffsets(mOffsetsBuffer); + calculateLegendOffsets(mOffsetsBuffer); - offsetLeft += mOffsetsBuffer.left; - offsetTop += mOffsetsBuffer.top; - offsetRight += mOffsetsBuffer.right; - offsetBottom += mOffsetsBuffer.bottom; + offsetLeft += mOffsetsBuffer.left; + offsetTop += mOffsetsBuffer.top; + offsetRight += mOffsetsBuffer.right; + offsetBottom += mOffsetsBuffer.bottom; - // offsets for y-labels - if (mAxisLeft.needsOffset()) { - offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels()); - } + // offsets for y-labels + if (mAxisLeft.needsOffset()) { + offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels()); + } - if (mAxisRight.needsOffset()) { - offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getPaintAxisLabels()); - } + if (mAxisRight.needsOffset()) { + offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getPaintAxisLabels()); + } - float xlabelwidth = mXAxis.mLabelRotatedWidth; + float xlabelwidth = mXAxis.mLabelRotatedWidth; - if (mXAxis.isEnabled()) { + if (mXAxis.isEnabled()) { - // offsets for x-labels - if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + // offsets for x-labels + if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - offsetLeft += xlabelwidth; + offsetLeft += xlabelwidth; - } else if (mXAxis.getPosition() == XAxisPosition.TOP) { + } else if (mXAxis.getPosition() == XAxisPosition.TOP) { - offsetRight += xlabelwidth; + offsetRight += xlabelwidth; - } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { - offsetLeft += xlabelwidth; - offsetRight += xlabelwidth; - } - } + offsetLeft += xlabelwidth; + offsetRight += xlabelwidth; + } + } - offsetTop += getExtraTopOffset(); - offsetRight += getExtraRightOffset(); - offsetBottom += getExtraBottomOffset(); - offsetLeft += getExtraLeftOffset(); + offsetTop += getExtraTopOffset(); + offsetRight += getExtraRightOffset(); + offsetBottom += getExtraBottomOffset(); + offsetLeft += getExtraLeftOffset(); - float minOffset = Utils.convertDpToPixel(mMinOffset); + float minOffset = Utils.convertDpToPixel(mMinOffset); - mViewPortHandler.restrainViewPort( - Math.max(minOffset, offsetLeft), - Math.max(minOffset, offsetTop), - Math.max(minOffset, offsetRight), - Math.max(minOffset, offsetBottom)); + mViewPortHandler.restrainViewPort( + Math.max(minOffset, offsetLeft), + Math.max(minOffset, offsetTop), + Math.max(minOffset, offsetRight), + Math.max(minOffset, offsetBottom)); - if (mLogEnabled) { - Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + ", offsetRight: " + offsetRight + ", offsetBottom: " - + offsetBottom); - Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); - } + if (mLogEnabled) { + Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + ", offsetRight: " + + offsetRight + ", offsetBottom: " + + offsetBottom); + Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); + } - prepareOffsetMatrix(); - prepareValuePxMatrix(); - } + prepareOffsetMatrix(); + prepareValuePxMatrix(); + } - @Override - protected void prepareValuePxMatrix() { - mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mXAxis.mAxisRange, mXAxis.mAxisMinimum); - mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mXAxis.mAxisRange, mXAxis.mAxisMinimum); - } - - @Override - protected void calcModulus() { - float[] values = new float[9]; - mViewPortHandler.getMatrixTouch().getValues(values); - - mXAxis.mAxisLabelModulus = - (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) - / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); - - if (mXAxis.mAxisLabelModulus < 1) - mXAxis.mAxisLabelModulus = 1; - } - - @Override - public RectF getBarBounds(BarEntry e) { - - IBarDataSet set = mData.getDataSetForEntry(e); - - if (set == null) - return null; - - float barspace = set.getBarSpace(); - float y = e.getY(); - float x = e.getX(); - - float spaceHalf = barspace / 2f; - - float top = x - 0.5f + spaceHalf; - float bottom = x + 0.5f - spaceHalf; - float left = y >= 0 ? y : 0; - float right = y <= 0 ? y : 0; - - RectF bounds = new RectF(left, top, right, bottom); - - getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - - return bounds; - } - - @Override - public PointF getPosition(Entry e, AxisDependency axis) { - - if (e == null) - return null; - - float[] vals = new float[] { e.getY(), e.getX() }; - - getTransformer(axis).pointValuesToPixel(vals); - - return new PointF(vals[0], vals[1]); - } - - /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point - * inside the BarChart. - * - * @param x - * @param y - * @return - */ - @Override - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else - return getHighlighter().getHighlight(y, x); // switch x and y - } - - /** - * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. - * - * @return - */ - @Override - public float getLowestVisibleX() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); - } - - /** - * Returns the highest x-index (value on the x-axis) that is still visible on the chart. - * - * @return - */ - @Override - public float getHighestVisibleX() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); - } + @Override + protected void prepareValuePxMatrix() { + mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mXAxis.mAxisRange, + mXAxis.mAxisMinimum); + mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mXAxis.mAxisRange, + mXAxis.mAxisMinimum); + } + + @Override + protected void calcModulus() { + float[] values = new float[9]; + mViewPortHandler.getMatrixTouch().getValues(values); + + mXAxis.mAxisLabelModulus = + (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) + / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); + + if (mXAxis.mAxisLabelModulus < 1) + mXAxis.mAxisLabelModulus = 1; + } + + @Override + public RectF getBarBounds(BarEntry e) { + + IBarDataSet set = mData.getDataSetForEntry(e); + + if (set == null) + return null; + + float barspace = set.getBarSpace(); + float y = e.getY(); + float x = e.getX(); + + float spaceHalf = barspace / 2f; + + float top = x - 0.5f + spaceHalf; + float bottom = x + 0.5f - spaceHalf; + float left = y >= 0 ? y : 0; + float right = y <= 0 ? y : 0; + + RectF bounds = new RectF(left, top, right, bottom); + + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); + + return bounds; + } + + @Override + public PointF getPosition(Entry e, AxisDependency axis) { + + if (e == null) + return null; + + float[] vals = new float[]{e.getY(), e.getX()}; + + getTransformer(axis).pointValuesToPixel(vals); + + return new PointF(vals[0], vals[1]); + } + + /** + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point + * inside the BarChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else + return getHighlighter().getHighlight(y, x); // switch x and y + } + + @Override + public float getLowestVisibleX() { + PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom()); + return (float) Math.min(mXAxis.mAxisMinimum, pos.y); + } + + @Override + public float getHighestVisibleX() { + PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop()); + return (float) Math.min(mXAxis.mAxisMaximum, pos.y); + } + +// /** +// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. +// * +// * @return +// */ +// @Override +// public float getLowestVisibleX() { +// +// float step = mData.getDataSetCount(); +// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); +// +// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; +// +// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); +// return (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); +// } +// +// /** +// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. +// * +// * @return +// */ +// @Override +// public float getHighestVisibleX() { +// +// float step = mData.getDataSetCount(); +// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); +// +// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() }; +// +// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); +// return ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); +// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index d7f19d3992..af7074559a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -376,6 +376,9 @@ public void pixelsToValue(float[] pixels) { tmp.mapPoints(pixels); } + /** buffer for performance */ + float[] ptsBuffer = new float[2]; + /** * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to @@ -388,15 +391,13 @@ public void pixelsToValue(float[] pixels) { */ public PointD getValuesByTouchPoint(float x, float y) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - pts[1] = y; + ptsBuffer[0] = x; + ptsBuffer[1] = y; - pixelsToValue(pts); + pixelsToValue(ptsBuffer); - double xTouchVal = pts[0]; - double yTouchVal = pts[1]; + double xTouchVal = ptsBuffer[0]; + double yTouchVal = ptsBuffer[1]; return new PointD(xTouchVal, yTouchVal); } From a0d39b918be3b5798280bcdee38de9eb7b0ef2f6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 11:08:29 +0200 Subject: [PATCH 0915/1390] Work on highlighting --- .../mpchartexample/AnotherBarActivity.java | 2 +- .../mpchartexample/BarChartActivity.java | 4 +- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BarChartActivitySinus.java | 4 +- .../BarChartPositiveNegative.java | 2 +- .../CandleStickChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 6 +- .../HorizontalBarChartActivity.java | 4 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 10 +- .../mpchartexample/LineChartActivity2.java | 2 +- .../LineChartActivityColored.java | 2 +- .../mpchartexample/LineChartTime.java | 4 +- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PerformanceLineChart.java | 2 +- .../RealtimeLineChartActivity.java | 4 +- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 4 +- .../StackedBarActivityNegative.java | 2 +- .../custom/MyCustomXAxisValueFormatter.java | 4 +- .../mpchartexample/custom/MyMarkerView.java | 2 +- .../custom/StackedBarsMarkerView.java | 4 +- .../notimportant/MainActivity.java | 8 +- .../realm/RealmBaseActivity.java | 2 +- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../charting/animation/ChartAnimator.java | 32 ++-- .../charting/buffer/AbstractBuffer.java | 14 +- .../mikephil/charting/buffer/BarBuffer.java | 4 +- .../charting/buffer/HorizontalBarBuffer.java | 2 +- .../mikephil/charting/charts/BarChart.java | 10 +- .../charting/charts/BarLineChartBase.java | 146 ++++++++---------- .../mikephil/charting/charts/Chart.java | 90 +++++------ .../charting/charts/CombinedChart.java | 4 +- .../charting/charts/HorizontalBarChart.java | 17 +- .../mikephil/charting/charts/PieChart.java | 16 +- .../charting/charts/PieRadarChartBase.java | 10 +- .../mikephil/charting/charts/RadarChart.java | 16 +- .../charting/components/AxisBase.java | 30 ++-- .../charting/components/ComponentBase.java | 10 +- .../mikephil/charting/components/Legend.java | 2 +- .../charting/components/LimitLine.java | 16 +- .../charting/components/MarkerView.java | 12 +- .../mikephil/charting/components/XAxis.java | 42 ++--- .../mikephil/charting/components/YAxis.java | 52 +++---- .../mikephil/charting/data/BarDataSet.java | 14 +- .../mikephil/charting/data/BarEntry.java | 4 +- .../mikephil/charting/data/BaseDataSet.java | 12 +- .../mikephil/charting/data/BubbleEntry.java | 12 +- .../mikephil/charting/data/CandleEntry.java | 34 ++-- .../mikephil/charting/data/ChartData.java | 105 +++++++------ .../mikephil/charting/data/CombinedData.java | 4 +- .../mikephil/charting/data/DataSet.java | 14 +- .../github/mikephil/charting/data/Entry.java | 26 ++-- .../mikephil/charting/data/LineDataSet.java | 6 +- .../charting/data/LineRadarDataSet.java | 2 +- .../mikephil/charting/data/PieData.java | 2 +- .../mikephil/charting/data/XAxisValue.java | 16 +- .../charting/data/filter/Approximator.java | 4 +- .../data/realm/base/RealmBaseDataSet.java | 20 +-- .../realm/base/RealmLineRadarDataSet.java | 2 +- .../realm/implementation/RealmBarDataSet.java | 10 +- .../implementation/RealmBubbleDataSet.java | 6 +- .../implementation/RealmCandleDataSet.java | 18 +-- .../implementation/RealmLineDataSet.java | 12 +- .../realm/implementation/RealmPieDataSet.java | 6 +- .../implementation/RealmRadarDataSet.java | 6 +- .../implementation/RealmScatterDataSet.java | 6 +- .../formatter/DefaultValueFormatter.java | 4 +- .../formatter/DefaultXAxisValueFormatter.java | 4 +- .../formatter/DefaultYAxisValueFormatter.java | 4 +- .../charting/formatter/FillFormatter.java | 2 +- .../formatter/LargeValueFormatter.java | 4 +- .../charting/formatter/PercentFormatter.java | 2 +- .../formatter/StackedValueFormatter.java | 8 +- .../charting/formatter/ValueFormatter.java | 6 +- .../formatter/XAxisValueFormatter.java | 8 +- .../formatter/YAxisValueFormatter.java | 6 +- .../charting/highlight/BarHighlighter.java | 16 +- .../charting/highlight/ChartHighlighter.java | 45 +++--- .../highlight/CombinedHighlighter.java | 4 +- .../charting/highlight/Highlight.java | 56 +++---- .../highlight/HorizontalBarHighlighter.java | 10 +- .../mikephil/charting/highlight/Range.java | 4 +- .../dataprovider/ChartInterface.java | 8 +- .../interfaces/datasets/IBarDataSet.java | 8 +- .../interfaces/datasets/IDataSet.java | 46 +++--- .../datasets/ILineRadarDataSet.java | 2 +- .../listener/BarLineChartTouchListener.java | 16 +- .../charting/listener/ChartTouchListener.java | 2 +- .../listener/OnChartGestureListener.java | 8 +- .../OnChartValueSelectedListener.java | 2 +- .../listener/PieRadarChartTouchListener.java | 2 +- .../charting/renderer/AxisRenderer.java | 8 +- .../charting/renderer/BarChartRenderer.java | 10 +- .../renderer/BubbleChartRenderer.java | 4 +- .../renderer/CandleStickChartRenderer.java | 11 +- .../charting/renderer/DataRenderer.java | 12 +- .../renderer/HorizontalBarChartRenderer.java | 10 +- .../charting/renderer/LineChartRenderer.java | 22 +-- .../LineScatterCandleRadarRenderer.java | 13 +- .../charting/renderer/PieChartRenderer.java | 8 +- .../charting/renderer/RadarChartRenderer.java | 13 +- .../mikephil/charting/renderer/Renderer.java | 8 +- .../renderer/ScatterChartRenderer.java | 21 +-- .../charting/renderer/XAxisRenderer.java | 10 +- .../renderer/XAxisRendererBarChart.java | 2 +- .../XAxisRendererHorizontalBarChart.java | 4 +- .../renderer/XAxisRendererRadarChart.java | 2 +- .../charting/renderer/YAxisRenderer.java | 14 +- .../YAxisRendererHorizontalBarChart.java | 16 +- .../renderer/YAxisRendererRadarChart.java | 4 +- .../charting/utils/EntryXIndexComparator.java | 2 +- .../github/mikephil/charting/utils/FSize.java | 2 +- .../mikephil/charting/utils/PointD.java | 2 +- .../charting/utils/SelectionDetail.java | 28 ++-- .../mikephil/charting/utils/Transformer.java | 62 +++++--- .../github/mikephil/charting/utils/Utils.java | 32 ++-- .../charting/utils/ViewPortHandler.java | 70 ++++----- README.md | 6 +- gradlew | 6 +- gradlew.bat | 2 +- 128 files changed, 813 insertions(+), 832 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 4a06e62c3c..20f015e640 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -54,7 +54,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 48d8fe02a3..a6c662a4c3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -74,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); @@ -282,7 +282,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); - Log.i("x-index", + Log.i("xPx-index", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index ef53cd5e86..5da09fc6d7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -62,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawBorders(true); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 7d9be92996..d7d5b2f5cb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -63,10 +63,10 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); - // draw shadows for each bar that show the maximum value + // draw shadows for each bar that show the maximum yValue // mChart.setDrawBarShadow(true); // mChart.setDrawXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index b795e80a9d..a2f653a7b9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -47,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 9cbcfd9247..1eb8fa6b8c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -57,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index ccd15f2067..4c42066d7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -73,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index cdd34adafc..9e2ba71981 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -69,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setEnabled(false); // mChart.setYRange(-40f, 40f, true); - // call this to reset the changed y-range + // call this to reset the changed yPx-range // mChart.resetYRange(true); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 3f5d4d152a..c67086f667 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -62,7 +62,7 @@ private void addEntry() { data.addDataSet(set); } - // add a new x-value first + // add a new xPx-yValue first data.addXValue(new XAxisValue(set.getEntryCount(), set.getEntryCount() + "")); // choose a random dataSet @@ -111,11 +111,11 @@ private void addDataSet() { int count = (data.getDataSetCount() + 1); - // create 10 y-vals + // create 10 yPx-vals ArrayList yVals = new ArrayList(); if(data.getXValCount() == 0) { - // add 10 x-entries + // add 10 xPx-entries for (int i = 0; i < 10; i++) { data.addXValue(new XAxisValue(i, i + "")); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 0acda456f8..ac3c6035ff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -72,10 +72,10 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); - // draw shadows for each bar that show the maximum value + // draw shadows for each bar that show the maximum yValue // mChart.setDrawBarShadow(true); // mChart.setDrawXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 086de305af..ab43c195ac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -69,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(true); // set an alternative background color diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 946e23b14d..ed3f86b921 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -84,7 +84,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setScaleXEnabled(true); // mChart.setScaleYEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(true); // set an alternative background color @@ -97,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { // set the marker to the chart mChart.setMarkerView(mv); - // x-axis limit line + // xPx-axis limit line LimitLine llXAxis = new LimitLine(10f, "Index 10"); llXAxis.setLineWidth(4f); llXAxis.enableDashedLine(10f, 10f, 0f); @@ -106,7 +106,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); - //xAxis.addLimitLine(llXAxis); // add x-axis limit line + //xAxis.addLimitLine(llXAxis); // add xPx-axis limit line Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -346,7 +346,7 @@ private void setData(int count, float range) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * - // 0.1) / 10);x + // 0.1) / 10);xPx yVals.add(new Entry(i, val)); xVals.add(new XAxisValue(i, i + "")); } @@ -400,7 +400,7 @@ private void setData(int count, float range) { @Override public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); + Log.i("Gesture", "START, xPx: " + me.getX() + ", yPx: " + me.getY()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 84ad55ac9c..9644dbd23a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -76,7 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(true); // set an alternative background color diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 9b65e1c74b..0474ea6508 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -74,7 +74,7 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setDragEnabled(true); chart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately chart.setPinchZoom(false); chart.setBackgroundColor(color); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 2e72d60dfa..a45baab65d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -73,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(true); // set an alternative background color @@ -104,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setSpaceBetweenLabels(1); - // custom x-axis min / max + // custom xPx-axis min / max xAxis.setAxisMinValue(5000); xAxis.setAxisMaxValue(30000); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index d98e83954a..e890773750 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -69,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mSeekBarX.setProgress(20); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 935f91721a..eedec87e5c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 6dda2d1d38..4edf885c94 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setScaleEnabled(true); mChart.setDrawGridBackground(false); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(true); // set an alternative background color @@ -139,7 +139,7 @@ private void addEntry() { data.addDataSet(set); } - // add a new x-value first + // add a new xPx-yValue first data.addXValue(new XAxisValue(data.getXValCount() ,mMonths[data.getXValCount() % 12] + " " + (year + data.getXValCount() / 12))); data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 1dcff1efe1..8c8ae3bb0a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -31,7 +31,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 36fd6f1d33..e5d7ce1076 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -63,7 +63,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(40); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); @@ -71,7 +71,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValueAboveBar(false); - // change the position of the y-labels + // change the position of the yPx-labels YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setValueFormatter(new MyYAxisValueFormatter()); leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index ddd8ac3fcf..5f74bbed62 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -51,7 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setDescription(""); - // scaling can now only be done on x- and y-axis separately + // scaling can now only be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index bdf918b1b7..ed25ba090a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -15,9 +15,9 @@ public MyCustomXAxisValueFormatter() { @Override public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { - //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); + //Log.i("TRANS", "xPx: " + viewPortHandler.getTransX() + ", yPx: " + viewPortHandler.getTransY()); - // e.g. adjust the x-axis values depending on scale / zoom level + // e.g. adjust the xPx-axis values depending on scale / zoom level if (viewPortHandler.getScaleX() > 5) return "4"; else if (viewPortHandler.getScaleX() > 3) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 53a3bc47f4..4389f11c04 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -50,7 +50,7 @@ public int getXOffset(float xpos) { @Override public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value + // this will cause the marker-view to be above the selected yValue return -getHeight(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 0b8938778d..4a28f772e8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -37,7 +37,7 @@ public void refreshContent(Entry e, Highlight highlight) { if(be.getYVals() != null) { - // draw the stack value + // draw the stack yValue tvContent.setText("" + Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); } else { tvContent.setText("" + Utils.formatNumber(be.getY(), 0, true)); @@ -56,7 +56,7 @@ public int getXOffset(float xpos) { @Override public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value + // this will cause the marker-view to be above the selected yValue return -getHeight(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 34362f1e4e..f511862353 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -68,14 +68,14 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); objects.add(new ContentItem("Line Chart (Dual YAxis)", - "Demonstration of the linechart with dual y-axis.")); + "Demonstration of the linechart with dual yPx-axis.")); objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); objects.add(new ContentItem("Horizontal Bar Chart", "A simple demonstration of the horizontal bar chart.")); objects.add(new ContentItem("Combined Chart", "Demonstrates how to create a combined chart (bar and line in this case).")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); - objects.add(new ContentItem("Pie Chart with value lines", "A simple demonstration of the pie chart with polyline notes.")); + objects.add(new ContentItem("Pie Chart with yValue lines", "A simple demonstration of the pie chart with polyline notes.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); objects.add(new ContentItem("Stacked Bar Chart", @@ -99,7 +99,7 @@ protected void onCreate(Bundle savedInstanceState) { "Demonstrates the usage of different chart types inside a ListView.")); objects.add(new ContentItem( "Inverted Line Chart", - "Demonstrates the feature of inverting the y-axis.")); + "Demonstrates the feature of inverting the yPx-axis.")); objects.add(new ContentItem( "Candle Stick Chart", "Demonstrates usage of the CandleStickChart.")); @@ -114,7 +114,7 @@ protected void onCreate(Bundle savedInstanceState) { "Shows a LineChart with different background and line color.")); objects.add(new ContentItem( "Realtime Chart", - "This chart is fed with new data in realtime. It also restrains the view on the x-axis.")); + "This chart is fed with new data in realtime. It also restrains the view on the xPx-axis.")); objects.add(new ContentItem( "Dynamical data adding", "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 1f51281e35..f84031c2db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -55,7 +55,7 @@ protected void setup(Chart chart) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately + // if disabled, scaling can be done on xPx- and yPx-axis separately mChart.setPinchZoom(false); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index ecde642f4f..9527f3e6be 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -50,7 +50,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "value", "xIndex"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "yValue", "xIndex"); // stacked entries set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); set.setLabel("Realm BarDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index 2f23561622..cd188a4266 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "value", "xIndex", "bubbleSize"); + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "yValue", "xIndex", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); set.setColors(ColorTemplate.COLORFUL_COLORS, 110); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index c2f8803b85..36a8dc5abd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result, "value", "xIndex"); + RealmLineDataSet set = new RealmLineDataSet(result, "yValue", "xIndex"); set.setDrawCubic(false); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 489399bc9e..dfe37e61f6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "value", "xIndex"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "xIndex"); // stacked entries set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 3e1c688f6c..599c7f9a29 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -55,7 +55,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "value", "xIndex"); // stacked entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue", "xIndex"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index 135667a4bf..a465433d00 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmScatterDataSet set = new RealmScatterDataSet(result, "value", "xIndex"); + RealmScatterDataSet set = new RealmScatterDataSet(result, "yValue", "xIndex"); set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index 639442a4c9..455f7be3e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -7,7 +7,7 @@ /** * Object responsible for all animations in the Chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. + * API LEVEL 11 (Android 3.0.xPx) AND HIGHER. * * @author Philipp Jahoda */ @@ -29,10 +29,10 @@ public ChartAnimator(AnimatorUpdateListener listener) { */ /** CODE BELOW THIS RELATED TO ANIMATION */ - /** the phase that is animated and influences the drawn values on the y-axis */ + /** the phase that is animated and influences the drawn values on the yPx-axis */ protected float mPhaseY = 1f; - /** the phase that is animated and influences the drawn values on the x-axis */ + /** the phase that is animated and influences the drawn values on the xPx-axis */ protected float mPhaseX = 1f; /** @@ -41,7 +41,7 @@ public ChartAnimator(AnimatorUpdateListener listener) { /** METHODS FOR CUSTOM EASING */ /** - * Animates the drawing / rendering of the chart on both x- and y-axis with + * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -78,7 +78,7 @@ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction e } /** - * Animates the rendering of the chart on the x-axis with the specified + * Animates the rendering of the chart on the xPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -98,7 +98,7 @@ public void animateX(int durationMillis, EasingFunction easing) { } /** - * Animates the rendering of the chart on the y-axis with the specified + * Animates the rendering of the chart on the yPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -123,7 +123,7 @@ public void animateY(int durationMillis, EasingFunction easing) { /** METHODS FOR PREDEFINED EASING */ /** - * Animates the drawing / rendering of the chart on both x- and y-axis with + * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -160,7 +160,7 @@ public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOpt } /** - * Animates the rendering of the chart on the x-axis with the specified + * Animates the rendering of the chart on the xPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -180,7 +180,7 @@ public void animateX(int durationMillis, Easing.EasingOption easing) { } /** - * Animates the rendering of the chart on the y-axis with the specified + * Animates the rendering of the chart on the yPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -205,7 +205,7 @@ public void animateY(int durationMillis, Easing.EasingOption easing) { /** METHODS FOR ANIMATION WITHOUT EASING */ /** - * Animates the drawing / rendering of the chart on both x- and y-axis with + * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -237,7 +237,7 @@ public void animateXY(int durationMillisX, int durationMillisY) { } /** - * Animates the rendering of the chart on the x-axis with the specified + * Animates the rendering of the chart on the xPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -255,7 +255,7 @@ public void animateX(int durationMillis) { } /** - * Animates the rendering of the chart on the y-axis with the specified + * Animates the rendering of the chart on the yPx-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -273,7 +273,7 @@ public void animateY(int durationMillis) { } /** - * This gets the y-phase that is used to animate the values. + * This gets the yPx-phase that is used to animate the values. * * @return */ @@ -282,7 +282,7 @@ public float getPhaseY() { } /** - * This modifys the y-phase that is used to animate the values. + * This modifys the yPx-phase that is used to animate the values. * * @param phase */ @@ -291,7 +291,7 @@ public void setPhaseY(float phase) { } /** - * This gets the x-phase that is used to animate the values. + * This gets the xPx-phase that is used to animate the values. * * @return */ @@ -300,7 +300,7 @@ public float getPhaseX() { } /** - * This modifys the x-phase that is used to animate the values. + * This modifys the xPx-phase that is used to animate the values. * * @param phase */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java index 958d12afba..6df0c01ba8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -15,19 +15,19 @@ public abstract class AbstractBuffer { /** index in the buffer */ protected int index = 0; - /** float-buffer that holds the data points to draw, order: x,y,x,y,... */ + /** float-buffer that holds the data points to draw, order: xPx,yPx,xPx,yPx,... */ public final float[] buffer; - /** animation phase x-axis */ + /** animation phase xPx-axis */ protected float phaseX = 1f; - /** animation phase y-axis */ + /** animation phase yPx-axis */ protected float phaseY = 1f; - /** indicates from which x-index the visible data begins */ + /** indicates from which xPx-index the visible data begins */ protected int mFrom = 0; - /** indicates to which x-index the visible data ranges */ + /** indicates to which xPx-index the visible data ranges */ protected int mTo = 0; /** @@ -40,14 +40,14 @@ public AbstractBuffer(int size) { buffer = new float[size]; } - /** limits the drawing on the x-axis */ + /** limits the drawing on the xPx-axis */ public void limitFrom(int from) { if (from < 0) from = 0; mFrom = from; } - /** limits the drawing on the x-axis */ + /** limits the drawing on the xPx-axis */ public void limitTo(int to) { if (to < 0) to = 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java index 91fc8c769a..d0ccaf01a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java @@ -14,7 +14,7 @@ public class BarBuffer extends AbstractBuffer { protected boolean mInverted = false; /** - * interval on the x-axis per group + * interval on the xPx-axis per group */ protected float mInterval = 0f; @@ -71,7 +71,7 @@ public void feed(IBarDataSet data) { BarEntry e = data.getEntryForIndex(i); - // calculate the x-position, depending on interval + // calculate the xPx-position, depending on interval float x = mInterval * i + dataSetSpace; float y = e.getY(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index e50267bd95..5a7044522e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -24,7 +24,7 @@ public void feed(IBarDataSet data) { BarEntry e = data.getEntryForIndex(i); - // calculate the x-position, depending on datasetcount + // calculate the xPx-position, depending on datasetcount float x = e.getX() + e.getX() * dataSetOffset + mDataSetIndex + mGroupSpace * e.getX() + groupSpaceHalf; float y = e.getY(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 0a69c03748..f5958d9018 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -31,7 +31,7 @@ public class BarChart extends BarLineChartBase implements BarDataProvid private boolean mDrawValueAboveBar = true; /** - * if set to true, a grey area is drawn behind each bar that indicates the maximum value + * if set to true, a grey area is drawn behind each bar that indicates the maximum yValue */ private boolean mDrawBarShadow = false; @@ -75,7 +75,7 @@ protected void calcMinMax() { } /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point + * Returns the Highlight object (contains xPx-index and DataSet index) of the selected yValue at the given touch point * inside the BarChart. * * @param x @@ -162,7 +162,7 @@ public boolean isDrawValueAboveBarEnabled() { } /** - * If set to true, a grey area is drawn behind each bar that indicates the maximum value. Enabling his will reduce + * If set to true, a grey area is drawn behind each bar that indicates the maximum yValue. Enabling his will reduce * performance by about 50%. * * @param enabled @@ -186,7 +186,7 @@ public BarData getBarData() { } // /** -// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. +// * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on the chart. // * // * @return // */ @@ -203,7 +203,7 @@ public BarData getBarData() { // } // // /** -// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. +// * Returns the highest xPx-index (yValue on the xPx-axis) that is still visible on the chart. // * // * @return // */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 714ff17a61..510c1e0a88 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -50,20 +50,20 @@ public abstract class BarLineChartBase zoom out, if > 1f --> zoom in @@ -730,7 +730,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { /** * Zooms in or out by the given scale factor. - * x and y are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). + * xPx and yPx are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). * * @param scaleX * @param scaleY @@ -785,7 +785,7 @@ public void fitScreen() { } /** - * Sets the minimum scale factor value to which can be zoomed out. 1f = + * Sets the minimum scale factor yValue to which can be zoomed out. 1f = * fitScreen * * @param scaleX @@ -797,12 +797,12 @@ public void setScaleMinima(float scaleX, float scaleY) { } /** - * Sets the size of the area (range on the x-axis) that should be maximum + * Sets the size of the area (range on the xPx-axis) that should be maximum * visible at once (no further zooming out allowed). If this is e.g. set to - * 10, no more than 10 values on the x-axis can be viewed at once without + * 10, no more than 10 values on the xPx-axis can be viewed at once without * scrolling. * - * @param maxXRange The maximum visible range of x-values. + * @param maxXRange The maximum visible range of xPx-values. */ public void setVisibleXRangeMaximum(float maxXRange) { float xScale = mXAxis.mAxisRange / (maxXRange); @@ -810,12 +810,12 @@ public void setVisibleXRangeMaximum(float maxXRange) { } /** - * Sets the size of the area (range on the x-axis) that should be minimum + * Sets the size of the area (range on the xPx-axis) that should be minimum * visible at once (no further zooming in allowed). If this is e.g. set to - * 10, no less than 10 values on the x-axis can be viewed at once without + * 10, no less than 10 values on the xPx-axis can be viewed at once without * scrolling. * - * @param minXRange The minimum visible range of x-values. + * @param minXRange The minimum visible range of xPx-values. */ public void setVisibleXRangeMinimum(float minXRange) { float xScale = mXAxis.mAxisRange / (minXRange); @@ -823,7 +823,7 @@ public void setVisibleXRangeMinimum(float minXRange) { } /** - * Limits the maximum and minimum value count that can be visible by + * Limits the maximum and minimum yValue count that can be visible by * pinching and zooming. e.g. minRange=10, maxRange=100 no less than 10 * values and no more that 100 values can be viewed at once without * scrolling @@ -838,10 +838,10 @@ public void setVisibleXRange(float minXRange, float maxXRange) { } /** - * Sets the size of the area (range on the y-axis) that should be maximum + * Sets the size of the area (range on the yPx-axis) that should be maximum * visible at once. * - * @param maxYRange the maximum visible range on the y-axis + * @param maxYRange the maximum visible range on the yPx-axis * @param axis - the axis for which this limit should apply */ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { @@ -850,7 +850,7 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { } /** - * Moves the left side of the current viewport to the specified x-index. + * Moves the left side of the current viewport to the specified xPx-index. * This also refreshes the chart by calling invalidate(). * * @param xIndex @@ -864,11 +864,11 @@ public void moveViewToX(float xIndex) { } /** - * Centers the viewport to the specified y-value on the y-axis. + * Centers the viewport to the specified yPx-yValue on the yPx-axis. * This also refreshes the chart by calling invalidate(). * * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the yPx-axis */ public void moveViewToY(float yValue, AxisDependency axis) { @@ -882,13 +882,13 @@ public void moveViewToY(float yValue, AxisDependency axis) { /** * This will move the left side of the current viewport to the specified - * x-value on the x-axis, and center the viewport to the specified y-value - * on the y-axis. + * xPx-yValue on the xPx-axis, and center the viewport to the specified yPx-yValue + * on the yPx-axis. * This also refreshes the chart by calling invalidate(). * * @param xIndex * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the yPx-axis */ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { @@ -901,8 +901,8 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { } /** - * This will move the left side of the current viewport to the specified x-position - * and center the viewport to the specified y-position animated. + * This will move the left side of the current viewport to the specified xPx-position + * and center the viewport to the specified yPx-position animated. * This also refreshes the chart by calling invalidate(). * * @param xIndex @@ -930,12 +930,12 @@ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, /** * This will move the center of the current viewport to the specified - * x-value and y-value. + * xPx-yValue and yPx-yValue. * This also refreshes the chart by calling invalidate(). * * @param xIndex * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the yPx-axis */ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { @@ -951,7 +951,7 @@ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { /** * This will move the center of the current viewport to the specified - * x-value and y-value animated. + * xPx-yValue and yPx-yValue animated. * * @param xIndex * @param yValue @@ -1026,7 +1026,7 @@ public void resetViewPortOffsets() { /** CODE BELOW IS GETTERS AND SETTERS */ /** - * Returns the delta-y value (y-value range) of the specified axis. + * Returns the delta-yPx yValue (yPx-yValue range) of the specified axis. * * @param axis * @return @@ -1116,7 +1116,7 @@ public void setHighlightFullBarEnabled(boolean enabled) { } /** - * @return true the highlight is be full-bar oriented, false if single-value + * @return true the highlight is be full-bar oriented, false if single-yValue */ public boolean isHighlightFullBarEnabled() { return mHighlightFullBarEnabled; @@ -1208,7 +1208,7 @@ public void setDrawGridBackground(boolean enabled) { /** * Sets drawing the borders rectangle to true. If this is enabled, there is - * no point drawing the axis-lines of x- and y-axis. + * no point drawing the axis-lines of xPx- and yPx-axis. * * @param enabled */ @@ -1263,8 +1263,8 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { } /** - * Returns the Highlight object (contains x-index and DataSet index) of the - * selected value at the given touch point inside the Line-, Scatter-, or + * Returns the Highlight object (contains xPx-index and DataSet index) of the + * selected yValue at the given touch point inside the Line-, Scatter-, or * CandleStick-Chart. * * @param x @@ -1281,7 +1281,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { } /** - * Returns the x and y values in the chart at the given touch point + * Returns the xPx and yPx values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). @@ -1291,18 +1291,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { * @return */ public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - pts[1] = y; - - getTransformer(axis).pixelsToValue(pts); - - double xTouchVal = pts[0]; - double yTouchVal = pts[1]; - - return new PointD(xTouchVal, yTouchVal); + return getTransformer(axis).getValuesByTouchPoint(x, y); } /** @@ -1314,19 +1303,12 @@ public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { * @return */ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { - - float[] pts = new float[]{ - x, y - }; - - getTransformer(axis).pointValuesToPixel(pts); - - return new PointD(pts[0], pts[1]); + return getTransformer(axis).getPixelsForValues(x, y); } /** - * returns the y-value at the given touch position (must not necessarily be - * a value contained in one of the datasets) + * returns the yPx-yValue at the given touch position (must not necessarily be + * a yValue contained in one of the datasets) * * @param x * @param y @@ -1367,7 +1349,7 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float } /** - * Returns the lowest x-index (value on the x-axis) that is still visible on + * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on * the chart. * * @return @@ -1380,7 +1362,7 @@ public float getLowestVisibleX() { } /** - * Returns the highest x-index (value on the x-axis) that is still visible + * Returns the highest xPx-index (yValue on the xPx-axis) that is still visible * on the chart. * * @return @@ -1393,7 +1375,7 @@ public float getHighestVisibleX() { } /** - * returns the current x-scale factor + * returns the current xPx-scale factor */ public float getScaleX() { if (mViewPortHandler == null) @@ -1403,7 +1385,7 @@ public float getScaleX() { } /** - * returns the current y-scale factor + * returns the current yPx-scale factor */ public float getScaleY() { if (mViewPortHandler == null) @@ -1422,7 +1404,7 @@ public boolean isFullyZoomedOut() { } /** - * Returns the left y-axis object. In the horizontal bar-chart, this is the + * Returns the left yPx-axis object. In the horizontal bar-chart, this is the * top axis. * * @return @@ -1432,7 +1414,7 @@ public YAxis getAxisLeft() { } /** - * Returns the right y-axis object. In the horizontal bar-chart, this is the + * Returns the right yPx-axis object. In the horizontal bar-chart, this is the * bottom axis. * * @return @@ -1442,7 +1424,7 @@ public YAxis getAxisRight() { } /** - * Returns the y-axis object to the corresponding AxisDependency. In the + * Returns the yPx-axis object to the corresponding AxisDependency. In the * horizontal bar-chart, LEFT == top, RIGHT == BOTTOM * * @param axis @@ -1461,8 +1443,8 @@ public boolean isInverted(AxisDependency axis) { } /** - * If set to true, both x and y axis can be scaled simultaneously with 2 fingers, if false, - * x and y axis can be scaled separately. default: false + * If set to true, both xPx and yPx axis can be scaled simultaneously with 2 fingers, if false, + * xPx and yPx axis can be scaled separately. default: false * * @param enabled */ @@ -1481,7 +1463,7 @@ public boolean isPinchZoomEnabled() { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the x-axis. + * bounds on the xPx-axis. * * @param offset */ @@ -1491,7 +1473,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the y-axis. + * bounds on the yPx-axis. * * @param offset */ @@ -1500,7 +1482,7 @@ public void setDragOffsetY(float offset) { } /** - * Returns true if both drag offsets (x and y) are zero or smaller. + * Returns true if both drag offsets (xPx and yPx) are zero or smaller. * * @return */ @@ -1571,11 +1553,11 @@ public boolean isAnyAxisInverted() { } /** - * Flag that indicates if auto scaling on the y axis is enabled. This is + * Flag that indicates if auto scaling on the yPx axis is enabled. This is * especially interesting for charts displaying financial data. * - * @param enabled the y axis automatically adjusts to the min and max y - * values of the current x axis range whenever the viewport + * @param enabled the yPx axis automatically adjusts to the min and max yPx + * values of the current xPx axis range whenever the viewport * changes */ public void setAutoScaleMinMaxEnabled(boolean enabled) { @@ -1583,7 +1565,7 @@ public void setAutoScaleMinMaxEnabled(boolean enabled) { } /** - * @return true if auto scaling on the y axis is enabled. + * @return true if auto scaling on the yPx axis is enabled. * @default false */ public boolean isAutoScaleMinMaxEnabled() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index e492d74e5b..ae7075b725 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -91,13 +91,13 @@ public abstract class Chart implements Lin /** * if set to true, a grey area is drawn behind each bar that indicates the - * maximum value + * maximum yValue */ private boolean mDrawBarShadow = false; @@ -194,7 +194,7 @@ public void setDrawValueAboveBar(boolean enabled) { /** * If set to true, a grey area is drawn behind each bar that indicates the - * maximum value. Enabling his will reduce performance by about 50%. + * maximum yValue. Enabling his will reduce performance by about 50%. * * @param enabled */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index f78419ce50..b183e28c69 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -22,7 +22,7 @@ import com.github.mikephil.charting.utils.Utils; /** - * BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched, meaning the YAxis class + * BarChart with horizontal bar orientation. In this implementation, xPx- and yPx-axis are switched, meaning the YAxis class * represents the horizontal values and the XAxis class represents the vertical values. * * @author Philipp Jahoda @@ -70,7 +70,7 @@ public void calculateOffsets() { offsetRight += mOffsetsBuffer.right; offsetBottom += mOffsetsBuffer.bottom; - // offsets for y-labels + // offsets for yPx-labels if (mAxisLeft.needsOffset()) { offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels()); } @@ -83,7 +83,7 @@ public void calculateOffsets() { if (mXAxis.isEnabled()) { - // offsets for x-labels + // offsets for xPx-labels if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { offsetLeft += xlabelwidth; @@ -184,7 +184,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { } /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point + * Returns the Highlight object (contains xPx-index and DataSet index) of the selected yValue at the given touch point * inside the BarChart. * * @param x @@ -195,10 +195,11 @@ public PointF getPosition(Entry e, AxisDependency axis) { public Highlight getHighlightByTouchPoint(float x, float y) { if (mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); + if(mLogEnabled) + Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } else - return getHighlighter().getHighlight(y, x); // switch x and y + return getHighlighter().getHighlight(y, x); // switch xPx and yPx } @Override @@ -216,7 +217,7 @@ public float getHighestVisibleX() { } // /** -// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. +// * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on the chart. // * // * @return // */ @@ -233,7 +234,7 @@ public float getHighestVisibleX() { // } // // /** -// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. +// * Returns the highest xPx-index (yValue on the xPx-axis) that is still visible on the chart. // * // * @return // */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index ba8e37c8ea..eee3026cac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -34,7 +34,7 @@ public class PieChart extends PieRadarChartBase { private RectF mCircleBox = new RectF(); /** - * flag indicating if the x-labels should be drawn or not + * flag indicating if the xPx-labels should be drawn or not */ private boolean mDrawXLabels = true; @@ -256,7 +256,7 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { } /** - * calculates the needed angle for a given value + * calculates the needed angle for a given yValue * * @param value * @return @@ -266,7 +266,7 @@ private float calcAngle(float value) { } /** - * calculates the needed angle for a given value + * calculates the needed angle for a given yValue * * @param value * @param yValueSum @@ -302,7 +302,7 @@ public int getIndexForAngle(float angle) { } /** - * Returns the index of the DataSet this x-index belongs to. + * Returns the index of the DataSet this xPx-index belongs to. * * @param xIndex * @return @@ -550,7 +550,7 @@ public float getTransparentCircleRadius() { /** * Sets the amount of transparency the transparent circle should have 0 = fully transparent, * 255 = fully opaque. - * Default value is 100. + * Default yValue is 100. * * @param alpha 0-255 */ @@ -559,7 +559,7 @@ public void setTransparentCircleAlpha(int alpha) { } /** - * set this to true to draw the x-value text into the pie slices + * set this to true to draw the xPx-yValue text into the pie slices * * @param enabled */ @@ -568,7 +568,7 @@ public void setDrawSliceText(boolean enabled) { } /** - * returns true if drawing x-values is enabled, false if not + * returns true if drawing xPx-values is enabled, false if not * * @return */ @@ -588,7 +588,7 @@ public boolean isDrawRoundedSlicesEnabled() { /** * If this is enabled, values inside the PieChart are drawn in percent and - * not with their original value. Values provided for the ValueFormatter to + * not with their original yValue. Values provided for the ValueFormatter to * format are then provided in percent. * * @param enabled diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 2c55c24125..fc00d890be 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -343,7 +343,7 @@ public void setRotationAngle(float angle) { /** * gets the raw version of the current rotation angle of the pie chart the - * returned value could be any value, negative or positive, outside of the + * returned yValue could be any yValue, negative or positive, outside of the * 360 degrees. this is used when working with rotation direction, mainly by * gestures and animations. * @@ -441,8 +441,8 @@ public float getYChartMin() { } /** - * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail - * objects give information about the value at the selected index and the + * Returns an array of SelectionDetail objects for the given xPx-index. The SelectionDetail + * objects give information about the yValue at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * @@ -456,12 +456,12 @@ public List getSelectionDetailsAtIndex(int xIndex) { IDataSet dataSet = mData.getDataSetByIndex(i); - // extract all y-values from all DataSets at the given x-index + // extract all yPx-values from all DataSets at the given xPx-index final float yVal = dataSet.getYValueForXValue(xIndex); if (Float.isNaN(yVal)) continue; - vals.add(new SelectionDetail(yVal, i, dataSet)); + vals.add(new SelectionDetail(0f, yVal, i, dataSet)); } return vals; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index e80066d6b6..400fb85711 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -62,7 +62,7 @@ public class RadarChart extends PieRadarChartBase { private int mSkipWebLineCount = 0; /** - * the object reprsenting the y-axis labels + * the object reprsenting the yPx-axis labels */ private YAxis mYAxis; @@ -100,7 +100,7 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - // calculate / set x-axis range + // calculate / set xPx-axis range mXAxis.mAxisMaximum = mData.getXVals().size() - 1; mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); @@ -210,7 +210,7 @@ public int getIndexForAngle(float angle) { } /** - * Returns the object that represents all y-labels of the RadarChart. + * Returns the object that represents all yPx-labels of the RadarChart. * * @return */ @@ -246,7 +246,7 @@ public float getWebLineWidthInner() { } /** - * Sets the transparency (alpha) value for all web lines, default: 150, 255 + * Sets the transparency (alpha) yValue for all web lines, default: 150, 255 * = 100% opaque, 0 = 100% transparent * * @param alpha @@ -256,7 +256,7 @@ public void setWebAlpha(int alpha) { } /** - * Returns the alpha value for all web lines. + * Returns the alpha yValue for all web lines. * * @return */ @@ -343,21 +343,21 @@ public float getRadius() { } /** - * Returns the maximum value this chart can display on it's y-axis. + * Returns the maximum yValue this chart can display on it's yPx-axis. */ public float getYChartMax() { return mYAxis.mAxisMaximum; } /** - * Returns the minimum value this chart can display on it's y-axis. + * Returns the minimum yValue this chart can display on it's yPx-axis. */ public float getYChartMin() { return mYAxis.mAxisMinimum; } /** - * Returns the range of y-values this chart can display. + * Returns the range of yPx-values this chart can display. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index f078ed00c7..4e3b3cc2a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -76,12 +76,12 @@ public abstract class AxisBase extends ComponentBase { protected boolean mDrawLimitLineBehindData = false; /** - * flag indicating that the axis-min value has been customized + * flag indicating that the axis-min yValue has been customized */ protected boolean mCustomAxisMin = false; /** - * flag indicating that the axis-max value has been customized + * flag indicating that the axis-max yValue has been customized */ protected boolean mCustomAxisMax = false; @@ -242,10 +242,10 @@ public boolean isDrawLabelsEnabled() { } /** - * Sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware + * Sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware * that this number is not fixed. * - * @param count the number of y-axis labels that sould be displayed + * @param count the number of yPx-axis labels that sould be displayed */ public void setLabelCount(int count) { @@ -258,7 +258,7 @@ public void setLabelCount(int count) { } /** - * Returns the number of label entries the y-axis should have + * Returns the number of label entries the yPx-axis should have * * @return */ @@ -381,7 +381,7 @@ public float getAxisMinimum() { } /** - * By calling this method, any custom maximum value that has been previously set is reseted, + * By calling this method, any custom maximum yValue that has been previously set is reseted, * and the calculation is * done automatically. */ @@ -390,7 +390,7 @@ public void resetAxisMaxValue() { } /** - * Returns true if the axis max value has been customized (and is not calculated automatically) + * Returns true if the axis max yValue has been customized (and is not calculated automatically) * * @return */ @@ -399,7 +399,7 @@ public boolean isAxisMaxCustom() { } /** - * By calling this method, any custom minimum value that has been previously set is reseted, + * By calling this method, any custom minimum yValue that has been previously set is reseted, * and the calculation is * done automatically. */ @@ -408,7 +408,7 @@ public void resetAxisMinValue() { } /** - * Returns true if the axis min value has been customized (and is not calculated automatically) + * Returns true if the axis min yValue has been customized (and is not calculated automatically) * * @return */ @@ -417,11 +417,11 @@ public boolean isAxisMinCustom() { } /** - * Set a custom minimum value for this axis. If set, this value will not be calculated + * Set a custom minimum yValue for this axis. If set, this yValue will not be calculated * automatically depending on * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call * setStartAtZero(false) if you use - * this method. Otherwise, the axis-minimum value will still be forced to 0. + * this method. Otherwise, the axis-minimum yValue will still be forced to 0. * * @param min */ @@ -431,7 +431,7 @@ public void setAxisMinValue(float min) { } /** - * Set a custom maximum value for this axis. If set, this value will not be calculated + * Set a custom maximum yValue for this axis. If set, this yValue will not be calculated * automatically depending on * the provided data. Use resetAxisMaxValue() to undo this. * @@ -446,12 +446,12 @@ public void setAxisMaxValue(float max) { * Calculates the minimum / maximum and range values of the axis with the given * minimum and maximum values from the chart data. * - * @param dataMin the min value according to chart data - * @param dataMax the max value according to chart data + * @param dataMin the min yValue according to chart data + * @param dataMax the max yValue according to chart data */ public void calculate(float dataMin, float dataMax) { - // if custom, use value as is, else use data value + // if custom, use yValue as is, else use data yValue float min = mCustomAxisMin ? mAxisMinimum : dataMin; float max = mCustomAxisMax ? mAxisMaximum : dataMax; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java index 713f89dd79..77bbe97ca7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java @@ -19,7 +19,7 @@ public abstract class ComponentBase { protected boolean mEnabled = true; /** - * the offset in pixels this axis labels have on the x-axis + * the offset in pixels this axis labels have on the xPx-axis */ protected float mXOffset = 5f; @@ -48,7 +48,7 @@ public ComponentBase() { } /** - * Returns the used offset on the x-axis for drawing the axis or legend + * Returns the used offset on the xPx-axis for drawing the axis or legend * labels. This offset is applied before and after the label. * * @return @@ -58,7 +58,7 @@ public float getXOffset() { } /** - * Sets the used x-axis offset for the labels on this axis. + * Sets the used xPx-axis offset for the labels on this axis. * * @param xOffset */ @@ -67,7 +67,7 @@ public void setXOffset(float xOffset) { } /** - * Returns the used offset on the x-axis for drawing the axis labels. This + * Returns the used offset on the xPx-axis for drawing the axis labels. This * offset is applied before and after the label. * * @return @@ -77,7 +77,7 @@ public float getYOffset() { } /** - * Sets the used y-axis offset for the labels on this axis. For the legend, + * Sets the used yPx-axis offset for the labels on this axis. For the legend, * higher offset means the legend as a whole will be placed further away * from the top. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 77f1710f27..0514d91f32 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -76,7 +76,7 @@ public enum LegendDirection { private String[] mExtraLabels; /** - * Are the legend labels/colors a custom value or auto calculated? If false, + * Are the legend labels/colors a custom yValue or auto calculated? If false, * then it's auto, if true, then custom. default false (automatic legend) */ private boolean mIsLegendCustom = false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java index 8fcdee8fc1..7b826fae30 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java @@ -11,13 +11,13 @@ /** * The limit line is an additional feature for all Line-, Bar- and * ScatterCharts. It allows the displaying of an additional line in the chart - * that marks a certain maximum / limit on the specified axis (x- or y-axis). + * that marks a certain maximum / limit on the specified axis (xPx- or yPx-axis). * * @author Philipp Jahoda */ public class LimitLine extends ComponentBase { - /** limit / maximum (the y-value or xIndex) */ + /** limit / maximum (the yPx-yValue or xIndex) */ private float mLimit = 0f; /** the width of the limit line */ @@ -46,7 +46,7 @@ public enum LimitLabelPosition { /** * Constructor with limit. * - * @param limit - the position (the value) on the y-axis (y-value) or x-axis + * @param limit - the position (the yValue) on the yPx-axis (yPx-yValue) or xPx-axis * (xIndex) where this line should appear */ public LimitLine(float limit) { @@ -56,7 +56,7 @@ public LimitLine(float limit) { /** * Constructor with limit and label. * - * @param limit - the position (the value) on the y-axis (y-value) or x-axis + * @param limit - the position (the yValue) on the yPx-axis (yPx-yValue) or xPx-axis * (xIndex) where this line should appear * @param label - provide "" if no label is required */ @@ -157,7 +157,7 @@ public DashPathEffect getDashPathEffect() { } /** - * Sets the color of the value-text that is drawn next to the LimitLine. + * Sets the color of the yValue-text that is drawn next to the LimitLine. * Default: Paint.Style.FILL_AND_STROKE * * @param style @@ -167,7 +167,7 @@ public void setTextStyle(Paint.Style style) { } /** - * Returns the color of the value-text that is drawn next to the LimitLine. + * Returns the color of the yValue-text that is drawn next to the LimitLine. * * @return */ @@ -176,7 +176,7 @@ public Paint.Style getTextStyle() { } /** - * Sets the position of the LimitLine value label (either on the right or on + * Sets the position of the LimitLine yValue label (either on the right or on * the left edge of the chart). Not supported for RadarChart. * * @param pos @@ -186,7 +186,7 @@ public void setLabelPosition(LimitLabelPosition pos) { } /** - * Returns the position of the LimitLine label (value). + * Returns the position of the LimitLine label (yValue). * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java index 523376c786..ca99c59b09 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java @@ -68,25 +68,25 @@ public void draw(Canvas canvas, float posx, float posy) { * * @param e The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or * CandleEntry, simply cast it at runtime. - * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the + * @param highlight the highlight object contains information about the highlighted yValue such as it's dataset-index, the * selected range or stack-index (only stacked bar entries). */ public abstract void refreshContent(Entry e, Highlight highlight); /** - * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / + * Use this to return the desired offset you wish the MarkerView to have on the xPx-axis. By returning -(getWidth() / * 2) you will center the MarkerView horizontally. * - * @param xpos the position on the x-axis in pixels where the marker is drawn + * @param xpos the position on the xPx-axis in pixels where the marker is drawn * @return */ public abstract int getXOffset(float xpos); /** - * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning - * -getHeight() you will cause the MarkerView to be above the selected value. + * Use this to return the desired position offset you wish the MarkerView to have on the yPx-axis. By returning + * -getHeight() you will cause the MarkerView to be above the selected yValue. * - * @param ypos the position on the y-axis in pixels where the marker is drawn + * @param ypos the position on the yPx-axis in pixels where the marker is drawn * @return */ public abstract int getYOffset(float ypos); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index d49605c3b8..3617cb69aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -10,7 +10,7 @@ import java.util.List; /** - * Class representing the x-axis labels settings. Only use the setter methods to + * Class representing the xPx-axis labels settings. Only use the setter methods to * modify it. Do not access public variables directly. Be aware that not all * features the XLabels class provides are suitable for the RadarChart. * @@ -18,29 +18,29 @@ */ public class XAxis extends AxisBase { - /** the arraylist containing all the x-axis labels */ + /** the arraylist containing all the xPx-axis labels */ protected List mValues = new ArrayList(); /** - * width of the x-axis labels in pixels - this is automatically + * width of the xPx-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelWidth = 1; /** - * height of the x-axis labels in pixels - this is automatically + * height of the xPx-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelHeight = 1; /** - * width of the (rotated) x-axis labels in pixels - this is automatically + * width of the (rotated) xPx-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedWidth = 1; /** - * height of the (rotated) x-axis labels in pixels - this is automatically + * height of the (rotated) xPx-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedHeight = 1; @@ -51,20 +51,20 @@ public class XAxis extends AxisBase { protected float mLabelRotationAngle = 0f; /** - * the space that should be left out (in characters) between the x-axis + * the space that should be left out (in characters) between the xPx-axis * labels */ private int mSpaceBetweenLabels = 4; /** - * the modulus that indicates if a value at a specified index in an - * array(list) for the x-axis-labels is drawn or not. If index % modulus == + * the modulus that indicates if a yValue at a specified index in an + * array(list) for the xPx-axis-labels is drawn or not. If index % modulus == * 0 DRAW, else dont draw. */ public int mAxisLabelModulus = 1; /** - * Is axisLabelModulus a custom value or auto calculated? If false, then + * Is axisLabelModulus a custom yValue or auto calculated? If false, then * it's auto, if true, then custom. default: false (automatic modulus) */ private boolean mIsAxisModulusCustom = false; @@ -75,14 +75,14 @@ public class XAxis extends AxisBase { private boolean mAvoidFirstLastClipping = false; /** - * Custom formatter for adjusting x-value strings + * Custom formatter for adjusting xPx-yValue strings */ protected XAxisValueFormatter mXAxisValueFormatter = new DefaultXAxisValueFormatter(); - /** the position of the x-labels relative to the chart */ + /** the position of the xPx-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; - /** enum for the position of the x-labels relative to the chart */ + /** enum for the position of the xPx-labels relative to the chart */ public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } @@ -94,14 +94,14 @@ public XAxis() { } /** - * returns the position of the x-labels + * returns the position of the xPx-labels */ public XAxisPosition getPosition() { return mPosition; } /** - * sets the position of the x-labels + * sets the position of the xPx-labels * * @param pos */ @@ -126,7 +126,7 @@ public void setLabelRotationAngle(float angle) { } /** - * Sets the space (in characters) that should be left out between the x-axis + * Sets the space (in characters) that should be left out between the xPx-axis * labels, default 4. This only applies if the number of labels that will be * skipped in between drawn axis labels is not custom set. * @@ -156,7 +156,7 @@ public void setLabelsToSkip(int count) { /** * Calling this will disable a custom number of labels to be skipped (set by - * setLabelsToSkip(...)) while drawing the x-axis. Instead, the number of + * setLabelsToSkip(...)) while drawing the xPx-axis. Instead, the number of * values to skip will again be calculated automatically. */ public void resetLabelsToSkip() { @@ -175,7 +175,7 @@ public boolean isAxisModulusCustom() { /** * Returns the space (in characters) that should be left out between the - * x-axis labels + * xPx-axis labels */ public int getSpaceBetweenLabels() { return mSpaceBetweenLabels; @@ -219,7 +219,7 @@ public List getValues() { } /** - * Adds a new x-value to the chart data. + * Adds a new xPx-yValue to the chart data. * * @param xVal */ @@ -228,7 +228,7 @@ public void addXValue(XAxisValue xVal) { } /** - * Removes the x-value at the specified index. + * Removes the xPx-yValue at the specified index. * * @param index */ @@ -239,7 +239,7 @@ public void removeXValue(int index) { /** * Sets a custom XAxisValueFormatter for the data object that allows custom-formatting - * of all x-values before rendering them. Provide null to reset back to the + * of all xPx-values before rendering them. Provide null to reset back to the * default formatting. * * @param formatter diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 82c4c10e6d..347d89ce96 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -9,11 +9,11 @@ import com.github.mikephil.charting.utils.Utils; /** - * Class representing the y-axis labels settings and its entries. Only use the setter methods to + * Class representing the yPx-axis labels settings and its entries. Only use the setter methods to * modify it. Do not * access public variables directly. Be aware that not all features the YLabels class provides * are suitable for the - * RadarChart. Customizations that affect the value range of the axis need to be applied before + * RadarChart. Customizations that affect the yValue range of the axis need to be applied before * setting data for the * chart. * @@ -27,12 +27,12 @@ public class YAxis extends AxisBase { protected YAxisValueFormatter mYAxisValueFormatter; /** - * indicates if the top y-label entry is drawn or not + * indicates if the top yPx-label entry is drawn or not */ private boolean mDrawTopYLabelEntry = true; /** - * if true, the y-labels show only the minimum and maximum value + * if true, the yPx-labels show only the minimum and maximum yValue */ protected boolean mShowOnlyMinMax = false; @@ -42,7 +42,7 @@ public class YAxis extends AxisBase { protected boolean mInverted = false; /** - * if true, the set number of y-labels will be forced + * if true, the set number of yPx-labels will be forced */ protected boolean mForceLabels = false; @@ -62,22 +62,22 @@ public class YAxis extends AxisBase { protected float mZeroLineWidth = 1f; /** - * axis space from the largest value to the top in percent of the total axis range + * axis space from the largest yValue to the top in percent of the total axis range */ protected float mSpacePercentTop = 10f; /** - * axis space from the smallest value to the bottom in percent of the total axis range + * axis space from the smallest yValue to the bottom in percent of the total axis range */ protected float mSpacePercentBottom = 10f; /** - * the position of the y-labels relative to the chart + * the position of the yPx-labels relative to the chart */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; /** - * enum for the position of the y-labels relative to the chart + * enum for the position of the yPx-labels relative to the chart */ public enum YAxisLabelPosition { OUTSIDE_CHART, INSIDE_CHART @@ -105,7 +105,7 @@ public enum YAxisLabelPosition { /** * When true, axis labels are controlled by the `granularity` property. * When false, axis values could possibly be repeated. - * This could happen if two adjacent axis values are rounded to same value. + * This could happen if two adjacent axis values are rounded to same yValue. * If using granularity this could be avoided by having fewer axis values visible. */ protected boolean mGranularityEnabled = false; @@ -182,7 +182,7 @@ public boolean isGranularityEnabled() { } /** - * Enabled/disable granularity control on axis value intervals. If enabled, the axis + * Enabled/disable granularity control on axis yValue intervals. If enabled, the axis * interval is not allowed to go below a certain granularity. Default: false * * @param enabled @@ -211,14 +211,14 @@ public void setGranularity(float granularity) { } /** - * returns the position of the y-labels + * returns the position of the yPx-labels */ public YAxisLabelPosition getLabelPosition() { return mPosition; } /** - * sets the position of the y-labels + * sets the position of the yPx-labels * * @param pos */ @@ -227,7 +227,7 @@ public void setPosition(YAxisLabelPosition pos) { } /** - * returns true if drawing the top y-axis label entry is enabled + * returns true if drawing the top yPx-axis label entry is enabled * * @return */ @@ -236,9 +236,9 @@ public boolean isDrawTopYLabelEntryEnabled() { } /** - * set this to true to enable drawing the top y-label entry. Disabling this can be helpful - * when the top y-label and - * left x-label interfere with each other. default: true + * set this to true to enable drawing the top yPx-label entry. Disabling this can be helpful + * when the top yPx-label and + * left xPx-label interfere with each other. default: true * * @param enabled */ @@ -247,11 +247,11 @@ public void setDrawTopYLabelEntry(boolean enabled) { } /** - * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware + * sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware * that this number is not * fixed (if force == false) and can only be approximated. * - * @param count the number of y-axis labels that sould be displayed + * @param count the number of yPx-axis labels that sould be displayed * @param force if enabled, the set label count will be forced, meaning that the exact * specified count of labels will * be drawn and evenly distributed alongside the axis - this might cause labels @@ -264,7 +264,7 @@ public void setLabelCount(int count, boolean force) { } /** - * Returns true if focing the y-label count is enabled. Default: false + * Returns true if focing the yPx-label count is enabled. Default: false * * @return */ @@ -273,7 +273,7 @@ public boolean isForceLabelsEnabled() { } /** - * If enabled, the YLabels will only show the minimum and maximum value of the chart. This + * If enabled, the YLabels will only show the minimum and maximum yValue of the chart. This * will ignore/override the * set label count. * @@ -284,7 +284,7 @@ public void setShowOnlyMinMax(boolean enabled) { } /** - * Returns true if showing only min and max value is enabled. + * Returns true if showing only min and max yValue is enabled. * * @return */ @@ -293,7 +293,7 @@ public boolean isShowOnlyMinMaxEnabled() { } /** - * If this is set to true, the y-axis is inverted which means that low values are on top of + * If this is set to true, the yPx-axis is inverted which means that low values are on top of * the chart, high values * on bottom. * @@ -304,7 +304,7 @@ public void setInverted(boolean enabled) { } /** - * If this returns true, the y-axis is inverted. + * If this returns true, the yPx-axis is inverted. * * @return */ @@ -459,7 +459,7 @@ public String getLongestLabel() { } /** - * Returns the formatted y-label at the specified index. This will either use the + * Returns the formatted yPx-label at the specified index. This will either use the * auto-formatter or the custom * formatter (if one is set). * @@ -535,7 +535,7 @@ public boolean needsOffset() { @Override public void calculate(float dataMin, float dataMax) { - // if custom, use value as is, else use data value + // if custom, use yValue as is, else use data yValue float min = mCustomAxisMin ? mAxisMinimum : dataMin; float max = mCustomAxisMax ? mAxisMaximum : dataMax; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 152b596e91..cacf466a80 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -16,7 +16,7 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl private float mBarSpace = 0.15f; /** - * the maximum number of bars that are stacked upon each other, this value + * the maximum number of bars that are stacked upon each other, this yValue * is calculated from the Entries that are added to the DataSet */ private int mStackSize = 1; @@ -31,12 +31,12 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl private int mBarBorderColor = Color.BLACK; /** - * the alpha value used to draw the highlight indicator bar + * the alpha yValue used to draw the highlight indicator bar */ private int mHighLightAlpha = 120; /** - * the overall entry count, including counting each stack-value individually + * the overall entry count, including counting each stack-yValue individually */ private int mEntryCountStacks = 0; @@ -176,7 +176,7 @@ public boolean isStacked() { } /** - * returns the overall entry count, including counting each stack-value + * returns the overall entry count, including counting each stack-yValue * individually * * @return @@ -186,7 +186,7 @@ public int getEntryCountStacks() { } /** - * returns the space between bars in percent of the whole width of one value + * returns the space between bars in percent of the whole width of one yValue * * @return */ @@ -210,7 +210,7 @@ public void setBarSpacePercent(float percent) { /** * Sets the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum value. Don't for get to + * surface behind the bar that indicates the maximum yValue. Don't for get to * use getResources().getColor(...) to set this. Or Color.rgb(...). * * @param color @@ -265,7 +265,7 @@ public int getBarBorderColor() { } /** - * Set the alpha value (transparency) that is used for drawing the highlight + * Set the alpha yValue (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index 97358ae378..62b2a8a940 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -84,7 +84,7 @@ public BarEntry copy() { } /** - * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use + * Returns the stacked values this BarEntry represents, or null, if only a single yValue is represented (then, use * getY()). * * @return @@ -105,7 +105,7 @@ public void setVals(float[] vals) { } /** - * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. + * Returns the yValue of this BarEntry. If the entry is stacked, it returns the positive sum of all values. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index e218dec225..1cdddda683 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -42,7 +42,7 @@ public abstract class BaseDataSet implements IDataSet { protected YAxis.AxisDependency mAxisDependency = YAxis.AxisDependency.LEFT; /** - * if true, value highlightning is enabled + * if true, yValue highlightning is enabled */ protected boolean mHighlightEnabled = true; @@ -52,17 +52,17 @@ public abstract class BaseDataSet implements IDataSet { protected transient ValueFormatter mValueFormatter; /** - * the typeface used for the value text + * the typeface used for the yValue text */ protected Typeface mValueTypeface; /** - * if true, y-values are drawn on the chart + * if true, yPx-values are drawn on the chart */ protected boolean mDrawValues = true; /** - * the size of the value-text labels + * the size of the yValue-text labels */ protected float mValueTextSize = 17f; @@ -196,7 +196,7 @@ public void setColor(int color) { } /** - * Sets a color with a specific alpha value. + * Sets a color with a specific alpha yValue. * * @param color * @param alpha from 0-255 @@ -206,7 +206,7 @@ public void setColor(int color, int alpha) { } /** - * Sets colors with a specific alpha value. + * Sets colors with a specific alpha yValue. * * @param colors * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java index c6ff908b85..0778e57673 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java @@ -4,7 +4,7 @@ import android.annotation.SuppressLint; /** - * Subclass of Entry that holds a value for one entry in a BubbleChart. Bubble + * Subclass of Entry that holds a yValue for one entry in a BubbleChart. Bubble * chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed under * Apache License 2.0 * @@ -13,14 +13,14 @@ @SuppressLint("ParcelCreator") public class BubbleEntry extends Entry { - /** size value */ + /** size yValue */ private float mSize = 0f; /** * Constructor. * - * @param x The value on the x-axis. - * @param y The value on the y-axis. + * @param x The yValue on the xPx-axis. + * @param y The yValue on the yPx-axis. * @param size The size of the bubble. */ public BubbleEntry(float x, float y, float size) { @@ -31,8 +31,8 @@ public BubbleEntry(float x, float y, float size) { /** * Constructor. * - * @param x The value on the x-axis. - * @param y The value on the y-axis. + * @param x The yValue on the xPx-axis. + * @param y The yValue on the yPx-axis. * @param size The size of the bubble. * @param data Spot for additional data this Entry represents. */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java index efe87d077a..b499540a64 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java @@ -11,26 +11,26 @@ @SuppressLint("ParcelCreator") public class CandleEntry extends Entry { - /** shadow-high value */ + /** shadow-high yValue */ private float mShadowHigh = 0f; - /** shadow-low value */ + /** shadow-low yValue */ private float mShadowLow = 0f; - /** close value */ + /** close yValue */ private float mClose = 0f; - /** open value */ + /** open yValue */ private float mOpen = 0f; /** * Constructor. * - * @param x The value on the x-axis. - * @param shadowH The (shadow) high value. - * @param shadowL The (shadow) low value. - * @param open The open value. - * @param close The close value. + * @param x The yValue on the xPx-axis. + * @param shadowH The (shadow) high yValue. + * @param shadowL The (shadow) low yValue. + * @param open The open yValue. + * @param close The close yValue. */ public CandleEntry(float x, float shadowH, float shadowL, float open, float close) { super(x, (shadowH + shadowL) / 2f); @@ -44,9 +44,9 @@ public CandleEntry(float x, float shadowH, float shadowL, float open, float clos /** * Constructor. * - * @param x The value on the x-axis. - * @param shadowH The (shadow) high value. - * @param shadowL The (shadow) low value. + * @param x The yValue on the xPx-axis. + * @param shadowH The (shadow) high yValue. + * @param shadowL The (shadow) low yValue. * @param open * @param close * @param data Spot for additional data this Entry represents. @@ -81,7 +81,7 @@ public float getBodyRange() { } /** - * Returns the center value of the candle. (Middle value between high and + * Returns the center yValue of the candle. (Middle yValue between high and * low) */ @Override @@ -98,7 +98,7 @@ public CandleEntry copy() { } /** - * Returns the upper shadows highest value. + * Returns the upper shadows highest yValue. * * @return */ @@ -111,7 +111,7 @@ public void setHigh(float mShadowHigh) { } /** - * Returns the lower shadows lowest value. + * Returns the lower shadows lowest yValue. * * @return */ @@ -124,7 +124,7 @@ public void setLow(float mShadowLow) { } /** - * Returns the bodys close value. + * Returns the bodys close yValue. * * @return */ @@ -137,7 +137,7 @@ public void setClose(float mClose) { } /** - * Returns the bodys open value. + * Returns the bodys open yValue. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 70605b3a8a..dd4fcee6bf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -15,29 +15,29 @@ /** * Class that holds all relevant data that represents the chart. That involves - * at least one (or more) DataSets, and an array of x-values. + * at least one (or more) DataSets, and an array of xPx-values. * * @author Philipp Jahoda */ public abstract class ChartData> { /** - * maximum y-value in the value array across all axes + * maximum yPx-yValue in the yValue array across all axes */ protected float mYMax = 0.0f; /** - * the minimum y-value in the value array across all axes + * the minimum yPx-yValue in the yValue array across all axes */ protected float mYMin = 0.0f; /** - * maximum x-value in the value array + * maximum xPx-yValue in the yValue array */ protected float mXMax = 0f; /** - * minimum x-value in the value array + * minimum xPx-yValue in the yValue array */ protected float mXMin = 0f; @@ -50,18 +50,18 @@ public abstract class ChartData> { protected float mRightAxisMin = 0.0f; /** - * total number of y-values across all DataSet objects + * total number of yPx-values across all DataSet objects */ private int mYValCount = 0; /** - * contains the maximum length (in characters) an entry in the x-vals array + * contains the maximum length (in characters) an entry in the xPx-vals array * has */ private float mXValMaximumLength = 0; /** - * holds all x-values the chart represents + * holds all xPx-values the chart represents */ protected List mXVals; @@ -81,7 +81,7 @@ public ChartData(T... dataSets) { } /** - * Constructor for only x-values. This constructor can be used for setting + * Constructor for only xPx-values. This constructor can be used for setting * up an empty chart without data. * * @param xVals @@ -93,7 +93,7 @@ public ChartData(List xVals) { } /** - * Constructor for only x-values. This constructor can be used for setting + * Constructor for only xPx-values. This constructor can be used for setting * up an empty chart without data. * * @param xVals @@ -107,7 +107,7 @@ public ChartData(XAxisValue[] xVals) { /** * constructor for chart data * - * @param xVals The values describing the x-axis. Must be at least as long + * @param xVals The values describing the xPx-axis. Must be at least as long * as the highest xIndex in the Entry objects across all * DataSets. * @param sets the dataset array @@ -122,7 +122,7 @@ public ChartData(List xVals, List sets) { /** * constructor that takes string array instead of List string * - * @param xVals The values describing the x-axis. Must be at least as long + * @param xVals The values describing the xPx-axis. Must be at least as long * as the highest xIndex in the Entry objects across all * DataSets. * @param sets the dataset array @@ -146,7 +146,7 @@ private List arrayToList(XAxisValue[] array) { /** * performs all kinds of initialization calculations, such as min-max and - * value count and sum + * yValue count and sum */ protected void init() { @@ -158,7 +158,7 @@ protected void init() { } /** - * calculates the average length (in characters) across all x-value strings + * calculates the average length (in characters) across all xPx-yValue strings */ private void calcXValMaximumLength() { @@ -181,7 +181,7 @@ private void calcXValMaximumLength() { } /** - * Checks if the combination of x-values array and DataSet array is legal or + * Checks if the combination of xPx-values array and DataSet array is legal or * not. */ private void checkLegal() { @@ -195,7 +195,7 @@ private void checkLegal() { for (int i = 0; i < mDataSets.size(); i++) { if (mDataSets.get(i).getEntryCount() > mXVals.size()) { // throw new IllegalArgumentException( -// "One or more of the DataSet Entry arrays are longer than the x-values array of this ChartData object."); +// "One or more of the DataSet Entry arrays are longer than the xPx-values array of this ChartData object."); } } } @@ -210,7 +210,7 @@ public void notifyDataChanged() { } /** - * calc minimum and maximum values (both x and y) over all DataSets + * calc minimum and maximum values (both xPx and yPx) over all DataSets */ public void calcMinMax() { @@ -297,7 +297,7 @@ public void calcMinMax() { } /** - * Calculates the total number of y-values across all DataSets the ChartData + * Calculates the total number of yPx-values across all DataSets the ChartData * represents. * * @return @@ -332,7 +332,7 @@ public int getDataSetCount() { } /** - * Returns the smallest y-value the data object contains. + * Returns the smallest yPx-yValue the data object contains. * * @return */ @@ -341,7 +341,7 @@ public float getYMin() { } /** - * Returns the minimum y-value for the specified axis. + * Returns the minimum yPx-yValue for the specified axis. * * @param axis * @return @@ -354,7 +354,7 @@ public float getYMin(AxisDependency axis) { } /** - * Returns the greatest y-value the data object contains. + * Returns the greatest yPx-yValue the data object contains. * * @return */ @@ -363,7 +363,7 @@ public float getYMax() { } /** - * Returns the maximum y-value for the specified axis. + * Returns the maximum yPx-yValue for the specified axis. * * @param axis * @return @@ -376,7 +376,7 @@ public float getYMax(AxisDependency axis) { } /** - * Returns the minimum x-value this data object contains. + * Returns the minimum xPx-yValue this data object contains. * * @return */ @@ -385,7 +385,7 @@ public float getXMin() { } /** - * Returns the maximum x-value this data object contains. + * Returns the maximum xPx-yValue this data object contains. * * @return */ @@ -395,7 +395,7 @@ public float getXMax() { /** * returns the maximum length (in characters) across all values in the - * x-vals array + * xPx-vals array * * @return */ @@ -404,7 +404,7 @@ public float getXValMaximumLength() { } /** - * Returns the total number of y-values across all DataSet objects the this + * Returns the total number of yPx-values across all DataSet objects the this * object represents. * * @return @@ -414,7 +414,7 @@ public int getYValCount() { } /** - * returns the x-values the chart represents + * returns the xPx-values the chart represents * * @return */ @@ -423,7 +423,7 @@ public List getXVals() { } /** - * sets the x-values the chart represents + * sets the xPx-values the chart represents * */ public void setXVals(List xVals) { @@ -431,7 +431,7 @@ public void setXVals(List xVals) { } /** - * Adds a new x-value to the chart data. + * Adds a new xPx-yValue to the chart data. * * @param xVal */ @@ -444,7 +444,7 @@ public void addXValue(XAxisValue xVal) { } /** - * Removes the x-value at the specified index. + * Removes the xPx-yValue at the specified index. * * @param index */ @@ -484,8 +484,8 @@ protected int getDataSetIndexByLabel(List dataSets, String label, } /** - * returns the total number of x-values this ChartData object represents - * (the size of the x-values array) + * returns the total number of xPx-values this ChartData object represents + * (the size of the xPx-values array) * * @return */ @@ -519,19 +519,26 @@ public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= mDataSets.size()) return null; else { - // The value of the highlighted entry could be NaN - - // if we are not interested in highlighting a specific value. - - List entries = mDataSets.get(highlight.getDataSetIndex()) - .getEntriesForXPos(highlight.getX()); - for (Object entry : entries) - if (((Entry)entry).getY() == highlight.getY() || - Float.isNaN(highlight.getY())) - return (Entry)entry; - - return null; + return mDataSets.get(highlight.getDataSetIndex()).getEntryForXPos(highlight.getX()); } } +// public Entry getEntryForHighlight(Highlight highlight) { +// if (highlight.getDataSetIndex() >= mDataSets.size()) +// return null; +// else { +// // The yValue of the highlighted entry could be NaN - +// // if we are not interested in highlighting a specific yValue. +// +// List entries = mDataSets.get(highlight.getDataSetIndex()) +// .getEntriesForXPos(highlight.getX()); +// for (Object entry : entries) +// if (((Entry)entry).getY() == highlight.getY() || +// Float.isNaN(highlight.getY())) +// return (Entry)entry; +// +// return null; +// } +// } /** * Returns the DataSet object with the given label. Search can be case @@ -880,7 +887,7 @@ public T getFirstRight() { } /** - * Generates an x-values array filled with numbers in range specified by the + * Generates an xPx-values array filled with numbers in range specified by the * parameters. Can be used for convenience. * * @return @@ -912,7 +919,7 @@ public void setValueFormatter(ValueFormatter f) { } /** - * Sets the color of the value-text (color in which the value-labels are + * Sets the color of the yValue-text (color in which the yValue-labels are * drawn) for all DataSets this data object contains. * * @param color @@ -924,7 +931,7 @@ public void setValueTextColor(int color) { } /** - * Sets the same list of value-colors for all DataSets this + * Sets the same list of yValue-colors for all DataSets this * data object contains. * * @param colors @@ -936,7 +943,7 @@ public void setValueTextColors(List colors) { } /** - * Sets the Typeface for all value-labels for all DataSets this data object + * Sets the Typeface for all yValue-labels for all DataSets this data object * contains. * * @param tf @@ -948,7 +955,7 @@ public void setValueTypeface(Typeface tf) { } /** - * Sets the size (in dp) of the value-text for all DataSets this data object + * Sets the size (in dp) of the yValue-text for all DataSets this data object * contains. * * @param size @@ -960,7 +967,7 @@ public void setValueTextSize(float size) { } /** - * Enables / disables drawing values (value-text) for all DataSets this data + * Enables / disables drawing values (yValue-text) for all DataSets this data * object contains. * * @param enabled diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 845499b7db..c6341f77e8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -139,8 +139,8 @@ public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= data.getDataSetCount()) return null; else { - // The value of the highlighted entry could be NaN - - // if we are not interested in highlighting a specific value. + // The yValue of the highlighted entry could be NaN - + // if we are not interested in highlighting a specific yValue. List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) .getEntriesForXPos(highlight.getX()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index f260339ca7..8c2eeb2346 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -20,22 +20,22 @@ public abstract class DataSet extends BaseDataSet { protected List mValues = null; /** - * maximum y-value in the value array + * maximum yPx-yValue in the yValue array */ protected float mYMax = 0.0f; /** - * minimum y-value in the value array + * minimum yPx-yValue in the yValue array */ protected float mYMin = 0.0f; /** - * maximum x-value in the value array + * maximum xPx-yValue in the yValue array */ protected float mXMax = 0.0f; /** - * minimum x-value in the value array + * minimum xPx-yValue in the yValue array */ protected float mXMin = 0.0f; @@ -108,7 +108,7 @@ public int getEntryCount() { } /** - * Returns the array of y-values that this DataSet represents. + * Returns the array of yPx-values that this DataSet represents. * * @return */ @@ -117,7 +117,7 @@ public List getYVals() { } /** - * Sets the array of y-values that this DataSet represents, and calls notifyDataSetChanged() + * Sets the array of yPx-values that this DataSet represents, and calls notifyDataSetChanged() * * @return */ @@ -396,7 +396,7 @@ public List getEntriesForXPos(float xVal) { /** * Determines how to round DataSet index values for * {@link DataSet#getEntryIndex(float, Rounding)} DataSet.getEntryIndex()} - * when an exact x-index is not found. + * when an exact xPx-index is not found. */ public enum Rounding { UP, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 12a98ac6ff..33f1c6d246 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -7,16 +7,16 @@ /** * Class representing one entry in the chart. Might contain multiple values. - * Might only contain a single value depending on the used constructor. + * Might only contain a single yValue depending on the used constructor. * * @author Philipp Jahoda */ public class Entry implements Parcelable { - /** the y value */ + /** the yPx yValue */ private float y = 0f; - /** the x value */ + /** the xPx yValue */ private float x = 0f; /** optional spot for additional data this Entry represents */ @@ -25,8 +25,8 @@ public class Entry implements Parcelable { /** * A Entry represents one single entry in the chart. * - * @param x the x value - * @param y the y value (the actual value of the entry) + * @param x the xPx yValue + * @param y the yPx yValue (the actual yValue of the entry) */ public Entry(float x, float y) { this.y = y; @@ -36,8 +36,8 @@ public Entry(float x, float y) { /** * A Entry represents one single entry in the chart. * - * @param x the x value - * @param y the y value (the actual value of the entry) + * @param x the xPx yValue + * @param y the yPx yValue (the actual yValue of the entry) * @param data Spot for additional data this Entry represents. */ public Entry(float x, float y, Object data) { @@ -46,7 +46,7 @@ public Entry(float x, float y, Object data) { } /** - * Returns the x-value of this Entry object. + * Returns the xPx-yValue of this Entry object. * * @return */ @@ -55,7 +55,7 @@ public float getX() { } /** - * Sets the x-value of this Entry object. + * Sets the xPx-yValue of this Entry object. * * @param x */ @@ -64,7 +64,7 @@ public void setX(float x) { } /** - * Returns the y value of this Entry. + * Returns the yPx yValue of this Entry. * * @return */ @@ -73,7 +73,7 @@ public float getY() { } /** - * Sets the y-value for the Entry. + * Sets the yPx-yValue for the Entry. * * @param y */ @@ -111,7 +111,7 @@ public Entry copy() { } /** - * Compares value, xIndex and data of the entries. Returns true if entries + * Compares yValue, xIndex and data of the entries. Returns true if entries * are equal in those points, false if not. Does not check by hash-code like * it's done by the "equals" method. * @@ -136,7 +136,7 @@ public boolean equalTo(Entry e) { } /** - * returns a string representation of the entry containing x-index and value + * returns a string representation of the entry containing xPx-index and yValue */ @Override public String toString() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 78b92da3a8..64937fba99 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -25,10 +25,10 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** the color of the inner circles */ private int mCircleColorHole = Color.WHITE; - /** the radius of the circle-shaped value indicators */ + /** the radius of the circle-shaped yValue indicators */ private float mCircleRadius = 8f; - /** the hole radius of the circle-shaped value indicators */ + /** the hole radius of the circle-shaped yValue indicators */ private float mCircleHoleRadius = 4f; /** sets the intensity of the cubic lines */ @@ -155,7 +155,7 @@ public float getCircleHoleRadius() { } /** - * sets the size (radius) of the circle shpaed value indicators, + * sets the size (radius) of the circle shpaed yValue indicators, * default size = 4f * * This method is deprecated because of unclarity. Use setCircleRadius instead. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index deced96ee9..14dc008243 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -84,7 +84,7 @@ public int getFillAlpha() { } /** - * sets the alpha value (transparency) that is used for filling the line + * sets the alpha yValue (transparency) that is used for filling the line * surface (0-255), default: 85 * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index 2af374e5da..4df8aee73f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -8,7 +8,7 @@ /** * A PieData object can only represent one DataSet. Unlike all other charts, the - * legend labels of the PieChart are created from the x-values array, and not + * legend labels of the PieChart are created from the xPx-values array, and not * from the DataSet labels. Each PieData object can only represent one * PieDataSet (multiple PieDataSets inside a single PieChart are not possible). * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java index eef5f638e5..cc0fde6e6f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java @@ -6,19 +6,19 @@ public class XAxisValue { /** - * the label that describes this value + * the label that describes this yValue */ private String mLabel = ""; /** - * the position of this value on the x-axis + * the position of this yValue on the xPx-axis */ private double mPosition; /** * Constructor only with label. This is relevant for pie and radarchart. * - * @param label the x-axis label of this value + * @param label the xPx-axis label of this yValue */ public XAxisValue(String label) { this.mLabel = label; @@ -27,8 +27,8 @@ public XAxisValue(String label) { /** * Constructor. * - * @param xPosition the position of this value on the x-axis - * @param label the x-axis label of this value + * @param xPosition the position of this yValue on the xPx-axis + * @param label the xPx-axis label of this yValue */ public XAxisValue(double xPosition, String label) { this.mLabel = label; @@ -36,7 +36,7 @@ public XAxisValue(double xPosition, String label) { } /** - * Sets both x-position and label. + * Sets both xPx-position and label. * * @param xPosition * @param label @@ -47,7 +47,7 @@ public void set(double xPosition, String label) { } /** - * Returns the position (x) of the value on the x-axis. + * Returns the position (xPx) of the yValue on the xPx-axis. * * @return */ @@ -56,7 +56,7 @@ public double getPosition() { } /** - * Returns the x-axis label of this value. + * Returns the xPx-axis label of this yValue. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java index cbc630c562..4fac3f615d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java @@ -81,7 +81,7 @@ public void setType(ApproximatorType type) { } /** - * Sets the ratios for x- and y-axis, as well as the ratio of the scale + * Sets the ratios for xPx- and yPx-axis, as well as the ratio of the scale * levels * * @param deltaRatio @@ -163,7 +163,7 @@ private List reduceWithDouglasPeuker(List entries, double epsilon) * epsilon (tolerance) * * @param entries - * @param epsilon as y-value + * @param epsilon as yPx-yValue * @param start * @param end */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 238546f83c..168903dbac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -28,32 +28,32 @@ public abstract class RealmBaseDataSet e protected List mValues; /** - * maximum y-value in the y-value array + * maximum yPx-yValue in the yPx-yValue array */ protected float mYMax = 0.0f; /** - * the minimum y-value in the y-value array + * the minimum yPx-yValue in the yPx-yValue array */ protected float mYMin = 0.0f; /** - * maximum x-value in the value array + * maximum xPx-yValue in the yValue array */ protected float mXMax = 0.0f; /** - * minimum x-value in the value array + * minimum xPx-yValue in the yValue array */ protected float mXMin = 0.0f; /** - * fieldname of the column that contains the y-values of this dataset + * fieldname of the column that contains the yPx-values of this dataset */ protected String mYValuesField; /** - * fieldname of the column that contains the x-values of this dataset + * fieldname of the column that contains the xPx-values of this dataset */ protected String mXValuesField; @@ -385,7 +385,7 @@ public RealmResults getResults() { } /** - * Returns the fieldname that represents the "y-values" in the realm-data. + * Returns the fieldname that represents the "yPx-values" in the realm-data. * * @return */ @@ -394,7 +394,7 @@ public String getYValuesField() { } /** - * Sets the field name that is used for getting the y-values out of the RealmResultSet. + * Sets the field name that is used for getting the yPx-values out of the RealmResultSet. * * @param yValuesField */ @@ -403,7 +403,7 @@ public void setYValuesField(String yValuesField) { } /** - * Returns the fieldname that represents the "x-values" in the realm-data. + * Returns the fieldname that represents the "xPx-values" in the realm-data. * * @return */ @@ -412,7 +412,7 @@ public String getXValuesField() { } /** - * Sets the field name that is used for getting the x-values out of the RealmResultSet. + * Sets the field name that is used for getting the xPx-values out of the RealmResultSet. * * @param xValuesField */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index 31010f2489..73e95f80c2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -82,7 +82,7 @@ public int getFillAlpha() { } /** - * sets the alpha value (transparency) that is used for filling the line + * sets the alpha yValue (transparency) that is used for filling the line * surface (0-255), default: 85 * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index a11ebcdc99..9e964b1eb6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -26,7 +26,7 @@ public class RealmBarDataSet extends RealmBarLineScatterC private float mBarSpace = 0.15f; /** - * the maximum number of bars that are stacked upon each other, this value + * the maximum number of bars that are stacked upon each other, this yValue * is calculated from the Entries that are added to the DataSet */ private int mStackSize = 1; @@ -41,7 +41,7 @@ public class RealmBarDataSet extends RealmBarLineScatterC private int mBarBorderColor = Color.BLACK; /** - * the alpha value used to draw the highlight indicator bar + * the alpha yValue used to draw the highlight indicator bar */ private int mHighLightAlpha = 120; @@ -185,7 +185,7 @@ public boolean isStacked() { } /** - * returns the space between bars in percent of the whole width of one value + * returns the space between bars in percent of the whole width of one yValue * * @return */ @@ -209,7 +209,7 @@ public void setBarSpacePercent(float percent) { /** * Sets the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum value. Don't for get to + * surface behind the bar that indicates the maximum yValue. Don't for get to * use getResources().getColor(...) to set this. Or Color.rgb(...). * * @param color @@ -264,7 +264,7 @@ public int getBarBorderColor() { } /** - * Set the alpha value (transparency) that is used for drawing the highlight + * Set the alpha yValue (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 196be07224..8c6e1d71c6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -25,7 +25,7 @@ public class RealmBubbleDataSet extends RealmBarLineScatt * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value + * @param yValuesField the name of the field in your data object that represents the yPx-yValue * @param sizeField the name of the field in your data object that represents the bubble size */ public RealmBubbleDataSet(RealmResults result, String yValuesField, String sizeField) { @@ -40,8 +40,8 @@ public RealmBubbleDataSet(RealmResults result, String yValuesField, String si * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index * @param sizeField the name of the field in your data object that represents the bubble size */ public RealmBubbleDataSet(RealmResults result, String yValuesField, String xIndexField, String sizeField) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 9f0d43bfaf..53279e5008 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -82,10 +82,10 @@ public class RealmCandleDataSet extends RealmLineScatterC * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param highField the name of the field in your data object that represents the "high" value - * @param lowField the name of the field in your data object that represents the "low" value - * @param openField the name of the field in your data object that represents the "open" value - * @param closeField the name of the field in your data object that represents the "close" value + * @param highField the name of the field in your data object that represents the "high" yValue + * @param lowField the name of the field in your data object that represents the "low" yValue + * @param openField the name of the field in your data object that represents the "open" yValue + * @param closeField the name of the field in your data object that represents the "close" yValue */ public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField) { super(result, null); @@ -102,11 +102,11 @@ public RealmCandleDataSet(RealmResults result, String highField, String lowFi * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param highField the name of the field in your data object that represents the "high" value - * @param lowField the name of the field in your data object that represents the "low" value - * @param openField the name of the field in your data object that represents the "open" value - * @param closeField the name of the field in your data object that represents the "close" value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param highField the name of the field in your data object that represents the "high" yValue + * @param lowField the name of the field in your data object that represents the "low" yValue + * @param openField the name of the field in your data object that represents the "open" yValue + * @param closeField the name of the field in your data object that represents the "close" yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index */ public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField, String xIndexField) { super(result, null, xIndexField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index 4bca14d960..d5ac1405c7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -37,11 +37,11 @@ public class RealmLineDataSet extends RealmLineRadarDataS private int mCircleColorHole = Color.WHITE; /** - * the radius of the circle-shaped value indicators + * the radius of the circle-shaped yValue indicators */ private float mCircleRadius = 8f; - /** the hole radius of the circle-shaped value indicators */ + /** the hole radius of the circle-shaped yValue indicators */ private float mCircleHoleRadius = 4f; /** @@ -70,7 +70,7 @@ public class RealmLineDataSet extends RealmLineRadarDataS * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value + * @param yValuesField the name of the field in your data object that represents the yPx-yValue */ public RealmLineDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); @@ -87,8 +87,8 @@ public RealmLineDataSet(RealmResults result, String yValuesField) { * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index */ public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); @@ -142,7 +142,7 @@ public float getCubicIntensity() { } /** - * sets the size (radius) of the circle shpaed value indicators, default + * sets the size (radius) of the circle shpaed yValue indicators, default * size = 4f * * @param size diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 55f0903119..bb6d275e8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -38,7 +38,7 @@ public class RealmPieDataSet extends RealmBaseDataSet result, String yValuesField) { super(result, yValuesField); @@ -51,8 +51,8 @@ public RealmPieDataSet(RealmResults result, String yValuesField) { * Constructor for creating a PieDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index */ public RealmPieDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 7688fec9f7..77b0b19da8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -32,7 +32,7 @@ public class RealmRadarDataSet extends RealmLineRadarData * Constructor for creating a RadarDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value + * @param yValuesField the name of the field in your data object that represents the yPx-yValue */ public RealmRadarDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); @@ -45,8 +45,8 @@ public RealmRadarDataSet(RealmResults result, String yValuesField) { * Constructor for creating a RadarDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index */ public RealmRadarDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index c532a3a186..18075feccc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -44,7 +44,7 @@ public class RealmScatterDataSet extends RealmLineScatter * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value + * @param yValuesField the name of the field in your data object that represents the yPx-yValue */ public RealmScatterDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); @@ -57,8 +57,8 @@ public RealmScatterDataSet(RealmResults result, String yValuesField) { * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index + * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param xIndexField the name of the field in your data object that represents the xPx-index */ public RealmScatterDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index bd66f51d08..fe92d5f4bb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -8,7 +8,7 @@ /** * Default formatter used for formatting values inside the chart. Uses a DecimalFormat with - * pre-calculated number of digits (depending on max and min value). + * pre-calculated number of digits (depending on max and min yValue). * * @author Philipp Jahoda */ @@ -18,7 +18,7 @@ public class DefaultValueFormatter implements ValueFormatter { private DecimalFormat mFormat; /** - * Constructor that specifies to how many digits the value should be + * Constructor that specifies to how many digits the yValue should be * formatted. * * @param digits diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java index 383e195322..16277c72ed 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java @@ -4,8 +4,8 @@ /** * Created by Philipp Jahoda on 14/09/15. - * Default formatter class for adjusting x-values before drawing them. - * This simply returns the original value unmodified. + * Default formatter class for adjusting xPx-values before drawing them. + * This simply returns the original yValue unmodified. */ public class DefaultXAxisValueFormatter implements XAxisValueFormatter { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java index 5b8cd01452..33fff63545 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java @@ -7,7 +7,7 @@ /** * Created by Philipp Jahoda on 20/09/15. * Default formatter used for formatting labels of the YAxis. Uses a DecimalFormat with - * pre-calculated number of digits (depending on max and min value). + * pre-calculated number of digits (depending on max and min yValue). */ public class DefaultYAxisValueFormatter implements YAxisValueFormatter { @@ -15,7 +15,7 @@ public class DefaultYAxisValueFormatter implements YAxisValueFormatter { private DecimalFormat mFormat; /** - * Constructor that specifies to how many digits the value should be + * Constructor that specifies to how many digits the yValue should be * formatted. * * @param digits diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java index 66895d77e7..22ba60528e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java @@ -12,7 +12,7 @@ public interface FillFormatter { /** - * Returns the vertical (y-axis) position where the filled-line of the + * Returns the vertical (yPx-axis) position where the filled-line of the * LineDataSet should end. * * @param dataSet the ILineDataSet that is currently drawn diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 96b4ead74f..d5fc954fdc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -8,7 +8,7 @@ import java.text.DecimalFormat; /** - * Predefined value-formatter that formats large numbers in a pretty way. + * Predefined yValue-formatter that formats large numbers in a pretty way. * Outputs: 856 = 856; 1000 = 1k; 5821 = 5.8k; 10500 = 10k; 101800 = 102k; * 2000000 = 2m; 7800000 = 7.8m; 92150000 = 92m; 123200000 = 123m; 9999999 = * 10m; 1000000000 = 1b; Special thanks to Roman Gromov @@ -53,7 +53,7 @@ public String getFormattedValue(float value, YAxis yAxis) { } /** - * Set an appendix text to be added at the end of the formatted value. + * Set an appendix text to be added at the end of the formatted yValue. * * @param appendix */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 6e3535d8b5..93fbe1fa25 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -9,7 +9,7 @@ /** * This ValueFormatter is just for convenience and simply puts a "%" sign after - * each value. (Recommeded for PieChart) + * each yValue. (Recommeded for PieChart) * * @author Philipp Jahoda */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index b13dd8d907..4c5dce6b50 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -10,7 +10,7 @@ * Created by Philipp Jahoda on 28/01/16. *

    * A formatter specifically for stacked BarChart that allows to specify whether the all stack values - * or just the top value should be drawn. + * or just the top yValue should be drawn. */ public class StackedValueFormatter implements ValueFormatter { @@ -20,7 +20,7 @@ public class StackedValueFormatter implements ValueFormatter { private boolean mDrawWholeStack; /** - * a string that should be appended behind the value + * a string that should be appended behind the yValue */ private String mAppendix; @@ -30,7 +30,7 @@ public class StackedValueFormatter implements ValueFormatter { * Constructor. * * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top - * @param appendix a string that should be appended behind the value + * @param appendix a string that should be appended behind the yValue * @param decimals the number of decimal digits to use */ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { @@ -68,7 +68,7 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View } } - // return the "proposed" value + // return the "proposed" yValue return mFormat.format(value) + mAppendix; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java index 1f056bf786..12e5ac6a72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java @@ -14,12 +14,12 @@ public interface ValueFormatter { /** - * Called when a value (from labels inside the chart) is formatted + * Called when a yValue (from labels inside the chart) is formatted * before being drawn. For performance reasons, avoid excessive calculations * and memory allocations inside this method. * - * @param value the value to be formatted - * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry + * @param value the yValue to be formatted + * @param entry the entry the yValue belongs to - in e.g. BarChart, this is of class BarEntry * @param dataSetIndex the index of the DataSet the entry in focus belongs to * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return the formatted label ready for being drawn diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java index 1dcb72b04b..d7fa386112 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java @@ -4,19 +4,19 @@ /** * Created by Philipp Jahoda on 14/09/15. - * An interface for providing custom x-axis Strings. + * An interface for providing custom xPx-axis Strings. * * @author Philipp Jahoda */ public interface XAxisValueFormatter { /** - * Returns the customized label that is drawn on the x-axis. + * Returns the customized label that is drawn on the xPx-axis. * For performance reasons, avoid excessive calculations * and memory allocations inside this method. * - * @param original the original x-axis label to be drawn - * @param index the x-index that is currently being drawn + * @param original the original xPx-axis label to be drawn + * @param index the xPx-index that is currently being drawn * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java index 4bc6c3e987..eacd3ab33a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java @@ -10,12 +10,12 @@ public interface YAxisValueFormatter { /** - * Called when a value from the YAxis is formatted + * Called when a yValue from the YAxis is formatted * before being drawn. For performance reasons, avoid excessive calculations * and memory allocations inside this method. * - * @param value the YAxis value to be formatted - * @param yAxis the YAxis object the value belongs to + * @param value the YAxis yValue to be formatted + * @param yAxis the YAxis object the yValue belongs to * @return */ String getFormattedValue(float value, YAxis yAxis); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 9ca0e66a05..0a5b4e6f94 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -43,7 +43,7 @@ public Highlight getHighlight(float x, float y) { float[] pts = new float[2]; pts[1] = y; - // take any transformer to determine the x-axis value + // take any transformer to determine the xPx-axis yValue mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); return getStackedHighlight(selectionDetail, @@ -54,7 +54,7 @@ public Highlight getHighlight(float x, float y) { return new Highlight( xVal, - selectionDetail.value, + selectionDetail.yValue, selectionDetail.dataIndex, selectionDetail.dataSetIndex, -1); @@ -99,14 +99,14 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int d if (yValue == Double.NaN) return null; - return new SelectionDetail( + return new SelectionDetail(0f, yValue, dataSetIndex, dataSet); } /** - * This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected. + * This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been selected. * * @param selectionDetail the selection detail to work with looking for stacked values * @param set @@ -149,7 +149,7 @@ protected Highlight getStackedHighlight( } /** - * Returns the index of the closest value inside the values array / ranges (stacked barchart) to the value given as + * Returns the index of the closest yValue inside the values array / ranges (stacked barchart) to the yValue given as * a parameter. * * @param ranges @@ -182,7 +182,7 @@ protected int getClosestStackIndex(Range[] ranges, float value) { // int index = 0; // float remainder = e.getNegativeSum(); // - // while (index < vals.length - 1 && value > vals[index] + remainder) { + // while (index < vals.length - 1 && yValue > vals[index] + remainder) { // remainder += vals[index]; // index++; // } @@ -191,7 +191,7 @@ protected int getClosestStackIndex(Range[] ranges, float value) { } /** - * Returns the base x-value to the corresponding x-touch value in pixels. + * Returns the base xPx-yValue to the corresponding xPx-touch yValue in pixels. * * @param x * @return @@ -202,7 +202,7 @@ protected float getBase(float x) { float[] pts = new float[2]; pts[0] = x; - // take any transformer to determine the x-axis value + // take any transformer to determine the xPx-axis yValue mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); float xVal = pts[0]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index a2e0f19deb..4fc57febdb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -4,9 +4,11 @@ import java.util.List; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; @@ -25,7 +27,7 @@ public ChartHighlighter(T chart) { } /** - * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. + * Returns a Highlight object corresponding to the given xPx- and yPx- touch positions in pixels. * * @param x * @param y @@ -39,32 +41,27 @@ public Highlight getHighlight(float x, float y) { if (selectionDetail == null) return null; - return new Highlight(xVal, - selectionDetail.value, + return new Highlight(selectionDetail.xValue, + selectionDetail.yValue, selectionDetail.dataIndex, selectionDetail.dataSetIndex); } /** - * Returns the corresponding x-index for a given touch-position in pixels. + * Returns the corresponding xPos for a given touch-position in pixels. * * @param x * @return */ protected float getXForTouch(float x) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - - return Math.round(pts[0]); + // take any transformer to determine the xPx-axis yValue + PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, 0f); + return (float) pos.x; } /** - * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. + * Returns the corresponding SelectionDetail for a given xVal and yPx-touch position in pixels. * * @param xVal * @param y @@ -98,8 +95,6 @@ protected List getSelectionDetailsAtIndex(float xVal, int dataS if (mChart.getData() == null) return vals; - float[] pts = new float[2]; - for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); i < dataSetCount; i++) { if (dataSetIndex > -1 && dataSetIndex != i) @@ -111,19 +106,19 @@ protected List getSelectionDetailsAtIndex(float xVal, int dataS if (!dataSet.isHighlightEnabled()) continue; - // extract all y-values from all DataSets at the given x-index - final Entry e = dataSet.getEntryForXPos(xVal); + vals.add(getDetails(dataSet, i, xVal, DataSet.Rounding.UP)); + vals.add(getDetails(dataSet, i, xVal, DataSet.Rounding.DOWN)); + } - pts[0] = e.getX(); - pts[1] = e.getY(); + return vals; + } - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + private SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[0], pts[1], e.getY(), i, dataSet)); - } - } + final Entry e = set.getEntryForXPos(xVal, rounding); - return vals; + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); + + return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index f752be4cfa..98e24859d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -45,7 +45,7 @@ protected List getSelectionDetailsAtIndex(float xVal, int dataS if (!dataSet.isHighlightEnabled()) continue; - // extract all y-values from all DataSets at the given x-index + // extract all yPx-values from all DataSets at the given xPx-index final float yVals[] = dataSet.getYValuesForXPos(xVal); for (float yVal : yVals) { pts[1] = yVal; @@ -53,7 +53,7 @@ protected List getSelectionDetailsAtIndex(float xVal, int dataS mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], yVal, i, j, dataSet)); + vals.add(new SelectionDetail(0f, pts[1], yVal, i, j, dataSet)); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 4bdd840d7c..fe52b33619 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -2,25 +2,25 @@ package com.github.mikephil.charting.highlight; /** - * Contains information needed to determine the highlighted value. + * Contains information needed to determine the highlighted yValue. * * @author Philipp Jahoda */ public class Highlight { - /** the x-value of the highlighted value */ + /** the xPx-yValue of the highlighted yValue */ private float mX = Float.NaN; - /** the y-value of the highlighted value */ + /** the yPx-yValue of the highlighted yValue */ private float mY = Float.NaN; /** the index of the data object - in case it refers to more than one */ private int mDataIndex; - /** the index of the dataset the highlighted value is in */ + /** the index of the dataset the highlighted yValue is in */ private int mDataSetIndex; - /** index which value of a stacked bar entry is highlighted, default -1 */ + /** index which yValue of a stacked bar entry is highlighted, default -1 */ private int mStackIndex = -1; /** the range of the bar that is selected (only for stacked-barchart) */ @@ -29,10 +29,10 @@ public class Highlight { /** * constructor * - * @param x the x-value of the highlighted value - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to - * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * @param x the xPx-yValue of the highlighted yValue + * @param y the yPx-yValue of the highlighted yValue + * @param dataIndex the index of the Data the highlighted yValue belongs to + * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to */ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { this.mX = x; @@ -43,11 +43,11 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { /** * Constructor, only used for stacked-barchart. * - * @param x the x-value of the highlighted value on the x-axis - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to - * @param dataSetIndex the index of the DataSet the highlighted value belongs to - * @param stackIndex references which value of a stacked-bar entry has been + * @param x the xPx-yValue of the highlighted yValue on the xPx-axis + * @param y the yPx-yValue of the highlighted yValue + * @param dataIndex the index of the Data the highlighted yValue belongs to + * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to + * @param stackIndex references which yValue of a stacked-bar entry has been * selected */ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex) { @@ -58,13 +58,13 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted value on the x-axis - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to - * @param dataSetIndex the index of the DataSet the highlighted value belongs to - * @param stackIndex references which value of a stacked-bar entry has been + * @param x the index of the highlighted yValue on the xPx-axis + * @param y the yPx-yValue of the highlighted yValue + * @param dataIndex the index of the Data the highlighted yValue belongs to + * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to + * @param stackIndex references which yValue of a stacked-bar entry has been * selected - * @param range the range the selected stack-value is in + * @param range the range the selected stack-yValue is in */ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex, Range range) { this(x, y, dataIndex, dataSetIndex, stackIndex); @@ -74,15 +74,15 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted value on the x-axis - * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * @param x the index of the highlighted yValue on the xPx-axis + * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to */ public Highlight(int x, int dataSetIndex) { this(x, Float.NaN, 0, dataSetIndex, -1); } /** - * returns the x-value of the highlighted value + * returns the xPx-yValue of the highlighted yValue * * @return */ @@ -91,7 +91,7 @@ public float getX() { } /** - * returns the y-value of the highlighted value + * returns the yPx-yValue of the highlighted yValue * * @return */ @@ -109,7 +109,7 @@ public int getDataIndex() { } /** - * returns the index of the DataSet the highlighted value is in + * returns the index of the DataSet the highlighted yValue is in * * @return */ @@ -119,7 +119,7 @@ public int getDataSetIndex() { /** * Only needed if a stacked-barchart entry was highlighted. References the - * selected value within the stacked-entry. + * selected yValue within the stacked-entry. * * @return */ @@ -128,7 +128,7 @@ public int getStackIndex() { } /** - * Returns the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart) + * Returns the range of values the selected yValue of a stacked bar is in. (this is only relevant for stacked-barchart) * @return */ public Range getRange() { @@ -157,7 +157,7 @@ public boolean equalTo(Highlight h) { @Override public String toString() { - return "Highlight, x: " + mX + "y: " + mY + ", dataSetIndex: " + mDataSetIndex + return "Highlight, xPx: " + mX + "yPx: " + mY + ", dataSetIndex: " + mDataSetIndex + ", stackIndex (only stacked barentry): " + mStackIndex; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 22a8d7356d..56865a8776 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -41,7 +41,7 @@ public Highlight getHighlight(float x, float y) { float[] pts = new float[2]; pts[0] = y; - // take any transformer to determine the x-axis value + // take any transformer to determine the xPx-axis yValue mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); return getStackedHighlight(selectionDetail, @@ -52,7 +52,7 @@ public Highlight getHighlight(float x, float y) { return new Highlight( xVal, - selectionDetail.value, + selectionDetail.yValue, selectionDetail.dataIndex, selectionDetail.dataSetIndex, -1); @@ -67,7 +67,7 @@ protected float getXForTouch(float x) { float[] pts = new float[2]; pts[1] = x; - // take any transformer to determine the x-axis value + // take any transformer to determine the xPx-axis yValue mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); return (int) Math.round(pts[1]); @@ -90,7 +90,7 @@ else if (xIndex >= valCount) } /** - * Returns the base y-value to the corresponding x-touch value in pixels. + * Returns the base yPx-yValue to the corresponding xPx-touch yValue in pixels. * * @param y * @return @@ -102,7 +102,7 @@ protected float getBase(float y) { float[] pts = new float[2]; pts[1] = y; - // take any transformer to determine the x-axis value + // take any transformer to determine the xPx-axis yValue mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); float yVal = pts[1]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java index 96dd592b8f..60391124ec 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.highlight; /** - * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one value in a stacked bar entry. e.g. + * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one yValue in a stacked bar entry. e.g. * stack values are -10, 5, 20 -> then ranges are (-10 - 0, 0 - 5, 5 - 25). */ public final class Range { @@ -15,7 +15,7 @@ public Range(float from, float to) { } /** - * Returns true if this range contains (if the value is in between) the given value, false if not. + * Returns true if this range contains (if the yValue is in between) the given yValue, false if not. * * @param value * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index a7f9544ed8..a063213380 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -15,14 +15,14 @@ public interface ChartInterface { /** - * Returns the minimum x-value of the chart, regardless of zoom or translation. + * Returns the minimum xPx-yValue of the chart, regardless of zoom or translation. * * @return */ float getXChartMin(); /** - * Returns the maximum x-value of the chart, regardless of zoom or translation. + * Returns the maximum xPx-yValue of the chart, regardless of zoom or translation. * * @return */ @@ -31,14 +31,14 @@ public interface ChartInterface { float getXRange(); /** - * Returns the minimum y-value of the chart, regardless of zoom or translation. + * Returns the minimum yPx-yValue of the chart, regardless of zoom or translation. * * @return */ float getYChartMin(); /** - * Returns the maximum y-value of the chart, regardless of zoom or translation. + * Returns the maximum yPx-yValue of the chart, regardless of zoom or translation. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index e7c2f64355..3c260245bc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -8,7 +8,7 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { /** - * Returns the space between bars as the actual value (0 - 1.0f) + * Returns the space between bars as the actual yValue (0 - 1.0f) * * @return */ @@ -31,7 +31,7 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { /** ###### ###### DATA RELATED METHODS ###### ###### */ /** - * returns the minimum y-value this DataSet holds + * returns the minimum yPx-yValue this DataSet holds * * @return */ float getYMin(); /** - * returns the maximum y-value this DataSet holds + * returns the maximum yPx-yValue this DataSet holds * * @return */ float getYMax(); /** - * returns the minimum x-value this DataSet holds + * returns the minimum xPx-yValue this DataSet holds * * @return */ float getXMin(); /** - * returns the maximum x-value this DataSet holds + * returns the maximum xPx-yValue this DataSet holds * * @return */ float getXMax(); /** - * Returns the number of y-values this DataSet represents -> the size of the y-values array + * Returns the number of yPx-values this DataSet represents -> the size of the yPx-values array * -> yvals.size() * * @return @@ -53,7 +53,7 @@ public interface IDataSet { int getEntryCount(); /** - * Calculates the minimum and maximum x and y values (mXMin, mXMax, mYMin, mYMax). + * Calculates the minimum and maximum xPx and yPx values (mXMin, mXMax, mYMin, mYMax). */ void calcMinMax(); @@ -65,7 +65,7 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xPos - * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index + * @param rounding determine to round up/down/closest if there is no Entry matching the provided xPx-index * @return */ T getEntryForXPos(float xPos, DataSet.Rounding rounding); @@ -109,7 +109,7 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xPos - * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index + * @param rounding determine to round up/down/closest if there is no Entry matching the provided xPx-index * @return */ int getEntryIndex(float xPos, DataSet.Rounding rounding); @@ -124,8 +124,8 @@ public interface IDataSet { int getEntryIndex(T e); /** - * Returns the value of the Entry object at the given xVal. Returns - * Float.NaN if no value is at the given xVal. INFORMATION: This method + * Returns the yValue of the Entry object at the given xVal. Returns + * Float.NaN if no yValue is at the given xVal. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * @@ -135,8 +135,8 @@ public interface IDataSet { float getYValueForXValue(float xVal); /** - * Returns all of the y values of the Entry objects at the given xPos. Returns - * Float.NaN if no value is at the given xPos. INFORMATION: This method + * Returns all of the yPx values of the Entry objects at the given xPos. Returns + * Float.NaN if no yValue is at the given xPos. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * @@ -160,7 +160,7 @@ public interface IDataSet { * Adds an Entry to the DataSet dynamically. * Entries are added to the end of the list. * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. + * values of the DataSet and the yValue-sum. * * @param e */ @@ -169,7 +169,7 @@ public interface IDataSet { /** * Removes an Entry from the DataSets entries array. This will also * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could + * yValue-sum. Returns true if an Entry was removed, false if no Entry could * be removed. * * @param e @@ -178,9 +178,9 @@ public interface IDataSet { /** * Adds an Entry to the DataSet dynamically. - * Entries are added to their appropriate index respective to it's x-index. + * Entries are added to their appropriate index respective to it's xPx-index. * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. + * values of the DataSet and the yValue-sum. * * @param e */ @@ -250,7 +250,7 @@ public interface IDataSet { YAxis.AxisDependency getAxisDependency(); /** - * Set the y-axis this DataSet should be plotted against (either LEFT or + * Set the yPx-axis this DataSet should be plotted against (either LEFT or * RIGHT). Default: LEFT * * @param dependency @@ -289,7 +289,7 @@ public interface IDataSet { boolean isHighlightEnabled(); /** - * If set to true, value highlighting is enabled which means that values can + * If set to true, yValue highlighting is enabled which means that values can * be highlighted programmatically or by touch gesture. * * @param enabled @@ -315,7 +315,7 @@ public interface IDataSet { ValueFormatter getValueFormatter(); /** - * Sets the color the value-labels of this DataSet should have. + * Sets the color the yValue-labels of this DataSet should have. * * @param color */ @@ -329,14 +329,14 @@ public interface IDataSet { void setValueTextColors(List colors); /** - * Sets a Typeface for the value-labels of this DataSet. + * Sets a Typeface for the yValue-labels of this DataSet. * * @param tf */ void setValueTypeface(Typeface tf); /** - * Sets the text-size of the value-labels of this DataSet in dp. + * Sets the text-size of the yValue-labels of this DataSet in dp. * * @param size */ @@ -373,7 +373,7 @@ public interface IDataSet { float getValueTextSize(); /** - * set this to true to draw y-values on the chart NOTE (for bar and + * set this to true to draw yPx-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even * if this is enabled * @@ -382,7 +382,7 @@ public interface IDataSet { void setDrawValues(boolean enabled); /** - * Returns true if y-value drawing is enabled, false if not + * Returns true if yPx-yValue drawing is enabled, false if not * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java index ce89822716..ebf7e4f565 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java @@ -24,7 +24,7 @@ public interface ILineRadarDataSet extends ILineScatterCandleRa Drawable getFillDrawable(); /** - * Returns the alpha value that is used for filling the line surface, + * Returns the alpha yValue that is used for filling the line surface, * default: 85 * * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 71168adebf..98e60ffb32 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -126,10 +126,10 @@ public boolean onTouch(View v, MotionEvent event) { saveTouchStart(event); - // get the distance between the pointers on the x-axis + // get the distance between the pointers on the xPx-axis mSavedXDist = getXDist(event); - // get the distance between the pointers on the y-axis + // get the distance between the pointers on the yPx-axis mSavedYDist = getYDist(event); // get the total distance between the pointers @@ -363,7 +363,7 @@ private void performZoom(MotionEvent event) { mLastGesture = ChartGesture.X_ZOOM; float xDist = getXDist(event); - float scaleX = xDist / mSavedXDist; // x-axis scale + float scaleX = xDist / mSavedXDist; // xPx-axis scale boolean isZoomingOut = (scaleX < 1); boolean canZoomMoreX = isZoomingOut ? @@ -384,7 +384,7 @@ private void performZoom(MotionEvent event) { mLastGesture = ChartGesture.Y_ZOOM; float yDist = getYDist(event); - float scaleY = yDist / mSavedYDist; // y-axis scale + float scaleY = yDist / mSavedYDist; // yPx-axis scale boolean isZoomingOut = (scaleY < 1); boolean canZoomMoreY = isZoomingOut ? @@ -450,7 +450,7 @@ private static float spacing(MotionEvent event) { } /** - * calculates the distance on the x-axis between two pointers (fingers on + * calculates the distance on the xPx-axis between two pointers (fingers on * the display) * * @param e @@ -462,7 +462,7 @@ private static float getXDist(MotionEvent e) { } /** - * calculates the distance on the y-axis between two pointers (fingers on + * calculates the distance on the yPx-axis between two pointers (fingers on * the display) * * @param e @@ -474,7 +474,7 @@ private static float getYDist(MotionEvent e) { } /** - * returns the correct translation depending on the provided x and y touch + * returns the correct translation depending on the provided xPx and yPx touch * points * * @param x @@ -532,7 +532,7 @@ public boolean onDoubleTap(MotionEvent e) { mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); if (mChart.isLogEnabled()) - Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + Log.i("BarlineChartTouch", "Double-Tap, Zooming In, xPx: " + trans.x + ", yPx: " + trans.y); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java index 75c8e864b4..aae6050916 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -83,7 +83,7 @@ public void endAction(MotionEvent me) { } /** - * Sets the last value that was highlighted via touch. + * Sets the last yValue that was highlighted via touch. * * @param high */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java index a17cdde941..0449e79228 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -60,8 +60,8 @@ public interface OnChartGestureListener { * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. * * @param me - * @param scaleX scalefactor on the x-axis - * @param scaleY scalefactor on the y-axis + * @param scaleX scalefactor on the xPx-axis + * @param scaleY scalefactor on the yPx-axis */ void onChartScale(MotionEvent me, float scaleX, float scaleY); @@ -69,8 +69,8 @@ public interface OnChartGestureListener { * Callbacks when the chart is moved / translated via drag gesture. * * @param me - * @param dX translation distance on the x-axis - * @param dY translation distance on the y-axis + * @param dX translation distance on the xPx-axis + * @param dY translation distance on the yPx-axis */ void onChartTranslate(MotionEvent me, float dX, float dY); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 4c6da2e8c9..e0153dada6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -12,7 +12,7 @@ public interface OnChartValueSelectedListener { /** - * Called when a value has been selected inside the chart. + * Called when a yValue has been selected inside the chart. * * @param e The selected Entry. * @param dataSetIndex The index in the datasets array of the data object diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index d40e2fdb4e..59ec3d1101 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -283,7 +283,7 @@ private float calculateVelocity() { /** * sets the starting angle of the rotation, this is only used by the touch - * listener, x and y is the touch position + * listener, xPx and yPx is the touch position * * @param x * @param y diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 48da4be2c3..6515f7b82b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -22,7 +22,7 @@ public abstract class AxisRenderer extends Renderer { /** paint object for the grid lines */ protected Paint mGridPaint; - /** paint for the x-label values */ + /** paint for the xPx-label values */ protected Paint mAxisLabelPaint; /** paint for the line surrounding the chart */ @@ -94,12 +94,12 @@ public Transformer getTransformer() { /** * Computes the axis values. * - * @param min - the minimum value in the data object for this axis - * @param max - the maximum value in the data object for this axis + * @param min - the minimum yValue in the data object for this axis + * @param max - the maximum yValue in the data object for this axis */ public void computeAxis(float min, float max, boolean inverted) { - // calculate the starting and entry point of the y-labels (depending on + // calculate the starting and entry point of the yPx-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index cfdba02418..740863325c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -133,7 +133,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; - // Set the color for the currently drawn value. If the index + // Set the color for the currently drawn yValue. If the index // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], @@ -220,7 +220,7 @@ public void drawValues(Canvas c) { boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); // calculate the correct offset depending on the draw position of - // the value + // the yValue float valueTextHeight = Utils.calcTextHeight(mValuePaint, "8"); posOffset = (drawValueAboveBar ? -valueOffsetPlus : valueTextHeight + valueOffsetPlus); negOffset = (drawValueAboveBar ? valueTextHeight + valueOffsetPlus : -valueOffsetPlus); @@ -418,9 +418,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); // // Path arrow = new Path(); -// arrow.moveTo(x + 0.4f, yArrow + offsetY); -// arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); -// arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); +// arrow.moveTo(xPx + 0.4f, yArrow + offsetY); +// arrow.lineTo(xPx + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); +// arrow.lineTo(xPx + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); // // trans.pathValueToPixel(arrow); // c.drawPath(arrow, mHighlightPaint); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index a1d9521a55..3fcaca0913 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -91,7 +91,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the x-axis + // calcualte the full width of 1 step on the xPx-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); @@ -245,7 +245,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the x-axis + // calcualte the full width of 1 step on the xPx-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs( mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index b6d567797b..04b97f31cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -327,7 +328,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { dataSetIndex++) { float x = high.getX(); // get the - // x-position + // xPx-position ICandleDataSet set = mChart.getCandleData().getDataSetByIndex(dataSetIndex); @@ -343,14 +344,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float highValue = e.getHigh() * mAnimator.getPhaseY(); float y = (lowValue + highValue) / 2f; - float[] pts = new float[]{ - x, y - }; - - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + PointD px = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); // draw the lines - drawHighlightLines(c, pts, set); + drawHighlightLines(c, (float) px.x, (float) px.y, set); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index f4a88fe08d..20a28ea9ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -67,7 +67,7 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { /** * Returns the Paint object this renderer uses for drawing the values - * (value-text). + * (yValue-text). * * @return */ @@ -95,7 +95,7 @@ public Paint getPaintRender() { } /** - * Applies the required styling (provided by the DataSet) to the value-paint + * Applies the required styling (provided by the DataSet) to the yValue-paint * object. * * @param set @@ -128,12 +128,12 @@ protected void applyValueTextStyle(IDataSet set) { public abstract void drawValues(Canvas c); /** - * Draws the value of the given entry by using the provided ValueFormatter. + * Draws the yValue of the given entry by using the provided ValueFormatter. * * @param c canvas - * @param formatter formatter for custom value-formatting - * @param value the value to be drawn - * @param entry the entry the value belongs to + * @param formatter formatter for custom yValue-formatting + * @param value the yValue to be drawn + * @param entry the entry the yValue belongs to * @param dataSetIndex the index of the DataSet the drawn Entry belongs to * @param x position * @param y position diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index b27c5ebdab..9b02178179 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -85,7 +85,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.buffer[j + 3], mShadowPaint); } - // Set the color for the currently drawn value. If the index + // Set the color for the currently drawn yValue. If the index // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], @@ -147,7 +147,7 @@ public void drawValues(Canvas c) { float val = e.getY(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the value + // calculate the correct offset depending on the draw position of the yValue float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -161,7 +161,7 @@ public void drawValues(Canvas c) { valuePoints[j + 1] + halfTextHeight, dataSet.getValueTextColor(j / 2)); } - // if each value of a potential stack should be drawn + // if each yValue of a potential stack should be drawn } else { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { @@ -187,7 +187,7 @@ public void drawValues(Canvas c) { float val = e.getY(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the value + // calculate the correct offset depending on the draw position of the yValue float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -231,7 +231,7 @@ public void drawValues(Canvas c) { float val = vals[k / 2]; String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the value + // calculate the correct offset depending on the draw position of the yValue float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1b8ab83c10..1cf0250791 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -28,7 +28,7 @@ public class LineChartRenderer extends LineRadarRenderer { protected LineDataProvider mChart; /** - * paint for the inner circle of the value indicators + * paint for the inner circle of the yValue indicators */ protected Paint mCirclePaintInner; @@ -738,28 +738,16 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - float x = high.getX(); // get the - // x-position + float x = high.getX(); + float y = high.getY() * mAnimator.getPhaseY(); if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - final float yVal = set.getYValueForXValue(x); - if (Float.isNaN(yVal)) - continue; - - float y = yVal * mAnimator.getPhaseY(); // get - // the - // y-position - - float[] pts = new float[]{ - x, y - }; - - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); // draw the lines - drawHighlightLines(c, pts, set); + drawHighlightLines(c, x, y, set); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index c262953aa3..1f19c44492 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -25,10 +25,11 @@ public LineScatterCandleRadarRenderer(ChartAnimator animator, ViewPortHandler vi * Draws vertical & horizontal highlight-lines if enabled. * * @param c - * @param pts the transformed x- and y-position of the lines + * @param x xPx-position of the highlight line intersection + * @param y yPx-position of the highlight line intersection * @param set the currently drawn dataset */ - protected void drawHighlightLines(Canvas c, float[] pts, ILineScatterCandleRadarDataSet set) { + protected void drawHighlightLines(Canvas c, float x, float y, ILineScatterCandleRadarDataSet set) { // set color and stroke-width mHighlightPaint.setColor(set.getHighLightColor()); @@ -42,8 +43,8 @@ protected void drawHighlightLines(Canvas c, float[] pts, ILineScatterCandleRadar // create vertical path mHighlightLinePath.reset(); - mHighlightLinePath.moveTo(pts[0], mViewPortHandler.contentTop()); - mHighlightLinePath.lineTo(pts[0], mViewPortHandler.contentBottom()); + mHighlightLinePath.moveTo(x, mViewPortHandler.contentTop()); + mHighlightLinePath.lineTo(x, mViewPortHandler.contentBottom()); c.drawPath(mHighlightLinePath, mHighlightPaint); } @@ -53,8 +54,8 @@ protected void drawHighlightLines(Canvas c, float[] pts, ILineScatterCandleRadar // create horizontal path mHighlightLinePath.reset(); - mHighlightLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); - mHighlightLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); + mHighlightLinePath.moveTo(mViewPortHandler.contentLeft(), y); + mHighlightLinePath.lineTo(mViewPortHandler.contentRight(), y); c.drawPath(mHighlightLinePath, mHighlightPaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 962ac88eaa..78f1a996b2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -198,7 +198,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { - // draw only if the value is greater than zero + // draw only if the yValue is greater than zero if ((Math.abs(dataSet.getEntryForIndex(j).getY()) > 0.000001)) { visibleAngleCount++; } @@ -213,7 +213,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); - // draw only if the value is greater than zero + // draw only if the yValue is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { if (!mChart.needsHighlight((int) e.getX(), @@ -711,7 +711,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final int entryCount = set.getEntryCount(); int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { - // draw only if the value is greater than zero + // draw only if the yValue is greater than zero if ((Math.abs(set.getEntryForIndex(j).getY()) > 0.000001)) { visibleAngleCount++; } @@ -896,7 +896,7 @@ protected void drawRoundedSlices(Canvas c) { Entry e = dataSet.getEntryForIndex(j); - // draw only if the value is greater than zero + // draw only if the yValue is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { float x = (float) ((r - circleRadius) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 30f3ef33ac..7e23bbd403 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -89,7 +89,7 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to + // calculate the factor that is needed for transforming the yValue to // pixels float factor = mChart.getFactor(); @@ -163,7 +163,7 @@ public void drawValues(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to + // calculate the factor that is needed for transforming the yValue to // pixels float factor = mChart.getFactor(); @@ -204,7 +204,7 @@ protected void drawWeb(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to + // calculate the factor that is needed for transforming the yValue to // pixels float factor = mChart.getFactor(); float rotationangle = mChart.getRotationAngle(); @@ -287,16 +287,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { y * factor * phaseY, sliceangle * j * phaseX + mChart.getRotationAngle()); - float[] pts = new float[]{ - p.x, p.y - }; // draw the lines - drawHighlightLines(c, pts, set); + drawHighlightLines(c, p.x, p.y, set); if (set.isDrawHighlightCircleEnabled()) { - if (!Float.isNaN(pts[0]) && !Float.isNaN(pts[1])) { + if (!Float.isNaN(p.x) && !Float.isNaN(p.y)) { int strokeColor = set.getHighlightCircleStrokeColor(); if (strokeColor == ColorTemplate.COLOR_NONE) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java index b646a527c2..f8d111d5b2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java @@ -16,10 +16,10 @@ public abstract class Renderer { */ protected ViewPortHandler mViewPortHandler; - /** the minimum value on the x-axis that should be plotted */ + /** the minimum yValue on the xPx-axis that should be plotted */ protected float mMinX = 0; - /** the maximum value on the x-axis that should be plotted */ + /** the maximum yValue on the xPx-axis that should be plotted */ protected float mMaxX = 0; public Renderer(ViewPortHandler viewPortHandler) { @@ -27,7 +27,7 @@ public Renderer(ViewPortHandler viewPortHandler) { } /** - * Returns true if the specified value fits in between the provided min + * Returns true if the specified yValue fits in between the provided min * and max bounds, false if not. * * @param val @@ -44,7 +44,7 @@ protected boolean fitsBounds(float val, float min, float max) { } /** - * Calculates the minimum and maximum x-value the chart can currently + * Calculates the minimum and maximum xPx-yValue the chart can currently * display (with the given zoom level). -> mMinX, mMaxX * * @param dataProvider diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index caf9650f3e..99cf49d1f5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Paint.Style; import android.graphics.Path; +import android.graphics.Point; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.ScatterBuffer; @@ -14,6 +15,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -397,27 +399,16 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - float x = high.getX(); // get the - // x-position - + float x = high.getX(); + float y = high.getY() * mAnimator.getPhaseY(); if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - final float yVal = set.getYValueForXValue(x); - if (Float.isNaN(yVal)) - continue; - - float y = yVal * mAnimator.getPhaseY(); - - float[] pts = new float[]{ - x, y - }; - - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); + PointD px = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); // draw the lines - drawHighlightLines(c, pts, set); + drawHighlightLines(c, (float) px.x, (float) px.y, set); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 3f28571f10..6a6fb2a045 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -36,7 +36,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t @Override public void computeAxis(float min, float max, boolean inverted) { - // calculate the starting and entry point of the y-labels (depending on + // calculate the starting and entry point of the yPx-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { @@ -186,7 +186,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the x-labels on the specified y-position + * draws the xPx-labels on the specified yPx-position * * @param pos */ @@ -197,7 +197,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { float[] positions = new float[mXAxis.mEntries.length * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill x values + // only fill xPx values positions[i] = mXAxis.mEntries[i / 2]; } @@ -248,7 +248,7 @@ public void renderGridLines(Canvas c) { float[] positions = new float[mXAxis.mEntries.length * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill x values + // only fill xPx values positions[i] = mXAxis.mEntries[i / 2]; } @@ -334,7 +334,7 @@ public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position, float yOffset) { String label = limitLine.getLabel(); - // if drawing the limit-value label is enabled + // if drawing the limit-yValue label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(limitLine.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 8398301463..0c16dc2a65 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -23,7 +23,7 @@ public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Trans } /** - * draws the x-labels on the specified y-position + * draws the xPx-labels on the specified yPx-position * * @param pos */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 44107750ea..7990205fac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -93,7 +93,7 @@ public void renderAxisLabels(Canvas c) { } /** - * draws the x-labels on the specified y-position + * draws the xPx-labels on the specified yPx-position * * @param pos */ @@ -229,7 +229,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-value label is enabled + // if drawing the limit-yValue label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 8d926ddfcb..71d9380e50 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -34,7 +34,7 @@ public void renderAxisLabels(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to + // calculate the factor that is needed for transforming the yValue to // pixels float factor = mChart.getFactor(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 94b7673205..17cf3dc397 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -52,7 +52,7 @@ protected void computeAxisValues(float min, float max) { return; } - // Find out how much spacing (in y value space) between axis values + // Find out how much spacing (in yPx yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -122,7 +122,7 @@ protected void computeAxisValues(float min, float max) { for (f = first, i = 0; i < n; f += interval, ++i) { - if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) + if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) f = 0.0; mYAxis.mEntries[i] = (float) f; @@ -139,7 +139,7 @@ protected void computeAxisValues(float min, float max) { } /** - * draws the y-axis labels to the screen + * draws the yPx-axis labels to the screen */ @Override public void renderAxisLabels(Canvas c) { @@ -150,9 +150,9 @@ public void renderAxisLabels(Canvas c) { float[] positions = new float[mYAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill y values, x values are not needed since the y-labels + // only fill yPx values, xPx values are not needed since the yPx-labels // are - // static on the x-axis + // static on the xPx-axis positions[i + 1] = mYAxis.mEntries[i / 2]; } @@ -213,7 +213,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the y-labels on the specified x-position + * draws the yPx-labels on the specified xPx-position * * @param fixedPosition * @param positions @@ -339,7 +339,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-value label is enabled + // if drawing the limit-yValue label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 4ce4879e3b..330ac05eb6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -30,13 +30,13 @@ public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yA /** * Computes the axis values. * - * @param yMin - the minimum y-value in the data object for this axis - * @param yMax - the maximum y-value in the data object for this axis + * @param yMin - the minimum yPx-yValue in the data object for this axis + * @param yMax - the maximum yPx-yValue in the data object for this axis */ @Override public void computeAxis(float yMin, float yMax, boolean inverted) { - // calculate the starting and entry point of the y-labels (depending on + // calculate the starting and entry point of the yPx-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentHeight() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { @@ -58,7 +58,7 @@ public void computeAxis(float yMin, float yMax, boolean inverted) { } /** - * draws the y-axis labels to the screen + * draws the yPx-axis labels to the screen */ @Override public void renderAxisLabels(Canvas c) { @@ -69,9 +69,9 @@ public void renderAxisLabels(Canvas c) { float[] positions = new float[mYAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill y values, x values are not needed since the y-labels + // only fill yPx values, xPx values are not needed since the yPx-labels // are - // static on the x-axis + // static on the xPx-axis positions[i] = mYAxis.mEntries[i / 2]; } @@ -131,7 +131,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the y-labels on the specified x-position + * draws the yPx-labels on the specified xPx-position * * @param fixedPosition * @param positions @@ -235,7 +235,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-value label is enabled + // if drawing the limit-yValue label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index e06d2fcbf8..e31487d84d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -80,7 +80,7 @@ protected void computeAxisValues(float min, float max) { final double rawCount = yMin / interval; double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + if (first == 0.0) // Fix for IEEE negative zero case (Where yValue == -0.0, and 0.0 == -0.0) first = 0.0; double last = Utils.nextUp(Math.floor(yMax / interval) * interval); @@ -164,7 +164,7 @@ public void renderLimitLines(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to + // calculate the factor that is needed for transforming the yValue to // pixels float factor = mChart.getFactor(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java index cf62492390..ed9045a25e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java @@ -5,7 +5,7 @@ import java.util.Comparator; /** - * Comparator for comparing Entry-objects by their x-index. + * Comparator for comparing Entry-objects by their xPx-index. * Created by philipp on 17/06/15. */ public class EntryXIndexComparator implements Comparator { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index fa7ff4489a..6cb5c837e7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -32,7 +32,7 @@ public boolean equals(final Object obj) { @Override public String toString() { - return width + "x" + height; + return width + "xPx" + height; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java index 7335d771ab..e5d7abce23 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java @@ -20,6 +20,6 @@ public PointD(double x, double y) { * returns a string representation of the object */ public String toString() { - return "PointD, x: " + x + ", y: " + y; + return "PointD, xPx: " + x + ", yPx: " + y; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java index 2aaa786e90..0934883b02 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java @@ -3,36 +3,38 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; /** - * Class that encapsulates information of a value that has been + * Class that encapsulates information of a yValue that has been * selected/highlighted and its DataSet index. The SelectionDetail objects give - * information about the value at the selected index and the DataSet it belongs + * information about the yValue at the selected index and the DataSet it belongs * to. Needed only for highlighting onTouch(). * * @author Philipp Jahoda */ public class SelectionDetail { - public float y; - public float x; - public float value; + public float yPx; + public float xPx; + public float yValue; + public float xValue; public int dataIndex; public int dataSetIndex; public IDataSet dataSet; - public SelectionDetail(float x, float y, float value, int dataIndex, int dataSetIndex, IDataSet set) { - this.x = x; - this.y = y; - this.value = value; + public SelectionDetail(float xPx, float yPx, float xValue, float yValue, int dataIndex, int dataSetIndex, IDataSet set) { + this.xPx = xPx; + this.yPx = yPx; + this.xValue = xValue; + this.yValue = yValue; this.dataIndex = dataIndex; this.dataSetIndex = dataSetIndex; this.dataSet = set; } - public SelectionDetail(float x, float y, float value, int dataSetIndex, IDataSet set) { - this(x, y, value, 0, dataSetIndex, set); + public SelectionDetail(float xPx, float yPx, float xValue, float yValue, int dataSetIndex, IDataSet set) { + this(xPx, yPx, xValue, yValue, 0, dataSetIndex, set); } - public SelectionDetail(float value, int dataSetIndex, IDataSet set) { - this(Float.NaN, value, 0, dataSetIndex, set); + public SelectionDetail(float xValue, float yValue, int dataSetIndex, IDataSet set) { + this(Float.NaN, Float.NaN, xValue, yValue, 0, dataSetIndex, set); } } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index af7074559a..40d738e9d6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -54,12 +54,10 @@ public void prepareMatrixValuePx(float xChartMin, float deltaX, float deltaY, fl float scaleX = (float) ((mViewPortHandler.contentWidth()) / deltaX); float scaleY = (float) ((mViewPortHandler.contentHeight()) / deltaY); - if (Float.isInfinite(scaleX)) - { + if (Float.isInfinite(scaleX)) { scaleX = 0; } - if (Float.isInfinite(scaleY)) - { + if (Float.isInfinite(scaleY)) { scaleY = 0; } @@ -98,8 +96,8 @@ public void prepareMatrixOffset(boolean inverted) { } /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the SCATTERCHART. + * Transforms an List of Entry into a float array containing the xPx and + * yPx values transformed with all matrices for the SCATTERCHART. * * @param data * @return @@ -125,8 +123,8 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, } /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the BUBBLECHART. + * Transforms an List of Entry into a float array containing the xPx and + * yPx values transformed with all matrices for the BUBBLECHART. * * @param data * @return @@ -154,8 +152,8 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, } /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the LINECHART. + * Transforms an List of Entry into a float array containing the xPx and + * yPx values transformed with all matrices for the LINECHART. * * @param data * @return @@ -183,8 +181,8 @@ public float[] generateTransformedValuesLine(ILineDataSet data, } /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the CANDLESTICKCHART. + * Transforms an List of Entry into a float array containing the xPx and + * yPx values transformed with all matrices for the CANDLESTICKCHART. * * @param data * @return @@ -212,8 +210,8 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, } /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the BARCHART. + * Transforms an List of Entry into a float array containing the xPx and + * yPx values transformed with all matrices for the BARCHART. * * @param data * @param dataSet the dataset index @@ -232,7 +230,7 @@ public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, Entry e = data.getEntryForIndex(j / 2); float i = e.getX(); - // calculate the x-position, depending on datasetcount + // calculate the xPx-position, depending on datasetcount float x = i + i * (setCount - 1) + dataSet + space * i + space / 2f; float y = e.getY(); @@ -248,7 +246,7 @@ public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, /** * transform a path with all the given matrices VERY IMPORTANT: keep order - * to value-touch-offset + * to yValue-touch-offset * * @param path */ @@ -273,7 +271,7 @@ public void pathValuesToPixel(List paths) { /** * Transform an array of points with all matrices. VERY IMPORTANT: Keep - * matrix order "value-touch-offset" when transforming. + * matrix order "yValue-touch-offset" when transforming. * * @param pts */ @@ -356,7 +354,7 @@ public void rectValuesToPixel(List rects) { } /** - * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) + * Transforms the given array of touch positions (pixels) (xPx, yPx, xPx, yPx, ...) * into values on the chart. * * @param pixels @@ -365,7 +363,7 @@ public void pixelsToValue(float[] pixels) { Matrix tmp = new Matrix(); - // invert all matrixes to convert back to the original value + // invert all matrixes to convert back to the original yValue mMatrixOffset.invert(tmp); tmp.mapPoints(pixels); @@ -376,11 +374,13 @@ public void pixelsToValue(float[] pixels) { tmp.mapPoints(pixels); } - /** buffer for performance */ + /** + * buffer for performance + */ float[] ptsBuffer = new float[2]; /** - * Returns the x and y values in the chart at the given touch point + * Returns the xPx and yPx values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). @@ -402,6 +402,26 @@ public PointD getValuesByTouchPoint(float x, float y) { return new PointD(xTouchVal, yTouchVal); } + /** + * Returns the xPx and yPx coordinates (pixels) for a given xPx and yPx yValue in the chart. + * + * @param x + * @param y + * @return + */ + public PointD getPixelsForValues(float x, float y) { + + ptsBuffer[0] = x; + ptsBuffer[1] = y; + + pointValuesToPixel(ptsBuffer); + + double xPx = ptsBuffer[0]; + double yPx = ptsBuffer[1]; + + return new PointD(xPx, yPx); + } + public Matrix getValueMatrix() { return mMatrixValueToPx; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 1abdc46b06..bf9f3157d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -89,9 +89,9 @@ public static void init(Resources res) { * This method converts dp unit to equivalent pixels, depending on device * density. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. * - * @param dp A value in dp (density independent pixels) unit. Which we need + * @param dp A yValue in dp (density independent pixels) unit. Which we need * to convert into pixels - * @return A float value to represent px equivalent to dp depending on + * @return A float yValue to represent px equivalent to dp depending on * device density */ public static float convertDpToPixel(float dp) { @@ -117,8 +117,8 @@ public static float convertDpToPixel(float dp) { * This method converts device specific pixels to density independent * pixels. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. * - * @param px A value in px (pixels) unit. Which we need to convert into db - * @return A float value to represent dp equivalent to px value + * @param px A yValue in px (pixels) unit. Which we need to convert into db + * @return A float yValue to represent dp equivalent to px yValue */ public static float convertPixelsToDp(float px) { @@ -382,8 +382,8 @@ public static double nextUp(double d) { } /** - * Returns the index of the DataSet that contains the closest value on the - * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. + * Returns the index of the DataSet that contains the closest yValue on the + * yPx-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. * * @param valsAtIndex all the values at a specific index * @return @@ -400,8 +400,8 @@ public static int getClosestDataSetIndexByValue(List valsAtInde } /** - * Returns the SelectionDetail of the DataSet that contains the closest value on the - * y-axis. + * Returns the SelectionDetail of the DataSet that contains the closest yValue on the + * yPx-axis. * * @param valsAtIndex all the values at a specific index * @return @@ -420,7 +420,7 @@ public static SelectionDetail getClosestSelectionDetailByValue( if (axis == null || sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs(sel.value - value); + float cdistance = Math.abs(sel.yValue - value); if (cdistance < distance) { closest = sel; distance = cdistance; @@ -432,8 +432,8 @@ public static SelectionDetail getClosestSelectionDetailByValue( } /** - * Returns the SelectionDetail of the DataSet that contains the closest value on the - * y-axis. + * Returns the SelectionDetail of the DataSet that contains the closest yValue on the + * yPx-axis. * * @param valsAtIndex all the values at a specific index * @return @@ -452,7 +452,7 @@ public static SelectionDetail getClosestSelectionDetailByPixel( if (axis == null || sel.dataSet.getAxisDependency() == axis) { - float cDistance = (float) Math.hypot(x - sel.x, y - sel.y); + float cDistance = (float) Math.hypot(x - sel.xPx, y - sel.yPx); if (cDistance < distance) { closest = sel; @@ -465,8 +465,8 @@ public static SelectionDetail getClosestSelectionDetailByPixel( } /** - * Returns the minimum distance from a touch-y-value (in pixels) to the - * closest y-value (in pixels) that is displayed in the chart. + * Returns the minimum distance from a touch-yPx-yValue (in pixels) to the + * closest yPx-yValue (in pixels) that is displayed in the chart. * * @param valsAtIndex * @param y @@ -485,7 +485,7 @@ public static float getMinimumDistance(List valsAtIndex, if (sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs(sel.y - y); + float cdistance = Math.abs(sel.yPx - y); if (cdistance < distance) { distance = cdistance; } @@ -785,7 +785,7 @@ public static int getSDKInt() { */ public static double granularity(float range, int labelCount) { - // Find out how much spacing (in y value space) between axis values + // Find out how much spacing (in yPx yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 955e39cf2d..4031a6323f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -28,52 +28,52 @@ public class ViewPortHandler { protected float mChartHeight = 0f; /** - * minimum scale value on the y-axis + * minimum scale yValue on the yPx-axis */ private float mMinScaleY = 1f; /** - * maximum scale value on the y-axis + * maximum scale yValue on the yPx-axis */ private float mMaxScaleY = Float.MAX_VALUE; /** - * minimum scale value on the x-axis + * minimum scale yValue on the xPx-axis */ private float mMinScaleX = 1f; /** - * maximum scale value on the x-axis + * maximum scale yValue on the xPx-axis */ private float mMaxScaleX = Float.MAX_VALUE; /** - * contains the current scale factor of the x-axis + * contains the current scale factor of the xPx-axis */ private float mScaleX = 1f; /** - * contains the current scale factor of the y-axis + * contains the current scale factor of the yPx-axis */ private float mScaleY = 1f; /** - * current translation (drag distance) on the x-axis + * current translation (drag distance) on the xPx-axis */ private float mTransX = 0f; /** - * current translation (drag distance) on the y-axis + * current translation (drag distance) on the yPx-axis */ private float mTransY = 0f; /** - * offset that allows the chart to be dragged over its bounds on the x-axis + * offset that allows the chart to be dragged over its bounds on the xPx-axis */ private float mTransOffsetX = 0f; /** - * offset that allows the chart to be dragged over its bounds on the x-axis + * offset that allows the chart to be dragged over its bounds on the xPx-axis */ private float mTransOffsetY = 0f; @@ -180,7 +180,7 @@ public float getChartWidth() { /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ /** - * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom + * Zooms in by 1.4f, xPx and yPx are the coordinates (in pixels) of the zoom * center. * * @param x @@ -197,7 +197,7 @@ public Matrix zoomIn(float x, float y) { } /** - * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom + * Zooms out by 0.7f, xPx and yPx are the coordinates (in pixels) of the zoom * center. */ public Matrix zoomOut(float x, float y) { @@ -228,7 +228,7 @@ public Matrix zoom(float scaleX, float scaleY) { } /** - * Post-scales by the specified scale factors. x and y is pivot. + * Post-scales by the specified scale factors. xPx and yPx is pivot. * * @param scaleX * @param scaleY @@ -264,7 +264,7 @@ public Matrix setZoom(float scaleX, float scaleY) { } /** - * Sets the scale factor to the specified values. x and y is pivot. + * Sets the scale factor to the specified values. xPx and yPx is pivot. * * @param scaleX * @param scaleY @@ -329,7 +329,7 @@ public Matrix translate(final float[] transformedPts) { } /** - * Centers the viewport around the specified position (x-index and y-value) + * Centers the viewport around the specified position (xPx-index and yPx-yValue) * in the chart. Centering the viewport outside the bounds of the chart is * not possible. Makes most sense in combination with the * setScaleMinima(...) method. @@ -391,10 +391,10 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float curTransY = matrixBuffer[Matrix.MTRANS_Y]; float curScaleY = matrixBuffer[Matrix.MSCALE_Y]; - // min scale-x is 1f + // min scale-xPx is 1f mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX); - // min scale-y is 1f + // min scale-yPx is 1f mScaleY = Math.min(Math.max(mMinScaleY, curScaleY), mMaxScaleY); float width = 0f; @@ -421,7 +421,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { } /** - * Sets the minimum scale factor for the x-axis + * Sets the minimum scale factor for the xPx-axis * * @param xScale */ @@ -436,7 +436,7 @@ public void setMinimumScaleX(float xScale) { } /** - * Sets the maximum scale factor for the x-axis + * Sets the maximum scale factor for the xPx-axis * * @param xScale */ @@ -451,7 +451,7 @@ public void setMaximumScaleX(float xScale) { } /** - * Sets the minimum and maximum scale factors for the x-axis + * Sets the minimum and maximum scale factors for the xPx-axis * * @param minScaleX * @param maxScaleX @@ -471,7 +471,7 @@ public void setMinMaxScaleX(float minScaleX, float maxScaleX) { } /** - * Sets the minimum scale factor for the y-axis + * Sets the minimum scale factor for the yPx-axis * * @param yScale */ @@ -486,7 +486,7 @@ public void setMinimumScaleY(float yScale) { } /** - * Sets the maximum scale factor for the y-axis + * Sets the maximum scale factor for the yPx-axis * * @param yScale */ @@ -556,14 +556,14 @@ public boolean isInBoundsBottom(float y) { } /** - * returns the current x-scale factor + * returns the current xPx-scale factor */ public float getScaleX() { return mScaleX; } /** - * returns the current y-scale factor + * returns the current yPx-scale factor */ public float getScaleY() { return mScaleY; @@ -586,7 +586,7 @@ public float getMaxScaleY() { } /** - * Returns the translation (drag / pan) distance on the x-axis + * Returns the translation (drag / pan) distance on the xPx-axis * * @return */ @@ -595,7 +595,7 @@ public float getTransX() { } /** - * Returns the translation (drag / pan) distance on the y-axis + * Returns the translation (drag / pan) distance on the yPx-axis * * @return */ @@ -617,7 +617,7 @@ public boolean isFullyZoomedOut() { } /** - * Returns true if the chart is fully zoomed out on it's y-axis (vertical). + * Returns true if the chart is fully zoomed out on it's yPx-axis (vertical). * * @return */ @@ -629,7 +629,7 @@ public boolean isFullyZoomedOutY() { } /** - * Returns true if the chart is fully zoomed out on it's x-axis + * Returns true if the chart is fully zoomed out on it's xPx-axis * (horizontal). * * @return @@ -643,7 +643,7 @@ public boolean isFullyZoomedOutX() { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the x-axis. + * bounds on the xPx-axis. * * @param offset */ @@ -653,7 +653,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the y-axis. + * bounds on the yPx-axis. * * @param offset */ @@ -662,7 +662,7 @@ public void setDragOffsetY(float offset) { } /** - * Returns true if both drag offsets (x and y) are zero or smaller. + * Returns true if both drag offsets (xPx and yPx) are zero or smaller. * * @return */ @@ -671,7 +671,7 @@ public boolean hasNoDragOffset() { } /** - * Returns true if the chart is not yet fully zoomed out on the x-axis + * Returns true if the chart is not yet fully zoomed out on the xPx-axis * * @return */ @@ -680,7 +680,7 @@ public boolean canZoomOutMoreX() { } /** - * Returns true if the chart is not yet fully zoomed in on the x-axis + * Returns true if the chart is not yet fully zoomed in on the xPx-axis * * @return */ @@ -689,7 +689,7 @@ public boolean canZoomInMoreX() { } /** - * Returns true if the chart is not yet fully zoomed out on the y-axis + * Returns true if the chart is not yet fully zoomed out on the yPx-axis * * @return */ @@ -698,7 +698,7 @@ public boolean canZoomOutMoreY() { } /** - * Returns true if the chart is not yet fully zoomed in on the y-axis + * Returns true if the chart is not yet fully zoomed in on the yPx-axis * * @return */ diff --git a/README.md b/README.md index 6390228dae..1d36cef3a8 100644 --- a/README.md +++ b/README.md @@ -78,12 +78,12 @@ Features - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) - Dual (separate) Axes - - Customizable Axes (both x- and y-axis) + - Customizable Axes (both xPx- and yPx-axis) - Highlighting values (with customizable popup-views) - Save chart to SD-Card (as image, or as .txt file) - Predefined color templates - Legends (generated automatically, customizable) - - Animations (build up animations, on both x- and y-axis) + - Animations (build up animations, on both xPx- and yPx-axis) - Limit lines (providing additional information, maximums, ...) - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart @@ -188,7 +188,7 @@ Chart types ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) - - **BubbleChart** (area covered by bubbles indicates the value) + - **BubbleChart** (area covered by bubbles indicates the yValue) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) diff --git a/gradlew b/gradlew index 9d82f78915..86ee20772b 100755 --- a/gradlew +++ b/gradlew @@ -12,7 +12,7 @@ DEFAULT_JVM_OPTS="" APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` -# Use the maximum available, or set MAX_FD != -1 to use that value. +# Use the maximum available, or set MAX_FD != -1 to use that yValue. MAX_FD="maximum" warn ( ) { @@ -64,13 +64,13 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + if [ -xPx "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi - if [ ! -x "$JAVACMD" ] ; then + if [ ! -xPx "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the diff --git a/gradlew.bat b/gradlew.bat index aec99730b4..b411ee1fa1 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -57,7 +57,7 @@ set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp -if "x%~1" == "x" goto execute +if "xPx%~1" == "xPx" goto execute set CMD_LINE_ARGS=%* goto execute From ddb03d4dec17c60c2c02a744c2dd885815c4596b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 12:27:45 +0200 Subject: [PATCH 0916/1390] Work on highlighting --- .../charting/charts/BarLineChartBase.java | 4 +- .../charting/highlight/BarHighlighter.java | 462 +++++++++--------- .../charting/renderer/LineChartRenderer.java | 5 +- 3 files changed, 230 insertions(+), 241 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 510c1e0a88..90e4f9ffdf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -940,7 +940,7 @@ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new MoveViewJob(mViewPortHandler, xIndex - xsInView / 2f, yValue + valsInView / 2f, @@ -966,7 +966,7 @@ public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex - xsInView / 2f, yValue + valsInView / 2f, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 0a5b4e6f94..ad96567eba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -3,9 +3,11 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; /** @@ -13,241 +15,227 @@ */ public class BarHighlighter extends ChartHighlighter { - public BarHighlighter(BarDataProvider chart) { - super(chart); - } - - @Override - public Highlight getHighlight(float x, float y) { - - BarData barData = mChart.getBarData(); - - final float xVal = getXForTouch(x); - final float baseNoSpace = getBase(x); - final int setCount = barData.getDataSetCount(); - int dataSetIndex = ((int)baseNoSpace) % setCount; - - if (dataSetIndex < 0) { - dataSetIndex = 0; - } else if (dataSetIndex >= setCount) { - dataSetIndex = setCount - 1; - } - - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); - if (selectionDetail == null) - return null; - - IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); - if (set.isStacked()) { - - float[] pts = new float[2]; - pts[1] = y; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - - return getStackedHighlight(selectionDetail, - set, - xVal, - pts[1]); - } - - return new Highlight( - xVal, - selectionDetail.yValue, - selectionDetail.dataIndex, - selectionDetail.dataSetIndex, - -1); - } - - @Override - protected float getXForTouch(float x) { - - if (!mChart.getBarData().isGrouped()) { - return super.getXForTouch(x); - } else { - - float baseNoSpace = getBase(x); - - int setCount = mChart.getBarData().getDataSetCount(); - int xIndex = (int) baseNoSpace / setCount; - - int valCount = mChart.getData().getXValCount(); - - if (xIndex < 0) - xIndex = 0; - else if (xIndex >= valCount) - xIndex = valCount - 1; - - return xIndex; - } - } - - @Override - protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { - - dataSetIndex = Math.max(dataSetIndex, 0); - - BarData barData = mChart.getBarData(); - IDataSet dataSet = barData.getDataSetCount() > dataSetIndex - ? barData.getDataSetByIndex(dataSetIndex) - : null; - if (dataSet == null) - return null; - - final float yValue = dataSet.getYValueForXValue(xVal); - - if (yValue == Double.NaN) return null; - - return new SelectionDetail(0f, - yValue, - dataSetIndex, - dataSet); - } - - /** - * This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been selected. - * - * @param selectionDetail the selection detail to work with looking for stacked values - * @param set - * @param xVal - * @param yValue - * @return - */ - protected Highlight getStackedHighlight( - SelectionDetail selectionDetail, - IBarDataSet set, - float xVal, - double yValue) { - - BarEntry entry = set.getEntryForXPos(xVal); - - if (entry == null) - return null; - - if (entry.getYVals() == null) { - return new Highlight(xVal, - entry.getY(), - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); - } - - Range[] ranges = getRanges(entry); - if (ranges.length > 0) { - int stackIndex = getClosestStackIndex(ranges, (float)yValue); - return new Highlight( - xVal, - entry.getPositiveSum() - entry.getNegativeSum(), - selectionDetail.dataIndex, - selectionDetail.dataSetIndex, - stackIndex, - ranges[stackIndex] - ); - } - - return null; - } - - /** - * Returns the index of the closest yValue inside the values array / ranges (stacked barchart) to the yValue given as - * a parameter. - * - * @param ranges - * @param value - * @return - */ - protected int getClosestStackIndex(Range[] ranges, float value) { - - if (ranges == null || ranges.length == 0) - return 0; - - int stackIndex = 0; - - for (Range range : ranges) { - if (range.contains(value)) - return stackIndex; - else - stackIndex++; - } - - int length = Math.max(ranges.length - 1, 0); - - return (value > ranges[length].to) ? length : 0; - // - // float[] vals = e.getYVals(); - // - // if (vals == null) - // return -1; - // - // int index = 0; - // float remainder = e.getNegativeSum(); - // - // while (index < vals.length - 1 && yValue > vals[index] + remainder) { - // remainder += vals[index]; - // index++; - // } - // - // return index; - } - - /** - * Returns the base xPx-yValue to the corresponding xPx-touch yValue in pixels. - * - * @param x - * @return - */ - protected float getBase(float x) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - float xVal = pts[0]; - - int setCount = mChart.getBarData().getDataSetCount(); - - // calculate how often the group-space appears - int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); - - float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; - - float baseNoSpace = (float) xVal - groupSpaceSum; - return baseNoSpace; - } - - /** - * Splits up the stack-values of the given bar-entry into Range objects. - * - * @param entry - * @return - */ - protected Range[] getRanges(BarEntry entry) { - - float[] values = entry.getYVals(); - - if (values == null || values.length == 0) - return new Range[0]; - - Range[] ranges = new Range[values.length]; - - float negRemain = -entry.getNegativeSum(); - float posRemain = 0f; - - for (int i = 0; i < ranges.length; i++) { - - float value = values[i]; - - if (value < 0) { - ranges[i] = new Range(negRemain, negRemain + Math.abs(value)); - negRemain += Math.abs(value); - } else { - ranges[i] = new Range(posRemain, posRemain + value); - posRemain += value; - } - } - - return ranges; - } + public BarHighlighter(BarDataProvider chart) { + super(chart); + } + + @Override + public Highlight getHighlight(float x, float y) { + + BarData barData = mChart.getBarData(); + + final float xVal = getXForTouch(x); + final float baseNoSpace = getBase(x); + final int setCount = barData.getDataSetCount(); + int dataSetIndex = ((int) baseNoSpace) % setCount; + + if (dataSetIndex < 0) { + dataSetIndex = 0; + } else if (dataSetIndex >= setCount) { + dataSetIndex = setCount - 1; + } + + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); + if (selectionDetail == null) + return null; + + IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + if (set.isStacked()) { + + float[] pts = new float[2]; + pts[1] = y; + + // take any transformer to determine the xPx-axis yValue + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + + return getStackedHighlight(selectionDetail, + set, + xVal, + pts[1]); + } + + return new Highlight( + selectionDetail.xValue, + selectionDetail.yValue, + selectionDetail.dataIndex, + selectionDetail.dataSetIndex, + -1); + } + + @Override + protected float getXForTouch(float x) { + + if (!mChart.getBarData().isGrouped()) { + return super.getXForTouch(x); + } else { + return getBase(x); +// +// float baseNoSpace = getBase(x); +// +// int setCount = mChart.getBarData().getDataSetCount(); +// int xIndex = (int) baseNoSpace / setCount; +// +// int valCount = mChart.getData().getXValCount(); +// +// if (xIndex < 0) +// xIndex = 0; +// else if (xIndex >= valCount) +// xIndex = valCount - 1; +// +// return xIndex; + } + } + + @Override + protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { + + dataSetIndex = Math.max(dataSetIndex, 0); + + BarData barData = mChart.getBarData(); + IDataSet dataSet = barData.getDataSetCount() > dataSetIndex + ? barData.getDataSetByIndex(dataSetIndex) + : null; + + if (dataSet == null) + return null; + + final Entry entry = dataSet.getEntryForXPos(xVal); + + return new SelectionDetail(entry.getX(), + entry.getY(), + dataSetIndex, + dataSet); + } + + /** + * This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been + * selected. + * + * @param selectionDetail the selection detail to work with looking for stacked values + * @param set + * @param xVal + * @param yValue + * @return + */ + protected Highlight getStackedHighlight( + SelectionDetail selectionDetail, + IBarDataSet set, + float xVal, + double yValue) { + + BarEntry entry = set.getEntryForXPos(xVal); + + if (entry == null) + return null; + + // not stacked + if (entry.getYVals() == null) { + return new Highlight(entry.getX(), + entry.getY(), + selectionDetail.dataIndex, + selectionDetail.dataSetIndex); + } else { + Range[] ranges = getRanges(entry); + + if (ranges.length > 0) { + int stackIndex = getClosestStackIndex(ranges, (float) yValue); + return new Highlight( + entry.getX(), + entry.getPositiveSum() - entry.getNegativeSum(), + selectionDetail.dataIndex, + selectionDetail.dataSetIndex, + stackIndex, + ranges[stackIndex] + ); + } + } + + return null; + } + + /** + * Returns the index of the closest yValue inside the values array / ranges (stacked barchart) to the yValue + * given as + * a parameter. + * + * @param ranges + * @param value + * @return + */ + protected int getClosestStackIndex(Range[] ranges, float value) { + + if (ranges == null || ranges.length == 0) + return 0; + + int stackIndex = 0; + + for (Range range : ranges) { + if (range.contains(value)) + return stackIndex; + else + stackIndex++; + } + + int length = Math.max(ranges.length - 1, 0); + + return (value > ranges[length].to) ? length : 0; + } + + /** + * Returns the base xPx-yValue to the given xPx-touch value in pixels. + * + * @param x + * @return + */ + protected float getBase(float x) { + + // take any transformer to determine the x-axis value + PointD val = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, 0f); + int setCount = mChart.getBarData().getDataSetCount(); + return (float) val.x; +// +// +// +// // calculate how often the group-space appears +// int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); +// +// float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; +// +// float baseNoSpace = (float) xVal - groupSpaceSum; +// return baseNoSpace; + } + + /** + * Splits up the stack-values of the given bar-entry into Range objects. + * + * @param entry + * @return + */ + protected Range[] getRanges(BarEntry entry) { + + float[] values = entry.getYVals(); + + if (values == null || values.length == 0) + return new Range[0]; + + Range[] ranges = new Range[values.length]; + + float negRemain = -entry.getNegativeSum(); + float posRemain = 0f; + + for (int i = 0; i < ranges.length; i++) { + + float value = values[i]; + + if (value < 0) { + ranges[i] = new Range(negRemain, negRemain + Math.abs(value)); + negRemain += Math.abs(value); + } else { + ranges[i] = new Range(posRemain, posRemain + value); + posRemain += value; + } + } + + return ranges; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1cf0250791..d7070cb7d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -744,10 +745,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); + PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); // draw the lines - drawHighlightLines(c, x, y, set); + drawHighlightLines(c, (float) pix.x, (float) pix.y, set); } } } From 1bf2948f48b31dc8979ccd3dddefe006968f050a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 15:02:31 +0200 Subject: [PATCH 0917/1390] Work on bar rendering --- .../mpchartexample/BarChartActivity.java | 14 +-- .../BarChartActivityMultiDataset.java | 7 +- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 7 +- .../ListViewBarChartActivity.java | 4 +- .../ListViewMultiChartActivity.java | 10 +- .../StackedBarActivityNegative.java | 2 +- .../mikephil/charting/buffer/BarBuffer.java | 37 ++---- .../charting/charts/CombinedChart.java | 60 +++++----- .../mikephil/charting/data/BarData.java | 113 ++++++++++++++---- .../mikephil/charting/data/BarDataSet.java | 9 +- .../github/mikephil/charting/data/Entry.java | 2 +- .../charting/highlight/BarHighlighter.java | 18 +-- .../highlight/HorizontalBarHighlighter.java | 60 +++++----- .../charting/renderer/BarChartRenderer.java | 24 +++- 16 files changed, 220 insertions(+), 151 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index a6c662a4c3..768e6f6ccb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -232,16 +232,15 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); + mChart.getXAxis().setAxisMinValue(0f); + mChart.getXAxis().setAxisMaxValue(count); + ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(i, val)); - - XAxisValue value = new XAxisValue(i, mMonths[i % 12]); - xVals.add(value); + yVals1.add(new BarEntry(i + 0.5f, val)); } BarDataSet set1; @@ -250,20 +249,19 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "DataSet"); - set1.setBarSpacePercent(35f); set1.setColors(ColorTemplate.MATERIAL_COLORS); ArrayList dataSets = new ArrayList(); dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); + BarData data = new BarData(new ArrayList(), dataSets); data.setValueTextSize(10f); data.setValueTypeface(mTf); + data.setBarWidth(0.9f); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 5da09fc6d7..853ccd763f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -183,6 +183,9 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + float groupSpace = 0.8f; + float barSpace = 0.15f; + tvX.setText("" + (mSeekBarX.getProgress() * 3)); tvY.setText("" + (mSeekBarY.getProgress())); @@ -247,12 +250,14 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width - data.setGroupSpace(80f); data.setValueTypeface(tf); mChart.setData(data); } + mChart.getBarData().groupBars(0, groupSpace, barSpace); + mChart.getXAxis().setAxisMinValue(0f); + mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getIntervalWidth(groupSpace, barSpace) * mSeekBarX.getProgress()); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index d7d5b2f5cb..133f2ac437 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -229,7 +229,7 @@ private void setData(int count) { mChart.notifyDataSetChanged(); } else { set = new BarDataSet(entries, "Sinus Function"); - set.setBarSpacePercent(40f); + set.setBarSpace(40f); set.setColor(Color.rgb(240, 120, 124)); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index a2f653a7b9..a7730e3250 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -119,7 +119,7 @@ private void setData(List dataList) { mChart.notifyDataSetChanged(); } else { set = new BarDataSet(values, "Values"); - set.setBarSpacePercent(40f); + set.setBarSpace(40f); set.setColors(colors); set.setValueTextColors(colors); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 67a4de9529..d97ac3bf12 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -93,7 +93,7 @@ private LineData generateLineData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(15, 10), index)); + entries.add(new Entry(index, getRandom(15, 10))); LineDataSet set = new LineDataSet(entries, "Line DataSet"); set.setColor(Color.rgb(240, 238, 70)); @@ -116,11 +116,12 @@ private LineData generateLineData() { private BarData generateBarData() { BarData d = new BarData(); + d.setBarWidth(0.9f); ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(getRandom(15, 30), index)); + entries.add(new BarEntry(index, getRandom(15, 30))); BarDataSet set = new BarDataSet(entries, "Bar DataSet"); set.setColor(Color.rgb(60, 220, 78)); @@ -140,7 +141,7 @@ protected ScatterData generateScatterData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(getRandom(20, 15), index)); + entries.add(new Entry(index, getRandom(20, 15))); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); set.setColor(Color.GREEN); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 1912e07f89..a99bae5937 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -12,7 +12,6 @@ import android.widget.ArrayAdapter; import android.widget.ListView; -import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -20,7 +19,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -138,7 +136,7 @@ private BarData generateData(int cnt) { } BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); - d.setBarSpacePercent(20f); + d.setBarSpace(20f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setBarShadowColor(Color.rgb(203, 203, 203)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 3a4f5ba75c..6f50439a68 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -98,7 +98,7 @@ private LineData generateDataLine(int cnt) { ArrayList e1 = new ArrayList(); for (int i = 0; i < 12; i++) { - e1.add(new Entry((int) (Math.random() * 65) + 40, i)); + e1.add(new Entry(i, (int) (Math.random() * 65) + 40)); } LineDataSet d1 = new LineDataSet(e1, "New DataSet " + cnt + ", (1)"); @@ -110,7 +110,7 @@ private LineData generateDataLine(int cnt) { ArrayList e2 = new ArrayList(); for (int i = 0; i < 12; i++) { - e2.add(new Entry(e1.get(i).getY() - 30, i)); + e2.add(new Entry(i, e1.get(i).getY() - 30)); } LineDataSet d2 = new LineDataSet(e2, "New DataSet " + cnt + ", (2)"); @@ -139,11 +139,11 @@ private BarData generateDataBar(int cnt) { ArrayList entries = new ArrayList(); for (int i = 0; i < 12; i++) { - entries.add(new BarEntry((int) (Math.random() * 70) + 30, i)); + entries.add(new BarEntry(i, (int) (Math.random() * 70) + 30)); } BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); - d.setBarSpacePercent(20f); + d.setBarSpace(20f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setHighLightAlpha(255); @@ -161,7 +161,7 @@ private PieData generateDataPie(int cnt) { ArrayList entries = new ArrayList(); for (int i = 0; i < 4; i++) { - entries.add(new Entry((int) (Math.random() * 70) + 30, i)); + entries.add(new Entry(i, (int) (Math.random() * 70) + 30)); } PieDataSet d = new PieDataSet(entries, ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 5f74bbed62..318e9d899d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); - set.setBarSpacePercent(40f); + set.setBarSpace(40f); set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); set.setStackLabels(new String[]{ "Men", "Women" diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java index d0ccaf01a6..615fe453dc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java @@ -13,10 +13,8 @@ public class BarBuffer extends AbstractBuffer { protected boolean mContainsStacks = false; protected boolean mInverted = false; - /** - * interval on the xPx-axis per group - */ - protected float mInterval = 0f; + /** width of the bar on the x-axis, in values (not pixels) */ + protected float mBarWidth = 1f; public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { super(size); @@ -25,8 +23,8 @@ public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsS this.mContainsStacks = containsStacks; } - public void setInterval(float interval) { - this.mInterval = interval; + public void setBarWidth(float barWidth) { + this.mBarWidth = barWidth; } public void setBarSpace(float barspace) { @@ -53,34 +51,23 @@ protected void addBar(float left, float top, float right, float bottom) { public void feed(IBarDataSet data) { float size = data.getEntryCount() * phaseX; - - float barWidth = mInterval / mDataSetCount; - - float groupSpaceWidth = mDataSetCount <= 1 ? 0 : barWidth * mGroupSpace; - float newInterval = (mInterval - groupSpaceWidth); - float newBarWidth = newInterval / mDataSetCount; - - float barSpaceWidth = newBarWidth * mBarSpace; - float barSpaceWidthHalf = barSpaceWidth / 2f; - - float groupSpaceWidthHalf = groupSpaceWidth / 2f; - float dataSetSpace = mDataSetCount <= 1 ? 0 : (newInterval / mDataSetCount) * mDataSetIndex; - + float barWidthHalf = mBarWidth / 2f; for (int i = 0; i < size; i++) { BarEntry e = data.getEntryForIndex(i); - // calculate the xPx-position, depending on interval - float x = mInterval * i + dataSetSpace; + if(e == null) + continue; + float x = e.getX(); float y = e.getY(); float[] vals = e.getYVals(); if (!mContainsStacks || vals == null) { - float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; - float right = left + newBarWidth - barSpaceWidth; + float left = x - barWidthHalf; + float right = x + barWidthHalf; float bottom, top; if (mInverted) { @@ -120,8 +107,8 @@ public void feed(IBarDataSet data) { negY += Math.abs(value); } - float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; - float right = left + newBarWidth - barSpaceWidth; + float left = x - barWidthHalf; + float right = x + barWidthHalf; float bottom, top; if (mInverted) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index 3e435538d9..a5f6d77de6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -82,36 +82,36 @@ protected void init() { // mViewPortHandler); } - @Override - protected void calcMinMax() { - super.calcMinMax(); - - if (getBarData() != null || getCandleData() != null || getBubbleData() != null) { - mXAxis.mAxisMinimum = -0.5f; - mXAxis.mAxisMaximum = mData.getXVals().size() - 0.5f; - - if (getBubbleData() != null) { - - for (IBubbleDataSet set : getBubbleData().getDataSets()) { - - final float xmin = set.getXMin(); - final float xmax = set.getXMax(); - - if (xmin < mXAxis.mAxisMinimum) - mXAxis.mAxisMinimum = xmin; - - if (xmax > mXAxis.mAxisMaximum) - mXAxis.mAxisMaximum = xmax; - } - } - } - - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - - if (mXAxis.mAxisRange == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { - mXAxis.mAxisRange = 1.f; - } - } +// @Override +// protected void calcMinMax() { +// super.calcMinMax(); +// +// if (getBarData() != null || getCandleData() != null || getBubbleData() != null) { +// mXAxis.mAxisMinimum = -0.5f; +// mXAxis.mAxisMaximum = mData.getXVals().size() - 0.5f; +// +// if (getBubbleData() != null) { +// +// for (IBubbleDataSet set : getBubbleData().getDataSets()) { +// +// final float xmin = set.getXMin(); +// final float xmax = set.getXMax(); +// +// if (xmin < mXAxis.mAxisMinimum) +// mXAxis.mAxisMinimum = xmin; +// +// if (xmax > mXAxis.mAxisMaximum) +// mXAxis.mAxisMaximum = xmax; +// } +// } +// } +// +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// +// if (mXAxis.mAxisRange == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { +// mXAxis.mAxisRange = 1.f; +// } +// } @Override public void setData(CombinedData data) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index bc87fcc24d..df43f4c073 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -9,13 +9,15 @@ /** * Data object that represents all data for the BarChart. - * + * * @author Philipp Jahoda */ public class BarData extends BarLineScatterCandleBubbleData { - /** the space that is left between groups of bars */ - private float mGroupSpace = 0.8f; + /** + * the width of the bars on the x-axis, in values (not pixels) + */ + private float mBarWidth = 1f; // /** // * The maximum space (in pixels on the screen) a single bar can consume. @@ -64,38 +66,103 @@ private static List toList(IBarDataSet dataSet) { * Returns the space that is left out between groups of bars. Always returns * 0 if the BarData object only contains one DataSet (because for one * DataSet, there is no group-space needed). - * + * * @return */ public float getGroupSpace() { - - if (mDataSets.size() <= 1) - return 0f; - else - return mGroupSpace; + return 0f; } /** - * Sets the space between groups of bars of different datasets in percent of - * the total width of one bar. 100 = space is exactly one bar width, - * default: 80 - * - * @param percent + * Sets the width each bar should have on the x-axis (in values, not pixels). + * Default 1f + * + * @param mBarWidth */ - public void setGroupSpace(float percent) { - mGroupSpace = percent / 100f; + public void setBarWidth(float mBarWidth) { + this.mBarWidth = mBarWidth; + } + + public float getBarWidth() { + return mBarWidth; } + // /** +// * Returns true if this BarData object contains grouped DataSets (more than +// * 1 DataSet). +// * +// * @return +// */ +// public boolean isGrouped() { +// return mDataSets.size() > 1 ? true : false; +// } + /** - * Returns true if this BarData object contains grouped DataSets (more than - * 1 DataSet). - * - * @return + * Groups all BarDataSet objects this data object holds together. Leaves space as specified by the parameters. + * + * @param fromX + * @param groupSpace the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f + * @param barSpace the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f */ - public boolean isGrouped() { - return mDataSets.size() > 1 ? true : false; + public void groupBars(float fromX, float groupSpace, float barSpace) { + + int setCount = mDataSets.size(); + if (setCount <= 1) { + throw new RuntimeException("BarData needs to hold at least 2 BarDataSets to allow grouping."); + } + + IBarDataSet max = getMaxEntryCountSet(); + int maxEntryCount = max.getEntryCount(); + + float groupSpaceWidthHalf = groupSpace / 2f; + float barSpaceHalf = barSpace / 2f; + float barWidthHalf = mBarWidth / 2f; + + for (int i = 0; i < maxEntryCount; i++) { + + fromX += groupSpaceWidthHalf; + + for (IBarDataSet set : mDataSets) { + + fromX += barSpaceHalf; + fromX += barWidthHalf; + + if (i < set.getEntryCount()) { + + BarEntry entry = set.getEntryForIndex(i); + + if (entry != null) { + entry.setX(fromX); + } + } + + fromX += barWidthHalf; + fromX += barSpaceHalf; + } + + fromX += groupSpaceWidthHalf; + } + + notifyDataChanged(); + } + + public float getIntervalWidth(float groupSpace, float barSpace) { + return mDataSets.size() * (mBarWidth + barSpace) + groupSpace; } - + + protected IBarDataSet getMaxEntryCountSet() { + + IBarDataSet max = mDataSets.get(0); + + for (IBarDataSet set : mDataSets) { + + if (set.getEntryCount() > max.getEntryCount()) + max = set; + } + + return max; + } + // // /** // * Sets the maximum width (in density pixels) a single bar in the barchart diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index cacf466a80..bc10e84ccb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -200,12 +200,13 @@ public float getBarSpace() { } /** - * sets the space between the bars in percent (0-100) of the total bar width + * Sets the space between the bars in values (not pixels). + * Default 0.15f * - * @param percent + * @param barSpace */ - public void setBarSpacePercent(float percent) { - mBarSpace = percent / 100f; + public void setBarSpace(float barSpace) { + mBarSpace = barSpace; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 33f1c6d246..5eefb72b0f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -140,7 +140,7 @@ public boolean equalTo(Entry e) { */ @Override public String toString() { - return "Entry, xIndex: " + x + " val (sum): " + getY(); + return "Entry, x: " + x + " y (sum): " + getY(); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index ad96567eba..6116f7d43e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -62,13 +62,13 @@ public Highlight getHighlight(float x, float y) { -1); } - @Override - protected float getXForTouch(float x) { - - if (!mChart.getBarData().isGrouped()) { - return super.getXForTouch(x); - } else { - return getBase(x); +// @Override +// protected float getXForTouch(float x) { +// +// if (!mChart.getBarData().isGrouped()) { +// return super.getXForTouch(x); +// } else { +// return getBase(x); // // float baseNoSpace = getBase(x); // @@ -83,8 +83,8 @@ protected float getXForTouch(float x) { // xIndex = valCount - 1; // // return xIndex; - } - } +// } +// } @Override protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 56865a8776..fae91f0d0a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -58,36 +58,36 @@ public Highlight getHighlight(float x, float y) { -1); } - @Override - protected float getXForTouch(float x) { - - if (!mChart.getBarData().isGrouped()) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = x; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - - return (int) Math.round(pts[1]); - } else { - - float baseNoSpace = getBase(x); - - int setCount = mChart.getBarData().getDataSetCount(); - int xIndex = (int) baseNoSpace / setCount; - - int valCount = mChart.getData().getXValCount(); - - if (xIndex < 0) - xIndex = 0; - else if (xIndex >= valCount) - xIndex = valCount - 1; - - return xIndex; - } - } +// @Override +// protected float getXForTouch(float x) { +// +// if (!mChart.getBarData().isGrouped()) { +// +// // create an array of the touch-point +// float[] pts = new float[2]; +// pts[1] = x; +// +// // take any transformer to determine the xPx-axis yValue +// mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); +// +// return (int) Math.round(pts[1]); +// } else { +// +// float baseNoSpace = getBase(x); +// +// int setCount = mChart.getBarData().getDataSetCount(); +// int xIndex = (int) baseNoSpace / setCount; +// +// int valCount = mChart.getData().getXValCount(); +// +// if (xIndex < 0) +// xIndex = 0; +// else if (xIndex >= valCount) +// xIndex = valCount - 1; +// +// return xIndex; +// } +// } /** * Returns the base yPx-yValue to the corresponding xPx-touch yValue in pixels. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 740863325c..52bd45907c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -99,7 +99,8 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setBarSpace(dataSet.getBarSpace()); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); - buffer.setInterval(mChart.getXRange() / dataSet.getEntryCount()); + buffer.setBarWidth(mChart.getBarData().getBarWidth()); + //buffer.setInterval(mChart.getXRange() / dataSet.getEntryCount()); buffer.feed(dataSet); @@ -194,6 +195,18 @@ protected void prepareBarHighlight(float y1, float y2, float interval, int entry trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); } + protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) { + + float left = x - barWidthHalf; + float right = x + barWidthHalf; + float top = y1; + float bottom = y2; + + mBarRect.set(left, top, right, bottom); + + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + } + @Override public void drawValues(Canvas c) { @@ -377,13 +390,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { BarEntry e = set.getEntryForXPos(x); int entryIndex = set.getEntryIndex(e); - if (e == null || e.getX() != x) + if (e == null) continue; - float interval = mChart.getXRange() / set.getEntryCount(); - float groupSpace = barData.getGroupSpace(); boolean isStack = high.getStackIndex() < 0 ? false : true; - float barSpace = set.getBarSpace(); final float y1; final float y2; @@ -396,7 +406,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { y2 = 0.f; } - prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, trans); + prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); + + //prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, trans); c.drawRect(mBarRect, mHighlightPaint); From e2ccaf353bc7a5197ace52e33dd537f538138a71 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 15:10:39 +0200 Subject: [PATCH 0918/1390] Remove barspace from BarDataSet --- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 2 +- .../ListViewBarChartActivity.java | 4 +-- .../ListViewMultiChartActivity.java | 2 +- .../StackedBarActivityNegative.java | 2 +- .../mikephil/charting/buffer/BarBuffer.java | 5 ---- .../charting/buffer/HorizontalBarBuffer.java | 21 ++++++------- .../mikephil/charting/charts/BarChart.java | 8 ++--- .../charting/charts/HorizontalBarChart.java | 7 ++--- .../mikephil/charting/data/BarDataSet.java | 30 ------------------- .../realm/implementation/RealmBarDataSet.java | 28 ----------------- .../interfaces/datasets/IBarDataSet.java | 7 ----- .../charting/renderer/BarChartRenderer.java | 1 - .../renderer/HorizontalBarChartRenderer.java | 1 - 14 files changed, 21 insertions(+), 99 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 133f2ac437..2710321aea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -229,7 +229,6 @@ private void setData(int count) { mChart.notifyDataSetChanged(); } else { set = new BarDataSet(entries, "Sinus Function"); - set.setBarSpace(40f); set.setColor(Color.rgb(240, 120, 124)); } @@ -237,6 +236,7 @@ private void setData(int count) { data.setValueTextSize(10f); data.setValueTypeface(mTf); data.setDrawValues(false); + data.setBarWidth(0.8f); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index a7730e3250..db8e954550 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -119,7 +119,6 @@ private void setData(List dataList) { mChart.notifyDataSetChanged(); } else { set = new BarDataSet(values, "Values"); - set.setBarSpace(40f); set.setColors(colors); set.setValueTextColors(colors); @@ -127,6 +126,7 @@ private void setData(List dataList) { data.setValueTextSize(13f); data.setValueTypeface(mTf); data.setValueFormatter(new ValueFormatter()); + data.setBarWidth(0.8f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index a99bae5937..7cbd00a414 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -135,8 +135,7 @@ private BarData generateData(int cnt) { entries.add(new BarEntry((int) (Math.random() * 70) + 30, i)); } - BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); - d.setBarSpace(20f); + BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setBarShadowColor(Color.rgb(203, 203, 203)); @@ -144,6 +143,7 @@ private BarData generateData(int cnt) { sets.add(d); BarData cd = new BarData(getMonths(), sets); + cd.setBarWidth(0.9f); return cd; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 6f50439a68..34389e8260 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -143,11 +143,11 @@ private BarData generateDataBar(int cnt) { } BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); - d.setBarSpace(20f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setHighLightAlpha(255); BarData cd = new BarData(getMonths(), d); + cd.setBarWidth(0.9f); return cd; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 318e9d899d..a8834f56ca 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -96,7 +96,6 @@ protected void onCreate(Bundle savedInstanceState) { set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); - set.setBarSpace(40f); set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); set.setStackLabels(new String[]{ "Men", "Women" @@ -110,6 +109,7 @@ protected void onCreate(Bundle savedInstanceState) { } BarData data = new BarData(xVals, set); + data.setBarWidth(0.8f); mChart.setData(data); mChart.invalidate(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java index 615fe453dc..fdcae06af7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java @@ -6,7 +6,6 @@ public class BarBuffer extends AbstractBuffer { - protected float mBarSpace = 0f; protected float mGroupSpace = 0f; protected int mDataSetIndex = 0; protected int mDataSetCount = 1; @@ -27,10 +26,6 @@ public void setBarWidth(float barWidth) { this.mBarWidth = barWidth; } - public void setBarSpace(float barspace) { - this.mBarSpace = barspace; - } - public void setDataSet(int index) { this.mDataSetIndex = index; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 5a7044522e..86cc1a7228 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -14,26 +14,23 @@ public HorizontalBarBuffer(int size, float groupspace, int dataSetCount, boolean public void feed(IBarDataSet data) { float size = data.getEntryCount() * phaseX; - - int dataSetOffset = (mDataSetCount - 1); - float barSpaceHalf = mBarSpace / 2f; - float groupSpaceHalf = mGroupSpace / 2f; - float barWidth = 0.5f; + float barWidthHalf = mBarWidth / 2f; for (int i = 0; i < size; i++) { BarEntry e = data.getEntryForIndex(i); - // calculate the xPx-position, depending on datasetcount - float x = e.getX() + e.getX() * dataSetOffset + mDataSetIndex - + mGroupSpace * e.getX() + groupSpaceHalf; + if(e == null) + continue; + + float x = e.getX(); float y = e.getY(); float[] vals = e.getYVals(); if (!mContainsStacks || vals == null) { - float bottom = x - barWidth + barSpaceHalf; - float top = x + barWidth - barSpaceHalf; + float top = x - barWidthHalf; + float bottom = x + barWidthHalf; float left, right; if (mInverted) { left = y >= 0 ? y : 0; @@ -72,8 +69,8 @@ public void feed(IBarDataSet data) { negY += Math.abs(value); } - float bottom = x - barWidth + barSpaceHalf; - float top = x + barWidth - barSpaceHalf; + float top = x - barWidthHalf; + float bottom = x + barWidthHalf; float left, right; if (mInverted) { left = y >= yStart ? y : yStart; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index f5958d9018..2c387c8488 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -106,15 +106,13 @@ public RectF getBarBounds(BarEntry e) { if (set == null) return null; - float barspace = set.getBarSpace(); float y = e.getY(); float x = e.getX(); - float barWidth = 0.5f; + float barWidth = mData.getBarWidth(); - float spaceHalf = barspace / 2f; - float left = x - barWidth + spaceHalf; - float right = x + barWidth - spaceHalf; + float left = x - barWidth / 2f; + float right = x + barWidth / 2f; float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index b183e28c69..18597df658 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -152,14 +152,13 @@ public RectF getBarBounds(BarEntry e) { if (set == null) return null; - float barspace = set.getBarSpace(); float y = e.getY(); float x = e.getX(); - float spaceHalf = barspace / 2f; + float barWidth = mData.getBarWidth(); - float top = x - 0.5f + spaceHalf; - float bottom = x + 0.5f - spaceHalf; + float top = x - barWidth / 2f; + float bottom = x + barWidth / 2f; float left = y >= 0 ? y : 0; float right = y <= 0 ? y : 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index bc10e84ccb..ad343eb110 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -10,11 +10,6 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet implements IBarDataSet { - /** - * space indicator between the bars 0.1f == 10 % - */ - private float mBarSpace = 0.15f; - /** * the maximum number of bars that are stacked upon each other, this yValue * is calculated from the Entries that are added to the DataSet @@ -68,7 +63,6 @@ public DataSet copy() { BarDataSet copied = new BarDataSet(yVals, getLabel()); copied.mColors = mColors; copied.mStackSize = mStackSize; - copied.mBarSpace = mBarSpace; copied.mBarShadowColor = mBarShadowColor; copied.mStackLabels = mStackLabels; copied.mHighLightColor = mHighLightColor; @@ -185,30 +179,6 @@ public int getEntryCountStacks() { return mEntryCountStacks; } - /** - * returns the space between bars in percent of the whole width of one yValue - * - * @return - */ - public float getBarSpacePercent() { - return mBarSpace * 100f; - } - - @Override - public float getBarSpace() { - return mBarSpace; - } - - /** - * Sets the space between the bars in values (not pixels). - * Default 0.15f - * - * @param barSpace - */ - public void setBarSpace(float barSpace) { - mBarSpace = barSpace; - } - /** * Sets the color used for drawing the bar-shadows. The bar shadows is a * surface behind the bar that indicates the maximum yValue. Don't for get to diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 9e964b1eb6..fae88776fa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -20,11 +20,6 @@ public class RealmBarDataSet extends RealmBarLineScatterC private String mStackValueFieldName; - /** - * space indicator between the bars 0.1f == 10 % - */ - private float mBarSpace = 0.15f; - /** * the maximum number of bars that are stacked upon each other, this yValue * is calculated from the Entries that are added to the DataSet @@ -184,29 +179,6 @@ public boolean isStacked() { return mStackSize > 1 ? true : false; } - /** - * returns the space between bars in percent of the whole width of one yValue - * - * @return - */ - public float getBarSpacePercent() { - return mBarSpace * 100f; - } - - @Override - public float getBarSpace() { - return mBarSpace; - } - - /** - * sets the space between the bars in percent (0-100) of the total bar width - * - * @param percent - */ - public void setBarSpacePercent(float percent) { - mBarSpace = percent / 100f; - } - /** * Sets the color used for drawing the bar-shadows. The bar shadows is a * surface behind the bar that indicates the maximum yValue. Don't for get to diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index 3c260245bc..87e651b16f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -7,13 +7,6 @@ */ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { - /** - * Returns the space between bars as the actual yValue (0 - 1.0f) - * - * @return - */ - float getBarSpace(); - /** * Returns true if this DataSet is stacked (stacksize > 1) or not. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 52bd45907c..0cc30c726b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -96,7 +96,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { // initialize the buffer BarBuffer buffer = mBarBuffers[index]; buffer.setPhases(phaseX, phaseY); - buffer.setBarSpace(dataSet.getBarSpace()); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); buffer.setBarWidth(mChart.getBarData().getBarWidth()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 9b02178179..347d3487fe 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -63,7 +63,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { // initialize the buffer BarBuffer buffer = mBarBuffers[index]; buffer.setPhases(phaseX, phaseY); - buffer.setBarSpace(dataSet.getBarSpace()); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); From 3d6f0b982b209692568dd47daf4fc93fd9d8d24b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 15:18:09 +0200 Subject: [PATCH 0919/1390] Fix in horizontal buffer --- .../mikephil/charting/buffer/HorizontalBarBuffer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 86cc1a7228..c97c909508 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -29,8 +29,8 @@ public void feed(IBarDataSet data) { if (!mContainsStacks || vals == null) { - float top = x - barWidthHalf; - float bottom = x + barWidthHalf; + float bottom = x - barWidthHalf; + float top = x + barWidthHalf; float left, right; if (mInverted) { left = y >= 0 ? y : 0; @@ -69,8 +69,8 @@ public void feed(IBarDataSet data) { negY += Math.abs(value); } - float top = x - barWidthHalf; - float bottom = x + barWidthHalf; + float bottom = x - barWidthHalf; + float top = x + barWidthHalf; float left, right; if (mInverted) { left = y >= yStart ? y : yStart; From d33b27cde0a9f0998d005be492fa1098755a51cb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 16:31:26 +0200 Subject: [PATCH 0920/1390] Work on bar highlighting --- .../charting/charts/BarLineChartBase.java | 41 --------- .../charting/highlight/BarHighlighter.java | 84 ++++++------------- .../charting/highlight/ChartHighlighter.java | 21 ++--- .../highlight/CombinedHighlighter.java | 2 +- .../highlight/HorizontalBarHighlighter.java | 5 +- .../listener/BarLineChartTouchListener.java | 1 - .../charting/renderer/BarChartRenderer.java | 42 +++++----- 7 files changed, 58 insertions(+), 138 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 90e4f9ffdf..fb70364186 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -563,47 +563,6 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { float xPos = e.getX(); float yPos = e.getY(); - if (this instanceof BarChart) { - - BarData bd = (BarData) mData; - float space = bd.getGroupSpace(); - int setCount = mData.getDataSetCount(); - float i = e.getX(); - - if (this instanceof HorizontalBarChart) { - - // calculate the xPx-position, depending on datasetcount - float y = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; - - yPos = y; - - BarEntry entry = (BarEntry) e; - if (entry.getYVals() != null) { - xPos = highlight.getRange().to; - } else { - xPos = e.getY(); - } - - xPos *= mAnimator.getPhaseY(); - } else { - - float x = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; - - xPos = x; - - BarEntry entry = (BarEntry) e; - if (entry.getYVals() != null) { - yPos = highlight.getRange().to; - } else { - yPos = e.getY(); - } - - yPos *= mAnimator.getPhaseY(); - } - } else { - yPos *= mAnimator.getPhaseY(); - } - // position of the marker depends on selected yValue index and yValue float[] pts = new float[]{ xPos, yPos diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 6116f7d43e..693fc63724 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -24,34 +24,19 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - final float xVal = getXForTouch(x); - final float baseNoSpace = getBase(x); - final int setCount = barData.getDataSetCount(); - int dataSetIndex = ((int) baseNoSpace) % setCount; - - if (dataSetIndex < 0) { - dataSetIndex = 0; - } else if (dataSetIndex >= setCount) { - dataSetIndex = setCount - 1; - } + PointD pos = getValsForTouch(x, y); - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail((float) pos.x, x, y); if (selectionDetail == null) return null; - IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + IBarDataSet set = barData.getDataSetByIndex(selectionDetail.dataSetIndex); if (set.isStacked()) { - float[] pts = new float[2]; - pts[1] = y; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(selectionDetail, set, - xVal, - pts[1]); + (float) pos.x, + (float) pos.y); } return new Highlight( @@ -87,24 +72,33 @@ public Highlight getHighlight(float x, float y) { // } @Override - protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { - - dataSetIndex = Math.max(dataSetIndex, 0); + protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { BarData barData = mChart.getBarData(); - IDataSet dataSet = barData.getDataSetCount() > dataSetIndex - ? barData.getDataSetByIndex(dataSetIndex) - : null; - if (dataSet == null) - return null; + int closestDataSetIndex = 0; + float closestDistance = Float.MAX_VALUE; + Entry closestEntry = null; + + for(int i = 0; i < barData.getDataSets().size(); i++) { - final Entry entry = dataSet.getEntryForXPos(xVal); + IBarDataSet dataSet = barData.getDataSetByIndex(i); - return new SelectionDetail(entry.getX(), - entry.getY(), - dataSetIndex, - dataSet); + final Entry entry = dataSet.getEntryForXPos(xVal); + + final float distance = Math.abs(xVal - entry.getX()); + + if(distance < closestDistance) { + closestDataSetIndex = i; + closestDistance = distance; + closestEntry = entry; + } + } + + return new SelectionDetail(x, y, closestEntry.getX(), + closestEntry.getY(), + closestDataSetIndex, + barData.getDataSetByIndex(closestDataSetIndex)); } /** @@ -181,30 +175,6 @@ protected int getClosestStackIndex(Range[] ranges, float value) { return (value > ranges[length].to) ? length : 0; } - /** - * Returns the base xPx-yValue to the given xPx-touch value in pixels. - * - * @param x - * @return - */ - protected float getBase(float x) { - - // take any transformer to determine the x-axis value - PointD val = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, 0f); - int setCount = mChart.getBarData().getDataSetCount(); - return (float) val.x; -// -// -// -// // calculate how often the group-space appears -// int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); -// -// float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; -// -// float baseNoSpace = (float) xVal - groupSpaceSum; -// return baseNoSpace; - } - /** * Splits up the stack-values of the given bar-entry into Range objects. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 4fc57febdb..c4896842de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -35,9 +35,9 @@ public ChartHighlighter(T chart) { */ public Highlight getHighlight(float x, float y) { - float xVal = getXForTouch(x); + float xVal = (float) getValsForTouch(x, y).x; - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, -1); + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y); if (selectionDetail == null) return null; @@ -53,11 +53,11 @@ public Highlight getHighlight(float x, float y) { * @param x * @return */ - protected float getXForTouch(float x) { + protected PointD getValsForTouch(float x, float y) { // take any transformer to determine the xPx-axis yValue - PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, 0f); - return (float) pos.x; + PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, y); + return pos; } /** @@ -65,12 +65,11 @@ protected float getXForTouch(float x) { * * @param xVal * @param y - * @param dataSetIndex * @return */ - protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int dataSetIndex) { + protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { - List valsAtIndex = getSelectionDetailsAtIndex(xVal, dataSetIndex); + List valsAtIndex = getSelectionDetailsAtIndex(xVal); float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); @@ -86,10 +85,9 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y, int d * Returns a list of SelectionDetail object corresponding to the given xIndex. * * @param xVal - * @param dataSetIndex dataSet index to look at. -1 if unspecified. * @return */ - protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { + protected List getSelectionDetailsAtIndex(float xVal) { List vals = new ArrayList(); @@ -97,9 +95,6 @@ protected List getSelectionDetailsAtIndex(float xVal, int dataS for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); i < dataSetCount; i++) { - if (dataSetIndex > -1 && dataSetIndex != i) - continue; - IDataSet dataSet = mChart.getData().getDataSetByIndex(i); // dont include datasets that cannot be highlighted diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 98e24859d4..8422b1e6a4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -25,7 +25,7 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { * @return */ @Override - protected List getSelectionDetailsAtIndex(float xVal, int dataSetIndex) { + protected List getSelectionDetailsAtIndex(float xVal) { List vals = new ArrayList(); float[] pts = new float[2]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index fae91f0d0a..753eb5018e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -20,7 +20,7 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - final float xVal = getXForTouch(x); + final float xVal = (float) getValsForTouch(x, y).x; final float baseNoSpace = getBase(x); final int setCount = barData.getDataSetCount(); int dataSetIndex = ((int)baseNoSpace) % setCount; @@ -31,7 +31,7 @@ public Highlight getHighlight(float x, float y) { dataSetIndex = setCount - 1; } - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y, dataSetIndex); + SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y); if (selectionDetail == null) return null; @@ -95,7 +95,6 @@ public Highlight getHighlight(float x, float y) { * @param y * @return */ - @Override protected float getBase(float y) { // create an array of the touch-point diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 98e60ffb32..7f293090bd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -567,7 +567,6 @@ public boolean onSingleTapUp(MotionEvent e) { return false; } - Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); performHighlight(h, e); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 0cc30c726b..f01d3d3ab3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -382,34 +382,31 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float x = high.getX(); - // check outofbounds - if (x >= 0 - && x < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { + BarEntry e = set.getEntryForXPos(x); + int entryIndex = set.getEntryIndex(e); - BarEntry e = set.getEntryForXPos(x); - int entryIndex = set.getEntryIndex(e); - - if (e == null) - continue; + if (e == null) + continue; - boolean isStack = high.getStackIndex() < 0 ? false : true; + boolean isStack = high.getStackIndex() < 0 ? false : true; - final float y1; - final float y2; + final float y1; + final float y2; - if (isStack) { - y1 = high.getRange().from; - y2 = high.getRange().to; - } else { - y1 = e.getY(); - y2 = 0.f; - } + if (isStack) { + y1 = high.getRange().from; + y2 = high.getRange().to; + } else { + y1 = e.getY(); + y2 = 0.f; + } - prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); + prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); - //prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, trans); + //prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, + // trans); - c.drawRect(mBarRect, mHighlightPaint); + c.drawRect(mBarRect, mHighlightPaint); // if (mChart.isDrawHighlightArrowEnabled()) { // @@ -436,9 +433,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // trans.pathValueToPixel(arrow); // c.drawPath(arrow, mHighlightPaint); // } - } + } } + } public float[] getTransformedValues(Transformer trans, IBarDataSet data, From 6919a97f177df4a15db69b818be9a509f35d0282 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 17:49:07 +0200 Subject: [PATCH 0921/1390] Remove x-values from data objects --- .../charting/charts/BarLineChartBase.java | 44 ++-- .../mikephil/charting/charts/BubbleChart.java | 52 ++--- .../mikephil/charting/charts/Chart.java | 36 +--- .../charting/charts/HorizontalBarChart.java | 18 +- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 8 +- .../mikephil/charting/data/BarData.java | 43 +--- .../mikephil/charting/data/BarDataSet.java | 2 +- .../data/BarLineScatterCandleBubbleData.java | 16 +- .../mikephil/charting/data/BubbleData.java | 29 +-- .../mikephil/charting/data/CandleData.java | 32 +-- .../mikephil/charting/data/ChartData.java | 194 ++++-------------- .../mikephil/charting/data/CombinedData.java | 8 - .../github/mikephil/charting/data/Entry.java | 4 + .../mikephil/charting/data/LineData.java | 30 +-- .../mikephil/charting/data/PieData.java | 22 +- .../mikephil/charting/data/PieDataSet.java | 8 +- .../mikephil/charting/data/PieEntry.java | 52 +++++ .../mikephil/charting/data/RadarData.java | 30 +-- .../mikephil/charting/data/ScatterData.java | 30 +-- .../realm/implementation/RealmBarData.java | 3 +- .../realm/implementation/RealmBubbleData.java | 3 +- .../realm/implementation/RealmCandleData.java | 3 +- .../realm/implementation/RealmLineData.java | 3 +- .../realm/implementation/RealmPieData.java | 3 +- .../realm/implementation/RealmPieDataSet.java | 3 +- .../realm/implementation/RealmRadarData.java | 3 +- .../implementation/RealmScatterData.java | 3 +- .../charting/highlight/Highlight.java | 4 +- .../dataprovider/ChartInterface.java | 2 - .../interfaces/datasets/IPieDataSet.java | 3 +- .../charting/renderer/LegendRenderer.java | 5 +- .../charting/renderer/PieChartRenderer.java | 19 +- .../charting/renderer/RadarChartRenderer.java | 4 +- .../renderer/YAxisRendererRadarChart.java | 2 +- 35 files changed, 228 insertions(+), 495 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index fb70364186..a419a1274e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -532,28 +532,28 @@ public void calculateOffsets() { */ protected void calcModulus() { - if (mXAxis == null || !mXAxis.isEnabled()) - return; - - if (!mXAxis.isAxisModulusCustom()) { - - float[] values = new float[9]; - mViewPortHandler.getMatrixTouch().getValues(values); - - mXAxis.mAxisLabelModulus = (int) Math - .ceil((mData.getXValCount() * mXAxis.mLabelRotatedWidth) - / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); - - } - - if (mLogEnabled) - Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + - ", xPx-axis label width: " + mXAxis.mLabelWidth + - ", xPx-axis label rotated width: " + mXAxis.mLabelRotatedWidth + - ", content width: " + mViewPortHandler.contentWidth()); - - if (mXAxis.mAxisLabelModulus < 1) - mXAxis.mAxisLabelModulus = 1; +// if (mXAxis == null || !mXAxis.isEnabled()) +// return; +// +// if (!mXAxis.isAxisModulusCustom()) { +// +// float[] values = new float[9]; +// mViewPortHandler.getMatrixTouch().getValues(values); +// +// mXAxis.mAxisLabelModulus = (int) Math +// .ceil((mData.getXValCount() * mXAxis.mLabelRotatedWidth) +// / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); +// +// } +// +// if (mLogEnabled) +// Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + +// ", xPx-axis label width: " + mXAxis.mLabelWidth + +// ", xPx-axis label rotated width: " + mXAxis.mLabelRotatedWidth + +// ", content width: " + mViewPortHandler.contentWidth()); +// +// if (mXAxis.mAxisLabelModulus < 1) +// mXAxis.mAxisLabelModulus = 1; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java index af93fdfb18..a0681e652c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java @@ -38,32 +38,32 @@ protected void init() { mRenderer = new BubbleChartRenderer(this, mAnimator, mViewPortHandler); } - @Override - protected void calcMinMax() { - super.calcMinMax(); - - if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) - mXAxis.mAxisRange = 1; - - mXAxis.mAxisMinimum = -0.5f; - mXAxis.mAxisMaximum = (float) mData.getXValCount() - 0.5f; - - if (mRenderer != null) { - for (IBubbleDataSet set : mData.getDataSets()) { - - final float xmin = set.getXMin(); - final float xmax = set.getXMax(); - - if (xmin < mXAxis.mAxisMinimum) - mXAxis.mAxisMinimum = xmin; - - if (xmax > mXAxis.mAxisMaximum) - mXAxis.mAxisMaximum = xmax; - } - } - - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - } +// @Override +// protected void calcMinMax() { +// super.calcMinMax(); +// +// if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) +// mXAxis.mAxisRange = 1; +// +// mXAxis.mAxisMinimum = -0.5f; +// mXAxis.mAxisMaximum = (float) mData.getXValCount() - 0.5f; +// +// if (mRenderer != null) { +// for (IBubbleDataSet set : mData.getDataSets()) { +// +// final float xmin = set.getXMin(); +// final float xmax = set.getXMax(); +// +// if (xmin < mXAxis.mAxisMinimum) +// mXAxis.mAxisMinimum = xmin; +// +// if (xmax > mXAxis.mAxisMaximum) +// mXAxis.mAxisMaximum = xmax; +// } +// } +// +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// } public BubbleData getBubbleData() { return mData; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ae7075b725..006cbd1c33 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -389,7 +389,7 @@ protected void calculateFormatter(float min, float max) { float reference = 0f; - if (mData == null || mData.getXValCount() < 2) { + if (mData == null || mData.getEntryCount() < 2) { reference = Math.max(Math.abs(min), Math.abs(max)); } else { @@ -561,20 +561,18 @@ public void highlightValue(int xIndex, int dataSetIndex) { } /** - * Highlights the yValue at the given xPx-index in the given DataSet. Provide - * -1 as the xPx-index or dataSetIndex to undo all highlighting. + * Highlights the yValue at the given x position in the given DataSet. Provide + * -1 as the dataSetIndex to undo all highlighting. * - * @param xIndex + * @param x * @param dataSetIndex */ - public void highlightValue(int xIndex, int dataSetIndex, boolean callListener) { - - if (xIndex < 0 || dataSetIndex < 0 || xIndex >= mData.getXValCount() - || dataSetIndex >= mData.getDataSetCount()) { + public void highlightValue(float x, int dataSetIndex, boolean callListener) { + if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) { highlightValue(null, callListener); } else { - highlightValue(new Highlight(xIndex, dataSetIndex), callListener); + highlightValue(new Highlight(x, dataSetIndex), callListener); } } @@ -686,7 +684,7 @@ protected void drawMarkers(Canvas canvas) { float deltaX = mXAxis != null ? mXAxis.mAxisRange - : ((mData == null ? 0.f : mData.getXValCount()) - 1.f); + : 1f; if (xVal <= deltaX && xVal <= deltaX * mAnimator.getPhaseX()) { @@ -1023,11 +1021,6 @@ public float getXRange() { return mXAxis.mAxisRange; } - @Override - public int getXValCount() { - return mData.getXValCount(); - } - /** * Returns the total number of (yPx) values the chart holds (across all DataSets). * @@ -1390,19 +1383,6 @@ public void setDrawMarkerViews(boolean enabled) { mDrawMarkerViews = enabled; } - /** - * returns the xPx-yValue at the given index - * - * @param index - * @return - */ - public XAxisValue getXValue(int index) { - if (mData == null || mData.getXValCount() <= index) - return null; - else - return mData.getXVals().get(index); - } - /** * Get all Entry objects at the given index across all DataSets. * INFORMATION: This method does calculations at runtime. Do not over-use in diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 18597df658..d8fd26da4e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -133,15 +133,15 @@ protected void prepareValuePxMatrix() { @Override protected void calcModulus() { - float[] values = new float[9]; - mViewPortHandler.getMatrixTouch().getValues(values); - - mXAxis.mAxisLabelModulus = - (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) - / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); - - if (mXAxis.mAxisLabelModulus < 1) - mXAxis.mAxisLabelModulus = 1; +// float[] values = new float[9]; +// mViewPortHandler.getMatrixTouch().getValues(values); +// +// mXAxis.mAxisLabelModulus = +// (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) +// / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); +// +// if (mXAxis.mAxisLabelModulus < 1) +// mXAxis.mAxisLabelModulus = 1; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index fc00d890be..c3d14c042a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -66,7 +66,7 @@ protected void init() { @Override protected void calcMinMax() { - mXAxis.mAxisRange = mData.getXVals().size() - 1; + //mXAxis.mAxisRange = mData.getXVals().size() - 1; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 400fb85711..28f2529db6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -101,8 +101,8 @@ protected void calcMinMax() { super.calcMinMax(); // calculate / set xPx-axis range - mXAxis.mAxisMaximum = mData.getXVals().size() - 1; - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// mXAxis.mAxisMaximum = mData.getXVals().size() - 1; +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); mYAxis.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); } @@ -190,7 +190,7 @@ public float getFactor() { * @return */ public float getSliceAngle() { - return 360f / (float) mData.getXValCount(); + return 360f / (float) mData.getEntryCount(); } @Override @@ -201,7 +201,7 @@ public int getIndexForAngle(float angle) { float sliceangle = getSliceAngle(); - for (int i = 0; i < mData.getXValCount(); i++) { + for (int i = 0; i < mData.getEntryCount(); i++) { if (sliceangle * (i + 1) - sliceangle / 2f > a) return i; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index df43f4c073..08187c2061 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -32,34 +32,8 @@ public BarData(IBarDataSet... dataSets) { super(dataSets); } - public BarData(List xVals) { - super(xVals); - } - - public BarData(XAxisValue[] xVals) { - super(xVals); - } - - public BarData(List xVals, List dataSets) { - super(xVals, dataSets); - } - - public BarData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); - } - - public BarData(List xVals, IBarDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public BarData(XAxisValue[] xVals, IBarDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(IBarDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + public BarData(List dataSets) { + super(dataSets); } /** @@ -150,19 +124,6 @@ public float getIntervalWidth(float groupSpace, float barSpace) { return mDataSets.size() * (mBarWidth + barSpace) + groupSpace; } - protected IBarDataSet getMaxEntryCountSet() { - - IBarDataSet max = mDataSets.get(0); - - for (IBarDataSet set : mDataSets) { - - if (set.getEntryCount() > max.getEntryCount()) - max = set; - } - - return max; - } - // // /** // * Sets the maximum width (in density pixels) a single bar in the barchart diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index ad343eb110..14738aa4bc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -57,7 +57,7 @@ public DataSet copy() { List yVals = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(((BarEntry) mValues.get(i)).copy()); + yVals.add(mValues.get(i).copy()); } BarDataSet copied = new BarDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index c16c2c72a1..c09eadec9b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -20,20 +20,8 @@ public BarLineScatterCandleBubbleData() { public BarLineScatterCandleBubbleData(T... sets) { super(sets); } - - public BarLineScatterCandleBubbleData(List xVals) { - super(xVals); - } - - public BarLineScatterCandleBubbleData(XAxisValue[] xVals) { - super(xVals); - } - public BarLineScatterCandleBubbleData(List xVals, List sets) { - super(xVals, sets); - } - - public BarLineScatterCandleBubbleData(XAxisValue[] xVals, List sets) { - super(xVals, sets); + public BarLineScatterCandleBubbleData(List sets) { + super(sets); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java index 28e317b306..0ce345bc90 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java @@ -12,35 +12,14 @@ public BubbleData() { super(); } - public BubbleData(List xVals) { - super(xVals); + public BubbleData(IBubbleDataSet... dataSets) { + super(dataSets); } - public BubbleData(XAxisValue[] xVals) { - super(xVals); + public BubbleData(List dataSets) { + super(dataSets); } - public BubbleData(List xVals, List dataSets) { - super(xVals, dataSets); - } - - public BubbleData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); - } - - public BubbleData(List xVals, IBubbleDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public BubbleData(XAxisValue[] xVals, IBubbleDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(IBubbleDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; - } /** * Sets the width of the circle that surrounds the bubble when highlighted diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java index 17e79c0748..1e90db2ba5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleData.java @@ -10,34 +10,12 @@ public class CandleData extends BarLineScatterCandleBubbleData { public CandleData() { super(); } - - public CandleData(List xVals) { - super(xVals); - } - - public CandleData(XAxisValue[] xVals) { - super(xVals); - } - - public CandleData(List xVals, List dataSets) { - super(xVals, dataSets); - } - public CandleData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); + public CandleData(List dataSets) { + super(dataSets); } - - public CandleData(List xVals, ICandleDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public CandleData(XAxisValue[] xVals, ICandleDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(ICandleDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + + public CandleData(ICandleDataSet... dataSets) { + super(dataSets); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index dd4fcee6bf..b3ea3809a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; @@ -60,18 +61,12 @@ public abstract class ChartData> { */ private float mXValMaximumLength = 0; - /** - * holds all xPx-values the chart represents - */ - protected List mXVals; - /** * array that holds all DataSets the ChartData object represents */ protected List mDataSets; public ChartData() { - mXVals = new ArrayList(); mDataSets = new ArrayList(); } @@ -80,124 +75,24 @@ public ChartData(T... dataSets) { init(); } - /** - * Constructor for only xPx-values. This constructor can be used for setting - * up an empty chart without data. - * - * @param xVals - */ - public ChartData(List xVals) { - this.mXVals = xVals; - this.mDataSets = new ArrayList(); - init(); - } - - /** - * Constructor for only xPx-values. This constructor can be used for setting - * up an empty chart without data. - * - * @param xVals - */ - public ChartData(XAxisValue[] xVals) { - this.mXVals = arrayToList(xVals); - this.mDataSets = new ArrayList(); - init(); - } - /** * constructor for chart data * - * @param xVals The values describing the xPx-axis. Must be at least as long - * as the highest xIndex in the Entry objects across all - * DataSets. - * @param sets the dataset array - */ - public ChartData(List xVals, List sets) { - this.mXVals = xVals; - this.mDataSets = sets; - - init(); - } - - /** - * constructor that takes string array instead of List string - * - * @param xVals The values describing the xPx-axis. Must be at least as long - * as the highest xIndex in the Entry objects across all - * DataSets. - * @param sets the dataset array + * @param sets the dataset array */ - public ChartData(XAxisValue[] xVals, List sets) { - this.mXVals = arrayToList(xVals); + public ChartData(List sets) { this.mDataSets = sets; - init(); } - /** - * Turns an array of strings into an List of strings. - * - * @param array - * @return - */ - private List arrayToList(XAxisValue[] array) { - return Arrays.asList(array); - } - /** * performs all kinds of initialization calculations, such as min-max and * yValue count and sum */ protected void init() { - checkLegal(); calcYValueCount(); calcMinMax(); - - calcXValMaximumLength(); - } - - /** - * calculates the average length (in characters) across all xPx-yValue strings - */ - private void calcXValMaximumLength() { - - if (mXVals.size() <= 0) { - mXValMaximumLength = 1; - return; - } - - int max = 1; - - for (int i = 0; i < mXVals.size(); i++) { - - int length = mXVals.get(i).getLabel().length(); - - if (length > max) - max = length; - } - - mXValMaximumLength = max; - } - - /** - * Checks if the combination of xPx-values array and DataSet array is legal or - * not. - */ - private void checkLegal() { - - if (mDataSets == null) - return; - - if (this instanceof ScatterData || this instanceof CombinedData) - return; - - for (int i = 0; i < mDataSets.size(); i++) { - if (mDataSets.get(i).getEntryCount() > mXVals.size()) { -// throw new IllegalArgumentException( -// "One or more of the DataSet Entry arrays are longer than the xPx-values array of this ChartData object."); - } - } } /** @@ -413,45 +308,6 @@ public int getYValCount() { return mYValCount; } - /** - * returns the xPx-values the chart represents - * - * @return - */ - public List getXVals() { - return mXVals; - } - - /** - * sets the xPx-values the chart represents - * - */ - public void setXVals(List xVals) { - mXVals = xVals; - } - - /** - * Adds a new xPx-yValue to the chart data. - * - * @param xVal - */ - public void addXValue(XAxisValue xVal) { - - if (xVal != null && xVal.getLabel().length() > mXValMaximumLength) - mXValMaximumLength = xVal.getLabel().length(); - - mXVals.add(xVal); - } - - /** - * Removes the xPx-yValue at the specified index. - * - * @param index - */ - public void removeXValue(int index) { - mXVals.remove(index); - } - public List getDataSets() { return mDataSets; } @@ -483,16 +339,6 @@ protected int getDataSetIndexByLabel(List dataSets, String label, return -1; } - /** - * returns the total number of xPx-values this ChartData object represents - * (the size of the xPx-values array) - * - * @return - */ - public int getXValCount() { - return mXVals.size(); - } - /** * Returns the labels of all DataSets as a string array. * @@ -1046,4 +892,38 @@ public boolean contains(T dataSet) { return false; } + + /** + * Returns the total entry count across all DataSet objects this data object contains. + * + * @return + */ + public int getEntryCount() { + + int count = 0; + + for (T set : mDataSets) { + count += set.getEntryCount(); + } + + return count; + } + + /** + * Returns the DataSet object with the maximum number of entries. + * + * @return + */ + public T getMaxEntryCountSet() { + + T max = mDataSets.get(0); + + for (T set : mDataSets) { + + if (set.getEntryCount() > max.getEntryCount()) + max = set; + } + + return max; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index c6341f77e8..174cac65a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -25,14 +25,6 @@ public CombinedData() { super(); } - public CombinedData(List xVals) { - super(xVals); - } - - public CombinedData(XAxisValue[] xVals) { - super(xVals); - } - public void setData(LineData data) { mLineData = data; mDataSets.addAll(data.getDataSets()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 5eefb72b0f..834f46b202 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -22,6 +22,10 @@ public class Entry implements Parcelable { /** optional spot for additional data this Entry represents */ private Object mData = null; + public Entry() { + + } + /** * A Entry represents one single entry in the chart. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java index b4ef3b1d53..4cf544874b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineData.java @@ -21,33 +21,7 @@ public LineData(ILineDataSet... dataSets) { super(dataSets); } - public LineData(List xVals) { - super(xVals); - } - - public LineData(XAxisValue[] xVals) { - super(xVals); - } - - public LineData(List xVals, List dataSets) { - super(xVals, dataSets); - } - - public LineData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); - } - - public LineData(List xVals, ILineDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public LineData(XAxisValue[] xVals, ILineDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(ILineDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + public LineData(List dataSets) { + super(dataSets); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index 4df8aee73f..62b5284c14 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -20,26 +20,8 @@ public PieData() { super(); } - public PieData(List xVals) { - super(xVals); - } - - public PieData(XAxisValue[] xVals) { - super(xVals); - } - - public PieData(List xVals, IPieDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public PieData(XAxisValue[] xVals, IPieDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(IPieDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + public PieData(IPieDataSet dataSet) { + super(dataSet); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 5e1f0b8732..4d8b33b964 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -7,7 +7,7 @@ import java.util.ArrayList; import java.util.List; -public class PieDataSet extends DataSet implements IPieDataSet { +public class PieDataSet extends DataSet implements IPieDataSet { /** the space in pixels between the chart-slices, default 0f */ private float mSliceSpace = 0f; @@ -24,15 +24,15 @@ public class PieDataSet extends DataSet implements IPieDataSet { private float mValueLinePart2Length = 0.4f; private boolean mValueLineVariableLength = true; - public PieDataSet(List yVals, String label) { + public PieDataSet(List yVals, String label) { super(yVals, label); // mShift = Utils.convertDpToPixel(12f); } @Override - public DataSet copy() { + public DataSet copy() { - List yVals = new ArrayList(); + List yVals = new ArrayList<>(); for (int i = 0; i < mValues.size(); i++) { yVals.add(mValues.get(i).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java new file mode 100644 index 0000000000..52853629fd --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java @@ -0,0 +1,52 @@ +package com.github.mikephil.charting.data; + +import android.annotation.SuppressLint; + +/** + * Created by Philipp Jahoda on 31/05/16. + */ +@SuppressLint("ParcelCreator") +public class PieEntry extends Entry { + + private String label; + + public PieEntry(float value) { + super(0f, value); + } + + public PieEntry(float value, Object data) { + super(0f, value, data); + } + + public PieEntry(float value, String label) { + super(0f, value); + this.label = label; + } + + public PieEntry(float value, String label, Object data) { + super(0f, value, data); + this.label = label; + } + + /** + * This is the same as getY(). Returns the value of the PieEntry. + * + * @return + */ + public float getValue() { + return getY(); + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public PieEntry copy() { + PieEntry e = new PieEntry(getY(), label, getData()); + return e; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java index ff18c0d8e1..bfb38c3e13 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java @@ -17,33 +17,11 @@ public RadarData() { super(); } - public RadarData(List xVals) { - super(xVals); + public RadarData(List dataSets) { + super(dataSets); } - public RadarData(XAxisValue[] xVals) { - super(xVals); - } - - public RadarData(List xVals, List dataSets) { - super(xVals, dataSets); - } - - public RadarData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); - } - - public RadarData(List xVals, IRadarDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - public RadarData(XAxisValue[] xVals, IRadarDataSet dataSet) { - super(xVals, toList(dataSet)); - } - - private static List toList(IRadarDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + public RadarData(IRadarDataSet... dataSets) { + super(dataSets); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java index 713fa7f2e0..fef13c20fd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java @@ -11,35 +11,13 @@ public class ScatterData extends BarLineScatterCandleBubbleData public ScatterData() { super(); } - - public ScatterData(List xVals) { - super(xVals); - } - - public ScatterData(XAxisValue[] xVals) { - super(xVals); - } - - public ScatterData(List xVals, List dataSets) { - super(xVals, dataSets); - } - - public ScatterData(XAxisValue[] xVals, List dataSets) { - super(xVals, dataSets); - } - - public ScatterData(List xVals, IScatterDataSet dataSet) { - super(xVals, toList(dataSet)); - } - public ScatterData(XAxisValue[] xVals, IScatterDataSet dataSet) { - super(xVals, toList(dataSet)); + public ScatterData(List dataSets) { + super(dataSets); } - private static List toList(IScatterDataSet dataSet) { - List sets = new ArrayList(); - sets.add(dataSet); - return sets; + public ScatterData(IScatterDataSet... dataSets) { + super(dataSets); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java index 8a46ff618a..a230385032 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java @@ -15,6 +15,7 @@ public class RealmBarData extends BarData { public RealmBarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java index e21017f6f9..ec23ec516b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java @@ -15,6 +15,7 @@ public class RealmBubbleData extends BubbleData { public RealmBubbleData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + ////RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java index 5cc2757498..fbe2cb6a92 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java @@ -15,6 +15,7 @@ public class RealmCandleData extends CandleData { public RealmCandleData(RealmResults result,String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java index 97357e034d..cee63fa6cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java @@ -15,6 +15,7 @@ public class RealmLineData extends LineData { public RealmLineData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java index d407e67864..3a08452813 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java @@ -13,6 +13,7 @@ public class RealmPieData extends PieData { public RealmPieData(RealmResults result,String xPositionField, String xLabelField, IPieDataSet dataSet) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSet); + super(dataSet); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index bb6d275e8a..8ce3fc0df1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -2,6 +2,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.data.realm.base.RealmBaseDataSet; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; @@ -13,7 +14,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { +public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { /** * the space in pixels between the chart-slices, default 0f diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java index 61dbf2b86d..e2a1d95811 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java @@ -15,6 +15,7 @@ public class RealmRadarData extends RadarData{ public RealmRadarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java index 8ae94aaac3..480455c30c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java @@ -15,6 +15,7 @@ public class RealmScatterData extends ScatterData { public RealmScatterData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(RealmUtils.toXVals(result, xPositionField, xLabelField), dataSets); + super(dataSets); + //RealmUtils.toXVals(result, xPositionField, xLabelField) } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index fe52b33619..4c267338b1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -74,10 +74,10 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted yValue on the xPx-axis + * @param x the x-value of the highlighted value on the x-axis * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to */ - public Highlight(int x, int dataSetIndex) { + public Highlight(float x, int dataSetIndex) { this(x, Float.NaN, 0, dataSetIndex, -1); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index a063213380..a77ecaf393 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -44,8 +44,6 @@ public interface ChartInterface { */ float getYChartMax(); - int getXValCount(); - int getWidth(); int getHeight(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 21980a428c..3b10d003ba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -2,11 +2,12 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; /** * Created by Philipp Jahoda on 03/11/15. */ -public interface IPieDataSet extends IDataSet { +public interface IPieDataSet extends IDataSet { /** * Returns the space that is set to be between the piechart-slices of this diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index f620a81b0c..f5fdacc0b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -111,12 +111,11 @@ public void computeLegend(ChartData data) { } else if (dataSet instanceof IPieDataSet) { - List xVals = data.getXVals(); IPieDataSet pds = (IPieDataSet) dataSet; - for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { + for (int j = 0; j < clrs.size() && j < entryCount; j++) { - labels.add(xVals.get(j).getLabel()); + labels.add(pds.getEntryForIndex(j).getLabel()); colors.add(clrs.get(j)); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 78f1a996b2..43f70b0809 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; @@ -412,7 +413,7 @@ public void drawValues(Canvas c) { for (int j = 0; j < entryCount; j++) { - Entry entry = dataSet.getEntryForIndex(j); + PieEntry entry = dataSet.getEntryForIndex(j); if (xIndex == 0) angle = 0.f; @@ -505,15 +506,15 @@ public void drawValues(Canvas c) { labelPty, dataSet.getValueTextColor(j)); - if (j < data.getXValCount()) { - c.drawText(data.getXVals().get(j).getLabel(), labelPtx, labelPty + lineHeight, + if (j < data.getEntryCount()) { + c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight, mValuePaint); } } else if (drawXOutside) { - if (j < data.getXValCount()) { + if (j < data.getEntryCount()) { mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(data.getXVals().get(j).getLabel(), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); + c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); } } else if (drawYOutside) { @@ -534,15 +535,15 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); - if (j < data.getXValCount()) { - c.drawText(data.getXVals().get(j).getLabel(), x, y + lineHeight, + if (j < data.getEntryCount()) { + c.drawText(entry.getLabel(), x, y + lineHeight, mValuePaint); } } else if (drawXInside) { - if (j < data.getXValCount()) { + if (j < data.getEntryCount()) { mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(data.getXVals().get(j).getLabel(), x, y + lineHeight / 2f, mValuePaint); + c.drawText(entry.getLabel(), x, y + lineHeight / 2f, mValuePaint); } } else if (drawYInside) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 7e23bbd403..ffdd8685cb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -218,7 +218,7 @@ protected void drawWeb(Canvas c) { final int xIncrements = 1 + mChart.getSkipWebLineCount(); - for (int i = 0; i < mChart.getData().getXValCount(); i += xIncrements) { + for (int i = 0; i < mChart.getData().getEntryCount(); i += xIncrements) { PointF p = Utils.getPosition( center, @@ -237,7 +237,7 @@ protected void drawWeb(Canvas c) { for (int j = 0; j < labelCount; j++) { - for (int i = 0; i < mChart.getData().getXValCount(); i++) { + for (int i = 0; i < mChart.getData().getEntryCount(); i++) { float r = (mChart.getYAxis().mEntries[j] - mChart.getYChartMin()) * factor; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index e31487d84d..dc79bc9aad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -185,7 +185,7 @@ public void renderLimitLines(Canvas c) { Path limitPath = new Path(); - for (int j = 0; j < mChart.getData().getXValCount(); j++) { + for (int j = 0; j < mChart.getData().getMaxEntryCountSet().getEntryCount(); j++) { PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); From 0d4b60800c1c48663247d3c83b49bd8803faebf2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 18:00:35 +0200 Subject: [PATCH 0922/1390] Remove XAxisValue from example --- .../mpchartexample/AnotherBarActivity.java | 11 +--- .../mpchartexample/BarChartActivity.java | 2 +- .../BarChartActivityMultiDataset.java | 10 +-- .../mpchartexample/BarChartActivitySinus.java | 3 +- .../BarChartPositiveNegative.java | 5 +- .../mpchartexample/BubbleChartActivity.java | 8 +-- .../CandleStickChartActivity.java | 6 +- .../mpchartexample/CombinedChartActivity.java | 8 +-- .../CubicLineChartActivity.java | 9 +-- .../DynamicalAddingActivity.java | 10 +-- .../HorizontalBarChartActivity.java | 3 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 3 +- .../mpchartexample/LineChartActivity2.java | 3 +- .../mpchartexample/LineChartTime.java | 9 +-- .../ListViewBarChartActivity.java | 2 +- .../ListViewMultiChartActivity.java | 11 ++-- .../MultiLineChartActivity.java | 7 +- .../mpchartexample/PerformanceLineChart.java | 7 +- .../mpchartexample/PieChartActivity.java | 12 ++-- .../PiePolylineChartActivity.java | 12 ++-- .../mpchartexample/RadarChartActivitry.java | 7 +- .../RealtimeLineChartActivity.java | 6 +- .../mpchartexample/ScatterChartActivity.java | 7 +- .../mpchartexample/ScrollViewActivity.java | 4 +- .../mpchartexample/StackedBarActivity.java | 8 +-- .../StackedBarActivityNegative.java | 7 +- .../fragments/SimpleFragment.java | 21 +++--- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../mikephil/charting/data/XAxisValue.java | 66 ------------------- 30 files changed, 53 insertions(+), 218 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 20f015e640..2ab4868b2a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -180,20 +180,12 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new BarEntry(i, val)); } - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - - XAxisValue xValue = new XAxisValue(i, (int) yVals1.get(i).getY() + ""); - xVals.add(xValue); - } - BarDataSet set1; if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -204,8 +196,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); - + BarData data = new BarData(dataSets); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 768e6f6ccb..753157c7f4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -258,7 +258,7 @@ private void setData(int count, float range) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); - BarData data = new BarData(new ArrayList(), dataSets); + BarData data = new BarData(dataSets); data.setValueTextSize(10f); data.setValueTypeface(mTf); data.setBarWidth(0.9f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 853ccd763f..c9f16aec0b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -189,13 +189,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() * 3)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - - XAxisValue value = new XAxisValue(i, (i+1990) + ""); - xVals.add(value); - } - ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); @@ -227,7 +220,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setYVals(yVals1); set2.setYVals(yVals2); set3.setYVals(yVals3); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -246,7 +238,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set2); dataSets.add(set3); - BarData data = new BarData(xVals, dataSets); + BarData data = new BarData(dataSets); // data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 2710321aea..fe32a1e2f7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -224,7 +224,6 @@ private void setData(int count) { mChart.getData().getDataSetCount() > 0) { set = (BarDataSet) mChart.getData().getDataSetByIndex(0); set.setYVals(entries); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -232,7 +231,7 @@ private void setData(int count) { set.setColor(Color.rgb(240, 120, 124)); } - BarData data = new BarData(xVals, set); + BarData data = new BarData(set); data.setValueTextSize(10f); data.setValueTypeface(mTf); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index db8e954550..ceb699561e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -88,7 +88,6 @@ protected void onCreate(Bundle savedInstanceState) { private void setData(List dataList) { ArrayList values = new ArrayList(); - XAxisValue[] dates = new XAxisValue[dataList.size()]; List colors = new ArrayList(); int green = Color.rgb(110, 190, 102); @@ -100,8 +99,6 @@ private void setData(List dataList) { BarEntry entry = new BarEntry(d.xValue, d.yValue); values.add(entry); - dates[i] = new XAxisValue(i, dataList.get(i).xAxisValue); - // specific colors if (d.yValue >= 0) colors.add(red); @@ -122,7 +119,7 @@ private void setData(List dataList) { set.setColors(colors); set.setValueTextColors(colors); - BarData data = new BarData(dates, set); + BarData data = new BarData(set); data.setValueTextSize(13f); data.setValueTypeface(mTf); data.setValueFormatter(new ValueFormatter()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 3c16c8a045..27050469b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -163,12 +163,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + count); tvY.setText("" + range); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - XAxisValue xVal = new XAxisValue(i,(i) + ""); - xVals.add(xVal); - } - ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); @@ -211,7 +205,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set3); // create a data object with the datasets - BubbleData data = new BubbleData(xVals, dataSets); + BubbleData data = new BubbleData(dataSets); data.setValueTypeface(tf); data.setValueTextSize(8f); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 1eb8fa6b8c..fe76c9e2cb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -167,7 +167,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.resetTracking(); - ArrayList xVals = new ArrayList(); ArrayList yVals1 = new ArrayList(); for (int i = 0; i < prog; i++) { @@ -184,9 +183,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new CandleEntry(i, val + high, val - low, even ? val + open : val - open, even ? val - close : val + close)); - - XAxisValue xVal = new XAxisValue(i,(i) + ""); - xVals.add(xVal); } CandleDataSet set1 = new CandleDataSet(yVals1, "Data Set"); @@ -201,7 +197,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setNeutralColor(Color.BLUE); //set1.setHighlightLineWidth(1f); - CandleData data = new CandleData(xVals, set1); + CandleData data = new CandleData(set1); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index d97ac3bf12..12923422dc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -68,13 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); - XAxisValue[] xVals = new XAxisValue[mMonths.length]; - - for(int i = 0; i < mMonths.length; i++) { - xVals[i] = new XAxisValue(i, mMonths[i]); - } - - CombinedData data = new CombinedData(xVals); + CombinedData data = new CombinedData(); data.setData(generateLineData()); data.setData(generateBarData()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 4c42066d7f..e82c445987 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -269,12 +269,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - xVals.add(new XAxisValue(1990 + i, (1990 +i) + "")); - } - ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -291,7 +285,6 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -318,7 +311,7 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv }); // create a data object with the datasets - LineData data = new LineData(xVals, set1); + LineData data = new LineData(set1); data.setValueTypeface(tf); data.setValueTextSize(9f); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index c67086f667..c040d12d7d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -63,7 +63,7 @@ private void addEntry() { } // add a new xPx-yValue first - data.addXValue(new XAxisValue(set.getEntryCount(), set.getEntryCount() + "")); + //data.addXValue(new XAxisValue(set.getEntryCount(), set.getEntryCount() + "")); // choose a random dataSet int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); @@ -77,7 +77,7 @@ private void addEntry() { mChart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); // // // this automatically refreshes the chart (calls invalidate()) - mChart.moveViewTo(data.getXValCount()-7, 50f, AxisDependency.LEFT); + mChart.moveViewTo(data.getEntryCount()-7, 50f, AxisDependency.LEFT); } } @@ -114,14 +114,14 @@ private void addDataSet() { // create 10 yPx-vals ArrayList yVals = new ArrayList(); - if(data.getXValCount() == 0) { + if(data.getEntryCount() == 0) { // add 10 xPx-entries for (int i = 0; i < 10; i++) { - data.addXValue(new XAxisValue(i, i + "")); + //data.addXValue(new XAxisValue(i, i + "")); } } - for (int i = 0; i < data.getXValCount(); i++) { + for (int i = 0; i < data.getEntryCount(); i++) { yVals.add(new Entry((float) (Math.random() * 50f) + 50f * count, i)); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index ac3c6035ff..4845af0128 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -250,7 +250,6 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -259,7 +258,7 @@ private void setData(int count, float range) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); + BarData data = new BarData(dataSets); data.setValueTextSize(10f); data.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index ab43c195ac..bfe3fabbe9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -273,7 +273,7 @@ private void setData(int count, float range) { set1.setCircleRadius(4f); // create a data object with the datasets - LineData data = new LineData(xVals, set1); + LineData data = new LineData(set1); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index ed3f86b921..0bff13fe87 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -357,7 +357,6 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -391,7 +390,7 @@ private void setData(int count, float range) { dataSets.add(set1); // add the datasets // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(dataSets); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9644dbd23a..45ae9ba8bd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -319,7 +319,6 @@ private void setData(int count, float range) { set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); set1.setYVals(yVals1); set2.setYVals(yVals2); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -358,7 +357,7 @@ private void setData(int count, float range) { dataSets.add(set2); // create a data object with the datasets - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(dataSets); data.setValueTextColor(Color.WHITE); data.setValueTextSize(9f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index a45baab65d..7b7fc8e0d9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -272,13 +272,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < 10; i++) { - - long timeLong = 10000 + i * 1000; - xVals.add(new XAxisValue(timeLong, i + "")); - } - ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { @@ -306,7 +299,7 @@ private void setData(int count, float range) { set1.setDrawCircleHole(false); // create a data object with the datasets - LineData data = new LineData(xVals, set1); + LineData data = new LineData(set1); data.setValueTextColor(Color.WHITE); data.setValueTextSize(9f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 7cbd00a414..ce58acaf41 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -142,7 +142,7 @@ private BarData generateData(int cnt) { ArrayList sets = new ArrayList(); sets.add(d); - BarData cd = new BarData(getMonths(), sets); + BarData cd = new BarData(sets); cd.setBarWidth(0.9f); return cd; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 34389e8260..0e273596fe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.listviewitems.BarChartItem; @@ -125,7 +126,7 @@ private LineData generateDataLine(int cnt) { sets.add(d1); sets.add(d2); - LineData cd = new LineData(getMonths(), sets); + LineData cd = new LineData(sets); return cd; } @@ -146,7 +147,7 @@ private BarData generateDataBar(int cnt) { d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setHighLightAlpha(255); - BarData cd = new BarData(getMonths(), d); + BarData cd = new BarData(d); cd.setBarWidth(0.9f); return cd; } @@ -158,10 +159,10 @@ private BarData generateDataBar(int cnt) { */ private PieData generateDataPie(int cnt) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList(); for (int i = 0; i < 4; i++) { - entries.add(new Entry(i, (int) (Math.random() * 70) + 30)); + entries.add(new PieEntry((float) ((Math.random() * 70) + 30), "Quarter " + (i+1))); } PieDataSet d = new PieDataSet(entries, ""); @@ -170,7 +171,7 @@ private PieData generateDataPie(int cnt) { d.setSliceSpace(2f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); - PieData cd = new PieData(getQuarters(), d); + PieData cd = new PieData(d); return cd; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index e890773750..52e0611a23 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -189,11 +189,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress())); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - xVals.add(new XAxisValue(i, i+"")); - } - ArrayList dataSets = new ArrayList(); for (int z = 0; z < 3; z++) { @@ -220,7 +215,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(dataSets); mChart.setData(data); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index eedec87e5c..18b5f42d3c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -93,11 +93,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add(new XAxisValue(i, i + "")); - } - ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -119,7 +114,7 @@ private void setData(int count, float range) { set1.setDrawFilled(false); // create a data object with the datasets - LineData data = new LineData(xVals, set1); + LineData data = new LineData(set1); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 601a4e6140..2f2997542b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -187,20 +188,15 @@ private void setData(int count, float range) { float mult = range; - ArrayList yVals1 = new ArrayList(); + ArrayList yVals1 = new ArrayList(); // IMPORTANT: In a PieChart, no values (Entry) should have the same // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < count + 1; i++) { - yVals1.add(new Entry(i, (float) (Math.random() * mult) + mult / 5)); + yVals1.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); } - ArrayList xVals = new ArrayList(); - - for (int i = 0; i < count + 1; i++) - xVals.add(new XAxisValue(mParties[i % mParties.length])); - PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); @@ -229,7 +225,7 @@ private void setData(int count, float range) { dataSet.setColors(colors); //dataSet.setSelectionShift(0f); - PieData data = new PieData(xVals, dataSet); + PieData data = new PieData(dataSet); data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 119fb8ba9b..0472b22c50 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -23,6 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.PercentFormatter; import com.github.mikephil.charting.highlight.Highlight; @@ -183,20 +184,15 @@ private void setData(int count, float range) { float mult = range; - ArrayList yVals1 = new ArrayList(); + ArrayList yVals1 = new ArrayList(); // IMPORTANT: In a PieChart, no values (Entry) should have the same // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < count + 1; i++) { - yVals1.add(new Entry((float) (Math.random() * mult) + mult / 5, i)); + yVals1.add(new PieEntry((float) (Math.random() * mult) + mult / 5, mParties[i % mParties.length])); } - ArrayList xVals = new ArrayList(); - - for (int i = 0; i < count + 1; i++) - xVals.add(new XAxisValue(mParties[i % mParties.length])); - PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); @@ -232,7 +228,7 @@ private void setData(int count, float range) { // dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); - PieData data = new PieData(xVals, dataSet); + PieData data = new PieData(dataSet); data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.BLACK); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index e843e09f08..c8b478ed7e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -204,11 +204,6 @@ public void setData() { yVals2.add(new Entry(i, val)); } - ArrayList xVals = new ArrayList(); - - for (int i = 0; i < cnt; i++) - xVals.add(new XAxisValue(mParties[i % mParties.length])); - RadarDataSet set1 = new RadarDataSet(yVals1, "Set 1"); set1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); set1.setFillColor(ColorTemplate.VORDIPLOM_COLORS[0]); @@ -225,7 +220,7 @@ public void setData() { sets.add(set1); sets.add(set2); - RadarData data = new RadarData(xVals, sets); + RadarData data = new RadarData(sets); data.setValueTypeface(tf); data.setValueTextSize(8f); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 4edf885c94..eb8701c5ad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -140,8 +140,8 @@ private void addEntry() { } // add a new xPx-yValue first - data.addXValue(new XAxisValue(data.getXValCount() ,mMonths[data.getXValCount() % 12] + " " - + (year + data.getXValCount() / 12))); +// data.addXValue(new XAxisValue(data.getXValCount() ,mMonths[data.getXValCount() % 12] + " " +// + (year + data.getXValCount() / 12))); data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); @@ -153,7 +153,7 @@ private void addEntry() { // mChart.setVisibleYRange(30, AxisDependency.LEFT); // move to the latest entry - mChart.moveViewToX(data.getXValCount() - 121); + mChart.moveViewToX(data.getEntryCount() - 121); // this automatically refreshes the chart (calls invalidate()) // mChart.moveViewTo(data.getXValCount()-7, 55f, diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 2614a015fd..dd317384fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -163,11 +163,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add(new XAxisValue(i, i + "")); - } - ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); @@ -210,7 +205,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set3); // create a data object with the datasets - ScatterData data = new ScatterData(xVals, dataSets); + ScatterData data = new ScatterData(dataSets); data.setValueTypeface(tf); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 8c8ae3bb0a..e91720b66f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -52,19 +52,17 @@ protected void onCreate(Bundle savedInstanceState) { private void setData(int count) { ArrayList yVals = new ArrayList(); - ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * count) + 15; yVals.add(new BarEntry(i, (int) val)); - xVals.add(new XAxisValue(i, (int) val + "")); } BarDataSet set = new BarDataSet(yVals, "Data Set"); set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setDrawValues(false); - BarData data = new BarData(xVals, set); + BarData data = new BarData(set); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index e5d7ce1076..8621611f80 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -185,11 +185,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add(new XAxisValue(i, mMonths[i % mMonths.length])); - } - ArrayList yVals1 = new ArrayList(); for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { @@ -207,7 +202,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); - mChart.getData().setXVals(xVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -218,7 +212,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); - BarData data = new BarData(xVals, dataSets); + BarData data = new BarData(dataSets); data.setValueFormatter(new MyValueFormatter()); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index a8834f56ca..7fadf7e13a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -102,13 +102,8 @@ protected void onCreate(Bundle savedInstanceState) { }); String []xLabels = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; - List xVals = new ArrayList(); - for(int i = 0; i < xLabels.length; i++) { - xVals.add(new XAxisValue(i, xLabels[i])); - } - - BarData data = new BarData(xVals, set); + BarData data = new BarData(set); data.setBarWidth(0.8f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 29bd091c6e..6edd7e2bea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.data.XAxisValue; @@ -63,7 +64,7 @@ protected BarData generateBarData(int dataSets, float range, int count) { sets.add(ds); } - BarData d = new BarData(ChartData.generateXVals(0, count), sets); + BarData d = new BarData(sets); d.setValueTypeface(tf); return d; } @@ -90,7 +91,7 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) sets.add(ds); } - ScatterData d = new ScatterData(ChartData.generateXVals(0, count), sets); + ScatterData d = new ScatterData(sets); d.setValueTypeface(tf); return d; } @@ -103,16 +104,10 @@ protected PieData generatePieData() { int count = 4; - ArrayList entries1 = new ArrayList(); - ArrayList xVals = new ArrayList(); - - xVals.add(new XAxisValue("Quarter 1")); - xVals.add(new XAxisValue("Quarter 2")); - xVals.add(new XAxisValue("Quarter 3")); - xVals.add(new XAxisValue("Quarter 4")); + ArrayList entries1 = new ArrayList(); for(int i = 0; i < count; i++) { - entries1.add(new Entry((float) (Math.random() * 60) + 40, i)); + entries1.add(new PieEntry((float) ((Math.random() * 60) + 40), "Quarter " + (i+1))); } PieDataSet ds1 = new PieDataSet(entries1, "Quarterly Revenues 2015"); @@ -121,7 +116,7 @@ protected PieData generatePieData() { ds1.setValueTextColor(Color.WHITE); ds1.setValueTextSize(12f); - PieData d = new PieData(xVals, ds1); + PieData d = new PieData(ds1); d.setValueTypeface(tf); return d; @@ -159,7 +154,7 @@ protected LineData generateLineData() { int max = Math.max(sets.get(0).getEntryCount(), sets.get(1).getEntryCount()); - LineData d = new LineData(ChartData.generateXVals(0, max), sets); + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } @@ -199,7 +194,7 @@ protected LineData getComplexity() { sets.add(ds3); sets.add(ds4); - LineData d = new LineData(ChartData.generateXVals(0, ds1.getEntryCount()), sets); + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 599c7f9a29..3b57ca9ceb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RadarData data = new RadarData(getYears(), dataSets); + RadarData data = new RadarData(dataSets); styleData(data); // set data diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java deleted file mode 100644 index cc0fde6e6f..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/XAxisValue.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.github.mikephil.charting.data; - -/** - * Created by Philipp Jahoda on 03/04/16. - */ -public class XAxisValue { - - /** - * the label that describes this yValue - */ - private String mLabel = ""; - - /** - * the position of this yValue on the xPx-axis - */ - private double mPosition; - - /** - * Constructor only with label. This is relevant for pie and radarchart. - * - * @param label the xPx-axis label of this yValue - */ - public XAxisValue(String label) { - this.mLabel = label; - } - - /** - * Constructor. - * - * @param xPosition the position of this yValue on the xPx-axis - * @param label the xPx-axis label of this yValue - */ - public XAxisValue(double xPosition, String label) { - this.mLabel = label; - this.mPosition = xPosition; - } - - /** - * Sets both xPx-position and label. - * - * @param xPosition - * @param label - */ - public void set(double xPosition, String label) { - this.mLabel = label; - this.mPosition = xPosition; - } - - /** - * Returns the position (xPx) of the yValue on the xPx-axis. - * - * @return - */ - public double getPosition() { - return mPosition; - } - - /** - * Returns the xPx-axis label of this yValue. - * - * @return - */ - public String getLabel() { - return mLabel; - } -} From 8e2355c78f315679395d38283497e07109fe4839 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 18:10:07 +0200 Subject: [PATCH 0923/1390] Remove all XAxisValue imports and dependencies --- .../mpchartexample/AnotherBarActivity.java | 1 - .../mpchartexample/BarChartActivity.java | 1 - .../BarChartActivityMultiDataset.java | 1 - .../mpchartexample/BarChartActivitySinus.java | 3 - .../BarChartPositiveNegative.java | 1 - .../mpchartexample/BubbleChartActivity.java | 1 - .../CandleStickChartActivity.java | 1 - .../mpchartexample/CombinedChartActivity.java | 1 - .../CubicLineChartActivity.java | 7 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 3 +- .../HorizontalBarChartActivity.java | 12 +-- .../InvertedLineChartActivity.java | 5 +- .../mpchartexample/LineChartActivity1.java | 3 - .../mpchartexample/LineChartActivity2.java | 6 -- .../LineChartActivityColored.java | 2 - .../mpchartexample/LineChartTime.java | 1 - .../MultiLineChartActivity.java | 1 - .../mpchartexample/PerformanceLineChart.java | 1 - .../mpchartexample/PieChartActivity.java | 5 +- .../PiePolylineChartActivity.java | 1 - .../mpchartexample/RadarChartActivitry.java | 1 - .../RealtimeLineChartActivity.java | 3 +- .../mpchartexample/ScatterChartActivity.java | 1 - .../mpchartexample/ScrollViewActivity.java | 1 - .../mpchartexample/StackedBarActivity.java | 1 - .../StackedBarActivityNegative.java | 7 +- .../custom/MyCustomXAxisValueFormatter.java | 2 +- .../custom/MyFillFormatter.java | 2 +- .../fragments/ScatterChartFrag.java | 3 +- .../fragments/SimpleFragment.java | 2 - .../mpchartexample/notimportant/DemoBase.java | 92 +++++++++---------- .../notimportant/MainActivity.java | 2 - .../realm/RealmBaseActivity.java | 3 - .../charting/charts/BarLineChartBase.java | 3 +- .../mikephil/charting/charts/Chart.java | 1 - .../mikephil/charting/components/XAxis.java | 89 +++++++++--------- .../mikephil/charting/data/ChartData.java | 32 +++---- .../charting/data/realm/base/RealmUtils.java | 52 +++++------ .../charting/jobs/AnimatedZoomJob.java | 8 +- .../mikephil/charting/jobs/ZoomJob.java | 2 +- .../charting/renderer/LegendRenderer.java | 1 - .../charting/renderer/XAxisRenderer.java | 2 +- .../XAxisRendererHorizontalBarChart.java | 1 - .../renderer/XAxisRendererRadarChart.java | 4 +- 45 files changed, 147 insertions(+), 227 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 2ab4868b2a..f327d4382c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -16,7 +16,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 753157c7f4..9a7de90190 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -28,7 +28,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index c9f16aec0b..7d0fa93790 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index fe32a1e2f7..09c03e3cef 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.FileUtils; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -210,12 +209,10 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count) { - List xVals = new ArrayList(); ArrayList entries = new ArrayList(); for (int i = 0; i < count; i++) { entries.add(mSinusData.get(i)); - xVals.add(new XAxisValue(i, i+"")); } BarDataSet set; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index ceb699561e..6c270a1e0f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -14,7 +14,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 27050469b7..63107114b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index fe76c9e2cb..35af7306b0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -20,7 +20,6 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 12923422dc..9c53fa7e85 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -27,7 +27,6 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index e82c445987..0e337219f1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -3,9 +3,7 @@ import android.graphics.Color; import android.graphics.Typeface; -import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.support.v4.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; @@ -20,13 +18,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 9e2ba71981..ba1fc3073c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -16,10 +16,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnDrawListener; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index c040d12d7d..48aace6cb4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -13,11 +13,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 4845af0128..fd741f846c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -25,12 +25,9 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -236,13 +233,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { ArrayList yVals1 = new ArrayList(); - ArrayList xVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - xVals.add(new XAxisValue(i, mMonths[i % 12])); - float val = (float) (Math.random() * range); - yVals1.add(new BarEntry(i, val)); - } BarDataSet set1; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index bfe3fabbe9..fe0a4cc6f1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -19,10 +19,9 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -254,7 +253,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -263,7 +261,6 @@ private void setData(int count, float range) { // ((mult * // 0.1) / 10); yVals.add(new Entry(val, i)); - xVals.add(new XAxisValue(i, (i % 30) + "/" + (i % 12) + "/14")); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 0bff13fe87..3a06bdeeb9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -27,7 +27,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; @@ -338,7 +337,6 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); ArrayList yVals = new ArrayList(); for (int i = 0; i < count; i++) { @@ -348,7 +346,6 @@ private void setData(int count, float range) { // ((mult * // 0.1) / 10);xPx yVals.add(new Entry(i, val)); - xVals.add(new XAxisValue(i, i + "")); } LineDataSet set1; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 45ae9ba8bd..5423d8fc20 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -23,7 +23,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -286,11 +285,6 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add(new XAxisValue(i, i + "")); - } - ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 0474ea6508..c452dda6bb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -11,8 +11,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 7b7fc8e0d9..9a10cf3e76 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -22,7 +22,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 52e0611a23..d354aedc5b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -16,7 +16,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 18b5f42d3c..e6b6f6444e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 2f2997542b..38d4799b99 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -24,12 +24,11 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.formatter.PercentFormatter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.formatter.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 0472b22c50..30a1dcd238 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -24,7 +24,6 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.PercentFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index c8b478ed7e..672fa2b261 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -17,7 +17,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index eb8701c5ad..ac8cdf568d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -19,11 +19,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; public class RealtimeLineChartActivity extends DemoBase implements diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index dd317384fa..5e4dcb37d4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -20,7 +20,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index e91720b66f..3d9f07f85d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 8621611f80..fa6808e23f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 7fadf7e13a..dac526041a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -19,13 +19,12 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; +import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; -import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index ed25ba090a..4cfa6d4d83 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,7 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.utils.ViewPortHandler; import com.github.mikephil.charting.formatter.XAxisValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; /** * Created by Philipp Jahoda on 14/09/15. diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index 2ca92f61eb..1c4d450167 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -1,8 +1,8 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; /** * Created by Philipp Jahoda on 12/09/15. diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index a93038c1e2..652a796321 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -1,4 +1,5 @@ package com.xxmassdeveloper.mpchartexample.fragments; + import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -9,8 +10,8 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 6edd7e2bea..2e837b1a19 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -22,7 +21,6 @@ import com.github.mikephil.charting.data.PieEntry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index 25d9dd450f..fb3eb51cf9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -3,12 +3,8 @@ import android.support.v4.app.FragmentActivity; -import com.github.mikephil.charting.data.XAxisValue; import com.xxmassdeveloper.mpchartexample.R; -import java.util.ArrayList; -import java.util.List; - /** * Baseclass of all Activities of the Demo Application. * @@ -28,50 +24,50 @@ public abstract class DemoBase extends FragmentActivity { }; - protected ArrayList getMonths() { - - ArrayList m = new ArrayList(); - m.add(new XAxisValue(0, "Jan")); - m.add(new XAxisValue(1, "Feb")); - m.add(new XAxisValue(2, "Mar")); - m.add(new XAxisValue(3, "Apr")); - m.add(new XAxisValue(4, "May")); - m.add(new XAxisValue(5, "Jun")); - m.add(new XAxisValue(6, "Jul")); - m.add(new XAxisValue(7, "Aug")); - m.add(new XAxisValue(8, "Sep")); - m.add(new XAxisValue(9, "Okt")); - m.add(new XAxisValue(10, "Nov")); - m.add(new XAxisValue(11, "Dec")); - - return m; - } - - - protected ArrayList getQuarters() { - - ArrayList q = new ArrayList(); - q.add(new XAxisValue(0, "Quarter 1")); - q.add(new XAxisValue(1, "Quarter 2")); - q.add(new XAxisValue(2, "Quarter 3")); - q.add(new XAxisValue(3, "Quarter 4")); - - return q; - } - - protected List getYears() { - ArrayList years = new ArrayList(); - - years.add(new XAxisValue(0, "2013")); - years.add(new XAxisValue(1, "2014")); - years.add(new XAxisValue(2, "2015")); - years.add(new XAxisValue(3, "2016")); - years.add(new XAxisValue(4, "2017")); - years.add(new XAxisValue(5, "2018")); - years.add(new XAxisValue(6, "2019")); - - return years; - } +// protected ArrayList getMonths() { +// +// ArrayList m = new ArrayList(); +// m.add(new XAxisValue(0, "Jan")); +// m.add(new XAxisValue(1, "Feb")); +// m.add(new XAxisValue(2, "Mar")); +// m.add(new XAxisValue(3, "Apr")); +// m.add(new XAxisValue(4, "May")); +// m.add(new XAxisValue(5, "Jun")); +// m.add(new XAxisValue(6, "Jul")); +// m.add(new XAxisValue(7, "Aug")); +// m.add(new XAxisValue(8, "Sep")); +// m.add(new XAxisValue(9, "Okt")); +// m.add(new XAxisValue(10, "Nov")); +// m.add(new XAxisValue(11, "Dec")); +// +// return m; +// } +// +// +// protected ArrayList getQuarters() { +// +// ArrayList q = new ArrayList(); +// q.add(new XAxisValue(0, "Quarter 1")); +// q.add(new XAxisValue(1, "Quarter 2")); +// q.add(new XAxisValue(2, "Quarter 3")); +// q.add(new XAxisValue(3, "Quarter 4")); +// +// return q; +// } +// +// protected List getYears() { +// ArrayList years = new ArrayList(); +// +// years.add(new XAxisValue(0, "2013")); +// years.add(new XAxisValue(1, "2014")); +// years.add(new XAxisValue(2, "2015")); +// years.add(new XAxisValue(3, "2016")); +// years.add(new XAxisValue(4, "2017")); +// years.add(new XAxisValue(5, "2018")); +// years.add(new XAxisValue(6, "2019")); +// +// return years; +// } @Override public void onBackPressed() { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index f511862353..96b383848a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -44,8 +44,6 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; -import com.xxmassdeveloper.mpchartexample.realm.RealmDatabaseActivityBar; -import com.xxmassdeveloper.mpchartexample.realm.RealmDatabaseActivityLine; import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index f84031c2db..9e3197b259 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -9,10 +9,7 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.DefaultYAxisValueFormatter; import com.github.mikephil.charting.formatter.PercentFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index a419a1274e..ae66e89fca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -721,8 +721,7 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis - .getValues().size(), scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 006cbd1c33..12c29c78da 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -33,7 +33,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index 3617cb69aa..60f7849854 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -1,14 +1,10 @@ package com.github.mikephil.charting.components; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; import com.github.mikephil.charting.formatter.XAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; -import java.util.List; - /** * Class representing the xPx-axis labels settings. Only use the setter methods to * modify it. Do not access public variables directly. Be aware that not all @@ -18,9 +14,6 @@ */ public class XAxis extends AxisBase { - /** the arraylist containing all the xPx-axis labels */ - protected List mValues = new ArrayList(); - /** * width of the xPx-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers @@ -200,41 +193,41 @@ public boolean isAvoidFirstLastClippingEnabled() { return mAvoidFirstLastClipping; } - /** - * Sets the labels for this axis. - * - * @param values - */ - public void setValues(List values) { - mValues = values; - } - - /** - * Returns the labels for this axis. - * - * @return - */ - public List getValues() { - return mValues; - } - - /** - * Adds a new xPx-yValue to the chart data. - * - * @param xVal - */ - public void addXValue(XAxisValue xVal) { - mValues.add(xVal); - } - - /** - * Removes the xPx-yValue at the specified index. - * - * @param index - */ - public void removeXValue(int index) { - mValues.remove(index); - } +// /** +// * Sets the labels for this axis. +// * +// * @param values +// */ +// public void setValues(List values) { +// mValues = values; +// } +// +// /** +// * Returns the labels for this axis. +// * +// * @return +// */ +// public List getValues() { +// return mValues; +// } +// +// /** +// * Adds a new xPx-yValue to the chart data. +// * +// * @param xVal +// */ +// public void addXValue(XAxisValue xVal) { +// mValues.add(xVal); +// } +// +// /** +// * Removes the xPx-yValue at the specified index. +// * +// * @param index +// */ +// public void removeXValue(int index) { +// mValues.remove(index); +// } /** @@ -264,12 +257,12 @@ public String getLongestLabel() { String longest = ""; - for (int i = 0; i < mValues.size(); i++) { - String text = mValues.get(i).getLabel(); - - if (longest.length() < text.length()) - longest = text; - } +// for (int i = 0; i < mValues.size(); i++) { +// String text = mValues.get(i).getLabel(); +// +// if (longest.length() < text.length()) +// longest = text; +// } return longest; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index b3ea3809a3..d29456774b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -732,22 +732,22 @@ public T getFirstRight() { return null; } - /** - * Generates an xPx-values array filled with numbers in range specified by the - * parameters. Can be used for convenience. - * - * @return - */ - public static List generateXVals(int from, int to) { - - List xvals = new ArrayList(); - - for (int i = from; i < to; i++) { - xvals.add(new XAxisValue(i, i + "")); - } - - return xvals; - } +// /** +// * Generates an xPx-values array filled with numbers in range specified by the +// * parameters. Can be used for convenience. +// * +// * @return +// */ +// public static List generateXVals(int from, int to) { +// +// List xvals = new ArrayList(); +// +// for (int i = from; i < to; i++) { +// xvals.add(new XAxisValue(i, i + "")); +// } +// +// return xvals; +// } /** * Sets a custom ValueFormatter for all DataSets this data object contains. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java index 8f9b8d5310..6e7d0558bc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java @@ -1,38 +1,30 @@ package com.github.mikephil.charting.data.realm.base; -import com.github.mikephil.charting.data.XAxisValue; - -import java.util.ArrayList; -import java.util.List; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; /** * Created by Philipp Jahoda on 19/12/15. */ public final class RealmUtils { - /** - * Transforms the given Realm-ResultSet into a String array by using the provided xValuesField. - * - * @param result - * @param xPositionField - * @param xLabelField - * @return - */ - public static List toXVals(RealmResults result, String xPositionField, String xLabelField) { - - List xVals = new ArrayList(); - - for (RealmObject object : result) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - - XAxisValue val = new XAxisValue(dynamicObject.getDouble(xPositionField), dynamicObject.getString(xLabelField)); - xVals.add(val); - } - - return xVals; - } +// /** +// * Transforms the given Realm-ResultSet into a String array by using the provided xValuesField. +// * +// * @param result +// * @param xPositionField +// * @param xLabelField +// * @return +// */ +// public static List toXVals(RealmResults result, String xPositionField, String xLabelField) { +// +// List xVals = new ArrayList(); +// +// for (RealmObject object : result) { +// +// DynamicRealmObject dynamicObject = new DynamicRealmObject(object); +// +// XAxisValue val = new XAxisValue(dynamicObject.getDouble(xPositionField), dynamicObject.getString(xLabelField)); +// xVals.add(val); +// } +// +// return xVals; +// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index 293032207a..da22c92507 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -25,10 +25,10 @@ public class AnimatedZoomJob extends AnimatedViewPortJob implements Animator.Ani protected YAxis yAxis; - protected float xValCount; + protected float xAxisRange; @SuppressLint("NewApi") - public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, YAxis axis, float xValCount, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { + public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer trans, YAxis axis, float xAxisRange, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { super(viewPortHandler, scaleX, scaleY, trans, v, xOrigin, yOrigin, duration); this.zoomCenterX = zoomCenterX; @@ -37,7 +37,7 @@ public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer tran this.zoomOriginY = zoomOriginY; this.animator.addListener(this); this.yAxis = axis; - this.xValCount = xValCount; + this.xAxisRange = xAxisRange; } @Override @@ -50,7 +50,7 @@ public void onAnimationUpdate(ValueAnimator animation) { mViewPortHandler.refresh(save, view, false); float valsInView = yAxis.mAxisRange / mViewPortHandler.getScaleY(); - float xsInView = xValCount / mViewPortHandler.getScaleX(); + float xsInView = xAxisRange / mViewPortHandler.getScaleX(); pts[0] = zoomOriginX + ((zoomCenterX - xsInView / 2f) - zoomOriginX) * phase; pts[1] = zoomOriginY + ((zoomCenterY + valsInView / 2f) - zoomOriginY) * phase; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java index 108a6f3955..d9d7e99354 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java @@ -34,7 +34,7 @@ public void run() { mViewPortHandler.refresh(save, view, false); float valsInView = ((BarLineChartBase) view).getDeltaY(axisDependency) / mViewPortHandler.getScaleY(); - float xsInView = ((BarLineChartBase) view).getXAxis().getValues().size() / mViewPortHandler.getScaleX(); + float xsInView = ((BarLineChartBase) view).getXAxis().mAxisRange / mViewPortHandler.getScaleX(); pts[0] = xValue - xsInView / 2f; pts[1] = yValue + valsInView / 2f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index f5fdacc0b9..9092f42857 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 6a6fb2a045..c481b02204 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -214,7 +214,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mXAxis.getValues().size() - 1 && mXAxis.getValues().size() > 1) { + if (i == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 7990205fac..9e37f729f0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -12,7 +12,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.XAxisValue; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 71d9380e50..d09a5e805c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -41,8 +41,8 @@ public void renderAxisLabels(Canvas c) { PointF center = mChart.getCenterOffsets(); int mod = mXAxis.mAxisLabelModulus; - for (int i = 0; i < mXAxis.getValues().size(); i += mod) { - String label = mXAxis.getValues().get(i).getLabel(); + for (int i = 0; i < mXAxis.mEntryCount; i += mod) { + String label = String.valueOf(mXAxis.mEntries[i]); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; From 2d4cf0d4b7306e72a63d849e1d2feb9af8edff01 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 31 May 2016 20:33:26 +0200 Subject: [PATCH 0924/1390] Work on x-axis formatting --- .../mpchartexample/ScatterChartActivity.java | 4 ++- .../custom/MonthXAxisFormatter.java | 28 +++++++++++++++++++ .../custom/MyCustomXAxisValueFormatter.java | 9 ++++-- .../charting/components/AxisBase.java | 2 ++ .../formatter/DefaultXAxisValueFormatter.java | 8 ++++-- .../formatter/XAxisValueFormatter.java | 9 +++--- .../charting/highlight/BarHighlighter.java | 18 ++++++++---- .../charting/renderer/XAxisRenderer.java | 6 ++-- .../renderer/XAxisRendererRadarChart.java | 2 +- .../charting/utils/ViewPortHandler.java | 4 +-- 10 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 5e4dcb37d4..916b211fd9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -24,6 +24,7 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MonthXAxisFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -88,6 +89,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setDrawGridLines(false); + xl.setValueFormatter(new MonthXAxisFormatter()); } @Override @@ -188,7 +190,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); set2.setScatterShape(ScatterShape.CIRCLE); set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); - set2.setScatterShapeHoleRadius(4f); + set2.setScatterShapeHoleRadius(3f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); set3.setScatterShape(ScatterShape.CROSS); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java new file mode 100644 index 0000000000..fe1021b979 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java @@ -0,0 +1,28 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.formatter.XAxisValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; + +/** + * Created by Philipp Jahoda on 14/09/15. + */ +public class MonthXAxisFormatter implements XAxisValueFormatter { + + protected String[] mMonths = new String[] { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + }; + + public MonthXAxisFormatter() { + // maybe do something here or provide parameters in constructor + + } + + @Override + public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { + + float percent = xValue / xRange; + return mMonths[(int) (mMonths.length * percent)]; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 4cfa6d4d83..6f3c789cf8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -3,17 +3,22 @@ import com.github.mikephil.charting.formatter.XAxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.text.DecimalFormat; + /** * Created by Philipp Jahoda on 14/09/15. */ public class MyCustomXAxisValueFormatter implements XAxisValueFormatter { + private DecimalFormat mFormat; + public MyCustomXAxisValueFormatter() { // maybe do something here or provide parameters in constructor + mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override - public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { + public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { //Log.i("TRANS", "xPx: " + viewPortHandler.getTransX() + ", yPx: " + viewPortHandler.getTransY()); @@ -25,6 +30,6 @@ else if (viewPortHandler.getScaleX() > 3) else if (viewPortHandler.getScaleX() > 1) return "2"; else - return original; + return mFormat.format(xValue); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 4e3b3cc2a1..56e9d0bc9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -428,6 +428,7 @@ public boolean isAxisMinCustom() { public void setAxisMinValue(float min) { mCustomAxisMin = true; mAxisMinimum = min; + this.mAxisRange = Math.abs(mAxisMaximum - min); } /** @@ -440,6 +441,7 @@ public void setAxisMinValue(float min) { public void setAxisMaxValue(float max) { mCustomAxisMax = true; mAxisMaximum = max; + this.mAxisRange = Math.abs(max - mAxisMinimum); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java index 16277c72ed..e836f7a47e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java @@ -2,6 +2,8 @@ import com.github.mikephil.charting.utils.ViewPortHandler; +import java.text.DecimalFormat; + /** * Created by Philipp Jahoda on 14/09/15. * Default formatter class for adjusting xPx-values before drawing them. @@ -9,8 +11,10 @@ */ public class DefaultXAxisValueFormatter implements XAxisValueFormatter { + private DecimalFormat mFormat = new DecimalFormat("###,###,###,##0.0"); + @Override - public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { - return original; // just return original, no adjustments + public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { + return mFormat.format(xValue); // just return original, no adjustments } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java index d7fa386112..a58b67ebd5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java @@ -11,14 +11,15 @@ public interface XAxisValueFormatter { /** - * Returns the customized label that is drawn on the xPx-axis. + * Returns the customized label that is drawn on the x-axis. * For performance reasons, avoid excessive calculations * and memory allocations inside this method. * - * @param original the original xPx-axis label to be drawn - * @param index the xPx-index that is currently being drawn + * @param xValue the original x-value + * @param xRange the total range of the x-values + * @param xPosition the position on the x-axis where the value is drawn (in pixels) * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return */ - String getXValue(String original, int index, ViewPortHandler viewPortHandler); + String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 693fc63724..0bda142eca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -80,21 +80,27 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { float closestDistance = Float.MAX_VALUE; Entry closestEntry = null; - for(int i = 0; i < barData.getDataSets().size(); i++) { + for (int i = 0; i < barData.getDataSets().size(); i++) { IBarDataSet dataSet = barData.getDataSetByIndex(i); final Entry entry = dataSet.getEntryForXPos(xVal); - final float distance = Math.abs(xVal - entry.getX()); + if (entry != null) { - if(distance < closestDistance) { - closestDataSetIndex = i; - closestDistance = distance; - closestEntry = entry; + final float distance = Math.abs(xVal - entry.getX()); + + if (distance < closestDistance) { + closestDataSetIndex = i; + closestDistance = distance; + closestEntry = entry; + } } } + if(closestEntry == null) + return null; + return new SelectionDetail(x, y, closestEntry.getX(), closestEntry.getY(), closestDataSetIndex, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index c481b02204..0b3c4d1178 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -229,13 +229,13 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } } - drawLabel(c, label, i, x, pos, anchor, labelRotationAngleDegrees); + drawLabel(c, mXAxis.mEntries[i / 2], x, pos, anchor, labelRotationAngleDegrees); } } } - protected void drawLabel(Canvas c, String label, int xIndex, float x, float y, PointF anchor, float angleDegrees) { - String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex, mViewPortHandler); + protected void drawLabel(Canvas c, float xValue, float x, float y, PointF anchor, float angleDegrees) { + String formattedLabel = mXAxis.getValueFormatter().getXValue(xValue, mXAxis.mAxisRange, x, mViewPortHandler); Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index d09a5e805c..0f861aaa72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -49,7 +49,7 @@ public void renderAxisLabels(Canvas c) { PointF p = Utils.getPosition(center, mChart.getYRange() * factor + mXAxis.mLabelRotatedWidth / 2f, angle); - drawLabel(c, label, i, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, + drawLabel(c, 0f, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, drawLabelAnchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 4031a6323f..5c37f6eaea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -538,12 +538,12 @@ public boolean isInBounds(float x, float y) { } public boolean isInBoundsLeft(float x) { - return mContentRect.left <= x ? true : false; + return mContentRect.left <= x + 1 ? true : false; } public boolean isInBoundsRight(float x) { x = (float) ((int) (x * 100.f)) / 100.f; - return mContentRect.right >= x ? true : false; + return mContentRect.right >= x - 1 ? true : false; } public boolean isInBoundsTop(float y) { From ceda923114ba3ee95ba6bce2303317c70f36abea Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jun 2016 18:05:23 +0200 Subject: [PATCH 0925/1390] Work on horizontalbarchart rendering --- .../HorizontalBarChartActivity.java | 5 ++ .../highlight/HorizontalBarHighlighter.java | 89 ++----------------- .../charting/renderer/BarChartRenderer.java | 35 -------- .../renderer/HorizontalBarChartRenderer.java | 66 +++++++------- 4 files changed, 48 insertions(+), 147 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index fd741f846c..afe35d1e10 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -234,6 +234,11 @@ private void setData(int count, float range) { ArrayList yVals1 = new ArrayList(); + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + yVals1.add(new BarEntry(i, val)); + } + BarDataSet set1; if (mChart.getData() != null && diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 753eb5018e..982c2eb6c6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,9 +1,9 @@ package com.github.mikephil.charting.highlight; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; /** @@ -20,99 +20,26 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - final float xVal = (float) getValsForTouch(x, y).x; - final float baseNoSpace = getBase(x); - final int setCount = barData.getDataSetCount(); - int dataSetIndex = ((int)baseNoSpace) % setCount; - - if (dataSetIndex < 0) { - dataSetIndex = 0; - } else if (dataSetIndex >= setCount) { - dataSetIndex = setCount - 1; - } + PointD pos = getValsForTouch(x, y); - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y); + SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, x, y); if (selectionDetail == null) return null; - IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + IBarDataSet set = barData.getDataSetByIndex(selectionDetail.dataSetIndex); if (set.isStacked()) { - float[] pts = new float[2]; - pts[0] = y; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(selectionDetail, set, - xVal, - pts[0]); + (float) pos.y, + (float) pos.x); } return new Highlight( - xVal, + selectionDetail.xValue, selectionDetail.yValue, selectionDetail.dataIndex, selectionDetail.dataSetIndex, -1); } - -// @Override -// protected float getXForTouch(float x) { -// -// if (!mChart.getBarData().isGrouped()) { -// -// // create an array of the touch-point -// float[] pts = new float[2]; -// pts[1] = x; -// -// // take any transformer to determine the xPx-axis yValue -// mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); -// -// return (int) Math.round(pts[1]); -// } else { -// -// float baseNoSpace = getBase(x); -// -// int setCount = mChart.getBarData().getDataSetCount(); -// int xIndex = (int) baseNoSpace / setCount; -// -// int valCount = mChart.getData().getXValCount(); -// -// if (xIndex < 0) -// xIndex = 0; -// else if (xIndex >= valCount) -// xIndex = valCount - 1; -// -// return xIndex; -// } -// } - - /** - * Returns the base yPx-yValue to the corresponding xPx-touch yValue in pixels. - * - * @param y - * @return - */ - protected float getBase(float y) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = y; - - // take any transformer to determine the xPx-axis yValue - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - float yVal = pts[1]; - - int setCount = mChart.getBarData().getDataSetCount(); - - // calculate how often the group-space appears - int steps = (int) ((float) yVal / ((float) setCount + mChart.getBarData().getGroupSpace())); - - float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; - - float baseNoSpace = (float) yVal - groupSpaceSum; - return baseNoSpace; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index f01d3d3ab3..7aeec4ce90 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -167,33 +167,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { } } - protected void prepareBarHighlight(float y1, float y2, float interval, int entryIndex, int dataSetIndex, int - dataSetCount, float barSpace, float groupSpace, Transformer trans) { - - float barWidth = interval / dataSetCount; - - float groupSpaceWidth = dataSetCount <= 1 ? 0 : barWidth * groupSpace; - float newInterval = (interval - groupSpaceWidth); - float newBarWidth = newInterval / dataSetCount; - - float barSpaceWidth = newBarWidth * barSpace; - float barSpaceWidthHalf = barSpaceWidth / 2f; - - float groupSpaceWidthHalf = groupSpaceWidth / 2f; - float dataSetSpace = dataSetCount <= 1 ? 0 : (newInterval / dataSetCount) * dataSetIndex; - - float x = interval * entryIndex + dataSetSpace; - - float left = x + groupSpaceWidthHalf + barSpaceWidthHalf; - float right = left + newBarWidth - barSpaceWidth; - float top = y1; - float bottom = y2; - - mBarRect.set(left, top, right, bottom); - - trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); - } - protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) { float left = x - barWidthHalf; @@ -439,14 +412,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } - public float[] getTransformedValues(Transformer trans, IBarDataSet data, - int dataSetIndex) { -// return trans.generateTransformedValuesBarChart(data, dataSetIndex, -// mChart.getBarData(), -// mAnimator.getPhaseY()); - return null; - } - protected boolean passesCheck() { return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 347d3487fe..8c1d64dd73 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -65,6 +65,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setPhases(phaseX, phaseY); buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); + buffer.setBarWidth(mChart.getBarData().getBarWidth()); buffer.feed(dataSet); @@ -124,25 +125,26 @@ public void drawValues(Canvas c) { ValueFormatter formatter = dataSet.getValueFormatter(); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - - float[] valuePoints = getTransformedValues(trans, dataSet, i); + // get the buffer + BarBuffer buffer = mBarBuffers[i]; // if only single values are drawn (sum) if (!dataSet.isStacked()) { - for (int j = 0; j < valuePoints.length * mAnimator.getPhaseX(); j += 2) { + for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) { + + float y = (buffer.buffer[j + 1] + buffer.buffer[j + 3]) / 2f; - if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) + if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 1])) break; - if (!mViewPortHandler.isInBoundsX(valuePoints[j])) + if (!mViewPortHandler.isInBoundsX(buffer.buffer[j])) continue; - if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) continue; - BarEntry e = dataSet.getEntryForIndex(j / 2); + BarEntry e = dataSet.getEntryForIndex(j / 4); float val = e.getY(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); @@ -156,17 +158,23 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, formattedValue, valuePoints[j] + (val >= 0 ? posOffset : negOffset), - valuePoints[j + 1] + halfTextHeight, dataSet.getValueTextColor(j / 2)); + drawValue(c, formattedValue, buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset), + y + halfTextHeight, dataSet.getValueTextColor(j / 2)); } // if each yValue of a potential stack should be drawn } else { - for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + int bufferIndex = 0; + int index = 0; - BarEntry e = dataSet.getEntryForIndex(j / 2); + while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) { + BarEntry e = dataSet.getEntryForIndex(index); + + int color = dataSet.getValueTextColor(index); float[] vals = e.getYVals(); // we still draw stacked bars, but there is one @@ -174,13 +182,13 @@ public void drawValues(Canvas c) { // in between if (vals == null) { - if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) + if (!mViewPortHandler.isInBoundsTop(buffer.buffer[bufferIndex + 1])) break; - if (!mViewPortHandler.isInBoundsX(valuePoints[j])) + if (!mViewPortHandler.isInBoundsX(buffer.buffer[bufferIndex])) continue; - if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1])) continue; float val = e.getY(); @@ -196,9 +204,9 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, formattedValue, valuePoints[j] + drawValue(c, formattedValue, buffer.buffer[bufferIndex + 2] + (e.getY() >= 0 ? posOffset : negOffset), - valuePoints[j + 1] + halfTextHeight, dataSet.getValueTextColor(j / 2)); + buffer.buffer[bufferIndex + 1] + halfTextHeight, color); } else { @@ -242,7 +250,7 @@ public void drawValues(Canvas c) { float x = transformed[k] + (val >= 0 ? posOffset : negOffset); - float y = valuePoints[j + 1]; + float y = (buffer.buffer[bufferIndex + 1] + buffer.buffer[bufferIndex + 3]) / 2f; if (!mViewPortHandler.isInBoundsTop(y)) break; @@ -253,9 +261,12 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(y)) continue; - drawValue(c, formattedValue, x, y + halfTextHeight, dataSet.getValueTextColor(j / 2)); + drawValue(c, formattedValue, x, y + halfTextHeight, color); } } + + bufferIndex = vals == null ? bufferIndex + 4 : bufferIndex + 4 * vals.length; + index++; } } } @@ -267,24 +278,17 @@ protected void drawValue(Canvas c, String valueText, float x, float y, int color c.drawText(valueText, x, y, mValuePaint); } - protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, - Transformer trans) { + @Override + protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) { - float top = x - 0.5f + barspaceHalf; - float bottom = x + 0.5f - barspaceHalf; + float top = x - barWidthHalf; + float bottom = x + barWidthHalf; float left = y1; float right = y2; mBarRect.set(left, top, right, bottom); - trans.rectValueToPixelHorizontal(mBarRect, mAnimator.getPhaseY()); - } - - @Override - public float[] getTransformedValues(Transformer trans, IBarDataSet data, - int dataSetIndex) { - return trans.generateTransformedValuesHorizontalBarChart(data, dataSetIndex, - mChart.getBarData(), mAnimator.getPhaseY()); + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); } @Override From 6d23f7a3aae3163ccd120912c323d94d5580de53 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jun 2016 21:40:37 +0200 Subject: [PATCH 0926/1390] Work on horizontal highlighting --- .../charting/highlight/BarHighlighter.java | 24 ------------------- .../highlight/HorizontalBarHighlighter.java | 2 +- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 0bda142eca..2768728dce 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -47,30 +47,6 @@ public Highlight getHighlight(float x, float y) { -1); } -// @Override -// protected float getXForTouch(float x) { -// -// if (!mChart.getBarData().isGrouped()) { -// return super.getXForTouch(x); -// } else { -// return getBase(x); -// -// float baseNoSpace = getBase(x); -// -// int setCount = mChart.getBarData().getDataSetCount(); -// int xIndex = (int) baseNoSpace / setCount; -// -// int valCount = mChart.getData().getXValCount(); -// -// if (xIndex < 0) -// xIndex = 0; -// else if (xIndex >= valCount) -// xIndex = valCount - 1; -// -// return xIndex; -// } -// } - @Override protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 982c2eb6c6..868f703a34 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -20,7 +20,7 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - PointD pos = getValsForTouch(x, y); + PointD pos = getValsForTouch(y, x); SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, x, y); if (selectionDetail == null) From 71be944ea9516abad2f7405c5e391311b98f6bd3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jun 2016 22:09:58 +0200 Subject: [PATCH 0927/1390] Fix offset related issues --- .../com/xxmassdeveloper/mpchartexample/LineChartActivity2.java | 2 +- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 3 +-- .../com/github/mikephil/charting/renderer/XAxisRenderer.java | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 5423d8fc20..d92de857ce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -102,7 +102,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); - xAxis.setTextSize(12f); + xAxis.setTextSize(11f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index ae66e89fca..6cbb7298dd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -347,8 +347,7 @@ public void notifyDataSetChanged() { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted()); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted()); - - //mXAxisRenderer.computeSize(mData.getXValMaximumLength(), mData.getXVals()); + mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); if (mLegend != null) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 0b3c4d1178..565c176399 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -133,7 +133,7 @@ public void renderAxisLabels(Canvas c) { if (mXAxis.getPosition() == XAxisPosition.TOP) { drawLabels(c, mViewPortHandler.contentTop() - yoffset, - new PointF(0.5f, 1.0f)); + new PointF(0.5f, 0.9f)); } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { From 92cfe0a482a5c4cd85416db4cdd9725cb3f6326a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jun 2016 22:14:38 +0200 Subject: [PATCH 0928/1390] Remove xmin and xmax from renderer --- .../charting/charts/BarLineChartBase.java | 3 --- .../renderer/CombinedChartRenderer.java | 7 ------ .../mikephil/charting/renderer/Renderer.java | 24 ------------------- 3 files changed, 34 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 6cbb7298dd..fd8d07874a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -199,9 +199,6 @@ protected void onDraw(Canvas canvas) { long starttime = System.currentTimeMillis(); calcModulus(); - mXAxisRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); - mRenderer.calcXBounds(this, mXAxis.mAxisLabelModulus); - // execute all drawing commands drawGridBackground(canvas); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 982e22e36a..c96db83df6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -134,16 +134,9 @@ else if (renderer instanceof BubbleChartRenderer) } renderer.drawHighlighted(c, dataIndices.toArray(new Highlight[dataIndices.size()])); - } } - @Override - public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { - for (DataRenderer renderer : mRenderers) - renderer.calcXBounds(chart, xAxisModulus); - } - /** * Returns the sub-renderer object at the specified index. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java index f8d111d5b2..dcaaeee2a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java @@ -16,12 +16,6 @@ public abstract class Renderer { */ protected ViewPortHandler mViewPortHandler; - /** the minimum yValue on the xPx-axis that should be plotted */ - protected float mMinX = 0; - - /** the maximum yValue on the xPx-axis that should be plotted */ - protected float mMaxX = 0; - public Renderer(ViewPortHandler viewPortHandler) { this.mViewPortHandler = viewPortHandler; } @@ -42,22 +36,4 @@ protected boolean fitsBounds(float val, float min, float max) { else return true; } - - /** - * Calculates the minimum and maximum xPx-yValue the chart can currently - * display (with the given zoom level). -> mMinX, mMaxX - * - * @param dataProvider - * @param xAxisModulus - */ - public void calcXBounds(BarLineScatterCandleBubbleDataProvider dataProvider, int xAxisModulus) { - - float low = dataProvider.getLowestVisibleX(); - float high = dataProvider.getHighestVisibleX(); - - int subLow = (low % xAxisModulus == 0) ? xAxisModulus : 0; - - mMinX = Math.max((low / xAxisModulus) * (xAxisModulus) - subLow, 0); - mMaxX = Math.min((high / xAxisModulus) * (xAxisModulus) + xAxisModulus, dataProvider.getXChartMax()); - } } From 90dc54a6853e7e82262c6ffeda006994bbc23b46 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jun 2016 22:30:02 +0200 Subject: [PATCH 0929/1390] Fix performance issue in linechart --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- .../com/github/mikephil/charting/charts/HorizontalBarChart.java | 2 +- .../main/java/com/github/mikephil/charting/utils/FileUtils.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index fd8d07874a..bac69f2633 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1312,7 +1312,7 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float public float getLowestVisibleX() { PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); - return (float) Math.min(mXAxis.mAxisMinimum, pos.x); + return (float) Math.max(mXAxis.mAxisMinimum, pos.x); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index d8fd26da4e..d917b8547d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -205,7 +205,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { public float getLowestVisibleX() { PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); - return (float) Math.min(mXAxis.mAxisMinimum, pos.y); + return (float) Math.max(mXAxis.mAxisMinimum, pos.y); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java index 31fbb10805..dac8573d5d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java @@ -242,7 +242,7 @@ public static List loadBarEntriesFromAssets(AssetManager am, String pa // process line String[] split = line.split("#"); - entries.add(new BarEntry(Float.parseFloat(split[1]), Integer.parseInt(split[0]))); + entries.add(new BarEntry(Float.parseFloat(split[1]), Float.parseFloat(split[0]))); line = reader.readLine(); } From d2aa701eb2597e6735bd701b2e4bd2fc9de88c39 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 09:50:06 +0200 Subject: [PATCH 0930/1390] Work on x-axis rendering and formatters --- .../mpchartexample/AnotherBarActivity.java | 1 - .../mpchartexample/BarChartActivity.java | 1 - .../BarChartPositiveNegative.java | 1 - .../CandleStickChartActivity.java | 1 - .../mpchartexample/LineChartActivity2.java | 1 - .../mpchartexample/LineChartTime.java | 1 - .../RealtimeLineChartActivity.java | 1 - .../mikephil/charting/charts/RadarChart.java | 1 - .../charting/components/AxisBase.java | 82 +++++++ .../mikephil/charting/components/XAxis.java | 50 ++--- .../mikephil/charting/components/YAxis.java | 105 --------- .../formatter/DefaultAxisValueFormatter.java | 30 +++ .../formatter/DefaultValueFormatter.java | 2 +- .../formatter/DefaultXAxisValueFormatter.java | 6 +- .../formatter/DefaultYAxisValueFormatter.java | 21 +- .../charting/renderer/AxisRenderer.java | 97 ++++++++- .../charting/renderer/XAxisRenderer.java | 64 +++--- .../charting/renderer/YAxisRenderer.java | 202 +++++++++--------- .../renderer/YAxisRendererRadarChart.java | 51 ++--- 19 files changed, 384 insertions(+), 334 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index f327d4382c..b7c2a50b06 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -61,7 +61,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setSpaceBetweenLabels(0); xAxis.setDrawGridLines(false); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 9a7de90190..800ba6b828 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -85,7 +85,6 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); - xAxis.setSpaceBetweenLabels(2); YAxisValueFormatter custom = new MyYAxisValueFormatter(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 6c270a1e0f..029e7936f5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -56,7 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); - xAxis.setSpaceBetweenLabels(2); xAxis.setTextColor(Color.LTGRAY); xAxis.setTextSize(13f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 35af7306b0..8eabc4be56 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -63,7 +63,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setSpaceBetweenLabels(2); xAxis.setDrawGridLines(false); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index d92de857ce..236fceb28c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -106,7 +106,6 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); - xAxis.setSpaceBetweenLabels(1); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 9a10cf3e76..8a3c0ae982 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -101,7 +101,6 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextSize(12f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); - xAxis.setSpaceBetweenLabels(1); // custom xPx-axis min / max xAxis.setAxisMinValue(5000); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index ac8cdf568d..833428e613 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -80,7 +80,6 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTextColor(Color.WHITE); xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); - xl.setSpaceBetweenLabels(5); xl.setEnabled(true); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 28f2529db6..b0adde7f69 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -86,7 +86,6 @@ protected void init() { super.init(); mYAxis = new YAxis(AxisDependency.LEFT); - mXAxis.setSpaceBetweenLabels(0); mWebLineWidth = Utils.convertDpToPixel(1.5f); mInnerWebLineWidth = Utils.convertDpToPixel(0.75f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 56e9d0bc9f..754ece5257 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -5,6 +5,7 @@ import android.graphics.DashPathEffect; import android.util.Log; +import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -45,6 +46,24 @@ public abstract class AxisBase extends ComponentBase { */ private int mLabelCount = 6; + /** + * the minimum interval between axis values + */ + protected float mGranularity = 1.0f; + + /** + * When true, axis labels are controlled by the `granularity` property. + * When false, axis values could possibly be repeated. + * This could happen if two adjacent axis values are rounded to same yValue. + * If using granularity this could be avoided by having fewer axis values visible. + */ + protected boolean mGranularityEnabled = false; + + /** + * if true, the set number of yPx-labels will be forced + */ + protected boolean mForceLabels = false; + /** * flag indicating if the grid lines for this axis should be drawn */ @@ -255,6 +274,33 @@ public void setLabelCount(int count) { count = 2; mLabelCount = count; + mForceLabels = false; + } + + /** + * sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware + * that this number is not + * fixed (if force == false) and can only be approximated. + * + * @param count the number of yPx-axis labels that sould be displayed + * @param force if enabled, the set label count will be forced, meaning that the exact + * specified count of labels will + * be drawn and evenly distributed alongside the axis - this might cause labels + * to have uneven values + */ + public void setLabelCount(int count, boolean force) { + + setLabelCount(count); + mForceLabels = force; + } + + /** + * Returns true if focing the yPx-label count is enabled. Default: false + * + * @return + */ + public boolean isForceLabelsEnabled() { + return mForceLabels; } /** @@ -266,6 +312,42 @@ public int getLabelCount() { return mLabelCount; } + /** + * @return true if granularity is enabled + */ + public boolean isGranularityEnabled() { + return mGranularityEnabled; + } + + /** + * Enabled/disable granularity control on axis yValue intervals. If enabled, the axis + * interval is not allowed to go below a certain granularity. Default: false + * + * @param enabled + */ + public void setGranularityEnabled(boolean enabled) { + mGranularityEnabled = true; + } + + /** + * @return the minimum interval between axis values + */ + public float getGranularity() { + return mGranularity; + } + + /** + * Set a minimum interval for the axis when zooming in. The axis is not allowed to go below + * that limit. This can be used to avoid label duplicating when zooming in. + * + * @param granularity + */ + public void setGranularity(float granularity) { + mGranularity = granularity; + // set this to true if it was disabled, as it makes no sense to call this method with granularity disabled + mGranularityEnabled = true; + } + /** * Adds a new LimitLine to this axis. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index 60f7849854..72a68a0ae7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -9,7 +9,7 @@ * Class representing the xPx-axis labels settings. Only use the setter methods to * modify it. Do not access public variables directly. Be aware that not all * features the XLabels class provides are suitable for the RadarChart. - * + * * @author Philipp Jahoda */ public class XAxis extends AxisBase { @@ -70,12 +70,16 @@ public class XAxis extends AxisBase { /** * Custom formatter for adjusting xPx-yValue strings */ - protected XAxisValueFormatter mXAxisValueFormatter = new DefaultXAxisValueFormatter(); + protected XAxisValueFormatter mXAxisValueFormatter; - /** the position of the xPx-labels relative to the chart */ + /** + * the position of the xPx-labels relative to the chart + */ private XAxisPosition mPosition = XAxisPosition.TOP; - /** enum for the position of the xPx-labels relative to the chart */ + /** + * enum for the position of the xPx-labels relative to the chart + */ public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE } @@ -95,7 +99,7 @@ public XAxisPosition getPosition() { /** * sets the position of the xPx-labels - * + * * @param pos */ public void setPosition(XAxisPosition pos) { @@ -118,24 +122,13 @@ public void setLabelRotationAngle(float angle) { mLabelRotationAngle = angle; } - /** - * Sets the space (in characters) that should be left out between the xPx-axis - * labels, default 4. This only applies if the number of labels that will be - * skipped in between drawn axis labels is not custom set. - * - * @param spaceCharacters - */ - public void setSpaceBetweenLabels(int spaceCharacters) { - mSpaceBetweenLabels = spaceCharacters; - } - /** * Sets the number of labels that should be skipped on the axis before the * next label is drawn. This will disable the feature that automatically * calculates an adequate space between the axis labels and set the number * of labels to be skipped to the fixed number provided by this method. Call * resetLabelsToSkip(...) to re-enable automatic calculation. - * + * * @param count */ public void setLabelsToSkip(int count) { @@ -159,25 +152,17 @@ public void resetLabelsToSkip() { /** * Returns true if a custom axis-modulus has been set that determines the * number of labels to skip when drawing. - * + * * @return */ public boolean isAxisModulusCustom() { return mIsAxisModulusCustom; } - /** - * Returns the space (in characters) that should be left out between the - * xPx-axis labels - */ - public int getSpaceBetweenLabels() { - return mSpaceBetweenLabels; - } - /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart or the screen - * + * * @param enabled */ public void setAvoidFirstLastClipping(boolean enabled) { @@ -186,7 +171,7 @@ public void setAvoidFirstLastClipping(boolean enabled) { /** * returns true if avoid-first-lastclipping is enabled, false if not - * + * * @return */ public boolean isAvoidFirstLastClippingEnabled() { @@ -238,17 +223,22 @@ public boolean isAvoidFirstLastClippingEnabled() { * @param formatter */ public void setValueFormatter(XAxisValueFormatter formatter) { - if(formatter == null) - mXAxisValueFormatter = new DefaultXAxisValueFormatter(); + if (formatter == null) + mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); else mXAxisValueFormatter = formatter; } /** * Returns the custom XAxisValueFormatter that is set for this data object. + * * @return */ public XAxisValueFormatter getValueFormatter() { + + if (mXAxisValueFormatter == null) + mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); + return mXAxisValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 347d89ce96..d2b928f71a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -31,21 +31,11 @@ public class YAxis extends AxisBase { */ private boolean mDrawTopYLabelEntry = true; - /** - * if true, the yPx-labels show only the minimum and maximum yValue - */ - protected boolean mShowOnlyMinMax = false; - /** * flag that indicates if the axis is inverted or not */ protected boolean mInverted = false; - /** - * if true, the set number of yPx-labels will be forced - */ - protected boolean mForceLabels = false; - /** * flag that indicates if the zero-line should be drawn regardless of other grid lines */ @@ -102,19 +92,6 @@ public enum YAxisLabelPosition { */ protected float mMaxWidth = Float.POSITIVE_INFINITY; - /** - * When true, axis labels are controlled by the `granularity` property. - * When false, axis values could possibly be repeated. - * This could happen if two adjacent axis values are rounded to same yValue. - * If using granularity this could be avoided by having fewer axis values visible. - */ - protected boolean mGranularityEnabled = false; - - /** - * the minimum interval between axis values - */ - protected float mGranularity = 1.0f; - /** * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. * @@ -174,42 +151,6 @@ public void setMaxWidth(float maxWidth) { mMaxWidth = maxWidth; } - /** - * @return true if granularity is enabled - */ - public boolean isGranularityEnabled() { - return mGranularityEnabled; - } - - /** - * Enabled/disable granularity control on axis yValue intervals. If enabled, the axis - * interval is not allowed to go below a certain granularity. Default: false - * - * @param enabled - */ - public void setGranularityEnabled(boolean enabled) { - mGranularityEnabled = true; - } - - /** - * @return the minimum interval between axis values - */ - public float getGranularity() { - return mGranularity; - } - - /** - * Set a minimum interval for the axis when zooming in. The axis is not allowed to go below - * that limit. This can be used to avoid label duplicating when zooming in. - * - * @param granularity - */ - public void setGranularity(float granularity) { - mGranularity = granularity; - // set this to true if it was disabled, as it makes no sense to call this method with granularity disabled - mGranularityEnabled = true; - } - /** * returns the position of the yPx-labels */ @@ -246,52 +187,6 @@ public void setDrawTopYLabelEntry(boolean enabled) { mDrawTopYLabelEntry = enabled; } - /** - * sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware - * that this number is not - * fixed (if force == false) and can only be approximated. - * - * @param count the number of yPx-axis labels that sould be displayed - * @param force if enabled, the set label count will be forced, meaning that the exact - * specified count of labels will - * be drawn and evenly distributed alongside the axis - this might cause labels - * to have uneven values - */ - public void setLabelCount(int count, boolean force) { - - setLabelCount(count); - mForceLabels = force; - } - - /** - * Returns true if focing the yPx-label count is enabled. Default: false - * - * @return - */ - public boolean isForceLabelsEnabled() { - return mForceLabels; - } - - /** - * If enabled, the YLabels will only show the minimum and maximum yValue of the chart. This - * will ignore/override the - * set label count. - * - * @param enabled - */ - public void setShowOnlyMinMax(boolean enabled) { - mShowOnlyMinMax = enabled; - } - - /** - * Returns true if showing only min and max yValue is enabled. - * - * @return - */ - public boolean isShowOnlyMinMaxEnabled() { - return mShowOnlyMinMax; - } - /** * If this is set to true, the yPx-axis is inverted which means that low values are on top of * the chart, high values diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java new file mode 100644 index 0000000000..c5b859d4a1 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -0,0 +1,30 @@ +package com.github.mikephil.charting.formatter; + +import java.text.DecimalFormat; + +/** + * Created by philipp on 02/06/16. + */ +public class DefaultAxisValueFormatter { + + /** decimalformat for formatting */ + protected DecimalFormat mFormat; + + /** + * Constructor that specifies to how many digits the yValue should be + * formatted. + * + * @param digits + */ + public DefaultAxisValueFormatter(int digits) { + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index fe92d5f4bb..00c514aff0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -15,7 +15,7 @@ public class DefaultValueFormatter implements ValueFormatter { /** decimalformat for formatting */ - private DecimalFormat mFormat; + protected DecimalFormat mFormat; /** * Constructor that specifies to how many digits the yValue should be diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java index e836f7a47e..a62f0f88be 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java @@ -9,9 +9,11 @@ * Default formatter class for adjusting xPx-values before drawing them. * This simply returns the original yValue unmodified. */ -public class DefaultXAxisValueFormatter implements XAxisValueFormatter { +public class DefaultXAxisValueFormatter extends DefaultAxisValueFormatter implements XAxisValueFormatter { - private DecimalFormat mFormat = new DecimalFormat("###,###,###,##0.0"); + public DefaultXAxisValueFormatter(int digits) { + super(digits); + } @Override public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java index 33fff63545..553362d317 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java @@ -9,27 +9,10 @@ * Default formatter used for formatting labels of the YAxis. Uses a DecimalFormat with * pre-calculated number of digits (depending on max and min yValue). */ -public class DefaultYAxisValueFormatter implements YAxisValueFormatter { +public class DefaultYAxisValueFormatter extends DefaultAxisValueFormatter implements YAxisValueFormatter { - /** decimalformat for formatting */ - private DecimalFormat mFormat; - - /** - * Constructor that specifies to how many digits the yValue should be - * formatted. - * - * @param digits - */ public DefaultYAxisValueFormatter(int digits) { - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + super(digits); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 6515f7b82b..644267cbac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -6,8 +6,10 @@ import android.graphics.Paint; import android.graphics.Paint.Style; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -17,6 +19,8 @@ */ public abstract class AxisRenderer extends Renderer { + private AxisBase mAxis; + protected Transformer mTrans; /** paint object for the grid lines */ @@ -31,10 +35,11 @@ public abstract class AxisRenderer extends Renderer { /** paint used for the limit lines */ protected Paint mLimitLinePaint; - public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans) { + public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase axis) { super(viewPortHandler); this.mTrans = trans; + this.mAxis = axis; mAxisLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -125,7 +130,95 @@ public void computeAxis(float min, float max, boolean inverted) { * * @return */ - protected abstract void computeAxisValues(float min, float max); + protected void computeAxisValues(float min, float max) { + + float yMin = min; + float yMax = max; + + int labelCount = mAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mAxis.mEntries = new float[]{}; + mAxis.mEntryCount = 0; + return; + } + + // Find out how much spacing (in yPx yValue space) between axis values + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + + // If granularity is enabled, then do not allow the interval to go below specified granularity. + // This is used to avoid repeated values when rounding values for display. + if (mAxis.isGranularityEnabled()) + interval = interval < mAxis.getGranularity() ? mAxis.getGranularity() : interval; + + // Normalize interval + double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } + + // force label count + if (mAxis.isForceLabelsEnabled()) { + + float step = (float) range / (float) (labelCount - 1); + mAxis.mEntryCount = labelCount; + + if (mAxis.mEntries.length < labelCount) { + // Ensure stops contains at least numStops elements. + mAxis.mEntries = new float[labelCount]; + } + + float v = min; + + for (int i = 0; i < labelCount; i++) { + mAxis.mEntries[i] = v; + v += step; + } + + // no forced count + } else { + + + double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; + double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); + + double f; + int i; + int n = 0; + if (interval != 0.0) { + for (f = first; f <= last; f += interval) { + ++n; + } + } + + mAxis.mEntryCount = n; + + if (mAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mAxis.mEntries = new float[n]; + } + + for (f = first, i = 0; i < n; f += interval, ++i) { + + if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) + f = 0.0; + + mAxis.mEntries[i] = (float) f; + } + } + + // set decimals + if (interval < 1) { + mAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mAxis.mDecimals = 0; + } + } /** * Draws the axis labels to the screen. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 565c176399..747d4917b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -24,7 +24,7 @@ public class XAxisRenderer extends AxisRenderer { protected XAxis mXAxis; public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans) { - super(viewPortHandler, trans); + super(viewPortHandler, trans, xAxis); this.mXAxis = xAxis; @@ -60,28 +60,30 @@ public void computeAxis(float min, float max, boolean inverted) { @Override protected void computeAxisValues(float min, float max) { - int labelCount = mXAxis.getLabelCount(); - float range = Math.abs(max - min); - - float interval = range / (labelCount - 1); - - if (mXAxis.mEntries == null || mXAxis.mEntries.length != labelCount) { - mXAxis.mEntries = new float[labelCount]; - mXAxis.mEntryCount = labelCount; - } - - mXAxis.mEntries[0] = min; - - for (int i = 1; i < labelCount; i++) { - mXAxis.mEntries[i] = min + interval * (float) i; - } - - // set decimals - if (interval < 1) { - mXAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); - } else { - mXAxis.mDecimals = 0; - } +// int labelCount = mXAxis.getLabelCount(); +// float range = Math.abs(max - min); +// +// float interval = range / (labelCount - 1); +// +// if (mXAxis.mEntries == null || mXAxis.mEntries.length != labelCount) { +// mXAxis.mEntries = new float[labelCount]; +// mXAxis.mEntryCount = labelCount; +// } +// +// mXAxis.mEntries[0] = min; +// +// for (int i = 1; i < labelCount; i++) { +// mXAxis.mEntries[i] = min + interval * (float) i; +// } +// +// // set decimals +// if (interval < 1) { +// mXAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); +// } else { +// mXAxis.mDecimals = 0; +// } + + super.computeAxisValues(min, max); computeSize(); } @@ -103,18 +105,10 @@ protected void computeSize() { labelHeight, mXAxis.getLabelRotationAngle()); - StringBuilder space = new StringBuilder(); - int xValSpaceChars = mXAxis.getSpaceBetweenLabels(); - - for (int i = 0; i < xValSpaceChars; i++) { - space.append('h'); - } - - final FSize spaceSize = Utils.calcTextSize(mAxisLabelPaint, space.toString()); - mXAxis.mLabelWidth = Math.round(labelWidth + spaceSize.width); + mXAxis.mLabelWidth = Math.round(labelWidth); mXAxis.mLabelHeight = Math.round(labelHeight); - mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width + spaceSize.width); + mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); } @@ -194,7 +188,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - float[] positions = new float[mXAxis.mEntries.length * 2]; + float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { // only fill xPx values @@ -245,7 +239,7 @@ public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; - float[] positions = new float[mXAxis.mEntries.length * 2]; + float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { // only fill xPx values diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 17cf3dc397..cf4c30ddb7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -24,7 +24,7 @@ public class YAxisRenderer extends AxisRenderer { protected Paint mZeroLinePaint; public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { - super(viewPortHandler, trans); + super(viewPortHandler, trans, yAxis); this.mYAxis = yAxis; @@ -37,106 +37,106 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t mZeroLinePaint.setStyle(Paint.Style.STROKE); } - @Override - protected void computeAxisValues(float min, float max) { - - float yMin = min; - float yMax = max; - - int labelCount = mYAxis.getLabelCount(); - double range = Math.abs(yMax - yMin); - - if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[]{}; - mYAxis.mEntryCount = 0; - return; - } - - // Find out how much spacing (in yPx yValue space) between axis values - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - - // If granularity is enabled, then do not allow the interval to go below specified granularity. - // This is used to avoid repeated values when rounding values for display. - if (mYAxis.isGranularityEnabled()) - interval = interval < mYAxis.getGranularity() ? mYAxis.getGranularity() : interval; - - // Normalize interval - double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); - int intervalSigDigit = (int) (interval / intervalMagnitude); - if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); - } - - // force label count - if (mYAxis.isForceLabelsEnabled()) { - - float step = (float) range / (float) (labelCount - 1); - mYAxis.mEntryCount = labelCount; - - if (mYAxis.mEntries.length < labelCount) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[labelCount]; - } - - float v = min; - - for (int i = 0; i < labelCount; i++) { - mYAxis.mEntries[i] = v; - v += step; - } - - // no forced count - } else { - - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { - - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; - - } else { - - double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; - double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); - - double f; - int i; - int n = 0; - if (interval != 0.0) { - for (f = first; f <= last; f += interval) { - ++n; - } - } - - mYAxis.mEntryCount = n; - - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } - - for (f = first, i = 0; i < n; f += interval, ++i) { - - if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) - f = 0.0; - - mYAxis.mEntries[i] = (float) f; - } - } - } - - // set decimals - if (interval < 1) { - mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); - } else { - mYAxis.mDecimals = 0; - } - } +// @Override +// protected void computeAxisValues(float min, float max) { +// +// float yMin = min; +// float yMax = max; +// +// int labelCount = mYAxis.getLabelCount(); +// double range = Math.abs(yMax - yMin); +// +// if (labelCount == 0 || range <= 0) { +// mYAxis.mEntries = new float[]{}; +// mYAxis.mEntryCount = 0; +// return; +// } +// +// // Find out how much spacing (in yPx yValue space) between axis values +// double rawInterval = range / labelCount; +// double interval = Utils.roundToNextSignificant(rawInterval); +// +// // If granularity is enabled, then do not allow the interval to go below specified granularity. +// // This is used to avoid repeated values when rounding values for display. +// if (mYAxis.isGranularityEnabled()) +// interval = interval < mYAxis.getGranularity() ? mYAxis.getGranularity() : interval; +// +// // Normalize interval +// double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); +// int intervalSigDigit = (int) (interval / intervalMagnitude); +// if (intervalSigDigit > 5) { +// // Use one order of magnitude higher, to avoid intervals like 0.9 or +// // 90 +// interval = Math.floor(10 * intervalMagnitude); +// } +// +// // force label count +// if (mYAxis.isForceLabelsEnabled()) { +// +// float step = (float) range / (float) (labelCount - 1); +// mYAxis.mEntryCount = labelCount; +// +// if (mYAxis.mEntries.length < labelCount) { +// // Ensure stops contains at least numStops elements. +// mYAxis.mEntries = new float[labelCount]; +// } +// +// float v = min; +// +// for (int i = 0; i < labelCount; i++) { +// mYAxis.mEntries[i] = v; +// v += step; +// } +// +// // no forced count +// } else { +// +// // if the labels should only show min and max +// if (mYAxis.isShowOnlyMinMaxEnabled()) { +// +// mYAxis.mEntryCount = 2; +// mYAxis.mEntries = new float[2]; +// mYAxis.mEntries[0] = yMin; +// mYAxis.mEntries[1] = yMax; +// +// } else { +// +// double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; +// double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); +// +// double f; +// int i; +// int n = 0; +// if (interval != 0.0) { +// for (f = first; f <= last; f += interval) { +// ++n; +// } +// } +// +// mYAxis.mEntryCount = n; +// +// if (mYAxis.mEntries.length < n) { +// // Ensure stops contains at least numStops elements. +// mYAxis.mEntries = new float[n]; +// } +// +// for (f = first, i = 0; i < n; f += interval, ++i) { +// +// if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) +// f = 0.0; +// +// mYAxis.mEntries[i] = (float) f; +// } +// } +// } +// +// // set decimals +// if (interval < 1) { +// mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); +// } else { +// mYAxis.mDecimals = 0; +// } +// } /** * draws the yPx-axis labels to the screen diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index dc79bc9aad..5dcaff1fcc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -67,44 +67,33 @@ protected void computeAxisValues(float min, float max) { // no forced count } else { - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { + final double rawCount = yMin / interval; + double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; + if (first == 0.0) // Fix for IEEE negative zero case (Where yValue == -0.0, and 0.0 == -0.0) + first = 0.0; - } else { + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - final double rawCount = yMin / interval; - double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - - if (first == 0.0) // Fix for IEEE negative zero case (Where yValue == -0.0, and 0.0 == -0.0) - first = 0.0; - - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } - if (!mYAxis.isAxisMaxCustom()) - n += 1; + if (!mYAxis.isAxisMaxCustom()) + n += 1; - mYAxis.mEntryCount = n; + mYAxis.mEntryCount = n; - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } - for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; - } + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; } } From 5110dc6349f0f06dc7502dfafe07d8e933a036b7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 09:54:04 +0200 Subject: [PATCH 0931/1390] Remove deprecated methods --- .../mpchartexample/CombinedChartActivity.java | 2 +- .../mpchartexample/CubicLineChartActivity.java | 2 +- .../mpchartexample/LineChartTime.java | 12 ++++++------ .../mpchartexample/PerformanceLineChart.java | 2 +- .../github/mikephil/charting/data/LineDataSet.java | 12 +----------- 5 files changed, 10 insertions(+), 20 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 9c53fa7e85..e9b5a6e81b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -94,7 +94,7 @@ private LineData generateLineData() { set.setCircleColor(Color.rgb(240, 238, 70)); set.setCircleRadius(5f); set.setFillColor(Color.rgb(240, 238, 70)); - set.setDrawCubic(true); + set.setMode(LineDataSet.Mode.CUBIC_BEZIER); set.setDrawValues(true); set.setValueTextSize(10f); set.setValueTextColor(Color.rgb(240, 238, 70)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 0e337219f1..6e8b0ec5d3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -286,7 +286,7 @@ private void setData(int count, float range) { // create a dataset and give it a type set1 = new LineDataSet(yVals, "DataSet 1"); - set1.setDrawCubic(true); + set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); set1.setCubicIntensity(0.2f); //set1.setDrawFilled(true); set1.setDrawCircles(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 8a3c0ae982..f12d003555 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -186,10 +186,10 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawCubicEnabled()) - set.setDrawCubic(false); + if (set.getMode() == LineDataSet.Mode.CUBIC_BEZIER) + set.setMode(LineDataSet.Mode.LINEAR); else - set.setDrawCubic(true); + set.setMode(LineDataSet.Mode.CUBIC_BEZIER); } mChart.invalidate(); break; @@ -201,10 +201,10 @@ public boolean onOptionsItemSelected(MenuItem item) { for (ILineDataSet iSet : sets) { LineDataSet set = (LineDataSet) iSet; - if (set.isDrawSteppedEnabled()) - set.setDrawStepped(false); + if (set.getMode() == LineDataSet.Mode.STEPPED) + set.setMode(LineDataSet.Mode.LINEAR); else - set.setDrawStepped(true); + set.setMode(LineDataSet.Mode.STEPPED); } mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index e6b6f6444e..14b0d7eda6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -109,7 +109,7 @@ private void setData(int count, float range) { set1.setLineWidth(0.5f); set1.setDrawValues(false); set1.setDrawCircles(false); - set1.setDrawCubic(false); + set1.setMode(LineDataSet.Mode.LINEAR); set1.setDrawFilled(false); // create a data object with the datasets diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 64937fba99..b8c3f5e642 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -94,7 +94,7 @@ public LineDataSet.Mode getMode() { } /** - * Returns the drawing mode for this line dataset + * Returns the drawing mode for this LineDataSet * * @return */ @@ -224,22 +224,12 @@ public boolean isDrawCirclesEnabled() { return mDrawCircles; } - @Deprecated - public void setDrawCubic(boolean enabled) { - mMode = enabled ? Mode.CUBIC_BEZIER : Mode.LINEAR; - } - @Deprecated @Override public boolean isDrawCubicEnabled() { return mMode == Mode.CUBIC_BEZIER; } - @Deprecated - public void setDrawStepped(boolean enabled) { - mMode = enabled ? Mode.STEPPED : Mode.LINEAR; - } - @Deprecated @Override public boolean isDrawSteppedEnabled() { From 1a642899e052aec3c299e994f89665069f3d5fa9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 10:08:04 +0200 Subject: [PATCH 0932/1390] Work on axis formatters --- .../mpchartexample/PerformanceLineChart.java | 2 +- .../mpchartexample/StackedBarActivityNegative.java | 5 +++++ .../mpchartexample/custom/MonthXAxisFormatter.java | 5 +++++ .../custom/MyCustomXAxisValueFormatter.java | 5 +++++ .../custom/MyYAxisValueFormatter.java | 5 +++++ .../github/mikephil/charting/components/XAxis.java | 6 +++++- .../github/mikephil/charting/components/YAxis.java | 7 ++++++- .../charting/formatter/AxisValueFormatter.java | 14 ++++++++++++++ .../formatter/DefaultAxisValueFormatter.java | 14 ++++++++++++-- .../charting/formatter/LargeValueFormatter.java | 5 +++++ .../charting/formatter/PercentFormatter.java | 5 +++++ .../charting/formatter/XAxisValueFormatter.java | 2 +- .../charting/formatter/YAxisValueFormatter.java | 2 +- 13 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 14b0d7eda6..036e12ace7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -99,7 +99,7 @@ private void setData(int count, float range) { float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * // 0.1) / 10); - yVals.add(new Entry(i, val)); + yVals.add(new Entry(i * 0.001f, val)); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index dac526041a..d7b82c1ded 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -226,5 +226,10 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View public String getFormattedValue(float value, YAxis yAxis) { return mFormat.format(Math.abs(value)) + "m"; } + + @Override + public int getDecimalDigits() { + return 0; + } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java index fe1021b979..f960f9bf37 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java @@ -25,4 +25,9 @@ public String getXValue(float xValue, float xRange, float xPosition, ViewPortHan float percent = xValue / xRange; return mMonths[(int) (mMonths.length * percent)]; } + + @Override + public int getDecimalDigits() { + return 0; + } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 6f3c789cf8..e11ee86732 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -32,4 +32,9 @@ else if (viewPortHandler.getScaleX() > 1) else return mFormat.format(xValue); } + + @Override + public int getDecimalDigits() { + return 1; + } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java index cae82be1d9..d9aefb0cd6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java @@ -17,4 +17,9 @@ public MyYAxisValueFormatter() { public String getFormattedValue(float value, YAxis yAxis) { return mFormat.format(value) + " $"; } + + @Override + public int getDecimalDigits() { + return 1; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index 72a68a0ae7..ae0983f5f0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -236,8 +236,12 @@ public void setValueFormatter(XAxisValueFormatter formatter) { */ public XAxisValueFormatter getValueFormatter() { - if (mXAxisValueFormatter == null) + if (mXAxisValueFormatter == null) { mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); + } else if (mXAxisValueFormatter.getDecimalDigits() != mDecimals && mXAxisValueFormatter instanceof + DefaultXAxisValueFormatter) { + mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); + } return mXAxisValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index d2b928f71a..3497cdb4d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -4,6 +4,7 @@ import android.graphics.Paint; import com.github.mikephil.charting.formatter.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; import com.github.mikephil.charting.formatter.DefaultYAxisValueFormatter; import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -393,8 +394,12 @@ public void setValueFormatter(YAxisValueFormatter f) { */ public YAxisValueFormatter getValueFormatter() { - if (mYAxisValueFormatter == null) + if (mYAxisValueFormatter == null) { + mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); + } else if (mYAxisValueFormatter.getDecimalDigits() != mDecimals && mYAxisValueFormatter instanceof + DefaultYAxisValueFormatter) { mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); + } return mYAxisValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java new file mode 100644 index 0000000000..4f16ece806 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java @@ -0,0 +1,14 @@ +package com.github.mikephil.charting.formatter; + +/** + * Created by philipp on 02/06/16. + */ +public interface AxisValueFormatter { + + /** + * Returns the number of decimal digits this formatter uses. + * + * @return + */ + int getDecimalDigits(); +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index c5b859d4a1..fcb0a348a4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -5,11 +5,15 @@ /** * Created by philipp on 02/06/16. */ -public class DefaultAxisValueFormatter { +public class DefaultAxisValueFormatter implements AxisValueFormatter { - /** decimalformat for formatting */ + /** + * decimalformat for formatting + */ protected DecimalFormat mFormat; + protected int digits = 0; + /** * Constructor that specifies to how many digits the yValue should be * formatted. @@ -17,6 +21,7 @@ public class DefaultAxisValueFormatter { * @param digits */ public DefaultAxisValueFormatter(int digits) { + this.digits = digits; StringBuffer b = new StringBuffer(); for (int i = 0; i < digits; i++) { @@ -27,4 +32,9 @@ public DefaultAxisValueFormatter(int digits) { mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } + + @Override + public int getDecimalDigits() { + return digits; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index d5fc954fdc..690fed4a56 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -89,4 +89,9 @@ private String makePretty(double number) { return r; } + + @Override + public int getDecimalDigits() { + return 0; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 93fbe1fa25..5f6e2946d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -41,4 +41,9 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View public String getFormattedValue(float value, YAxis yAxis) { return mFormat.format(value) + " %"; } + + @Override + public int getDecimalDigits() { + return 1; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java index a58b67ebd5..f805907eb5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java @@ -8,7 +8,7 @@ * * @author Philipp Jahoda */ -public interface XAxisValueFormatter { +public interface XAxisValueFormatter extends AxisValueFormatter { /** * Returns the customized label that is drawn on the x-axis. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java index eacd3ab33a..a8f5c1b273 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java @@ -7,7 +7,7 @@ * Custom formatter interface that allows formatting of * YAxis labels before they are being drawn. */ -public interface YAxisValueFormatter { +public interface YAxisValueFormatter extends AxisValueFormatter { /** * Called when a yValue from the YAxis is formatted From 2ae37c30883b0208a2490674495e85e948011687 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 10:24:51 +0200 Subject: [PATCH 0933/1390] Restructuring of axis formatters --- .../mpchartexample/BarChartActivity.java | 6 +- .../mpchartexample/StackedBarActivity.java | 4 +- .../StackedBarActivityNegative.java | 7 +- .../custom/MonthXAxisFormatter.java | 14 ++- ...rmatter.java => MyAxisValueFormatter.java} | 10 +-- .../custom/MyCustomXAxisValueFormatter.java | 19 ++-- .../charting/components/AxisBase.java | 62 ++++++++++++- .../mikephil/charting/components/XAxis.java | 54 ----------- .../mikephil/charting/components/YAxis.java | 89 ------------------- .../formatter/AxisValueFormatter.java | 17 +++- .../formatter/DefaultAxisValueFormatter.java | 11 +++ .../formatter/DefaultXAxisValueFormatter.java | 22 ----- .../formatter/DefaultYAxisValueFormatter.java | 23 ----- .../formatter/LargeValueFormatter.java | 8 +- .../charting/formatter/PercentFormatter.java | 8 +- .../formatter/XAxisValueFormatter.java | 25 ------ .../formatter/YAxisValueFormatter.java | 22 ----- .../charting/renderer/XAxisRenderer.java | 2 +- 18 files changed, 128 insertions(+), 275 deletions(-) rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/{MyYAxisValueFormatter.java => MyAxisValueFormatter.java} (53%) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 800ba6b828..103f87a76c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -28,13 +28,13 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -86,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); - YAxisValueFormatter custom = new MyYAxisValueFormatter(); + AxisValueFormatter custom = new MyAxisValueFormatter(); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index fa6808e23f..2e281d797e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -25,8 +25,8 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the yPx-labels YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setValueFormatter(new MyYAxisValueFormatter()); + leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index d7b82c1ded..cbf4bb4fe5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -10,6 +10,7 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; @@ -20,7 +21,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -207,7 +208,7 @@ public void onNothingSelected() { Log.i("NOTING SELECTED", ""); } - private class CustomFormatter implements ValueFormatter, YAxisValueFormatter { + private class CustomFormatter implements ValueFormatter, AxisValueFormatter { private DecimalFormat mFormat; @@ -223,7 +224,7 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View // YAxis @Override - public String getFormattedValue(float value, YAxis yAxis) { + public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(Math.abs(value)) + "m"; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java index f960f9bf37..ffa49ec24f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java @@ -1,16 +1,14 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.formatter.XAxisValueFormatter; -import com.github.mikephil.charting.utils.ViewPortHandler; - -import java.text.DecimalFormat; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.AxisValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ -public class MonthXAxisFormatter implements XAxisValueFormatter { +public class MonthXAxisFormatter implements AxisValueFormatter { - protected String[] mMonths = new String[] { + protected String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; @@ -20,9 +18,9 @@ public MonthXAxisFormatter() { } @Override - public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { + public String getFormattedValue(float value, AxisBase axis) { - float percent = xValue / xRange; + float percent = value / axis.mAxisRange; return mMonths[(int) (mMonths.length * percent)]; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java similarity index 53% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index d9aefb0cd6..ea50fd8fad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -1,20 +1,20 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import java.text.DecimalFormat; -public class MyYAxisValueFormatter implements YAxisValueFormatter { +public class MyAxisValueFormatter implements AxisValueFormatter { private DecimalFormat mFormat; - public MyYAxisValueFormatter() { + public MyAxisValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override - public String getFormattedValue(float value, YAxis yAxis) { + public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + " $"; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index e11ee86732..73c1ef4681 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.formatter.XAxisValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -8,29 +9,31 @@ /** * Created by Philipp Jahoda on 14/09/15. */ -public class MyCustomXAxisValueFormatter implements XAxisValueFormatter { +public class MyCustomXAxisValueFormatter implements AxisValueFormatter { private DecimalFormat mFormat; + private ViewPortHandler mViewPortHandler; - public MyCustomXAxisValueFormatter() { + public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { + mViewPortHandler = viewPortHandler; // maybe do something here or provide parameters in constructor mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override - public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { + public String getFormattedValue(float value, AxisBase axis) { //Log.i("TRANS", "xPx: " + viewPortHandler.getTransX() + ", yPx: " + viewPortHandler.getTransY()); // e.g. adjust the xPx-axis values depending on scale / zoom level - if (viewPortHandler.getScaleX() > 5) + if (mViewPortHandler.getScaleX() > 5) return "4"; - else if (viewPortHandler.getScaleX() > 3) + else if (mViewPortHandler.getScaleX() > 3) return "3"; - else if (viewPortHandler.getScaleX() > 1) + else if (mViewPortHandler.getScaleX() > 1) return "2"; else - return mFormat.format(xValue); + return mFormat.format(value); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 754ece5257..c5c3445207 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -5,6 +5,7 @@ import android.graphics.DashPathEffect; import android.util.Log; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -18,6 +19,11 @@ */ public abstract class AxisBase extends ComponentBase { + /** + * custom formatter that is used instead of the auto-formatter if set + */ + protected AxisValueFormatter mAxisValueFormatter; + private int mGridColor = Color.GRAY; private float mGridLineWidth = 1f; @@ -408,7 +414,61 @@ public boolean isDrawLimitLinesBehindDataEnabled() { * * @return */ - public abstract String getLongestLabel(); + public String getLongestLabel() { + + String longest = ""; + + for (int i = 0; i < mEntries.length; i++) { + String text = getFormattedLabel(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } + + public String getFormattedLabel(int index) { + + if (index < 0 || index >= mEntries.length) + return ""; + else + return getValueFormatter().getFormattedValue(mEntries[index], this); + } + + /** + * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the + * chart will + * automatically determine a reasonable formatting (concerning decimals) for all the values + * that are drawn inside + * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. + * + * @param f + */ + public void setValueFormatter(AxisValueFormatter f) { + + if (f == null) + mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); + else + mAxisValueFormatter = f; + } + + /** + * Returns the formatter used for formatting the axis labels. + * + * @return + */ + public AxisValueFormatter getValueFormatter() { + + if (mAxisValueFormatter == null) { + mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); + } else if (mAxisValueFormatter.getDecimalDigits() != mDecimals && mAxisValueFormatter instanceof + DefaultAxisValueFormatter) { + mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); + } + + return mAxisValueFormatter; + } /** * Enables the grid line to be drawn in dashed mode, e.g. like this diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index ae0983f5f0..a19711ebef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -1,8 +1,6 @@ package com.github.mikephil.charting.components; -import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; -import com.github.mikephil.charting.formatter.XAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; /** @@ -67,11 +65,6 @@ public class XAxis extends AxisBase { */ private boolean mAvoidFirstLastClipping = false; - /** - * Custom formatter for adjusting xPx-yValue strings - */ - protected XAxisValueFormatter mXAxisValueFormatter; - /** * the position of the xPx-labels relative to the chart */ @@ -213,51 +206,4 @@ public boolean isAvoidFirstLastClippingEnabled() { // public void removeXValue(int index) { // mValues.remove(index); // } - - - /** - * Sets a custom XAxisValueFormatter for the data object that allows custom-formatting - * of all xPx-values before rendering them. Provide null to reset back to the - * default formatting. - * - * @param formatter - */ - public void setValueFormatter(XAxisValueFormatter formatter) { - if (formatter == null) - mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); - else - mXAxisValueFormatter = formatter; - } - - /** - * Returns the custom XAxisValueFormatter that is set for this data object. - * - * @return - */ - public XAxisValueFormatter getValueFormatter() { - - if (mXAxisValueFormatter == null) { - mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); - } else if (mXAxisValueFormatter.getDecimalDigits() != mDecimals && mXAxisValueFormatter instanceof - DefaultXAxisValueFormatter) { - mXAxisValueFormatter = new DefaultXAxisValueFormatter(mDecimals); - } - - return mXAxisValueFormatter; - } - - @Override - public String getLongestLabel() { - - String longest = ""; - -// for (int i = 0; i < mValues.size(); i++) { -// String text = mValues.get(i).getLabel(); -// -// if (longest.length() < text.length()) -// longest = text; -// } - - return longest; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 3497cdb4d4..6b0c6adedf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -3,10 +3,6 @@ import android.graphics.Color; import android.graphics.Paint; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; -import com.github.mikephil.charting.formatter.DefaultYAxisValueFormatter; -import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; /** @@ -22,11 +18,6 @@ */ public class YAxis extends AxisBase { - /** - * custom formatter that is used instead of the auto-formatter if set - */ - protected YAxisValueFormatter mYAxisValueFormatter; - /** * indicates if the top yPx-label entry is drawn or not */ @@ -339,86 +330,6 @@ public float getRequiredHeightSpace(Paint p) { return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; } - @Override - public String getLongestLabel() { - - String longest = ""; - - for (int i = 0; i < mEntries.length; i++) { - String text = getFormattedLabel(i); - - if (longest.length() < text.length()) - longest = text; - } - - return longest; - } - - /** - * Returns the formatted yPx-label at the specified index. This will either use the - * auto-formatter or the custom - * formatter (if one is set). - * - * @param index - * @return - */ - public String getFormattedLabel(int index) { - - if (index < 0 || index >= mEntries.length) - return ""; - else - return getValueFormatter().getFormattedValue(mEntries[index], this); - } - - /** - * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the - * chart will - * automatically determine a reasonable formatting (concerning decimals) for all the values - * that are drawn inside - * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. - * - * @param f - */ - public void setValueFormatter(YAxisValueFormatter f) { - - if (f == null) - mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); - else - mYAxisValueFormatter = f; - } - - /** - * Returns the formatter used for formatting the axis labels. - * - * @return - */ - public YAxisValueFormatter getValueFormatter() { - - if (mYAxisValueFormatter == null) { - mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); - } else if (mYAxisValueFormatter.getDecimalDigits() != mDecimals && mYAxisValueFormatter instanceof - DefaultYAxisValueFormatter) { - mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); - } - - return mYAxisValueFormatter; - } - - /** - * If this component has no YAxisValueFormatter or is only equipped with the default one (no - * custom set), return true. - * - * @return - */ - public boolean needsDefaultFormatter() { - if (mYAxisValueFormatter == null) - return true; - if (mYAxisValueFormatter instanceof DefaultValueFormatter) - return true; - - return false; - } - /** * Returns true if this axis needs horizontal offset, false if no offset is needed. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java index 4f16ece806..dee03a9272 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java @@ -1,10 +1,25 @@ package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; + /** - * Created by philipp on 02/06/16. + * Created by Philipp Jahoda on 20/09/15. + * Custom formatter interface that allows formatting of + * axis labels before they are being drawn. */ public interface AxisValueFormatter { + /** + * Called when a value from an axis is to be formatted + * before being drawn. For performance reasons, avoid excessive calculations + * and memory allocations inside this method. + * + * @param value the value to be formatted + * @param axis the axis the value belongs to + * @return + */ + String getFormattedValue(float value, AxisBase axis); + /** * Returns the number of decimal digits this formatter uses. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index fcb0a348a4..80294399e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; + import java.text.DecimalFormat; /** @@ -12,6 +14,9 @@ public class DefaultAxisValueFormatter implements AxisValueFormatter { */ protected DecimalFormat mFormat; + /** + * the number of decimal digits this formatter uses + */ protected int digits = 0; /** @@ -33,6 +38,12 @@ public DefaultAxisValueFormatter(int digits) { mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } + @Override + public String getFormattedValue(float value, AxisBase axis) { + // avoid memory allocations here (for performance) + return mFormat.format(value); + } + @Override public int getDecimalDigits() { return digits; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java deleted file mode 100644 index a62f0f88be..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.utils.ViewPortHandler; - -import java.text.DecimalFormat; - -/** - * Created by Philipp Jahoda on 14/09/15. - * Default formatter class for adjusting xPx-values before drawing them. - * This simply returns the original yValue unmodified. - */ -public class DefaultXAxisValueFormatter extends DefaultAxisValueFormatter implements XAxisValueFormatter { - - public DefaultXAxisValueFormatter(int digits) { - super(digits); - } - - @Override - public String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler) { - return mFormat.format(xValue); // just return original, no adjustments - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java deleted file mode 100644 index 553362d317..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.components.YAxis; - -import java.text.DecimalFormat; - -/** - * Created by Philipp Jahoda on 20/09/15. - * Default formatter used for formatting labels of the YAxis. Uses a DecimalFormat with - * pre-calculated number of digits (depending on max and min yValue). - */ -public class DefaultYAxisValueFormatter extends DefaultAxisValueFormatter implements YAxisValueFormatter { - - public DefaultYAxisValueFormatter(int digits) { - super(digits); - } - - @Override - public String getFormattedValue(float value, YAxis yAxis) { - // avoid memory allocations here (for performance) - return mFormat.format(value); - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 690fed4a56..ba9d355830 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,7 +17,7 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter implements ValueFormatter, YAxisValueFormatter { +public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { private static String[] SUFFIX = new String[]{ "", "k", "m", "b", "t" @@ -46,9 +46,9 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View return makePretty(value) + mText; } - // YAxisValueFormatter + // AxisValueFormatter @Override - public String getFormattedValue(float value, YAxis yAxis) { + public String getFormattedValue(float value, AxisBase axis) { return makePretty(value) + mText; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 5f6e2946d4..b4a5fd9dee 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -13,7 +13,7 @@ * * @author Philipp Jahoda */ -public class PercentFormatter implements ValueFormatter, YAxisValueFormatter { +public class PercentFormatter implements ValueFormatter, AxisValueFormatter { protected DecimalFormat mFormat; @@ -36,9 +36,9 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View return mFormat.format(value) + " %"; } - // YAxisValueFormatter + // AxisValueFormatter @Override - public String getFormattedValue(float value, YAxis yAxis) { + public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + " %"; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java deleted file mode 100644 index f805907eb5..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/XAxisValueFormatter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.utils.ViewPortHandler; - -/** - * Created by Philipp Jahoda on 14/09/15. - * An interface for providing custom xPx-axis Strings. - * - * @author Philipp Jahoda - */ -public interface XAxisValueFormatter extends AxisValueFormatter { - - /** - * Returns the customized label that is drawn on the x-axis. - * For performance reasons, avoid excessive calculations - * and memory allocations inside this method. - * - * @param xValue the original x-value - * @param xRange the total range of the x-values - * @param xPosition the position on the x-axis where the value is drawn (in pixels) - * @param viewPortHandler provides information about the current chart state (scale, translation, ...) - * @return - */ - String getXValue(float xValue, float xRange, float xPosition, ViewPortHandler viewPortHandler); -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java deleted file mode 100644 index a8f5c1b273..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/YAxisValueFormatter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.components.YAxis; - -/** - * Created by Philipp Jahoda on 20/09/15. - * Custom formatter interface that allows formatting of - * YAxis labels before they are being drawn. - */ -public interface YAxisValueFormatter extends AxisValueFormatter { - - /** - * Called when a yValue from the YAxis is formatted - * before being drawn. For performance reasons, avoid excessive calculations - * and memory allocations inside this method. - * - * @param value the YAxis yValue to be formatted - * @param yAxis the YAxis object the yValue belongs to - * @return - */ - String getFormattedValue(float value, YAxis yAxis); -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 747d4917b6..2ba4b57b8f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -229,7 +229,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } protected void drawLabel(Canvas c, float xValue, float x, float y, PointF anchor, float angleDegrees) { - String formattedLabel = mXAxis.getValueFormatter().getXValue(xValue, mXAxis.mAxisRange, x, mViewPortHandler); + String formattedLabel = mXAxis.getValueFormatter().getFormattedValue(xValue, mXAxis); Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } From b857e58837e686b2aeb3301541079ec3daf3a70e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 14:00:06 +0200 Subject: [PATCH 0934/1390] Work on x-axis rendering of barchart --- .../mpchartexample/BarChartActivity.java | 4 +- .../BarChartActivityMultiDataset.java | 24 +-- .../custom/YearXAxisFormatter.java | 31 ++++ .../charting/components/AxisBase.java | 15 ++ .../mikephil/charting/components/XAxis.java | 6 - .../mikephil/charting/data/BarData.java | 11 ++ .../charting/renderer/AxisRenderer.java | 79 +++++++--- .../charting/renderer/XAxisRenderer.java | 15 +- .../renderer/XAxisRendererBarChart.java | 146 +++++++----------- .../renderer/XAxisRendererRadarChart.java | 4 +- 10 files changed, 198 insertions(+), 137 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 103f87a76c..561756882d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -231,14 +231,14 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { mChart.getXAxis().setAxisMinValue(0f); - mChart.getXAxis().setAxisMaxValue(count); + mChart.getXAxis().setAxisMaxValue(count+1f); ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(i + 0.5f, val)); + yVals1.add(new BarEntry(i + 1f, val)); } BarDataSet set1; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 7d0fa93790..71328613d6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -93,6 +93,8 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); + xl.setGranularity(1f); + xl.setCenterAxisLabels(true); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -182,10 +184,13 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - float groupSpace = 0.8f; - float barSpace = 0.15f; + float groupSpace = 0.04f; + float barSpace = 0.02f; + float barWidth = 0.3f; + int startYear = 1980; + int endYear = startYear + mSeekBarX.getProgress(); - tvX.setText("" + (mSeekBarX.getProgress() * 3)); + tvX.setText(startYear + "\n-" + endYear); tvY.setText("" + (mSeekBarY.getProgress())); ArrayList yVals1 = new ArrayList(); @@ -194,17 +199,17 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float mult = mSeekBarY.getProgress() * 1000f; - for (int i = 0; i < mSeekBarX.getProgress(); i++) { + for (int i = startYear; i < endYear; i++) { float val = (float) (Math.random() * mult) + 3; yVals1.add(new BarEntry(i, val)); } - for (int i = 0; i < mSeekBarX.getProgress(); i++) { + for (int i = startYear; i < endYear; i++) { float val = (float) (Math.random() * mult) + 3; yVals2.add(new BarEntry(i, val)); } - for (int i = 0; i < mSeekBarX.getProgress(); i++) { + for (int i = startYear; i < endYear; i++) { float val = (float) (Math.random() * mult) + 3; yVals3.add(new BarEntry(i, val)); } @@ -246,9 +251,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.setData(data); } - mChart.getBarData().groupBars(0, groupSpace, barSpace); - mChart.getXAxis().setAxisMinValue(0f); - mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getIntervalWidth(groupSpace, barSpace) * mSeekBarX.getProgress()); + mChart.getBarData().setBarWidth(barWidth); + mChart.getBarData().groupBars(startYear, groupSpace, barSpace); + mChart.getXAxis().setAxisMinValue(startYear); + mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getIntervalWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java new file mode 100644 index 0000000000..e9b31bb6c0 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -0,0 +1,31 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.AxisValueFormatter; + +/** + * Created by Philipp Jahoda on 14/09/15. + */ +public class YearXAxisFormatter implements AxisValueFormatter { + + protected String[] mMonths = new String[]{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + }; + + public YearXAxisFormatter() { + // maybe do something here or provide parameters in constructor + + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + + float percent = value / axis.mAxisRange; + return mMonths[(int) (mMonths.length * percent)]; + } + + @Override + public int getDecimalDigits() { + return 0; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index c5c3445207..2c717ea6de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -37,6 +37,11 @@ public abstract class AxisBase extends ComponentBase { */ public float[] mEntries = new float[]{}; + /** + * axis label entries only used for centered labels + */ + public float[] mCenteredEntries = new float[]{}; + /** * the number of entries the legend contains */ @@ -85,6 +90,8 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mDrawLabels = true; + protected boolean mCenterAxisLabels = false; + /** * the path effect of the grid lines that makes dashed lines possible */ @@ -171,6 +178,14 @@ public boolean isDrawAxisLineEnabled() { return mDrawAxisLine; } + public void setCenterAxisLabels(boolean enabled) { + mCenterAxisLabels = enabled; + } + + public boolean isCenterAxisLabelsEnabled() { + return mCenterAxisLabels && mEntryCount > 1; + } + /** * Sets the color of the grid lines for this axis (the horizontal lines * coming from each label). diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index a19711ebef..3e796f5365 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -41,12 +41,6 @@ public class XAxis extends AxisBase { */ protected float mLabelRotationAngle = 0f; - /** - * the space that should be left out (in characters) between the xPx-axis - * labels - */ - private int mSpaceBetweenLabels = 4; - /** * the modulus that indicates if a yValue at a specified index in an * array(list) for the xPx-axis-labels is drawn or not. If index % modulus == diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 08187c2061..0bc79d56e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -92,8 +92,11 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { float barSpaceHalf = barSpace / 2f; float barWidthHalf = mBarWidth / 2f; + float interval = getIntervalWidth(groupSpace, barSpace); + for (int i = 0; i < maxEntryCount; i++) { + float start = fromX; fromX += groupSpaceWidthHalf; for (IBarDataSet set : mDataSets) { @@ -115,6 +118,14 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { } fromX += groupSpaceWidthHalf; + float end = fromX; + float innerInterval = end - start; + float diff = interval - innerInterval; + + // correct rounding errors + if (diff > 0 || diff < 0) { + fromX += diff; + } } notifyDataChanged(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 644267cbac..c52b1cb0bb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -14,7 +14,7 @@ /** * Baseclass of all axis renderers. - * + * * @author Philipp Jahoda */ public abstract class AxisRenderer extends Renderer { @@ -23,19 +23,27 @@ public abstract class AxisRenderer extends Renderer { protected Transformer mTrans; - /** paint object for the grid lines */ + /** + * paint object for the grid lines + */ protected Paint mGridPaint; - /** paint for the xPx-label values */ + /** + * paint for the xPx-label values + */ protected Paint mAxisLabelPaint; - /** paint for the line surrounding the chart */ + /** + * paint for the line surrounding the chart + */ protected Paint mAxisLinePaint; - /** paint used for the limit lines */ - protected Paint mLimitLinePaint; + /** + * paint used for the limit lines + */ + protected Paint mLimitLinePaint; - public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase axis) { + public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase axis) { super(viewPortHandler); this.mTrans = trans; @@ -54,13 +62,13 @@ public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase mAxisLinePaint.setStrokeWidth(1f); mAxisLinePaint.setStyle(Style.STROKE); - mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mLimitLinePaint.setStyle(Paint.Style.STROKE); - } + mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + } /** * Returns the Paint object used for drawing the axis (labels). - * + * * @return */ public Paint getPaintAxisLabels() { @@ -70,7 +78,7 @@ public Paint getPaintAxisLabels() { /** * Returns the Paint object that is used for drawing the grid-lines of the * axis. - * + * * @return */ public Paint getPaintGrid() { @@ -80,7 +88,7 @@ public Paint getPaintGrid() { /** * Returns the Paint object that is used for drawing the axis-line that goes * alongside the axis. - * + * * @return */ public Paint getPaintAxisLine() { @@ -89,7 +97,7 @@ public Paint getPaintAxisLine() { /** * Returns the Transformer object used for transforming the axis values. - * + * * @return */ public Transformer getTransformer() { @@ -162,6 +170,9 @@ protected void computeAxisValues(float min, float max) { interval = Math.floor(10 * intervalMagnitude); } + boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); + int n = centeringEnabled ? 1 : 0; + // force label count if (mAxis.isForceLabelsEnabled()) { @@ -180,16 +191,21 @@ protected void computeAxisValues(float min, float max) { v += step; } + n = labelCount; + // no forced count } else { - double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; + if(centeringEnabled) { + first -= interval; + } + double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); double f; int i; - int n = 0; + if (interval != 0.0) { for (f = first; f <= last; f += interval) { ++n; @@ -218,33 +234,46 @@ protected void computeAxisValues(float min, float max) { } else { mAxis.mDecimals = 0; } + + if (centeringEnabled) { + + if (mAxis.mCenteredEntries.length < n) { + mAxis.mCenteredEntries = new float[n]; + } + + float offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f; + + for (int i = 0; i < n; i++) { + mAxis.mCenteredEntries[i] = mAxis.mEntries[i] + offset; + } + } } /** * Draws the axis labels to the screen. - * + * * @param c */ public abstract void renderAxisLabels(Canvas c); /** * Draws the grid lines belonging to the axis. - * + * * @param c */ public abstract void renderGridLines(Canvas c); /** * Draws the line that goes alongside the axis. - * + * * @param c */ public abstract void renderAxisLine(Canvas c); - /** - * Draws the LimitLines associated with this axis to the screen. - * - * @param c - */ - public abstract void renderLimitLines(Canvas c); + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + public abstract void renderLimitLines(Canvas c); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 2ba4b57b8f..0f13346701 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -187,12 +187,18 @@ public void renderAxisLine(Canvas c) { protected void drawLabels(Canvas c, float pos, PointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); + boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { + // only fill xPx values - positions[i] = mXAxis.mEntries[i / 2]; + if (centeringEnabled) { + positions[i] = mXAxis.mCenteredEntries[i / 2]; + } else { + positions[i] = mXAxis.mEntries[i / 2]; + } } mTrans.pointValuesToPixel(positions); @@ -203,7 +209,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { if (mViewPortHandler.isInBoundsX(x)) { - String label = String.valueOf(mXAxis.mEntries[i / 2]); + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); if (mXAxis.isAvoidFirstLastClippingEnabled()) { @@ -223,13 +229,12 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } } - drawLabel(c, mXAxis.mEntries[i / 2], x, pos, anchor, labelRotationAngleDegrees); + drawLabel(c, label, x, pos, anchor, labelRotationAngleDegrees); } } } - protected void drawLabel(Canvas c, float xValue, float x, float y, PointF anchor, float angleDegrees) { - String formattedLabel = mXAxis.getValueFormatter().getFormattedValue(xValue, mXAxis); + protected void drawLabel(Canvas c, String formattedLabel, float x, float y, PointF anchor, float angleDegrees) { Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 0c16dc2a65..ad36599444 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -22,92 +22,62 @@ public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Trans this.mChart = chart; } - /** - * draws the xPx-labels on the specified yPx-position - * - * @param pos - */ - @Override - protected void drawLabels(Canvas c, float pos, PointF anchor) { - - final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; - - BarData bd = mChart.getData(); - int step = bd.getDataSetCount(); - -// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { -// -// position[0] = i * step + i * bd.getGroupSpace() -// + bd.getGroupSpace() / 2f; -// -// // consider groups (center label for each group) -// if (step > 1) { -// position[0] += ((float) step - 1f) / 2f; -// } -// -// mTrans.pointValuesToPixel(position); -// -// if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 -// && i < mXAxis.getValues().size()) { -// -// String label = mXAxis.getValues().get(i).getLabel(); -// -// if (mXAxis.isAvoidFirstLastClippingEnabled()) { -// -// // avoid clipping of the last -// if (i == mXAxis.getValues().size() - 1) { -// float width = Utils.calcTextWidth(mAxisLabelPaint, label); -// -// if (position[0] + width / 2.f > mViewPortHandler.contentRight()) -// position[0] = mViewPortHandler.contentRight() - (width / 2.f); -// -// // avoid clipping of the first -// } else if (i == 0) { -// -// float width = Utils.calcTextWidth(mAxisLabelPaint, label); -// -// if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) -// position[0] = mViewPortHandler.contentLeft() + (width / 2.f); -// } -// } -// -// drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); -// } -// } - } - - @Override - public void renderGridLines(Canvas c) { - - if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) - return; - - float[] position = new float[] { - 0f, 0f - }; - - mGridPaint.setColor(mXAxis.getGridColor()); - mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - - BarData bd = mChart.getData(); - int step = bd.getDataSetCount(); - -// for (int i = mMinX; i < mMaxX; i += mXAxis.mAxisLabelModulus) { -// -// position[0] = i * step + i * bd.getGroupSpace() - 0.5f; -// -// mTrans.pointValuesToPixel(position); -// -// if (mViewPortHandler.isInBoundsX(position[0])) { -// -// c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], -// mViewPortHandler.contentBottom(), mGridPaint); -// } -// } - } +// /** +// * draws the xPx-labels on the specified yPx-position +// * +// * @param pos +// */ +// @Override +// protected void drawLabels(Canvas c, float pos, PointF anchor) { +// +// final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); +// +// // pre allocate to save performance (dont allocate in loop) +// float[] position = new float[] { +// 0f, 0f +// }; +// +// BarData bd = mChart.getData(); +// int step = bd.getDataSetCount(); +// +//// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { +//// +//// position[0] = i * step + i * bd.getGroupSpace() +//// + bd.getGroupSpace() / 2f; +//// +//// // consider groups (center label for each group) +//// if (step > 1) { +//// position[0] += ((float) step - 1f) / 2f; +//// } +//// +//// mTrans.pointValuesToPixel(position); +//// +//// if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 +//// && i < mXAxis.getValues().size()) { +//// +//// String label = mXAxis.getValues().get(i).getLabel(); +//// +//// if (mXAxis.isAvoidFirstLastClippingEnabled()) { +//// +//// // avoid clipping of the last +//// if (i == mXAxis.getValues().size() - 1) { +//// float width = Utils.calcTextWidth(mAxisLabelPaint, label); +//// +//// if (position[0] + width / 2.f > mViewPortHandler.contentRight()) +//// position[0] = mViewPortHandler.contentRight() - (width / 2.f); +//// +//// // avoid clipping of the first +//// } else if (i == 0) { +//// +//// float width = Utils.calcTextWidth(mAxisLabelPaint, label); +//// +//// if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) +//// position[0] = mViewPortHandler.contentLeft() + (width / 2.f); +//// } +//// } +//// +//// drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); +//// } +//// } +// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 0f861aaa72..6c505bc5ba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -42,14 +42,14 @@ public void renderAxisLabels(Canvas c) { int mod = mXAxis.mAxisLabelModulus; for (int i = 0; i < mXAxis.mEntryCount; i += mod) { - String label = String.valueOf(mXAxis.mEntries[i]); + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i], mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; PointF p = Utils.getPosition(center, mChart.getYRange() * factor + mXAxis.mLabelRotatedWidth / 2f, angle); - drawLabel(c, 0f, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, + drawLabel(c, label, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, drawLabelAnchor, labelRotationAngleDegrees); } } From 5292cfc8184ae7bde2393bc0c1fdcc708f892f31 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 14:59:06 +0200 Subject: [PATCH 0935/1390] Improve examples --- .../mpchartexample/BarChartActivity.java | 108 ++++++++++++++++-- .../mpchartexample/ScatterChartActivity.java | 2 - .../custom/MonthXAxisFormatter.java | 31 ----- 3 files changed, 100 insertions(+), 41 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 561756882d..6c8fcca1c2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -16,6 +16,7 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -85,6 +86,8 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); + xAxis.setGranularity(1f); // only intervals of 1 day + xAxis.setValueFormatter(new DayAxisFormatter()); AxisValueFormatter custom = new MyAxisValueFormatter(); @@ -145,7 +148,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { + if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); mChart.invalidate(); } @@ -167,7 +170,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleBarBorders: { for (IBarDataSet set : mChart.getData().getDataSets()) - ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); mChart.invalidate(); break; @@ -230,12 +233,14 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - mChart.getXAxis().setAxisMinValue(0f); - mChart.getXAxis().setAxisMaxValue(count+1f); + float start = 0.5f; + + mChart.getXAxis().setAxisMinValue(start); + mChart.getXAxis().setAxisMaxValue(start + count); ArrayList yVals1 = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = (int) start; i < start + count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); yVals1.add(new BarEntry(i + 1f, val)); @@ -245,12 +250,12 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); set1.setYVals(yVals1); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { - set1 = new BarDataSet(yVals1, "DataSet"); + set1 = new BarDataSet(yVals1, "The year 2017"); set1.setColors(ColorTemplate.MATERIAL_COLORS); ArrayList dataSets = new ArrayList(); @@ -284,5 +289,92 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { } public void onNothingSelected() { - }; + } + + private class DayAxisFormatter implements AxisValueFormatter { + + protected String[] mMonths = new String[]{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + }; + + @Override + public String getFormattedValue(float value, AxisBase axis) { + + int dayOfYear = (int) value; + + int month = determineMonth(dayOfYear); + int dayOfMonth = determineDayOfMonth(dayOfYear, month); + + String appendix = "th"; + + switch (dayOfMonth) { + case 1: + appendix = "st"; + break; + case 2: + appendix = "nd"; + break; + case 3: + appendix = "rd"; + break; + case 21: + appendix = "st"; + break; + case 22: + appendix = "nd"; + break; + case 23: + appendix = "rd"; + break; + case 31: + appendix = "st"; + break; + } + + return dayOfMonth + appendix + " " + mMonths[month % mMonths.length]; + } + + private int getDaysForMonth(int month) { + + if (month == 1) { + return 28; + } + + if (month == 3 || month == 5 || month == 8 || month == 10) + return 30; + else + return 31; + } + + private int determineMonth(int dayOfYear) { + + int month = -1; + int days = 0; + + while (days < dayOfYear) { + month++; + days += getDaysForMonth(month); + } + + return month; + } + + private int determineDayOfMonth(int dayOfYear, int month) { + + int count = 0; + int days = 0; + + while (count < month) { + days += getDaysForMonth(count); + count++; + } + + return dayOfYear - days; + } + + @Override + public int getDecimalDigits() { + return 0; + } + } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 916b211fd9..0bac51c1c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -24,7 +24,6 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.MonthXAxisFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -89,7 +88,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); xl.setDrawGridLines(false); - xl.setValueFormatter(new MonthXAxisFormatter()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java deleted file mode 100644 index ffa49ec24f..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MonthXAxisFormatter.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.AxisValueFormatter; - -/** - * Created by Philipp Jahoda on 14/09/15. - */ -public class MonthXAxisFormatter implements AxisValueFormatter { - - protected String[] mMonths = new String[]{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" - }; - - public MonthXAxisFormatter() { - // maybe do something here or provide parameters in constructor - - } - - @Override - public String getFormattedValue(float value, AxisBase axis) { - - float percent = value / axis.mAxisRange; - return mMonths[(int) (mMonths.length * percent)]; - } - - @Override - public int getDecimalDigits() { - return 0; - } -} From ec880022ab3d214255e23a18c45912e5b192f019 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 15:53:03 +0200 Subject: [PATCH 0936/1390] Fine tuning of days example --- .../mpchartexample/BarChartActivity.java | 72 +++++++++++-------- .../charting/charts/BarLineChartBase.java | 12 +++- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 6c8fcca1c2..3979f4983a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -35,6 +35,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -87,6 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day + xAxis.setLabelCount(7); xAxis.setValueFormatter(new DayAxisFormatter()); AxisValueFormatter custom = new MyAxisValueFormatter(); @@ -233,7 +235,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - float start = 0.5f; + float start = 0f; mChart.getXAxis().setAxisMinValue(start); mChart.getXAxis().setAxisMaxValue(start + count); @@ -299,39 +301,47 @@ private class DayAxisFormatter implements AxisValueFormatter { @Override public String getFormattedValue(float value, AxisBase axis) { - + int dayOfYear = (int) value; int month = determineMonth(dayOfYear); - int dayOfMonth = determineDayOfMonth(dayOfYear, month); - - String appendix = "th"; - - switch (dayOfMonth) { - case 1: - appendix = "st"; - break; - case 2: - appendix = "nd"; - break; - case 3: - appendix = "rd"; - break; - case 21: - appendix = "st"; - break; - case 22: - appendix = "nd"; - break; - case 23: - appendix = "rd"; - break; - case 31: - appendix = "st"; - break; - } + String monthName = mMonths[month % mMonths.length]; + + if (mChart.getVisibleXRange() > 30 * axis.getLabelCount()) { + + return monthName; + } else { + + int dayOfMonth = determineDayOfMonth(dayOfYear, month); + + String appendix = "th"; + + switch (dayOfMonth) { + case 1: + appendix = "st"; + break; + case 2: + appendix = "nd"; + break; + case 3: + appendix = "rd"; + break; + case 21: + appendix = "st"; + break; + case 22: + appendix = "nd"; + break; + case 23: + appendix = "rd"; + break; + case 31: + appendix = "st"; + break; + } - return dayOfMonth + appendix + " " + mMonths[month % mMonths.length]; + return dayOfMonth + appendix + " " + monthName; + } } private int getDaysForMonth(int month) { @@ -356,7 +366,7 @@ private int determineMonth(int dayOfYear) { days += getDaysForMonth(month); } - return month; + return Math.max(month, 0); } private int determineDayOfMonth(int dayOfYear, int month) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index bac69f2633..2c31f9ba92 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -717,7 +717,8 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis.mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis + .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); @@ -1328,6 +1329,15 @@ public float getHighestVisibleX() { return (float) Math.min(mXAxis.mAxisMaximum, pos.x); } + /** + * Returns the range visible on the x-axis. + * + * @return + */ + public float getVisibleXRange() { + return Math.abs(getHighestVisibleX() - getLowestVisibleX()); + } + /** * returns the current xPx-scale factor */ From 11212eb72dcc67bbbed4c09928f98b580b2fc524 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 17:16:34 +0200 Subject: [PATCH 0937/1390] Write example of day axis formatter --- .../mpchartexample/BarChartActivity.java | 112 +------------ .../custom/DayAxisValueFormatter.java | 147 ++++++++++++++++++ 2 files changed, 155 insertions(+), 104 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 3979f4983a..d77962f5cf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -36,6 +36,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.ViewPortHandler; +import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -89,7 +90,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day xAxis.setLabelCount(7); - xAxis.setValueFormatter(new DayAxisFormatter()); + xAxis.setValueFormatter(new DayAxisValueFormatter(mChart)); AxisValueFormatter custom = new MyAxisValueFormatter(); @@ -214,23 +215,21 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvX.setText("" + (mSeekBarX.getProgress() + 2)); tvY.setText("" + (mSeekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(mSeekBarX.getProgress() + 1 , mSeekBarY.getProgress()); mChart.invalidate(); } @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub - } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub - } private void setData(int count, float range) { @@ -238,11 +237,11 @@ private void setData(int count, float range) { float start = 0f; mChart.getXAxis().setAxisMinValue(start); - mChart.getXAxis().setAxisMaxValue(start + count); + mChart.getXAxis().setAxisMaxValue(start + count + 2); ArrayList yVals1 = new ArrayList(); - for (int i = (int) start; i < start + count; i++) { + for (int i = (int) start; i < start + count + 1; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); yVals1.add(new BarEntry(i + 1f, val)); @@ -290,101 +289,6 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + mChart.getHighestVisibleX()); } - public void onNothingSelected() { - } - - private class DayAxisFormatter implements AxisValueFormatter { - - protected String[] mMonths = new String[]{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" - }; - - @Override - public String getFormattedValue(float value, AxisBase axis) { - - int dayOfYear = (int) value; - - int month = determineMonth(dayOfYear); - String monthName = mMonths[month % mMonths.length]; - - if (mChart.getVisibleXRange() > 30 * axis.getLabelCount()) { - - return monthName; - } else { - - int dayOfMonth = determineDayOfMonth(dayOfYear, month); - - String appendix = "th"; - - switch (dayOfMonth) { - case 1: - appendix = "st"; - break; - case 2: - appendix = "nd"; - break; - case 3: - appendix = "rd"; - break; - case 21: - appendix = "st"; - break; - case 22: - appendix = "nd"; - break; - case 23: - appendix = "rd"; - break; - case 31: - appendix = "st"; - break; - } - - return dayOfMonth + appendix + " " + monthName; - } - } - - private int getDaysForMonth(int month) { - - if (month == 1) { - return 28; - } - - if (month == 3 || month == 5 || month == 8 || month == 10) - return 30; - else - return 31; - } - - private int determineMonth(int dayOfYear) { - - int month = -1; - int days = 0; - - while (days < dayOfYear) { - month++; - days += getDaysForMonth(month); - } - - return Math.max(month, 0); - } - - private int determineDayOfMonth(int dayOfYear, int month) { - - int count = 0; - int days = 0; - - while (count < month) { - days += getDaysForMonth(count); - count++; - } - - return dayOfYear - days; - } - - @Override - public int getDecimalDigits() { - return 0; - } - } + @Override + public void onNothingSelected() { } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java new file mode 100644 index 0000000000..4299f48bce --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -0,0 +1,147 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; + +/** + * Created by philipp on 02/06/16. + */ +public class DayAxisValueFormatter implements AxisValueFormatter { + + protected String[] mMonths = new String[]{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + }; + + private BarLineChartBase chart; + + public DayAxisValueFormatter(BarLineChartBase chart) { + this.chart = chart; + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + + int days = (int) value; + + if (days == 0) + return ""; + + int year = determineYear(days); + + int month = determineMonth(days); + String monthName = mMonths[month % mMonths.length]; + String yearName = String.valueOf(year); + + if (year == 2017) { + System.out.println(""); + } + + if (chart.getVisibleXRange() > 30 * axis.getLabelCount()) { + + return monthName + " " + yearName; + } else { + + int dayOfMonth = determineDayOfMonth(days, month + 12 * (year - 2016)); + + String appendix = "th"; + + switch (dayOfMonth) { + case 1: + appendix = "st"; + break; + case 2: + appendix = "nd"; + break; + case 3: + appendix = "rd"; + break; + case 21: + appendix = "st"; + break; + case 22: + appendix = "nd"; + break; + case 23: + appendix = "rd"; + break; + case 31: + appendix = "st"; + break; + } + + return dayOfMonth + appendix + " " + monthName; + } + } + + private int getDaysForMonth(int month, int year) { + + if (month == 1) { + + if (year == 2016 || year == 2020) + return 29; + else + return 28; + } + + if (month == 3 || month == 5 || month == 8 || month == 10) + return 30; + else + return 31; + } + + private int determineMonth(int dayOfYear) { + + int month = -1; + int days = 0; + + while (days < dayOfYear) { + month = month + 1; + + if (month >= 12) + month = 0; + + int year = determineYear(days); + days += getDaysForMonth(month, year); + } + + return Math.max(month, 0); + } + + private int determineDayOfMonth(int dayOfYear, int month) { + + int count = 0; + int days = 0; + + while (count < month) { + + int year = determineYear(days); + days += getDaysForMonth(count % 12, year); + count++; + } + + return dayOfYear - days; + } + + private int determineYear(int days) { + + if (days <= 366) + return 2016; + else if (days <= 730) + return 2017; + else if (days <= 1094) + return 2018; + else if (days <= 1458) + return 2019; + else + return 2020; + + } + + @Override + public int getDecimalDigits() { + return 0; + } +} From 0632fedfd287e43c91195ca855c327305dbd801d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 19:16:05 +0200 Subject: [PATCH 0938/1390] Work on improving example --- .../HorizontalBarChartActivity.java | 12 +-- .../InvertedLineChartActivity.java | 18 ++-- .../ListViewBarChartActivity.java | 2 +- .../StackedBarActivityNegative.java | 43 ++++++--- .../mikephil/charting/charts/BarChart.java | 3 - .../renderer/XAxisRendererBarChart.java | 34 +++---- .../XAxisRendererHorizontalBarChart.java | 89 ++++++++++++++++--- ...xComparator.java => EntryXComparator.java} | 4 +- 8 files changed, 138 insertions(+), 67 deletions(-) rename MPChartLib/src/main/java/com/github/mikephil/charting/utils/{EntryXIndexComparator.java => EntryXComparator.java} (76%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index afe35d1e10..b571fc7d2b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -75,12 +75,8 @@ protected void onCreate(Bundle savedInstanceState) { // draw shadows for each bar that show the maximum yValue // mChart.setDrawBarShadow(true); - // mChart.setDrawXLabels(false); - mChart.setDrawGridBackground(false); - // mChart.setDrawYLabels(false); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis xl = mChart.getXAxis(); @@ -89,6 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { xl.setDrawAxisLine(true); xl.setDrawGridLines(true); xl.setGridLineWidth(0.3f); + xl.setGranularity(10f); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); @@ -232,11 +229,13 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { + float barWidth = 9f; + float spaceForBar = 10f; ArrayList yVals1 = new ArrayList(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range); - yVals1.add(new BarEntry(i, val)); + yVals1.add(new BarEntry(i * spaceForBar, val)); } BarDataSet set1; @@ -256,7 +255,7 @@ private void setData(int count, float range) { BarData data = new BarData(dataSets); data.setValueTextSize(10f); data.setValueTypeface(tf); - + data.setBarWidth(barWidth); mChart.setData(data); } } @@ -276,6 +275,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("position", position.toString()); } + @Override public void onNothingSelected() { }; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index fe0a4cc6f1..0b6900637f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -22,10 +22,12 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.EntryXComparator; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class InvertedLineChartActivity extends DemoBase implements OnSeekBarChangeListener, @@ -83,6 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); + xl.setAxisMinValue(0f); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setInverted(true); @@ -253,18 +256,19 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList yVals = new ArrayList(); + ArrayList entries = new ArrayList(); for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10); - yVals.add(new Entry(val, i)); + float xVal = (float) (Math.random() * range); + float yVal = (float) (Math.random() * range); + entries.add(new Entry(xVal, yVal)); } + // sort by x-value + Collections.sort(entries, new EntryXComparator()); + // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + LineDataSet set1 = new LineDataSet(entries, "DataSet 1"); set1.setLineWidth(1.5f); set1.setCircleRadius(4f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index ce58acaf41..0a998bce96 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -132,7 +132,7 @@ private BarData generateData(int cnt) { ArrayList entries = new ArrayList(); for (int i = 0; i < 12; i++) { - entries.add(new BarEntry((int) (Math.random() * 70) + 30, i)); + entries.add(new BarEntry(i, (float) (Math.random() * 70) + 30)); } BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index cbf4bb4fe5..9aa82fc614 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -71,6 +71,25 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); xAxis.setTextSize(9f); + xAxis.setAxisMinValue(0f); + xAxis.setAxisMaxValue(110f); + xAxis.setCenterAxisLabels(true); + xAxis.setLabelCount(12); + xAxis.setGranularity(10f); + xAxis.setValueFormatter(new AxisValueFormatter() { + + private DecimalFormat format = new DecimalFormat("###"); + + @Override + public String getFormattedValue(float value, AxisBase axis) { + return format.format(value) + "-" + format.format(value + 10); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); Legend l = mChart.getLegend(); l.setPosition(LegendPosition.BELOW_CHART_RIGHT); @@ -80,17 +99,17 @@ protected void onCreate(Bundle savedInstanceState) { // IMPORTANT: When using negative values in stacked bars, always make sure the negative values are in the array first ArrayList yValues = new ArrayList(); - yValues.add(new BarEntry(0, new float[]{ -10, 10 })); - yValues.add(new BarEntry(1, new float[]{ -12, 13 })); - yValues.add(new BarEntry(2, new float[]{ -15, 15 })); - yValues.add(new BarEntry(3, new float[]{ -17, 17 })); - yValues.add(new BarEntry(4, new float[]{ -19, 20 })); - yValues.add(new BarEntry(5, new float[]{ -19, 19 })); - yValues.add(new BarEntry(6, new float[]{ -16, 16 })); - yValues.add(new BarEntry(7, new float[]{ -13, 14 })); - yValues.add(new BarEntry(8, new float[]{ -10, 11 })); - yValues.add(new BarEntry(9, new float[]{ -5, 6 })); - yValues.add(new BarEntry(10, new float[]{ -1, 2 })); + yValues.add(new BarEntry(5, new float[]{ -10, 10 })); + yValues.add(new BarEntry(15, new float[]{ -12, 13 })); + yValues.add(new BarEntry(25, new float[]{ -15, 15 })); + yValues.add(new BarEntry(35, new float[]{ -17, 17 })); + yValues.add(new BarEntry(45, new float[]{ -19, 20 })); + yValues.add(new BarEntry(55, new float[]{ -19, 19 })); + yValues.add(new BarEntry(65, new float[]{ -16, 16 })); + yValues.add(new BarEntry(75, new float[]{ -13, 14 })); + yValues.add(new BarEntry(85, new float[]{ -10, 11 })); + yValues.add(new BarEntry(95, new float[]{ -5, 6 })); + yValues.add(new BarEntry(105, new float[]{ -1, 2 })); BarDataSet set = new BarDataSet(yValues, "Age Distribution"); set.setValueFormatter(new CustomFormatter()); @@ -104,7 +123,7 @@ protected void onCreate(Bundle savedInstanceState) { String []xLabels = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; BarData data = new BarData(set); - data.setBarWidth(0.8f); + data.setBarWidth(8.5f); mChart.setData(data); mChart.invalidate(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 2c387c8488..050c1be8d2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -5,7 +5,6 @@ import android.util.AttributeSet; import android.util.Log; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.BarHighlighter; @@ -13,7 +12,6 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.renderer.BarChartRenderer; -import com.github.mikephil.charting.renderer.XAxisRendererBarChart; /** * Chart that draws bars. @@ -52,7 +50,6 @@ protected void init() { super.init(); mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); - mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); setHighlighter(new BarHighlighter(this)); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index ad36599444..0be78ca0e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -1,27 +1,17 @@ package com.github.mikephil.charting.renderer; -import android.graphics.Canvas; -import android.graphics.PointF; - -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.utils.Transformer; -import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ViewPortHandler; - -public class XAxisRendererBarChart extends XAxisRenderer { - - protected BarChart mChart; - - public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, - BarChart chart) { - super(viewPortHandler, xAxis, trans); - - this.mChart = chart; - } - +//public class XAxisRendererBarChart extends XAxisRenderer { +// +// protected BarChart mChart; +// +// public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, +// BarChart chart) { +// super(viewPortHandler, xAxis, trans); +// +// this.mChart = chart; +// } +// // /** // * draws the xPx-labels on the specified yPx-position // * @@ -80,4 +70,4 @@ public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Trans //// } //// } // } -} +//} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9e37f729f0..4b40a35778 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -13,17 +13,46 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; -public class XAxisRendererHorizontalBarChart extends XAxisRendererBarChart { +public class XAxisRendererHorizontalBarChart extends XAxisRenderer { + + protected BarChart mChart; public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, BarChart chart) { - super(viewPortHandler, xAxis, trans, chart); + super(viewPortHandler, xAxis, trans); + + this.mChart = chart; + } + + @Override + public void computeAxis(float min, float max, boolean inverted) { + + // calculate the starting and entry point of the yPx-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + + if (inverted) { + + min = (float) p2.y; + max = (float) p1.y; + } else { + + min = (float) p1.y; + max = (float) p2.y; + } + } + + computeAxisValues(min, max); } @Override @@ -91,24 +120,56 @@ public void renderAxisLabels(Canvas c) { } } - /** - * draws the xPx-labels on the specified yPx-position - * - * @param pos - */ @Override protected void drawLabels(Canvas c, float pos, PointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); + boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - // pre allocate to save performance (dont allocate in loop) - float[] position = new float[] { - 0f, 0f - }; + float[] positions = new float[mXAxis.mEntryCount * 2]; - BarData bd = mChart.getData(); - int step = bd.getDataSetCount(); + for (int i = 0; i < positions.length; i += 2) { + + // only fill xPx values + if (centeringEnabled) { + positions[i + 1] = mXAxis.mCenteredEntries[i / 2]; + } else { + positions[i + 1] = mXAxis.mEntries[i / 2]; + } + } + + mTrans.pointValuesToPixel(positions); + for (int i = 0; i < positions.length; i += 2) { + + float y = positions[i + 1]; + + if (mViewPortHandler.isInBoundsY(y)) { + + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); + drawLabel(c, label, pos, y, anchor, labelRotationAngleDegrees); + } + } + } + +// /** +// * draws the xPx-labels on the specified yPx-position +// * +// * @param pos +// */ +// @Override +// protected void drawLabels(Canvas c, float pos, PointF anchor) { +// +// final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); +// +// // pre allocate to save performance (dont allocate in loop) +// float[] position = new float[] { +// 0f, 0f +// }; +// +// BarData bd = mChart.getData(); +// int step = bd.getDataSetCount(); +// // for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { // // position[1] = i * step + i * bd.getGroupSpace() @@ -127,7 +188,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { // drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); // } // } - } +// } @Override public void renderGridLines(Canvas c) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXComparator.java similarity index 76% rename from MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXComparator.java index ed9045a25e..8f59c12d07 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXIndexComparator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/EntryXComparator.java @@ -5,10 +5,10 @@ import java.util.Comparator; /** - * Comparator for comparing Entry-objects by their xPx-index. + * Comparator for comparing Entry-objects by their x-value. * Created by philipp on 17/06/15. */ -public class EntryXIndexComparator implements Comparator { +public class EntryXComparator implements Comparator { @Override public int compare(Entry entry1, Entry entry2) { float diff = entry1.getX() - entry2.getX(); From b4268fc5022e34394e79d99cf12d7e8f62521c12 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 19:22:24 +0200 Subject: [PATCH 0939/1390] Work on candlestick chart rendering --- .../renderer/CandleStickChartRenderer.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 04b97f31cc..df1fb3da60 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -7,6 +7,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -54,6 +56,8 @@ public void drawData(Canvas c) { @SuppressWarnings("ResourceAsColor") protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { + int entryCount = dataSet.getEntryCount(); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); @@ -61,8 +65,15 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { float barSpace = dataSet.getBarSpace(); boolean showCandleBar = dataSet.getShowCandleBar(); - int minx = Math.max((int) mChart.getLowestVisibleX(), 0); - int maxx = Math.min((int) mChart.getHighestVisibleX(), dataSet.getEntryCount()); + float lowX = mChart.getLowestVisibleX(); + float highX = mChart.getHighestVisibleX(); + + CandleEntry entryFrom = dataSet.getEntryForXPos(lowX, DataSet.Rounding.DOWN); + CandleEntry entryTo = dataSet.getEntryForXPos(highX, DataSet.Rounding.UP); + + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); + int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); From a25290742df991004d4c6d4654295446cd00bdc0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 19:49:01 +0200 Subject: [PATCH 0940/1390] Work on dynamic adding examples --- .../DynamicalAddingActivity.java | 74 ++++++++----------- .../LineChartActivityColored.java | 2 +- .../RealtimeLineChartActivity.java | 33 ++++++--- 3 files changed, 55 insertions(+), 54 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 48aace6cb4..886a8f7ed2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -36,7 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); mChart.setDescription(""); - + // add an empty data object mChart.setData(new LineData()); // mChart.getXAxis().setDrawLabels(false); @@ -50,42 +50,39 @@ protected void onCreate(Bundle savedInstanceState) { private void addEntry() { LineData data = mChart.getData(); - - if(data != null) { - ILineDataSet set = data.getDataSetByIndex(0); - // set.addEntry(...); // can be called as well + ILineDataSet set = data.getDataSetByIndex(0); + // set.addEntry(...); // can be called as well - if (set == null) { - set = createSet(); - data.addDataSet(set); - } + if (set == null) { + set = createSet(); + data.addDataSet(set); + } - // add a new xPx-yValue first - //data.addXValue(new XAxisValue(set.getEntryCount(), set.getEntryCount() + "")); - - // choose a random dataSet - int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); - - data.addEntry(new Entry((float) (Math.random() * 10) + 50f, set.getEntryCount()), randomDataSetIndex); + // choose a random dataSet + int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); + float yValue = (float) (Math.random() * 10) + 50f; - // let the chart know it's data has changed - mChart.notifyDataSetChanged(); - - mChart.setVisibleXRangeMaximum(6); - mChart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); + data.addEntry(new Entry(data.getDataSetByIndex(randomDataSetIndex).getEntryCount(), yValue), randomDataSetIndex); + data.notifyDataChanged(); + + // let the chart know it's data has changed + mChart.notifyDataSetChanged(); + + mChart.setVisibleXRangeMaximum(6); + //mChart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); // // // this automatically refreshes the chart (calls invalidate()) - mChart.moveViewTo(data.getEntryCount()-7, 50f, AxisDependency.LEFT); - } + mChart.moveViewTo(data.getEntryCount() - 7, 50f, AxisDependency.LEFT); + } private void removeLastEntry() { LineData data = mChart.getData(); - - if(data != null) { - + + if (data != null) { + ILineDataSet set = data.getDataSetByIndex(0); if (set != null) { @@ -95,7 +92,7 @@ private void removeLastEntry() { data.removeEntry(e, 0); // or remove by index // mData.removeEntry(xIndex, dataSetIndex); - + data.notifyDataChanged(); mChart.notifyDataSetChanged(); mChart.invalidate(); } @@ -105,23 +102,15 @@ private void removeLastEntry() { private void addDataSet() { LineData data = mChart.getData(); - - if(data != null) { + + if (data != null) { int count = (data.getDataSetCount() + 1); - // create 10 yPx-vals ArrayList yVals = new ArrayList(); - - if(data.getEntryCount() == 0) { - // add 10 xPx-entries - for (int i = 0; i < 10; i++) { - //data.addXValue(new XAxisValue(i, i + "")); - } - } for (int i = 0; i < data.getEntryCount(); i++) { - yVals.add(new Entry((float) (Math.random() * 50f) + 50f * count, i)); + yVals.add(new Entry(i, (float) (Math.random() * 50f) + 50f * count)); } LineDataSet set = new LineDataSet(yVals, "DataSet " + count); @@ -137,21 +126,22 @@ private void addDataSet() { set.setValueTextColor(color); data.addDataSet(set); + data.notifyDataChanged(); mChart.notifyDataSetChanged(); - mChart.invalidate(); + mChart.invalidate(); } } private void removeDataSet() { LineData data = mChart.getData(); - - if(data != null) { + + if (data != null) { data.removeDataSet(data.getDataSetByIndex(data.getDataSetCount() - 1)); mChart.notifyDataSetChanged(); - mChart.invalidate(); + mChart.invalidate(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index c452dda6bb..2ae7d0e4df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -104,7 +104,7 @@ private LineData getData(int count, float range) { for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range) + 3; - yVals.add(new Entry(val, i)); + yVals.add(new Entry(i, val)); } // create a dataset and give it a type diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 833428e613..95f260bce9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -121,8 +121,6 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - private int year = 2015; - private void addEntry() { LineData data = mChart.getData(); @@ -137,11 +135,8 @@ private void addEntry() { data.addDataSet(set); } - // add a new xPx-yValue first -// data.addXValue(new XAxisValue(data.getXValCount() ,mMonths[data.getXValCount() % 12] + " " -// + (year + data.getXValCount() / 12))); - data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); - + data.addEntry(new Entry(set.getEntryCount(), (float) (Math.random() * 40) + 30f), 0); + data.notifyDataChanged(); // let the chart know it's data has changed mChart.notifyDataSetChanged(); @@ -176,13 +171,18 @@ private LineDataSet createSet() { return set; } + private Thread thread; + private void feedMultiple() { - new Thread(new Runnable() { + if(thread != null) + thread.interrupt(); + + thread = new Thread(new Runnable() { @Override public void run() { - for(int i = 0; i < 500; i++) { + for(int i = 0; i < 1000; i++) { runOnUiThread(new Runnable() { @@ -193,14 +193,16 @@ public void run() { }); try { - Thread.sleep(35); + Thread.sleep(25); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } - }).start(); + }); + + thread.start(); } @Override @@ -212,4 +214,13 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { public void onNothingSelected() { Log.i("Nothing selected", "Nothing selected."); } + + @Override + protected void onPause() { + super.onPause(); + + if(thread != null) { + thread.interrupt(); + } + } } From bfcbae4263b53a410305e81cc4f8c04b4e66633e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 20:02:49 +0200 Subject: [PATCH 0941/1390] Fix issue related to barchart value labels --- .../BarChartPositiveNegative.java | 31 +++++++++++++++---- .../charting/renderer/BarChartRenderer.java | 3 +- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 029e7936f5..8dfad58845 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -7,6 +7,7 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -14,6 +15,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -58,6 +60,11 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setTextColor(Color.LTGRAY); xAxis.setTextSize(13f); + xAxis.setAxisMinValue(0f); + xAxis.setAxisMaxValue(5f); + xAxis.setLabelCount(5); + xAxis.setCenterAxisLabels(true); + xAxis.setGranularity(1f); YAxis left = mChart.getAxisLeft(); left.setDrawLabels(false); @@ -73,12 +80,24 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setEnabled(false); // THIS IS THE ORIGINAL DATA YOU WANT TO PLOT - List data = new ArrayList<>(); - data.add(new Data(0, -224.1f, "12-29")); - data.add(new Data(1, 238.5f, "12-30")); - data.add(new Data(2, 1280.1f, "12-31")); - data.add(new Data(3, -442.3f, "01-01")); - data.add(new Data(4, -2280.1f, "01-02")); + final List data = new ArrayList<>(); + data.add(new Data(0.5f, -224.1f, "12-29")); + data.add(new Data(1.5f, 238.5f, "12-30")); + data.add(new Data(2.5f, 1280.1f, "12-31")); + data.add(new Data(3.5f, -442.3f, "01-01")); + data.add(new Data(4.5f, -2280.1f, "01-02")); + + xAxis.setValueFormatter(new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); setData(data); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 7aeec4ce90..8c81fb5eba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -236,7 +236,7 @@ public void drawValues(Canvas c) { float val = entry.getY(); drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, - buffer.buffer[j + 1] + (val >= 0 ? posOffset : negOffset), dataSet.getValueTextColor + val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), dataSet.getValueTextColor (j / 4)); } @@ -327,7 +327,6 @@ public void drawValues(Canvas c) { public void drawHighlighted(Canvas c, Highlight[] indices) { BarData barData = mChart.getBarData(); - int setCount = barData.getDataSetCount(); for (Highlight high : indices) { From 4ae9950632a38aad0cf2083fa2b667ee02c3a90e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 20:10:37 +0200 Subject: [PATCH 0942/1390] Work on radarchart rendering --- .../mpchartexample/BarChartPositiveNegative.java | 1 - .../github/mikephil/charting/charts/RadarChart.java | 5 ++--- .../charting/renderer/RadarChartRenderer.java | 11 +++-------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 8dfad58845..5e279db25f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -68,7 +68,6 @@ protected void onCreate(Bundle savedInstanceState) { YAxis left = mChart.getAxisLeft(); left.setDrawLabels(false); - left.setStartAtZero(false); left.setSpaceTop(25f); left.setSpaceBottom(25f); left.setDrawAxisLine(false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index b0adde7f69..6f2a19e79d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -179,8 +179,7 @@ protected void onDraw(Canvas canvas) { */ public float getFactor() { RectF content = mViewPortHandler.getContentRect(); - return (float) Math.min(content.width() / 2f, content.height() / 2f) - / mYAxis.mAxisRange; + return Math.min(content.width() / 2f, content.height() / 2f) / mYAxis.mAxisRange; } /** @@ -189,7 +188,7 @@ public float getFactor() { * @return */ public float getSliceAngle() { - return 360f / (float) mData.getEntryCount(); + return 360f / (float) mData.getMaxEntryCountSet().getEntryCount(); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index ffdd8685cb..e8c086c9d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -59,13 +59,7 @@ public void drawData(Canvas c) { RadarData radarData = mChart.getData(); - int mostEntries = 0; - - for (IRadarDataSet set : radarData.getDataSets()) { - if (set.getEntryCount() > mostEntries) { - mostEntries = set.getEntryCount(); - } - } + int mostEntries = radarData.getMaxEntryCountSet().getEntryCount(); for (IRadarDataSet set : radarData.getDataSets()) { @@ -217,8 +211,9 @@ protected void drawWeb(Canvas c) { mWebPaint.setAlpha(mChart.getWebAlpha()); final int xIncrements = 1 + mChart.getSkipWebLineCount(); + int maxEntryCount = mChart.getData().getMaxEntryCountSet().getEntryCount(); - for (int i = 0; i < mChart.getData().getEntryCount(); i += xIncrements) { + for (int i = 0; i < maxEntryCount; i += xIncrements) { PointF p = Utils.getPosition( center, From 639d3359093ac91f52e5da7718834b034ed491b9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 22:57:48 +0200 Subject: [PATCH 0943/1390] Work on radarchart rendering, cleanup xaxis --- .../mpchartexample/RadarChartActivitry.java | 13 ++++ .../mpchartexample/ScrollViewActivity.java | 1 - .../charting/charts/BarLineChartBase.java | 30 -------- .../charting/charts/HorizontalBarChart.java | 13 ---- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 8 ++- .../mikephil/charting/components/XAxis.java | 49 ------------- .../mikephil/charting/data/BaseEntry.java | 63 ++++++++++++++++ .../github/mikephil/charting/data/Entry.java | 71 ++++--------------- .../mikephil/charting/data/RadarData.java | 25 +++++++ .../charting/renderer/XAxisRenderer.java | 24 ------- .../renderer/XAxisRendererRadarChart.java | 10 +-- 12 files changed, 128 insertions(+), 181 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 672fa2b261..66d9f537e5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; @@ -17,6 +18,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -64,6 +66,17 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); xAxis.setTextSize(9f); + xAxis.setValueFormatter(new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mMonths[(int) value % mMonths.length]; + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); YAxis yAxis = mChart.getYAxis(); yAxis.setTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 3d9f07f85d..0204147df7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -38,7 +38,6 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setLabelsToSkip(0); xAxis.setDrawGridLines(false); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 2c31f9ba92..2768ad89df 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -197,7 +197,6 @@ protected void onDraw(Canvas canvas) { return; long starttime = System.currentTimeMillis(); - calcModulus(); // execute all drawing commands drawGridBackground(canvas); @@ -523,35 +522,6 @@ public void calculateOffsets() { prepareValuePxMatrix(); } - /** - * calculates the modulus for xPx-labels and grid - */ - protected void calcModulus() { - -// if (mXAxis == null || !mXAxis.isEnabled()) -// return; -// -// if (!mXAxis.isAxisModulusCustom()) { -// -// float[] values = new float[9]; -// mViewPortHandler.getMatrixTouch().getValues(values); -// -// mXAxis.mAxisLabelModulus = (int) Math -// .ceil((mData.getXValCount() * mXAxis.mLabelRotatedWidth) -// / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); -// -// } -// -// if (mLogEnabled) -// Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + -// ", xPx-axis label width: " + mXAxis.mLabelWidth + -// ", xPx-axis label rotated width: " + mXAxis.mLabelRotatedWidth + -// ", content width: " + mViewPortHandler.contentWidth()); -// -// if (mXAxis.mAxisLabelModulus < 1) -// mXAxis.mAxisLabelModulus = 1; - } - @Override protected float[] getMarkerPosition(Entry e, Highlight highlight) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index d917b8547d..c51d102bda 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -131,19 +131,6 @@ protected void prepareValuePxMatrix() { mXAxis.mAxisMinimum); } - @Override - protected void calcModulus() { -// float[] values = new float[9]; -// mViewPortHandler.getMatrixTouch().getValues(values); -// -// mXAxis.mAxisLabelModulus = -// (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) -// / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); -// -// if (mXAxis.mAxisLabelModulus < 1) -// mXAxis.mAxisLabelModulus = 1; - } - @Override public RectF getBarBounds(BarEntry e) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index c3d14c042a..9dbdfc8974 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -217,7 +217,7 @@ public void calculateOffsets() { XAxis x = this.getXAxis(); if (x.isEnabled() && x.isDrawLabelsEnabled()) { - minOffset = Math.max(minOffset, x.mLabelRotatedWidth); + minOffset = Math.max(minOffset, x.mLabelRotatedWidth * 2f); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 6f2a19e79d..94af22eab0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -104,6 +104,7 @@ protected void calcMinMax() { // mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); mYAxis.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); + mXAxis.calculate(0, mData.getMaxEntryCountSet().getEntryCount()); } @Override @@ -134,7 +135,6 @@ public void notifyDataSetChanged() { mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); - //mXAxisRenderer.computeSize(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null && !mLegend.isLegendCustom()) mLegendRenderer.computeLegend(mData); @@ -149,6 +149,12 @@ protected void onDraw(Canvas canvas) { if (mData == null) return; + if (mYAxis.isEnabled()) + mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); + + if (mXAxis.isEnabled()) + mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); + mXAxisRenderer.renderAxisLabels(canvas); if (mDrawWeb) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index 3e796f5365..be48c164b7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -41,18 +41,6 @@ public class XAxis extends AxisBase { */ protected float mLabelRotationAngle = 0f; - /** - * the modulus that indicates if a yValue at a specified index in an - * array(list) for the xPx-axis-labels is drawn or not. If index % modulus == - * 0 DRAW, else dont draw. - */ - public int mAxisLabelModulus = 1; - - /** - * Is axisLabelModulus a custom yValue or auto calculated? If false, then - * it's auto, if true, then custom. default: false (automatic modulus) - */ - private boolean mIsAxisModulusCustom = false; /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart @@ -109,43 +97,6 @@ public void setLabelRotationAngle(float angle) { mLabelRotationAngle = angle; } - /** - * Sets the number of labels that should be skipped on the axis before the - * next label is drawn. This will disable the feature that automatically - * calculates an adequate space between the axis labels and set the number - * of labels to be skipped to the fixed number provided by this method. Call - * resetLabelsToSkip(...) to re-enable automatic calculation. - * - * @param count - */ - public void setLabelsToSkip(int count) { - - if (count < 0) - count = 0; - - mIsAxisModulusCustom = true; - mAxisLabelModulus = count + 1; - } - - /** - * Calling this will disable a custom number of labels to be skipped (set by - * setLabelsToSkip(...)) while drawing the xPx-axis. Instead, the number of - * values to skip will again be calculated automatically. - */ - public void resetLabelsToSkip() { - mIsAxisModulusCustom = false; - } - - /** - * Returns true if a custom axis-modulus has been set that determines the - * number of labels to skip when drawing. - * - * @return - */ - public boolean isAxisModulusCustom() { - return mIsAxisModulusCustom; - } - /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart or the screen diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java new file mode 100644 index 0000000000..48e773edfe --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java @@ -0,0 +1,63 @@ +package com.github.mikephil.charting.data; + +/** + * Created by Philipp Jahoda on 02/06/16. + */ +public abstract class BaseEntry { + + /** the y value */ + private float y = 0f; + + /** optional spot for additional data this Entry represents */ + private Object mData = null; + + public BaseEntry() { + + } + + public BaseEntry(float y) { + this.y = y; + } + + public BaseEntry(float y, Object data) { + this(y); + this.mData = data; + } + + /** + * Returns the yPx yValue of this Entry. + * + * @return + */ + public float getY() { + return y; + } + + /** + * Sets the yPx-yValue for the Entry. + * + * @param y + */ + public void setY(float y) { + this.y = y; + } + + /** + * Returns the data, additional information that this Entry represents, or + * null, if no data has been specified. + * + * @return + */ + public Object getData() { + return mData; + } + + /** + * Sets additional data this Entry should represent. + * + * @param data + */ + public void setData(Object data) { + this.mData = data; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 834f46b202..7c23e500e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -11,17 +11,11 @@ * * @author Philipp Jahoda */ -public class Entry implements Parcelable { +public class Entry extends BaseEntry implements Parcelable { - /** the yPx yValue */ - private float y = 0f; - - /** the xPx yValue */ + /** the x value */ private float x = 0f; - /** optional spot for additional data this Entry represents */ - private Object mData = null; - public Entry() { } @@ -33,7 +27,7 @@ public Entry() { * @param y the yPx yValue (the actual yValue of the entry) */ public Entry(float x, float y) { - this.y = y; + super(y); this.x = x; } @@ -45,8 +39,8 @@ public Entry(float x, float y) { * @param data Spot for additional data this Entry represents. */ public Entry(float x, float y, Object data) { - this(x, y); - this.mData = data; + super(y, data); + this.x = x; } /** @@ -67,50 +61,13 @@ public void setX(float x) { this.x = x; } - /** - * Returns the yPx yValue of this Entry. - * - * @return - */ - public float getY() { - return y; - } - - /** - * Sets the yPx-yValue for the Entry. - * - * @param y - */ - public void setY(float y) { - this.y = y; - } - - /** - * Returns the data, additional information that this Entry represents, or - * null, if no data has been specified. - * - * @return - */ - public Object getData() { - return mData; - } - - /** - * Sets additional data this Entry should represent. - * - * @param data - */ - public void setData(Object data) { - this.mData = data; - } - /** * returns an exact copy of the entry * * @return */ public Entry copy() { - Entry e = new Entry(x, y, mData); + Entry e = new Entry(x, getY(), getData()); return e; } @@ -127,13 +84,13 @@ public boolean equalTo(Entry e) { if (e == null) return false; - if (e.mData != this.mData) + if (e.getData() != this.getData()) return false; if (Math.abs(e.x - this.x) > 0.000001f) return false; - if (Math.abs(e.y - this.y) > 0.000001f) + if (Math.abs(e.getY() - this.getY()) > 0.000001f) return false; return true; @@ -155,11 +112,11 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeFloat(this.x); - dest.writeFloat(this.y); - if (mData != null) { - if (mData instanceof Parcelable) { + dest.writeFloat(this.getY()); + if (getData() != null) { + if (getData() instanceof Parcelable) { dest.writeInt(1); - dest.writeParcelable((Parcelable) this.mData, flags); + dest.writeParcelable((Parcelable) this.getData(), flags); } else { throw new ParcelFormatException("Cannot parcel an Entry with non-parcelable data"); } @@ -170,9 +127,9 @@ public void writeToParcel(Parcel dest, int flags) { protected Entry(Parcel in) { this.x = in.readFloat(); - this.y = in.readFloat(); + this.setY(in.readFloat()); if (in.readInt() == 1) { - this.mData = in.readParcelable(Object.class.getClassLoader()); + this.setData(in.readParcelable(Object.class.getClassLoader())); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java index bfb38c3e13..811414139a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -13,6 +14,8 @@ */ public class RadarData extends ChartData { + private List mLabels; + public RadarData() { super(); } @@ -24,4 +27,26 @@ public RadarData(List dataSets) { public RadarData(IRadarDataSet... dataSets) { super(dataSets); } + + /** + * Sets the labels that should be drawn around the RadarChart at the end of each web line. + * + * @param labels + */ + public void setLabels(List labels) { + this.mLabels = labels; + } + + /** + * Sets the labels that should be drawn around the RadarChart at the end of each web line. + * + * @param labels + */ + public void setLabels(String... labels) { + this.mLabels = Arrays.asList(labels); + } + + public List getLabels() { + return mLabels; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 0f13346701..c9354056c0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -59,30 +59,6 @@ public void computeAxis(float min, float max, boolean inverted) { @Override protected void computeAxisValues(float min, float max) { - -// int labelCount = mXAxis.getLabelCount(); -// float range = Math.abs(max - min); -// -// float interval = range / (labelCount - 1); -// -// if (mXAxis.mEntries == null || mXAxis.mEntries.length != labelCount) { -// mXAxis.mEntries = new float[labelCount]; -// mXAxis.mEntryCount = labelCount; -// } -// -// mXAxis.mEntries[0] = min; -// -// for (int i = 1; i < labelCount; i++) { -// mXAxis.mEntries[i] = min + interval * (float) i; -// } -// -// // set decimals -// if (interval < 1) { -// mXAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); -// } else { -// mXAxis.mDecimals = 0; -// } - super.computeAxisValues(min, max); computeSize(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 6c505bc5ba..8dd2191001 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -26,7 +26,7 @@ public void renderAxisLabels(Canvas c) { return; final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - final PointF drawLabelAnchor = new PointF(0.5f, 0.0f); + final PointF drawLabelAnchor = new PointF(0.5f, 0.25f); mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -40,14 +40,14 @@ public void renderAxisLabels(Canvas c) { PointF center = mChart.getCenterOffsets(); - int mod = mXAxis.mAxisLabelModulus; - for (int i = 0; i < mXAxis.mEntryCount; i += mod) { - String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i], mXAxis); + for (int i = 0; i < mChart.getData().getMaxEntryCountSet().getEntryCount(); i++) { + + String label = mXAxis.getValueFormatter().getFormattedValue(i, mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; PointF p = Utils.getPosition(center, mChart.getYRange() * factor - + mXAxis.mLabelRotatedWidth / 2f, angle); + + mXAxis.mLabelRotatedWidth, angle); drawLabel(c, label, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, drawLabelAnchor, labelRotationAngleDegrees); From 8751f608a4b74df01c31e19dd1e793795c202553 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 23:10:02 +0200 Subject: [PATCH 0944/1390] Work on radarchart rendering --- .../mikephil/charting/charts/RadarChart.java | 4 +- .../charting/renderer/AxisRenderer.java | 4 +- .../renderer/YAxisRendererRadarChart.java | 91 ++++++++++++------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 94af22eab0..9e5118d63b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -149,8 +149,8 @@ protected void onDraw(Canvas canvas) { if (mData == null) return; - if (mYAxis.isEnabled()) - mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); +// if (mYAxis.isEnabled()) +// mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); if (mXAxis.isEnabled()) mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index c52b1cb0bb..26260c320e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -19,8 +19,10 @@ */ public abstract class AxisRenderer extends Renderer { - private AxisBase mAxis; + /** base axis this axis renderer works with */ + protected AxisBase mAxis; + /** transformer to transform values to screen pixels and return */ protected Transformer mTrans; /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 5dcaff1fcc..670c8a4eca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -24,21 +24,30 @@ public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, Rad @Override protected void computeAxisValues(float min, float max) { + float yMin = min; float yMax = max; - int labelCount = mYAxis.getLabelCount(); + int labelCount = mAxis.getLabelCount(); double range = Math.abs(yMax - yMin); if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[]{}; - mYAxis.mEntryCount = 0; + mAxis.mEntries = new float[]{}; + mAxis.mEntryCount = 0; return; } + // Find out how much spacing (in yPx yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + + // If granularity is enabled, then do not allow the interval to go below specified granularity. + // This is used to avoid repeated values when rounding values for display. + if (mAxis.isGranularityEnabled()) + interval = interval < mAxis.getGranularity() ? mAxis.getGranularity() : interval; + + // Normalize interval + double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { // Use one order of magnitude higher, to avoid intervals like 0.9 or @@ -46,71 +55,89 @@ protected void computeAxisValues(float min, float max) { interval = Math.floor(10 * intervalMagnitude); } + boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); + int n = centeringEnabled ? 1 : 0; + // force label count - if (mYAxis.isForceLabelsEnabled()) { + if (mAxis.isForceLabelsEnabled()) { float step = (float) range / (float) (labelCount - 1); - mYAxis.mEntryCount = labelCount; + mAxis.mEntryCount = labelCount; - if (mYAxis.mEntries.length < labelCount) { + if (mAxis.mEntries.length < labelCount) { // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[labelCount]; + mAxis.mEntries = new float[labelCount]; } float v = min; for (int i = 0; i < labelCount; i++) { - mYAxis.mEntries[i] = v; + mAxis.mEntries[i] = v; v += step; } + n = labelCount; + // no forced count } else { - final double rawCount = yMin / interval; - double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - - if (first == 0.0) // Fix for IEEE negative zero case (Where yValue == -0.0, and 0.0 == -0.0) - first = 0.0; + double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; + if (centeringEnabled) { + first -= interval; + } - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); double f; int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; + + if (interval != 0.0) { + for (f = first; f <= last; f += interval) { + ++n; + } } - if (!mYAxis.isAxisMaxCustom()) - n += 1; + n++; - mYAxis.mEntryCount = n; + mAxis.mEntryCount = n; - if (mYAxis.mEntries.length < n) { + if (mAxis.mEntries.length < n) { // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; + mAxis.mEntries = new float[n]; } for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; + + if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) + f = 0.0; + + mAxis.mEntries[i] = (float) f; } } + // set decimals if (interval < 1) { - mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + mAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); } else { - mYAxis.mDecimals = 0; + mAxis.mDecimals = 0; } - if (mYAxis.mEntries[0] < yMin) { - // If startAtZero is disabled, and the first label is lower that the axis minimum, - // Then adjust the axis minimum - mYAxis.mAxisMinimum = mYAxis.mEntries[0]; + if (centeringEnabled) { + + if (mAxis.mCenteredEntries.length < n) { + mAxis.mCenteredEntries = new float[n]; + } + + float offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f; + + for (int i = 0; i < n; i++) { + mAxis.mCenteredEntries[i] = mAxis.mEntries[i] + offset; + } } - mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; - mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); + mAxis.mAxisMinimum = mAxis.mEntries[0]; + mAxis.mAxisMaximum = mAxis.mEntries[n-1]; + mAxis.mAxisRange = Math.abs(mAxis.mAxisMaximum - mAxis.mAxisMinimum); } @Override From 423b8857455597a37e3882d1d344168844a834c8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 2 Jun 2016 23:43:16 +0200 Subject: [PATCH 0945/1390] Work on combined highlighting --- .../charting/highlight/ChartHighlighter.java | 2 +- .../highlight/CombinedHighlighter.java | 24 ++++++++----------- .../charting/highlight/Highlight.java | 2 +- .../renderer/CombinedChartRenderer.java | 1 + 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index c4896842de..30d7550ede 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -108,7 +108,7 @@ protected List getSelectionDetailsAtIndex(float xVal) { return vals; } - private SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { final Entry e = set.getEntryForXPos(xVal, rounding); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 8422b1e6a4..78aa797458 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -2,6 +2,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; @@ -19,7 +20,7 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { } /** - * Returns a list of SelectionDetail object corresponding to the given xIndex. + * Returns a list of SelectionDetail object corresponding to the given xValue. * * @param xVal * @return @@ -28,7 +29,6 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { protected List getSelectionDetailsAtIndex(float xVal) { List vals = new ArrayList(); - float[] pts = new float[2]; CombinedData data = (CombinedData) mChart.getData(); @@ -37,25 +37,21 @@ protected List getSelectionDetailsAtIndex(float xVal) { for (int i = 0; i < dataObjects.size(); i++) { - for(int j = 0; j < dataObjects.get(i).getDataSetCount(); j++) { + for (int j = 0, dataSetCount = dataObjects.get(i).getDataSetCount(); j < dataSetCount; j++) { IDataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); - // dont include datasets that cannot be highlighted + // don't include datasets that cannot be highlighted if (!dataSet.isHighlightEnabled()) continue; - // extract all yPx-values from all DataSets at the given xPx-index - final float yVals[] = dataSet.getYValuesForXPos(xVal); - for (float yVal : yVals) { - pts[1] = yVal; + SelectionDetail s1 = getDetails(dataSet, j, xVal, DataSet.Rounding.UP); + s1.dataIndex = i; + vals.add(s1); - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(0f, pts[1], yVal, i, j, dataSet)); - } - } + SelectionDetail s2 = getDetails(dataSet, j, xVal, DataSet.Rounding.DOWN); + s2.dataIndex = i; + vals.add(s2); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 4c267338b1..11244c80ba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -148,7 +148,7 @@ public boolean equalTo(Highlight h) { return false; else { if (this.mDataSetIndex == h.mDataSetIndex && this.mX == h.mX - && this.mStackIndex == h.mStackIndex) + && this.mStackIndex == h.mStackIndex && this.mDataIndex == h.mDataIndex) return true; else return false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index c96db83df6..be8d98e476 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; From ac3eafaba92d986e7d848f6888bf5e07dd21de64 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 10:26:05 +0200 Subject: [PATCH 0946/1390] Work on highlighting, introduced highlight max distance --- .../mikephil/charting/charts/Chart.java | 32 +++++-- .../charting/formatter/ColorFormatter.java | 14 +++- .../charting/highlight/BarHighlighter.java | 44 ++-------- .../charting/highlight/ChartHighlighter.java | 83 ++++++++++++++++++- .../highlight/HorizontalBarHighlighter.java | 24 +++++- .../dataprovider/ChartInterface.java | 8 ++ .../renderer/ScatterChartRenderer.java | 25 ------ .../github/mikephil/charting/utils/Utils.java | 64 -------------- 8 files changed, 157 insertions(+), 137 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 12c29c78da..7586d08035 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -228,6 +228,7 @@ public void onAnimationUpdate(ValueAnimator animation) { // initialize the utils Utils.init(getContext()); + mMaxHighlightDistance = Utils.convertDpToPixel(70f); mDefaultFormatter = new DefaultValueFormatter(1); @@ -483,6 +484,26 @@ protected void drawDescription(Canvas c) { */ protected Highlight[] mIndicesToHighlight; + /** + * The maximum distance in screen pixels away from an entry causing it to highlight. + */ + protected float mMaxHighlightDistance = 0f; + + @Override + public float getMaxHighlightDistance() { + return mMaxHighlightDistance; + } + + /** + * Sets the maximum distance in screen dp a touch can be away from an entry to cause it to get highlighted. + * Default: 70dp + * + * @param distDp + */ + public void setMaxHighlightDistance(float distDp) { + mMaxHighlightDistance = Utils.convertDpToPixel(distDp); + } + /** * Returns the array of currently highlighted values. This might a null or * empty array if nothing is highlighted. @@ -610,7 +631,7 @@ public void highlightValue(Highlight high, boolean callListener) { high = null; } else { if (this instanceof BarLineChartBase - && ((BarLineChartBase)this).isHighlightFullBarEnabled()) + && ((BarLineChartBase) this).isHighlightFullBarEnabled()) high = new Highlight(high.getX(), Float.NaN, -1, -1, -1); // set the indices to highlight @@ -681,9 +702,9 @@ protected void drawMarkers(Canvas canvas) { float xVal = highlight.getX(); int dataSetIndex = highlight.getDataSetIndex(); - float deltaX = mXAxis != null - ? mXAxis.mAxisRange - : 1f; + float deltaX = mXAxis != null + ? mXAxis.mAxisRange + : 1f; if (xVal <= deltaX && xVal <= deltaX * mAnimator.getPhaseX()) { @@ -1539,7 +1560,8 @@ public boolean saveToPath(String title, String pathOnSD) { * @param quality e.g. 50, min = 0, max = 100 * @return returns true if saving was successful, false if not */ - public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat format, int quality) { + public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat + format, int quality) { // restrain quality if (quality < 0 || quality > 100) quality = 50; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java index 3a7d119e60..2db66fd43f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ColorFormatter.java @@ -1,14 +1,24 @@ package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; /** * Interface that can be used to return a customized color instead of setting * colors via the setColor(...) method of the DataSet. - * + * * @author Philipp Jahoda */ public interface ColorFormatter { - int getColor(Entry e, int index); + /** + * Returns the color to be used for the given Entry at the given index (in the entries array) + * + * @param index index in the entries array + * @param e the entry to color + * @param set the DataSet the entry belongs to + * @return + */ + int getColor(int index, Entry e, IDataSet set); } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 2768728dce..1175887aba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -9,6 +9,9 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; +import com.github.mikephil.charting.utils.Utils; + +import java.util.List; /** * Created by Philipp Jahoda on 22/07/15. @@ -47,42 +50,6 @@ public Highlight getHighlight(float x, float y) { -1); } - @Override - protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { - - BarData barData = mChart.getBarData(); - - int closestDataSetIndex = 0; - float closestDistance = Float.MAX_VALUE; - Entry closestEntry = null; - - for (int i = 0; i < barData.getDataSets().size(); i++) { - - IBarDataSet dataSet = barData.getDataSetByIndex(i); - - final Entry entry = dataSet.getEntryForXPos(xVal); - - if (entry != null) { - - final float distance = Math.abs(xVal - entry.getX()); - - if (distance < closestDistance) { - closestDataSetIndex = i; - closestDistance = distance; - closestEntry = entry; - } - } - } - - if(closestEntry == null) - return null; - - return new SelectionDetail(x, y, closestEntry.getX(), - closestEntry.getY(), - closestDataSetIndex, - barData.getDataSetByIndex(closestDataSetIndex)); - } - /** * This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been * selected. @@ -190,4 +157,9 @@ protected Range[] getRanges(BarEntry entry) { return ranges; } + + @Override + protected float getDistance(float x, float y, float selX, float selY) { + return Math.abs(x - selX); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 30d7550ede..265c8a66c1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -71,18 +71,54 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { List valsAtIndex = getSelectionDetailsAtIndex(xVal); - float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); - float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); + float leftdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); + float rightdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - SelectionDetail detail = Utils.getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis); + SelectionDetail detail = getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis, mChart + .getMaxHighlightDistance()); return detail; } /** - * Returns a list of SelectionDetail object corresponding to the given xIndex. + * Returns the minimum distance from a touch value (in pixels) to the + * closest value (in pixels) that is displayed in the chart. + * + * @param valsAtIndex + * @param pos + * @param axis + * @return + */ + protected float getMinimumDistance(List valsAtIndex, + float pos, + YAxis.AxisDependency axis) { + + float distance = Float.MAX_VALUE; + + for (int i = 0; i < valsAtIndex.size(); i++) { + + SelectionDetail sel = valsAtIndex.get(i); + + if (sel.dataSet.getAxisDependency() == axis) { + + float cdistance = Math.abs(getSelectionPos(sel) - pos); + if (cdistance < distance) { + distance = cdistance; + } + } + } + + return distance; + } + + protected float getSelectionPos(SelectionDetail sel) { + return sel.yPx; + } + + /** + * Returns a list of SelectionDetail object corresponding to the given xVal. * * @param xVal * @return @@ -116,4 +152,43 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); } + + /** + * Returns the SelectionDetail of the DataSet that contains the closest yValue on the + * yPx-axis. + * + * @param valsAtIndex all the values at a specific index + * @return + */ + public SelectionDetail getClosestSelectionDetailByPixel( + List valsAtIndex, + float x, float y, + YAxis.AxisDependency axis, float minSelectionDistance) { + + SelectionDetail closest = null; + float distance = minSelectionDistance; + + System.out.println(distance); + + for (int i = 0; i < valsAtIndex.size(); i++) { + + SelectionDetail sel = valsAtIndex.get(i); + + if (axis == null || sel.dataSet.getAxisDependency() == axis) { + + float cDistance = getDistance(x, y, sel.xPx, sel.yPx); + + if (cDistance < distance) { + closest = sel; + distance = cDistance; + } + } + } + + return closest; + } + + protected float getDistance(float x, float y, float selX, float selY) { + return (float) Math.hypot(x - selX, y - selY); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 868f703a34..5e3cbdd3fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,10 +1,17 @@ package com.github.mikephil.charting.highlight; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; +import com.github.mikephil.charting.utils.Utils; + +import java.util.List; /** * Created by Philipp Jahoda on 22/07/15. @@ -22,7 +29,7 @@ public Highlight getHighlight(float x, float y) { PointD pos = getValsForTouch(y, x); - SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, x, y); + SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, y, x); if (selectionDetail == null) return null; @@ -42,4 +49,19 @@ public Highlight getHighlight(float x, float y) { selectionDetail.dataSetIndex, -1); } + + @Override + protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + + final Entry e = set.getEntryForXPos(xVal, rounding); + + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX()); + + return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); + } + + @Override + protected float getDistance(float x, float y, float selX, float selY) { + return Math.abs(y - selY); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index a77ecaf393..14a61521de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.utils.Utils; /** * Interface that provides everything there is to know about the dimensions, @@ -44,6 +45,13 @@ public interface ChartInterface { */ float getYChartMax(); + /** + * Returns the maximum distance in scren dp a touch can be away from an entry to cause it to get highlighted. + * + * @return + */ + float getMaxHighlightDistance(); + int getWidth(); int getHeight(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 99cf49d1f5..ff876208f2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -300,31 +300,6 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { default: break; } - - // else { // draw the custom-shape - // - // Path customShape = dataSet.getCustomScatterShape(); - // - // for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j += 2) { - // - // Entry e = entries.get(j / 2); - // - // if (!fitsBounds(e.getX(), mMinX, mMaxX)) - // continue; - // - // if (customShape == null) - // return; - // - // mRenderPaint.setColor(dataSet.getColor(j)); - // - // Path newPath = new Path(customShape); - // newPath.offset(e.getX(), e.getY()); - // - // // transform the provided custom path - // trans.pathValueToPixel(newPath); - // c.drawPath(newPath, mRenderPaint); - // } - // } } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index bf9f3157d3..9ec8a5e808 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -431,70 +431,6 @@ public static SelectionDetail getClosestSelectionDetailByValue( return closest; } - /** - * Returns the SelectionDetail of the DataSet that contains the closest yValue on the - * yPx-axis. - * - * @param valsAtIndex all the values at a specific index - * @return - */ - public static SelectionDetail getClosestSelectionDetailByPixel( - List valsAtIndex, - float x, float y, - AxisDependency axis) { - - SelectionDetail closest = null; - float distance = Float.MAX_VALUE; - - for (int i = 0; i < valsAtIndex.size(); i++) { - - SelectionDetail sel = valsAtIndex.get(i); - - if (axis == null || sel.dataSet.getAxisDependency() == axis) { - - float cDistance = (float) Math.hypot(x - sel.xPx, y - sel.yPx); - - if (cDistance < distance) { - closest = sel; - distance = cDistance; - } - } - } - - return closest; - } - - /** - * Returns the minimum distance from a touch-yPx-yValue (in pixels) to the - * closest yPx-yValue (in pixels) that is displayed in the chart. - * - * @param valsAtIndex - * @param y - * @param axis - * @return - */ - public static float getMinimumDistance(List valsAtIndex, - float y, - AxisDependency axis) { - - float distance = Float.MAX_VALUE; - - for (int i = 0; i < valsAtIndex.size(); i++) { - - SelectionDetail sel = valsAtIndex.get(i); - - if (sel.dataSet.getAxisDependency() == axis) { - - float cdistance = Math.abs(sel.yPx - y); - if (cdistance < distance) { - distance = cdistance; - } - } - } - - return distance; - } - /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. From 4b058a594fddbd4035489df32553e37d327f3283 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 11:35:16 +0200 Subject: [PATCH 0947/1390] Fixes regarding drawing of markerview --- .../mpchartexample/BarChartActivity.java | 2 +- .../mikephil/charting/charts/Chart.java | 59 ++++++++----------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index d77962f5cf..3a9b9e3533 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -234,7 +234,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - float start = 0f; + float start = 1f; mChart.getXAxis().setAxisMinValue(start); mChart.getXAxis().setAxisMaxValue(start + count + 2); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 7586d08035..42e40d0f65 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -699,48 +699,39 @@ protected void drawMarkers(Canvas canvas) { for (int i = 0; i < mIndicesToHighlight.length; i++) { Highlight highlight = mIndicesToHighlight[i]; - float xVal = highlight.getX(); - int dataSetIndex = highlight.getDataSetIndex(); - float deltaX = mXAxis != null - ? mXAxis.mAxisRange - : 1f; + Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); - if (xVal <= deltaX && xVal <= deltaX * mAnimator.getPhaseX()) { + // make sure entry not null + if (e == null || e.getX() != mIndicesToHighlight[i].getX()) + continue; - Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); + float[] pos = getMarkerPosition(e, highlight); - // make sure entry not null - if (e == null || e.getX() != mIndicesToHighlight[i].getX()) - continue; + // check bounds + if (!mViewPortHandler.isInBounds(pos[0], pos[1])) + continue; - float[] pos = getMarkerPosition(e, highlight); + // callbacks to update the content + mMarkerView.refreshContent(e, highlight); - // check bounds - if (!mViewPortHandler.isInBounds(pos[0], pos[1])) - continue; + // mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, + // MeasureSpec.UNSPECIFIED), + // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + // mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), + // mMarkerView.getMeasuredHeight()); + // mMarkerView.draw(mDrawCanvas, pos[0], pos[1]); - // callbacks to update the content - mMarkerView.refreshContent(e, highlight); + mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), + mMarkerView.getMeasuredHeight()); - // mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, - // MeasureSpec.UNSPECIFIED), - // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - // mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), - // mMarkerView.getMeasuredHeight()); - // mMarkerView.draw(mDrawCanvas, pos[0], pos[1]); - - mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), - mMarkerView.getMeasuredHeight()); - - if (pos[1] - mMarkerView.getHeight() <= 0) { - float y = mMarkerView.getHeight() - pos[1]; - mMarkerView.draw(canvas, pos[0], pos[1] + y); - } else { - mMarkerView.draw(canvas, pos[0], pos[1]); - } + if (pos[1] - mMarkerView.getHeight() <= 0) { + float y = mMarkerView.getHeight() - pos[1]; + mMarkerView.draw(canvas, pos[0], pos[1] + y); + } else { + mMarkerView.draw(canvas, pos[0], pos[1]); } } } From f39d8911d3b0a70941c2e4afd86c1163d60c0ad3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 12:11:42 +0200 Subject: [PATCH 0948/1390] Work on radarchart --- .../layout/activity_radarchart_noseekbar.xml | 20 +++++-- .../mpchartexample/RadarChartActivitry.java | 59 ++++++++++++------- .../mpchartexample/ScatterChartActivity.java | 2 +- .../charting/charts/PieRadarChartBase.java | 2 +- .../charting/renderer/RadarChartRenderer.java | 2 +- .../renderer/XAxisRendererRadarChart.java | 2 +- 6 files changed, 57 insertions(+), 30 deletions(-) diff --git a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml b/MPChartExample/res/layout/activity_radarchart_noseekbar.xml index 1de38d5660..2e8d7b5ebf 100644 --- a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml +++ b/MPChartExample/res/layout/activity_radarchart_noseekbar.xml @@ -1,11 +1,23 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> + + + + android:layout_height="0dp" + android:layout_weight="2" /> - \ No newline at end of file + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 66d9f537e5..5062ab3c7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -1,11 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; +import android.widget.TextView; import android.widget.Toast; import com.github.mikephil.charting.animation.Easing; @@ -37,16 +39,23 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart); - - mChart = (RadarChart) findViewById(R.id.chart1); + setContentView(R.layout.activity_radarchart_noseekbar); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + TextView tv = (TextView) findViewById(R.id.textView); + tv.setTypeface(tf); + tv.setTextColor(Color.WHITE); + tv.setBackgroundColor(Color.rgb(60, 65, 82)); + + mChart = (RadarChart) findViewById(R.id.chart1); + mChart.setBackgroundColor(Color.rgb(60, 65, 82)); + mChart.setDescription(""); - mChart.setWebLineWidth(1.5f); - mChart.setWebLineWidthInner(0.75f); + mChart.setWebLineWidth(1f); + mChart.setWebColor(Color.LTGRAY); + mChart.setWebLineWidthInner(1f); mChart.setWebAlpha(100); // create a custom MarkerView (extend MarkerView) and specify the layout @@ -66,10 +75,14 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); xAxis.setTextSize(9f); + xAxis.setYOffset(0f); + xAxis.setXOffset(0f); xAxis.setValueFormatter(new AxisValueFormatter() { + + private String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override public String getFormattedValue(float value, AxisBase axis) { - return mMonths[(int) value % mMonths.length]; + return mActivities[(int) value % mActivities.length]; } @Override @@ -77,18 +90,21 @@ public int getDecimalDigits() { return 0; } }); + xAxis.setTextColor(Color.WHITE); YAxis yAxis = mChart.getYAxis(); yAxis.setTypeface(tf); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setAxisMinValue(0f); + yAxis.setDrawLabels(false); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setPosition(LegendPosition.ABOVE_CHART_CENTER); l.setTypeface(tf); l.setXEntrySpace(7f); l.setYEntrySpace(5f); + l.setTextColor(Color.WHITE); } @Override @@ -190,15 +206,11 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - private String[] mParties = new String[]{ - "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H", - "Party I" - }; - public void setData() { - float mult = 150; - int cnt = 9; + float mult = 80; + float min = 20; + int cnt = 5; ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); @@ -207,25 +219,27 @@ public void setData() { // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < cnt; i++) { - float val = (float) (Math.random() * mult) + mult / 2; + float val = (float) (Math.random() * mult) + min; yVals1.add(new Entry(i, val)); } for (int i = 0; i < cnt; i++) { - float val = (float) (Math.random() * mult) + mult / 2; + float val = (float) (Math.random() * mult) + min; yVals2.add(new Entry(i, val)); } - RadarDataSet set1 = new RadarDataSet(yVals1, "Set 1"); - set1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); - set1.setFillColor(ColorTemplate.VORDIPLOM_COLORS[0]); + RadarDataSet set1 = new RadarDataSet(yVals1, "Last Week"); + set1.setColor(Color.rgb(103, 110, 129)); + set1.setFillColor(Color.rgb(103, 110, 129)); set1.setDrawFilled(true); + set1.setFillAlpha(180); set1.setLineWidth(2f); - RadarDataSet set2 = new RadarDataSet(yVals2, "Set 2"); - set2.setColor(ColorTemplate.VORDIPLOM_COLORS[4]); - set2.setFillColor(ColorTemplate.VORDIPLOM_COLORS[4]); + RadarDataSet set2 = new RadarDataSet(yVals2, "This Week"); + set2.setColor(Color.rgb(121, 162, 175)); + set2.setFillColor(Color.rgb(121, 162, 175)); set2.setDrawFilled(true); + set2.setFillAlpha(180); set2.setLineWidth(2f); ArrayList sets = new ArrayList(); @@ -236,6 +250,7 @@ public void setData() { data.setValueTypeface(tf); data.setValueTextSize(8f); data.setDrawValues(false); + data.setValueTextColor(Color.WHITE); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 0bac51c1c6..7c5652f109 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -62,8 +62,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); - mChart.setTouchEnabled(true); + mChart.setMaxHighlightDistance(50f); // enable scaling and dragging mChart.setDragEnabled(true); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 9dbdfc8974..c3d14c042a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -217,7 +217,7 @@ public void calculateOffsets() { XAxis x = this.getXAxis(); if (x.isEnabled() && x.isDrawLabelsEnabled()) { - minOffset = Math.max(minOffset, x.mLabelRotatedWidth * 2f); + minOffset = Math.max(minOffset, x.mLabelRotatedWidth); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index e8c086c9d8..7519d50693 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -228,7 +228,7 @@ protected void drawWeb(Canvas c) { mWebPaint.setColor(mChart.getWebColorInner()); mWebPaint.setAlpha(mChart.getWebAlpha()); - int labelCount = mChart.getYAxis().mEntries.length; + int labelCount = mChart.getYAxis().mEntryCount; for (int j = 0; j < labelCount; j++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 8dd2191001..ed30084f7f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -47,7 +47,7 @@ public void renderAxisLabels(Canvas c) { float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; PointF p = Utils.getPosition(center, mChart.getYRange() * factor - + mXAxis.mLabelRotatedWidth, angle); + + mXAxis.mLabelRotatedWidth / 2f, angle); drawLabel(c, label, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, drawLabelAnchor, labelRotationAngleDegrees); From 6d39afa02881b700ad126cbd513570f484249326 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 16:13:04 +0200 Subject: [PATCH 0949/1390] Brush up radarchart example --- .../res/drawable-nodpi/radar_marker.png | Bin 0 -> 9753 bytes .../layout/activity_radarchart_noseekbar.xml | 3 +- .../res/layout/radar_markerview.xml | 23 ++++++++ .../mpchartexample/RadarChartActivitry.java | 12 +++- .../custom/RadarMarkerView.java | 52 ++++++++++++++++++ 5 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 MPChartExample/res/drawable-nodpi/radar_marker.png create mode 100644 MPChartExample/res/layout/radar_markerview.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java diff --git a/MPChartExample/res/drawable-nodpi/radar_marker.png b/MPChartExample/res/drawable-nodpi/radar_marker.png new file mode 100644 index 0000000000000000000000000000000000000000..a84b93b5391a4d54c448ac12ab3998dac1206954 GIT binary patch literal 9753 zcmY*fcRbbK|9=~i6^VrGl@Zw)+2Io6$_!}!iFnUyUeBm0^mn~Vw(A|qQNdt_wu zJMY`)_x*goe|X%7bI*C5=Xt%JujlJ^4iR@XRmh0xh#?3fL#Qh0KoCw0_~AQG07lko z=G(vrk&CLKI|Pwjf`4$Jl-E}vh*--`QSt6wTW6HByREYeGeS|3*~QJ-+U}7R1bL68 zA#HS#OP6o$P3m!;O2tdQPiGWEP6I(<=K2Th5cdR29}1MU!F_ z7%$EQcYJLBF~=_#M9l62QJk-|WN|-X!-4h#q@{UTTL|AnINsk#&Ouf{zL?x30LR%x^Tp`F*iJf1! zt5UY(JOn9a2JyU=r{8J4!q-A@we{RYE6MQ#v8M{`AKMft6o@U+SKS_P7e7(B7TWWc zf#-q1pd5opi?(fOyvqgtwtKY~Zn=;jK0Ke^daW^t2w%SQ{H2F1W8paFkp^s0=V_8d z_E}n0@hP9NGk*@J(q>hU6;&0~iPUAjr^>K(%MDi|?7nh+tW+l?^yE0SQAIEzs6zYJ zAZe9iU4b~=Q{^m@ua+pml<3QusbAgR(cOA3_GaO0kuCXHw2WfMjh4kLgu)*m-QaKk zpiq93k0{=vyPUO{w5Xl#tzI!+L&UB{U%3}PWzg*wA~Ad~1?Gp0@~Q@R3^c#17BF9B z7r8h_Bu<3)RJ)CfHNHUo9cTT;gO69tg#^P4RQcG3DWfk5Q22!_eiUb?j8GKfs*Axz zl;`LUP!1>$IO(u0@nKR$RO#5_KaW{DR1iue@GMyThO zWF>y1v!$`!vnyLf)nA-UWYkRhsz1=Zq_UW_h_~ZKN)}2T+!1bbjW+cP;T0QNuPbG* z?&Q&adq&%#dqZ4s<<&wmd9w381D}P<$J=&Sq#zO%c6UQX?ItU^hg_wR6$swO@XtnY)*jTNd$r6hdUp%6mzsQ%gtsR z+nGr$Xe+(>SRBZTLOp^+KXR7$jQV@>G`u=tXn1z35c5VtQCLk_zfxyA!CIDZ_Lb}Y zYm_F@!nORQ?SRNBstxX+-1K=Ocj^SK?mHB|OnPZhq*|n1q_WZ^R=Sp-me+KP zf_#S>*L^M(o9NziX$#0vusCO%C1@iexs zUpjk8`Gqq1bG!EYv+T2u?T+o)oCKUKoa!3O8tW-K8g+Txc~WB;IDP8LnQ zB{(9qkh+jMk~&@Uz{uN(uezYR)(TNEXOw5SUft*vVkBXhYjDrVq*A#gt%PH^p`;=I zVt$=wyk=4Qu+4|JzpFo2V`^yM&VMHuFRga0e*DnJoW`c+Q|X8G_@?;B^^aei+#)0k z8@*7(V8jsM{?3g`QcrR!rT6u^?Bh>6FP8*t4EiYgz6;M*U+U)mXqSde{ib3=V^ilI zydC~5Lj6fMf07J;Dt-H8XVaV-YS-1|hws2{T54r#+gibR*}B-e-FnzW#ut$c?sP+8 z_pcv16=$^P`(;To5^p$67YAr5Y6aO;EwBk#2*m1_jJ&PM^(x$ZxIrWHN5(B(A00B`Y~@ z^`~NVP5yaiojkRC^plb&^Q|Q;wwJDT zWRPZnc%*(+f}f{U%<0kl>EpHSu%Br^NoM_MUI}!XxcI#3ZQBXSzl`ChY*+>Q#rng)E8gc})Z9|#(eRC1jcpY5VgDqY%Qs*5 zlnWEnc!%uHWU6HP*Q`PCq$4s}W#K zB>e198B=`D@H%m|Lf)dT(X|mC!U`KJee33)h%SkjMd`dfYhNn6#$&`^Z)BXUQMOV3 zh^x*GRoB1HVDPJ{*j}PS+SO;Ac$WGcZ>SzYv2<-@HIL(vR?(V%QfWXFr>}-XkZEhz zlh!I6hZT~0#PcDKS0+Z*OtcIH45zCe9)_mT%TPx|mQsz=BvA)`zc%4LPao#o)to$$ z@D5Y-vCgv3dcb<=*VOfN;|nhflYS*#a3UKWdq*~{_ikNTlrW_fY8`o=n zk?9{^p7K3b8D}DYEh25`qqeR4*=}s<$+vi$t-j}JiD{1m_zxx?jAvE*Em-tU+mkzQ z)Kj2-4BS3@wjk9g)q8)d7PVC|K7UESRzIao(#&xgwJd!a|4pl-;dMhwY2AH?x^>^C zDnIMJCHi#n-pQRNpWm0yhKJH6ZcR3A`#SG^+S{GJJQ?7|b<*42FzUs%Uec)5XtpD_ zCO@h;88#$qd^+)cV<`(O3HN!m(^Z+7(0Jy~v9p)DJ4Z)<0K|Jhqu z&~!)dXsy+2!i!-edzxHp&YwB(+L`S^`7ZKn{!u(_eEbM)LGf_1%o4`Kvqj`BjP?+Uqm8|HS1?-9J=^wUFR`+-A4zQ`oo_=;upJr<^ zB}c?*E^|2ru`h|7KA=2XG&}8?K9!v*vuG6X3M$o#7Oot-_e?L*NdHH-q%CNW`V!rcD@E2^>pY5rlmlmd(AQ^iZ(}l=d(Mux zo6#za$%{097PF(6%N{F=%S+~d2|VqX8IauEVsFliFl~ncHneC31clM9CjE<&kPAyx}P!av)Ai&SuNrR_0b`gcdvb!roDgS zMKE=$Wrbe#OX>6&S!=q*bMRX0Dgske->6jSx_37R3X~O=68}x!Vt$bs7@?kF%5vzQ zryRe&Ar+rsn#P>@y88nE+4h&!i5l1a!=I>x&$77lO!?J}AqV3!!R)zu9L+6LQ%)$% zZErSDzK@)8*47I~E%S?G!|js0W1)Sl2u$UqeYp-d8Go~cu#~=-obnO1i>*j^-*o$> zV2)f3LHE@4AAbE^Ee@`SbQaVwh+8v)tYIGtZ)E z(5pYn*PH!A5h+IVA*(ZQvdLy_Tu*#0=wXNrEpL#V8%|C-#>TsboOa6-aB%EgT@G@S zN9#QB=1?qK0xd5VjRf6oHV4EIYK?8jX|2YWe+AXd9*dr_;~e=CEoKzgRyOsx)h$+P z3=DoZC~@<0aCbR~00s=q0_cvQ<5oRI=yaQA%S*aMU&oEQavMdyH>TB?=gEU-Y3<3+d@R?rF*SKu zkfMT!Y;qN?0^5R<`76vh%pAVK?<3`?W&dRS+`&FyOzw{f!C}&awY4aJa_u;C-d@ov zBm?XwiJ6i`BX8;tQGIHNa+6Rf6w+zr@)sRL0VZ3x%WdgDfS;FQqdy{F&Y{m9YQx1 zuQ5N`DV%ecvEcZm9A|Hjq-H*1l40;AcdgU0ZW!7!Z5Xd};Vb1fgw zef9e_A0j^KUCP+txz5wDyZTuUsVggk4)ij992$2h9qhl|1Xwlq-{_hJ)UxWt@xxRDXfO2X zcfnu$cM+2AVAw3VeZvDAO{b)w+1L%I;ewKq!_}84r@S|L!$j<)u>wK#VWzZ}zX-M3 z5^^d9-{<`qdl%3xo4m!eG%I&z`6+Gfa`$|e77Agr9-cCWc|0UJgd-#@wTHLqgmNs8 zVS0oYpA#mOm-j~>QH&9lyWmGua69m8?xS{_#vEZ`FuwIJaQbg>MQ08c$Huz0W(v3w z`S6k#Im3f=%pU*=cbRs5=Qg|z%W}fR!56zC{u`L{F(7#8&DX{6{k&GP`D@~HEK=K3 zjPNW`;r?Xzqf1}Z{!odFvNCe8CyV*bk9VR~-+ons8A1L|C|9(KpmU#_ov@MG#F*#u z=;Y|{8u@|ps=Yr2ckDDuaNOSM2ic!-DAp(nx_3;UM|6nwz$^NZonOg)EvnQk9J;58 z5#%Ck@M!Sk{~{jagE4qJLM;}P8Ns$n`vCuY<&AUBVL9akcaaY0s{%^z31uQm6WwSf zWQ{GJfAI-*kMlMp4=>tJ=sTXIQ7`1aPW?2|+DN=&9u$ zprX@8`Xy1p@NL9H2GI-I4i3EC!CrZ4YPDd0f&6j+R>F7#ujVk?_tutIW3he;Cp>#W zGz9v4|0gWh={)-Bh?Nw*ZjOh-8IA z(yJf;*4BE70etx2>^VU4bUMXxzMMdBc;Z#zwEy4b-Nw{BA0=(A&tqo z!%~CZ%W`-Yay-N06xaI-cH%qlivYIjz=&I_ zGNRn5#k-UMdpK{BIx~=H_!aMM_OvJ1{k2#OXOjA>a&=rcjXV%smLOnpmzyC_{_4|u z3mU9A(%@jL8s)_hY(7Fc{?(qISj|?zAa+L?d?!ZVbBT3i!_#V9=J48f?i`Z)tc@Qj z(AL?l%P?F1F`zgnHS_I1Y(bI2?zP(!`H>qcd#W(!z8?9{P=-QiDU~4xNY24%28s&A zkRoJ?xp9u-it!UR?l!Qk(hsTu-1Nv&$I>$GGRInpf%C8}$yMPtb@FK65RTk*fH*w# zADJ<>Glp4`-o|{}5ctFv6+VG46JDCQ4LUPq9X`C&H)a9d-Wr@anb#QOp${@iRBk7e zJBPTD(xixA&sH?mDN3gY-ne61>?@O$ZxiFW73V~2?5=;PD!S!}G#^(gJ30>aX!F2( zELyT`opWKU*ZcB?{11aF()o_Y+5&d=*rk6fRzsF9EfVSXDNRrgwL|4b;w^yHl~W-E z(xG9<+-KjkV59^$0Ap&Q*ALD%SKPWlVg67QjhWux}yhuc}I%ZzZS7 z#lXd^0zSLuFCLeoGh0+hzKCd40p=vJ!2*Cns>*q5>PV4AjsKplw;-8gO?6TIt;1zD}^ko&x9#$+1v3)I9nyiuKQ-H+5+tm)w7;^qj@@)PeMQdqxA1^}-rowP?^FU>A!_w;DlPcj zk^28d9r52hrZ7k-%5wn8V4U^!v}h>C`U&tpUq>IrHQ8= z-HJfbU>{ziEyV@(NZCw{JFO1X!ob<}E6i%`RFo9y@k3r^rc6Vv%xM@{|7wK^!sDm` zW6YFBl;5==Y<_{p%g3t&(%!mH;K{T}!k-oa<_Xln^CUtnX=}HvFuGU$pUL~$stgW_ zO)!A->=NI-<^6RHRopx@3Rk)QK}{C2Hn!=bwr;+fiK}TuaOP{&kfT%kLll02YE%>k zi&NH8hC=<*q}@N4vi~8=;u|b_29~Ysn}$IBy9Z#h=A{&c(12Eb9*$~bv1iMc#h65#IL)$+W*z+YbQAU$R`9|dO~90;f0<%Yo~K8k zTK|~XpT^{xW#}P&4$JUh7vxI3gp>5gOad1)x){AiZ)KHAFfSZ5%nd~T-iy(SGAduI zw^gzYk-T_H+I_euAJ(6Erfw+=oAj%~>$OqD7~JOY(t9+#?@~0xRl*G5iP^`Li_r|= z#`t8nCUVhJ3ZB{D$!(bwRQYTG2a|v^s-*0NHu)&tXV&te=86o+cdgulW?KA171NV z40;!uzrBk`F1B@w#+q00A+PmVOk8Zt-_83Bs!bo(5}^hQ4qlS2*fQHR$w&en5_yy$ z#RgQ0D3-p3roZZ<{;VxA%uXPs08IqwU94=qW#w8;lHEX!oJQGLq8HhbsxO0rw_d7+ zv`WQ^-p1Ok-1&zp*Q}dxeCV(UY;J{!pck?n=!dB3jE$Xo6X5uS_kJLRn->;$`r_s^ zI;`7#G+0d9+$#zA8*-c!*kAvsh!OqbC&vXXUtY0NI}lvo$lpVzuLb(a9V z7Vsw?KWT__!J4>zhsA2<#p0M+?nlpVUg`KQ7=OKL*`+B10=b%ThI<}`_;2Cu`F)A) zaI{oLz(YX6h}gvIr&v&&KaevG0F>~KOuhLRcx}oc)c_v<#VK0?xuVe=qu<3%IoS1_ zw5;Mm!7u{ri9{kv&`xDcG5}-WsC4j5pO==D@R6H}6_SW#HQN>wh>ic1IukhU%khlUUSqpEMz+MIo z1rttchM5n)&)P;QX{J7-K;!_br3Gp41a9^=SfZp< zbLXgoVk#?`@`9kKTivOb7Mu8af=cht$vi7fbTn3SBMq{Z)x-5o<3A+hq8#rz11vT73g$j;}@4&*^eKfWwn(^}nn_R=`{vnEQuS zsMXLYP+tJ}ahO#&CwmLVJ)A?4f!mr`qN-WIRZDs&Ng#vG)=&4Ft0Ojnxc~5dZB}8i zt>G51oJ_P>-1Vix!lKe*xi>SkXyj3@P&A5iXMB+R2nMlqop}$fKOAYhvG$@K=Nopv zNvaBU1L-0C>0)hTV-NTCYxA%LR)(jY9y2T8T}eu-W<_H#czxR8Z8g>i_cG-_s${i) z8ajyen22=91nyLH={;hS)wQ*Hi6g9y7kkowYgd!1XI1Wa8K0Vw$%VB9}5CKbu%cpU^o^Qq9b}(h{)se#{i?$VJ^fn zu3BaKZf1@z-Tl&=|C62xPzpSf2+8HlYOs*aEc92sSSEf^Qi3^~>Hr|uDisLAQT`+6 zr}s8^E!SJ9My8Emx=N=0%b$i~egTcOy}xc=RhToL*;WkHh6!}TW4Z`yyV5IU6a34? zpFf@$s>^xH^zUE>pk%;n!1zsG@Df_GZt%<$WIrnso9SB&v$QruUM6e$3^~ zJ19r@$1i*x*?v!_Vr_2k5p6z3y@{cJP6Wuv0S7>4@FDXga?4r#y24oJgHVlO(a9>8HTb*O=lCvrehcftSG zPDdU6bT0=M;BQy#izIlf74pC8D~%PQ$RW6OmaW(0=6hRHL*Gy~1cTB!mL?y(z=(Q+ zcH=iq+Qs@ja)C<6Vn%WCV%Z-qY-Z^AH<28F4IEt2eihwe*92zOP+@JB$o~p+J^>vzx1ATF~yTo za0kHrnf;ms_~V|>|FJg3C{PWsWZ##zfKhtUQXk)sW2@ z5(alr6n2vT&7RpWr)1brd|SCRa|Bmfn@xKR@^8o|k*eh0q>D9YRVf;U&&YkUe9Kf= zgi%w8*d4h^VpCgG`m44SqB0*J@;>_TvrsV@Toiy)xOas!&uC;}2E8sl1!?&i(yq^o z;n}oDmDC%62cGo(vu^C@VdJ^E3yeF;fl;pDcF%#QwDelRGpM`2%C`jEzjnW$F%1u@ z0db^f9SJJScF0|oo?H)>J*v*r1KX&>cP~)e5`Wa>UI37VFF|qT7MyZ`?5C&jRegju_2RsW>{UXm8 zmI8OLzbsu!SHLCkm7?4IK*$~iDjAoT7D2dW_yqL+c`3uyei<+^PP8fx2&FeAs99AF zm5LG>^!mu7GN&XIUztQELzPJ2y0ADk<)?SP`2>B>cv5{ zKK2YbZ1?d3WX(?`us9{{iI*scr8xpK#fiYW1;v^~WJ~~90gkAIR88J2 t1VtxTkdgLgmV6vL7X@PA;9vs>@@f2DiKiwr4gU59A#Q6bl`1@V@_(15jhz4h literal 0 HcmV?d00001 diff --git a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml b/MPChartExample/res/layout/activity_radarchart_noseekbar.xml index 2e8d7b5ebf..d8e3b35aab 100644 --- a/MPChartExample/res/layout/activity_radarchart_noseekbar.xml +++ b/MPChartExample/res/layout/activity_radarchart_noseekbar.xml @@ -4,11 +4,10 @@ android:layout_height="match_parent" android:orientation="vertical"> - + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 5062ab3c7f..17866470b1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; @@ -25,6 +26,7 @@ import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; +import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -41,7 +43,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_radarchart_noseekbar); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tf = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); TextView tv = (TextView) findViewById(R.id.textView); tv.setTypeface(tf); @@ -56,11 +58,12 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setWebLineWidth(1f); mChart.setWebColor(Color.LTGRAY); mChart.setWebLineWidthInner(1f); + mChart.setWebColorInner(Color.LTGRAY); mChart.setWebAlpha(100); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it - MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); + MarkerView mv = new RadarMarkerView(this, R.layout.radar_markerview); // set the marker to the chart mChart.setMarkerView(mv); @@ -97,6 +100,7 @@ public int getDecimalDigits() { yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setAxisMinValue(0f); + yAxis.setAxisMaxValue(80f); yAxis.setDrawLabels(false); Legend l = mChart.getLegend(); @@ -234,6 +238,8 @@ public void setData() { set1.setDrawFilled(true); set1.setFillAlpha(180); set1.setLineWidth(2f); + set1.setDrawHighlightCircleEnabled(true); + set1.setDrawHighlightIndicators(false); RadarDataSet set2 = new RadarDataSet(yVals2, "This Week"); set2.setColor(Color.rgb(121, 162, 175)); @@ -241,6 +247,8 @@ public void setData() { set2.setDrawFilled(true); set2.setFillAlpha(180); set2.setLineWidth(2f); + set2.setDrawHighlightCircleEnabled(true); + set2.setDrawHighlightIndicators(false); ArrayList sets = new ArrayList(); sets.add(set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java new file mode 100644 index 0000000000..cac42ef0fd --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -0,0 +1,52 @@ + +package com.xxmassdeveloper.mpchartexample.custom; + +import android.content.Context; +import android.graphics.Typeface; +import android.widget.TextView; + +import com.github.mikephil.charting.components.MarkerView; +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.Utils; +import com.xxmassdeveloper.mpchartexample.R; + +import java.text.DecimalFormat; + +/** + * Custom implementation of the MarkerView. + * + * @author Philipp Jahoda + */ +public class RadarMarkerView extends MarkerView { + + private TextView tvContent; + private DecimalFormat format = new DecimalFormat("##0"); + + public RadarMarkerView(Context context, int layoutResource) { + super(context, layoutResource); + + tvContent = (TextView) findViewById(R.id.tvContent); + tvContent.setTypeface(Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf")); + } + + // callbacks everytime the MarkerView is redrawn, can be used to update the + // content (user-interface) + @Override + public void refreshContent(Entry e, Highlight highlight) { + tvContent.setText(format.format(e.getY()) + " %"); + } + + @Override + public int getXOffset(float xpos) { + // this will center the marker-view horizontally + return -(getWidth() / 2); + } + + @Override + public int getYOffset(float ypos) { + // this will cause the marker-view to be above the selected yValue + return -getHeight()-10; + } +} From 589bd0cbadc7ee6bc812217c3031f9065d2b1243 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 16:52:32 +0200 Subject: [PATCH 0950/1390] Work on making realm example work again --- .../mpchartexample/custom/RealmDemoData.java | 60 +++++++++---------- .../realm/RealmBaseActivity.java | 12 ++-- .../realm/RealmDatabaseActivityBar.java | 6 +- .../realm/RealmDatabaseActivityBubble.java | 6 +- .../realm/RealmDatabaseActivityCandle.java | 6 +- .../RealmDatabaseActivityHorizontalBar.java | 6 +- .../realm/RealmDatabaseActivityLine.java | 6 +- .../realm/RealmDatabaseActivityPie.java | 6 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 5 +- .../realm/RealmWikiExample.java | 43 +++++++++---- .../mpchartexample/realm/Score.java | 8 +-- ...ealmBarLineScatterCandleBubbleDataSet.java | 6 +- .../data/realm/base/RealmBaseDataSet.java | 13 ++-- .../RealmLineScatterCandleRadarDataSet.java | 1 - .../realm/implementation/RealmBarDataSet.java | 14 ++--- .../implementation/RealmBubbleDataSet.java | 2 +- .../implementation/RealmCandleDataSet.java | 2 +- .../implementation/RealmLineDataSet.java | 8 +-- .../realm/implementation/RealmPieDataSet.java | 14 ----- .../implementation/RealmRadarDataSet.java | 8 +-- .../implementation/RealmScatterDataSet.java | 8 +-- 22 files changed, 124 insertions(+), 118 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index a84c65d003..4f3323374e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -10,7 +10,8 @@ */ public class RealmDemoData extends RealmObject { - private float value; + private float yValue; + private float xValue; private float open, close, high, low; @@ -18,8 +19,6 @@ public class RealmDemoData extends RealmObject { private RealmList stackValues; - private int xIndex; - private String xAxisLabel; private double xAxisPosition; @@ -31,9 +30,9 @@ public RealmDemoData() { } - public RealmDemoData(float value, int xIndex, double xAxisPosition, String xAxisLabel) { - this.value = value; - this.xIndex = xIndex; + public RealmDemoData(float xValue, float yValue, double xAxisPosition, String xAxisLabel) { + this.xValue = xValue; + this.yValue = yValue; this.xAxisPosition = xAxisPosition; this.xAxisLabel = xAxisLabel; } @@ -41,13 +40,13 @@ public RealmDemoData(float value, int xIndex, double xAxisPosition, String xAxis /** * Constructor for stacked bars. * + * @param xValue * @param stackValues - * @param xIndex * @param xAxisPosition * @param xAxisLabel */ - public RealmDemoData(float[] stackValues, int xIndex, double xAxisPosition, String xAxisLabel) { - this.xIndex = xIndex; + public RealmDemoData(float xValue, float[] stackValues, double xAxisPosition, String xAxisLabel) { + this.xValue = xValue; this.xAxisPosition = xAxisPosition; this.xAxisLabel = xAxisLabel; this.stackValues = new RealmList(); @@ -60,21 +59,22 @@ public RealmDemoData(float[] stackValues, int xIndex, double xAxisPosition, Stri /** * Constructor for candles. * + * @param xValue * @param high * @param low * @param open * @param close - * @param xIndex * @param xAxisPosition * @param xAxisLabel */ - public RealmDemoData(float high, float low, float open, float close, int xIndex, double xAxisPosition, String xAxisLabel) { - this.value = (high + low) / 2f; + public RealmDemoData(float xValue, float high, float low, float open, float close, double xAxisPosition, String + xAxisLabel) { + this.yValue = (high + low) / 2f; this.high = high; this.low = low; this.open = open; this.close = close; - this.xIndex = xIndex; + this.xValue = xValue; this.xAxisPosition = xAxisPosition; this.xAxisLabel = xAxisLabel; } @@ -82,42 +82,42 @@ public RealmDemoData(float high, float low, float open, float close, int xIndex, /** * Constructor for bubbles. * - * @param value - * @param xIndex + * @param xValue + * @param yValue * @param bubbleSize * @param xAxisPosition * @param xAxisLabel */ - public RealmDemoData(float value, int xIndex, float bubbleSize, double xAxisPosition, String xAxisLabel) { - this.value = value; - this.xIndex = xIndex; + public RealmDemoData(float xValue, float yValue, float bubbleSize, double xAxisPosition, String xAxisLabel) { + this.xValue = xValue; + this.yValue = yValue; this.bubbleSize = bubbleSize; this.xAxisPosition = xAxisPosition; this.xAxisLabel = xAxisLabel; } - public float getValue() { - return value; + public float getyValue() { + return yValue; } - public void setValue(float value) { - this.value = value; + public void setyValue(float yValue) { + this.yValue = yValue; } - public RealmList getStackValues() { - return stackValues; + public float getxValue() { + return xValue; } - public void setStackValues(RealmList stackValues) { - this.stackValues = stackValues; + public void setxValue(float xValue) { + this.xValue = xValue; } - public int getxIndex() { - return xIndex; + public RealmList getStackValues() { + return stackValues; } - public void setxIndex(int xIndex) { - this.xIndex = xIndex; + public void setStackValues(RealmList stackValues) { + this.stackValues = stackValues; } public float getOpen() { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 9e3197b259..4eef9d13af 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -110,7 +110,7 @@ protected void writeToDB(int objectCount) { float value = 40f + (float) (Math.random() * 60f); - RealmDemoData d = new RealmDemoData(value, i, i, "" + i); + RealmDemoData d = new RealmDemoData(i, value, i, "" + i); mRealm.copyToRealm(d); } @@ -129,7 +129,7 @@ protected void writeToDBStack(int objectCount) { float val2 = 34f + (float) (Math.random() * 12.0f); float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - RealmDemoData d = new RealmDemoData(stack, i, i, "" + i); + RealmDemoData d = new RealmDemoData(i, stack, i, "" + i); mRealm.copyToRealm(d); } @@ -155,8 +155,8 @@ protected void writeToDBCandle(int objectCount) { boolean even = i % 2 == 0; - RealmDemoData d = new RealmDemoData(val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close, i, i, i + ""); + RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, + even ? val - close : val + close, i, i + ""); mRealm.copyToRealm(d); } @@ -175,7 +175,7 @@ protected void writeToDBBubble(int objectCount) { float value = 30f + (float) (Math.random() * 100.0); float size = 15f + (float) (Math.random() * 20.0); - RealmDemoData d = new RealmDemoData(value, i, size, "" + i); + RealmDemoData d = new RealmDemoData(i, value, size, "" + i); mRealm.copyToRealm(d); } @@ -198,7 +198,7 @@ protected void writeToDBPie() { String[] xValues = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], i, i, xValues[i]); + RealmDemoData d = new RealmDemoData(i, values[i], i, xValues[i]); mRealm.copyToRealm(d); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 9527f3e6be..0e612bee58 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.data.realm.implementation.RealmBarData; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -50,7 +50,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "yValue", "xIndex"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "yValue", "xValue"); // stacked entries set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); set.setLabel("Realm BarDataSet"); @@ -58,7 +58,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBarData data = new RealmBarData(result, "xAxisPosition", "xAxisLabel", dataSets); + BarData data = new BarData(dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index cd188a4266..c2c2003d2e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BubbleChart; -import com.github.mikephil.charting.data.realm.implementation.RealmBubbleData; +import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "yValue", "xIndex", "bubbleSize"); + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); set.setColors(ColorTemplate.COLORFUL_COLORS, 110); @@ -61,7 +61,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBubbleData data = new RealmBubbleData(result, "xAxisPosition", "xAxisLabel", dataSets); + BubbleData data = new BubbleData(dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 97a0036567..c8f7abb84d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.CandleStickChart; -import com.github.mikephil.charting.data.realm.implementation.RealmCandleData; +import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.xxmassdeveloper.mpchartexample.R; @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmCandleDataSet set = new RealmCandleDataSet(result, "high", "low", "open", "close", "xIndex"); + RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); set.setLabel("Realm Realm CandleDataSet"); set.setShadowColor(Color.DKGRAY); set.setShadowWidth(0.7f); @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmCandleData data = new RealmCandleData(result, "xAxisPosition", "xAxisLabel", dataSets); + CandleData data = new CandleData(dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 40bbf10910..2c6081e40c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.realm.implementation.RealmBarData; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex", "floatValue"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); set.setLabel("Mobile OS distribution"); set.setStackLabels(new String[]{"iOS", "Android", "Other"}); @@ -63,7 +63,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmBarData data = new RealmBarData(result, "xAxisPosition", "xAxisLabel", dataSets); + BarData data = new BarData(dataSets); styleData(data); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 36a8dc5abd..4e04cf09df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.realm.implementation.RealmLineData; +import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result, "yValue", "xIndex"); + RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); set.setDrawCubic(false); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); @@ -67,7 +67,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmLineData data = new RealmLineData(result, "xAxisPosition", "xAxisLabel", dataSets); + LineData data = new LineData(dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index dfe37e61f6..bb97dd6681 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -10,7 +10,7 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.realm.implementation.RealmPieData; +import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.R; @@ -54,13 +54,13 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "xIndex"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue"); // stacked entries set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); // create a data object with the dataset list - RealmPieData data = new RealmPieData(result, "xAxisPosition", "xAxisLabel", set); + PieData data = new PieData(set); styleData(data); data.setValueTextColor(Color.WHITE); data.setValueTextSize(12f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 3b57ca9ceb..5995ebb5a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -55,7 +55,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue", "xIndex"); // stacked entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "yValue"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index a465433d00..35d598f6cf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.realm.implementation.RealmScatterData; import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -53,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmScatterDataSet set = new RealmScatterDataSet(result, "yValue", "xIndex"); + RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); @@ -63,7 +64,7 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - RealmScatterData data = new RealmScatterData(result, "xAxisPosition", "xAxisLabel", dataSets); + ScatterData data = new ScatterData(dataSets); styleData(data); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 2d5e3a90a5..7a9386bfbe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -6,10 +6,14 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.implementation.RealmBarData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.data.realm.implementation.RealmLineData; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -46,6 +50,7 @@ protected void onCreate(Bundle savedInstanceState) { lineChart.getXAxis().setDrawGridLines(false); barChart.getAxisLeft().setDrawGridLines(false); barChart.getXAxis().setDrawGridLines(false); + barChart.getXAxis().setCenterAxisLabels(true); } @Override @@ -55,15 +60,15 @@ protected void onResume() { mRealm.beginTransaction(); // write some demo-data into the realm.io database - Score score1 = new Score(100f, 0, "Peter"); + Score score1 = new Score(100f, 0f, "Peter"); mRealm.copyToRealm(score1); - Score score2 = new Score(110f, 1, "Lisa"); + Score score2 = new Score(110f, 1f, "Lisa"); mRealm.copyToRealm(score2); - Score score3 = new Score(130f, 2, "Dennis"); + Score score3 = new Score(130f, 2f, "Dennis"); mRealm.copyToRealm(score3); - Score score4 = new Score(70f, 3, "Luke"); + Score score4 = new Score(70f, 3f, "Luke"); mRealm.copyToRealm(score4); - Score score5 = new Score(80f, 4, "Sarah"); + Score score5 = new Score(80f, 4f, "Sarah"); mRealm.copyToRealm(score5); mRealm.commitTransaction(); @@ -75,11 +80,27 @@ protected void onResume() { private void setData() { // LINE-CHART - RealmResults results = mRealm.allObjects(Score.class); + final RealmResults results = mRealm.allObjects(Score.class); - RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "totalScore", "scoreNr"); + + AxisValueFormatter formatter = new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return results.get((int) value).getPlayerName(); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }; + + lineChart.getXAxis().setValueFormatter(formatter); + barChart.getXAxis().setValueFormatter(formatter); + + RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); lineDataSet.setDrawCubic(false); - lineDataSet.setLabel("Realm LineDataSet"); + lineDataSet.setLabel("Result Scores"); lineDataSet.setDrawCircleHole(false); lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); @@ -89,7 +110,7 @@ private void setData() { ArrayList dataSets = new ArrayList(); dataSets.add(lineDataSet); - RealmLineData lineData = new RealmLineData(results, "scoreNr", "playerName", dataSets); + LineData lineData = new LineData(dataSets); styleData(lineData); // set data @@ -98,14 +119,14 @@ private void setData() { // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet(results, "totalScore", "scoreNr"); + RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); barDataSet.setLabel("Realm BarDataSet"); ArrayList barDataSets = new ArrayList(); barDataSets.add(barDataSet); - RealmBarData barData = new RealmBarData(results, "scoreNr", "playerName", barDataSets); + BarData barData = new BarData(barDataSets); styleData(barData); barChart.setData(barData); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java index cf3afcf46d..870e371491 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java @@ -10,14 +10,14 @@ public class Score extends RealmObject { private float totalScore; - private int scoreNr; + private float scoreNr; private String playerName; public Score() { } - public Score(float totalScore, int scoreNr, String playerName) { + public Score(float totalScore, float scoreNr, String playerName) { this.scoreNr = scoreNr; this.playerName = playerName; this.totalScore = totalScore; @@ -33,11 +33,11 @@ public void setTotalScore(float totalScore) { this.totalScore = totalScore; } - public int getScoreNr() { + public float getScoreNr() { return scoreNr; } - public void setScoreNr(int scoreNr) { + public void setScoreNr(float scoreNr) { this.scoreNr = scoreNr; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java index cfff7b8b28..55e33227c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java @@ -24,11 +24,11 @@ public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String yV * Constructor that takes the realm RealmResults, sorts & stores them. * * @param results + * @param xValuesField * @param yValuesField - * @param xIndexField */ - public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String yValuesField, String xIndexField) { - super(results, yValuesField, xIndexField); + public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String xValuesField, String yValuesField) { + super(results, xValuesField, yValuesField); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 168903dbac..ee17c51587 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -48,12 +48,12 @@ public abstract class RealmBaseDataSet e protected float mXMin = 0.0f; /** - * fieldname of the column that contains the yPx-values of this dataset + * fieldname of the column that contains the y-values of this dataset */ protected String mYValuesField; /** - * fieldname of the column that contains the xPx-values of this dataset + * fieldname of the column that contains the x-values of this dataset */ protected String mXValuesField; @@ -70,13 +70,13 @@ public RealmBaseDataSet(RealmResults results, String yValuesField) { * Constructor that takes the realm RealmResults, sorts & stores them. * * @param results + * @param xValuesField * @param yValuesField - * @param xIndexField */ - public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { + public RealmBaseDataSet(RealmResults results, String xValuesField, String yValuesField) { this.results = results; this.mYValuesField = yValuesField; - this.mXValuesField = xIndexField; + this.mXValuesField = xValuesField; this.mValues = new ArrayList(); if (mXValuesField != null) @@ -97,8 +97,7 @@ public void build(RealmResults results) { public S buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - return (S) new Entry(dynamicObject.getFloat(mYValuesField), - mXValuesField == null ? x : dynamicObject.getInt(mXValuesField)); + return (S) new Entry(mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), dynamicObject.getFloat(mYValuesField)); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java index d86b98d0b0..9024bb6389 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java @@ -23,7 +23,6 @@ public abstract class RealmLineScatterCandleRadarDataSet results, String yValuesField) { super(results, yValuesField); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index fae88776fa..fa9c12c4a0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -47,8 +47,8 @@ public class RealmBarDataSet extends RealmBarLineScatterC "Stack" }; - public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { - super(results, yValuesField, xIndexField); + public RealmBarDataSet(RealmResults results, String xValuesField, String yValuesField) { + super(results, xValuesField, yValuesField); mHighLightColor = Color.rgb(0, 0, 0); build(this.results); @@ -59,13 +59,13 @@ public RealmBarDataSet(RealmResults results, String yValuesField, String xInd * Constructor for supporting stacked values. * * @param results + * @param xValuesField * @param yValuesField - * @param xIndexField * @param stackValueFieldName */ - public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField, String + public RealmBarDataSet(RealmResults results, String xValuesField, String yValuesField, String stackValueFieldName) { - super(results, yValuesField, xIndexField); + super(results, xValuesField, yValuesField); this.mStackValueFieldName = stackValueFieldName; mHighLightColor = Color.rgb(0, 0, 0); @@ -97,10 +97,10 @@ public BarEntry buildEntryFromResultObject(T realmObject, float x) { } return new BarEntry( - mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), values); + mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), values); } else { float value = dynamicObject.getFloat(mYValuesField); - return new BarEntry(mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), value); + return new BarEntry(mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), value); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 8c6e1d71c6..5a2e0c5f93 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -57,7 +57,7 @@ public BubbleEntry buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); return new BubbleEntry( - mXValuesField == null ? x : dynamicObject.getInt(mXValuesField), + mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), dynamicObject.getFloat(mYValuesField), dynamicObject.getFloat(mSizeField)); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 53279e5008..e4288af115 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -123,7 +123,7 @@ public CandleEntry buildEntryFromResultObject(T realmObject, int xIndex) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); return new CandleEntry( - mXValuesField == null ? xIndex : dynamicObject.getInt(mXValuesField), + mXValuesField == null ? xIndex : dynamicObject.getFloat(mXValuesField), dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), dynamicObject.getFloat(mOpenField), diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index d5ac1405c7..b2ea4a7de9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -87,11 +87,11 @@ public RealmLineDataSet(RealmResults result, String yValuesField) { * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index + * @param xValuesField the name of the field in your data object that represents the x-axis value + * @param yValuesField the name of the field in your data object that represents the y-axis value */ - public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { - super(result, yValuesField, xIndexField); + public RealmLineDataSet(RealmResults result, String xValuesField, String yValuesField) { + super(result, xValuesField, yValuesField); mCircleColors = new ArrayList(); // default color diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 8ce3fc0df1..4d22de97c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -48,20 +48,6 @@ public RealmPieDataSet(RealmResults result, String yValuesField) { calcMinMax(); } - /** - * Constructor for creating a PieDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index - */ - public RealmPieDataSet(RealmResults result, String yValuesField, String xIndexField) { - super(result, yValuesField, xIndexField); - - build(this.results); - calcMinMax(); - } - /** * Sets the space that is left out between the piechart-slices in dp. * Default: 0 --> no space, maximum 20f diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 77b0b19da8..0d2ed766aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -45,11 +45,11 @@ public RealmRadarDataSet(RealmResults result, String yValuesField) { * Constructor for creating a RadarDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index + * @param xValuesField the name of the field in your data object that represents the x value + * @param yValuesField the name of the field in your data object that represents the y value */ - public RealmRadarDataSet(RealmResults result, String yValuesField, String xIndexField) { - super(result, yValuesField, xIndexField); + public RealmRadarDataSet(RealmResults result, String xValuesField, String yValuesField) { + super(result, xValuesField, yValuesField); build(this.results); calcMinMax(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 18075feccc..d8126e7e06 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -57,11 +57,11 @@ public RealmScatterDataSet(RealmResults result, String yValuesField) { * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index + * @param xValuesField the name of the field in your data object that represents the x value + * @param yValuesField the name of the field in your data object that represents the y value */ - public RealmScatterDataSet(RealmResults result, String yValuesField, String xIndexField) { - super(result, yValuesField, xIndexField); + public RealmScatterDataSet(RealmResults result, String xValuesField, String yValuesField) { + super(result, xValuesField, yValuesField); build(this.results); calcMinMax(); From 40f078a2bfed61cac57c8547baface85b2e9ff39 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 3 Jun 2016 23:30:49 +0200 Subject: [PATCH 0951/1390] Work on realm and barchart --- .../mpchartexample/AnotherBarActivity.java | 1 + .../ListViewBarChartActivity.java | 1 + .../mpchartexample/custom/RealmDemoData.java | 41 +-- .../listviewitems/BarChartItem.java | 1 + .../realm/RealmBaseActivity.java | 10 +- .../realm/RealmDatabaseActivityBar.java | 3 +- .../mikephil/charting/charts/BarChart.java | 336 ++++++++++-------- .../charting/charts/BarLineChartBase.java | 2 +- 8 files changed, 194 insertions(+), 201 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index b7c2a50b06..3daac14bc0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -196,6 +196,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BarData data = new BarData(dataSets); mChart.setData(data); + mChart.setFitBars(true); } mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 0a998bce96..84360bd7b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -108,6 +108,7 @@ public View getView(int position, View convertView, ViewGroup parent) { // set data holder.chart.setData(data); + holder.chart.setFitBars(true); // do not forget to refresh the chart // holder.chart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index 4f3323374e..d753d3e8c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -19,9 +19,6 @@ public class RealmDemoData extends RealmObject { private RealmList stackValues; - private String xAxisLabel; - private double xAxisPosition; - private String someStringField; // ofc there could me more fields here... @@ -30,11 +27,9 @@ public RealmDemoData() { } - public RealmDemoData(float xValue, float yValue, double xAxisPosition, String xAxisLabel) { + public RealmDemoData(float xValue, float yValue) { this.xValue = xValue; this.yValue = yValue; - this.xAxisPosition = xAxisPosition; - this.xAxisLabel = xAxisLabel; } /** @@ -42,13 +37,9 @@ public RealmDemoData(float xValue, float yValue, double xAxisPosition, String xA * * @param xValue * @param stackValues - * @param xAxisPosition - * @param xAxisLabel */ - public RealmDemoData(float xValue, float[] stackValues, double xAxisPosition, String xAxisLabel) { + public RealmDemoData(float xValue, float[] stackValues) { this.xValue = xValue; - this.xAxisPosition = xAxisPosition; - this.xAxisLabel = xAxisLabel; this.stackValues = new RealmList(); for (float val : stackValues) { @@ -64,19 +55,14 @@ public RealmDemoData(float xValue, float[] stackValues, double xAxisPosition, St * @param low * @param open * @param close - * @param xAxisPosition - * @param xAxisLabel */ - public RealmDemoData(float xValue, float high, float low, float open, float close, double xAxisPosition, String - xAxisLabel) { + public RealmDemoData(float xValue, float high, float low, float open, float close) { this.yValue = (high + low) / 2f; this.high = high; this.low = low; this.open = open; this.close = close; this.xValue = xValue; - this.xAxisPosition = xAxisPosition; - this.xAxisLabel = xAxisLabel; } /** @@ -85,15 +71,11 @@ public RealmDemoData(float xValue, float high, float low, float open, float clos * @param xValue * @param yValue * @param bubbleSize - * @param xAxisPosition - * @param xAxisLabel */ - public RealmDemoData(float xValue, float yValue, float bubbleSize, double xAxisPosition, String xAxisLabel) { + public RealmDemoData(float xValue, float yValue, float bubbleSize) { this.xValue = xValue; this.yValue = yValue; this.bubbleSize = bubbleSize; - this.xAxisPosition = xAxisPosition; - this.xAxisLabel = xAxisLabel; } public float getyValue() { @@ -168,19 +150,4 @@ public void setSomeStringField(String someStringField) { this.someStringField = someStringField; } - public double getxAxisPosition() { - return xAxisPosition; - } - - public void setxAxisPosition(double xAxisPosition) { - this.xAxisPosition = xAxisPosition; - } - - public String getxAxisLabel() { - return xAxisLabel; - } - - public void setxAxisLabel(String xAxisLabel) { - this.xAxisLabel = xAxisLabel; - } } \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index 70463a7534..008c849786 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -74,6 +74,7 @@ public View getView(int position, View convertView, Context c) { // set data holder.chart.setData((BarData) mChartData); + holder.chart.setFitBars(true); // do not forget to refresh the chart // holder.chart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 4eef9d13af..29007c8c97 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -110,7 +110,7 @@ protected void writeToDB(int objectCount) { float value = 40f + (float) (Math.random() * 60f); - RealmDemoData d = new RealmDemoData(i, value, i, "" + i); + RealmDemoData d = new RealmDemoData(i, value); mRealm.copyToRealm(d); } @@ -129,7 +129,7 @@ protected void writeToDBStack(int objectCount) { float val2 = 34f + (float) (Math.random() * 12.0f); float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - RealmDemoData d = new RealmDemoData(i, stack, i, "" + i); + RealmDemoData d = new RealmDemoData(i, stack); mRealm.copyToRealm(d); } @@ -156,7 +156,7 @@ protected void writeToDBCandle(int objectCount) { boolean even = i % 2 == 0; RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close, i, i + ""); + even ? val - close : val + close); mRealm.copyToRealm(d); } @@ -175,7 +175,7 @@ protected void writeToDBBubble(int objectCount) { float value = 30f + (float) (Math.random() * 100.0); float size = 15f + (float) (Math.random() * 20.0); - RealmDemoData d = new RealmDemoData(i, value, size, "" + i); + RealmDemoData d = new RealmDemoData(i, value, size); mRealm.copyToRealm(d); } @@ -198,7 +198,7 @@ protected void writeToDBPie() { String[] xValues = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(i, values[i], i, xValues[i]); + RealmDemoData d = new RealmDemoData(i, values[i]); mRealm.copyToRealm(d); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 0e612bee58..54e4c55bfd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -50,7 +50,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "yValue", "xValue"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); set.setLabel("Realm BarDataSet"); @@ -63,6 +63,7 @@ private void setData() { // set data mChart.setData(data); + mChart.setFitBars(true); mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 050c1be8d2..d02c947bac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -5,6 +5,7 @@ import android.util.AttributeSet; import android.util.Log; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.BarHighlighter; @@ -15,170 +16,191 @@ /** * Chart that draws bars. - * + * * @author Philipp Jahoda */ public class BarChart extends BarLineChartBase implements BarDataProvider { - /** flag that enables or disables the highlighting arrow */ - private boolean mDrawHighlightArrow = false; + /** + * flag that enables or disables the highlighting arrow + */ + private boolean mDrawHighlightArrow = false; - /** - * if set to true, all values are drawn above their bars, instead of below their top - */ - private boolean mDrawValueAboveBar = true; + /** + * if set to true, all values are drawn above their bars, instead of below their top + */ + private boolean mDrawValueAboveBar = true; - /** - * if set to true, a grey area is drawn behind each bar that indicates the maximum yValue - */ - private boolean mDrawBarShadow = false; + /** + * if set to true, a grey area is drawn behind each bar that indicates the maximum yValue + */ + private boolean mDrawBarShadow = false; + + private boolean mFitBars = false; + + public BarChart(Context context) { + super(context); + } + + public BarChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BarChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); + + setHighlighter(new BarHighlighter(this)); + + //mXAxis.mAxisMinimum = -0.5f; + } + + @Override + protected void calcMinMax() { + + if (mAutoScaleMinMaxEnabled) + mData.calcMinMax(); + + if (mFitBars) { + mXAxis.calculate(mData.getXMin() - mData.getBarWidth() / 2f, mData.getXMax() + mData.getBarWidth() / 2f); + } else { + mXAxis.calculate(mData.getXMin(), mData.getXMax()); + } + + // calculate axis range (min / max) according to provided data + mAxisLeft.calculate(mData.getYMin(YAxis.AxisDependency.LEFT), mData.getYMax(YAxis.AxisDependency.LEFT)); + mAxisRight.calculate(mData.getYMin(YAxis.AxisDependency.RIGHT), mData.getYMax(YAxis.AxisDependency + .RIGHT)); + } + + /** + * Returns the Highlight object (contains xPx-index and DataSet index) of the selected yValue at the given touch + * point + * inside the BarChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else + return getHighlighter().getHighlight(x, y); + } + + /** + * Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be + * found in the charts data. + * + * @param e + * @return + */ + public RectF getBarBounds(BarEntry e) { + + IBarDataSet set = mData.getDataSetForEntry(e); + + if (set == null) + return null; + + float y = e.getY(); + float x = e.getX(); + + float barWidth = mData.getBarWidth(); + + float left = x - barWidth / 2f; + float right = x + barWidth / 2f; + float top = y >= 0 ? y : 0; + float bottom = y <= 0 ? y : 0; + + RectF bounds = new RectF(left, top, right, bottom); + + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); + + return bounds; + } + + /** + * set this to true to draw the highlightning arrow + * + * @param enabled + */ + public void setDrawHighlightArrow(boolean enabled) { + mDrawHighlightArrow = enabled; + } + + /** + * returns true if drawing the highlighting arrow is enabled, false if not + * + * @return + */ + public boolean isDrawHighlightArrowEnabled() { + return mDrawHighlightArrow; + } + + /** + * If set to true, all values are drawn above their bars, instead of below their top. + * + * @param enabled + */ + public void setDrawValueAboveBar(boolean enabled) { + mDrawValueAboveBar = enabled; + } + + /** + * returns true if drawing values above bars is enabled, false if not + * + * @return + */ + public boolean isDrawValueAboveBarEnabled() { + return mDrawValueAboveBar; + } + + /** + * If set to true, a grey area is drawn behind each bar that indicates the maximum yValue. Enabling his will reduce + * performance by about 50%. + * + * @param enabled + */ + public void setDrawBarShadow(boolean enabled) { + mDrawBarShadow = enabled; + } + + /** + * returns true if drawing shadows (maxvalue) for each bar is enabled, false if not + * + * @return + */ + public boolean isDrawBarShadowEnabled() { + return mDrawBarShadow; + } + + @Override + public BarData getBarData() { + return mData; + } + + + /** + * Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be + * fully displayed. + * Default: false + * + * @param enabled + */ + public void setFitBars(boolean enabled) { + mFitBars = enabled; + } - public BarChart(Context context) { - super(context); - } - - public BarChart(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public BarChart(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void init() { - super.init(); - - mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); - - setHighlighter(new BarHighlighter(this)); - - //mXAxis.mAxisMinimum = -0.5f; - } - - @Override - protected void calcMinMax() { - super.calcMinMax(); -// -// // increase deltax by 1 because the bars have a width of 1 -// mXAxis.mAxisRange += 0.5f; -// -// // extend xDelta to make space for multiple datasets (if ther are one) -// mXAxis.mAxisRange *= mData.getDataSetCount(); -// -// float groupSpace = mData.getGroupSpace(); -// mXAxis.mAxisRange += mData.getXValCount() * groupSpace; -// mXAxis.mAxisMaximum = mXAxis.mAxisRange - mXAxis.mAxisMinimum; - } - - /** - * Returns the Highlight object (contains xPx-index and DataSet index) of the selected yValue at the given touch point - * inside the BarChart. - * - * @param x - * @param y - * @return - */ - @Override - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else - return getHighlighter().getHighlight(x, y); - } - - /** - * Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be - * found in the charts data. - * - * @param e - * @return - */ - public RectF getBarBounds(BarEntry e) { - - IBarDataSet set = mData.getDataSetForEntry(e); - - if (set == null) - return null; - - float y = e.getY(); - float x = e.getX(); - - float barWidth = mData.getBarWidth(); - - float left = x - barWidth / 2f; - float right = x + barWidth / 2f; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - - RectF bounds = new RectF(left, top, right, bottom); - - getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - - return bounds; - } - - /** - * set this to true to draw the highlightning arrow - * - * @param enabled - */ - public void setDrawHighlightArrow(boolean enabled) { - mDrawHighlightArrow = enabled; - } - - /** - * returns true if drawing the highlighting arrow is enabled, false if not - * - * @return - */ - public boolean isDrawHighlightArrowEnabled() { - return mDrawHighlightArrow; - } - - /** - * If set to true, all values are drawn above their bars, instead of below their top. - * - * @param enabled - */ - public void setDrawValueAboveBar(boolean enabled) { - mDrawValueAboveBar = enabled; - } - - /** - * returns true if drawing values above bars is enabled, false if not - * - * @return - */ - public boolean isDrawValueAboveBarEnabled() { - return mDrawValueAboveBar; - } - - /** - * If set to true, a grey area is drawn behind each bar that indicates the maximum yValue. Enabling his will reduce - * performance by about 50%. - * - * @param enabled - */ - public void setDrawBarShadow(boolean enabled) { - mDrawBarShadow = enabled; - } - - /** - * returns true if drawing shadows (maxvalue) for each bar is enabled, false if not - * - * @return - */ - public boolean isDrawBarShadowEnabled() { - return mDrawBarShadow; - } - - @Override - public BarData getBarData() { - return mData; - } // /** // * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on the chart. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 2768ad89df..f50200ab39 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -57,7 +57,7 @@ public abstract class BarLineChartBase Date: Sat, 4 Jun 2016 00:24:42 +0200 Subject: [PATCH 0952/1390] Bugfixes related to realm support --- .../mpchartexample/custom/RealmDemoData.java | 27 +++++++++++++ .../realm/RealmBaseActivity.java | 4 +- .../realm/RealmDatabaseActivityCandle.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 1 + .../realm/RealmWikiExample.java | 6 ++- .../RealmLineScatterCandleRadarDataSet.java | 6 +-- .../implementation/RealmCandleDataSet.java | 38 ++++++++++--------- .../realm/implementation/RealmPieDataSet.java | 21 ++++++++++ .../charting/renderer/PieChartRenderer.java | 8 ++-- 10 files changed, 86 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index d753d3e8c8..7becc88c90 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -21,12 +21,21 @@ public class RealmDemoData extends RealmObject { private String someStringField; + /** + * label for pie entries + */ + private String label; + // ofc there could me more fields here... public RealmDemoData() { } + public RealmDemoData(float yValue) { + this.yValue = yValue; + } + public RealmDemoData(float xValue, float yValue) { this.xValue = xValue; this.yValue = yValue; @@ -78,6 +87,17 @@ public RealmDemoData(float xValue, float yValue, float bubbleSize) { this.bubbleSize = bubbleSize; } + /** + * Constructor for pie chart. + * + * @param yValue + * @param label + */ + public RealmDemoData(float yValue, String label) { + this.yValue = yValue; + this.label = label; + } + public float getyValue() { return yValue; } @@ -150,4 +170,11 @@ public void setSomeStringField(String someStringField) { this.someStringField = someStringField; } + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } } \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 29007c8c97..5d5eb0d06a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -195,10 +195,10 @@ protected void writeToDBPie() { float value5 = 100f - value1 - value2 - value3 - value4; float[] values = new float[] { value1, value2, value3, value4, value5 }; - String[] xValues = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; + String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(i, values[i]); + RealmDemoData d = new RealmDemoData(values[i], labels[i]); mRealm.copyToRealm(d); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index c8f7abb84d..1dd544fcce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); - set.setLabel("Realm Realm CandleDataSet"); + set.setLabel("Realm CandleDataSet"); set.setShadowColor(Color.DKGRAY); set.setShadowWidth(0.7f); set.setDecreasingColor(Color.RED); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index bb97dd6681..8bcda98356 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 5995ebb5a2..fe408bdc00 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -34,6 +34,7 @@ protected void onCreate(Bundle savedInstanceState) { setup(mChart); mChart.getYAxis().setEnabled(false); + mChart.getXAxis().setEnabled(false); mChart.setWebAlpha(180); mChart.setWebColorInner(Color.DKGRAY); mChart.setWebColor(Color.GRAY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 7a9386bfbe..06408f6878 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -48,9 +48,12 @@ protected void onCreate(Bundle savedInstanceState) { lineChart.getAxisLeft().setDrawGridLines(false); lineChart.getXAxis().setDrawGridLines(false); + lineChart.getXAxis().setLabelCount(5); + lineChart.getXAxis().setGranularity(1f); barChart.getAxisLeft().setDrawGridLines(false); barChart.getXAxis().setDrawGridLines(false); - barChart.getXAxis().setCenterAxisLabels(true); + barChart.getXAxis().setLabelCount(5); + barChart.getXAxis().setGranularity(1f); } @Override @@ -130,6 +133,7 @@ public int getDecimalDigits() { styleData(barData); barChart.setData(barData); + barChart.setFitBars(true); barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java index 9024bb6389..1f0c4b064b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java @@ -31,11 +31,11 @@ public RealmLineScatterCandleRadarDataSet(RealmResults results, String yValue * Constructor that takes the realm RealmResults, sorts & stores them. * * @param results + * @param xValueField * @param yValuesField - * @param xIndexField */ - public RealmLineScatterCandleRadarDataSet(RealmResults results, String yValuesField, String xIndexField) { - super(results, yValuesField, xIndexField); + public RealmLineScatterCandleRadarDataSet(RealmResults results, String xValueField, String yValuesField) { + super(results, xValueField, yValuesField); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index e4288af115..1328fb1e4f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -15,7 +15,8 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmCandleDataSet extends RealmLineScatterCandleRadarDataSet implements ICandleDataSet { +public class RealmCandleDataSet extends RealmLineScatterCandleRadarDataSet + implements ICandleDataSet { private String mHighField; private String mLowField; @@ -30,7 +31,7 @@ public class RealmCandleDataSet extends RealmLineScatterC /** * should the candle bars show? * when false, only "ticks" will show - * + *

    * - default: true */ private boolean mShowCandleBar = true; @@ -82,12 +83,13 @@ public class RealmCandleDataSet extends RealmLineScatterC * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param highField the name of the field in your data object that represents the "high" yValue - * @param lowField the name of the field in your data object that represents the "low" yValue - * @param openField the name of the field in your data object that represents the "open" yValue - * @param closeField the name of the field in your data object that represents the "close" yValue + * @param highField the name of the field in your data object that represents the "high" value + * @param lowField the name of the field in your data object that represents the "low" value + * @param openField the name of the field in your data object that represents the "open" value + * @param closeField the name of the field in your data object that represents the "close" value */ - public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField) { + public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String + closeField) { super(result, null); this.mHighField = highField; this.mLowField = lowField; @@ -102,14 +104,15 @@ public RealmCandleDataSet(RealmResults result, String highField, String lowFi * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param highField the name of the field in your data object that represents the "high" yValue - * @param lowField the name of the field in your data object that represents the "low" yValue - * @param openField the name of the field in your data object that represents the "open" yValue - * @param closeField the name of the field in your data object that represents the "close" yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index + * @param xValueField the name of the field in your data object that represents the "x" value + * @param highField the name of the field in your data object that represents the "high" value + * @param lowField the name of the field in your data object that represents the "low" value + * @param openField the name of the field in your data object that represents the "open" value + * @param closeField the name of the field in your data object that represents the "close" value */ - public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField, String xIndexField) { - super(result, null, xIndexField); + public RealmCandleDataSet(RealmResults result, String xValueField, String highField, String lowField, String openField, String + closeField) { + super(result, xValueField, null); this.mHighField = highField; this.mLowField = lowField; this.mOpenField = openField; @@ -119,11 +122,12 @@ public RealmCandleDataSet(RealmResults result, String highField, String lowFi calcMinMax(); } - public CandleEntry buildEntryFromResultObject(T realmObject, int xIndex) { + @Override + public CandleEntry buildEntryFromResultObject(T realmObject, float x) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); return new CandleEntry( - mXValuesField == null ? xIndex : dynamicObject.getFloat(mXValuesField), + mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), dynamicObject.getFloat(mOpenField), @@ -165,7 +169,7 @@ public void calcMinMax() { mYMax = 0.f; } - if(mXMin == Float.MAX_VALUE) { + if (mXMin == Float.MAX_VALUE) { mXMin = 0.f; mXMax = 0.f; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 4d22de97c8..01d923eef5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.data.realm.implementation; +import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -35,6 +36,8 @@ public class RealmPieDataSet extends RealmBaseDataSet result, String yValuesField) { calcMinMax(); } + public RealmPieDataSet(RealmResults result, String yValuesField, String labelField) { + super(result, yValuesField); + this.mLabelField = labelField; + build(this.results); + calcMinMax(); + } + + @Override + public PieEntry buildEntryFromResultObject(T realmObject, float x) { + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); + + if(mLabelField == null) { + return new PieEntry(dynamicObject.getFloat(mYValuesField)); + } else { + return new PieEntry(dynamicObject.getFloat(mYValuesField), dynamicObject.getString(mLabelField)); + } + } + /** * Sets the space that is left out between the piechart-slices in dp. * Default: 0 --> no space, maximum 20f diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 43f70b0809..dfe3a96f66 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -506,13 +506,13 @@ public void drawValues(Canvas c) { labelPty, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount()) { + if (j < data.getEntryCount() && entry.getLabel() != null) { c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight, mValuePaint); } } else if (drawXOutside) { - if (j < data.getEntryCount()) { + if (j < data.getEntryCount() && entry.getLabel() != null) { mValuePaint.setColor(dataSet.getValueTextColor(j)); c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); } @@ -535,13 +535,13 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount()) { + if (j < data.getEntryCount() && entry.getLabel() != null) { c.drawText(entry.getLabel(), x, y + lineHeight, mValuePaint); } } else if (drawXInside) { - if (j < data.getEntryCount()) { + if (j < data.getEntryCount() && entry.getLabel() != null) { mValuePaint.setColor(dataSet.getValueTextColor(j)); c.drawText(entry.getLabel(), x, y + lineHeight / 2f, mValuePaint); } From 3076f259f96551ea3fa3d660d24a83a622c51ef4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 10:28:30 +0200 Subject: [PATCH 0953/1390] Fix drawing of horizontal x-axis grid lines --- .../HorizontalBarChartActivity.java | 4 +- .../XAxisRendererHorizontalBarChart.java | 76 +++++-------------- 2 files changed, 21 insertions(+), 59 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index b571fc7d2b..9797ae799f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -83,7 +83,7 @@ protected void onCreate(Bundle savedInstanceState) { xl.setPosition(XAxisPosition.BOTTOM); xl.setTypeface(tf); xl.setDrawAxisLine(true); - xl.setDrawGridLines(true); + xl.setDrawGridLines(false); xl.setGridLineWidth(0.3f); xl.setGranularity(10f); @@ -103,6 +103,7 @@ protected void onCreate(Bundle savedInstanceState) { // yr.setInverted(true); setData(12, 50); + mChart.setFitBars(true); mChart.animateY(2500); // setting data @@ -212,6 +213,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + mChart.setFitBars(true); mChart.invalidate(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 4b40a35778..3985343ed1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -152,73 +152,33 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } } -// /** -// * draws the xPx-labels on the specified yPx-position -// * -// * @param pos -// */ -// @Override -// protected void drawLabels(Canvas c, float pos, PointF anchor) { -// -// final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); -// -// // pre allocate to save performance (dont allocate in loop) -// float[] position = new float[] { -// 0f, 0f -// }; -// -// BarData bd = mChart.getData(); -// int step = bd.getDataSetCount(); -// -// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { -// -// position[1] = i * step + i * bd.getGroupSpace() -// + bd.getGroupSpace() / 2f; -// -// // consider groups (center label for each group) -// if (step > 1) { -// position[1] += ((float) step - 1f) / 2f; -// } -// -// mTrans.pointValuesToPixel(position); -// -// if (mViewPortHandler.isInBoundsY(position[1])) { -// -// String label = mXAxis.getValues().get(i).getLabel(); -// drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); -// } -// } -// } - @Override public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; - - float[] position = new float[] { - 0f, 0f - }; mGridPaint.setColor(mXAxis.getGridColor()); mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - BarData bd = mChart.getData(); - // take into consideration that multiple DataSets increase mDeltaX - int step = bd.getDataSetCount(); - -// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { -// -// position[1] = i * step + i * bd.getGroupSpace() - 0.5f; -// -// mTrans.pointValuesToPixel(position); -// -// if (mViewPortHandler.isInBoundsY(position[1])) { -// -// c.drawLine(mViewPortHandler.contentLeft(), position[1], -// mViewPortHandler.contentRight(), position[1], mGridPaint); -// } -// } + float[] positions = new float[mXAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + positions[i + 1] = mXAxis.mEntries[i / 2]; + } + + mTrans.pointValuesToPixel(positions); + + for (int i = 0; i < positions.length; i += 2) { + + float y = positions[i + 1]; + + if (mViewPortHandler.isInBoundsY(y)) { + + c.drawLine(mViewPortHandler.contentLeft(), y, + mViewPortHandler.contentRight(), y, mGridPaint); + } + } } @Override From 084935d9e30334d8c8937fc1ff76e1cf7a56c1fa Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 11:14:39 +0200 Subject: [PATCH 0954/1390] Cleanup y-axis renderers --- .../HorizontalBarChartActivity.java | 1 - .../renderer/XAxisRendererBarChart.java | 73 ---------------- .../charting/renderer/YAxisRenderer.java | 84 +++++++++++-------- .../YAxisRendererHorizontalBarChart.java | 62 +++++++------- 4 files changed, 76 insertions(+), 144 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 9797ae799f..3d6905f757 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -91,7 +91,6 @@ protected void onCreate(Bundle savedInstanceState) { yl.setTypeface(tf); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); - yl.setGridLineWidth(0.3f); yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java deleted file mode 100644 index 0be78ca0e9..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ /dev/null @@ -1,73 +0,0 @@ - -package com.github.mikephil.charting.renderer; - -//public class XAxisRendererBarChart extends XAxisRenderer { -// -// protected BarChart mChart; -// -// public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer trans, -// BarChart chart) { -// super(viewPortHandler, xAxis, trans); -// -// this.mChart = chart; -// } -// -// /** -// * draws the xPx-labels on the specified yPx-position -// * -// * @param pos -// */ -// @Override -// protected void drawLabels(Canvas c, float pos, PointF anchor) { -// -// final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); -// -// // pre allocate to save performance (dont allocate in loop) -// float[] position = new float[] { -// 0f, 0f -// }; -// -// BarData bd = mChart.getData(); -// int step = bd.getDataSetCount(); -// -//// for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { -//// -//// position[0] = i * step + i * bd.getGroupSpace() -//// + bd.getGroupSpace() / 2f; -//// -//// // consider groups (center label for each group) -//// if (step > 1) { -//// position[0] += ((float) step - 1f) / 2f; -//// } -//// -//// mTrans.pointValuesToPixel(position); -//// -//// if (mViewPortHandler.isInBoundsX(position[0]) && i >= 0 -//// && i < mXAxis.getValues().size()) { -//// -//// String label = mXAxis.getValues().get(i).getLabel(); -//// -//// if (mXAxis.isAvoidFirstLastClippingEnabled()) { -//// -//// // avoid clipping of the last -//// if (i == mXAxis.getValues().size() - 1) { -//// float width = Utils.calcTextWidth(mAxisLabelPaint, label); -//// -//// if (position[0] + width / 2.f > mViewPortHandler.contentRight()) -//// position[0] = mViewPortHandler.contentRight() - (width / 2.f); -//// -//// // avoid clipping of the first -//// } else if (i == 0) { -//// -//// float width = Utils.calcTextWidth(mAxisLabelPaint, label); -//// -//// if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) -//// position[0] = mViewPortHandler.contentLeft() + (width / 2.f); -//// } -//// } -//// -//// drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); -//// } -//// } -// } -//} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index cf4c30ddb7..372174c3be 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -147,16 +147,7 @@ public void renderAxisLabels(Canvas c) { if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; - float[] positions = new float[mYAxis.mEntryCount * 2]; - - for (int i = 0; i < positions.length; i += 2) { - // only fill yPx values, xPx values are not needed since the yPx-labels - // are - // static on the xPx-axis - positions[i + 1] = mYAxis.mEntries[i / 2]; - } - - mTrans.pointValuesToPixel(positions); + float[] positions = getTransformedPositions(); mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); @@ -238,61 +229,80 @@ public void renderGridLines(Canvas c) { if (!mYAxis.isEnabled()) return; - // pre alloc - float[] position = new float[2]; - if (mYAxis.isDrawGridLinesEnabled()) { + float[] positions = getTransformedPositions(); + mGridPaint.setColor(mYAxis.getGridColor()); mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); Path gridLinePath = new Path(); - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { - - position[1] = mYAxis.mEntries[i]; - mTrans.pointValuesToPixel(position); - - gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); - gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); + // draw the grid + for (int i = 0; i < positions.length; i += 2) { // draw a path because lines don't support dashing on lower android versions - c.drawPath(gridLinePath, mGridPaint); - + c.drawPath(linePath(gridLinePath, i, positions), mGridPaint); gridLinePath.reset(); } } if (mYAxis.isDrawZeroLineEnabled()) { + drawZeroLine(c); + } + } + + /** + * Calculates the path for a grid line. + * + * @param p + * @param i + * @param positions + * @return + */ + protected Path linePath(Path p, int i, float[] positions) { - // draw zero line - position[1] = 0f; - mTrans.pointValuesToPixel(position); + p.moveTo(mViewPortHandler.offsetLeft(), positions[i + 1]); + p.lineTo(mViewPortHandler.contentRight(), positions[i + 1]); - drawZeroLine(c, mViewPortHandler.offsetLeft(), mViewPortHandler.contentRight(), position[1] - 1, position[1] - 1); - } + return p; } /** - * Draws the zero line at the specified position. + * Transforms the values contained in the axis entries to screen pixels and returns them in form of a float array + * of x- and y-coordinates. * - * @param c - * @param x1 - * @param x2 - * @param y1 - * @param y2 + * @return */ - protected void drawZeroLine(Canvas c, float x1, float x2, float y1, float y2) { + protected float[] getTransformedPositions() { + + float[] positions = new float[mYAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + // only fill y values, x values are not needed for y-labels + positions[i + 1] = mYAxis.mEntries[i / 2]; + } + + mTrans.pointValuesToPixel(positions); + return positions; + } + + /** + * Draws the zero line. + */ + protected void drawZeroLine(Canvas c) { + + // draw zero line + PointD pos = mTrans.getPixelsForValues(0f, 0f); mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); Path zeroLinePath = new Path(); - zeroLinePath.moveTo(x1, y1); - zeroLinePath.lineTo(x2, y2); + zeroLinePath.moveTo(mViewPortHandler.contentLeft(), (float) pos.y - 1); + zeroLinePath.lineTo(mViewPortHandler.contentRight(), (float) pos.y - 1); // draw a path because lines don't support dashing on lower android versions c.drawPath(zeroLinePath, mZeroLinePaint); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 330ac05eb6..7b5ff68b8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -66,16 +66,7 @@ public void renderAxisLabels(Canvas c) { if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) return; - float[] positions = new float[mYAxis.mEntryCount * 2]; - - for (int i = 0; i < positions.length; i += 2) { - // only fill yPx values, xPx values are not needed since the yPx-labels - // are - // static on the xPx-axis - positions[i] = mYAxis.mEntries[i / 2]; - } - - mTrans.pointValuesToPixel(positions); + float[] positions = getTransformedPositions(); mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); @@ -155,39 +146,44 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo } @Override - public void renderGridLines(Canvas c) { + protected float[] getTransformedPositions() { - if (!mYAxis.isEnabled()) - return; + float[] positions = new float[mYAxis.mEntryCount * 2]; + + for (int i = 0; i < positions.length; i += 2) { + // only fill x values, y values are not needed for x-labels + positions[i] = mYAxis.mEntries[i / 2]; + } - // pre alloc - float[] position = new float[2]; + mTrans.pointValuesToPixel(positions); + return positions; + } - if (mYAxis.isDrawGridLinesEnabled()) { + @Override + protected Path linePath(Path p, int i, float[] positions) { - mGridPaint.setColor(mYAxis.getGridColor()); - mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + p.moveTo(positions[i], mViewPortHandler.contentTop()); + p.lineTo(positions[i], mViewPortHandler.contentBottom()); - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { + return p; + } - position[0] = mYAxis.mEntries[i]; - mTrans.pointValuesToPixel(position); + @Override + protected void drawZeroLine(Canvas c) { - c.drawLine(position[0], mViewPortHandler.contentTop(), position[0], - mViewPortHandler.contentBottom(), - mGridPaint); - } - } + // draw zero line + PointD pos = mTrans.getPixelsForValues(0f, 0f); - if (mYAxis.isDrawZeroLineEnabled()) { + mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); + mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); - // draw zero line - position[0] = 0f; - mTrans.pointValuesToPixel(position); + Path zeroLinePath = new Path(); - drawZeroLine(c, position[0]+1, position[0]+1, mViewPortHandler.contentTop(), mViewPortHandler.contentBottom()); - } + zeroLinePath.moveTo((float) pos.x - 1, mViewPortHandler.contentTop()); + zeroLinePath.lineTo((float) pos.x - 1, mViewPortHandler.contentBottom()); + + // draw a path because lines don't support dashing on lower android versions + c.drawPath(zeroLinePath, mZeroLinePaint); } /** From 66434c6a8eaccce157d7da58558a945fff3e9f2d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 14:18:43 +0200 Subject: [PATCH 0955/1390] Test axis renderer --- .../mikephil/charting/components/XAxis.java | 36 ------ .../charting/renderer/AxisRenderer.java | 29 +++-- .../charting/renderer/YAxisRenderer.java | 15 ++- .../charting/test/AxisRendererTest.java | 111 ++++++++++++++++++ 4 files changed, 136 insertions(+), 55 deletions(-) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index be48c164b7..5a21292866 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -115,40 +115,4 @@ public void setAvoidFirstLastClipping(boolean enabled) { public boolean isAvoidFirstLastClippingEnabled() { return mAvoidFirstLastClipping; } - -// /** -// * Sets the labels for this axis. -// * -// * @param values -// */ -// public void setValues(List values) { -// mValues = values; -// } -// -// /** -// * Returns the labels for this axis. -// * -// * @return -// */ -// public List getValues() { -// return mValues; -// } -// -// /** -// * Adds a new xPx-yValue to the chart data. -// * -// * @param xVal -// */ -// public void addXValue(XAxisValue xVal) { -// mValues.add(xVal); -// } -// -// /** -// * Removes the xPx-yValue at the specified index. -// * -// * @param index -// */ -// public void removeXValue(int index) { -// mValues.remove(index); -// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 26260c320e..0c641a5ffd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -51,21 +51,24 @@ public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase this.mTrans = trans; this.mAxis = axis; - mAxisLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + if(mTrans != null) { - mGridPaint = new Paint(); - mGridPaint.setColor(Color.GRAY); - mGridPaint.setStrokeWidth(1f); - mGridPaint.setStyle(Style.STROKE); - mGridPaint.setAlpha(90); + mAxisLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mAxisLinePaint = new Paint(); - mAxisLinePaint.setColor(Color.BLACK); - mAxisLinePaint.setStrokeWidth(1f); - mAxisLinePaint.setStyle(Style.STROKE); + mGridPaint = new Paint(); + mGridPaint.setColor(Color.GRAY); + mGridPaint.setStrokeWidth(1f); + mGridPaint.setStyle(Style.STROKE); + mGridPaint.setAlpha(90); - mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mLimitLinePaint.setStyle(Paint.Style.STROKE); + mAxisLinePaint = new Paint(); + mAxisLinePaint.setColor(Color.BLACK); + mAxisLinePaint.setStrokeWidth(1f); + mAxisLinePaint.setStyle(Style.STROKE); + + mLimitLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + } } /** @@ -116,7 +119,7 @@ public void computeAxis(float min, float max, boolean inverted) { // calculate the starting and entry point of the yPx-labels (depending on // zoom / contentrect bounds) - if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + if (mViewPortHandler != null && mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 372174c3be..f5b1539af1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -28,13 +28,16 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t this.mYAxis = yAxis; - mAxisLabelPaint.setColor(Color.BLACK); - mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + if(mTrans != null) { - mZeroLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mZeroLinePaint.setColor(Color.GRAY); - mZeroLinePaint.setStrokeWidth(1f); - mZeroLinePaint.setStyle(Paint.Style.STROKE); + mAxisLabelPaint.setColor(Color.BLACK); + mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + + mZeroLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mZeroLinePaint.setColor(Color.GRAY); + mZeroLinePaint.setStrokeWidth(1f); + mZeroLinePaint.setStyle(Paint.Style.STROKE); + } } // @Override diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java new file mode 100644 index 0000000000..b50bd4f9a5 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java @@ -0,0 +1,111 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.renderer.AxisRenderer; +import com.github.mikephil.charting.renderer.YAxisRenderer; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by philipp on 31/05/16. + */ +public class AxisRendererTest { + + + @Test + public void testComputeAxisValues() { + + YAxis yAxis = new YAxis(); + yAxis.setLabelCount(6); + AxisRenderer renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(0, 100, false); + float[] entries = yAxis.mEntries; + + assertEquals(6, entries.length); + assertEquals(20, entries[1] - entries[0], 0.01); // interval 20 + assertEquals(0, entries[0], 0.01); + assertEquals(100, entries[entries.length - 1], 0.01); + + yAxis = new YAxis(); + yAxis.setLabelCount(6); + yAxis.setGranularity(50f); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(0, 100, false); + entries = yAxis.mEntries; + + assertEquals(3, entries.length); + assertEquals(50, entries[1] - entries[0], 0.01); // interval 50 + assertEquals(0, entries[0], 0.01); + assertEquals(100, entries[entries.length - 1], 0.01); + + yAxis = new YAxis(); + yAxis.setLabelCount(5, true); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(0, 100, false); + entries = yAxis.mEntries; + + assertEquals(5, entries.length); + assertEquals(25, entries[1] - entries[0], 0.01); // interval 25 + assertEquals(0, entries[0], 0.01); + assertEquals(100, entries[entries.length - 1], 0.01); + + yAxis = new YAxis(); + yAxis.setLabelCount(5, true); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(0, 0.01f, false); + entries = yAxis.mEntries; + + assertEquals(5, entries.length); + assertEquals(0.0025, entries[1] - entries[0], 0.0001); + assertEquals(0, entries[0], 0.0001); + assertEquals(0.01, entries[entries.length - 1], 0.0001); + + yAxis = new YAxis(); + yAxis.setLabelCount(5, false); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(0, 0.01f, false); + entries = yAxis.mEntries; + + assertEquals(5, entries.length); + assertEquals(0.0020, entries[1] - entries[0], 0.0001); + assertEquals(0, entries[0], 0.0001); + assertEquals(0.0080, entries[entries.length - 1], 0.0001); + + yAxis = new YAxis(); + yAxis.setLabelCount(6); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(-50, 50, false); + entries = yAxis.mEntries; + + assertEquals(5, entries.length); + assertEquals(-40, entries[0], 0.0001); + assertEquals(0, entries[2], 0.0001); + assertEquals(40, entries[entries.length - 1], 0.0001); + + yAxis = new YAxis(); + yAxis.setLabelCount(6); + renderer = new YAxisRenderer(null, yAxis, null); + + renderer.computeAxis(-50, 100, false); + entries = yAxis.mEntries; + + assertEquals(5, entries.length); + assertEquals(-30, entries[0], 0.0001); + assertEquals(30, entries[2], 0.0001); + assertEquals(90, entries[entries.length - 1], 0.0001); + } +} From b5cf9e120b5b0025b4729459a2902ca6760d3c46 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 14:31:47 +0200 Subject: [PATCH 0956/1390] Remove highlight-arrow feature, this can be done by markerview --- MPChartExample/res/menu/bar.xml | 4 -- .../mpchartexample/AnotherBarActivity.java | 8 ---- .../mpchartexample/BarChartActivity.java | 8 ---- .../BarChartActivityMultiDataset.java | 8 ---- .../mpchartexample/BarChartActivitySinus.java | 8 ---- .../HorizontalBarChartActivity.java | 8 ---- .../mpchartexample/StackedBarActivity.java | 8 ---- .../StackedBarActivityNegative.java | 8 ---- .../mikephil/charting/charts/BarChart.java | 34 +++++++------- .../charting/charts/CombinedChart.java | 5 -- .../dataprovider/BarDataProvider.java | 1 - .../charting/renderer/BarChartRenderer.java | 47 +++++++++---------- 12 files changed, 40 insertions(+), 107 deletions(-) diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index 4b35e2ff5d..9e0b3c3ce1 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -9,10 +9,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 3daac14bc0..fe967ffb8d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -130,14 +130,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 3a9b9e3533..80dd81db2b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -178,14 +178,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 71328613d6..ccaf24b348 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -151,14 +151,6 @@ public boolean onOptionsItemSelected(MenuItem item) { } break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 09c03e3cef..c9f6e3c48e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -152,14 +152,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(1500); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 3d6905f757..738e2ab40c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -171,14 +171,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 2e281d797e..2b75a119c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -146,14 +146,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 9aa82fc614..45f040c168 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -179,14 +179,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index d02c947bac..5187051d44 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -129,23 +129,23 @@ public RectF getBarBounds(BarEntry e) { return bounds; } - /** - * set this to true to draw the highlightning arrow - * - * @param enabled - */ - public void setDrawHighlightArrow(boolean enabled) { - mDrawHighlightArrow = enabled; - } - - /** - * returns true if drawing the highlighting arrow is enabled, false if not - * - * @return - */ - public boolean isDrawHighlightArrowEnabled() { - return mDrawHighlightArrow; - } +// /** +// * set this to true to draw the highlightning arrow +// * +// * @param enabled +// */ +// public void setDrawHighlightArrow(boolean enabled) { +// mDrawHighlightArrow = enabled; +// } +// +// /** +// * returns true if drawing the highlighting arrow is enabled, false if not +// * +// * @return +// */ +// public boolean isDrawHighlightArrowEnabled() { +// return mDrawHighlightArrow; +// } /** * If set to true, all values are drawn above their bars, instead of below their top. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index a5f6d77de6..f6419d9cb7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -167,11 +167,6 @@ public boolean isDrawValueAboveBarEnabled() { return mDrawValueAboveBar; } - @Override - public boolean isDrawHighlightArrowEnabled() { - return mDrawHighlightArrow; - } - /** * set this to true to draw the highlightning arrow * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java index 2f0675fc4a..631060d2d6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java @@ -7,5 +7,4 @@ public interface BarDataProvider extends BarLineScatterCandleBubbleDataProvider BarData getBarData(); boolean isDrawBarShadowEnabled(); boolean isDrawValueAboveBarEnabled(); - boolean isDrawHighlightArrowEnabled(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 8c81fb5eba..a946467426 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -3,7 +3,9 @@ import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; @@ -236,7 +238,8 @@ public void drawValues(Canvas c) { float val = entry.getY(); drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, - val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), dataSet.getValueTextColor + val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), + dataSet.getValueTextColor (j / 4)); } @@ -355,7 +358,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float x = high.getX(); BarEntry e = set.getEntryForXPos(x); - int entryIndex = set.getEntryIndex(e); if (e == null) continue; @@ -375,37 +377,34 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); - //prepareBarHighlight(y1, y2, interval, entryIndex, dataSetIndex, setCount, barSpace, groupSpace, - // trans); - c.drawRect(mBarRect, mHighlightPaint); -// if (mChart.isDrawHighlightArrowEnabled()) { +// if (mChart.isDrawHighlightArrowEnabled()) { // -// mHighlightPaint.setAlpha(255); +// mHighlightPaint.setAlpha(255); // -// // distance between highlight arrow and bar -// float offsetY = mAnimator.getPhaseY() * 0.07f; +// // distance between highlight arrow and bar +// float offsetY = mAnimator.getPhaseY() * 0.07f; // -// float[] values = new float[9]; -// trans.getPixelToValueMatrix().getValues(values); -// final float xToYRel = Math.abs( -// values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); +// float[] values = new float[9]; +// trans.getPixelToValueMatrix().getValues(values); +// final float xToYRel = Math.abs( +// values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); // -// final float arrowWidth = set.getBarSpace() / 2.f; -// final float arrowHeight = arrowWidth * xToYRel; +// final float arrowWidth = barData.getBarWidth(); +// final float arrowWidthHalf = arrowWidth / 2f; +// final float arrowHeight = arrowWidth * xToYRel; // -// final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); +// final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); // -// Path arrow = new Path(); -// arrow.moveTo(xPx + 0.4f, yArrow + offsetY); -// arrow.lineTo(xPx + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); -// arrow.lineTo(xPx + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); +// Path arrow = new Path(); +// arrow.moveTo(e.getX() - arrowWidthHalf, yArrow + offsetY + arrowHeight); +// arrow.lineTo(e.getX(), yArrow + offsetY); +// arrow.lineTo(e.getX() + arrowWidthHalf, yArrow + offsetY + arrowHeight); // -// trans.pathValueToPixel(arrow); -// c.drawPath(arrow, mHighlightPaint); -// } - +// trans.pathValueToPixel(arrow); +// c.drawPath(arrow, mHighlightPaint); +// } } } From cee380be6cdd57ce00d0078e27ba6b7dfa6d3a87 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 14:44:39 +0200 Subject: [PATCH 0957/1390] Fix issue in highlight animation for barchart --- .../charting/renderer/BarChartRenderer.java | 5 +++-- .../renderer/HorizontalBarChartRenderer.java | 2 +- .../github/mikephil/charting/utils/Transformer.java | 13 ++++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index a946467426..899ef7ce0b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -178,7 +178,7 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHa mBarRect.set(left, top, right, bottom); - trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + trans.rectToPixelPhase(mBarRect, mAnimator.getPhaseY()); } @Override @@ -358,8 +358,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float x = high.getX(); BarEntry e = set.getEntryForXPos(x); + float entryIndex = set.getEntryIndex(e); - if (e == null) + if (e == null || entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) continue; boolean isStack = high.getStackIndex() < 0 ? false : true; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 8c1d64dd73..e4cb3150d2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -288,7 +288,7 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHa mBarRect.set(left, top, right, bottom); - trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + trans.rectToPixelPhaseHorizontal(mBarRect, mAnimator.getPhaseY()); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 40d738e9d6..189de13cd1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -300,7 +300,7 @@ public void rectValueToPixel(RectF r) { * @param r * @param phaseY */ - public void rectValueToPixel(RectF r, float phaseY) { + public void rectToPixelPhase(RectF r, float phaseY) { // multiply the height of the rect with the phase r.top *= phaseY; @@ -311,6 +311,17 @@ public void rectValueToPixel(RectF r, float phaseY) { mMatrixOffset.mapRect(r); } + public void rectToPixelPhaseHorizontal(RectF r, float phaseY) { + + // multiply the height of the rect with the phase + r.left *= phaseY; + r.right *= phaseY; + + mMatrixValueToPx.mapRect(r); + mViewPortHandler.getMatrixTouch().mapRect(r); + mMatrixOffset.mapRect(r); + } + /** * Transform a rectangle with all matrices with potential animation phases. * From 1dd8c901d613bff9fc025d05bde81a4b8235f8fd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 14:51:39 +0200 Subject: [PATCH 0958/1390] Documentation cleanup --- .../charting/charts/BarLineChartBase.java | 49 +++++++++---------- .../dataprovider/ChartInterface.java | 8 +-- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index f50200ab39..e4676a5b71 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -655,7 +655,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { /** * Zooms in or out by the given scale factor. - * xPx and yPx are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). + * x and y are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). * * @param scaleX * @param scaleY @@ -789,11 +789,11 @@ public void moveViewToX(float xIndex) { } /** - * Centers the viewport to the specified yPx-yValue on the yPx-axis. + * Centers the viewport to the specified y value on the y-axis. * This also refreshes the chart by calling invalidate(). * * @param yValue - * @param axis - which axis should be used as a reference for the yPx-axis + * @param axis - which axis should be used as a reference for the y-axis */ public void moveViewToY(float yValue, AxisDependency axis) { @@ -807,36 +807,35 @@ public void moveViewToY(float yValue, AxisDependency axis) { /** * This will move the left side of the current viewport to the specified - * xPx-yValue on the xPx-axis, and center the viewport to the specified yPx-yValue - * on the yPx-axis. + * x value on the x-axis, and center the viewport to the specified y value on the y-axis. * This also refreshes the chart by calling invalidate(). * - * @param xIndex + * @param xValue * @param yValue - * @param axis - which axis should be used as a reference for the yPx-axis + * @param axis - which axis should be used as a reference for the y-axis */ - public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { + public void moveViewTo(float xValue, float yValue, AxisDependency axis) { float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new MoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, + Runnable job = new MoveViewJob(mViewPortHandler, xValue, yValue + valsInView / 2f, getTransformer(axis), this); addViewportJob(job); } /** - * This will move the left side of the current viewport to the specified xPx-position - * and center the viewport to the specified yPx-position animated. + * This will move the left side of the current viewport to the specified x value + * and center the viewport to the y value animated. * This also refreshes the chart by calling invalidate(). * - * @param xIndex + * @param xValue * @param yValue * @param axis * @param duration the duration of the animation in milliseconds */ @TargetApi(11) - public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { + public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { @@ -844,7 +843,7 @@ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xIndex, yValue + valsInView / 2f, + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xValue, yValue + valsInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); @@ -855,20 +854,20 @@ public void moveViewToAnimated(float xIndex, float yValue, AxisDependency axis, /** * This will move the center of the current viewport to the specified - * xPx-yValue and yPx-yValue. + * x and y value. * This also refreshes the chart by calling invalidate(). * - * @param xIndex + * @param xValue * @param yValue - * @param axis - which axis should be used as a reference for the yPx-axis + * @param axis - which axis should be used as a reference for the y axis */ - public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { + public void centerViewTo(float xValue, float yValue, AxisDependency axis) { float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new MoveViewJob(mViewPortHandler, - xIndex - xsInView / 2f, yValue + valsInView / 2f, + xValue - xsInView / 2f, yValue + valsInView / 2f, getTransformer(axis), this); addViewportJob(job); @@ -876,15 +875,15 @@ public void centerViewTo(float xIndex, float yValue, AxisDependency axis) { /** * This will move the center of the current viewport to the specified - * xPx-yValue and yPx-yValue animated. + * x and y value animated. * - * @param xIndex + * @param xValue * @param yValue * @param axis * @param duration the duration of the animation in milliseconds */ @TargetApi(11) - public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis, long duration) { + public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { if (android.os.Build.VERSION.SDK_INT >= 11) { @@ -894,7 +893,7 @@ public void centerViewToAnimated(float xIndex, float yValue, AxisDependency axis float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new AnimatedMoveViewJob(mViewPortHandler, - xIndex - xsInView / 2f, yValue + valsInView / 2f, + xValue - xsInView / 2f, yValue + valsInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); @@ -1206,7 +1205,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { } /** - * Returns the xPx and yPx values in the chart at the given touch point + * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). @@ -1232,7 +1231,7 @@ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { } /** - * returns the yPx-yValue at the given touch position (must not necessarily be + * Returns y value at the given touch position (must not necessarily be * a yValue contained in one of the datasets) * * @param x diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 14a61521de..6660e2e4fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -16,14 +16,14 @@ public interface ChartInterface { /** - * Returns the minimum xPx-yValue of the chart, regardless of zoom or translation. + * Returns the minimum x value of the chart, regardless of zoom or translation. * * @return */ float getXChartMin(); /** - * Returns the maximum xPx-yValue of the chart, regardless of zoom or translation. + * Returns the maximum x value of the chart, regardless of zoom or translation. * * @return */ @@ -32,14 +32,14 @@ public interface ChartInterface { float getXRange(); /** - * Returns the minimum yPx-yValue of the chart, regardless of zoom or translation. + * Returns the minimum y value of the chart, regardless of zoom or translation. * * @return */ float getYChartMin(); /** - * Returns the maximum yPx-yValue of the chart, regardless of zoom or translation. + * Returns the maximum y value of the chart, regardless of zoom or translation. * * @return */ From 22c7a6dc0377969210a2640a6bd0232c3509611a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 14:57:11 +0200 Subject: [PATCH 0959/1390] Cleanup recently noticed refactoring fail --- .../mpchartexample/AnotherBarActivity.java | 2 +- .../mpchartexample/BarChartActivity.java | 4 +- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 2 +- .../CandleStickChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../HorizontalBarChartActivity.java | 2 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 10 +-- .../mpchartexample/LineChartActivity2.java | 2 +- .../LineChartActivityColored.java | 2 +- .../mpchartexample/LineChartTime.java | 4 +- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PerformanceLineChart.java | 2 +- .../RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 4 +- .../StackedBarActivityNegative.java | 2 +- .../custom/MyCustomXAxisValueFormatter.java | 4 +- .../notimportant/MainActivity.java | 6 +- .../realm/RealmBaseActivity.java | 2 +- .../charting/animation/ChartAnimator.java | 32 ++++---- .../charting/buffer/AbstractBuffer.java | 14 ++-- .../mikephil/charting/charts/BarChart.java | 6 +- .../charting/charts/BarLineChartBase.java | 74 +++++++++---------- .../mikephil/charting/charts/Chart.java | 66 ++++++++--------- .../charting/charts/HorizontalBarChart.java | 14 ++-- .../mikephil/charting/charts/PieChart.java | 8 +- .../charting/charts/PieRadarChartBase.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 12 +-- .../charting/components/AxisBase.java | 14 ++-- .../charting/components/ComponentBase.java | 10 +-- .../charting/components/LimitLine.java | 8 +- .../charting/components/MarkerView.java | 8 +- .../mikephil/charting/components/XAxis.java | 18 ++--- .../mikephil/charting/components/YAxis.java | 24 +++--- .../mikephil/charting/data/BaseDataSet.java | 2 +- .../mikephil/charting/data/BaseEntry.java | 4 +- .../mikephil/charting/data/BubbleEntry.java | 8 +- .../mikephil/charting/data/CandleEntry.java | 4 +- .../mikephil/charting/data/ChartData.java | 36 ++++----- .../mikephil/charting/data/DataSet.java | 14 ++-- .../github/mikephil/charting/data/Entry.java | 14 ++-- .../mikephil/charting/data/PieData.java | 2 +- .../charting/data/filter/Approximator.java | 4 +- .../data/realm/base/RealmBaseDataSet.java | 16 ++-- .../implementation/RealmBubbleDataSet.java | 6 +- .../implementation/RealmLineDataSet.java | 2 +- .../realm/implementation/RealmPieDataSet.java | 2 +- .../implementation/RealmRadarDataSet.java | 2 +- .../implementation/RealmScatterDataSet.java | 2 +- .../charting/formatter/FillFormatter.java | 2 +- .../charting/highlight/ChartHighlighter.java | 8 +- .../charting/highlight/Highlight.java | 22 +++--- .../interfaces/datasets/IDataSet.java | 26 +++---- .../listener/BarLineChartTouchListener.java | 16 ++-- .../listener/OnChartGestureListener.java | 8 +- .../listener/PieRadarChartTouchListener.java | 2 +- .../charting/renderer/AxisRenderer.java | 6 +- .../renderer/BubbleChartRenderer.java | 4 +- .../renderer/CandleStickChartRenderer.java | 2 +- .../LineScatterCandleRadarRenderer.java | 4 +- .../charting/renderer/XAxisRenderer.java | 8 +- .../XAxisRendererHorizontalBarChart.java | 4 +- .../charting/renderer/YAxisRenderer.java | 6 +- .../YAxisRendererHorizontalBarChart.java | 10 +-- .../renderer/YAxisRendererRadarChart.java | 2 +- .../github/mikephil/charting/utils/FSize.java | 2 +- .../mikephil/charting/utils/PointD.java | 2 +- .../mikephil/charting/utils/Transformer.java | 28 +++---- .../github/mikephil/charting/utils/Utils.java | 6 +- .../charting/utils/ViewPortHandler.java | 70 +++++++++--------- 74 files changed, 367 insertions(+), 367 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index fe967ffb8d..159aafce7b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 80dd81db2b..37232cdbf1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -76,7 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); @@ -276,7 +276,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); - Log.i("xPx-index", + Log.i("x-index", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index ccaf24b348..93150589b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -61,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setDrawBorders(true); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index c9f6e3c48e..ce00167fb0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -62,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); // draw shadows for each bar that show the maximum yValue diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 5e279db25f..932e049674 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -48,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 8eabc4be56..51e7aa6bf9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 6e8b0ec5d3..d2b1e923e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -68,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index ba1fc3073c..4d103bedfc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -69,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setEnabled(false); // mChart.setYRange(-40f, 40f, true); - // call this to reset the changed yPx-range + // call this to reset the changed y-range // mChart.resetYRange(true); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 738e2ab40c..d70e7d219a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -69,7 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(60); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); // draw shadows for each bar that show the maximum yValue diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 0b6900637f..a28c7b1630 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -70,7 +70,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3a06bdeeb9..1e34863659 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -83,7 +83,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setScaleXEnabled(true); // mChart.setScaleYEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { // set the marker to the chart mChart.setMarkerView(mv); - // xPx-axis limit line + // x-axis limit line LimitLine llXAxis = new LimitLine(10f, "Index 10"); llXAxis.setLineWidth(4f); llXAxis.enableDashedLine(10f, 10f, 0f); @@ -105,7 +105,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); - //xAxis.addLimitLine(llXAxis); // add xPx-axis limit line + //xAxis.addLimitLine(llXAxis); // add x-axis limit line Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -344,7 +344,7 @@ private void setData(int count, float range) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) // ((mult * - // 0.1) / 10);xPx + // 0.1) / 10);x yVals.add(new Entry(i, val)); } @@ -396,7 +396,7 @@ private void setData(int count, float range) { @Override public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "START, xPx: " + me.getX() + ", yPx: " + me.getY()); + Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 236fceb28c..68ede3e0e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -75,7 +75,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 2ae7d0e4df..b66b166320 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -72,7 +72,7 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setDragEnabled(true); chart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately chart.setPinchZoom(false); chart.setBackgroundColor(color); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index f12d003555..c6f1ea85c7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color @@ -102,7 +102,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); - // custom xPx-axis min / max + // custom x-axis min / max xAxis.setAxisMinValue(5000); xAxis.setAxisMaxValue(30000); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index d354aedc5b..03ebedd57b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -68,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); mSeekBarX.setProgress(20); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 036e12ace7..8d2fc7f170 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -52,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 95f260bce9..62e82dff28 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -52,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setScaleEnabled(true); mChart.setDrawGridBackground(false); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(true); // set an alternative background color diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 0204147df7..f04d843904 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 2b75a119c8..8e86eaf158 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -62,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { // drawn mChart.setMaxVisibleValueCount(40); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); @@ -70,7 +70,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValueAboveBar(false); - // change the position of the yPx-labels + // change the position of the y-labels YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 45f040c168..4bbe293c5f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -51,7 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setDescription(""); - // scaling can now only be done on xPx- and yPx-axis separately + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 73c1ef4681..16d5752905 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -23,9 +23,9 @@ public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { @Override public String getFormattedValue(float value, AxisBase axis) { - //Log.i("TRANS", "xPx: " + viewPortHandler.getTransX() + ", yPx: " + viewPortHandler.getTransY()); + //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); - // e.g. adjust the xPx-axis values depending on scale / zoom level + // e.g. adjust the x-axis values depending on scale / zoom level if (mViewPortHandler.getScaleX() > 5) return "4"; else if (mViewPortHandler.getScaleX() > 3) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 96b383848a..dcade871f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -66,7 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); objects.add(new ContentItem("Line Chart (Dual YAxis)", - "Demonstration of the linechart with dual yPx-axis.")); + "Demonstration of the linechart with dual y-axis.")); objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); objects.add(new ContentItem("Horizontal Bar Chart", "A simple demonstration of the horizontal bar chart.")); @@ -97,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { "Demonstrates the usage of different chart types inside a ListView.")); objects.add(new ContentItem( "Inverted Line Chart", - "Demonstrates the feature of inverting the yPx-axis.")); + "Demonstrates the feature of inverting the y-axis.")); objects.add(new ContentItem( "Candle Stick Chart", "Demonstrates usage of the CandleStickChart.")); @@ -112,7 +112,7 @@ protected void onCreate(Bundle savedInstanceState) { "Shows a LineChart with different background and line color.")); objects.add(new ContentItem( "Realtime Chart", - "This chart is fed with new data in realtime. It also restrains the view on the xPx-axis.")); + "This chart is fed with new data in realtime. It also restrains the view on the x-axis.")); objects.add(new ContentItem( "Dynamical data adding", "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 5d5eb0d06a..05aa742864 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -52,7 +52,7 @@ protected void setup(Chart chart) { mChart.setDragEnabled(true); mChart.setScaleEnabled(true); - // if disabled, scaling can be done on xPx- and yPx-axis separately + // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index 455f7be3e2..639442a4c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -7,7 +7,7 @@ /** * Object responsible for all animations in the Chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.xPx) AND HIGHER. + * API LEVEL 11 (Android 3.0.x) AND HIGHER. * * @author Philipp Jahoda */ @@ -29,10 +29,10 @@ public ChartAnimator(AnimatorUpdateListener listener) { */ /** CODE BELOW THIS RELATED TO ANIMATION */ - /** the phase that is animated and influences the drawn values on the yPx-axis */ + /** the phase that is animated and influences the drawn values on the y-axis */ protected float mPhaseY = 1f; - /** the phase that is animated and influences the drawn values on the xPx-axis */ + /** the phase that is animated and influences the drawn values on the x-axis */ protected float mPhaseX = 1f; /** @@ -41,7 +41,7 @@ public ChartAnimator(AnimatorUpdateListener listener) { /** METHODS FOR CUSTOM EASING */ /** - * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with + * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -78,7 +78,7 @@ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction e } /** - * Animates the rendering of the chart on the xPx-axis with the specified + * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -98,7 +98,7 @@ public void animateX(int durationMillis, EasingFunction easing) { } /** - * Animates the rendering of the chart on the yPx-axis with the specified + * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -123,7 +123,7 @@ public void animateY(int durationMillis, EasingFunction easing) { /** METHODS FOR PREDEFINED EASING */ /** - * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with + * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -160,7 +160,7 @@ public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOpt } /** - * Animates the rendering of the chart on the xPx-axis with the specified + * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -180,7 +180,7 @@ public void animateX(int durationMillis, Easing.EasingOption easing) { } /** - * Animates the rendering of the chart on the yPx-axis with the specified + * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -205,7 +205,7 @@ public void animateY(int durationMillis, Easing.EasingOption easing) { /** METHODS FOR ANIMATION WITHOUT EASING */ /** - * Animates the drawing / rendering of the chart on both xPx- and yPx-axis with + * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * @@ -237,7 +237,7 @@ public void animateXY(int durationMillisX, int durationMillisY) { } /** - * Animates the rendering of the chart on the xPx-axis with the specified + * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -255,7 +255,7 @@ public void animateX(int durationMillis) { } /** - * Animates the rendering of the chart on the yPx-axis with the specified + * Animates the rendering of the chart on the y-axis with the specified * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * @@ -273,7 +273,7 @@ public void animateY(int durationMillis) { } /** - * This gets the yPx-phase that is used to animate the values. + * This gets the y-phase that is used to animate the values. * * @return */ @@ -282,7 +282,7 @@ public float getPhaseY() { } /** - * This modifys the yPx-phase that is used to animate the values. + * This modifys the y-phase that is used to animate the values. * * @param phase */ @@ -291,7 +291,7 @@ public void setPhaseY(float phase) { } /** - * This gets the xPx-phase that is used to animate the values. + * This gets the x-phase that is used to animate the values. * * @return */ @@ -300,7 +300,7 @@ public float getPhaseX() { } /** - * This modifys the xPx-phase that is used to animate the values. + * This modifys the x-phase that is used to animate the values. * * @param phase */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java index 6df0c01ba8..958d12afba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -15,19 +15,19 @@ public abstract class AbstractBuffer { /** index in the buffer */ protected int index = 0; - /** float-buffer that holds the data points to draw, order: xPx,yPx,xPx,yPx,... */ + /** float-buffer that holds the data points to draw, order: x,y,x,y,... */ public final float[] buffer; - /** animation phase xPx-axis */ + /** animation phase x-axis */ protected float phaseX = 1f; - /** animation phase yPx-axis */ + /** animation phase y-axis */ protected float phaseY = 1f; - /** indicates from which xPx-index the visible data begins */ + /** indicates from which x-index the visible data begins */ protected int mFrom = 0; - /** indicates to which xPx-index the visible data ranges */ + /** indicates to which x-index the visible data ranges */ protected int mTo = 0; /** @@ -40,14 +40,14 @@ public AbstractBuffer(int size) { buffer = new float[size]; } - /** limits the drawing on the xPx-axis */ + /** limits the drawing on the x-axis */ public void limitFrom(int from) { if (from < 0) from = 0; mFrom = from; } - /** limits the drawing on the xPx-axis */ + /** limits the drawing on the x-axis */ public void limitTo(int to) { if (to < 0) to = 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 5187051d44..e025728920 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -80,7 +80,7 @@ protected void calcMinMax() { } /** - * Returns the Highlight object (contains xPx-index and DataSet index) of the selected yValue at the given touch + * Returns the Highlight object (contains x-index and DataSet index) of the selected yValue at the given touch * point * inside the BarChart. * @@ -203,7 +203,7 @@ public void setFitBars(boolean enabled) { // /** -// * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on the chart. +// * Returns the lowest x-index (yValue on the x-axis) that is still visible on the chart. // * // * @return // */ @@ -220,7 +220,7 @@ public void setFitBars(boolean enabled) { // } // // /** -// * Returns the highest xPx-index (yValue on the xPx-axis) that is still visible on the chart. +// * Returns the highest x-index (yValue on the x-axis) that is still visible on the chart. // * // * @return // */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index e4676a5b71..e9055fec74 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -55,15 +55,15 @@ public abstract class BarLineChartBase zoom out, if > 1f --> zoom in @@ -722,12 +722,12 @@ public void setScaleMinima(float scaleX, float scaleY) { } /** - * Sets the size of the area (range on the xPx-axis) that should be maximum + * Sets the size of the area (range on the x-axis) that should be maximum * visible at once (no further zooming out allowed). If this is e.g. set to - * 10, no more than 10 values on the xPx-axis can be viewed at once without + * 10, no more than 10 values on the x-axis can be viewed at once without * scrolling. * - * @param maxXRange The maximum visible range of xPx-values. + * @param maxXRange The maximum visible range of x-values. */ public void setVisibleXRangeMaximum(float maxXRange) { float xScale = mXAxis.mAxisRange / (maxXRange); @@ -735,12 +735,12 @@ public void setVisibleXRangeMaximum(float maxXRange) { } /** - * Sets the size of the area (range on the xPx-axis) that should be minimum + * Sets the size of the area (range on the x-axis) that should be minimum * visible at once (no further zooming in allowed). If this is e.g. set to - * 10, no less than 10 values on the xPx-axis can be viewed at once without + * 10, no less than 10 values on the x-axis can be viewed at once without * scrolling. * - * @param minXRange The minimum visible range of xPx-values. + * @param minXRange The minimum visible range of x-values. */ public void setVisibleXRangeMinimum(float minXRange) { float xScale = mXAxis.mAxisRange / (minXRange); @@ -763,10 +763,10 @@ public void setVisibleXRange(float minXRange, float maxXRange) { } /** - * Sets the size of the area (range on the yPx-axis) that should be maximum + * Sets the size of the area (range on the y-axis) that should be maximum * visible at once. * - * @param maxYRange the maximum visible range on the yPx-axis + * @param maxYRange the maximum visible range on the y-axis * @param axis - the axis for which this limit should apply */ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { @@ -775,7 +775,7 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { } /** - * Moves the left side of the current viewport to the specified xPx-index. + * Moves the left side of the current viewport to the specified x-index. * This also refreshes the chart by calling invalidate(). * * @param xIndex @@ -950,7 +950,7 @@ public void resetViewPortOffsets() { /** CODE BELOW IS GETTERS AND SETTERS */ /** - * Returns the delta-yPx yValue (yPx-yValue range) of the specified axis. + * Returns the delta-y yValue (y-yValue range) of the specified axis. * * @param axis * @return @@ -1132,7 +1132,7 @@ public void setDrawGridBackground(boolean enabled) { /** * Sets drawing the borders rectangle to true. If this is enabled, there is - * no point drawing the axis-lines of xPx- and yPx-axis. + * no point drawing the axis-lines of x- and y-axis. * * @param enabled */ @@ -1187,7 +1187,7 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { } /** - * Returns the Highlight object (contains xPx-index and DataSet index) of the + * Returns the Highlight object (contains x-index and DataSet index) of the * selected yValue at the given touch point inside the Line-, Scatter-, or * CandleStick-Chart. * @@ -1273,7 +1273,7 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float } /** - * Returns the lowest xPx-index (yValue on the xPx-axis) that is still visible on + * Returns the lowest x-index (yValue on the x-axis) that is still visible on * the chart. * * @return @@ -1286,7 +1286,7 @@ public float getLowestVisibleX() { } /** - * Returns the highest xPx-index (yValue on the xPx-axis) that is still visible + * Returns the highest x-index (yValue on the x-axis) that is still visible * on the chart. * * @return @@ -1308,7 +1308,7 @@ public float getVisibleXRange() { } /** - * returns the current xPx-scale factor + * returns the current x-scale factor */ public float getScaleX() { if (mViewPortHandler == null) @@ -1318,7 +1318,7 @@ public float getScaleX() { } /** - * returns the current yPx-scale factor + * returns the current y-scale factor */ public float getScaleY() { if (mViewPortHandler == null) @@ -1337,7 +1337,7 @@ public boolean isFullyZoomedOut() { } /** - * Returns the left yPx-axis object. In the horizontal bar-chart, this is the + * Returns the left y-axis object. In the horizontal bar-chart, this is the * top axis. * * @return @@ -1347,7 +1347,7 @@ public YAxis getAxisLeft() { } /** - * Returns the right yPx-axis object. In the horizontal bar-chart, this is the + * Returns the right y-axis object. In the horizontal bar-chart, this is the * bottom axis. * * @return @@ -1357,7 +1357,7 @@ public YAxis getAxisRight() { } /** - * Returns the yPx-axis object to the corresponding AxisDependency. In the + * Returns the y-axis object to the corresponding AxisDependency. In the * horizontal bar-chart, LEFT == top, RIGHT == BOTTOM * * @param axis @@ -1376,8 +1376,8 @@ public boolean isInverted(AxisDependency axis) { } /** - * If set to true, both xPx and yPx axis can be scaled simultaneously with 2 fingers, if false, - * xPx and yPx axis can be scaled separately. default: false + * If set to true, both x and y axis can be scaled simultaneously with 2 fingers, if false, + * x and y axis can be scaled separately. default: false * * @param enabled */ @@ -1396,7 +1396,7 @@ public boolean isPinchZoomEnabled() { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the xPx-axis. + * bounds on the x-axis. * * @param offset */ @@ -1406,7 +1406,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the yPx-axis. + * bounds on the y-axis. * * @param offset */ @@ -1415,7 +1415,7 @@ public void setDragOffsetY(float offset) { } /** - * Returns true if both drag offsets (xPx and yPx) are zero or smaller. + * Returns true if both drag offsets (x and y) are zero or smaller. * * @return */ @@ -1486,11 +1486,11 @@ public boolean isAnyAxisInverted() { } /** - * Flag that indicates if auto scaling on the yPx axis is enabled. This is + * Flag that indicates if auto scaling on the y axis is enabled. This is * especially interesting for charts displaying financial data. * - * @param enabled the yPx axis automatically adjusts to the min and max yPx - * values of the current xPx axis range whenever the viewport + * @param enabled the y axis automatically adjusts to the min and max y + * values of the current x axis range whenever the viewport * changes */ public void setAutoScaleMinMaxEnabled(boolean enabled) { @@ -1498,7 +1498,7 @@ public void setAutoScaleMinMaxEnabled(boolean enabled) { } /** - * @return true if auto scaling on the yPx axis is enabled. + * @return true if auto scaling on the y axis is enabled. * @default false */ public boolean isAutoScaleMinMaxEnabled() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 42e40d0f65..13165ae147 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -118,7 +118,7 @@ public abstract class Chart { private RectF mCircleBox = new RectF(); /** - * flag indicating if the xPx-labels should be drawn or not + * flag indicating if the x-labels should be drawn or not */ private boolean mDrawXLabels = true; @@ -302,7 +302,7 @@ public int getIndexForAngle(float angle) { } /** - * Returns the index of the DataSet this xPx-index belongs to. + * Returns the index of the DataSet this x-index belongs to. * * @param xIndex * @return @@ -559,7 +559,7 @@ public void setTransparentCircleAlpha(int alpha) { } /** - * set this to true to draw the xPx-yValue text into the pie slices + * set this to true to draw the x-yValue text into the pie slices * * @param enabled */ @@ -568,7 +568,7 @@ public void setDrawSliceText(boolean enabled) { } /** - * returns true if drawing xPx-values is enabled, false if not + * returns true if drawing x-values is enabled, false if not * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index c3d14c042a..2c54ec3abc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -441,7 +441,7 @@ public float getYChartMin() { } /** - * Returns an array of SelectionDetail objects for the given xPx-index. The SelectionDetail + * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail * objects give information about the yValue at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. @@ -456,7 +456,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { IDataSet dataSet = mData.getDataSetByIndex(i); - // extract all yPx-values from all DataSets at the given xPx-index + // extract all y-values from all DataSets at the given x-index final float yVal = dataSet.getYValueForXValue(xIndex); if (Float.isNaN(yVal)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 9e5118d63b..854f5bef63 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -62,7 +62,7 @@ public class RadarChart extends PieRadarChartBase { private int mSkipWebLineCount = 0; /** - * the object reprsenting the yPx-axis labels + * the object reprsenting the y-axis labels */ private YAxis mYAxis; @@ -99,7 +99,7 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - // calculate / set xPx-axis range + // calculate / set x-axis range // mXAxis.mAxisMaximum = mData.getXVals().size() - 1; // mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); @@ -214,7 +214,7 @@ public int getIndexForAngle(float angle) { } /** - * Returns the object that represents all yPx-labels of the RadarChart. + * Returns the object that represents all y-labels of the RadarChart. * * @return */ @@ -347,21 +347,21 @@ public float getRadius() { } /** - * Returns the maximum yValue this chart can display on it's yPx-axis. + * Returns the maximum yValue this chart can display on it's y-axis. */ public float getYChartMax() { return mYAxis.mAxisMaximum; } /** - * Returns the minimum yValue this chart can display on it's yPx-axis. + * Returns the minimum yValue this chart can display on it's y-axis. */ public float getYChartMin() { return mYAxis.mAxisMinimum; } /** - * Returns the range of yPx-values this chart can display. + * Returns the range of y-values this chart can display. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 2c717ea6de..7f852342e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -71,7 +71,7 @@ public abstract class AxisBase extends ComponentBase { protected boolean mGranularityEnabled = false; /** - * if true, the set number of yPx-labels will be forced + * if true, the set number of y-labels will be forced */ protected boolean mForceLabels = false; @@ -282,10 +282,10 @@ public boolean isDrawLabelsEnabled() { } /** - * Sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware + * Sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware * that this number is not fixed. * - * @param count the number of yPx-axis labels that sould be displayed + * @param count the number of y-axis labels that sould be displayed */ public void setLabelCount(int count) { @@ -299,11 +299,11 @@ public void setLabelCount(int count) { } /** - * sets the number of label entries for the yPx-axis max = 25, min = 2, default: 6, be aware + * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware * that this number is not * fixed (if force == false) and can only be approximated. * - * @param count the number of yPx-axis labels that sould be displayed + * @param count the number of y-axis labels that sould be displayed * @param force if enabled, the set label count will be forced, meaning that the exact * specified count of labels will * be drawn and evenly distributed alongside the axis - this might cause labels @@ -316,7 +316,7 @@ public void setLabelCount(int count, boolean force) { } /** - * Returns true if focing the yPx-label count is enabled. Default: false + * Returns true if focing the y-label count is enabled. Default: false * * @return */ @@ -325,7 +325,7 @@ public boolean isForceLabelsEnabled() { } /** - * Returns the number of label entries the yPx-axis should have + * Returns the number of label entries the y-axis should have * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java index 77bbe97ca7..713f89dd79 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java @@ -19,7 +19,7 @@ public abstract class ComponentBase { protected boolean mEnabled = true; /** - * the offset in pixels this axis labels have on the xPx-axis + * the offset in pixels this axis labels have on the x-axis */ protected float mXOffset = 5f; @@ -48,7 +48,7 @@ public ComponentBase() { } /** - * Returns the used offset on the xPx-axis for drawing the axis or legend + * Returns the used offset on the x-axis for drawing the axis or legend * labels. This offset is applied before and after the label. * * @return @@ -58,7 +58,7 @@ public float getXOffset() { } /** - * Sets the used xPx-axis offset for the labels on this axis. + * Sets the used x-axis offset for the labels on this axis. * * @param xOffset */ @@ -67,7 +67,7 @@ public void setXOffset(float xOffset) { } /** - * Returns the used offset on the xPx-axis for drawing the axis labels. This + * Returns the used offset on the x-axis for drawing the axis labels. This * offset is applied before and after the label. * * @return @@ -77,7 +77,7 @@ public float getYOffset() { } /** - * Sets the used yPx-axis offset for the labels on this axis. For the legend, + * Sets the used y-axis offset for the labels on this axis. For the legend, * higher offset means the legend as a whole will be placed further away * from the top. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java index 7b826fae30..791e56e2e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java @@ -11,13 +11,13 @@ /** * The limit line is an additional feature for all Line-, Bar- and * ScatterCharts. It allows the displaying of an additional line in the chart - * that marks a certain maximum / limit on the specified axis (xPx- or yPx-axis). + * that marks a certain maximum / limit on the specified axis (x- or y-axis). * * @author Philipp Jahoda */ public class LimitLine extends ComponentBase { - /** limit / maximum (the yPx-yValue or xIndex) */ + /** limit / maximum (the y-yValue or xIndex) */ private float mLimit = 0f; /** the width of the limit line */ @@ -46,7 +46,7 @@ public enum LimitLabelPosition { /** * Constructor with limit. * - * @param limit - the position (the yValue) on the yPx-axis (yPx-yValue) or xPx-axis + * @param limit - the position (the yValue) on the y-axis (y-yValue) or x-axis * (xIndex) where this line should appear */ public LimitLine(float limit) { @@ -56,7 +56,7 @@ public LimitLine(float limit) { /** * Constructor with limit and label. * - * @param limit - the position (the yValue) on the yPx-axis (yPx-yValue) or xPx-axis + * @param limit - the position (the yValue) on the y-axis (y-yValue) or x-axis * (xIndex) where this line should appear * @param label - provide "" if no label is required */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java index ca99c59b09..be0786133f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java @@ -74,19 +74,19 @@ public void draw(Canvas canvas, float posx, float posy) { public abstract void refreshContent(Entry e, Highlight highlight); /** - * Use this to return the desired offset you wish the MarkerView to have on the xPx-axis. By returning -(getWidth() / + * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / * 2) you will center the MarkerView horizontally. * - * @param xpos the position on the xPx-axis in pixels where the marker is drawn + * @param xpos the position on the x-axis in pixels where the marker is drawn * @return */ public abstract int getXOffset(float xpos); /** - * Use this to return the desired position offset you wish the MarkerView to have on the yPx-axis. By returning + * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning * -getHeight() you will cause the MarkerView to be above the selected yValue. * - * @param ypos the position on the yPx-axis in pixels where the marker is drawn + * @param ypos the position on the y-axis in pixels where the marker is drawn * @return */ public abstract int getYOffset(float ypos); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java index 5a21292866..77d4aaf98f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/XAxis.java @@ -4,7 +4,7 @@ import com.github.mikephil.charting.utils.Utils; /** - * Class representing the xPx-axis labels settings. Only use the setter methods to + * Class representing the x-axis labels settings. Only use the setter methods to * modify it. Do not access public variables directly. Be aware that not all * features the XLabels class provides are suitable for the RadarChart. * @@ -13,25 +13,25 @@ public class XAxis extends AxisBase { /** - * width of the xPx-axis labels in pixels - this is automatically + * width of the x-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelWidth = 1; /** - * height of the xPx-axis labels in pixels - this is automatically + * height of the x-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelHeight = 1; /** - * width of the (rotated) xPx-axis labels in pixels - this is automatically + * width of the (rotated) x-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedWidth = 1; /** - * height of the (rotated) xPx-axis labels in pixels - this is automatically + * height of the (rotated) x-axis labels in pixels - this is automatically * calculated by the computeSize() methods in the renderers */ public int mLabelRotatedHeight = 1; @@ -48,12 +48,12 @@ public class XAxis extends AxisBase { private boolean mAvoidFirstLastClipping = false; /** - * the position of the xPx-labels relative to the chart + * the position of the x-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; /** - * enum for the position of the xPx-labels relative to the chart + * enum for the position of the x-labels relative to the chart */ public enum XAxisPosition { TOP, BOTTOM, BOTH_SIDED, TOP_INSIDE, BOTTOM_INSIDE @@ -66,14 +66,14 @@ public XAxis() { } /** - * returns the position of the xPx-labels + * returns the position of the x-labels */ public XAxisPosition getPosition() { return mPosition; } /** - * sets the position of the xPx-labels + * sets the position of the x-labels * * @param pos */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 6b0c6adedf..317d7a3a97 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.utils.Utils; /** - * Class representing the yPx-axis labels settings and its entries. Only use the setter methods to + * Class representing the y-axis labels settings and its entries. Only use the setter methods to * modify it. Do not * access public variables directly. Be aware that not all features the YLabels class provides * are suitable for the @@ -19,7 +19,7 @@ public class YAxis extends AxisBase { /** - * indicates if the top yPx-label entry is drawn or not + * indicates if the top y-label entry is drawn or not */ private boolean mDrawTopYLabelEntry = true; @@ -54,12 +54,12 @@ public class YAxis extends AxisBase { protected float mSpacePercentBottom = 10f; /** - * the position of the yPx-labels relative to the chart + * the position of the y-labels relative to the chart */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; /** - * enum for the position of the yPx-labels relative to the chart + * enum for the position of the y-labels relative to the chart */ public enum YAxisLabelPosition { OUTSIDE_CHART, INSIDE_CHART @@ -144,14 +144,14 @@ public void setMaxWidth(float maxWidth) { } /** - * returns the position of the yPx-labels + * returns the position of the y-labels */ public YAxisLabelPosition getLabelPosition() { return mPosition; } /** - * sets the position of the yPx-labels + * sets the position of the y-labels * * @param pos */ @@ -160,7 +160,7 @@ public void setPosition(YAxisLabelPosition pos) { } /** - * returns true if drawing the top yPx-axis label entry is enabled + * returns true if drawing the top y-axis label entry is enabled * * @return */ @@ -169,9 +169,9 @@ public boolean isDrawTopYLabelEntryEnabled() { } /** - * set this to true to enable drawing the top yPx-label entry. Disabling this can be helpful - * when the top yPx-label and - * left xPx-label interfere with each other. default: true + * set this to true to enable drawing the top y-label entry. Disabling this can be helpful + * when the top y-label and + * left x-label interfere with each other. default: true * * @param enabled */ @@ -180,7 +180,7 @@ public void setDrawTopYLabelEntry(boolean enabled) { } /** - * If this is set to true, the yPx-axis is inverted which means that low values are on top of + * If this is set to true, the y-axis is inverted which means that low values are on top of * the chart, high values * on bottom. * @@ -191,7 +191,7 @@ public void setInverted(boolean enabled) { } /** - * If this returns true, the yPx-axis is inverted. + * If this returns true, the y-axis is inverted. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 1cdddda683..866f78f678 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -57,7 +57,7 @@ public abstract class BaseDataSet implements IDataSet { protected Typeface mValueTypeface; /** - * if true, yPx-values are drawn on the chart + * if true, y-values are drawn on the chart */ protected boolean mDrawValues = true; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java index 48e773edfe..09896c84a4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java @@ -25,7 +25,7 @@ public BaseEntry(float y, Object data) { } /** - * Returns the yPx yValue of this Entry. + * Returns the y yValue of this Entry. * * @return */ @@ -34,7 +34,7 @@ public float getY() { } /** - * Sets the yPx-yValue for the Entry. + * Sets the y-yValue for the Entry. * * @param y */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java index 0778e57673..d0371cc7fc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java @@ -19,8 +19,8 @@ public class BubbleEntry extends Entry { /** * Constructor. * - * @param x The yValue on the xPx-axis. - * @param y The yValue on the yPx-axis. + * @param x The yValue on the x-axis. + * @param y The yValue on the y-axis. * @param size The size of the bubble. */ public BubbleEntry(float x, float y, float size) { @@ -31,8 +31,8 @@ public BubbleEntry(float x, float y, float size) { /** * Constructor. * - * @param x The yValue on the xPx-axis. - * @param y The yValue on the yPx-axis. + * @param x The yValue on the x-axis. + * @param y The yValue on the y-axis. * @param size The size of the bubble. * @param data Spot for additional data this Entry represents. */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java index b499540a64..41e69ffba7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java @@ -26,7 +26,7 @@ public class CandleEntry extends Entry { /** * Constructor. * - * @param x The yValue on the xPx-axis. + * @param x The yValue on the x-axis. * @param shadowH The (shadow) high yValue. * @param shadowL The (shadow) low yValue. * @param open The open yValue. @@ -44,7 +44,7 @@ public CandleEntry(float x, float shadowH, float shadowL, float open, float clos /** * Constructor. * - * @param x The yValue on the xPx-axis. + * @param x The yValue on the x-axis. * @param shadowH The (shadow) high yValue. * @param shadowL The (shadow) low yValue. * @param open diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index d29456774b..0cd23e873c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -16,29 +16,29 @@ /** * Class that holds all relevant data that represents the chart. That involves - * at least one (or more) DataSets, and an array of xPx-values. + * at least one (or more) DataSets, and an array of x-values. * * @author Philipp Jahoda */ public abstract class ChartData> { /** - * maximum yPx-yValue in the yValue array across all axes + * maximum y-yValue in the yValue array across all axes */ protected float mYMax = 0.0f; /** - * the minimum yPx-yValue in the yValue array across all axes + * the minimum y-yValue in the yValue array across all axes */ protected float mYMin = 0.0f; /** - * maximum xPx-yValue in the yValue array + * maximum x-yValue in the yValue array */ protected float mXMax = 0f; /** - * minimum xPx-yValue in the yValue array + * minimum x-yValue in the yValue array */ protected float mXMin = 0f; @@ -51,12 +51,12 @@ public abstract class ChartData> { protected float mRightAxisMin = 0.0f; /** - * total number of yPx-values across all DataSet objects + * total number of y-values across all DataSet objects */ private int mYValCount = 0; /** - * contains the maximum length (in characters) an entry in the xPx-vals array + * contains the maximum length (in characters) an entry in the x-vals array * has */ private float mXValMaximumLength = 0; @@ -105,7 +105,7 @@ public void notifyDataChanged() { } /** - * calc minimum and maximum values (both xPx and yPx) over all DataSets + * calc minimum and maximum values (both x and y) over all DataSets */ public void calcMinMax() { @@ -192,7 +192,7 @@ public void calcMinMax() { } /** - * Calculates the total number of yPx-values across all DataSets the ChartData + * Calculates the total number of y-values across all DataSets the ChartData * represents. * * @return @@ -227,7 +227,7 @@ public int getDataSetCount() { } /** - * Returns the smallest yPx-yValue the data object contains. + * Returns the smallest y-yValue the data object contains. * * @return */ @@ -236,7 +236,7 @@ public float getYMin() { } /** - * Returns the minimum yPx-yValue for the specified axis. + * Returns the minimum y-yValue for the specified axis. * * @param axis * @return @@ -249,7 +249,7 @@ public float getYMin(AxisDependency axis) { } /** - * Returns the greatest yPx-yValue the data object contains. + * Returns the greatest y-yValue the data object contains. * * @return */ @@ -258,7 +258,7 @@ public float getYMax() { } /** - * Returns the maximum yPx-yValue for the specified axis. + * Returns the maximum y-yValue for the specified axis. * * @param axis * @return @@ -271,7 +271,7 @@ public float getYMax(AxisDependency axis) { } /** - * Returns the minimum xPx-yValue this data object contains. + * Returns the minimum x-yValue this data object contains. * * @return */ @@ -280,7 +280,7 @@ public float getXMin() { } /** - * Returns the maximum xPx-yValue this data object contains. + * Returns the maximum x-yValue this data object contains. * * @return */ @@ -290,7 +290,7 @@ public float getXMax() { /** * returns the maximum length (in characters) across all values in the - * xPx-vals array + * x-vals array * * @return */ @@ -299,7 +299,7 @@ public float getXValMaximumLength() { } /** - * Returns the total number of yPx-values across all DataSet objects the this + * Returns the total number of y-values across all DataSet objects the this * object represents. * * @return @@ -733,7 +733,7 @@ public T getFirstRight() { } // /** -// * Generates an xPx-values array filled with numbers in range specified by the +// * Generates an x-values array filled with numbers in range specified by the // * parameters. Can be used for convenience. // * // * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 8c2eeb2346..2cc8422843 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -20,22 +20,22 @@ public abstract class DataSet extends BaseDataSet { protected List mValues = null; /** - * maximum yPx-yValue in the yValue array + * maximum y-yValue in the yValue array */ protected float mYMax = 0.0f; /** - * minimum yPx-yValue in the yValue array + * minimum y-yValue in the yValue array */ protected float mYMin = 0.0f; /** - * maximum xPx-yValue in the yValue array + * maximum x-yValue in the yValue array */ protected float mXMax = 0.0f; /** - * minimum xPx-yValue in the yValue array + * minimum x-yValue in the yValue array */ protected float mXMin = 0.0f; @@ -108,7 +108,7 @@ public int getEntryCount() { } /** - * Returns the array of yPx-values that this DataSet represents. + * Returns the array of y-values that this DataSet represents. * * @return */ @@ -117,7 +117,7 @@ public List getYVals() { } /** - * Sets the array of yPx-values that this DataSet represents, and calls notifyDataSetChanged() + * Sets the array of y-values that this DataSet represents, and calls notifyDataSetChanged() * * @return */ @@ -396,7 +396,7 @@ public List getEntriesForXPos(float xVal) { /** * Determines how to round DataSet index values for * {@link DataSet#getEntryIndex(float, Rounding)} DataSet.getEntryIndex()} - * when an exact xPx-index is not found. + * when an exact x-index is not found. */ public enum Rounding { UP, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 7c23e500e2..a210093fad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -23,8 +23,8 @@ public Entry() { /** * A Entry represents one single entry in the chart. * - * @param x the xPx yValue - * @param y the yPx yValue (the actual yValue of the entry) + * @param x the x yValue + * @param y the y yValue (the actual yValue of the entry) */ public Entry(float x, float y) { super(y); @@ -34,8 +34,8 @@ public Entry(float x, float y) { /** * A Entry represents one single entry in the chart. * - * @param x the xPx yValue - * @param y the yPx yValue (the actual yValue of the entry) + * @param x the x yValue + * @param y the y yValue (the actual yValue of the entry) * @param data Spot for additional data this Entry represents. */ public Entry(float x, float y, Object data) { @@ -44,7 +44,7 @@ public Entry(float x, float y, Object data) { } /** - * Returns the xPx-yValue of this Entry object. + * Returns the x-yValue of this Entry object. * * @return */ @@ -53,7 +53,7 @@ public float getX() { } /** - * Sets the xPx-yValue of this Entry object. + * Sets the x-yValue of this Entry object. * * @param x */ @@ -97,7 +97,7 @@ public boolean equalTo(Entry e) { } /** - * returns a string representation of the entry containing xPx-index and yValue + * returns a string representation of the entry containing x-index and yValue */ @Override public String toString() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index 62b5284c14..801114943c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -8,7 +8,7 @@ /** * A PieData object can only represent one DataSet. Unlike all other charts, the - * legend labels of the PieChart are created from the xPx-values array, and not + * legend labels of the PieChart are created from the x-values array, and not * from the DataSet labels. Each PieData object can only represent one * PieDataSet (multiple PieDataSets inside a single PieChart are not possible). * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java index 4fac3f615d..f562f22f06 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java @@ -81,7 +81,7 @@ public void setType(ApproximatorType type) { } /** - * Sets the ratios for xPx- and yPx-axis, as well as the ratio of the scale + * Sets the ratios for x- and y-axis, as well as the ratio of the scale * levels * * @param deltaRatio @@ -163,7 +163,7 @@ private List reduceWithDouglasPeuker(List entries, double epsilon) * epsilon (tolerance) * * @param entries - * @param epsilon as yPx-yValue + * @param epsilon as y-yValue * @param start * @param end */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index ee17c51587..b0fad9d14f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -28,22 +28,22 @@ public abstract class RealmBaseDataSet e protected List mValues; /** - * maximum yPx-yValue in the yPx-yValue array + * maximum y-yValue in the y-yValue array */ protected float mYMax = 0.0f; /** - * the minimum yPx-yValue in the yPx-yValue array + * the minimum y-yValue in the y-yValue array */ protected float mYMin = 0.0f; /** - * maximum xPx-yValue in the yValue array + * maximum x-yValue in the yValue array */ protected float mXMax = 0.0f; /** - * minimum xPx-yValue in the yValue array + * minimum x-yValue in the yValue array */ protected float mXMin = 0.0f; @@ -384,7 +384,7 @@ public RealmResults getResults() { } /** - * Returns the fieldname that represents the "yPx-values" in the realm-data. + * Returns the fieldname that represents the "y-values" in the realm-data. * * @return */ @@ -393,7 +393,7 @@ public String getYValuesField() { } /** - * Sets the field name that is used for getting the yPx-values out of the RealmResultSet. + * Sets the field name that is used for getting the y-values out of the RealmResultSet. * * @param yValuesField */ @@ -402,7 +402,7 @@ public void setYValuesField(String yValuesField) { } /** - * Returns the fieldname that represents the "xPx-values" in the realm-data. + * Returns the fieldname that represents the "x-values" in the realm-data. * * @return */ @@ -411,7 +411,7 @@ public String getXValuesField() { } /** - * Sets the field name that is used for getting the xPx-values out of the RealmResultSet. + * Sets the field name that is used for getting the x-values out of the RealmResultSet. * * @param xValuesField */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 5a2e0c5f93..67700a428e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -25,7 +25,7 @@ public class RealmBubbleDataSet extends RealmBarLineScatt * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param yValuesField the name of the field in your data object that represents the y-yValue * @param sizeField the name of the field in your data object that represents the bubble size */ public RealmBubbleDataSet(RealmResults result, String yValuesField, String sizeField) { @@ -40,8 +40,8 @@ public RealmBubbleDataSet(RealmResults result, String yValuesField, String si * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue - * @param xIndexField the name of the field in your data object that represents the xPx-index + * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param xIndexField the name of the field in your data object that represents the x-index * @param sizeField the name of the field in your data object that represents the bubble size */ public RealmBubbleDataSet(RealmResults result, String yValuesField, String xIndexField, String sizeField) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index b2ea4a7de9..0713cb55bb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -70,7 +70,7 @@ public class RealmLineDataSet extends RealmLineRadarDataS * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param yValuesField the name of the field in your data object that represents the y-yValue */ public RealmLineDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 01d923eef5..d7640fee4a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -42,7 +42,7 @@ public class RealmPieDataSet extends RealmBaseDataSet result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 0d2ed766aa..7421e3a8ad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -32,7 +32,7 @@ public class RealmRadarDataSet extends RealmLineRadarData * Constructor for creating a RadarDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param yValuesField the name of the field in your data object that represents the y-yValue */ public RealmRadarDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index d8126e7e06..cd9afa98fc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -44,7 +44,7 @@ public class RealmScatterDataSet extends RealmLineScatter * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the yPx-yValue + * @param yValuesField the name of the field in your data object that represents the y-yValue */ public RealmScatterDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java index 22ba60528e..66895d77e7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java @@ -12,7 +12,7 @@ public interface FillFormatter { /** - * Returns the vertical (yPx-axis) position where the filled-line of the + * Returns the vertical (y-axis) position where the filled-line of the * LineDataSet should end. * * @param dataSet the ILineDataSet that is currently drawn diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 265c8a66c1..65a6dab0a9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -27,7 +27,7 @@ public ChartHighlighter(T chart) { } /** - * Returns a Highlight object corresponding to the given xPx- and yPx- touch positions in pixels. + * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. * * @param x * @param y @@ -55,13 +55,13 @@ public Highlight getHighlight(float x, float y) { */ protected PointD getValsForTouch(float x, float y) { - // take any transformer to determine the xPx-axis yValue + // take any transformer to determine the x-axis yValue PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, y); return pos; } /** - * Returns the corresponding SelectionDetail for a given xVal and yPx-touch position in pixels. + * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. * * @param xVal * @param y @@ -155,7 +155,7 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, /** * Returns the SelectionDetail of the DataSet that contains the closest yValue on the - * yPx-axis. + * y-axis. * * @param valsAtIndex all the values at a specific index * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 11244c80ba..63664c9f45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -8,10 +8,10 @@ */ public class Highlight { - /** the xPx-yValue of the highlighted yValue */ + /** the x-yValue of the highlighted yValue */ private float mX = Float.NaN; - /** the yPx-yValue of the highlighted yValue */ + /** the y-yValue of the highlighted yValue */ private float mY = Float.NaN; /** the index of the data object - in case it refers to more than one */ @@ -29,8 +29,8 @@ public class Highlight { /** * constructor * - * @param x the xPx-yValue of the highlighted yValue - * @param y the yPx-yValue of the highlighted yValue + * @param x the x-yValue of the highlighted yValue + * @param y the y-yValue of the highlighted yValue * @param dataIndex the index of the Data the highlighted yValue belongs to * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to */ @@ -43,8 +43,8 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { /** * Constructor, only used for stacked-barchart. * - * @param x the xPx-yValue of the highlighted yValue on the xPx-axis - * @param y the yPx-yValue of the highlighted yValue + * @param x the x-yValue of the highlighted yValue on the x-axis + * @param y the y-yValue of the highlighted yValue * @param dataIndex the index of the Data the highlighted yValue belongs to * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to * @param stackIndex references which yValue of a stacked-bar entry has been @@ -58,8 +58,8 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted yValue on the xPx-axis - * @param y the yPx-yValue of the highlighted yValue + * @param x the index of the highlighted yValue on the x-axis + * @param y the y-yValue of the highlighted yValue * @param dataIndex the index of the Data the highlighted yValue belongs to * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to * @param stackIndex references which yValue of a stacked-bar entry has been @@ -82,7 +82,7 @@ public Highlight(float x, int dataSetIndex) { } /** - * returns the xPx-yValue of the highlighted yValue + * returns the x-yValue of the highlighted yValue * * @return */ @@ -91,7 +91,7 @@ public float getX() { } /** - * returns the yPx-yValue of the highlighted yValue + * returns the y-yValue of the highlighted yValue * * @return */ @@ -157,7 +157,7 @@ public boolean equalTo(Highlight h) { @Override public String toString() { - return "Highlight, xPx: " + mX + "yPx: " + mY + ", dataSetIndex: " + mDataSetIndex + return "Highlight, x: " + mX + "y: " + mY + ", dataSetIndex: " + mDataSetIndex + ", stackIndex (only stacked barentry): " + mStackIndex; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index dbfd39e1c2..271ab4e216 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -17,35 +17,35 @@ public interface IDataSet { /** ###### ###### DATA RELATED METHODS ###### ###### */ /** - * returns the minimum yPx-yValue this DataSet holds + * returns the minimum y-yValue this DataSet holds * * @return */ float getYMin(); /** - * returns the maximum yPx-yValue this DataSet holds + * returns the maximum y-yValue this DataSet holds * * @return */ float getYMax(); /** - * returns the minimum xPx-yValue this DataSet holds + * returns the minimum x-yValue this DataSet holds * * @return */ float getXMin(); /** - * returns the maximum xPx-yValue this DataSet holds + * returns the maximum x-yValue this DataSet holds * * @return */ float getXMax(); /** - * Returns the number of yPx-values this DataSet represents -> the size of the yPx-values array + * Returns the number of y-values this DataSet represents -> the size of the y-values array * -> yvals.size() * * @return @@ -53,7 +53,7 @@ public interface IDataSet { int getEntryCount(); /** - * Calculates the minimum and maximum xPx and yPx values (mXMin, mXMax, mYMin, mYMax). + * Calculates the minimum and maximum x and y values (mXMin, mXMax, mYMin, mYMax). */ void calcMinMax(); @@ -65,7 +65,7 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xPos - * @param rounding determine to round up/down/closest if there is no Entry matching the provided xPx-index + * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ T getEntryForXPos(float xPos, DataSet.Rounding rounding); @@ -109,7 +109,7 @@ public interface IDataSet { * not over-use in performance critical situations. * * @param xPos - * @param rounding determine to round up/down/closest if there is no Entry matching the provided xPx-index + * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ int getEntryIndex(float xPos, DataSet.Rounding rounding); @@ -135,7 +135,7 @@ public interface IDataSet { float getYValueForXValue(float xVal); /** - * Returns all of the yPx values of the Entry objects at the given xPos. Returns + * Returns all of the y values of the Entry objects at the given xPos. Returns * Float.NaN if no yValue is at the given xPos. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. @@ -178,7 +178,7 @@ public interface IDataSet { /** * Adds an Entry to the DataSet dynamically. - * Entries are added to their appropriate index respective to it's xPx-index. + * Entries are added to their appropriate index respective to it's x-index. * This will also recalculate the current minimum and maximum * values of the DataSet and the yValue-sum. * @@ -250,7 +250,7 @@ public interface IDataSet { YAxis.AxisDependency getAxisDependency(); /** - * Set the yPx-axis this DataSet should be plotted against (either LEFT or + * Set the y-axis this DataSet should be plotted against (either LEFT or * RIGHT). Default: LEFT * * @param dependency @@ -373,7 +373,7 @@ public interface IDataSet { float getValueTextSize(); /** - * set this to true to draw yPx-values on the chart NOTE (for bar and + * set this to true to draw y-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even * if this is enabled * @@ -382,7 +382,7 @@ public interface IDataSet { void setDrawValues(boolean enabled); /** - * Returns true if yPx-yValue drawing is enabled, false if not + * Returns true if y-yValue drawing is enabled, false if not * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 7f293090bd..02713af88a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -126,10 +126,10 @@ public boolean onTouch(View v, MotionEvent event) { saveTouchStart(event); - // get the distance between the pointers on the xPx-axis + // get the distance between the pointers on the x-axis mSavedXDist = getXDist(event); - // get the distance between the pointers on the yPx-axis + // get the distance between the pointers on the y-axis mSavedYDist = getYDist(event); // get the total distance between the pointers @@ -363,7 +363,7 @@ private void performZoom(MotionEvent event) { mLastGesture = ChartGesture.X_ZOOM; float xDist = getXDist(event); - float scaleX = xDist / mSavedXDist; // xPx-axis scale + float scaleX = xDist / mSavedXDist; // x-axis scale boolean isZoomingOut = (scaleX < 1); boolean canZoomMoreX = isZoomingOut ? @@ -384,7 +384,7 @@ private void performZoom(MotionEvent event) { mLastGesture = ChartGesture.Y_ZOOM; float yDist = getYDist(event); - float scaleY = yDist / mSavedYDist; // yPx-axis scale + float scaleY = yDist / mSavedYDist; // y-axis scale boolean isZoomingOut = (scaleY < 1); boolean canZoomMoreY = isZoomingOut ? @@ -450,7 +450,7 @@ private static float spacing(MotionEvent event) { } /** - * calculates the distance on the xPx-axis between two pointers (fingers on + * calculates the distance on the x-axis between two pointers (fingers on * the display) * * @param e @@ -462,7 +462,7 @@ private static float getXDist(MotionEvent e) { } /** - * calculates the distance on the yPx-axis between two pointers (fingers on + * calculates the distance on the y-axis between two pointers (fingers on * the display) * * @param e @@ -474,7 +474,7 @@ private static float getYDist(MotionEvent e) { } /** - * returns the correct translation depending on the provided xPx and yPx touch + * returns the correct translation depending on the provided x and y touch * points * * @param x @@ -532,7 +532,7 @@ public boolean onDoubleTap(MotionEvent e) { mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); if (mChart.isLogEnabled()) - Log.i("BarlineChartTouch", "Double-Tap, Zooming In, xPx: " + trans.x + ", yPx: " + Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java index 0449e79228..a17cdde941 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -60,8 +60,8 @@ public interface OnChartGestureListener { * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. * * @param me - * @param scaleX scalefactor on the xPx-axis - * @param scaleY scalefactor on the yPx-axis + * @param scaleX scalefactor on the x-axis + * @param scaleY scalefactor on the y-axis */ void onChartScale(MotionEvent me, float scaleX, float scaleY); @@ -69,8 +69,8 @@ public interface OnChartGestureListener { * Callbacks when the chart is moved / translated via drag gesture. * * @param me - * @param dX translation distance on the xPx-axis - * @param dY translation distance on the yPx-axis + * @param dX translation distance on the x-axis + * @param dY translation distance on the y-axis */ void onChartTranslate(MotionEvent me, float dX, float dY); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 59ec3d1101..d40e2fdb4e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -283,7 +283,7 @@ private float calculateVelocity() { /** * sets the starting angle of the rotation, this is only used by the touch - * listener, xPx and yPx is the touch position + * listener, x and y is the touch position * * @param x * @param y diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 0c641a5ffd..55d8a03ad4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -31,7 +31,7 @@ public abstract class AxisRenderer extends Renderer { protected Paint mGridPaint; /** - * paint for the xPx-label values + * paint for the x-label values */ protected Paint mAxisLabelPaint; @@ -117,7 +117,7 @@ public Transformer getTransformer() { */ public void computeAxis(float min, float max, boolean inverted) { - // calculate the starting and entry point of the yPx-labels (depending on + // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler != null && mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { @@ -157,7 +157,7 @@ protected void computeAxisValues(float min, float max) { return; } - // Find out how much spacing (in yPx yValue space) between axis values + // Find out how much spacing (in y yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 3fcaca0913..a1d9521a55 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -91,7 +91,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the xPx-axis + // calcualte the full width of 1 step on the x-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); @@ -245,7 +245,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the xPx-axis + // calcualte the full width of 1 step on the x-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs( mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index df1fb3da60..39630d8978 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -339,7 +339,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { dataSetIndex++) { float x = high.getX(); // get the - // xPx-position + // x-position ICandleDataSet set = mChart.getCandleData().getDataSetByIndex(dataSetIndex); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index 1f19c44492..122e90f80c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -25,8 +25,8 @@ public LineScatterCandleRadarRenderer(ChartAnimator animator, ViewPortHandler vi * Draws vertical & horizontal highlight-lines if enabled. * * @param c - * @param x xPx-position of the highlight line intersection - * @param y yPx-position of the highlight line intersection + * @param x x-position of the highlight line intersection + * @param y y-position of the highlight line intersection * @param set the currently drawn dataset */ protected void drawHighlightLines(Canvas c, float x, float y, ILineScatterCandleRadarDataSet set) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index c9354056c0..8afc282b01 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -36,7 +36,7 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t @Override public void computeAxis(float min, float max, boolean inverted) { - // calculate the starting and entry point of the yPx-labels (depending on + // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { @@ -156,7 +156,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the xPx-labels on the specified yPx-position + * draws the x-labels on the specified y-position * * @param pos */ @@ -169,7 +169,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { for (int i = 0; i < positions.length; i += 2) { - // only fill xPx values + // only fill x values if (centeringEnabled) { positions[i] = mXAxis.mCenteredEntries[i / 2]; } else { @@ -223,7 +223,7 @@ public void renderGridLines(Canvas c) { float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill xPx values + // only fill x values positions[i] = mXAxis.mEntries[i / 2]; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 3985343ed1..ba398fc6d7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -34,7 +34,7 @@ public XAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, XAxis xA @Override public void computeAxis(float min, float max, boolean inverted) { - // calculate the starting and entry point of the yPx-labels (depending on + // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { @@ -130,7 +130,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { for (int i = 0; i < positions.length; i += 2) { - // only fill xPx values + // only fill x values if (centeringEnabled) { positions[i + 1] = mXAxis.mCenteredEntries[i / 2]; } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index f5b1539af1..6c18d098c6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -55,7 +55,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t // return; // } // -// // Find out how much spacing (in yPx yValue space) between axis values +// // Find out how much spacing (in y yValue space) between axis values // double rawInterval = range / labelCount; // double interval = Utils.roundToNextSignificant(rawInterval); // @@ -142,7 +142,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t // } /** - * draws the yPx-axis labels to the screen + * draws the y-axis labels to the screen */ @Override public void renderAxisLabels(Canvas c) { @@ -207,7 +207,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the yPx-labels on the specified xPx-position + * draws the y-labels on the specified x-position * * @param fixedPosition * @param positions diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 7b5ff68b8a..2841839510 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -30,13 +30,13 @@ public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yA /** * Computes the axis values. * - * @param yMin - the minimum yPx-yValue in the data object for this axis - * @param yMax - the maximum yPx-yValue in the data object for this axis + * @param yMin - the minimum y-yValue in the data object for this axis + * @param yMax - the maximum y-yValue in the data object for this axis */ @Override public void computeAxis(float yMin, float yMax, boolean inverted) { - // calculate the starting and entry point of the yPx-labels (depending on + // calculate the starting and entry point of the y-labels (depending on // zoom / contentrect bounds) if (mViewPortHandler.contentHeight() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { @@ -58,7 +58,7 @@ public void computeAxis(float yMin, float yMax, boolean inverted) { } /** - * draws the yPx-axis labels to the screen + * draws the y-axis labels to the screen */ @Override public void renderAxisLabels(Canvas c) { @@ -122,7 +122,7 @@ public void renderAxisLine(Canvas c) { } /** - * draws the yPx-labels on the specified xPx-position + * draws the y-labels on the specified x-position * * @param fixedPosition * @param positions diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 670c8a4eca..db8dec3e73 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -37,7 +37,7 @@ protected void computeAxisValues(float min, float max) { return; } - // Find out how much spacing (in yPx yValue space) between axis values + // Find out how much spacing (in y yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index 6cb5c837e7..fa7ff4489a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -32,7 +32,7 @@ public boolean equals(final Object obj) { @Override public String toString() { - return width + "xPx" + height; + return width + "x" + height; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java index e5d7abce23..7335d771ab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java @@ -20,6 +20,6 @@ public PointD(double x, double y) { * returns a string representation of the object */ public String toString() { - return "PointD, xPx: " + x + ", yPx: " + y; + return "PointD, x: " + x + ", y: " + y; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 189de13cd1..337049f058 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -96,8 +96,8 @@ public void prepareMatrixOffset(boolean inverted) { } /** - * Transforms an List of Entry into a float array containing the xPx and - * yPx values transformed with all matrices for the SCATTERCHART. + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the SCATTERCHART. * * @param data * @return @@ -123,8 +123,8 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, } /** - * Transforms an List of Entry into a float array containing the xPx and - * yPx values transformed with all matrices for the BUBBLECHART. + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the BUBBLECHART. * * @param data * @return @@ -152,8 +152,8 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, } /** - * Transforms an List of Entry into a float array containing the xPx and - * yPx values transformed with all matrices for the LINECHART. + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the LINECHART. * * @param data * @return @@ -181,8 +181,8 @@ public float[] generateTransformedValuesLine(ILineDataSet data, } /** - * Transforms an List of Entry into a float array containing the xPx and - * yPx values transformed with all matrices for the CANDLESTICKCHART. + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the CANDLESTICKCHART. * * @param data * @return @@ -210,8 +210,8 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, } /** - * Transforms an List of Entry into a float array containing the xPx and - * yPx values transformed with all matrices for the BARCHART. + * Transforms an List of Entry into a float array containing the x and + * y values transformed with all matrices for the BARCHART. * * @param data * @param dataSet the dataset index @@ -230,7 +230,7 @@ public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, Entry e = data.getEntryForIndex(j / 2); float i = e.getX(); - // calculate the xPx-position, depending on datasetcount + // calculate the x-position, depending on datasetcount float x = i + i * (setCount - 1) + dataSet + space * i + space / 2f; float y = e.getY(); @@ -365,7 +365,7 @@ public void rectValuesToPixel(List rects) { } /** - * Transforms the given array of touch positions (pixels) (xPx, yPx, xPx, yPx, ...) + * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) * into values on the chart. * * @param pixels @@ -391,7 +391,7 @@ public void pixelsToValue(float[] pixels) { float[] ptsBuffer = new float[2]; /** - * Returns the xPx and yPx values in the chart at the given touch point + * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). @@ -414,7 +414,7 @@ public PointD getValuesByTouchPoint(float x, float y) { } /** - * Returns the xPx and yPx coordinates (pixels) for a given xPx and yPx yValue in the chart. + * Returns the x and y coordinates (pixels) for a given x and y yValue in the chart. * * @param x * @param y diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 9ec8a5e808..e705bd6592 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -383,7 +383,7 @@ public static double nextUp(double d) { /** * Returns the index of the DataSet that contains the closest yValue on the - * yPx-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. + * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. * * @param valsAtIndex all the values at a specific index * @return @@ -401,7 +401,7 @@ public static int getClosestDataSetIndexByValue(List valsAtInde /** * Returns the SelectionDetail of the DataSet that contains the closest yValue on the - * yPx-axis. + * y-axis. * * @param valsAtIndex all the values at a specific index * @return @@ -721,7 +721,7 @@ public static int getSDKInt() { */ public static double granularity(float range, int labelCount) { - // Find out how much spacing (in yPx yValue space) between axis values + // Find out how much spacing (in y yValue space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 5c37f6eaea..078af45b5b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -28,52 +28,52 @@ public class ViewPortHandler { protected float mChartHeight = 0f; /** - * minimum scale yValue on the yPx-axis + * minimum scale yValue on the y-axis */ private float mMinScaleY = 1f; /** - * maximum scale yValue on the yPx-axis + * maximum scale yValue on the y-axis */ private float mMaxScaleY = Float.MAX_VALUE; /** - * minimum scale yValue on the xPx-axis + * minimum scale yValue on the x-axis */ private float mMinScaleX = 1f; /** - * maximum scale yValue on the xPx-axis + * maximum scale yValue on the x-axis */ private float mMaxScaleX = Float.MAX_VALUE; /** - * contains the current scale factor of the xPx-axis + * contains the current scale factor of the x-axis */ private float mScaleX = 1f; /** - * contains the current scale factor of the yPx-axis + * contains the current scale factor of the y-axis */ private float mScaleY = 1f; /** - * current translation (drag distance) on the xPx-axis + * current translation (drag distance) on the x-axis */ private float mTransX = 0f; /** - * current translation (drag distance) on the yPx-axis + * current translation (drag distance) on the y-axis */ private float mTransY = 0f; /** - * offset that allows the chart to be dragged over its bounds on the xPx-axis + * offset that allows the chart to be dragged over its bounds on the x-axis */ private float mTransOffsetX = 0f; /** - * offset that allows the chart to be dragged over its bounds on the xPx-axis + * offset that allows the chart to be dragged over its bounds on the x-axis */ private float mTransOffsetY = 0f; @@ -180,7 +180,7 @@ public float getChartWidth() { /** CODE BELOW THIS RELATED TO SCALING AND GESTURES */ /** - * Zooms in by 1.4f, xPx and yPx are the coordinates (in pixels) of the zoom + * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom * center. * * @param x @@ -197,7 +197,7 @@ public Matrix zoomIn(float x, float y) { } /** - * Zooms out by 0.7f, xPx and yPx are the coordinates (in pixels) of the zoom + * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom * center. */ public Matrix zoomOut(float x, float y) { @@ -228,7 +228,7 @@ public Matrix zoom(float scaleX, float scaleY) { } /** - * Post-scales by the specified scale factors. xPx and yPx is pivot. + * Post-scales by the specified scale factors. x and y is pivot. * * @param scaleX * @param scaleY @@ -264,7 +264,7 @@ public Matrix setZoom(float scaleX, float scaleY) { } /** - * Sets the scale factor to the specified values. xPx and yPx is pivot. + * Sets the scale factor to the specified values. x and y is pivot. * * @param scaleX * @param scaleY @@ -329,7 +329,7 @@ public Matrix translate(final float[] transformedPts) { } /** - * Centers the viewport around the specified position (xPx-index and yPx-yValue) + * Centers the viewport around the specified position (x-index and y-yValue) * in the chart. Centering the viewport outside the bounds of the chart is * not possible. Makes most sense in combination with the * setScaleMinima(...) method. @@ -391,10 +391,10 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float curTransY = matrixBuffer[Matrix.MTRANS_Y]; float curScaleY = matrixBuffer[Matrix.MSCALE_Y]; - // min scale-xPx is 1f + // min scale-x is 1f mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX); - // min scale-yPx is 1f + // min scale-y is 1f mScaleY = Math.min(Math.max(mMinScaleY, curScaleY), mMaxScaleY); float width = 0f; @@ -421,7 +421,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { } /** - * Sets the minimum scale factor for the xPx-axis + * Sets the minimum scale factor for the x-axis * * @param xScale */ @@ -436,7 +436,7 @@ public void setMinimumScaleX(float xScale) { } /** - * Sets the maximum scale factor for the xPx-axis + * Sets the maximum scale factor for the x-axis * * @param xScale */ @@ -451,7 +451,7 @@ public void setMaximumScaleX(float xScale) { } /** - * Sets the minimum and maximum scale factors for the xPx-axis + * Sets the minimum and maximum scale factors for the x-axis * * @param minScaleX * @param maxScaleX @@ -471,7 +471,7 @@ public void setMinMaxScaleX(float minScaleX, float maxScaleX) { } /** - * Sets the minimum scale factor for the yPx-axis + * Sets the minimum scale factor for the y-axis * * @param yScale */ @@ -486,7 +486,7 @@ public void setMinimumScaleY(float yScale) { } /** - * Sets the maximum scale factor for the yPx-axis + * Sets the maximum scale factor for the y-axis * * @param yScale */ @@ -556,14 +556,14 @@ public boolean isInBoundsBottom(float y) { } /** - * returns the current xPx-scale factor + * returns the current x-scale factor */ public float getScaleX() { return mScaleX; } /** - * returns the current yPx-scale factor + * returns the current y-scale factor */ public float getScaleY() { return mScaleY; @@ -586,7 +586,7 @@ public float getMaxScaleY() { } /** - * Returns the translation (drag / pan) distance on the xPx-axis + * Returns the translation (drag / pan) distance on the x-axis * * @return */ @@ -595,7 +595,7 @@ public float getTransX() { } /** - * Returns the translation (drag / pan) distance on the yPx-axis + * Returns the translation (drag / pan) distance on the y-axis * * @return */ @@ -617,7 +617,7 @@ public boolean isFullyZoomedOut() { } /** - * Returns true if the chart is fully zoomed out on it's yPx-axis (vertical). + * Returns true if the chart is fully zoomed out on it's y-axis (vertical). * * @return */ @@ -629,7 +629,7 @@ public boolean isFullyZoomedOutY() { } /** - * Returns true if the chart is fully zoomed out on it's xPx-axis + * Returns true if the chart is fully zoomed out on it's x-axis * (horizontal). * * @return @@ -643,7 +643,7 @@ public boolean isFullyZoomedOutX() { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the xPx-axis. + * bounds on the x-axis. * * @param offset */ @@ -653,7 +653,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's - * bounds on the yPx-axis. + * bounds on the y-axis. * * @param offset */ @@ -662,7 +662,7 @@ public void setDragOffsetY(float offset) { } /** - * Returns true if both drag offsets (xPx and yPx) are zero or smaller. + * Returns true if both drag offsets (x and y) are zero or smaller. * * @return */ @@ -671,7 +671,7 @@ public boolean hasNoDragOffset() { } /** - * Returns true if the chart is not yet fully zoomed out on the xPx-axis + * Returns true if the chart is not yet fully zoomed out on the x-axis * * @return */ @@ -680,7 +680,7 @@ public boolean canZoomOutMoreX() { } /** - * Returns true if the chart is not yet fully zoomed in on the xPx-axis + * Returns true if the chart is not yet fully zoomed in on the x-axis * * @return */ @@ -689,7 +689,7 @@ public boolean canZoomInMoreX() { } /** - * Returns true if the chart is not yet fully zoomed out on the yPx-axis + * Returns true if the chart is not yet fully zoomed out on the y-axis * * @return */ @@ -698,7 +698,7 @@ public boolean canZoomOutMoreY() { } /** - * Returns true if the chart is not yet fully zoomed in on the yPx-axis + * Returns true if the chart is not yet fully zoomed in on the y-axis * * @return */ From 565c8a465eccbe1ad03954c0250394fd7eef5c1d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 15:13:08 +0200 Subject: [PATCH 0960/1390] More fixes for RadarChart --- .../github/mikephil/charting/charts/RadarChart.java | 12 ++---------- .../mikephil/charting/renderer/AxisRenderer.java | 2 +- .../mikephil/charting/renderer/YAxisRenderer.java | 2 +- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 854f5bef63..b0da7219d0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -99,10 +99,6 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - // calculate / set x-axis range -// mXAxis.mAxisMaximum = mData.getXVals().size() - 1; -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - mYAxis.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); mXAxis.calculate(0, mData.getMaxEntryCountSet().getEntryCount()); } @@ -110,8 +106,8 @@ protected void calcMinMax() { @Override protected float[] getMarkerPosition(Entry e, Highlight highlight) { - float angle = getSliceAngle() * e.getX() + getRotationAngle(); - float val = e.getY() * getFactor(); + float angle = getSliceAngle() * e.getX() * mAnimator.getPhaseX() + getRotationAngle(); + float val = e.getY() * getFactor() * mAnimator.getPhaseY(); PointF c = getCenterOffsets(); PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), @@ -129,10 +125,6 @@ public void notifyDataSetChanged() { calcMinMax(); -// if (mYAxis.needsDefaultFormatter()) { -// mYAxis.setValueFormatter(mDefaultFormatter); -// } - mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted()); mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 55d8a03ad4..f98c9b2547 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -51,7 +51,7 @@ public AxisRenderer(ViewPortHandler viewPortHandler, Transformer trans, AxisBase this.mTrans = trans; this.mAxis = axis; - if(mTrans != null) { + if(mViewPortHandler != null) { mAxisLabelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 6c18d098c6..03ff4af9f8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -28,7 +28,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t this.mYAxis = yAxis; - if(mTrans != null) { + if(mViewPortHandler != null) { mAxisLabelPaint.setColor(Color.BLACK); mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); From 6fd2ffa2786f29fa7b26f544832569128bd88332 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 15:15:26 +0200 Subject: [PATCH 0961/1390] Comment refactoring --- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../HorizontalBarChartActivity.java | 2 +- .../mpchartexample/custom/MyMarkerView.java | 2 +- .../custom/RadarMarkerView.java | 2 +- .../custom/StackedBarsMarkerView.java | 4 +- .../notimportant/MainActivity.java | 2 +- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../mikephil/charting/charts/BarChart.java | 10 ++-- .../charting/charts/BarLineChartBase.java | 22 ++++---- .../mikephil/charting/charts/Chart.java | 28 +++++----- .../charting/charts/CombinedChart.java | 4 +- .../charting/charts/HorizontalBarChart.java | 6 +-- .../mikephil/charting/charts/PieChart.java | 10 ++-- .../charting/charts/PieRadarChartBase.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 8 +-- .../charting/components/AxisBase.java | 28 +++++----- .../mikephil/charting/components/Legend.java | 2 +- .../charting/components/LimitLine.java | 14 ++--- .../charting/components/MarkerView.java | 4 +- .../mikephil/charting/components/YAxis.java | 8 +-- .../mikephil/charting/data/BarDataSet.java | 12 ++--- .../mikephil/charting/data/BarEntry.java | 4 +- .../mikephil/charting/data/BaseDataSet.java | 10 ++-- .../mikephil/charting/data/BaseEntry.java | 4 +- .../mikephil/charting/data/BubbleEntry.java | 12 ++--- .../mikephil/charting/data/CandleEntry.java | 34 ++++++------ .../mikephil/charting/data/ChartData.java | 36 ++++++------- .../mikephil/charting/data/CombinedData.java | 4 +- .../mikephil/charting/data/DataSet.java | 8 +-- .../github/mikephil/charting/data/Entry.java | 18 +++---- .../mikephil/charting/data/LineDataSet.java | 6 +-- .../charting/data/LineRadarDataSet.java | 2 +- .../charting/data/filter/Approximator.java | 2 +- .../data/realm/base/RealmBaseDataSet.java | 8 +-- .../realm/base/RealmLineRadarDataSet.java | 2 +- .../realm/implementation/RealmBarDataSet.java | 8 +-- .../implementation/RealmBubbleDataSet.java | 4 +- .../implementation/RealmLineDataSet.java | 8 +-- .../realm/implementation/RealmPieDataSet.java | 2 +- .../implementation/RealmRadarDataSet.java | 2 +- .../implementation/RealmScatterDataSet.java | 2 +- .../formatter/DefaultAxisValueFormatter.java | 2 +- .../formatter/DefaultValueFormatter.java | 4 +- .../formatter/LargeValueFormatter.java | 4 +- .../charting/formatter/PercentFormatter.java | 2 +- .../formatter/StackedValueFormatter.java | 8 +-- .../charting/formatter/ValueFormatter.java | 6 +-- .../charting/highlight/BarHighlighter.java | 4 +- .../charting/highlight/ChartHighlighter.java | 4 +- .../charting/highlight/Highlight.java | 52 +++++++++---------- .../mikephil/charting/highlight/Range.java | 4 +- .../interfaces/datasets/IBarDataSet.java | 6 +-- .../interfaces/datasets/IDataSet.java | 30 +++++------ .../datasets/ILineRadarDataSet.java | 2 +- .../charting/listener/ChartTouchListener.java | 2 +- .../OnChartValueSelectedListener.java | 2 +- .../charting/renderer/AxisRenderer.java | 8 +-- .../charting/renderer/BarChartRenderer.java | 4 +- .../charting/renderer/DataRenderer.java | 12 ++--- .../renderer/HorizontalBarChartRenderer.java | 10 ++-- .../charting/renderer/LineChartRenderer.java | 2 +- .../charting/renderer/PieChartRenderer.java | 8 +-- .../charting/renderer/RadarChartRenderer.java | 6 +-- .../mikephil/charting/renderer/Renderer.java | 2 +- .../charting/renderer/XAxisRenderer.java | 2 +- .../XAxisRendererHorizontalBarChart.java | 2 +- .../renderer/XAxisRendererRadarChart.java | 2 +- .../charting/renderer/YAxisRenderer.java | 6 +-- .../YAxisRendererHorizontalBarChart.java | 6 +-- .../renderer/YAxisRendererRadarChart.java | 6 +-- .../charting/utils/SelectionDetail.java | 4 +- .../mikephil/charting/utils/Transformer.java | 8 +-- .../github/mikephil/charting/utils/Utils.java | 14 ++--- .../charting/utils/ViewPortHandler.java | 10 ++-- 79 files changed, 303 insertions(+), 303 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index ce00167fb0..ae0a20ddb5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -65,7 +65,7 @@ protected void onCreate(Bundle savedInstanceState) { // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); - // draw shadows for each bar that show the maximum yValue + // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); // mChart.setDrawXLabels(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index d70e7d219a..676da05e7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); - // draw shadows for each bar that show the maximum yValue + // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 4389f11c04..53a3bc47f4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -50,7 +50,7 @@ public int getXOffset(float xpos) { @Override public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected yValue + // this will cause the marker-view to be above the selected value return -getHeight(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index cac42ef0fd..b86e8ba603 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -46,7 +46,7 @@ public int getXOffset(float xpos) { @Override public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected yValue + // this will cause the marker-view to be above the selected value return -getHeight()-10; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 4a28f772e8..0b8938778d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -37,7 +37,7 @@ public void refreshContent(Entry e, Highlight highlight) { if(be.getYVals() != null) { - // draw the stack yValue + // draw the stack value tvContent.setText("" + Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); } else { tvContent.setText("" + Utils.formatNumber(be.getY(), 0, true)); @@ -56,7 +56,7 @@ public int getXOffset(float xpos) { @Override public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected yValue + // this will cause the marker-view to be above the selected value return -getHeight(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index dcade871f2..06dbb7b865 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -73,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Combined Chart", "Demonstrates how to create a combined chart (bar and line in this case).")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); - objects.add(new ContentItem("Pie Chart with yValue lines", "A simple demonstration of the pie chart with polyline notes.")); + objects.add(new ContentItem("Pie Chart with value lines", "A simple demonstration of the pie chart with polyline notes.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); objects.add(new ContentItem("Stacked Bar Chart", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 54e4c55bfd..a03a1ad959 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -50,7 +50,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "value"); // stacked entries set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); set.setLabel("Realm BarDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index c2c2003d2e..24e3931e6b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "value", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); set.setColors(ColorTemplate.COLORFUL_COLORS, 110); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 4e04cf09df..b73d122855 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); + RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "value"); set.setDrawCubic(false); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 8bcda98356..8a2ca4545a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "value", "label"); // stacked entries set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index fe408bdc00..b4cb14840f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -56,7 +56,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "yValue"); // stacked entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "value"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index 35d598f6cf..caa0190922 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); + RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "value"); set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index e025728920..d48b04d417 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -32,7 +32,7 @@ public class BarChart extends BarLineChartBase implements BarDataProvid private boolean mDrawValueAboveBar = true; /** - * if set to true, a grey area is drawn behind each bar that indicates the maximum yValue + * if set to true, a grey area is drawn behind each bar that indicates the maximum value */ private boolean mDrawBarShadow = false; @@ -80,7 +80,7 @@ protected void calcMinMax() { } /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected yValue at the given touch + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch * point * inside the BarChart. * @@ -166,7 +166,7 @@ public boolean isDrawValueAboveBarEnabled() { } /** - * If set to true, a grey area is drawn behind each bar that indicates the maximum yValue. Enabling his will reduce + * If set to true, a grey area is drawn behind each bar that indicates the maximum value. Enabling his will reduce * performance by about 50%. * * @param enabled @@ -203,7 +203,7 @@ public void setFitBars(boolean enabled) { // /** -// * Returns the lowest x-index (yValue on the x-axis) that is still visible on the chart. +// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. // * // * @return // */ @@ -220,7 +220,7 @@ public void setFitBars(boolean enabled) { // } // // /** -// * Returns the highest x-index (yValue on the x-axis) that is still visible on the chart. +// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. // * // * @return // */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index e9055fec74..5a1a860b56 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -50,7 +50,7 @@ public abstract class BarLineChartBase implements Lin /** * if set to true, a grey area is drawn behind each bar that indicates the - * maximum yValue + * maximum value */ private boolean mDrawBarShadow = false; @@ -189,7 +189,7 @@ public void setDrawValueAboveBar(boolean enabled) { /** * If set to true, a grey area is drawn behind each bar that indicates the - * maximum yValue. Enabling his will reduce performance by about 50%. + * maximum value. Enabling his will reduce performance by about 50%. * * @param enabled */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 7ed1ef5666..e8265af86d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -170,7 +170,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { } /** - * Returns the Highlight object (contains x-index and DataSet index) of the selected yValue at the given touch point + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point * inside the BarChart. * * @param x @@ -203,7 +203,7 @@ public float getHighestVisibleX() { } // /** -// * Returns the lowest x-index (yValue on the x-axis) that is still visible on the chart. +// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. // * // * @return // */ @@ -220,7 +220,7 @@ public float getHighestVisibleX() { // } // // /** -// * Returns the highest x-index (yValue on the x-axis) that is still visible on the chart. +// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. // * // * @return // */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 48cce8c707..ba8e37c8ea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -256,7 +256,7 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { } /** - * calculates the needed angle for a given yValue + * calculates the needed angle for a given value * * @param value * @return @@ -266,7 +266,7 @@ private float calcAngle(float value) { } /** - * calculates the needed angle for a given yValue + * calculates the needed angle for a given value * * @param value * @param yValueSum @@ -550,7 +550,7 @@ public float getTransparentCircleRadius() { /** * Sets the amount of transparency the transparent circle should have 0 = fully transparent, * 255 = fully opaque. - * Default yValue is 100. + * Default value is 100. * * @param alpha 0-255 */ @@ -559,7 +559,7 @@ public void setTransparentCircleAlpha(int alpha) { } /** - * set this to true to draw the x-yValue text into the pie slices + * set this to true to draw the x-value text into the pie slices * * @param enabled */ @@ -588,7 +588,7 @@ public boolean isDrawRoundedSlicesEnabled() { /** * If this is enabled, values inside the PieChart are drawn in percent and - * not with their original yValue. Values provided for the ValueFormatter to + * not with their original value. Values provided for the ValueFormatter to * format are then provided in percent. * * @param enabled diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 2c54ec3abc..ea18e39ee7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -343,7 +343,7 @@ public void setRotationAngle(float angle) { /** * gets the raw version of the current rotation angle of the pie chart the - * returned yValue could be any yValue, negative or positive, outside of the + * returned value could be any value, negative or positive, outside of the * 360 degrees. this is used when working with rotation direction, mainly by * gestures and animations. * @@ -442,7 +442,7 @@ public float getYChartMin() { /** * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail - * objects give information about the yValue at the selected index and the + * objects give information about the value at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index b0da7219d0..fb9d9fb46c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -242,7 +242,7 @@ public float getWebLineWidthInner() { } /** - * Sets the transparency (alpha) yValue for all web lines, default: 150, 255 + * Sets the transparency (alpha) value for all web lines, default: 150, 255 * = 100% opaque, 0 = 100% transparent * * @param alpha @@ -252,7 +252,7 @@ public void setWebAlpha(int alpha) { } /** - * Returns the alpha yValue for all web lines. + * Returns the alpha value for all web lines. * * @return */ @@ -339,14 +339,14 @@ public float getRadius() { } /** - * Returns the maximum yValue this chart can display on it's y-axis. + * Returns the maximum value this chart can display on it's y-axis. */ public float getYChartMax() { return mYAxis.mAxisMaximum; } /** - * Returns the minimum yValue this chart can display on it's y-axis. + * Returns the minimum value this chart can display on it's y-axis. */ public float getYChartMin() { return mYAxis.mAxisMinimum; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 7f852342e2..dcb613b926 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -65,7 +65,7 @@ public abstract class AxisBase extends ComponentBase { /** * When true, axis labels are controlled by the `granularity` property. * When false, axis values could possibly be repeated. - * This could happen if two adjacent axis values are rounded to same yValue. + * This could happen if two adjacent axis values are rounded to same value. * If using granularity this could be avoided by having fewer axis values visible. */ protected boolean mGranularityEnabled = false; @@ -108,12 +108,12 @@ public abstract class AxisBase extends ComponentBase { protected boolean mDrawLimitLineBehindData = false; /** - * flag indicating that the axis-min yValue has been customized + * flag indicating that the axis-min value has been customized */ protected boolean mCustomAxisMin = false; /** - * flag indicating that the axis-max yValue has been customized + * flag indicating that the axis-max value has been customized */ protected boolean mCustomAxisMax = false; @@ -341,7 +341,7 @@ public boolean isGranularityEnabled() { } /** - * Enabled/disable granularity control on axis yValue intervals. If enabled, the axis + * Enabled/disable granularity control on axis value intervals. If enabled, the axis * interval is not allowed to go below a certain granularity. Default: false * * @param enabled @@ -538,7 +538,7 @@ public float getAxisMinimum() { } /** - * By calling this method, any custom maximum yValue that has been previously set is reseted, + * By calling this method, any custom maximum value that has been previously set is reseted, * and the calculation is * done automatically. */ @@ -547,7 +547,7 @@ public void resetAxisMaxValue() { } /** - * Returns true if the axis max yValue has been customized (and is not calculated automatically) + * Returns true if the axis max value has been customized (and is not calculated automatically) * * @return */ @@ -556,7 +556,7 @@ public boolean isAxisMaxCustom() { } /** - * By calling this method, any custom minimum yValue that has been previously set is reseted, + * By calling this method, any custom minimum value that has been previously set is reseted, * and the calculation is * done automatically. */ @@ -565,7 +565,7 @@ public void resetAxisMinValue() { } /** - * Returns true if the axis min yValue has been customized (and is not calculated automatically) + * Returns true if the axis min value has been customized (and is not calculated automatically) * * @return */ @@ -574,11 +574,11 @@ public boolean isAxisMinCustom() { } /** - * Set a custom minimum yValue for this axis. If set, this yValue will not be calculated + * Set a custom minimum value for this axis. If set, this value will not be calculated * automatically depending on * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call * setStartAtZero(false) if you use - * this method. Otherwise, the axis-minimum yValue will still be forced to 0. + * this method. Otherwise, the axis-minimum value will still be forced to 0. * * @param min */ @@ -589,7 +589,7 @@ public void setAxisMinValue(float min) { } /** - * Set a custom maximum yValue for this axis. If set, this yValue will not be calculated + * Set a custom maximum value for this axis. If set, this value will not be calculated * automatically depending on * the provided data. Use resetAxisMaxValue() to undo this. * @@ -605,12 +605,12 @@ public void setAxisMaxValue(float max) { * Calculates the minimum / maximum and range values of the axis with the given * minimum and maximum values from the chart data. * - * @param dataMin the min yValue according to chart data - * @param dataMax the max yValue according to chart data + * @param dataMin the min value according to chart data + * @param dataMax the max value according to chart data */ public void calculate(float dataMin, float dataMax) { - // if custom, use yValue as is, else use data yValue + // if custom, use value as is, else use data value float min = mCustomAxisMin ? mAxisMinimum : dataMin; float max = mCustomAxisMax ? mAxisMaximum : dataMax; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 0514d91f32..77f1710f27 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -76,7 +76,7 @@ public enum LegendDirection { private String[] mExtraLabels; /** - * Are the legend labels/colors a custom yValue or auto calculated? If false, + * Are the legend labels/colors a custom value or auto calculated? If false, * then it's auto, if true, then custom. default false (automatic legend) */ private boolean mIsLegendCustom = false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java index 791e56e2e0..8fcdee8fc1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LimitLine.java @@ -17,7 +17,7 @@ */ public class LimitLine extends ComponentBase { - /** limit / maximum (the y-yValue or xIndex) */ + /** limit / maximum (the y-value or xIndex) */ private float mLimit = 0f; /** the width of the limit line */ @@ -46,7 +46,7 @@ public enum LimitLabelPosition { /** * Constructor with limit. * - * @param limit - the position (the yValue) on the y-axis (y-yValue) or x-axis + * @param limit - the position (the value) on the y-axis (y-value) or x-axis * (xIndex) where this line should appear */ public LimitLine(float limit) { @@ -56,7 +56,7 @@ public LimitLine(float limit) { /** * Constructor with limit and label. * - * @param limit - the position (the yValue) on the y-axis (y-yValue) or x-axis + * @param limit - the position (the value) on the y-axis (y-value) or x-axis * (xIndex) where this line should appear * @param label - provide "" if no label is required */ @@ -157,7 +157,7 @@ public DashPathEffect getDashPathEffect() { } /** - * Sets the color of the yValue-text that is drawn next to the LimitLine. + * Sets the color of the value-text that is drawn next to the LimitLine. * Default: Paint.Style.FILL_AND_STROKE * * @param style @@ -167,7 +167,7 @@ public void setTextStyle(Paint.Style style) { } /** - * Returns the color of the yValue-text that is drawn next to the LimitLine. + * Returns the color of the value-text that is drawn next to the LimitLine. * * @return */ @@ -176,7 +176,7 @@ public Paint.Style getTextStyle() { } /** - * Sets the position of the LimitLine yValue label (either on the right or on + * Sets the position of the LimitLine value label (either on the right or on * the left edge of the chart). Not supported for RadarChart. * * @param pos @@ -186,7 +186,7 @@ public void setLabelPosition(LimitLabelPosition pos) { } /** - * Returns the position of the LimitLine label (yValue). + * Returns the position of the LimitLine label (value). * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java index be0786133f..523376c786 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java @@ -68,7 +68,7 @@ public void draw(Canvas canvas, float posx, float posy) { * * @param e The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or * CandleEntry, simply cast it at runtime. - * @param highlight the highlight object contains information about the highlighted yValue such as it's dataset-index, the + * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the * selected range or stack-index (only stacked bar entries). */ public abstract void refreshContent(Entry e, Highlight highlight); @@ -84,7 +84,7 @@ public void draw(Canvas canvas, float posx, float posy) { /** * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning - * -getHeight() you will cause the MarkerView to be above the selected yValue. + * -getHeight() you will cause the MarkerView to be above the selected value. * * @param ypos the position on the y-axis in pixels where the marker is drawn * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 317d7a3a97..e2663dde6b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -10,7 +10,7 @@ * modify it. Do not * access public variables directly. Be aware that not all features the YLabels class provides * are suitable for the - * RadarChart. Customizations that affect the yValue range of the axis need to be applied before + * RadarChart. Customizations that affect the value range of the axis need to be applied before * setting data for the * chart. * @@ -44,12 +44,12 @@ public class YAxis extends AxisBase { protected float mZeroLineWidth = 1f; /** - * axis space from the largest yValue to the top in percent of the total axis range + * axis space from the largest value to the top in percent of the total axis range */ protected float mSpacePercentTop = 10f; /** - * axis space from the smallest yValue to the bottom in percent of the total axis range + * axis space from the smallest value to the bottom in percent of the total axis range */ protected float mSpacePercentBottom = 10f; @@ -346,7 +346,7 @@ public boolean needsOffset() { @Override public void calculate(float dataMin, float dataMax) { - // if custom, use yValue as is, else use data yValue + // if custom, use value as is, else use data value float min = mCustomAxisMin ? mAxisMinimum : dataMin; float max = mCustomAxisMax ? mAxisMaximum : dataMax; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 14738aa4bc..f77a26e446 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -11,7 +11,7 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet implements IBarDataSet { /** - * the maximum number of bars that are stacked upon each other, this yValue + * the maximum number of bars that are stacked upon each other, this value * is calculated from the Entries that are added to the DataSet */ private int mStackSize = 1; @@ -26,12 +26,12 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl private int mBarBorderColor = Color.BLACK; /** - * the alpha yValue used to draw the highlight indicator bar + * the alpha value used to draw the highlight indicator bar */ private int mHighLightAlpha = 120; /** - * the overall entry count, including counting each stack-yValue individually + * the overall entry count, including counting each stack-value individually */ private int mEntryCountStacks = 0; @@ -170,7 +170,7 @@ public boolean isStacked() { } /** - * returns the overall entry count, including counting each stack-yValue + * returns the overall entry count, including counting each stack-value * individually * * @return @@ -181,7 +181,7 @@ public int getEntryCountStacks() { /** * Sets the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum yValue. Don't for get to + * surface behind the bar that indicates the maximum value. Don't for get to * use getResources().getColor(...) to set this. Or Color.rgb(...). * * @param color @@ -236,7 +236,7 @@ public int getBarBorderColor() { } /** - * Set the alpha yValue (transparency) that is used for drawing the highlight + * Set the alpha value (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index 62b2a8a940..97358ae378 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -84,7 +84,7 @@ public BarEntry copy() { } /** - * Returns the stacked values this BarEntry represents, or null, if only a single yValue is represented (then, use + * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use * getY()). * * @return @@ -105,7 +105,7 @@ public void setVals(float[] vals) { } /** - * Returns the yValue of this BarEntry. If the entry is stacked, it returns the positive sum of all values. + * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 866f78f678..e218dec225 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -42,7 +42,7 @@ public abstract class BaseDataSet implements IDataSet { protected YAxis.AxisDependency mAxisDependency = YAxis.AxisDependency.LEFT; /** - * if true, yValue highlightning is enabled + * if true, value highlightning is enabled */ protected boolean mHighlightEnabled = true; @@ -52,7 +52,7 @@ public abstract class BaseDataSet implements IDataSet { protected transient ValueFormatter mValueFormatter; /** - * the typeface used for the yValue text + * the typeface used for the value text */ protected Typeface mValueTypeface; @@ -62,7 +62,7 @@ public abstract class BaseDataSet implements IDataSet { protected boolean mDrawValues = true; /** - * the size of the yValue-text labels + * the size of the value-text labels */ protected float mValueTextSize = 17f; @@ -196,7 +196,7 @@ public void setColor(int color) { } /** - * Sets a color with a specific alpha yValue. + * Sets a color with a specific alpha value. * * @param color * @param alpha from 0-255 @@ -206,7 +206,7 @@ public void setColor(int color, int alpha) { } /** - * Sets colors with a specific alpha yValue. + * Sets colors with a specific alpha value. * * @param colors * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java index 09896c84a4..099fee86d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java @@ -25,7 +25,7 @@ public BaseEntry(float y, Object data) { } /** - * Returns the y yValue of this Entry. + * Returns the y value of this Entry. * * @return */ @@ -34,7 +34,7 @@ public float getY() { } /** - * Sets the y-yValue for the Entry. + * Sets the y-value for the Entry. * * @param y */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java index d0371cc7fc..c6ff908b85 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java @@ -4,7 +4,7 @@ import android.annotation.SuppressLint; /** - * Subclass of Entry that holds a yValue for one entry in a BubbleChart. Bubble + * Subclass of Entry that holds a value for one entry in a BubbleChart. Bubble * chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed under * Apache License 2.0 * @@ -13,14 +13,14 @@ @SuppressLint("ParcelCreator") public class BubbleEntry extends Entry { - /** size yValue */ + /** size value */ private float mSize = 0f; /** * Constructor. * - * @param x The yValue on the x-axis. - * @param y The yValue on the y-axis. + * @param x The value on the x-axis. + * @param y The value on the y-axis. * @param size The size of the bubble. */ public BubbleEntry(float x, float y, float size) { @@ -31,8 +31,8 @@ public BubbleEntry(float x, float y, float size) { /** * Constructor. * - * @param x The yValue on the x-axis. - * @param y The yValue on the y-axis. + * @param x The value on the x-axis. + * @param y The value on the y-axis. * @param size The size of the bubble. * @param data Spot for additional data this Entry represents. */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java index 41e69ffba7..efe87d077a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java @@ -11,26 +11,26 @@ @SuppressLint("ParcelCreator") public class CandleEntry extends Entry { - /** shadow-high yValue */ + /** shadow-high value */ private float mShadowHigh = 0f; - /** shadow-low yValue */ + /** shadow-low value */ private float mShadowLow = 0f; - /** close yValue */ + /** close value */ private float mClose = 0f; - /** open yValue */ + /** open value */ private float mOpen = 0f; /** * Constructor. * - * @param x The yValue on the x-axis. - * @param shadowH The (shadow) high yValue. - * @param shadowL The (shadow) low yValue. - * @param open The open yValue. - * @param close The close yValue. + * @param x The value on the x-axis. + * @param shadowH The (shadow) high value. + * @param shadowL The (shadow) low value. + * @param open The open value. + * @param close The close value. */ public CandleEntry(float x, float shadowH, float shadowL, float open, float close) { super(x, (shadowH + shadowL) / 2f); @@ -44,9 +44,9 @@ public CandleEntry(float x, float shadowH, float shadowL, float open, float clos /** * Constructor. * - * @param x The yValue on the x-axis. - * @param shadowH The (shadow) high yValue. - * @param shadowL The (shadow) low yValue. + * @param x The value on the x-axis. + * @param shadowH The (shadow) high value. + * @param shadowL The (shadow) low value. * @param open * @param close * @param data Spot for additional data this Entry represents. @@ -81,7 +81,7 @@ public float getBodyRange() { } /** - * Returns the center yValue of the candle. (Middle yValue between high and + * Returns the center value of the candle. (Middle value between high and * low) */ @Override @@ -98,7 +98,7 @@ public CandleEntry copy() { } /** - * Returns the upper shadows highest yValue. + * Returns the upper shadows highest value. * * @return */ @@ -111,7 +111,7 @@ public void setHigh(float mShadowHigh) { } /** - * Returns the lower shadows lowest yValue. + * Returns the lower shadows lowest value. * * @return */ @@ -124,7 +124,7 @@ public void setLow(float mShadowLow) { } /** - * Returns the bodys close yValue. + * Returns the bodys close value. * * @return */ @@ -137,7 +137,7 @@ public void setClose(float mClose) { } /** - * Returns the bodys open yValue. + * Returns the bodys open value. * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0cd23e873c..abc1fd034e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -23,22 +23,22 @@ public abstract class ChartData> { /** - * maximum y-yValue in the yValue array across all axes + * maximum y-value in the value array across all axes */ protected float mYMax = 0.0f; /** - * the minimum y-yValue in the yValue array across all axes + * the minimum y-value in the value array across all axes */ protected float mYMin = 0.0f; /** - * maximum x-yValue in the yValue array + * maximum x-value in the value array */ protected float mXMax = 0f; /** - * minimum x-yValue in the yValue array + * minimum x-value in the value array */ protected float mXMin = 0f; @@ -87,7 +87,7 @@ public ChartData(List sets) { /** * performs all kinds of initialization calculations, such as min-max and - * yValue count and sum + * value count and sum */ protected void init() { @@ -227,7 +227,7 @@ public int getDataSetCount() { } /** - * Returns the smallest y-yValue the data object contains. + * Returns the smallest y-value the data object contains. * * @return */ @@ -236,7 +236,7 @@ public float getYMin() { } /** - * Returns the minimum y-yValue for the specified axis. + * Returns the minimum y-value for the specified axis. * * @param axis * @return @@ -249,7 +249,7 @@ public float getYMin(AxisDependency axis) { } /** - * Returns the greatest y-yValue the data object contains. + * Returns the greatest y-value the data object contains. * * @return */ @@ -258,7 +258,7 @@ public float getYMax() { } /** - * Returns the maximum y-yValue for the specified axis. + * Returns the maximum y-value for the specified axis. * * @param axis * @return @@ -271,7 +271,7 @@ public float getYMax(AxisDependency axis) { } /** - * Returns the minimum x-yValue this data object contains. + * Returns the minimum x-value this data object contains. * * @return */ @@ -280,7 +280,7 @@ public float getXMin() { } /** - * Returns the maximum x-yValue this data object contains. + * Returns the maximum x-value this data object contains. * * @return */ @@ -372,8 +372,8 @@ public Entry getEntryForHighlight(Highlight highlight) { // if (highlight.getDataSetIndex() >= mDataSets.size()) // return null; // else { -// // The yValue of the highlighted entry could be NaN - -// // if we are not interested in highlighting a specific yValue. +// // The value of the highlighted entry could be NaN - +// // if we are not interested in highlighting a specific value. // // List entries = mDataSets.get(highlight.getDataSetIndex()) // .getEntriesForXPos(highlight.getX()); @@ -765,7 +765,7 @@ public void setValueFormatter(ValueFormatter f) { } /** - * Sets the color of the yValue-text (color in which the yValue-labels are + * Sets the color of the value-text (color in which the value-labels are * drawn) for all DataSets this data object contains. * * @param color @@ -777,7 +777,7 @@ public void setValueTextColor(int color) { } /** - * Sets the same list of yValue-colors for all DataSets this + * Sets the same list of value-colors for all DataSets this * data object contains. * * @param colors @@ -789,7 +789,7 @@ public void setValueTextColors(List colors) { } /** - * Sets the Typeface for all yValue-labels for all DataSets this data object + * Sets the Typeface for all value-labels for all DataSets this data object * contains. * * @param tf @@ -801,7 +801,7 @@ public void setValueTypeface(Typeface tf) { } /** - * Sets the size (in dp) of the yValue-text for all DataSets this data object + * Sets the size (in dp) of the value-text for all DataSets this data object * contains. * * @param size @@ -813,7 +813,7 @@ public void setValueTextSize(float size) { } /** - * Enables / disables drawing values (yValue-text) for all DataSets this data + * Enables / disables drawing values (value-text) for all DataSets this data * object contains. * * @param enabled diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 174cac65a8..65bb6cca62 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -131,8 +131,8 @@ public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= data.getDataSetCount()) return null; else { - // The yValue of the highlighted entry could be NaN - - // if we are not interested in highlighting a specific yValue. + // The value of the highlighted entry could be NaN - + // if we are not interested in highlighting a specific value. List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) .getEntriesForXPos(highlight.getX()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 2cc8422843..f260339ca7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -20,22 +20,22 @@ public abstract class DataSet extends BaseDataSet { protected List mValues = null; /** - * maximum y-yValue in the yValue array + * maximum y-value in the value array */ protected float mYMax = 0.0f; /** - * minimum y-yValue in the yValue array + * minimum y-value in the value array */ protected float mYMin = 0.0f; /** - * maximum x-yValue in the yValue array + * maximum x-value in the value array */ protected float mXMax = 0.0f; /** - * minimum x-yValue in the yValue array + * minimum x-value in the value array */ protected float mXMin = 0.0f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index a210093fad..f5847a029d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -7,7 +7,7 @@ /** * Class representing one entry in the chart. Might contain multiple values. - * Might only contain a single yValue depending on the used constructor. + * Might only contain a single value depending on the used constructor. * * @author Philipp Jahoda */ @@ -23,8 +23,8 @@ public Entry() { /** * A Entry represents one single entry in the chart. * - * @param x the x yValue - * @param y the y yValue (the actual yValue of the entry) + * @param x the x value + * @param y the y value (the actual value of the entry) */ public Entry(float x, float y) { super(y); @@ -34,8 +34,8 @@ public Entry(float x, float y) { /** * A Entry represents one single entry in the chart. * - * @param x the x yValue - * @param y the y yValue (the actual yValue of the entry) + * @param x the x value + * @param y the y value (the actual value of the entry) * @param data Spot for additional data this Entry represents. */ public Entry(float x, float y, Object data) { @@ -44,7 +44,7 @@ public Entry(float x, float y, Object data) { } /** - * Returns the x-yValue of this Entry object. + * Returns the x-value of this Entry object. * * @return */ @@ -53,7 +53,7 @@ public float getX() { } /** - * Sets the x-yValue of this Entry object. + * Sets the x-value of this Entry object. * * @param x */ @@ -72,7 +72,7 @@ public Entry copy() { } /** - * Compares yValue, xIndex and data of the entries. Returns true if entries + * Compares value, xIndex and data of the entries. Returns true if entries * are equal in those points, false if not. Does not check by hash-code like * it's done by the "equals" method. * @@ -97,7 +97,7 @@ public boolean equalTo(Entry e) { } /** - * returns a string representation of the entry containing x-index and yValue + * returns a string representation of the entry containing x-index and value */ @Override public String toString() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index b8c3f5e642..d0d7cb3e82 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -25,10 +25,10 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** the color of the inner circles */ private int mCircleColorHole = Color.WHITE; - /** the radius of the circle-shaped yValue indicators */ + /** the radius of the circle-shaped value indicators */ private float mCircleRadius = 8f; - /** the hole radius of the circle-shaped yValue indicators */ + /** the hole radius of the circle-shaped value indicators */ private float mCircleHoleRadius = 4f; /** sets the intensity of the cubic lines */ @@ -155,7 +155,7 @@ public float getCircleHoleRadius() { } /** - * sets the size (radius) of the circle shpaed yValue indicators, + * sets the size (radius) of the circle shpaed value indicators, * default size = 4f * * This method is deprecated because of unclarity. Use setCircleRadius instead. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index 14dc008243..deced96ee9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -84,7 +84,7 @@ public int getFillAlpha() { } /** - * sets the alpha yValue (transparency) that is used for filling the line + * sets the alpha value (transparency) that is used for filling the line * surface (0-255), default: 85 * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java index f562f22f06..cbc630c562 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java @@ -163,7 +163,7 @@ private List reduceWithDouglasPeuker(List entries, double epsilon) * epsilon (tolerance) * * @param entries - * @param epsilon as y-yValue + * @param epsilon as y-value * @param start * @param end */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index b0fad9d14f..63e10754b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -28,22 +28,22 @@ public abstract class RealmBaseDataSet e protected List mValues; /** - * maximum y-yValue in the y-yValue array + * maximum y-value in the y-value array */ protected float mYMax = 0.0f; /** - * the minimum y-yValue in the y-yValue array + * the minimum y-value in the y-value array */ protected float mYMin = 0.0f; /** - * maximum x-yValue in the yValue array + * maximum x-value in the value array */ protected float mXMax = 0.0f; /** - * minimum x-yValue in the yValue array + * minimum x-value in the value array */ protected float mXMin = 0.0f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index 73e95f80c2..31010f2489 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -82,7 +82,7 @@ public int getFillAlpha() { } /** - * sets the alpha yValue (transparency) that is used for filling the line + * sets the alpha value (transparency) that is used for filling the line * surface (0-255), default: 85 * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index fa9c12c4a0..f74379f5a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -21,7 +21,7 @@ public class RealmBarDataSet extends RealmBarLineScatterC private String mStackValueFieldName; /** - * the maximum number of bars that are stacked upon each other, this yValue + * the maximum number of bars that are stacked upon each other, this value * is calculated from the Entries that are added to the DataSet */ private int mStackSize = 1; @@ -36,7 +36,7 @@ public class RealmBarDataSet extends RealmBarLineScatterC private int mBarBorderColor = Color.BLACK; /** - * the alpha yValue used to draw the highlight indicator bar + * the alpha value used to draw the highlight indicator bar */ private int mHighLightAlpha = 120; @@ -181,7 +181,7 @@ public boolean isStacked() { /** * Sets the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum yValue. Don't for get to + * surface behind the bar that indicates the maximum value. Don't for get to * use getResources().getColor(...) to set this. Or Color.rgb(...). * * @param color @@ -236,7 +236,7 @@ public int getBarBorderColor() { } /** - * Set the alpha yValue (transparency) that is used for drawing the highlight + * Set the alpha value (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) * * @param alpha diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 67700a428e..05a7ff523d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -25,7 +25,7 @@ public class RealmBubbleDataSet extends RealmBarLineScatt * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param yValuesField the name of the field in your data object that represents the y-value * @param sizeField the name of the field in your data object that represents the bubble size */ public RealmBubbleDataSet(RealmResults result, String yValuesField, String sizeField) { @@ -40,7 +40,7 @@ public RealmBubbleDataSet(RealmResults result, String yValuesField, String si * Constructor for creating a CandleDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param yValuesField the name of the field in your data object that represents the y-value * @param xIndexField the name of the field in your data object that represents the x-index * @param sizeField the name of the field in your data object that represents the bubble size */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index 0713cb55bb..c985aee55c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -37,11 +37,11 @@ public class RealmLineDataSet extends RealmLineRadarDataS private int mCircleColorHole = Color.WHITE; /** - * the radius of the circle-shaped yValue indicators + * the radius of the circle-shaped value indicators */ private float mCircleRadius = 8f; - /** the hole radius of the circle-shaped yValue indicators */ + /** the hole radius of the circle-shaped value indicators */ private float mCircleHoleRadius = 4f; /** @@ -70,7 +70,7 @@ public class RealmLineDataSet extends RealmLineRadarDataS * Constructor for creating a LineDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param yValuesField the name of the field in your data object that represents the y-value */ public RealmLineDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); @@ -142,7 +142,7 @@ public float getCubicIntensity() { } /** - * sets the size (radius) of the circle shpaed yValue indicators, default + * sets the size (radius) of the circle shpaed value indicators, default * size = 4f * * @param size diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index d7640fee4a..985fc1d143 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -42,7 +42,7 @@ public class RealmPieDataSet extends RealmBaseDataSet result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 7421e3a8ad..880e68586f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -32,7 +32,7 @@ public class RealmRadarDataSet extends RealmLineRadarData * Constructor for creating a RadarDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param yValuesField the name of the field in your data object that represents the y-value */ public RealmRadarDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index cd9afa98fc..35f3863c02 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -44,7 +44,7 @@ public class RealmScatterDataSet extends RealmLineScatter * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-yValue + * @param yValuesField the name of the field in your data object that represents the y-value */ public RealmScatterDataSet(RealmResults result, String yValuesField) { super(result, yValuesField); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index 80294399e9..ad3bb783ee 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -20,7 +20,7 @@ public class DefaultAxisValueFormatter implements AxisValueFormatter { protected int digits = 0; /** - * Constructor that specifies to how many digits the yValue should be + * Constructor that specifies to how many digits the value should be * formatted. * * @param digits diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 00c514aff0..a2de6d99bb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -8,7 +8,7 @@ /** * Default formatter used for formatting values inside the chart. Uses a DecimalFormat with - * pre-calculated number of digits (depending on max and min yValue). + * pre-calculated number of digits (depending on max and min value). * * @author Philipp Jahoda */ @@ -18,7 +18,7 @@ public class DefaultValueFormatter implements ValueFormatter { protected DecimalFormat mFormat; /** - * Constructor that specifies to how many digits the yValue should be + * Constructor that specifies to how many digits the value should be * formatted. * * @param digits diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index ba9d355830..0f852b6f74 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -8,7 +8,7 @@ import java.text.DecimalFormat; /** - * Predefined yValue-formatter that formats large numbers in a pretty way. + * Predefined value-formatter that formats large numbers in a pretty way. * Outputs: 856 = 856; 1000 = 1k; 5821 = 5.8k; 10500 = 10k; 101800 = 102k; * 2000000 = 2m; 7800000 = 7.8m; 92150000 = 92m; 123200000 = 123m; 9999999 = * 10m; 1000000000 = 1b; Special thanks to Roman Gromov @@ -53,7 +53,7 @@ public String getFormattedValue(float value, AxisBase axis) { } /** - * Set an appendix text to be added at the end of the formatted yValue. + * Set an appendix text to be added at the end of the formatted value. * * @param appendix */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index b4a5fd9dee..209da1fa83 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -9,7 +9,7 @@ /** * This ValueFormatter is just for convenience and simply puts a "%" sign after - * each yValue. (Recommeded for PieChart) + * each value. (Recommeded for PieChart) * * @author Philipp Jahoda */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 4c5dce6b50..b13dd8d907 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -10,7 +10,7 @@ * Created by Philipp Jahoda on 28/01/16. *

    * A formatter specifically for stacked BarChart that allows to specify whether the all stack values - * or just the top yValue should be drawn. + * or just the top value should be drawn. */ public class StackedValueFormatter implements ValueFormatter { @@ -20,7 +20,7 @@ public class StackedValueFormatter implements ValueFormatter { private boolean mDrawWholeStack; /** - * a string that should be appended behind the yValue + * a string that should be appended behind the value */ private String mAppendix; @@ -30,7 +30,7 @@ public class StackedValueFormatter implements ValueFormatter { * Constructor. * * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top - * @param appendix a string that should be appended behind the yValue + * @param appendix a string that should be appended behind the value * @param decimals the number of decimal digits to use */ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { @@ -68,7 +68,7 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View } } - // return the "proposed" yValue + // return the "proposed" value return mFormat.format(value) + mAppendix; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java index 12e5ac6a72..1f056bf786 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java @@ -14,12 +14,12 @@ public interface ValueFormatter { /** - * Called when a yValue (from labels inside the chart) is formatted + * Called when a value (from labels inside the chart) is formatted * before being drawn. For performance reasons, avoid excessive calculations * and memory allocations inside this method. * - * @param value the yValue to be formatted - * @param entry the entry the yValue belongs to - in e.g. BarChart, this is of class BarEntry + * @param value the value to be formatted + * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry * @param dataSetIndex the index of the DataSet the entry in focus belongs to * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return the formatted label ready for being drawn diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 1175887aba..1d23073740 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -51,7 +51,7 @@ public Highlight getHighlight(float x, float y) { } /** - * This method creates the Highlight object that also indicates which yValue of a stacked BarEntry has been + * This method creates the Highlight object that also indicates which value of a stacked BarEntry has been * selected. * * @param selectionDetail the selection detail to work with looking for stacked values @@ -97,7 +97,7 @@ protected Highlight getStackedHighlight( } /** - * Returns the index of the closest yValue inside the values array / ranges (stacked barchart) to the yValue + * Returns the index of the closest value inside the values array / ranges (stacked barchart) to the value * given as * a parameter. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 65a6dab0a9..a12d5c3fdc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -55,7 +55,7 @@ public Highlight getHighlight(float x, float y) { */ protected PointD getValsForTouch(float x, float y) { - // take any transformer to determine the x-axis yValue + // take any transformer to determine the x-axis value PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, y); return pos; } @@ -154,7 +154,7 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, } /** - * Returns the SelectionDetail of the DataSet that contains the closest yValue on the + * Returns the SelectionDetail of the DataSet that contains the closest value on the * y-axis. * * @param valsAtIndex all the values at a specific index diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 63664c9f45..f46329f336 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -2,25 +2,25 @@ package com.github.mikephil.charting.highlight; /** - * Contains information needed to determine the highlighted yValue. + * Contains information needed to determine the highlighted value. * * @author Philipp Jahoda */ public class Highlight { - /** the x-yValue of the highlighted yValue */ + /** the x-value of the highlighted value */ private float mX = Float.NaN; - /** the y-yValue of the highlighted yValue */ + /** the y-value of the highlighted value */ private float mY = Float.NaN; /** the index of the data object - in case it refers to more than one */ private int mDataIndex; - /** the index of the dataset the highlighted yValue is in */ + /** the index of the dataset the highlighted value is in */ private int mDataSetIndex; - /** index which yValue of a stacked bar entry is highlighted, default -1 */ + /** index which value of a stacked bar entry is highlighted, default -1 */ private int mStackIndex = -1; /** the range of the bar that is selected (only for stacked-barchart) */ @@ -29,10 +29,10 @@ public class Highlight { /** * constructor * - * @param x the x-yValue of the highlighted yValue - * @param y the y-yValue of the highlighted yValue - * @param dataIndex the index of the Data the highlighted yValue belongs to - * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to + * @param x the x-value of the highlighted value + * @param y the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { this.mX = x; @@ -43,11 +43,11 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { /** * Constructor, only used for stacked-barchart. * - * @param x the x-yValue of the highlighted yValue on the x-axis - * @param y the y-yValue of the highlighted yValue - * @param dataIndex the index of the Data the highlighted yValue belongs to - * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to - * @param stackIndex references which yValue of a stacked-bar entry has been + * @param x the x-value of the highlighted value on the x-axis + * @param y the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * @param stackIndex references which value of a stacked-bar entry has been * selected */ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex) { @@ -58,13 +58,13 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd /** * Constructor, only used for stacked-barchart. * - * @param x the index of the highlighted yValue on the x-axis - * @param y the y-yValue of the highlighted yValue - * @param dataIndex the index of the Data the highlighted yValue belongs to - * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to - * @param stackIndex references which yValue of a stacked-bar entry has been + * @param x the index of the highlighted value on the x-axis + * @param y the y-value of the highlighted value + * @param dataIndex the index of the Data the highlighted value belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * @param stackIndex references which value of a stacked-bar entry has been * selected - * @param range the range the selected stack-yValue is in + * @param range the range the selected stack-value is in */ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex, Range range) { this(x, y, dataIndex, dataSetIndex, stackIndex); @@ -75,14 +75,14 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd * Constructor, only used for stacked-barchart. * * @param x the x-value of the highlighted value on the x-axis - * @param dataSetIndex the index of the DataSet the highlighted yValue belongs to + * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ public Highlight(float x, int dataSetIndex) { this(x, Float.NaN, 0, dataSetIndex, -1); } /** - * returns the x-yValue of the highlighted yValue + * returns the x-value of the highlighted value * * @return */ @@ -91,7 +91,7 @@ public float getX() { } /** - * returns the y-yValue of the highlighted yValue + * returns the y-value of the highlighted value * * @return */ @@ -109,7 +109,7 @@ public int getDataIndex() { } /** - * returns the index of the DataSet the highlighted yValue is in + * returns the index of the DataSet the highlighted value is in * * @return */ @@ -119,7 +119,7 @@ public int getDataSetIndex() { /** * Only needed if a stacked-barchart entry was highlighted. References the - * selected yValue within the stacked-entry. + * selected value within the stacked-entry. * * @return */ @@ -128,7 +128,7 @@ public int getStackIndex() { } /** - * Returns the range of values the selected yValue of a stacked bar is in. (this is only relevant for stacked-barchart) + * Returns the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart) * @return */ public Range getRange() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java index 60391124ec..96dd592b8f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Range.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.highlight; /** - * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one yValue in a stacked bar entry. e.g. + * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one value in a stacked bar entry. e.g. * stack values are -10, 5, 20 -> then ranges are (-10 - 0, 0 - 5, 5 - 25). */ public final class Range { @@ -15,7 +15,7 @@ public Range(float from, float to) { } /** - * Returns true if this range contains (if the yValue is in between) the given yValue, false if not. + * Returns true if this range contains (if the value is in between) the given value, false if not. * * @param value * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index 87e651b16f..fbdfd79531 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -24,7 +24,7 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { /** ###### ###### DATA RELATED METHODS ###### ###### */ /** - * returns the minimum y-yValue this DataSet holds + * returns the minimum y-value this DataSet holds * * @return */ float getYMin(); /** - * returns the maximum y-yValue this DataSet holds + * returns the maximum y-value this DataSet holds * * @return */ float getYMax(); /** - * returns the minimum x-yValue this DataSet holds + * returns the minimum x-value this DataSet holds * * @return */ float getXMin(); /** - * returns the maximum x-yValue this DataSet holds + * returns the maximum x-value this DataSet holds * * @return */ @@ -124,8 +124,8 @@ public interface IDataSet { int getEntryIndex(T e); /** - * Returns the yValue of the Entry object at the given xVal. Returns - * Float.NaN if no yValue is at the given xVal. INFORMATION: This method + * Returns the value of the Entry object at the given xVal. Returns + * Float.NaN if no value is at the given xVal. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * @@ -136,7 +136,7 @@ public interface IDataSet { /** * Returns all of the y values of the Entry objects at the given xPos. Returns - * Float.NaN if no yValue is at the given xPos. INFORMATION: This method + * Float.NaN if no value is at the given xPos. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. * @@ -160,7 +160,7 @@ public interface IDataSet { * Adds an Entry to the DataSet dynamically. * Entries are added to the end of the list. * This will also recalculate the current minimum and maximum - * values of the DataSet and the yValue-sum. + * values of the DataSet and the value-sum. * * @param e */ @@ -169,7 +169,7 @@ public interface IDataSet { /** * Removes an Entry from the DataSets entries array. This will also * recalculate the current minimum and maximum values of the DataSet and the - * yValue-sum. Returns true if an Entry was removed, false if no Entry could + * value-sum. Returns true if an Entry was removed, false if no Entry could * be removed. * * @param e @@ -180,7 +180,7 @@ public interface IDataSet { * Adds an Entry to the DataSet dynamically. * Entries are added to their appropriate index respective to it's x-index. * This will also recalculate the current minimum and maximum - * values of the DataSet and the yValue-sum. + * values of the DataSet and the value-sum. * * @param e */ @@ -289,7 +289,7 @@ public interface IDataSet { boolean isHighlightEnabled(); /** - * If set to true, yValue highlighting is enabled which means that values can + * If set to true, value highlighting is enabled which means that values can * be highlighted programmatically or by touch gesture. * * @param enabled @@ -315,7 +315,7 @@ public interface IDataSet { ValueFormatter getValueFormatter(); /** - * Sets the color the yValue-labels of this DataSet should have. + * Sets the color the value-labels of this DataSet should have. * * @param color */ @@ -329,14 +329,14 @@ public interface IDataSet { void setValueTextColors(List colors); /** - * Sets a Typeface for the yValue-labels of this DataSet. + * Sets a Typeface for the value-labels of this DataSet. * * @param tf */ void setValueTypeface(Typeface tf); /** - * Sets the text-size of the yValue-labels of this DataSet in dp. + * Sets the text-size of the value-labels of this DataSet in dp. * * @param size */ @@ -382,7 +382,7 @@ public interface IDataSet { void setDrawValues(boolean enabled); /** - * Returns true if y-yValue drawing is enabled, false if not + * Returns true if y-value drawing is enabled, false if not * * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java index ebf7e4f565..ce89822716 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java @@ -24,7 +24,7 @@ public interface ILineRadarDataSet extends ILineScatterCandleRa Drawable getFillDrawable(); /** - * Returns the alpha yValue that is used for filling the line surface, + * Returns the alpha value that is used for filling the line surface, * default: 85 * * @return diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java index aae6050916..75c8e864b4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -83,7 +83,7 @@ public void endAction(MotionEvent me) { } /** - * Sets the last yValue that was highlighted via touch. + * Sets the last value that was highlighted via touch. * * @param high */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index e0153dada6..4c6da2e8c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -12,7 +12,7 @@ public interface OnChartValueSelectedListener { /** - * Called when a yValue has been selected inside the chart. + * Called when a value has been selected inside the chart. * * @param e The selected Entry. * @param dataSetIndex The index in the datasets array of the data object diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index f98c9b2547..e0d71b7a59 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -112,8 +112,8 @@ public Transformer getTransformer() { /** * Computes the axis values. * - * @param min - the minimum yValue in the data object for this axis - * @param max - the maximum yValue in the data object for this axis + * @param min - the minimum value in the data object for this axis + * @param max - the maximum value in the data object for this axis */ public void computeAxis(float min, float max, boolean inverted) { @@ -157,7 +157,7 @@ protected void computeAxisValues(float min, float max) { return; } - // Find out how much spacing (in y yValue space) between axis values + // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -226,7 +226,7 @@ protected void computeAxisValues(float min, float max) { for (f = first, i = 0; i < n; f += interval, ++i) { - if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) + if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) f = 0.0; mAxis.mEntries[i] = (float) f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 899ef7ce0b..ed1008f12c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -135,7 +135,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) break; - // Set the color for the currently drawn yValue. If the index + // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], @@ -207,7 +207,7 @@ public void drawValues(Canvas c) { boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); // calculate the correct offset depending on the draw position of - // the yValue + // the value float valueTextHeight = Utils.calcTextHeight(mValuePaint, "8"); posOffset = (drawValueAboveBar ? -valueOffsetPlus : valueTextHeight + valueOffsetPlus); negOffset = (drawValueAboveBar ? valueTextHeight + valueOffsetPlus : -valueOffsetPlus); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index 20a28ea9ae..f4a88fe08d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -67,7 +67,7 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { /** * Returns the Paint object this renderer uses for drawing the values - * (yValue-text). + * (value-text). * * @return */ @@ -95,7 +95,7 @@ public Paint getPaintRender() { } /** - * Applies the required styling (provided by the DataSet) to the yValue-paint + * Applies the required styling (provided by the DataSet) to the value-paint * object. * * @param set @@ -128,12 +128,12 @@ protected void applyValueTextStyle(IDataSet set) { public abstract void drawValues(Canvas c); /** - * Draws the yValue of the given entry by using the provided ValueFormatter. + * Draws the value of the given entry by using the provided ValueFormatter. * * @param c canvas - * @param formatter formatter for custom yValue-formatting - * @param value the yValue to be drawn - * @param entry the entry the yValue belongs to + * @param formatter formatter for custom value-formatting + * @param value the value to be drawn + * @param entry the entry the value belongs to * @param dataSetIndex the index of the DataSet the drawn Entry belongs to * @param x position * @param y position diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index e4cb3150d2..dda51b0a48 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -85,7 +85,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.buffer[j + 3], mShadowPaint); } - // Set the color for the currently drawn yValue. If the index + // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], @@ -148,7 +148,7 @@ public void drawValues(Canvas c) { float val = e.getY(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the yValue + // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -162,7 +162,7 @@ public void drawValues(Canvas c) { y + halfTextHeight, dataSet.getValueTextColor(j / 2)); } - // if each yValue of a potential stack should be drawn + // if each value of a potential stack should be drawn } else { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -194,7 +194,7 @@ public void drawValues(Canvas c) { float val = e.getY(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the yValue + // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -238,7 +238,7 @@ public void drawValues(Canvas c) { float val = vals[k / 2]; String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); - // calculate the correct offset depending on the draw position of the yValue + // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index d7070cb7d5..7135f569a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -29,7 +29,7 @@ public class LineChartRenderer extends LineRadarRenderer { protected LineDataProvider mChart; /** - * paint for the inner circle of the yValue indicators + * paint for the inner circle of the value indicators */ protected Paint mCirclePaintInner; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index dfe3a96f66..4c8fa78747 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -199,7 +199,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { - // draw only if the yValue is greater than zero + // draw only if the value is greater than zero if ((Math.abs(dataSet.getEntryForIndex(j).getY()) > 0.000001)) { visibleAngleCount++; } @@ -214,7 +214,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); - // draw only if the yValue is greater than zero + // draw only if the value is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { if (!mChart.needsHighlight((int) e.getX(), @@ -712,7 +712,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final int entryCount = set.getEntryCount(); int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { - // draw only if the yValue is greater than zero + // draw only if the value is greater than zero if ((Math.abs(set.getEntryForIndex(j).getY()) > 0.000001)) { visibleAngleCount++; } @@ -897,7 +897,7 @@ protected void drawRoundedSlices(Canvas c) { Entry e = dataSet.getEntryForIndex(j); - // draw only if the yValue is greater than zero + // draw only if the value is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { float x = (float) ((r - circleRadius) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 7519d50693..ebf8435696 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -83,7 +83,7 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the yValue to + // calculate the factor that is needed for transforming the value to // pixels float factor = mChart.getFactor(); @@ -157,7 +157,7 @@ public void drawValues(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the yValue to + // calculate the factor that is needed for transforming the value to // pixels float factor = mChart.getFactor(); @@ -198,7 +198,7 @@ protected void drawWeb(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the yValue to + // calculate the factor that is needed for transforming the value to // pixels float factor = mChart.getFactor(); float rotationangle = mChart.getRotationAngle(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java index dcaaeee2a8..337bb54061 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java @@ -21,7 +21,7 @@ public Renderer(ViewPortHandler viewPortHandler) { } /** - * Returns true if the specified yValue fits in between the provided min + * Returns true if the specified value fits in between the provided min * and max bounds, false if not. * * @param val diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 8afc282b01..dd17aec6c4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -309,7 +309,7 @@ public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position, float yOffset) { String label = limitLine.getLabel(); - // if drawing the limit-yValue label is enabled + // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(limitLine.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index ba398fc6d7..10332ab99a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -249,7 +249,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-yValue label is enabled + // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index ed30084f7f..6ccfb09a2a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -34,7 +34,7 @@ public void renderAxisLabels(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the yValue to + // calculate the factor that is needed for transforming the value to // pixels float factor = mChart.getFactor(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 03ff4af9f8..27d56b63a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -55,7 +55,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t // return; // } // -// // Find out how much spacing (in y yValue space) between axis values +// // Find out how much spacing (in y value space) between axis values // double rawInterval = range / labelCount; // double interval = Utils.roundToNextSignificant(rawInterval); // @@ -125,7 +125,7 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t // // for (f = first, i = 0; i < n; f += interval, ++i) { // -// if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) +// if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) // f = 0.0; // // mYAxis.mEntries[i] = (float) f; @@ -352,7 +352,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-yValue label is enabled + // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 2841839510..1bb4598831 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -30,8 +30,8 @@ public YAxisRendererHorizontalBarChart(ViewPortHandler viewPortHandler, YAxis yA /** * Computes the axis values. * - * @param yMin - the minimum y-yValue in the data object for this axis - * @param yMax - the maximum y-yValue in the data object for this axis + * @param yMin - the minimum y-value in the data object for this axis + * @param yMax - the maximum y-value in the data object for this axis */ @Override public void computeAxis(float yMin, float yMax, boolean inverted) { @@ -231,7 +231,7 @@ public void renderLimitLines(Canvas c) { String label = l.getLabel(); - // if drawing the limit-yValue label is enabled + // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { mLimitLinePaint.setStyle(l.getTextStyle()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index db8dec3e73..05ac1ab2dd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -37,7 +37,7 @@ protected void computeAxisValues(float min, float max) { return; } - // Find out how much spacing (in y yValue space) between axis values + // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -108,7 +108,7 @@ protected void computeAxisValues(float min, float max) { for (f = first, i = 0; i < n; f += interval, ++i) { - if (f == 0.0) // Fix for negative zero case (Where yValue == -0.0, and 0.0 == -0.0) + if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) f = 0.0; mAxis.mEntries[i] = (float) f; @@ -180,7 +180,7 @@ public void renderLimitLines(Canvas c) { float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the yValue to + // calculate the factor that is needed for transforming the value to // pixels float factor = mChart.getFactor(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java index 0934883b02..0adeb4b787 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java @@ -3,9 +3,9 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; /** - * Class that encapsulates information of a yValue that has been + * Class that encapsulates information of a value that has been * selected/highlighted and its DataSet index. The SelectionDetail objects give - * information about the yValue at the selected index and the DataSet it belongs + * information about the value at the selected index and the DataSet it belongs * to. Needed only for highlighting onTouch(). * * @author Philipp Jahoda diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 337049f058..6203c2a27d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -246,7 +246,7 @@ public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, /** * transform a path with all the given matrices VERY IMPORTANT: keep order - * to yValue-touch-offset + * to value-touch-offset * * @param path */ @@ -271,7 +271,7 @@ public void pathValuesToPixel(List paths) { /** * Transform an array of points with all matrices. VERY IMPORTANT: Keep - * matrix order "yValue-touch-offset" when transforming. + * matrix order "value-touch-offset" when transforming. * * @param pts */ @@ -374,7 +374,7 @@ public void pixelsToValue(float[] pixels) { Matrix tmp = new Matrix(); - // invert all matrixes to convert back to the original yValue + // invert all matrixes to convert back to the original value mMatrixOffset.invert(tmp); tmp.mapPoints(pixels); @@ -414,7 +414,7 @@ public PointD getValuesByTouchPoint(float x, float y) { } /** - * Returns the x and y coordinates (pixels) for a given x and y yValue in the chart. + * Returns the x and y coordinates (pixels) for a given x and y value in the chart. * * @param x * @param y diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index e705bd6592..4e5fb6ac00 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -89,9 +89,9 @@ public static void init(Resources res) { * This method converts dp unit to equivalent pixels, depending on device * density. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. * - * @param dp A yValue in dp (density independent pixels) unit. Which we need + * @param dp A value in dp (density independent pixels) unit. Which we need * to convert into pixels - * @return A float yValue to represent px equivalent to dp depending on + * @return A float value to represent px equivalent to dp depending on * device density */ public static float convertDpToPixel(float dp) { @@ -117,8 +117,8 @@ public static float convertDpToPixel(float dp) { * This method converts device specific pixels to density independent * pixels. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. * - * @param px A yValue in px (pixels) unit. Which we need to convert into db - * @return A float yValue to represent dp equivalent to px yValue + * @param px A value in px (pixels) unit. Which we need to convert into db + * @return A float value to represent dp equivalent to px value */ public static float convertPixelsToDp(float px) { @@ -382,7 +382,7 @@ public static double nextUp(double d) { } /** - * Returns the index of the DataSet that contains the closest yValue on the + * Returns the index of the DataSet that contains the closest value on the * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. * * @param valsAtIndex all the values at a specific index @@ -400,7 +400,7 @@ public static int getClosestDataSetIndexByValue(List valsAtInde } /** - * Returns the SelectionDetail of the DataSet that contains the closest yValue on the + * Returns the SelectionDetail of the DataSet that contains the closest value on the * y-axis. * * @param valsAtIndex all the values at a specific index @@ -721,7 +721,7 @@ public static int getSDKInt() { */ public static double granularity(float range, int labelCount) { - // Find out how much spacing (in y yValue space) between axis values + // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 078af45b5b..b2aff63e8b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -28,22 +28,22 @@ public class ViewPortHandler { protected float mChartHeight = 0f; /** - * minimum scale yValue on the y-axis + * minimum scale value on the y-axis */ private float mMinScaleY = 1f; /** - * maximum scale yValue on the y-axis + * maximum scale value on the y-axis */ private float mMaxScaleY = Float.MAX_VALUE; /** - * minimum scale yValue on the x-axis + * minimum scale value on the x-axis */ private float mMinScaleX = 1f; /** - * maximum scale yValue on the x-axis + * maximum scale value on the x-axis */ private float mMaxScaleX = Float.MAX_VALUE; @@ -329,7 +329,7 @@ public Matrix translate(final float[] transformedPts) { } /** - * Centers the viewport around the specified position (x-index and y-yValue) + * Centers the viewport around the specified position (x-index and y-value) * in the chart. Centering the viewport outside the bounds of the chart is * not possible. Makes most sense in combination with the * setScaleMinima(...) method. From 01f8a57550ce7e57f019fc8e4ad6a011fd97ebd9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 23:07:19 +0200 Subject: [PATCH 0962/1390] Work on zooming methods --- .../com/xxmassdeveloper/mpchartexample/LineChartActivity1.java | 2 +- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 1e34863659..30b9391415 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -149,7 +149,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.centerViewTo(20, 50, AxisDependency.LEFT); mChart.animateX(2500, Easing.EasingOption.EaseInOutQuart); -// mChart.invalidate(); + //mChart.invalidate(); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 5a1a860b56..ca286a6fe6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -663,7 +663,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { * @param yValue * @param axis the axis relative to which the zoom should take place */ - public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { + public void zoomAndCenter(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { Runnable job = new ZoomJob(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); addViewportJob(job); From 073b4778114403ee8a1f8560b501b2eea7475474 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 23:15:56 +0200 Subject: [PATCH 0963/1390] Fixes related to markerview drawing in animation --- .../mikephil/charting/charts/BarChart.java | 37 ------------------- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/Chart.java | 12 ++---- 3 files changed, 5 insertions(+), 46 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index d48b04d417..a76bd6ebce 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -57,8 +57,6 @@ protected void init() { mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); setHighlighter(new BarHighlighter(this)); - - //mXAxis.mAxisMinimum = -0.5f; } @Override @@ -200,39 +198,4 @@ public BarData getBarData() { public void setFitBars(boolean enabled) { mFitBars = enabled; } - - -// /** -// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. -// * -// * @return -// */ -// @Override -// public float getLowestVisibleX() { -// -// float step = mData.getDataSetCount(); -// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); -// -// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; -// -// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); -// return ((pts[0] <= getXChartMin()) ? 0 : (pts[0] / div) + 1); -// } -// -// /** -// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. -// * -// * @return -// */ -// @Override -// public float getHighestVisibleX() { -// -// float step = mData.getDataSetCount(); -// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); -// -// float[] pts = new float[] { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; -// -// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); -// return ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); -// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index ca286a6fe6..b75e6567b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -527,7 +527,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { int dataSetIndex = highlight.getDataSetIndex(); float xPos = e.getX(); - float yPos = e.getY(); + float yPos = e.getY() * mAnimator.getPhaseY(); // position of the marker depends on selected value index and value float[] pts = new float[]{ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 48eca130b7..359d2228c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -700,10 +700,13 @@ protected void drawMarkers(Canvas canvas) { Highlight highlight = mIndicesToHighlight[i]; + IDataSet set = mData.getDataSetByIndex(highlight.getDataSetIndex()); + Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); + int entryIndex = set.getEntryIndex(e); // make sure entry not null - if (e == null || e.getX() != mIndicesToHighlight[i].getX()) + if (e == null || entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) continue; float[] pos = getMarkerPosition(e, highlight); @@ -715,13 +718,6 @@ protected void drawMarkers(Canvas canvas) { // callbacks to update the content mMarkerView.refreshContent(e, highlight); - // mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, - // MeasureSpec.UNSPECIFIED), - // MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - // mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), - // mMarkerView.getMeasuredHeight()); - // mMarkerView.draw(mDrawCanvas, pos[0], pos[1]); - mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), From 33fbf34a7c7d6893510a9020a29f7a793c0fe3d6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 23:32:39 +0200 Subject: [PATCH 0964/1390] Cleanup --- .../mpchartexample/RealtimeLineChartActivity.java | 10 +++++----- .../mikephil/charting/charts/BarLineChartBase.java | 4 ---- .../mikephil/charting/highlight/ChartHighlighter.java | 2 -- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 62e82dff28..2ec8b19e45 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -146,7 +146,7 @@ private void addEntry() { // mChart.setVisibleYRange(30, AxisDependency.LEFT); // move to the latest entry - mChart.moveViewToX(data.getEntryCount() - 121); + mChart.moveViewToX(data.getEntryCount()); // this automatically refreshes the chart (calls invalidate()) // mChart.moveViewTo(data.getXValCount()-7, 55f, @@ -175,14 +175,14 @@ private LineDataSet createSet() { private void feedMultiple() { - if(thread != null) + if (thread != null) thread.interrupt(); - thread = new Thread(new Runnable() { + thread = new Thread(new Runnable() { @Override public void run() { - for(int i = 0; i < 1000; i++) { + for (int i = 0; i < 1000; i++) { runOnUiThread(new Runnable() { @@ -219,7 +219,7 @@ public void onNothingSelected() { protected void onPause() { super.onPause(); - if(thread != null) { + if (thread != null) { thread.interrupt(); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index b75e6567b6..cc4a14bb9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -357,10 +357,6 @@ protected void calcMinMax() { if (mAutoScaleMinMaxEnabled) mData.calcMinMax(); -// // calculate / set x-axis range -// mXAxis.mAxisMaximum = mData.getXVals().size() - 1; -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - mXAxis.calculate(mData.getXMin(), mData.getXMax()); // calculate axis range (min / max) according to provided data diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index a12d5c3fdc..7ba76d6a77 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -168,8 +168,6 @@ public SelectionDetail getClosestSelectionDetailByPixel( SelectionDetail closest = null; float distance = minSelectionDistance; - System.out.println(distance); - for (int i = 0; i < valsAtIndex.size(); i++) { SelectionDetail sel = valsAtIndex.get(i); From 92504fa81de9c3cf935fa3d37babc5f0721734d0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 4 Jun 2016 23:35:16 +0200 Subject: [PATCH 0965/1390] Update gradle files --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- MPChartLib/build.gradle | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 98bfc41b70..c0e6931a4c 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="52" + android:versionName="3.0.0" > Date: Mon, 6 Jun 2016 16:44:56 +0200 Subject: [PATCH 0966/1390] Improve & test LargeValueFormatter --- .../BarChartActivityMultiDataset.java | 1 + .../formatter/LargeValueFormatter.java | 14 +-- .../charting/utils/ViewPortHandler.java | 1 - .../charting/test/AxisRendererTest.java | 6 -- .../mikephil/charting/test/DataSetTest.java | 3 +- .../test/LargeValueFormatterTest.java | 95 +++++++++++++++++++ 6 files changed, 105 insertions(+), 15 deletions(-) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 93150589b7..69a646fa9c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -247,6 +247,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.getBarData().groupBars(startYear, groupSpace, barSpace); mChart.getXAxis().setAxisMinValue(startYear); mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getIntervalWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); + mChart.notifyDataSetChanged(); mChart.invalidate(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 0f852b6f74..ef8dc4077a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -22,12 +22,12 @@ public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { private static String[] SUFFIX = new String[]{ "", "k", "m", "b", "t" }; - private static final int MAX_LENGTH = 4; + private static final int MAX_LENGTH = 5; private DecimalFormat mFormat; private String mText = ""; public LargeValueFormatter() { - mFormat = new DecimalFormat("###E0"); + mFormat = new DecimalFormat("###E00"); } /** @@ -68,9 +68,7 @@ public void setAppendix(String appendix) { * @param suff new suffix */ public void setSuffix(String[] suff) { - if (suff.length == 5) { - SUFFIX = suff; - } + SUFFIX = suff; } /** @@ -81,7 +79,11 @@ private String makePretty(double number) { String r = mFormat.format(number); - r = r.replaceAll("E[0-9]", SUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); + int numericValue1 = Character.getNumericValue(r.charAt(r.length() - 1)); + int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); + int combined = Integer.valueOf(numericValue2 + "" + numericValue1); + + r = r.replaceAll("E[0-9][0-9]", SUFFIX[combined / 3]); while (r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")) { r = r.substring(0, r.length() - 2) + r.substring(r.length() - 1); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index b2aff63e8b..47ff9aa02e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -102,7 +102,6 @@ public void setChartDimens(float width, float height) { mChartWidth = width; restrainViewPort(offsetLeft, offsetTop, offsetRight, offsetBottom); - } public boolean hasChartDimens() { diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java index b50bd4f9a5..05cb2f3592 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/AxisRendererTest.java @@ -1,17 +1,11 @@ package com.github.mikephil.charting.test; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.renderer.AxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; import org.junit.Test; -import java.util.ArrayList; -import java.util.List; - import static junit.framework.Assert.assertEquals; /** diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 5e86a89e66..51922f5835 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -3,14 +3,13 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; import org.junit.Test; import java.util.ArrayList; import java.util.List; -import static junit.framework.Assert.*; +import static junit.framework.Assert.assertEquals; /** * Created by philipp on 31/05/16. diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java new file mode 100644 index 0000000000..f1e1e0279e --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java @@ -0,0 +1,95 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.formatter.LargeValueFormatter; + +import org.junit.Test; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by philipp on 06/06/16. + */ +public class LargeValueFormatterTest { + + @Test + public void test() { + + LargeValueFormatter formatter = new LargeValueFormatter(); + + String result = formatter.getFormattedValue(5f, null); + assertEquals("5", result); + + result = formatter.getFormattedValue(5.5f, null); + assertEquals("5.5", result); + + result = formatter.getFormattedValue(50f, null); + assertEquals("50", result); + + result = formatter.getFormattedValue(50.5f, null); + assertEquals("50.5", result); + + result = formatter.getFormattedValue(500f, null); + assertEquals("500", result); + + result = formatter.getFormattedValue(1100f, null); + assertEquals("1.1k", result); + + result = formatter.getFormattedValue(10000f, null); + assertEquals("10k", result); + + result = formatter.getFormattedValue(10500f, null); + assertEquals("10.5k", result); + + result = formatter.getFormattedValue(100000f, null); + assertEquals("100k", result); + + result = formatter.getFormattedValue(1000000f, null); + assertEquals("1m", result); + + result = formatter.getFormattedValue(1500000f, null); + assertEquals("1.5m", result); + + result = formatter.getFormattedValue(9500000f, null); + assertEquals("9.5m", result); + + result = formatter.getFormattedValue(22200000f, null); + assertEquals("22.2m", result); + + result = formatter.getFormattedValue(222000000f, null); + assertEquals("222m", result); + + result = formatter.getFormattedValue(1000000000f, null); + assertEquals("1b", result); + + result = formatter.getFormattedValue(9900000000f, null); + assertEquals("9.9b", result); + + result = formatter.getFormattedValue(99000000000f, null); + assertEquals("99b", result); + + result = formatter.getFormattedValue(99500000000f, null); + assertEquals("99.5b", result); + + result = formatter.getFormattedValue(999000000000f, null); + assertEquals("999b", result); + + result = formatter.getFormattedValue(1000000000000f, null); + assertEquals("1t", result); + + formatter.setSuffix(new String[]{"", "k", "m", "b", "t", "q"}); // quadrillion support + result = formatter.getFormattedValue(1000000000000000f, null); + assertEquals("1q", result); + + result = formatter.getFormattedValue(1100000000000000f, null); + assertEquals("1.1q", result); + + result = formatter.getFormattedValue(10000000000000000f, null); + assertEquals("10q", result); + + result = formatter.getFormattedValue(13300000000000000f, null); + assertEquals("13.3q", result); + + result = formatter.getFormattedValue(100000000000000000f, null); + assertEquals("100q", result); + } +} From 40917f0ddaa8b7da142efc384ae7fb83c392c50f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 17:13:10 +0200 Subject: [PATCH 0967/1390] Refactoring --- .../mpchartexample/AnotherBarActivity.java | 2 +- .../mpchartexample/BarChartActivity.java | 4 +-- .../BarChartActivityMultiDataset.java | 26 ++++++++++++++----- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../HorizontalBarChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 4 +-- .../mpchartexample/StackedBarActivity.java | 2 +- .../mikephil/charting/data/DataSet.java | 22 ++++++++-------- 11 files changed, 41 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 159aafce7b..4b12f8c98c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -175,7 +175,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals1); + set1.setValues(yVals1); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 37232cdbf1..448b0f8ba5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -16,7 +16,6 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -35,7 +34,6 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -244,7 +242,7 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals1); + set1.setValues(yVals1); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 69a646fa9c..9b8eb43973 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -13,6 +13,7 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; @@ -21,6 +22,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -95,6 +97,17 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(tf); xl.setGranularity(1f); xl.setCenterAxisLabels(true); + xl.setValueFormatter(new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return String.valueOf((int) value); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -177,8 +190,9 @@ public boolean onOptionsItemSelected(MenuItem item) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float groupSpace = 0.04f; - float barSpace = 0.02f; - float barWidth = 0.3f; + float barSpace = 0.02f; // x3 + float barWidth = 0.3f; // x3 + // (0.3 + 0.02) * 3 + 0.04 = 1.00 int startYear = 1980; int endYear = startYear + mSeekBarX.getProgress(); @@ -213,9 +227,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); set2 = (BarDataSet)mChart.getData().getDataSetByIndex(1); set3 = (BarDataSet)mChart.getData().getDataSetByIndex(2); - set1.setYVals(yVals1); - set2.setYVals(yVals2); - set3.setYVals(yVals3); + set1.setValues(yVals1); + set2.setValues(yVals2); + set3.setValues(yVals3); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -235,7 +249,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set3); BarData data = new BarData(dataSets); -// data.setValueFormatter(new LargeValueFormatter()); + data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width data.setValueTypeface(tf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index ae0a20ddb5..31937a7a31 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -212,7 +212,7 @@ private void setData(int count) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set.setYVals(entries); + set.setValues(entries); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 932e049674..1c22ae41c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -127,7 +127,7 @@ private void setData(List dataList) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set.setYVals(values); + set.setValues(values); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index d2b1e923e0..10e874ac48 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -279,7 +279,7 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals); + set1.setValues(yVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 676da05e7f..301501f77f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -236,7 +236,7 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals1); + set1.setValues(yVals1); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 30b9391415..ac0a864266 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -353,7 +353,7 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals); + set1.setValues(yVals); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 68ede3e0e7..e114db8521 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -310,8 +310,8 @@ private void setData(int count, float range) { mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); - set1.setYVals(yVals1); - set2.setYVals(yVals2); + set1.setValues(yVals1); + set2.setValues(yVals2); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 8e86eaf158..24038acbe9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -192,7 +192,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setYVals(yVals1); + set1.setValues(yVals1); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index f260339ca7..68128e7c39 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -15,7 +15,7 @@ public abstract class DataSet extends BaseDataSet { /** - * the entries that this dataset represents / holds together + * the entries that this DataSet represents / holds together */ protected List mValues = null; @@ -41,16 +41,16 @@ public abstract class DataSet extends BaseDataSet { /** - * Creates a new DataSet object with the given values it represents. Also, a + * Creates a new DataSet object with the given values (entries) it represents. Also, a * label that describes the DataSet can be specified. The label can also be * used to retrieve the DataSet from a ChartData object. * - * @param yVals + * @param values * @param label */ - public DataSet(List yVals, String label) { + public DataSet(List values, String label) { super(label); - this.mValues = yVals; + this.mValues = values; if (mValues == null) mValues = new ArrayList(); @@ -108,21 +108,21 @@ public int getEntryCount() { } /** - * Returns the array of y-values that this DataSet represents. + * Returns the array of entries that this DataSet represents. * * @return */ - public List getYVals() { + public List getValues() { return mValues; } /** - * Sets the array of y-values that this DataSet represents, and calls notifyDataSetChanged() + * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() * * @return */ - public void setYVals(List yVals) { - mValues = yVals; + public void setValues(List values) { + mValues = values; notifyDataSetChanged(); } @@ -221,7 +221,7 @@ public boolean addEntry(T e) { float val = e.getY(); - List yVals = getYVals(); + List yVals = getValues(); if (yVals == null) { yVals = new ArrayList(); } From 68947023d47b5135e9ae580a122315c48b08e1da Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 17:23:26 +0200 Subject: [PATCH 0968/1390] Refactoring and improvements related to grouped bars --- .../BarChartActivityMultiDataset.java | 12 ++-- .../mikephil/charting/buffer/BarBuffer.java | 4 +- .../charting/buffer/HorizontalBarBuffer.java | 4 +- .../mikephil/charting/charts/BarChart.java | 19 ++++++ .../mikephil/charting/data/BarData.java | 66 ++++--------------- .../charting/renderer/BarChartRenderer.java | 1 - .../renderer/HorizontalBarChartRenderer.java | 1 - .../mikephil/charting/utils/Transformer.java | 35 ---------- 8 files changed, 41 insertions(+), 101 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 9b8eb43973..e49e2ecadd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -190,9 +190,10 @@ public boolean onOptionsItemSelected(MenuItem item) { public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float groupSpace = 0.04f; - float barSpace = 0.02f; // x3 - float barWidth = 0.3f; // x3 - // (0.3 + 0.02) * 3 + 0.04 = 1.00 + float barSpace = 0.02f; // x3 dataset + float barWidth = 0.3f; // x3 dataset + // (0.3 + 0.02) * 3 + 0.04 = 1.00 -> interval per "group" + int startYear = 1980; int endYear = startYear + mSeekBarX.getProgress(); @@ -258,10 +259,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } mChart.getBarData().setBarWidth(barWidth); - mChart.getBarData().groupBars(startYear, groupSpace, barSpace); mChart.getXAxis().setAxisMinValue(startYear); - mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getIntervalWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); - mChart.notifyDataSetChanged(); + mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getGroupWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); + mChart.groupBars(startYear, groupSpace, barSpace); mChart.invalidate(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java index fdcae06af7..1a6b85bcb3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java @@ -6,7 +6,6 @@ public class BarBuffer extends AbstractBuffer { - protected float mGroupSpace = 0f; protected int mDataSetIndex = 0; protected int mDataSetCount = 1; protected boolean mContainsStacks = false; @@ -15,9 +14,8 @@ public class BarBuffer extends AbstractBuffer { /** width of the bar on the x-axis, in values (not pixels) */ protected float mBarWidth = 1f; - public BarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { + public BarBuffer(int size, int dataSetCount, boolean containsStacks) { super(size); - this.mGroupSpace = groupspace; this.mDataSetCount = dataSetCount; this.mContainsStacks = containsStacks; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index c97c909508..6b63bc30ea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -6,8 +6,8 @@ public class HorizontalBarBuffer extends BarBuffer { - public HorizontalBarBuffer(int size, float groupspace, int dataSetCount, boolean containsStacks) { - super(size, groupspace, dataSetCount, containsStacks); + public HorizontalBarBuffer(int size, int dataSetCount, boolean containsStacks) { + super(size, dataSetCount, containsStacks); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index a76bd6ebce..c5bd2c8fdc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -198,4 +198,23 @@ public BarData getBarData() { public void setFitBars(boolean enabled) { mFitBars = enabled; } + + /** + * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. + * Leaves space as specified by the parameters. + * Calls notifyDataSetChanged() afterwards. + * + * @param fromX the starting point on the x-axis where the grouping should begin + * @param groupSpace the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f + * @param barSpace the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f + */ + public void groupBars(float fromX, float groupSpace, float barSpace) { + + if (getBarData() == null) { + throw new RuntimeException("You need to set data for the chart before grouping bars."); + } else { + getBarData().groupBars(fromX, groupSpace, barSpace); + notifyDataSetChanged(); + } + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 0bc79d56e9..92109c7a2c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -3,8 +3,6 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -19,11 +17,6 @@ public class BarData extends BarLineScatterCandleBubbleData { */ private float mBarWidth = 1f; - // /** - // * The maximum space (in pixels on the screen) a single bar can consume. - // */ - // private float mMaximumBarWidth = 100f; - public BarData() { super(); } @@ -36,17 +29,6 @@ public BarData(List dataSets) { super(dataSets); } - /** - * Returns the space that is left out between groups of bars. Always returns - * 0 if the BarData object only contains one DataSet (because for one - * DataSet, there is no group-space needed). - * - * @return - */ - public float getGroupSpace() { - return 0f; - } - /** * Sets the width each bar should have on the x-axis (in values, not pixels). * Default 1f @@ -61,20 +43,12 @@ public float getBarWidth() { return mBarWidth; } - // /** -// * Returns true if this BarData object contains grouped DataSets (more than -// * 1 DataSet). -// * -// * @return -// */ -// public boolean isGrouped() { -// return mDataSets.size() > 1 ? true : false; -// } - /** - * Groups all BarDataSet objects this data object holds together. Leaves space as specified by the parameters. + * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. + * Leaves space as specified by the parameters. + * Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method. * - * @param fromX + * @param fromX the starting point on the x-axis where the grouping should begin * @param groupSpace the space between groups of bars in values (not pixels) e.g. 0.8f for bar width 1f * @param barSpace the space between individual bars in values (not pixels) e.g. 0.1f for bar width 1f */ @@ -92,7 +66,7 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { float barSpaceHalf = barSpace / 2f; float barWidthHalf = mBarWidth / 2f; - float interval = getIntervalWidth(groupSpace, barSpace); + float interval = getGroupWidth(groupSpace, barSpace); for (int i = 0; i < maxEntryCount; i++) { @@ -131,28 +105,14 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { notifyDataChanged(); } - public float getIntervalWidth(float groupSpace, float barSpace) { + /** + * In case of grouped bars, this method returns the space an individual group of bar needs on the x-axis. + * + * @param groupSpace + * @param barSpace + * @return + */ + public float getGroupWidth(float groupSpace, float barSpace) { return mDataSets.size() * (mBarWidth + barSpace) + groupSpace; } - - // - // /** - // * Sets the maximum width (in density pixels) a single bar in the barchart - // * should consume. - // * - // * @param max - // */ - // public void setBarWidthMaximum(float max) { - // mMaximumBarWidth = Utils.convertDpToPixel(max); - // } - // - // /** - // * Returns the maximum width (in density pixels) a single bar in the - // * barchart should consume. - // * - // * @return - // */ - // public float getBarWidthMaximum() { - // return mMaximumBarWidth; - // } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index ed1008f12c..82f91ed847 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -62,7 +62,6 @@ public void initBuffers() { for (int i = 0; i < mBarBuffers.length; i++) { IBarDataSet set = barData.getDataSetByIndex(i); mBarBuffers[i] = new BarBuffer(set.getEntryCount() * 4 * (set.isStacked() ? set.getStackSize() : 1), - barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index dda51b0a48..21e386e19c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -41,7 +41,6 @@ public void initBuffers() { for (int i = 0; i < mBarBuffers.length; i++) { IBarDataSet set = barData.getDataSetByIndex(i); mBarBuffers[i] = new HorizontalBarBuffer(set.getEntryCount() * 4 * (set.isStacked() ? set.getStackSize() : 1), - barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 6203c2a27d..5c2d98e7c7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -209,41 +209,6 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, return valuePoints; } - /** - * Transforms an List of Entry into a float array containing the x and - * y values transformed with all matrices for the BARCHART. - * - * @param data - * @param dataSet the dataset index - * @return - */ - public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, - int dataSet, BarData bd, float phaseY) { - - float[] valuePoints = new float[data.getEntryCount() * 2]; - - int setCount = bd.getDataSetCount(); - float space = bd.getGroupSpace(); - - for (int j = 0; j < valuePoints.length; j += 2) { - - Entry e = data.getEntryForIndex(j / 2); - float i = e.getX(); - - // calculate the x-position, depending on datasetcount - float x = i + i * (setCount - 1) + dataSet + space * i - + space / 2f; - float y = e.getY(); - - valuePoints[j] = y * phaseY; - valuePoints[j + 1] = x; - } - - getValueToPixelMatrix().mapPoints(valuePoints); - - return valuePoints; - } - /** * transform a path with all the given matrices VERY IMPORTANT: keep order * to value-touch-offset From 67911b1317467691e50010b485d9baea67049e8e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 17:47:40 +0200 Subject: [PATCH 0969/1390] Write unit tests for groupBars --- .../mikephil/charting/test/BarDataTest.java | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/BarDataTest.java diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/BarDataTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/BarDataTest.java new file mode 100644 index 0000000000..99954bce27 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/BarDataTest.java @@ -0,0 +1,72 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by philipp on 06/06/16. + */ +public class BarDataTest { + + @Test + public void testGroupBars() { + + float groupSpace = 5f; + float barSpace = 1f; + + List values1 = new ArrayList<>(); + List values2 = new ArrayList<>(); + + for(int i = 0; i < 5; i++) { + values1.add(new BarEntry(i, 50)); + values2.add(new BarEntry(i, 60)); + } + + BarDataSet barDataSet1 = new BarDataSet(values1, "Set1"); + BarDataSet barDataSet2 = new BarDataSet(values2, "Set2"); + + BarData data = new BarData(barDataSet1, barDataSet2); + data.setBarWidth(10f); + + float groupWidth = data.getGroupWidth(groupSpace, barSpace); + assertEquals(27f, groupWidth, 0.01f); + + assertEquals(0f, values1.get(0).getX(), 0.01f); + assertEquals(1f, values1.get(1).getX(), 0.01f); + + data.groupBars(1000, groupSpace, barSpace); + + // 1000 + 2.5 + 0.5 + 5 + assertEquals(1008f, values1.get(0).getX(), 0.01f); + assertEquals(1019f, values2.get(0).getX(), 0.01f); + assertEquals(1035f, values1.get(1).getX(), 0.01f); + assertEquals(1046f, values2.get(1).getX(), 0.01f); + + data.groupBars(-1000, groupSpace, barSpace); + + assertEquals(-992f, values1.get(0).getX(), 0.01f); + assertEquals(-981f, values2.get(0).getX(), 0.01f); + assertEquals(-965f, values1.get(1).getX(), 0.01f); + assertEquals(-954f, values2.get(1).getX(), 0.01f); + + data.setBarWidth(20f); + groupWidth = data.getGroupWidth(groupSpace, barSpace); + assertEquals(47f, groupWidth, 0.01f); + + data.setBarWidth(10f); + data.groupBars(-20, groupSpace, barSpace); + + assertEquals(-12f, values1.get(0).getX(), 0.01f); + assertEquals(-1f, values2.get(0).getX(), 0.01f); + assertEquals(15f, values1.get(1).getX(), 0.01f); + assertEquals(26f, values2.get(1).getX(), 0.01f); + } +} From b4109d3248b34cbdb7035475a2a3385be9f4ae75 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 22:51:20 +0200 Subject: [PATCH 0970/1390] Testing of calculate min max of dataset, changes in remove entry methods --- .../DynamicalAddingActivity.java | 2 +- .../mikephil/charting/data/BaseDataSet.java | 11 +++- .../mikephil/charting/data/ChartData.java | 1 - .../mikephil/charting/data/DataSet.java | 65 ++++++++----------- .../data/realm/base/RealmBaseDataSet.java | 43 ++++++------ .../interfaces/datasets/IDataSet.java | 36 ++++++---- .../mikephil/charting/test/DataSetTest.java | 62 ++++++++++++++++++ 7 files changed, 144 insertions(+), 76 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 886a8f7ed2..a505e4a4f9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -91,7 +91,7 @@ private void removeLastEntry() { data.removeEntry(e, 0); // or remove by index - // mData.removeEntry(xIndex, dataSetIndex); + // mData.removeEntryByXPos(xIndex, dataSetIndex); data.notifyDataChanged(); mChart.notifyDataSetChanged(); mChart.invalidate(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index e218dec225..77a8367069 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -363,9 +363,16 @@ public boolean removeLast() { } @Override - public boolean removeEntry(int xIndex) { + public boolean removeEntryByXPos(float xPos) { - T e = getEntryForXPos(xIndex); + T e = getEntryForXPos(xPos); + return removeEntry(e); + } + + @Override + public boolean removeEntry(int index) { + + T e = getEntryForIndex(index); return removeEntry(e); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index abc1fd034e..02ac723ba2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -7,7 +7,6 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 68128e7c39..407c1e653b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -76,18 +76,7 @@ public void calcMinMax() { for (T e : mValues) { if (e != null && !Float.isNaN(e.getY())) { - - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); - - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); + calcMinMax(e); } } @@ -102,6 +91,26 @@ public void calcMinMax() { } } + /** + * Updates the min and max x and y value of this DataSet based on the given Entry. + * + * @param e + */ + protected void calcMinMax(T e) { + + if (e.getY() < mYMin) + mYMin = e.getY(); + + if (e.getY() > mYMax) + mYMax = e.getY(); + + if (e.getX() < mXMin) + mXMin = e.getX(); + + if (e.getX() > mXMax) + mXMax = e.getX(); + } + @Override public int getEntryCount() { return mValues.size(); @@ -182,21 +191,11 @@ public void addEntryOrdered(T e) { if (e == null) return; - float val = e.getY(); - if (mValues == null) { mValues = new ArrayList(); } - if (mValues.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } + calcMinMax(e); if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { int closestIndex = getEntryIndex(e.getX(), Rounding.UP); @@ -219,25 +218,15 @@ public boolean addEntry(T e) { if (e == null) return false; - float val = e.getY(); - - List yVals = getValues(); - if (yVals == null) { - yVals = new ArrayList(); + List values = getValues(); + if (values == null) { + values = new ArrayList(); } - if (yVals.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } + calcMinMax(e); // add the entry - yVals.add(e); + values.add(e); return true; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 63e10754b5..189c1221ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -145,18 +145,7 @@ public void calcMinMax() { for (S e : mValues) { if (e != null && !Float.isNaN(e.getY())) { - - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); - - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); + calcMinMax(e); } } @@ -171,6 +160,26 @@ public void calcMinMax() { } } + /** + * Updates the min and max x and y value of this DataSet based on the given Entry. + * + * @param e + */ + protected void calcMinMax(S e) { + + if (e.getY() < mYMin) + mYMin = e.getY(); + + if (e.getY() > mYMax) + mYMax = e.getY(); + + if (e.getX() < mXMin) + mXMin = e.getX(); + + if (e.getX() > mXMax) + mXMax = e.getX(); + } + @Override public S getEntryForXPos(float xPos) { //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mXValuesField, xIndex).findFirst()); @@ -298,15 +307,7 @@ public boolean addEntry(S e) { mValues = new ArrayList(); } - if (mValues.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } + calcMinMax(e); // add the entry mValues.add(e); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 5e62fc9224..4d69438465 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -166,19 +166,10 @@ public interface IDataSet { */ boolean addEntry(T e); - /** - * Removes an Entry from the DataSets entries array. This will also - * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could - * be removed. - * - * @param e - */ - boolean removeEntry(T e); /** * Adds an Entry to the DataSet dynamically. - * Entries are added to their appropriate index respective to it's x-index. + * Entries are added to their appropriate index in the values array respective to their x-position. * This will also recalculate the current minimum and maximum * values of the DataSet and the value-sum. * @@ -203,12 +194,31 @@ public interface IDataSet { boolean removeLast(); /** - * Removes the Entry object that has the given xIndex from the DataSet. + * Removes an Entry from the DataSets entries array. This will also + * recalculate the current minimum and maximum values of the DataSet and the + * value-sum. Returns true if an Entry was removed, false if no Entry could + * be removed. + * + * @param e + */ + boolean removeEntry(T e); + + /** + * Removes the Entry object that has the given xPos from the DataSet. * Returns true if an Entry was removed, false if no Entry could be removed. * - * @param xIndex + * @param xPos + */ + boolean removeEntryByXPos(float xPos); + + /** + * Removes the Entry object at the given index in the values array from the DataSet. + * Returns true if an Entry was removed, false if no Entry could be removed. + * + * @param index + * @return */ - boolean removeEntry(int xIndex); + boolean removeEntry(int index); /** * Checks if this DataSet contains the specified Entry. Returns true if so, diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 51922f5835..7da83018d4 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -16,6 +16,68 @@ */ public class DataSetTest { + @Test + public void testCalcMinMax() { + + List entries = new ArrayList(); + entries.add(new Entry(10, 10)); + entries.add(new Entry(15, 2)); + entries.add(new Entry(21, 5)); + + ScatterDataSet set = new ScatterDataSet(entries, ""); + + assertEquals(10f, set.getXMin(), 0.01f); + assertEquals(21f, set.getXMax(), 0.01f); + + assertEquals(2f, set.getYMin(), 0.01f); + assertEquals(10f, set.getYMax(), 0.01f); + + assertEquals(3, set.getEntryCount()); + + set.addEntry(new Entry(25, 1)); + + assertEquals(10f, set.getXMin(), 0.01f); + assertEquals(25f, set.getXMax(), 0.01f); + + assertEquals(1f, set.getYMin(), 0.01f); + assertEquals(10f, set.getYMax(), 0.01f); + + assertEquals(4, set.getEntryCount()); + } + + @Test + public void testAddRemoveEntry() { + + List entries = new ArrayList(); + entries.add(new Entry(10, 10)); + entries.add(new Entry(15, 2)); + entries.add(new Entry(21, 5)); + + ScatterDataSet set = new ScatterDataSet(entries, ""); + + assertEquals(3, set.getEntryCount()); + + set.addEntryOrdered(new Entry(5, 1)); + + assertEquals(4, set.getEntryCount()); + + assertEquals(5, set.getXMin(), 0.01f); + assertEquals(21, set.getXMax(), 0.01f); + + assertEquals(1f, set.getYMin(), 0.01f); + assertEquals(10f, set.getYMax(), 0.01f); + + assertEquals(5, set.getEntryForIndex(0).getX(), 0.01f); + assertEquals(1, set.getEntryForIndex(0).getY(), 0.01f); + + set.addEntryOrdered(new Entry(20, 50)); + + assertEquals(5, set.getEntryCount()); + + assertEquals(20, set.getEntryForIndex(3).getX(), 0.01f); + assertEquals(50, set.getEntryForIndex(3).getY(), 0.01f); + + } @Test public void testGetEntryForXPos() { From 280101bafc8fe84081e031b30f2b96bd3b9580e2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 22:53:09 +0200 Subject: [PATCH 0971/1390] IDataSet interface cleanup --- .../charting/interfaces/datasets/IDataSet.java | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 4d69438465..49a78d7e52 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -124,18 +124,7 @@ public interface IDataSet { int getEntryIndex(T e); /** - * Returns the value of the Entry object at the given xVal. Returns - * Float.NaN if no value is at the given xVal. INFORMATION: This method - * does calculations at runtime. Do not over-use in performance critical - * situations. - * - * @param xVal - * @return - */ - float getYValueForXValue(float xVal); - - /** - * Returns all of the y values of the Entry objects at the given xPos. Returns + * Returns the value of the Entry object at the given xPos. Returns * Float.NaN if no value is at the given xPos. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. @@ -143,7 +132,8 @@ public interface IDataSet { * @param xPos * @return */ - float[] getYValuesForXPos(float xPos); + float getYValueForXValue(float xPos); + /** * This method returns the actual @@ -204,7 +194,7 @@ public interface IDataSet { boolean removeEntry(T e); /** - * Removes the Entry object that has the given xPos from the DataSet. + * Removes the Entry object closest to the given xPos from the DataSet. * Returns true if an Entry was removed, false if no Entry could be removed. * * @param xPos From dc03cf2593b7c8dbf379f2448e6d58c1c78ce62f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 23:11:18 +0200 Subject: [PATCH 0972/1390] Test adding and removing entries --- .../mikephil/charting/data/BaseDataSet.java | 32 +++++++---- .../mikephil/charting/data/DataSet.java | 19 +------ .../data/realm/base/RealmBaseDataSet.java | 14 ----- .../mikephil/charting/test/DataSetTest.java | 53 +++++++++++++++++++ 4 files changed, 78 insertions(+), 40 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 77a8367069..14a8241451 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -110,7 +110,9 @@ public List getColors() { return mColors; } - public List getValueColors() { return mValueColors; } + public List getValueColors() { + return mValueColors; + } @Override public int getColor() { @@ -225,7 +227,9 @@ public void resetColors() { mColors = new ArrayList(); } - /** ###### ###### OTHER STYLING RELATED METHODS ##### ###### */ + /** + * ###### ###### OTHER STYLING RELATED METHODS ##### ###### + */ @Override public void setLabel(String label) { @@ -335,7 +339,9 @@ public void setAxisDependency(YAxis.AxisDependency dependency) { } - /** ###### ###### DATA RELATED METHODS ###### ###### */ + /** + * ###### ###### DATA RELATED METHODS ###### ###### + */ @Override public int getIndexInEntries(int xIndex) { @@ -351,15 +357,23 @@ public int getIndexInEntries(int xIndex) { @Override public boolean removeFirst() { - T entry = getEntryForIndex(0); - return removeEntry(entry); + if (getEntryCount() > 0) { + + T entry = getEntryForIndex(0); + return removeEntry(entry); + } else + return false; } @Override public boolean removeLast() { - T entry = getEntryForIndex(getEntryCount() - 1); - return removeEntry(entry); + if (getEntryCount() > 0) { + + T e = getEntryForIndex(getEntryCount() - 1); + return removeEntry(e); + } else + return false; } @Override @@ -379,8 +393,8 @@ public boolean removeEntry(int index) { @Override public boolean contains(T e) { - for(int i = 0; i < getEntryCount(); i++) { - if(getEntryForIndex(i).equals(e)) + for (int i = 0; i < getEntryCount(); i++) { + if (getEntryForIndex(i).equals(e)) return true; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 407c1e653b..39beb6405f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -200,10 +200,9 @@ public void addEntryOrdered(T e) { if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { int closestIndex = getEntryIndex(e.getX(), Rounding.UP); mValues.add(closestIndex, e); - return; + } else { + mValues.add(e); } - - mValues.add(e); } @Override @@ -322,20 +321,6 @@ public float getYValueForXValue(float xVal) { return Float.NaN; } - @Override - public float[] getYValuesForXPos(float xVal) { - - List entries = getEntriesForXPos(xVal); - - float[] yVals = new float[entries.size()]; - int i = 0; - - for (T e : entries) - yVals[i++] = e.getY(); - - return yVals; - } - /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 189c1221ae..3e06759f66 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -281,20 +281,6 @@ public float getYValueForXValue(float xVal) { return Float.NaN; } - @Override - public float[] getYValuesForXPos(float xVal) { - - List entries = getEntriesForXPos(xVal); - - float[] yVals = new float[entries.size()]; - int i = 0; - - for (S e : entries) - yVals[i++] = e.getY(); - - return yVals; - } - @Override public boolean addEntry(S e) { diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 7da83018d4..2d2d2f7555 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -10,6 +10,8 @@ import java.util.List; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; /** * Created by philipp on 31/05/16. @@ -77,6 +79,57 @@ public void testAddRemoveEntry() { assertEquals(20, set.getEntryForIndex(3).getX(), 0.01f); assertEquals(50, set.getEntryForIndex(3).getY(), 0.01f); + assertTrue(set.removeEntry(3)); + + assertEquals(4, set.getEntryCount()); + + assertEquals(21, set.getEntryForIndex(3).getX(), 0.01f); + assertEquals(5, set.getEntryForIndex(3).getY(), 0.01f); + + assertEquals(5, set.getEntryForIndex(0).getX(), 0.01f); + assertEquals(1, set.getEntryForIndex(0).getY(), 0.01f); + + assertTrue(set.removeFirst()); + + assertEquals(3, set.getEntryCount()); + + assertEquals(10, set.getEntryForIndex(0).getX(), 0.01f); + assertEquals(10, set.getEntryForIndex(0).getY(), 0.01f); + + set.addEntryOrdered(new Entry(15, 3)); + + assertEquals(4, set.getEntryCount()); + + assertEquals(15, set.getEntryForIndex(1).getX(), 0.01f); + assertEquals(3, set.getEntryForIndex(1).getY(), 0.01f); + + assertEquals(21, set.getEntryForIndex(3).getX(), 0.01f); + assertEquals(5, set.getEntryForIndex(3).getY(), 0.01f); + + assertTrue(set.removeLast()); + + assertEquals(3, set.getEntryCount()); + + assertEquals(15, set.getEntryForIndex(2).getX(), 0.01f); + assertEquals(2, set.getEntryForIndex(2).getY(), 0.01f); + + assertTrue(set.removeLast()); + + assertEquals(2, set.getEntryCount()); + + assertTrue(set.removeLast()); + + assertEquals(1, set.getEntryCount()); + + assertEquals(10, set.getEntryForIndex(0).getX(), 0.01f); + assertEquals(10, set.getEntryForIndex(0).getY(), 0.01f); + + assertTrue(set.removeLast()); + + assertEquals(0, set.getEntryCount()); + + assertFalse(set.removeLast()); + assertFalse(set.removeFirst()); } @Test From 0a55308975c769bd7fafdcb8085d48c1ac181553 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 23:54:54 +0200 Subject: [PATCH 0973/1390] Fixes and testing related to dynamic data adding and removing from chartdata --- .../mikephil/charting/data/ChartData.java | 285 +++++++----------- .../mikephil/charting/test/ChartDataTest.java | 95 ++++++ 2 files changed, 203 insertions(+), 177 deletions(-) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 02ac723ba2..0b88010cbc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -41,18 +41,18 @@ public abstract class ChartData> { */ protected float mXMin = 0f; - protected float mLeftAxisMax = 0.0f; + protected float mLeftAxisMax = Float.MIN_VALUE; - protected float mLeftAxisMin = 0.0f; + protected float mLeftAxisMin = Float.MAX_VALUE; - protected float mRightAxisMax = 0.0f; + protected float mRightAxisMax = Float.MIN_VALUE; - protected float mRightAxisMin = 0.0f; + protected float mRightAxisMin = Float.MAX_VALUE; /** - * total number of y-values across all DataSet objects + * total number of values (entries) across all DataSet objects */ - private int mYValCount = 0; + private int mValueCount = 0; /** * contains the maximum length (in characters) an entry in the x-vals array @@ -70,10 +70,27 @@ public ChartData() { } public ChartData(T... dataSets) { - mDataSets = Arrays.asList(dataSets); + mDataSets = arrayToList(dataSets); init(); } + /** + * Created because Arrays.asList(...) does not support modification. + * + * @param array + * @return + */ + private List arrayToList(T[] array) { + + List list = new ArrayList<>(); + + for (T set : array) { + list.add(set); + } + + return list; + } + /** * constructor for chart data * @@ -126,20 +143,8 @@ public void calcMinMax() { for (int i = 0; i < mDataSets.size(); i++) { - IDataSet set = mDataSets.get(i); - set.calcMinMax(); - - if (set.getYMin() < mYMin) - mYMin = set.getYMin(); - - if (set.getYMax() > mYMax) - mYMax = set.getYMax(); - - if (set.getXMin() < mXMin) - mXMin = set.getXMin(); - - if (set.getXMax() > mXMax) - mXMax = set.getXMax(); + T set = mDataSets.get(i); + calcMinMax(set); } if (mYMin == Float.MAX_VALUE) { @@ -184,9 +189,6 @@ public void calcMinMax() { } } } - - // in case there is only one axis, adjust the second axis - handleEmptyAxis(firstLeft, firstRight); } } @@ -198,7 +200,7 @@ public void calcMinMax() { */ protected void calcYValueCount() { - mYValCount = 0; + mValueCount = 0; if (mDataSets == null) return; @@ -209,7 +211,7 @@ protected void calcYValueCount() { count += mDataSets.get(i).getEntryCount(); } - mYValCount = count; + mValueCount = count; } /** ONLY GETTERS AND SETTERS BELOW THIS */ @@ -241,10 +243,18 @@ public float getYMin() { * @return */ public float getYMin(AxisDependency axis) { - if (axis == AxisDependency.LEFT) - return mLeftAxisMin; - else - return mRightAxisMin; + if (axis == AxisDependency.LEFT) { + + if (mLeftAxisMin == Float.MAX_VALUE) { + return mRightAxisMin; + } else + return mLeftAxisMin; + } else { + if (mRightAxisMin == Float.MAX_VALUE) { + return mLeftAxisMin; + } else + return mRightAxisMin; + } } /** @@ -263,10 +273,18 @@ public float getYMax() { * @return */ public float getYMax(AxisDependency axis) { - if (axis == AxisDependency.LEFT) - return mLeftAxisMax; - else - return mRightAxisMax; + if (axis == AxisDependency.LEFT) { + + if (mLeftAxisMax == Float.MIN_VALUE) { + return mRightAxisMax; + } else + return mLeftAxisMax; + } else { + if (mRightAxisMax == Float.MIN_VALUE) { + return mLeftAxisMax; + } else + return mRightAxisMax; + } } /** @@ -304,7 +322,7 @@ public float getXValMaximumLength() { * @return */ public int getYValCount() { - return mYValCount; + return mValueCount; } public List getDataSets() { @@ -367,23 +385,6 @@ public Entry getEntryForHighlight(Highlight highlight) { return mDataSets.get(highlight.getDataSetIndex()).getEntryForXPos(highlight.getX()); } } -// public Entry getEntryForHighlight(Highlight highlight) { -// if (highlight.getDataSetIndex() >= mDataSets.size()) -// return null; -// else { -// // The value of the highlighted entry could be NaN - -// // if we are not interested in highlighting a specific value. -// -// List entries = mDataSets.get(highlight.getDataSetIndex()) -// .getEntriesForXPos(highlight.getX()); -// for (Object entry : entries) -// if (((Entry)entry).getY() == highlight.getY() || -// Float.isNaN(highlight.getY())) -// return (Entry)entry; -// -// return null; -// } -// } /** * Returns the DataSet object with the given label. Search can be case @@ -422,63 +423,11 @@ public void addDataSet(T d) { if (d == null) return; - mYValCount += d.getEntryCount(); - - if (mDataSets.size() <= 0) { - - mYMax = d.getYMax(); - mYMin = d.getYMin(); - - if (d.getAxisDependency() == AxisDependency.LEFT) { - - mLeftAxisMax = d.getYMax(); - mLeftAxisMin = d.getYMin(); - } else { - mRightAxisMax = d.getYMax(); - mRightAxisMin = d.getYMin(); - } - } else { + mValueCount += d.getEntryCount(); - if (mYMax < d.getYMax()) - mYMax = d.getYMax(); - if (mYMin > d.getYMin()) - mYMin = d.getYMin(); - - if (d.getAxisDependency() == AxisDependency.LEFT) { - - if (mLeftAxisMax < d.getYMax()) - mLeftAxisMax = d.getYMax(); - if (mLeftAxisMin > d.getYMin()) - mLeftAxisMin = d.getYMin(); - } else { - if (mRightAxisMax < d.getYMax()) - mRightAxisMax = d.getYMax(); - if (mRightAxisMin > d.getYMin()) - mRightAxisMin = d.getYMin(); - } - } + calcMinMax(d); mDataSets.add(d); - - handleEmptyAxis(getFirstLeft(), getFirstRight()); - } - - /** - * This adjusts the other axis if one axis is empty and the other is not. - * - * @param firstLeft - * @param firstRight - */ - private void handleEmptyAxis(T firstLeft, T firstRight) { - - // in case there is only one axis, adjust the second axis - if (firstLeft == null) { - mLeftAxisMax = mRightAxisMax; - mLeftAxisMin = mRightAxisMin; - } else if (firstRight == null) { - mRightAxisMax = mLeftAxisMax; - mRightAxisMin = mLeftAxisMin; - } } /** @@ -498,7 +447,7 @@ public boolean removeDataSet(T d) { // if a DataSet was removed if (removed) { - mYValCount -= d.getEntryCount(); + mValueCount -= d.getEntryCount(); calcMinMax(); } @@ -538,47 +487,64 @@ public void addEntry(Entry e, int dataSetIndex) { if (!set.addEntry(e)) return; - float val = e.getY(); + calcMinMax(e, set.getAxisDependency()); - if (mYValCount == 0) { - mYMin = val; - mYMax = val; + mValueCount += 1; - if (set.getAxisDependency() == AxisDependency.LEFT) { + } else { + Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); + } + } - mLeftAxisMax = e.getY(); - mLeftAxisMin = e.getY(); - } else { - mRightAxisMax = e.getY(); - mRightAxisMin = e.getY(); - } - } else { - - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - - if (set.getAxisDependency() == AxisDependency.LEFT) { - - if (mLeftAxisMax < e.getY()) - mLeftAxisMax = e.getY(); - if (mLeftAxisMin > e.getY()) - mLeftAxisMin = e.getY(); - } else { - if (mRightAxisMax < e.getY()) - mRightAxisMax = e.getY(); - if (mRightAxisMin > e.getY()) - mRightAxisMin = e.getY(); - } - } + protected void calcMinMax(Entry e, AxisDependency axis) { + + if (mYMax < e.getY()) + mYMax = e.getY(); + if (mYMin > e.getY()) + mYMin = e.getY(); - mYValCount += 1; + if (mXMax < e.getX()) + mXMax = e.getX(); + if (mXMin > e.getX()) + mXMin = e.getX(); - handleEmptyAxis(getFirstLeft(), getFirstRight()); + if (axis == AxisDependency.LEFT) { + if (mLeftAxisMax < e.getY()) + mLeftAxisMax = e.getY(); + if (mLeftAxisMin > e.getY()) + mLeftAxisMin = e.getY(); } else { - Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); + if (mRightAxisMax < e.getY()) + mRightAxisMax = e.getY(); + if (mRightAxisMin > e.getY()) + mRightAxisMin = e.getY(); + } + } + + protected void calcMinMax(T d) { + + if (mYMax < d.getYMax()) + mYMax = d.getYMax(); + if (mYMin > d.getYMin()) + mYMin = d.getYMin(); + + if (mXMax < d.getXMax()) + mXMax = d.getXMax(); + if (mXMin > d.getXMin()) + mXMin = d.getXMin(); + + if (d.getAxisDependency() == AxisDependency.LEFT) { + + if (mLeftAxisMax < d.getYMax()) + mLeftAxisMax = d.getYMax(); + if (mLeftAxisMin > d.getYMin()) + mLeftAxisMin = d.getYMin(); + } else { + if (mRightAxisMax < d.getYMax()) + mRightAxisMax = d.getYMax(); + if (mRightAxisMin > d.getYMin()) + mRightAxisMin = d.getYMin(); } } @@ -601,7 +567,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = set.removeEntry(e); if (removed) { - mYValCount -= 1; + mValueCount -= 1; calcMinMax(); } @@ -731,23 +697,6 @@ public T getFirstRight() { return null; } -// /** -// * Generates an x-values array filled with numbers in range specified by the -// * parameters. Can be used for convenience. -// * -// * @return -// */ -// public static List generateXVals(int from, int to) { -// -// List xvals = new ArrayList(); -// -// for (int i = from; i < to; i++) { -// xvals.add(new XAxisValue(i, i + "")); -// } -// -// return xvals; -// } - /** * Sets a custom ValueFormatter for all DataSets this data object contains. * @@ -857,24 +806,6 @@ public void clearValues() { notifyDataChanged(); } -// /** -// * Checks if this data object contains the specified Entry. Returns true if -// * so, false if not. NOTE: Performance is pretty bad on this one, do not -// * over-use in performance critical situations. -// * -// * @param e -// * @return -// */ -// public boolean contains(Entry e) { -// -// for (T set : mDataSets) { -// if (set.contains(e)) -// return true; -// } -// -// return false; -// } - /** * Checks if this data object contains the specified DataSet. Returns true * if so, false if not. diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java new file mode 100644 index 0000000000..487fd1eac1 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java @@ -0,0 +1,95 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.data.ScatterDataSet; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by philipp on 06/06/16. + */ +public class ChartDataTest { + + @Test + public void testDynamicChartData() { + + List entries1 = new ArrayList(); + entries1.add(new Entry(10, 10)); + entries1.add(new Entry(15, -2)); + entries1.add(new Entry(21, 50)); + + ScatterDataSet set1 = new ScatterDataSet(entries1, ""); + + List entries2 = new ArrayList(); + entries2.add(new Entry(-1, 10)); + entries2.add(new Entry(10, 2)); + entries2.add(new Entry(20, 5)); + + ScatterDataSet set2 = new ScatterDataSet(entries2, ""); + + ScatterData data = new ScatterData(set1, set2); + + assertEquals(-2, data.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(50f, data.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(6, data.getEntryCount()); + + assertEquals(-1f, data.getXMin(), 0.01f); + assertEquals(21f, data.getXMax(), 0.01f); + + assertEquals(-2f, data.getYMin(), 0.01f); + assertEquals(50f, data.getYMax(), 0.01f); + + assertEquals(3, data.getMaxEntryCountSet().getEntryCount()); + + + // now add and remove values + data.addEntry(new Entry(-10, -10), 0); + + assertEquals(set1, data.getMaxEntryCountSet()); + assertEquals(4, data.getMaxEntryCountSet().getEntryCount()); + + assertEquals(-10f, data.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(50f, data.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(-10f, data.getXMin(), 0.01f); + assertEquals(21f, data.getXMax(), 0.01f); + + assertEquals(-10f, data.getYMin(), 0.01f); + assertEquals(50f, data.getYMax(), 0.01f); + + data.addEntry(new Entry(-100, 100), 0); + data.addEntry(new Entry(0, -100), 0); + + assertEquals(-100f, data.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(100f, data.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + // right axis will adapt left axis values if no right axis values are present + assertEquals(-100, data.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(100f, data.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + List entries3 = new ArrayList(); + entries3.add(new Entry(0, 200)); + entries3.add(new Entry(0, -50)); + + ScatterDataSet set3 = new ScatterDataSet(entries3, ""); + set3.setAxisDependency(YAxis.AxisDependency.RIGHT); + + data.addDataSet(set3); + + assertEquals(3, data.getDataSetCount()); + + assertEquals(-100f, data.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(100f, data.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(-50f, data.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(200f, data.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + } +} From 33b158147e346b23e3aaba37fe2b96823f65b60b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 6 Jun 2016 23:55:58 +0200 Subject: [PATCH 0974/1390] Minor fix in example --- .../xxmassdeveloper/mpchartexample/MultiLineChartActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 03ebedd57b..487fd4baa9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -196,7 +196,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { for (int i = 0; i < mSeekBarX.getProgress(); i++) { double val = (Math.random() * mSeekBarY.getProgress()) + 3; - values.add(new Entry((float) val, i)); + values.add(new Entry(i, (float) val)); } LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); From ae2d917fa75f91c635c9bc67a00b74ea1b42d9c2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 14:00:45 +0200 Subject: [PATCH 0975/1390] Refactoring, tests and fixes related to min and max calculation --- MPChartExample/build.gradle | 2 +- .../mikephil/charting/components/YAxis.java | 7 - .../mikephil/charting/data/BarDataSet.java | 20 +-- .../mikephil/charting/data/BubbleDataSet.java | 20 +-- .../mikephil/charting/data/CandleDataSet.java | 20 +-- .../mikephil/charting/data/ChartData.java | 135 +++++++++--------- .../mikephil/charting/data/DataSet.java | 39 ++--- .../mikephil/charting/test/ChartDataTest.java | 82 +++++++++++ .../mikephil/charting/test/DataSetTest.java | 8 ++ build.gradle | 2 +- 10 files changed, 179 insertions(+), 156 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index c0fe48d40c..dd8194aa12 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -38,7 +38,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index e2663dde6b..21dc5f7367 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -375,12 +375,5 @@ public void calculate(float dataMin, float dataMax) { // calc actual range this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); - -// // in case granularity is not customized, auto-calculate it -// if (!mCustomGranularity && mGranularityEnabled) { -// -// double granularity = Utils.granularity(mAxisRange, mLabelCount); -// this.mGranularity = (float) granularity; -// } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index f77a26e446..6cc820ceb4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -108,17 +108,13 @@ private void calcStackSize(List yVals) { @Override public void calcMinMax() { - if (mValues == null) - return; - - if (mValues.size() == 0) + if (mValues == null || mValues.isEmpty()) return; + mYMax = Float.MIN_VALUE; mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - + mXMax = Float.MIN_VALUE; mXMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; for (BarEntry e : mValues) { @@ -147,16 +143,6 @@ public void calcMinMax() { mXMax = e.getX(); } } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if(mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 3cb824f54d..6814adc8a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -31,17 +31,13 @@ public float getHighlightCircleWidth() { @Override public void calcMinMax() { - if (mValues == null) - return; - - if (mValues.size() == 0) + if (mValues == null || mValues.isEmpty()) return; + mYMax = Float.MIN_VALUE; mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - + mXMax = Float.MIN_VALUE; mXMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; // need chart width to guess this properly @@ -75,16 +71,6 @@ public void calcMinMax() { mMaxSize = size; } } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if(mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 2a10024e80..2331b3e589 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -102,17 +102,13 @@ public DataSet copy() { @Override public void calcMinMax() { - if (mValues == null) - return; - - if (mValues.size() == 0) + if (mValues == null || mValues.isEmpty()) return; + mYMax = Float.MIN_VALUE; mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - + mXMax = Float.MIN_VALUE; mXMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; for (CandleEntry e : mValues) { @@ -128,16 +124,6 @@ public void calcMinMax() { if (e.getX() > mXMax) mXMax = e.getX(); } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if(mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0b88010cbc..cea9befdb4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -24,28 +24,29 @@ public abstract class ChartData> { /** * maximum y-value in the value array across all axes */ - protected float mYMax = 0.0f; + protected float mYMax = -Float.MAX_VALUE; /** * the minimum y-value in the value array across all axes */ - protected float mYMin = 0.0f; + protected float mYMin = Float.MAX_VALUE; /** * maximum x-value in the value array */ - protected float mXMax = 0f; + protected float mXMax = -Float.MAX_VALUE; /** * minimum x-value in the value array */ - protected float mXMin = 0f; + protected float mXMin = Float.MAX_VALUE; - protected float mLeftAxisMax = Float.MIN_VALUE; + + protected float mLeftAxisMax = -Float.MAX_VALUE; protected float mLeftAxisMin = Float.MAX_VALUE; - protected float mRightAxisMax = Float.MIN_VALUE; + protected float mRightAxisMax = -Float.MAX_VALUE; protected float mRightAxisMin = Float.MAX_VALUE; @@ -125,68 +126,57 @@ public void notifyDataChanged() { */ public void calcMinMax() { - if (mDataSets == null || mDataSets.size() < 1) { - - mYMax = 0f; - mYMin = 0f; - - mXMax = 0f; - mXMin = 0f; - - } else { - - mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; + if (mDataSets == null) + return; - for (int i = 0; i < mDataSets.size(); i++) { + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; - T set = mDataSets.get(i); - calcMinMax(set); - } + for (T set : mDataSets) { + calcMinMax(set); + } - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } + mLeftAxisMax = -Float.MAX_VALUE; + mLeftAxisMin = Float.MAX_VALUE; + mRightAxisMax = -Float.MAX_VALUE; + mRightAxisMin = Float.MAX_VALUE; - // left axis - T firstLeft = getFirstLeft(); + // left axis + T firstLeft = getFirstLeft(); - if (firstLeft != null) { + if (firstLeft != null) { - mLeftAxisMax = firstLeft.getYMax(); - mLeftAxisMin = firstLeft.getYMin(); + mLeftAxisMax = firstLeft.getYMax(); + mLeftAxisMin = firstLeft.getYMin(); - for (IDataSet dataSet : mDataSets) { - if (dataSet.getAxisDependency() == AxisDependency.LEFT) { - if (dataSet.getYMin() < mLeftAxisMin) - mLeftAxisMin = dataSet.getYMin(); + for (IDataSet dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.LEFT) { + if (dataSet.getYMin() < mLeftAxisMin) + mLeftAxisMin = dataSet.getYMin(); - if (dataSet.getYMax() > mLeftAxisMax) - mLeftAxisMax = dataSet.getYMax(); - } + if (dataSet.getYMax() > mLeftAxisMax) + mLeftAxisMax = dataSet.getYMax(); } } + } - // right axis - T firstRight = getFirstRight(); + // right axis + T firstRight = getFirstRight(); - if (firstRight != null) { + if (firstRight != null) { - mRightAxisMax = firstRight.getYMax(); - mRightAxisMin = firstRight.getYMin(); + mRightAxisMax = firstRight.getYMax(); + mRightAxisMin = firstRight.getYMin(); - for (IDataSet dataSet : mDataSets) { - if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { - if (dataSet.getYMin() < mRightAxisMin) - mRightAxisMin = dataSet.getYMin(); + for (IDataSet dataSet : mDataSets) { + if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { + if (dataSet.getYMin() < mRightAxisMin) + mRightAxisMin = dataSet.getYMin(); - if (dataSet.getYMax() > mRightAxisMax) - mRightAxisMax = dataSet.getYMax(); - } + if (dataSet.getYMax() > mRightAxisMax) + mRightAxisMax = dataSet.getYMax(); } } } @@ -275,12 +265,12 @@ public float getYMax() { public float getYMax(AxisDependency axis) { if (axis == AxisDependency.LEFT) { - if (mLeftAxisMax == Float.MIN_VALUE) { + if (mLeftAxisMax == -Float.MAX_VALUE) { return mRightAxisMax; } else return mLeftAxisMax; } else { - if (mRightAxisMax == Float.MIN_VALUE) { + if (mRightAxisMax == -Float.MAX_VALUE) { return mLeftAxisMax; } else return mRightAxisMax; @@ -325,6 +315,11 @@ public int getYValCount() { return mValueCount; } + /** + * Returns all DataSet objects this ChartData object holds. + * + * @return + */ public List getDataSets() { return mDataSets; } @@ -578,23 +573,23 @@ public boolean removeEntry(Entry e, int dataSetIndex) { } /** - * Removes the Entry object at the given xIndex from the DataSet at the + * Removes the Entry object closest to the given DataSet at the * specified index. Returns true if an Entry was removed, false if no Entry * was found that meets the specified requirements. * - * @param xIndex + * @param xPos * @param dataSetIndex * @return */ - public boolean removeEntry(int xIndex, int dataSetIndex) { + public boolean removeEntry(float xPos, int dataSetIndex) { if (dataSetIndex >= mDataSets.size()) return false; IDataSet dataSet = mDataSets.get(dataSetIndex); - Entry e = dataSet.getEntryForXPos(xIndex); + Entry e = dataSet.getEntryForXPos(xPos); - if (e == null || e.getX() != xIndex) + if (e == null) return false; return removeEntry(e, dataSetIndex); @@ -658,13 +653,14 @@ public int[] getColors() { return colors; } + /** + * Returns the index of the provided DataSet in the DataSet array of this data object, or -1 if it does not exist. + * + * @param dataSet + * @return + */ public int getIndexOfDataSet(T dataSet) { - for (int i = 0; i < mDataSets.size(); i++) { - if (mDataSets.get(i) == dataSet) - return i; - } - - return -1; + return mDataSets.indexOf(dataSet); } /** @@ -678,7 +674,6 @@ public T getFirstLeft() { if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; } - return null; } @@ -693,7 +688,6 @@ public T getFirstRight() { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; } - return null; } @@ -840,12 +834,15 @@ public int getEntryCount() { } /** - * Returns the DataSet object with the maximum number of entries. + * Returns the DataSet object with the maximum number of entries or null if there are no DataSets. * * @return */ public T getMaxEntryCountSet() { + if (mDataSets == null || mDataSets.isEmpty()) + return null; + T max = mDataSets.get(0); for (T set : mDataSets) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 39beb6405f..0abdb49fdf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -22,22 +22,22 @@ public abstract class DataSet extends BaseDataSet { /** * maximum y-value in the value array */ - protected float mYMax = 0.0f; + protected float mYMax = -Float.MAX_VALUE; /** * minimum y-value in the value array */ - protected float mYMin = 0.0f; + protected float mYMin = Float.MAX_VALUE; /** * maximum x-value in the value array */ - protected float mXMax = 0.0f; + protected float mXMax = -Float.MAX_VALUE; /** * minimum x-value in the value array */ - protected float mXMin = 0.0f; + protected float mXMin = Float.MAX_VALUE; /** @@ -61,33 +61,16 @@ public DataSet(List values, String label) { @Override public void calcMinMax() { - if (mValues == null) - return; - - if (mValues.size() == 0) + if (mValues == null || mValues.isEmpty()) return; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; for (T e : mValues) { - - if (e != null && !Float.isNaN(e.getY())) { - calcMinMax(e); - } - } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if (mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; + calcMinMax(e); } } @@ -98,6 +81,9 @@ public void calcMinMax() { */ protected void calcMinMax(T e) { + if (e == null) + return; + if (e.getY() < mYMin) mYMin = e.getY(); @@ -225,8 +211,7 @@ public boolean addEntry(T e) { calcMinMax(e); // add the entry - values.add(e); - return true; + return values.add(e); } @Override diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java index 487fd1eac1..2fa1a12994 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java @@ -2,6 +2,8 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; @@ -11,6 +13,7 @@ import java.util.List; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; /** * Created by philipp on 06/06/16. @@ -91,5 +94,84 @@ public void testDynamicChartData() { assertEquals(-50f, data.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); assertEquals(200f, data.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + LineData lineData = new LineData(); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(), 0.01f); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + assertEquals(0, lineData.getDataSetCount()); + + List lineEntries1 = new ArrayList(); + lineEntries1.add(new Entry(10, 90)); + lineEntries1.add(new Entry(1000, 1000)); + + LineDataSet lineSet1 = new LineDataSet(lineEntries1, ""); + + lineData.addDataSet(lineSet1); + + assertEquals(1, lineData.getDataSetCount()); + assertEquals(2, lineSet1.getEntryCount()); + assertEquals(2, lineData.getEntryCount()); + + assertEquals(10, lineData.getXMin(), 0.01f); + assertEquals(1000f, lineData.getXMax(), 0.01f); + + assertEquals(90, lineData.getYMin(), 0.01f); + assertEquals(1000, lineData.getYMax(), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(1000f, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(1000, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + List lineEntries2 = new ArrayList(); + lineEntries2.add(new Entry(-1000, 2000)); + lineEntries2.add(new Entry(2000, -3000)); + + Entry e = new Entry(-1000, 2500); + lineEntries2.add(e); + + LineDataSet lineSet2 = new LineDataSet(lineEntries2, ""); + lineSet2.setAxisDependency(YAxis.AxisDependency.RIGHT); + + lineData.addDataSet(lineSet2); + + assertEquals(2, lineData.getDataSetCount()); + assertEquals(3, lineSet2.getEntryCount()); + assertEquals(5, lineData.getEntryCount()); + + assertEquals(-1000, lineData.getXMin(), 0.01f); + assertEquals(2000, lineData.getXMax(), 0.01f); + + assertEquals(-3000, lineData.getYMin(), 0.01f); + assertEquals(2500, lineData.getYMax(), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(1000f, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(-3000, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(2500, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + assertTrue(lineData.removeEntry(e, 1)); + + assertEquals(-1000, lineData.getXMin(), 0.01f); + assertEquals(2000, lineData.getXMax(), 0.01f); + + assertEquals(-3000, lineData.getYMin(), 0.01f); + assertEquals(2000, lineData.getYMax(), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(1000f, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(-3000, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(2000, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 2d2d2f7555..4ade7977b1 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -45,6 +45,14 @@ public void testCalcMinMax() { assertEquals(10f, set.getYMax(), 0.01f); assertEquals(4, set.getEntryCount()); + + set.removeEntry(3); + + assertEquals(10f, set.getXMin(), 0.01f); + assertEquals(21, set.getXMax(), 0.01f); + + assertEquals(2f, set.getYMin(), 0.01f); + assertEquals(10f, set.getYMax(), 0.01f); } @Test diff --git a/build.gradle b/build.gradle index 564d957cc5..2bda1ed031 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From 72b4948aa3cbfc55eb02952160e6b2e3d3541147 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 16:55:48 +0200 Subject: [PATCH 0976/1390] Cleanup of chartdata object --- .../mikephil/charting/charts/Chart.java | 11 +--- .../mikephil/charting/charts/PieChart.java | 8 +-- .../charting/charts/PieRadarChartBase.java | 5 ++ .../charting/charts/ScatterChart.java | 20 +++--- .../mikephil/charting/data/ChartData.java | 64 ------------------- ...arLineScatterCandleBubbleDataProvider.java | 1 - .../dataprovider/ChartInterface.java | 2 + .../charting/renderer/BarChartRenderer.java | 9 +-- .../renderer/BubbleChartRenderer.java | 3 +- .../renderer/CandleStickChartRenderer.java | 3 +- .../charting/renderer/DataRenderer.java | 7 ++ .../renderer/HorizontalBarChartRenderer.java | 7 +- .../charting/renderer/LineChartRenderer.java | 3 +- .../renderer/ScatterChartRenderer.java | 3 +- .../mikephil/charting/test/ChartDataTest.java | 36 ++++++++++- 15 files changed, 73 insertions(+), 109 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 359d2228c8..ddcb1f8485 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -354,7 +354,7 @@ public boolean isEmpty() { return true; else { - if (mData.getYValCount() <= 0) + if (mData.getEntryCount() <= 0) return true; else return false; @@ -1028,15 +1028,6 @@ public float getXRange() { return mXAxis.mAxisRange; } - /** - * Returns the total number of (y) values the chart holds (across all DataSets). - * - * @return - */ - public int getValueCount() { - return mData.getYValCount(); - } - /** * Returns the center point of the chart (the whole View) in pixels. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index ba8e37c8ea..7440ca3141 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -161,7 +161,6 @@ public void calculateOffsets() { @Override protected void calcMinMax() { - calcAngles(); } @@ -202,8 +201,10 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { */ private void calcAngles() { - mDrawAngles = new float[mData.getYValCount()]; - mAbsoluteAngles = new float[mData.getYValCount()]; + int entryCount = mData.getEntryCount(); + + mDrawAngles = new float[entryCount]; + mAbsoluteAngles = new float[entryCount]; float yValueSum = mData.getYValueSum(); @@ -653,5 +654,4 @@ protected void onDetachedFromWindow() { } super.onDetachedFromWindow(); } - } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index ea18e39ee7..749346e38b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -69,6 +69,11 @@ protected void calcMinMax() { //mXAxis.mAxisRange = mData.getXVals().size() - 1; } + @Override + public int getMaxVisibleCount() { + return mData.getEntryCount(); + } + @Override public boolean onTouchEvent(MotionEvent event) { // use the pie- and radarchart listener own listener diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 292568a6b3..00043e3088 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -44,16 +44,16 @@ protected void init() { mXAxis.mAxisMinimum = -0.5f; } - @Override - protected void calcMinMax() { - super.calcMinMax(); - - if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) - mXAxis.mAxisRange = 1; - - mXAxis.mAxisMaximum += 0.5f; - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - } +// @Override +// protected void calcMinMax() { +// super.calcMinMax(); +// +// if (mXAxis.mAxisRange == 0 && mData.getEntryCount() > 0) +// mXAxis.mAxisRange = 1; +// +// mXAxis.mAxisMaximum += 0.5f; +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// } /** * Returns all possible predefined ScatterShapes. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index cea9befdb4..2e2d1a91c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -50,17 +50,6 @@ public abstract class ChartData> { protected float mRightAxisMin = Float.MAX_VALUE; - /** - * total number of values (entries) across all DataSet objects - */ - private int mValueCount = 0; - - /** - * contains the maximum length (in characters) an entry in the x-vals array - * has - */ - private float mXValMaximumLength = 0; - /** * array that holds all DataSets the ChartData object represents */ @@ -107,8 +96,6 @@ public ChartData(List sets) { * value count and sum */ protected void init() { - - calcYValueCount(); calcMinMax(); } @@ -182,28 +169,6 @@ public void calcMinMax() { } } - /** - * Calculates the total number of y-values across all DataSets the ChartData - * represents. - * - * @return - */ - protected void calcYValueCount() { - - mValueCount = 0; - - if (mDataSets == null) - return; - - int count = 0; - - for (int i = 0; i < mDataSets.size(); i++) { - count += mDataSets.get(i).getEntryCount(); - } - - mValueCount = count; - } - /** ONLY GETTERS AND SETTERS BELOW THIS */ /** @@ -295,26 +260,6 @@ public float getXMax() { return mXMax; } - /** - * returns the maximum length (in characters) across all values in the - * x-vals array - * - * @return - */ - public float getXValMaximumLength() { - return mXValMaximumLength; - } - - /** - * Returns the total number of y-values across all DataSet objects the this - * object represents. - * - * @return - */ - public int getYValCount() { - return mValueCount; - } - /** * Returns all DataSet objects this ChartData object holds. * @@ -418,8 +363,6 @@ public void addDataSet(T d) { if (d == null) return; - mValueCount += d.getEntryCount(); - calcMinMax(d); mDataSets.add(d); @@ -441,9 +384,6 @@ public boolean removeDataSet(T d) { // if a DataSet was removed if (removed) { - - mValueCount -= d.getEntryCount(); - calcMinMax(); } @@ -484,8 +424,6 @@ public void addEntry(Entry e, int dataSetIndex) { calcMinMax(e, set.getAxisDependency()); - mValueCount += 1; - } else { Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); } @@ -562,8 +500,6 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = set.removeEntry(e); if (removed) { - mValueCount -= 1; - calcMinMax(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java index 0628356991..68beeb8d62 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java @@ -7,7 +7,6 @@ public interface BarLineScatterCandleBubbleDataProvider extends ChartInterface { Transformer getTransformer(AxisDependency axis); - int getMaxVisibleCount(); boolean isInverted(AxisDependency axis); float getLowestVisibleX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 6660e2e4fb..1083e34863 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -65,4 +65,6 @@ public interface ChartInterface { ValueFormatter getDefaultValueFormatter(); ChartData getData(); + + int getMaxVisibleCount(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 82f91ed847..9ec7ad3aab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -3,9 +3,7 @@ import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; @@ -184,7 +182,7 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHa public void drawValues(Canvas c) { // if values are drawn - if (passesCheck()) { + if (isDrawingValuesAllowed(mChart)) { List dataSets = mChart.getBarData().getDataSets(); @@ -410,11 +408,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } - protected boolean passesCheck() { - return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() - * mViewPortHandler.getScaleX(); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index a1d9521a55..47542dc591 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -132,8 +132,7 @@ public void drawValues(Canvas c) { return; // if values are drawn - if (bubbleData.getYValCount() < (int) (Math.ceil((float) (mChart.getMaxVisibleCount()) - * mViewPortHandler.getScaleX()))) { + if (isDrawingValuesAllowed(mChart)) { final List dataSets = bubbleData.getDataSets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 39630d8978..3720e61153 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -271,8 +271,7 @@ else if (open < close) public void drawValues(Canvas c) { // if values are drawn - if (mChart.getCandleData().getYValCount() < mChart.getMaxVisibleCount() - * mViewPortHandler.getScaleX()) { + if (isDrawingValuesAllowed(mChart)) { List dataSets = mChart.getCandleData().getDataSets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index f4a88fe08d..c1822a7c05 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -8,9 +8,11 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -65,6 +67,11 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { mHighlightPaint.setColor(Color.rgb(255, 187, 115)); } + protected boolean isDrawingValuesAllowed(ChartInterface chart) { + return chart.getData().getEntryCount() < chart.getMaxVisibleCount() + * mViewPortHandler.getScaleX(); + } + /** * Returns the Paint object this renderer uses for drawing the values * (value-text). diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 21e386e19c..3952b90d90 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -100,7 +101,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { @Override public void drawValues(Canvas c) { // if values are drawn - if (passesCheck()) { + if (isDrawingValuesAllowed(mChart)) { List dataSets = mChart.getBarData().getDataSets(); @@ -291,8 +292,8 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHa } @Override - protected boolean passesCheck() { - return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() + protected boolean isDrawingValuesAllowed(ChartInterface chart) { + return chart.getData().getEntryCount() < chart.getMaxVisibleCount() * mViewPortHandler.getScaleY(); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 7135f569a3..276d2f7971 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -543,8 +543,7 @@ private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { @Override public void drawValues(Canvas c) { - if (mChart.getLineData().getYValCount() < mChart.getMaxVisibleCount() - * mViewPortHandler.getScaleX()) { + if (isDrawingValuesAllowed(mChart)) { List dataSets = mChart.getLineData().getDataSets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index ff876208f2..c3583c6579 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -306,8 +306,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { public void drawValues(Canvas c) { // if values are drawn - if (mChart.getScatterData().getYValCount() < mChart.getMaxVisibleCount() - * mViewPortHandler.getScaleX()) { + if (isDrawingValuesAllowed(mChart)) { List dataSets = mChart.getScatterData().getDataSets(); diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java index 2fa1a12994..ae464eefd0 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ChartDataTest.java @@ -13,6 +13,7 @@ import java.util.List; import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; /** @@ -52,7 +53,6 @@ public void testDynamicChartData() { assertEquals(3, data.getMaxEntryCountSet().getEntryCount()); - // now add and remove values data.addEntry(new Entry(-10, -10), 0); @@ -173,5 +173,39 @@ public void testDynamicChartData() { assertEquals(-3000, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); assertEquals(2000, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + assertEquals(2, lineData.getDataSetCount()); + assertTrue(lineData.removeDataSet(lineSet2)); + assertEquals(1, lineData.getDataSetCount()); + + assertEquals(10, lineData.getXMin(), 0.01f); + assertEquals(1000, lineData.getXMax(), 0.01f); + + assertEquals(90, lineData.getYMin(), 0.01f); + assertEquals(1000, lineData.getYMax(), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(1000f, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(90, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(1000, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + assertTrue(lineData.removeDataSet(lineSet1)); + assertEquals(0, lineData.getDataSetCount()); + + assertEquals(Float.MAX_VALUE, lineData.getXMin(), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getXMax(), 0.01f); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(), 0.01f); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(YAxis.AxisDependency.LEFT), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(YAxis.AxisDependency.LEFT), 0.01f); + + assertEquals(Float.MAX_VALUE, lineData.getYMin(YAxis.AxisDependency.RIGHT), 0.01f); + assertEquals(-Float.MAX_VALUE, lineData.getYMax(YAxis.AxisDependency.RIGHT), 0.01f); + + assertFalse(lineData.removeDataSet(lineSet1)); + assertFalse(lineData.removeDataSet(lineSet2)); } } From 4367fbb8f6d77ac28b77e669b42f297edb2358b6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 16:57:13 +0200 Subject: [PATCH 0977/1390] Minor fixes --- .../mikephil/charting/charts/CandleStickChart.java | 14 +++++++------- .../mikephil/charting/charts/ScatterChart.java | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java index 87008d4a83..26fb82043f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java @@ -35,13 +35,13 @@ protected void init() { mXAxis.mAxisMinimum = -0.5f; } - @Override - protected void calcMinMax() { - super.calcMinMax(); - - mXAxis.mAxisMaximum += 0.5f; - mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); - } +// @Override +// protected void calcMinMax() { +// super.calcMinMax(); +// +// mXAxis.mAxisMaximum += 0.5f; +// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); +// } @Override public CandleData getCandleData() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 00043e3088..9624a64d34 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -41,7 +41,7 @@ protected void init() { super.init(); mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); - mXAxis.mAxisMinimum = -0.5f; +// mXAxis.mAxisMinimum = -0.5f; } // @Override From 1ff1c8fcfa7db2fea5a1e94a03a50f130673f44f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 16:59:22 +0200 Subject: [PATCH 0978/1390] Documentation --- .../java/com/github/mikephil/charting/data/ChartData.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 2e2d1a91c8..0938fb1f11 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -55,10 +55,18 @@ public abstract class ChartData> { */ protected List mDataSets; + /** + * Default constructor. + */ public ChartData() { mDataSets = new ArrayList(); } + /** + * Constructor taking single or multiple DataSet objects. + * + * @param dataSets + */ public ChartData(T... dataSets) { mDataSets = arrayToList(dataSets); init(); From 42ceaa9aa20a115dda316150d0e887eb66487cfd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 21:48:26 +0200 Subject: [PATCH 0979/1390] Work on line approximation --- .../charting/charts/BarLineChartBase.java | 2 - .../charting/charts/CombinedChart.java | 24 +- .../charting/data/filter/Approximator.java | 300 ++++-------------- .../charting/test/ApproximatorTest.java | 43 +++ 4 files changed, 115 insertions(+), 254 deletions(-) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/ApproximatorTest.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index cc4a14bb9f..a4cf5b3b0b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -18,8 +18,6 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.ChartHighlighter; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index c40b4a242c..f6a7c0c814 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -28,10 +28,10 @@ public class CombinedChart extends BarLineChartBase implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider, BubbleDataProvider { - /** - * flag that enables or disables the highlighting arrow - */ - private boolean mDrawHighlightArrow = false; +// /** +// * flag that enables or disables the highlighting arrow +// */ +// private boolean mDrawHighlightArrow = false; /** * if set to true, all values are drawn above their bars, instead of below @@ -167,14 +167,14 @@ public boolean isDrawValueAboveBarEnabled() { return mDrawValueAboveBar; } - /** - * set this to true to draw the highlightning arrow - * - * @param enabled - */ - public void setDrawHighlightArrow(boolean enabled) { - mDrawHighlightArrow = enabled; - } +// /** +// * set this to true to draw the highlightning arrow +// * +// * @param enabled +// */ +// public void setDrawHighlightArrow(boolean enabled) { +// mDrawHighlightArrow = enabled; +// } /** * If set to true, all values are drawn above their bars, instead of below diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java index cbc630c562..920da8d212 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java @@ -1,282 +1,102 @@ package com.github.mikephil.charting.data.filter; -import com.github.mikephil.charting.data.Entry; +import android.annotation.TargetApi; +import android.os.Build; -import java.util.ArrayList; -import java.util.List; +import java.util.Arrays; /** * Implemented according to Wiki-Pseudocode {@link} * http://en.wikipedia.org/wiki/Ramer�Douglas�Peucker_algorithm - * + * * @author Philipp Baldauf & Phliipp Jahoda */ public class Approximator { - /** the type of filtering algorithm to use */ - private ApproximatorType mType = ApproximatorType.DOUGLAS_PEUCKER; + @TargetApi(Build.VERSION_CODES.GINGERBREAD) + public float[] reduceWithDouglasPeucker(float[] points, float tolerance) { - /** the tolerance to be filtered with */ - private double mTolerance = 0; + int greatestIndex = 0; + float greatestDistance = 0f; - private float mScaleRatio = 1f; - private float mDeltaRatio = 1f; + Line line = new Line(points[0], points[1], points[points.length - 2], points[points.length - 1]); - /** - * array that contains "true" on all indices that will be kept after - * filtering - */ - private boolean[] keep; - - /** enums for the different types of filtering algorithms */ - public enum ApproximatorType { - NONE, DOUGLAS_PEUCKER - } - - /** - * Initializes the approximator with type NONE - */ - public Approximator() { - this.mType = ApproximatorType.NONE; - } - - /** - * Initializes the approximator with the given type and tolerance. If - * toleranec <= 0, no filtering will be done. - * - * @param type - */ - public Approximator(ApproximatorType type, double tolerance) { - setup(type, tolerance); - } - - /** - * sets type and tolerance, if tolerance <= 0, no filtering will be done - * - * @param type - * @param tolerance - */ - public void setup(ApproximatorType type, double tolerance) { - mType = type; - mTolerance = tolerance; - } - - /** - * sets the tolerance for the Approximator. When using the - * Douglas-Peucker-Algorithm, the tolerance is an angle in degrees, that - * will trigger the filtering. - */ - public void setTolerance(double tolerance) { - mTolerance = tolerance; - } - - /** - * Sets the filtering algorithm that should be used. - * - * @param type - */ - public void setType(ApproximatorType type) { - this.mType = type; - } - - /** - * Sets the ratios for x- and y-axis, as well as the ratio of the scale - * levels - * - * @param deltaRatio - * @param scaleRatio - */ - public void setRatios(float deltaRatio, float scaleRatio) { - mDeltaRatio = deltaRatio; - mScaleRatio = scaleRatio; - } - - /** - * Filters according to type. Uses the pre set set tolerance - * - * @param points the points to filter - * @return - */ - public List filter(List points) { - return filter(points, mTolerance); - } - - /** - * Filters according to type. - * - * @param points the points to filter - * @param tolerance the angle in degrees that will trigger the filtering - * @return - */ - public List filter(List points, double tolerance) { - - if (tolerance <= 0) - return points; + for (int i = 2; i < points.length - 2; i += 2) { - keep = new boolean[points.size()]; + float distance = line.distance(points[i], points[i + 1]); - switch (mType) { - case DOUGLAS_PEUCKER: - return reduceWithDouglasPeuker(points, tolerance); - case NONE: - return points; - default: - return points; + if (distance > greatestDistance) { + greatestDistance = distance; + greatestIndex = i; + } } - } - /** - * uses the douglas peuker algorithm to reduce the given List of - * entries - * - * @param entries - * @param epsilon - * @return - */ - private List reduceWithDouglasPeuker(List entries, double epsilon) { - // if a shape has 2 or less points it cannot be reduced - if (epsilon <= 0 || entries.size() < 3) { - return entries; - } + if (greatestDistance > tolerance) { - // first and last always stay - keep[0] = true; - keep[entries.size() - 1] = true; + float[] reduced1 = reduceWithDouglasPeucker(Arrays.copyOfRange(points, 0, greatestIndex + 2), tolerance); + float[] reduced2 = reduceWithDouglasPeucker(Arrays.copyOfRange(points, greatestIndex, points.length), + tolerance); - // first and last entry are entry point to recursion - algorithmDouglasPeucker(entries, epsilon, 0, entries.size() - 1); + float[] result1 = reduced1; + float[] result2 = Arrays.copyOfRange(reduced2, 2, reduced2.length); - // create a new array with series, only take the kept ones - List reducedEntries = new ArrayList(); - for (int i = 0; i < entries.size(); i++) { - if (keep[i]) { - Entry curEntry = entries.get(i); - reducedEntries.add(new Entry(curEntry.getY(), curEntry.getX())); - } + return concat(result1, result2); + } else { + return line.getPoints(); } - return reducedEntries; } /** - * apply the Douglas-Peucker-Reduction to an List of Entry with a given - * epsilon (tolerance) - * - * @param entries - * @param epsilon as y-value - * @param start - * @param end + * Combine arrays. + * + * @param arrays + * @return */ - private void algorithmDouglasPeucker(List entries, double epsilon, int start, - int end) { - if (end <= start + 1) { - // recursion finished - return; + float[] concat(float[]... arrays) { + int length = 0; + for (float[] array : arrays) { + length += array.length; } - - // find the greatest distance between start and endpoint - int maxDistIndex = 0; - double distMax = 0; - - Entry firstEntry = entries.get(start); - Entry lastEntry = entries.get(end); - - for (int i = start + 1; i < end; i++) { - double dist = calcAngleBetweenLines(firstEntry, lastEntry, firstEntry, entries.get(i)); - - // keep the point with the greatest distance - if (dist > distMax) { - distMax = dist; - maxDistIndex = i; + float[] result = new float[length]; + int pos = 0; + for (float[] array : arrays) { + for (float element : array) { + result[pos] = element; + pos++; } } - - // Log.i("maxangle", "" + distMax); - - if (distMax > epsilon) { - // keep max dist point - keep[maxDistIndex] = true; - - // recursive call - algorithmDouglasPeucker(entries, epsilon, start, maxDistIndex); - algorithmDouglasPeucker(entries, epsilon, maxDistIndex, end); - } // else don't keep the point... - } - - /** - * calculate the distance between a line between two entries and an entry - * (point) - * - * @param startEntry line startpoint - * @param endEntry line endpoint - * @param entryPoint the point to which the distance is measured from the - * line - * @return - */ - public double calcPointToLineDistance(Entry startEntry, Entry endEntry, Entry entryPoint) { - - float xDiffEndStart = (float) endEntry.getX() - (float) startEntry.getX(); - float xDiffEntryStart = (float) entryPoint.getX() - (float) startEntry.getX(); - - double normalLength = Math.sqrt((xDiffEndStart) - * (xDiffEndStart) - + (endEntry.getY() - startEntry.getY()) - * (endEntry.getY() - startEntry.getY())); - return Math.abs((xDiffEntryStart) - * (endEntry.getY() - startEntry.getY()) - - (entryPoint.getY() - startEntry.getY()) - * (xDiffEndStart)) - / normalLength; + return result; } - /** - * Calculates the angle between two given lines. The provided Entry objects - * mark the starting and end points of the lines. - * - * @param start1 - * @param end1 - * @param start2 - * @param end2 - * @return - */ - public double calcAngleBetweenLines(Entry start1, Entry end1, Entry start2, Entry end2) { + private class Line { - double angle1 = calcAngleWithRatios(start1, end1); - double angle2 = calcAngleWithRatios(start2, end2); + private float[] points; - return Math.abs(angle1 - angle2); - } + private float sxey; + private float exsy; - /** - * calculates the angle between two Entries (points) in the chart taking - * ratios into consideration - * - * @param p1 - * @param p2 - * @return - */ - public double calcAngleWithRatios(Entry p1, Entry p2) { + private float dx; + private float dy; - float dx = p2.getX() * mDeltaRatio - p1.getX() * mDeltaRatio; - float dy = p2.getY() * mScaleRatio - p1.getY() * mScaleRatio; - double angle = Math.atan2(dy, dx) * 180.0 / Math.PI; + private float length; - return angle; - } + public Line(float x1, float y1, float x2, float y2) { + dx = x1 - x2; + dy = y1 - y2; + sxey = x1 * y2; + exsy = x2 * y1; + length = (float) Math.sqrt(dx * dx + dy * dy); - /** - * calculates the angle between two Entries (points) in the chart - * - * @param p1 - * @param p2 - * @return - */ - public double calcAngle(Entry p1, Entry p2) { + points = new float[]{x1, y1, x2, y2}; + } - float dx = p2.getX() - p1.getX(); - float dy = p2.getY() - p1.getY(); - double angle = Math.atan2(dy, dx) * 180.0 / Math.PI; + float distance(float x, float y) { + return Math.abs(dy * x - dx * y + sxey - exsy) / length; + } - return angle; + public float[] getPoints() { + return points; + } } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ApproximatorTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ApproximatorTest.java new file mode 100644 index 0000000000..784c290ceb --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ApproximatorTest.java @@ -0,0 +1,43 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.filter.Approximator; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.Assert.assertEquals; + +/** + * Created by philipp on 07/06/16. + */ +public class ApproximatorTest { + + @Test + public void testApproximation() { + + float[] points = new float[]{ + 10, 20, + 20, 30, + 25, 25, + 30, 28, + 31, 31, + 33, 33, + 40, 40, + 44, 40, + 48, 23, + 50, 20, + 55, 20, + 60, 25}; + + assertEquals(24, points.length); + + Approximator a = new Approximator(); + + float[] reduced = a.reduceWithDouglasPeucker(points, 2); + + assertEquals(18, reduced.length); + } +} From f927517bea36a2471b31fd2abffc7b196859c5f0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 21:58:44 +0200 Subject: [PATCH 0980/1390] Comment cleanup --- .../mikephil/charting/charts/BubbleChart.java | 27 --------------- .../charting/charts/CandleStickChart.java | 8 ----- .../charting/charts/CombinedChart.java | 31 ----------------- .../charting/charts/HorizontalBarChart.java | 34 ------------------- .../mikephil/charting/charts/LineChart.java | 8 ----- .../charting/charts/ScatterChart.java | 20 +++-------- .../charting/data/filter/Approximator.java | 2 +- .../mikephil/charting/renderer/Renderer.java | 18 ---------- 8 files changed, 5 insertions(+), 143 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java index a0681e652c..58532d2084 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java @@ -38,33 +38,6 @@ protected void init() { mRenderer = new BubbleChartRenderer(this, mAnimator, mViewPortHandler); } -// @Override -// protected void calcMinMax() { -// super.calcMinMax(); -// -// if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) -// mXAxis.mAxisRange = 1; -// -// mXAxis.mAxisMinimum = -0.5f; -// mXAxis.mAxisMaximum = (float) mData.getXValCount() - 0.5f; -// -// if (mRenderer != null) { -// for (IBubbleDataSet set : mData.getDataSets()) { -// -// final float xmin = set.getXMin(); -// final float xmax = set.getXMax(); -// -// if (xmin < mXAxis.mAxisMinimum) -// mXAxis.mAxisMinimum = xmin; -// -// if (xmax > mXAxis.mAxisMaximum) -// mXAxis.mAxisMaximum = xmax; -// } -// } -// -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); -// } - public BubbleData getBubbleData() { return mData; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java index 26fb82043f..029a2bb490 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java @@ -35,14 +35,6 @@ protected void init() { mXAxis.mAxisMinimum = -0.5f; } -// @Override -// protected void calcMinMax() { -// super.calcMinMax(); -// -// mXAxis.mAxisMaximum += 0.5f; -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); -// } - @Override public CandleData getCandleData() { return mData; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index f6a7c0c814..b1259b683a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -82,37 +82,6 @@ protected void init() { // mViewPortHandler); } -// @Override -// protected void calcMinMax() { -// super.calcMinMax(); -// -// if (getBarData() != null || getCandleData() != null || getBubbleData() != null) { -// mXAxis.mAxisMinimum = -0.5f; -// mXAxis.mAxisMaximum = mData.getXVals().size() - 0.5f; -// -// if (getBubbleData() != null) { -// -// for (IBubbleDataSet set : getBubbleData().getDataSets()) { -// -// final float xmin = set.getXMin(); -// final float xmax = set.getXMax(); -// -// if (xmin < mXAxis.mAxisMinimum) -// mXAxis.mAxisMinimum = xmin; -// -// if (xmax > mXAxis.mAxisMaximum) -// mXAxis.mAxisMaximum = xmax; -// } -// } -// } -// -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); -// -// if (mXAxis.mAxisRange == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { -// mXAxis.mAxisRange = 1.f; -// } -// } - @Override public void setData(CombinedData data) { mData = null; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index e8265af86d..a7a1cdf687 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -201,38 +201,4 @@ public float getHighestVisibleX() { mViewPortHandler.contentTop()); return (float) Math.min(mXAxis.mAxisMaximum, pos.y); } - -// /** -// * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. -// * -// * @return -// */ -// @Override -// public float getLowestVisibleX() { -// -// float step = mData.getDataSetCount(); -// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); -// -// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; -// -// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); -// return (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); -// } -// -// /** -// * Returns the highest x-index (value on the x-axis) that is still visible on the chart. -// * -// * @return -// */ -// @Override -// public float getHighestVisibleX() { -// -// float step = mData.getDataSetCount(); -// float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); -// -// float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() }; -// -// getTransformer(AxisDependency.LEFT).pixelsToValue(pts); -// return ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); -// } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java index 71acbb8d01..c96926017f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java @@ -33,14 +33,6 @@ protected void init() { mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); } - -// @Override -// protected void calcMinMax() { -// super.calcMinMax(); -// -// if (mXAxis.mAxisRange == 0 && mData.getYValCount() > 0) -// mXAxis.mAxisRange = 1; -// } @Override public LineData getLineData() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 9624a64d34..25fdadae55 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -12,7 +12,7 @@ * The ScatterChart. Draws dots, triangles, squares and custom shapes into the * Chart-View. CIRCLE and SCQUARE offer the best performance, TRIANGLE has the * worst performance. - * + * * @author Philipp Jahoda */ public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { @@ -41,32 +41,20 @@ protected void init() { super.init(); mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); -// mXAxis.mAxisMinimum = -0.5f; } -// @Override -// protected void calcMinMax() { -// super.calcMinMax(); -// -// if (mXAxis.mAxisRange == 0 && mData.getEntryCount() > 0) -// mXAxis.mAxisRange = 1; -// -// mXAxis.mAxisMaximum += 0.5f; -// mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); -// } - /** * Returns all possible predefined ScatterShapes. - * + * * @return */ public static ScatterShape[] getAllPossibleShapes() { - return new ScatterShape[] { + return new ScatterShape[]{ ScatterShape.SQUARE, ScatterShape.CIRCLE, ScatterShape.TRIANGLE, ScatterShape.CROSS }; } public ScatterData getScatterData() { return mData; - }; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java index 920da8d212..542188e602 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/Approximator.java @@ -91,7 +91,7 @@ public Line(float x1, float y1, float x2, float y2) { points = new float[]{x1, y1, x2, y2}; } - float distance(float x, float y) { + public float distance(float x, float y) { return Math.abs(dy * x - dx * y + sxey - exsy) / length; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java index 337bb54061..90f49683ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/Renderer.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.renderer; -import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -19,21 +18,4 @@ public abstract class Renderer { public Renderer(ViewPortHandler viewPortHandler) { this.mViewPortHandler = viewPortHandler; } - - /** - * Returns true if the specified value fits in between the provided min - * and max bounds, false if not. - * - * @param val - * @param min - * @param max - * @return - */ - protected boolean fitsBounds(float val, float min, float max) { - - if (val < min || val > max) - return false; - else - return true; - } } From 5a4b6f1532282ef9338bbadbe6cce78e6cfa43ba Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 23:20:06 +0200 Subject: [PATCH 0981/1390] Fixes related to combined chart and refinement of combined chart example --- .../mpchartexample/CombinedChartActivity.java | 55 ++++++++++++++----- .../renderer/CandleStickChartRenderer.java | 31 ++++++----- 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index e9b5a6e81b..007f36c837 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -2,6 +2,7 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; +import android.graphics.Paint; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -9,6 +10,8 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -27,6 +30,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -50,12 +54,16 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setBackgroundColor(Color.WHITE); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); - + // draw bars behind lines mChart.setDrawOrder(new DrawOrder[]{ DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); + Legend l = mChart.getLegend(); + l.setWordWrapEnabled(true); + l.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER); + YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) @@ -66,14 +74,29 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); + xAxis.setAxisMinValue(0f); + xAxis.setGranularity(1f); + xAxis.setValueFormatter(new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mMonths[(int) value % mMonths.length]; + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); CombinedData data = new CombinedData(); data.setData(generateLineData()); data.setData(generateBarData()); -// data.setData(generateBubbleData()); -// data.setData(generateScatterData()); -// data.setData(generateCandleData()); + data.setData(generateBubbleData()); + data.setData(generateScatterData()); + data.setData(generateCandleData()); + + xAxis.setAxisMaxValue(data.getXMax() + 0.25f); mChart.setData(data); mChart.invalidate(); @@ -86,7 +109,7 @@ private LineData generateLineData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new Entry(index, getRandom(15, 10))); + entries.add(new Entry(index + 0.5f, getRandom(15, 5))); LineDataSet set = new LineDataSet(entries, "Line DataSet"); set.setColor(Color.rgb(240, 238, 70)); @@ -114,7 +137,7 @@ private BarData generateBarData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(index, getRandom(15, 30))); + entries.add(new BarEntry(index + 0.5f, getRandom(25, 25))); BarDataSet set = new BarDataSet(entries, "Bar DataSet"); set.setColor(Color.rgb(60, 220, 78)); @@ -133,11 +156,11 @@ protected ScatterData generateScatterData() { ArrayList entries = new ArrayList(); - for (int index = 0; index < itemcount; index++) - entries.add(new Entry(index, getRandom(20, 15))); + for (float index = 0; index < itemcount; index += 0.5f) + entries.add(new Entry(index + 0.25f, getRandom(10, 55))); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); - set.setColor(Color.GREEN); + set.setColors(ColorTemplate.MATERIAL_COLORS); set.setScatterShapeSize(7.5f); set.setDrawValues(false); set.setValueTextSize(10f); @@ -152,11 +175,12 @@ protected CandleData generateCandleData() { ArrayList entries = new ArrayList(); - for (int index = 0; index < itemcount; index++) - entries.add(new CandleEntry(index, 20f, 10f, 13f, 17f)); + for (int index = 0; index < itemcount; index += 2) + entries.add(new CandleEntry(index + 1f, 90, 70, 85, 75f)); CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); - set.setColor(Color.rgb(80, 80, 80)); + set.setDecreasingColor(Color.rgb(142, 150, 175)); + set.setShadowColor(Color.DKGRAY); set.setBarSpace(0.3f); set.setValueTextSize(10f); set.setDrawValues(false); @@ -164,7 +188,7 @@ protected CandleData generateCandleData() { return d; } - + protected BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); @@ -172,8 +196,9 @@ protected BubbleData generateBubbleData() { ArrayList entries = new ArrayList(); for (int index = 0; index < itemcount; index++) { - float rnd = getRandom(20, 30); - entries.add(new BubbleEntry(index, rnd, rnd)); + float y = getRandom(10, 105); + float size = getRandom(50, 105); + entries.add(new BubbleEntry(index + 0.5f, y, size)); } BubbleDataSet set = new BubbleDataSet(entries, "Bubble DataSet"); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 3720e61153..998668e863 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -56,8 +56,6 @@ public void drawData(Canvas c) { @SuppressWarnings("ResourceAsColor") protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { - int entryCount = dataSet.getEntryCount(); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); @@ -71,26 +69,22 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { CandleEntry entryFrom = dataSet.getEntryForXPos(lowX, DataSet.Rounding.DOWN); CandleEntry entryTo = dataSet.getEntryForXPos(highX, DataSet.Rounding.UP); - int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = dataSet.getEntryIndex(entryTo); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); // draw the body - for (int j = minx, - count = (int) Math.ceil((maxx - minx) * phaseX + (float)minx); - j < count; - j++) { + for (int j = minx; j <= maxx * phaseX; j++) { // get the entry CandleEntry e = dataSet.getEntryForIndex(j); - final float xPos = e.getX(); - - if (xPos < minx || xPos >= maxx) + if(e == null) continue; + final float xPos = e.getX(); + final float open = e.getOpen(); final float close = e.getClose(); final float high = e.getHigh(); @@ -287,8 +281,14 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - int minx = Math.max((int) mChart.getLowestVisibleX(), 0); - int maxx = Math.min((int) mChart.getHighestVisibleX() + 1, dataSet.getEntryCount()); + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + CandleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + CandleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = dataSet.getEntryIndex(entryTo); float[] positions = trans.generateTransformedValuesCandle( dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -308,7 +308,8 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); - drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet + .getValueTextColor(j / 2)); } } } From dad6cc0ce516f8a5e1ff65ad83cb5f85d8c14fd0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 7 Jun 2016 23:42:33 +0200 Subject: [PATCH 0982/1390] Modify build.gradle --- MPChartExample/build.gradle | 2 +- MPChartLib/build.gradle | 1 + build.gradle | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 12d3a86424..2293cb5448 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -37,7 +37,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + classpath 'com.android.tools.build:gradle:2.1.2' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 1c7ca0e099..69db788eef 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'maven' apply plugin: 'com.github.dcendents.android-maven' +//apply plugin: 'realm-android' android { compileSdkVersion 23 diff --git a/build.gradle b/build.gradle index 564d957cc5..f2bd5c0e14 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,8 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.0' + //classpath "io.realm:realm-gradle-plugin:1.0.0" + classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From 3c47d0ade9e62e1d798b89129653c9f49e7c6a8d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 8 Jun 2016 16:50:20 +0200 Subject: [PATCH 0983/1390] Create example for timechart --- .../res/layout/activity_linechart_time.xml | 35 ++++++ .../mpchartexample/CombinedChartActivity.java | 4 - .../mpchartexample/LineChartTime.java | 111 +++++++++--------- .../mpchartexample/notimportant/DemoBase.java | 48 +------- .../notimportant/MainActivity.java | 3 +- .../charting/components/AxisBase.java | 2 +- .../charting/highlight/ChartHighlighter.java | 7 +- 7 files changed, 101 insertions(+), 109 deletions(-) create mode 100644 MPChartExample/res/layout/activity_linechart_time.xml diff --git a/MPChartExample/res/layout/activity_linechart_time.xml b/MPChartExample/res/layout/activity_linechart_time.xml new file mode 100644 index 0000000000..27f70f8ba3 --- /dev/null +++ b/MPChartExample/res/layout/activity_linechart_time.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 007f36c837..aacced57f3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -212,10 +212,6 @@ protected BubbleData generateBubbleData() { return bd; } - private float getRandom(float range, float startsfrom) { - return (float) (Math.random() * range) + startsfrom; - } - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.combined, menu); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index c6f1ea85c7..e53840362c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -6,6 +6,7 @@ import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -13,6 +14,7 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -22,40 +24,37 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - private long curTime = System.currentTimeMillis(); + private SeekBar mSeekBarX; + private TextView tvX; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart); + setContentView(R.layout.activity_linechart_time); tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX.setProgress(100); + tvX.setText("100"); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); mChart = (LineChart) findViewById(R.id.chart1); - mChart.setLogEnabled(true); // no description text mChart.setDescription(""); @@ -72,47 +71,54 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); - // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + mChart.setBackgroundColor(Color.WHITE); + mChart.setViewPortOffsets(0f, 0f, 0f, 0f); // add data - setData(20, 30); + setData(100, 30); mChart.invalidate(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); - - // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); - l.setForm(LegendForm.LINE); - l.setTypeface(tf); - l.setTextSize(11f); - l.setTextColor(Color.WHITE); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); -// l.setYOffset(11f); + l.setEnabled(false); XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); xAxis.setTypeface(tf); - xAxis.setTextSize(12f); + xAxis.setTextSize(10f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); + xAxis.setDrawGridLines(true); + xAxis.setTextColor(Color.rgb(255, 192, 56)); + xAxis.setCenterAxisLabels(true); + xAxis.setValueFormatter(new AxisValueFormatter() { + + private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); - // custom x-axis min / max - xAxis.setAxisMinValue(5000); - xAxis.setAxisMaxValue(30000); + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(new Date((long) value)); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); leftAxis.setTypeface(tf); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); - leftAxis.setAxisMaxValue(200f); - leftAxis.setAxisMinValue(0f); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); + leftAxis.setAxisMinValue(0f); + leftAxis.setAxisMaxValue(170f); + leftAxis.setYOffset(-9f); + leftAxis.setTextColor(Color.rgb(255, 192, 56)); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); @@ -254,43 +260,38 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText("" + (mSeekBarX.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(mSeekBarX.getProgress(), 50); // redraw mChart.invalidate(); - - System.out.println("xmin: " + mChart.getXAxis().getAxisMinimum()); - System.out.println("xmax: " + mChart.getXAxis().getAxisMaximum()); - System.out.println("lvx: " + mChart.getLowestVisibleX()); - System.out.println("hvx: " + mChart.getHighestVisibleX()); } private void setData(int count, float range) { - ArrayList yVals1 = new ArrayList(); + long now = System.currentTimeMillis(); + long hourMillis = 3600000L; - for (int i = 0; i < count; i++) { - float mult = range / 2f; - float val = (float) (Math.random() * mult) + 50;// + (float) - // ((mult * - // 0.1) / 10); - //yVals1.add(new Entry(val, 10000 + i * 1000)); - } + ArrayList values = new ArrayList(); - yVals1.add(new Entry(100, 10000)); - yVals1.add(new Entry(130, 15000)); - yVals1.add(new Entry(120, 20000)); + float from = now - (count / 2) * hourMillis; + float to = now + (count / 2) * hourMillis; + + for (float x = from; x < to; x += hourMillis) { + + float y = getRandom(range, 50); + values.add(new Entry(x, y)); // add one entry per hour + } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); set1.setAxisDependency(AxisDependency.LEFT); set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(Color.WHITE); - set1.setLineWidth(2f); - set1.setCircleRadius(3f); + set1.setValueTextColor(ColorTemplate.getHoloBlue()); + set1.setLineWidth(1.5f); + set1.setDrawCircles(false); + set1.setDrawValues(false); set1.setFillAlpha(65); set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index fb3eb51cf9..7141be0aaa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -23,51 +23,9 @@ public abstract class DemoBase extends FragmentActivity { "Party Y", "Party Z" }; - -// protected ArrayList getMonths() { -// -// ArrayList m = new ArrayList(); -// m.add(new XAxisValue(0, "Jan")); -// m.add(new XAxisValue(1, "Feb")); -// m.add(new XAxisValue(2, "Mar")); -// m.add(new XAxisValue(3, "Apr")); -// m.add(new XAxisValue(4, "May")); -// m.add(new XAxisValue(5, "Jun")); -// m.add(new XAxisValue(6, "Jul")); -// m.add(new XAxisValue(7, "Aug")); -// m.add(new XAxisValue(8, "Sep")); -// m.add(new XAxisValue(9, "Okt")); -// m.add(new XAxisValue(10, "Nov")); -// m.add(new XAxisValue(11, "Dec")); -// -// return m; -// } -// -// -// protected ArrayList getQuarters() { -// -// ArrayList q = new ArrayList(); -// q.add(new XAxisValue(0, "Quarter 1")); -// q.add(new XAxisValue(1, "Quarter 2")); -// q.add(new XAxisValue(2, "Quarter 3")); -// q.add(new XAxisValue(3, "Quarter 4")); -// -// return q; -// } -// -// protected List getYears() { -// ArrayList years = new ArrayList(); -// -// years.add(new XAxisValue(0, "2013")); -// years.add(new XAxisValue(1, "2014")); -// years.add(new XAxisValue(2, "2015")); -// years.add(new XAxisValue(3, "2016")); -// years.add(new XAxisValue(4, "2017")); -// years.add(new XAxisValue(5, "2018")); -// years.add(new XAxisValue(6, "2019")); -// -// return years; -// } + protected float getRandom(float range, float startsfrom) { + return (float) (Math.random() * range) + startsfrom; + } @Override public void onBackPressed() { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 06dbb7b865..1cf582ce6d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -132,12 +132,11 @@ protected void onCreate(Bundle savedInstanceState) { ContentItem realm = new ContentItem( "Realm.io Database", "This demonstrates how to use this library with Realm.io mobile database."); - realm.isNew = true; objects.add(realm); ContentItem time = new ContentItem( "Time Chart", - "Simple demonstration of a time-chart."); + "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds."); time.isNew = true; objects.add(time); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index dcb613b926..e92cdcd54c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -436,7 +436,7 @@ public String getLongestLabel() { for (int i = 0; i < mEntries.length; i++) { String text = getFormattedLabel(i); - if (longest.length() < text.length()) + if (text != null && longest.length() < text.length()) longest = text; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 7ba76d6a77..bc9a2aa84c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -92,8 +92,8 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { * @return */ protected float getMinimumDistance(List valsAtIndex, - float pos, - YAxis.AxisDependency axis) { + float pos, + YAxis.AxisDependency axis) { float distance = Float.MAX_VALUE; @@ -148,6 +148,9 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, final Entry e = set.getEntryForXPos(xVal, rounding); + if (e == null) + return null; + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); From e704fb87a0119bf1c9e3dfbb8b7c28d47ea0a66e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 09:45:20 +0200 Subject: [PATCH 0984/1390] Fixes related to line renering --- .../res/layout/activity_linechart_time.xml | 35 ++++++ .../mpchartexample/CombinedChartActivity.java | 4 - .../mpchartexample/LineChartActivity1.java | 18 +-- .../mpchartexample/LineChartTime.java | 113 +++++++++--------- .../mpchartexample/notimportant/DemoBase.java | 48 +------- .../notimportant/MainActivity.java | 3 +- .../charting/components/AxisBase.java | 2 +- .../mikephil/charting/data/CombinedData.java | 3 +- .../charting/highlight/ChartHighlighter.java | 7 +- .../charting/renderer/LineChartRenderer.java | 82 ++++--------- .../charting/renderer/LineRadarRenderer.java | 11 +- .../mikephil/charting/utils/Transformer.java | 2 +- 12 files changed, 143 insertions(+), 185 deletions(-) create mode 100644 MPChartExample/res/layout/activity_linechart_time.xml diff --git a/MPChartExample/res/layout/activity_linechart_time.xml b/MPChartExample/res/layout/activity_linechart_time.xml new file mode 100644 index 0000000000..27f70f8ba3 --- /dev/null +++ b/MPChartExample/res/layout/activity_linechart_time.xml @@ -0,0 +1,35 @@ + + + + + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 007f36c837..aacced57f3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -212,10 +212,6 @@ protected BubbleData generateBubbleData() { return bd; } - private float getRandom(float range, float startsfrom) { - return (float) (Math.random() * range) + startsfrom; - } - @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.combined, menu); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index ac0a864266..bfa5c2dde2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -148,7 +148,7 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.setVisibleYRange(20f, AxisDependency.LEFT); // mChart.centerViewTo(20, 50, AxisDependency.LEFT); - mChart.animateX(2500, Easing.EasingOption.EaseInOutQuart); + mChart.animateX(2500); //mChart.invalidate(); // get the legend (only possible after setting data) @@ -337,15 +337,12 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList(); for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10);x - yVals.add(new Entry(i, val)); + float val = (float) (Math.random() * range) + 3; + values.add(new Entry(i, val)); } LineDataSet set1; @@ -353,15 +350,12 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals); + set1.setValues(values); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { // create a dataset and give it a type - set1 = new LineDataSet(yVals, "DataSet 1"); - - // set1.setFillAlpha(110); - // set1.setFillColor(Color.RED); + set1 = new LineDataSet(values, "DataSet 1"); // set the line to be drawn like this "- - - - - -" set1.enableDashedLine(10f, 5f, 0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index c6f1ea85c7..46677a51cf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -6,6 +6,7 @@ import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -13,6 +14,7 @@ import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.Legend.LegendPosition; @@ -22,40 +24,38 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - private long curTime = System.currentTimeMillis(); + private SeekBar mSeekBarX; + private TextView tvX; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart); + setContentView(R.layout.activity_linechart_time); tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX.setProgress(100); + tvX.setText("100"); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); mChart = (LineChart) findViewById(R.id.chart1); - mChart.setLogEnabled(true); + mChart.setHardwareAccelerationEnabled(true); // no description text mChart.setDescription(""); @@ -72,47 +72,55 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setHighlightPerDragEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); - // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + mChart.setBackgroundColor(Color.WHITE); + mChart.setViewPortOffsets(0f, 0f, 0f, 0f); // add data - setData(20, 30); + setData(100, 30); mChart.invalidate(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); // get the legend (only possible after setting data) Legend l = mChart.getLegend(); - - // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); - l.setForm(LegendForm.LINE); - l.setTypeface(tf); - l.setTextSize(11f); - l.setTextColor(Color.WHITE); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); -// l.setYOffset(11f); + l.setEnabled(false); XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); xAxis.setTypeface(tf); - xAxis.setTextSize(12f); + xAxis.setTextSize(10f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); + xAxis.setDrawGridLines(true); + xAxis.setTextColor(Color.rgb(255, 192, 56)); + xAxis.setCenterAxisLabels(true); + xAxis.setGranularity(60000L); // one minute in millis + xAxis.setValueFormatter(new AxisValueFormatter() { + + private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); - // custom x-axis min / max - xAxis.setAxisMinValue(5000); - xAxis.setAxisMaxValue(30000); + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(new Date((long) value)); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }); YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); leftAxis.setTypeface(tf); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); - leftAxis.setAxisMaxValue(200f); - leftAxis.setAxisMinValue(0f); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); + leftAxis.setAxisMinValue(0f); + leftAxis.setAxisMaxValue(170f); + leftAxis.setYOffset(-9f); + leftAxis.setTextColor(Color.rgb(255, 192, 56)); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); @@ -254,43 +262,38 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText("" + (mSeekBarX.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(mSeekBarX.getProgress(), 50); // redraw mChart.invalidate(); - - System.out.println("xmin: " + mChart.getXAxis().getAxisMinimum()); - System.out.println("xmax: " + mChart.getXAxis().getAxisMaximum()); - System.out.println("lvx: " + mChart.getLowestVisibleX()); - System.out.println("hvx: " + mChart.getHighestVisibleX()); } private void setData(int count, float range) { - ArrayList yVals1 = new ArrayList(); + long now = System.currentTimeMillis(); + long hourMillis = 3600000L; - for (int i = 0; i < count; i++) { - float mult = range / 2f; - float val = (float) (Math.random() * mult) + 50;// + (float) - // ((mult * - // 0.1) / 10); - //yVals1.add(new Entry(val, 10000 + i * 1000)); - } + ArrayList values = new ArrayList(); - yVals1.add(new Entry(100, 10000)); - yVals1.add(new Entry(130, 15000)); - yVals1.add(new Entry(120, 20000)); + float from = now - (count / 2) * hourMillis; + float to = now + (count / 2) * hourMillis; + + for (float x = from; x < to; x += hourMillis) { + + float y = getRandom(range, 50); + values.add(new Entry(x, y)); // add one entry per hour + } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals1, "DataSet 1"); + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); set1.setAxisDependency(AxisDependency.LEFT); set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(Color.WHITE); - set1.setLineWidth(2f); - set1.setCircleRadius(3f); + set1.setValueTextColor(ColorTemplate.getHoloBlue()); + set1.setLineWidth(1.5f); + set1.setDrawCircles(false); + set1.setDrawValues(false); set1.setFillAlpha(65); set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index fb3eb51cf9..7141be0aaa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -23,51 +23,9 @@ public abstract class DemoBase extends FragmentActivity { "Party Y", "Party Z" }; - -// protected ArrayList getMonths() { -// -// ArrayList m = new ArrayList(); -// m.add(new XAxisValue(0, "Jan")); -// m.add(new XAxisValue(1, "Feb")); -// m.add(new XAxisValue(2, "Mar")); -// m.add(new XAxisValue(3, "Apr")); -// m.add(new XAxisValue(4, "May")); -// m.add(new XAxisValue(5, "Jun")); -// m.add(new XAxisValue(6, "Jul")); -// m.add(new XAxisValue(7, "Aug")); -// m.add(new XAxisValue(8, "Sep")); -// m.add(new XAxisValue(9, "Okt")); -// m.add(new XAxisValue(10, "Nov")); -// m.add(new XAxisValue(11, "Dec")); -// -// return m; -// } -// -// -// protected ArrayList getQuarters() { -// -// ArrayList q = new ArrayList(); -// q.add(new XAxisValue(0, "Quarter 1")); -// q.add(new XAxisValue(1, "Quarter 2")); -// q.add(new XAxisValue(2, "Quarter 3")); -// q.add(new XAxisValue(3, "Quarter 4")); -// -// return q; -// } -// -// protected List getYears() { -// ArrayList years = new ArrayList(); -// -// years.add(new XAxisValue(0, "2013")); -// years.add(new XAxisValue(1, "2014")); -// years.add(new XAxisValue(2, "2015")); -// years.add(new XAxisValue(3, "2016")); -// years.add(new XAxisValue(4, "2017")); -// years.add(new XAxisValue(5, "2018")); -// years.add(new XAxisValue(6, "2019")); -// -// return years; -// } + protected float getRandom(float range, float startsfrom) { + return (float) (Math.random() * range) + startsfrom; + } @Override public void onBackPressed() { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 06dbb7b865..1cf582ce6d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -132,12 +132,11 @@ protected void onCreate(Bundle savedInstanceState) { ContentItem realm = new ContentItem( "Realm.io Database", "This demonstrates how to use this library with Realm.io mobile database."); - realm.isNew = true; objects.add(realm); ContentItem time = new ContentItem( "Time Chart", - "Simple demonstration of a time-chart."); + "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds."); time.isNew = true; objects.add(time); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index dcb613b926..e92cdcd54c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -436,7 +436,7 @@ public String getLongestLabel() { for (int i = 0; i < mEntries.length; i++) { String text = getFormattedLabel(i); - if (longest.length() < text.length()) + if (text != null && longest.length() < text.length()) longest = text; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 65bb6cca62..fc1b566a07 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; import java.util.List; @@ -13,7 +14,7 @@ * * @author Philipp Jahoda */ -public class CombinedData extends BarLineScatterCandleBubbleData> { +public class CombinedData extends BarLineScatterCandleBubbleData> { private LineData mLineData; private BarData mBarData; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 7ba76d6a77..bc9a2aa84c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -92,8 +92,8 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { * @return */ protected float getMinimumDistance(List valsAtIndex, - float pos, - YAxis.AxisDependency axis) { + float pos, + YAxis.AxisDependency axis) { float distance = Float.MAX_VALUE; @@ -148,6 +148,9 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, final Entry e = set.getEntryForXPos(xVal, rounding); + if (e == null) + return null; + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 276d2f7971..3510509374 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -286,7 +286,7 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); - + // Take the from/to xIndex from the entries themselves, // so missing entries won't screw up the filling. // What we need to draw is line from points of the xIndexes - not arbitrary entry indexes! @@ -349,11 +349,9 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); - - final int count = (int)(Math.ceil((float)(maxx - minx) * phaseX + (float)(minx))); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = dataSet.getEntryIndex(entryTo); + int count = (int) ((maxx - minx) * phaseX); // more than 1 color if (dataSet.getColors().size() > 1) { @@ -361,14 +359,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (mLineBuffer.length != pointsPerEntryPair * 2) mLineBuffer = new float[pointsPerEntryPair * 2]; - for (int j = minx; - j < count; - j++) { - - if (count > 1 && j == count - 1) { - // Last point, we have already drawn a line to this point - break; - } + for (int j = minx; j <= count + minx; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -376,7 +367,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[0] = e.getX(); mLineBuffer[1] = e.getY() * phaseY; - if (j + 1 < count) { + if (j < maxx) { e = dataSet.getEntryForIndex(j + 1); @@ -421,8 +412,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { } else { // only one color per dataset - if (mLineBuffer.length != Math.max((entryCount - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2) - mLineBuffer = new float[Math.max((entryCount - 1) * pointsPerEntryPair, pointsPerEntryPair) * 2]; + if (mLineBuffer.length != Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 2) + mLineBuffer = new float[Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 2]; Entry e1, e2; @@ -431,7 +422,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (e1 != null) { int j = 0; - for (int x = count > 1 ? minx + 1 : minx; x < count; x++) { + for (int x = minx; x <= count + minx; x++) { e1 = dataSet.getEntryForIndex(x == 0 ? 0 : (x - 1)); e2 = dataSet.getEntryForIndex(x); @@ -455,14 +446,11 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (j > 0) { trans.pointValuesToPixel(mLineBuffer); - final int size = - Math.max((count - minx - 1) * pointsPerEntryPair, pointsPerEntryPair) * - 2; + final int size = Math.max((maxx - minx + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; mRenderPaint.setColor(dataSet.getColor()); - canvas.drawLines(mLineBuffer, 0, size, - mRenderPaint); + canvas.drawLines(mLineBuffer, 0, size, mRenderPaint); } } } @@ -479,8 +467,7 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, int maxx, Transformer trans) { - Path filled = generateFilledPath( - dataSet, minx, maxx); + Path filled = generateFilledPath(dataSet, minx, maxx); trans.pathValueToPixel(filled); @@ -500,21 +487,23 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, * @param dataSet * @return */ - private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { + private Path generateFilledPath(ILineDataSet dataSet, int minx, int maxx) { float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); + final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; + + int count = (int) ((maxx - minx) * phaseX); Path filled = new Path(); - Entry entry = dataSet.getEntryForIndex(from); + Entry entry = dataSet.getEntryForIndex(minx); filled.moveTo(entry.getX(), fillMin); filled.lineTo(entry.getX(), entry.getY() * phaseY); // create a new path - for (int x = from + 1, count = (int) Math.ceil((to - from) * phaseX + from); x < count; x++) { + for (int x = minx + 1; x <= count + minx; x++) { Entry e = dataSet.getEntryForIndex(x); @@ -529,12 +518,7 @@ private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { } // close up - filled.lineTo( - dataSet.getEntryForIndex( - Math.max( - Math.min((int) Math.ceil((to - from) * phaseX + from) - 1, - dataSet.getEntryCount() - 1), 0)).getX(), fillMin); - + filled.lineTo(dataSet.getEntryForIndex(count + minx).getX(), fillMin); filled.close(); return filled; @@ -565,20 +549,14 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - int entryCount = dataSet.getEntryCount(); - float low = mChart.getLowestVisibleX(); float high = mChart.getHighestVisibleX(); Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - int diff = (entryFrom == entryTo) ? 1 : 0; - if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) - diff += 1; - - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = dataSet.getEntryIndex(entryTo); float[] positions = trans.generateTransformedValuesLine( dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -633,20 +611,15 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - int entryCount = dataSet.getEntryCount(); - float low = mChart.getLowestVisibleX(); float high = mChart.getHighestVisibleX(); Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - int diff = (entryFrom == entryTo) ? 1 : 0; - if (dataSet.getMode() == LineDataSet.Mode.CUBIC_BEZIER) - diff += 1; - - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = dataSet.getEntryIndex(entryTo); + int count = (int) ((maxx - minx) * phaseX); float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); @@ -656,10 +629,7 @@ protected void drawCircles(Canvas c) { boolean drawTransparentCircleHole = drawCircleHole && dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; - for (int j = minx, - count = (int) Math.ceil((maxx - minx) * phaseX + minx); - j < count; - j ++) { + for (int j = minx; j <= count + minx; j++) { Entry e = dataSet.getEntryForIndex(j); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java index f29c77513e..288eff64bf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineRadarRenderer.java @@ -3,8 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; @@ -31,7 +29,7 @@ protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { if (clipPathSupported()) { - c.save(); + int save = c.save(); c.clipPath(filledPath); drawable.setBounds((int) mViewPortHandler.contentLeft(), @@ -40,7 +38,7 @@ protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { (int) mViewPortHandler.contentBottom()); drawable.draw(c); - c.restore(); + c.restoreToCount(save); } else { throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " + "this code was run on API level " + Utils.getSDKInt() + "."); @@ -62,11 +60,12 @@ protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fill if (clipPathSupported()) { - c.save(); + int save = c.save(); + c.clipPath(filledPath); c.drawColor(color); - c.restore(); + c.restoreToCount(save); } else { // save diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 5c2d98e7c7..581708640b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -161,7 +161,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, public float[] generateTransformedValuesLine(ILineDataSet data, float phaseX, float phaseY, int from, int to) { - final int count = (int) Math.ceil((to - from) * phaseX) * 2; + final int count = (int) ((to - from) * phaseX + 1) * 2; float[] valuePoints = new float[count]; From 0c90c44a010e5cce2c8511ee9fd8d140c430e89a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 10:45:11 +0200 Subject: [PATCH 0985/1390] Work on improving line rendering --- .../charting/renderer/LineChartRenderer.java | 185 +++++++----------- 1 file changed, 71 insertions(+), 114 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 3510509374..ace49879cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.PointD; @@ -115,11 +116,11 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { break; case CUBIC_BEZIER: - drawCubicBezier(c, dataSet); + drawCubicBezier(dataSet); break; case HORIZONTAL_BEZIER: - drawHorizontalBezier(c, dataSet); + drawHorizontalBezier(dataSet); break; } @@ -129,41 +130,27 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { /** * Draws a cubic line. * - * @param c * @param dataSet */ - protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { - - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + protected void drawHorizontalBezier(ILineDataSet dataSet) { - int entryCount = dataSet.getEntryCount(); - - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + float phaseY = mAnimator.getPhaseY(); - int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); - float phaseY = mAnimator.getPhaseY(); + XBounds bounds = getXBounds(dataSet); cubicPath.reset(); - int size = (int) Math.ceil((maxx - minx) * phaseX + minx); - - if (size - minx >= 2) { + if (bounds.range >= 1) { - Entry prev = dataSet.getEntryForIndex(minx); + Entry prev = dataSet.getEntryForIndex(bounds.min); Entry cur = prev; // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); - for (int j = minx + 1, count = Math.min(size, entryCount); j < count; j++) { + for (int j = bounds.min + 1; j <= bounds.range + bounds.min; j++) { prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); @@ -184,8 +171,7 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, - minx, size); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, bounds); } mRenderPaint.setColor(dataSet.getColor()); @@ -199,52 +185,40 @@ protected void drawHorizontalBezier(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } - protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { - - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - - int entryCount = dataSet.getEntryCount(); - - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff - 1, 0); - int maxx = Math.min(Math.max(minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); + protected void drawCubicBezier(ILineDataSet dataSet) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + + XBounds bounds = getXBounds(dataSet); + float intensity = dataSet.getCubicIntensity(); cubicPath.reset(); - int size = (int) Math.ceil((maxx - minx) * phaseX + minx); - - if (size - minx >= 2) { + if (bounds.range >= 1) { float prevDx = 0f; float prevDy = 0f; float curDx = 0f; float curDy = 0f; - Entry prevPrev = dataSet.getEntryForIndex(minx); + Entry prevPrev = dataSet.getEntryForIndex(bounds.min); Entry prev = prevPrev; Entry cur = prev; - Entry next = dataSet.getEntryForIndex(minx + 1); + Entry next = dataSet.getEntryForIndex(bounds.min + 1); // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); - for (int j = minx + 1, count = Math.min(size, entryCount); j < count; j++) { + for (int j = bounds.min + 1; j <= bounds.range + bounds.min; j++) { prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); - next = entryCount > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; + next = bounds.max > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; prevDx = (cur.getX() - prevPrev.getX()) * intensity; prevDy = (cur.getY() - prevPrev.getY()) * intensity; @@ -263,8 +237,7 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, - minx, size); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, bounds); } mRenderPaint.setColor(dataSet.getColor()); @@ -278,26 +251,13 @@ protected void drawCubicBezier(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } - protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transformer trans, - int from, int to) { - - if (to - from <= 1) - return; + protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transformer trans, XBounds bounds) { float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); - // Take the from/to xIndex from the entries themselves, - // so missing entries won't screw up the filling. - // What we need to draw is line from points of the xIndexes - not arbitrary entry indexes! - - final Entry toEntry = dataSet.getEntryForIndex(to - 1); - final Entry fromEntry = dataSet.getEntryForIndex(from); - final float xTo = toEntry == null ? 0 : toEntry.getX(); - final float xFrom = fromEntry == null ? 0 : fromEntry.getX(); - - spline.lineTo(xTo, fillMin); - spline.lineTo(xFrom, fillMin); + spline.lineTo(bounds.min + bounds.range, fillMin); + spline.lineTo(bounds.min, fillMin); spline.close(); trans.pathValueToPixel(spline); @@ -329,7 +289,6 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); mRenderPaint.setStyle(Paint.Style.STROKE); @@ -343,15 +302,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { canvas = c; } - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = dataSet.getEntryIndex(entryTo); - int count = (int) ((maxx - minx) * phaseX); + XBounds bounds = getXBounds(dataSet); // more than 1 color if (dataSet.getColors().size() > 1) { @@ -359,7 +310,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (mLineBuffer.length != pointsPerEntryPair * 2) mLineBuffer = new float[pointsPerEntryPair * 2]; - for (int j = minx; j <= count + minx; j++) { + for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -367,7 +318,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[0] = e.getX(); mLineBuffer[1] = e.getY() * phaseY; - if (j < maxx) { + if (j < bounds.max) { e = dataSet.getEntryForIndex(j + 1); @@ -417,12 +368,12 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Entry e1, e2; - e1 = dataSet.getEntryForIndex(minx); + e1 = dataSet.getEntryForIndex(bounds.min); if (e1 != null) { int j = 0; - for (int x = minx; x <= count + minx; x++) { + for (int x = bounds.min; x <= bounds.range + bounds.min; x++) { e1 = dataSet.getEntryForIndex(x == 0 ? 0 : (x - 1)); e2 = dataSet.getEntryForIndex(x); @@ -446,7 +397,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (j > 0) { trans.pointValuesToPixel(mLineBuffer); - final int size = Math.max((maxx - minx + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; + final int size = Math.max((bounds.range + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; mRenderPaint.setColor(dataSet.getColor()); @@ -459,15 +410,13 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // if drawing filled is enabled if (dataSet.isDrawFilledEnabled() && entryCount > 0) { - drawLinearFill(c, dataSet, minx, maxx, trans); + drawLinearFill(c, dataSet, trans, bounds); } } - protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, - int maxx, - Transformer trans) { + protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) { - Path filled = generateFilledPath(dataSet, minx, maxx); + Path filled = generateFilledPath(dataSet, bounds); trans.pathValueToPixel(filled); @@ -487,23 +436,20 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, * @param dataSet * @return */ - private Path generateFilledPath(ILineDataSet dataSet, int minx, int maxx) { + private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) { float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); float phaseY = mAnimator.getPhaseY(); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; - int count = (int) ((maxx - minx) * phaseX); - Path filled = new Path(); - Entry entry = dataSet.getEntryForIndex(minx); + Entry entry = dataSet.getEntryForIndex(bounds.min); filled.moveTo(entry.getX(), fillMin); filled.lineTo(entry.getX(), entry.getY() * phaseY); // create a new path - for (int x = minx + 1; x <= count + minx; x++) { + for (int x = bounds.min + 1; x <= bounds.range + bounds.min; x++) { Entry e = dataSet.getEntryForIndex(x); @@ -518,7 +464,7 @@ private Path generateFilledPath(ILineDataSet dataSet, int minx, int maxx) { } // close up - filled.lineTo(dataSet.getEntryForIndex(count + minx).getX(), fillMin); + filled.lineTo(dataSet.getEntryForIndex(bounds.range + bounds.min).getX(), fillMin); filled.close(); return filled; @@ -549,17 +495,10 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + XBounds bounds = getXBounds(dataSet); - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = dataSet.getEntryIndex(entryTo); - - float[] positions = trans.generateTransformedValuesLine( - dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); + float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator + .getPhaseY(), bounds.min, bounds.max); for (int j = 0; j < positions.length; j += 2) { @@ -572,7 +511,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - Entry entry = dataSet.getEntryForIndex(j / 2 + minx); + Entry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, y - valOffset, dataSet.getValueTextColor(j / 2)); @@ -592,7 +531,6 @@ protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float[] circlesBuffer = new float[2]; @@ -611,15 +549,7 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = dataSet.getEntryIndex(entryTo); - int count = (int) ((maxx - minx) * phaseX); + XBounds bounds = getXBounds(dataSet); float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); @@ -629,7 +559,7 @@ protected void drawCircles(Canvas c) { boolean drawTransparentCircleHole = drawCircleHole && dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; - for (int j = minx; j <= count + minx; j++) { + for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { Entry e = dataSet.getEntryForIndex(j); @@ -757,4 +687,31 @@ public void releaseBitmap() { mDrawBitmap = null; } } + + private XBounds getXBounds(IBarLineScatterCandleBubbleDataSet dataSet) { + return new XBounds(dataSet); + } + + private class XBounds { + + public final int min; + public final int max; + + public final int range; + + public XBounds(IBarLineScatterCandleBubbleDataSet dataSet) { + + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); + + float low = mChart.getLowestVisibleX(); + float high = mChart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + + min = dataSet.getEntryIndex(entryFrom); + max = dataSet.getEntryIndex(entryTo); + range = (int) ((max - min) * phaseX); + } + } } From c0bee1c1cd3542375eb28e9235ce51b72198aa6d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 10:52:51 +0200 Subject: [PATCH 0986/1390] Further abstraction of XBounds calculation --- .../BarLineScatterCandleBubbleRenderer.java | 61 +++++++++++++++++++ .../charting/renderer/LineChartRenderer.java | 50 ++++----------- .../LineScatterCandleRadarRenderer.java | 2 +- 3 files changed, 75 insertions(+), 38 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java new file mode 100644 index 0000000000..9b6fdfabd6 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -0,0 +1,61 @@ +package com.github.mikephil.charting.renderer; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 09/06/16. + */ +public abstract class BarLineScatterCandleBubbleRenderer extends DataRenderer { + + + public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + } + + /** + * Calculates and returns the x-bounds for the given DataSet in terms of index in their values array. This + * includes minimum and maximum visible x, as well as range. + * + * @param dataSet + * @return + */ + protected XBounds getXBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet + dataSet) { + return new XBounds(chart, dataSet); + } + + /** + * Class representing the bounds of the current viewport in terms of indices in the values array of a DataSet. + */ + protected class XBounds { + + /** minimum visible entry index */ + public final int min; + + /** maximum visible entry index */ + public final int max; + + /** range of visible entry indices */ + public final int range; + + public XBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { + + float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); + + float low = chart.getLowestVisibleX(); + float high = chart.getHighestVisibleX(); + + Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + + min = dataSet.getEntryIndex(entryFrom); + max = dataSet.getEntryIndex(entryTo); + range = (int) ((max - min) * phaseX); + } + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index ace49879cc..a61b8ad8ec 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -127,18 +127,13 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } - /** - * Draws a cubic line. - * - * @param dataSet - */ protected void drawHorizontalBezier(ILineDataSet dataSet) { float phaseY = mAnimator.getPhaseY(); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); cubicPath.reset(); @@ -192,7 +187,7 @@ protected void drawCubicBezier(ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); float intensity = dataSet.getCubicIntensity(); @@ -302,7 +297,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { canvas = c; } - XBounds bounds = getXBounds(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); // more than 1 color if (dataSet.getColors().size() > 1) { @@ -414,6 +409,14 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { } } + /** + * Draws a filled linear path on the canvas. + * + * @param c + * @param dataSet + * @param trans + * @param bounds + */ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, XBounds bounds) { Path filled = generateFilledPath(dataSet, bounds); @@ -495,7 +498,7 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - XBounds bounds = getXBounds(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator .getPhaseY(), bounds.min, bounds.max); @@ -549,7 +552,7 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); @@ -687,31 +690,4 @@ public void releaseBitmap() { mDrawBitmap = null; } } - - private XBounds getXBounds(IBarLineScatterCandleBubbleDataSet dataSet) { - return new XBounds(dataSet); - } - - private class XBounds { - - public final int min; - public final int max; - - public final int range; - - public XBounds(IBarLineScatterCandleBubbleDataSet dataSet) { - - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); - - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - min = dataSet.getEntryIndex(entryFrom); - max = dataSet.getEntryIndex(entryTo); - range = (int) ((max - min) * phaseX); - } - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index 122e90f80c..53f54cbfd9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -10,7 +10,7 @@ /** * Created by Philipp Jahoda on 11/07/15. */ -public abstract class LineScatterCandleRadarRenderer extends DataRenderer { +public abstract class LineScatterCandleRadarRenderer extends BarLineScatterCandleBubbleRenderer { /** * path that is used for drawing highlight-lines (drawLines(...) cannot be used because of dashes) From 455ff894cbfe1022a76ce53d1f31b3c6affe6366 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 12:04:01 +0200 Subject: [PATCH 0987/1390] Fixes related to minmax and bubblechart rendering --- .../mpchartexample/BubbleChartActivity.java | 6 +- .../mikephil/charting/data/BarDataSet.java | 4 +- .../mikephil/charting/data/BubbleDataSet.java | 32 ++------- .../mikephil/charting/data/CandleDataSet.java | 4 +- .../renderer/BubbleChartRenderer.java | 67 ++++++------------- .../charting/renderer/LineChartRenderer.java | 2 - .../mikephil/charting/utils/Transformer.java | 5 +- 7 files changed, 33 insertions(+), 87 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 63107114b5..fb46034d5f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -73,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setMaxVisibleValueCount(200); mChart.setPinchZoom(true); - mSeekBarX.setProgress(5); + mSeekBarX.setProgress(1); mSeekBarY.setProgress(50); Legend l = mChart.getLegend(); @@ -132,7 +132,6 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); break; } @@ -156,7 +155,7 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - int count = mSeekBarX.getProgress() + 1; + int count = mSeekBarX.getProgress(); int range = mSeekBarY.getProgress(); tvX.setText("" + count); @@ -205,6 +204,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a data object with the datasets BubbleData data = new BubbleData(dataSets); + data.setDrawValues(false); data.setValueTypeface(tf); data.setValueTextSize(8f); data.setValueTextColor(Color.WHITE); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 6cc820ceb4..2802ebc4c2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -111,9 +111,9 @@ public void calcMinMax() { if (mValues == null || mValues.isEmpty()) return; - mYMax = Float.MIN_VALUE; + mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - mXMax = Float.MIN_VALUE; + mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; for (BarEntry e : mValues) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 6814adc8a1..ec288123e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -34,38 +34,16 @@ public void calcMinMax() { if (mValues == null || mValues.isEmpty()) return; - mYMax = Float.MIN_VALUE; + mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - mXMax = Float.MIN_VALUE; + mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - // need chart width to guess this properly + for (BubbleEntry e : mValues) { - for (BubbleEntry entry : mValues) { + calcMinMax(e); - float ymin = entry.getY(); - float ymax = entry.getY(); - - if (ymin < mYMin) { - mYMin = ymin; - } - - if (ymax > mYMax) { - mYMax = ymax; - } - - final float xmin = entry.getX(); - final float xmax = entry.getX(); - - if (xmin < mXMin) { - mXMin = xmin; - } - - if (xmax > mXMax) { - mXMax = xmax; - } - - final float size = entry.getSize(); + final float size = e.getSize(); if (size > mMaxSize) { mMaxSize = size; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 2331b3e589..124a6a3253 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -105,9 +105,9 @@ public void calcMinMax() { if (mValues == null || mValues.isEmpty()) return; - mYMax = Float.MIN_VALUE; + mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - mXMax = Float.MIN_VALUE; + mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; for (CandleEntry e : mValues) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 47542dc591..b23cf3721e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -22,7 +21,7 @@ * Bubble chart implementation: Copyright 2015 Pierre-Marc Airoldi Licensed * under Apache License 2.0 Ported by Daniel Cohen Gindi */ -public class BubbleChartRenderer extends DataRenderer { +public class BubbleChartRenderer extends BarLineScatterCandleBubbleRenderer { protected BubbleDataProvider mChart; @@ -57,13 +56,9 @@ public void drawData(Canvas c) { private float[] sizeBuffer = new float[4]; private float[] pointBuffer = new float[2]; - protected float getShapeSize(float entrySize, - float maxSize, - float reference, - boolean normalizeSize) { - final float factor = normalizeSize - ? ((maxSize == 0f) ? 1f : (float) Math.sqrt(entrySize / maxSize)) - : entrySize; + protected float getShapeSize(float entrySize, float maxSize, float reference, boolean normalizeSize) { + final float factor = normalizeSize ? ((maxSize == 0f) ? 1f : (float) Math.sqrt(entrySize / maxSize)) : + entrySize; final float shapeSize = reference * factor; return shapeSize; } @@ -72,17 +67,9 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - BubbleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); + XBounds bounds = getXBounds(mChart, dataSet); sizeBuffer[0] = 0f; sizeBuffer[2] = 1f; @@ -96,12 +83,12 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - for (int j = minx; j < maxx; j++) { + for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { final BubbleEntry entry = dataSet.getEntryForIndex(j); - pointBuffer[0] = (float) (entry.getX() - minx) * phaseX + (float) minx; - pointBuffer[1] = (float) (entry.getY()) * phaseY; + pointBuffer[0] = entry.getX(); + pointBuffer[1] = (entry.getY()) * phaseY; trans.pointValuesToPixel(pointBuffer); float shapeHalf = getShapeSize(entry.getSize(), dataSet.getMaxSize(), referenceSize, normalizeSize) / 2f; @@ -151,23 +138,16 @@ public void drawValues(Canvas c) { final float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); final float phaseY = mAnimator.getPhaseY(); - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - BubbleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); + XBounds bounds = getXBounds(mChart, dataSet); final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) - .generateTransformedValuesBubble(dataSet, phaseX, phaseY, minx, maxx); + .generateTransformedValuesBubble(dataSet, phaseY, bounds.min, bounds.max); final float alpha = phaseX == 1 ? phaseY : phaseX; for (int j = 0; j < positions.length; j += 2) { - int valueTextColor = dataSet.getValueTextColor(j / 2 + minx); + int valueTextColor = dataSet.getValueTextColor(j / 2 + bounds.min); valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), Color.green(valueTextColor), Color.blue(valueTextColor)); @@ -180,7 +160,7 @@ public void drawValues(Canvas c) { if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; - BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); + BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, y + (0.5f * lineHeight), valueTextColor); @@ -200,7 +180,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { BubbleData bubbleData = mChart.getBubbleData(); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); for (Highlight high : indices) { @@ -213,9 +192,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { : (high.getDataSetIndex() + 1); if (maxDataSetIndex - minDataSetIndex < 1) continue; - for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { + for (int dataSetIndex = minDataSetIndex; dataSetIndex < maxDataSetIndex; dataSetIndex++) { IBubbleDataSet dataSet = bubbleData.getDataSetByIndex(dataSetIndex); @@ -223,17 +200,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(high); - if (entry == null || entry.getX() != high.getX()) - continue; - - float low = mChart.getLowestVisibleX(); - float highX = mChart.getHighestVisibleX(); - BubbleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - BubbleEntry entryTo = dataSet.getEntryForXPos(highX, DataSet.Rounding.UP); + if (entry == null) + continue; - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); + XBounds bounds = getXBounds(mChart, dataSet); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -250,8 +221,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - pointBuffer[0] = (float) (entry.getX() - minx) * phaseX + (float) minx; - pointBuffer[1] = (float) (entry.getY()) * phaseY; + pointBuffer[0] = entry.getX(); + pointBuffer[1] = (entry.getY()) * phaseY; trans.pointValuesToPixel(pointBuffer); float shapeHalf = getShapeSize(entry.getSize(), @@ -269,7 +240,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - if (high.getX() < minx || high.getX() >= maxx) + if (high.getX() < bounds.min || high.getX() > bounds.max) continue; final int originalColor = dataSet.getColor((int) entry.getX()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a61b8ad8ec..ac0e57d2de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -9,13 +9,11 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.PointD; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 581708640b..6d16b2107e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -129,8 +129,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, * @param data * @return */ - public float[] generateTransformedValuesBubble(IBubbleDataSet data, - float phaseX, float phaseY, int from, int to) { + public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY, int from, int to) { final int count = (int) Math.ceil(to - from) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; @@ -141,7 +140,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, Entry e = data.getEntryForIndex(j / 2 + from); if (e != null) { - valuePoints[j] = (float) (e.getX() - from) * phaseX + from; + valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; } } From d507234cc84f064e4be475b8422f903657cbe942 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 12:10:15 +0200 Subject: [PATCH 0988/1390] Further improve rendering x-bounds calculation --- .../charting/renderer/BarChartRenderer.java | 1 - .../renderer/CandleStickChartRenderer.java | 33 ++++--------------- .../renderer/CombinedChartRenderer.java | 3 +- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 9ec7ad3aab..27cfb77aa5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -98,7 +98,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); buffer.setBarWidth(mChart.getBarData().getBarWidth()); - //buffer.setInterval(mChart.getXRange() / dataSet.getEntryCount()); buffer.feed(dataSet); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 998668e863..9ced6efa05 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -7,8 +7,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -58,29 +56,21 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); float barSpace = dataSet.getBarSpace(); boolean showCandleBar = dataSet.getShowCandleBar(); - float lowX = mChart.getLowestVisibleX(); - float highX = mChart.getHighestVisibleX(); - - CandleEntry entryFrom = dataSet.getEntryForXPos(lowX, DataSet.Rounding.DOWN); - CandleEntry entryTo = dataSet.getEntryForXPos(highX, DataSet.Rounding.UP); - - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = dataSet.getEntryIndex(entryTo); + XBounds bounds = getXBounds(mChart, dataSet); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); // draw the body - for (int j = minx; j <= maxx * phaseX; j++) { + for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { // get the entry CandleEntry e = dataSet.getEntryForIndex(j); - if(e == null) + if (e == null) continue; final float xPos = e.getX(); @@ -256,7 +246,6 @@ else if (open < close) mCloseBuffers[0], mCloseBuffers[1], mCloseBuffers[2], mCloseBuffers[3], mRenderPaint); - } } } @@ -281,17 +270,10 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float low = mChart.getLowestVisibleX(); - float high = mChart.getHighestVisibleX(); - - CandleEntry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - CandleEntry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); - - int minx = dataSet.getEntryIndex(entryFrom); - int maxx = dataSet.getEntryIndex(entryTo); + XBounds bounds = getXBounds(mChart, dataSet); float[] positions = trans.generateTransformedValuesCandle( - dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); + dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), bounds.min, bounds.max); float yOffset = Utils.convertDpToPixel(5f); @@ -306,7 +288,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - CandleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); + CandleEntry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet .getValueTextColor(j / 2)); @@ -348,7 +330,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { CandleEntry e = set.getEntryForXPos(x); - if (e == null || e.getX() != x) + if (e == null) continue; float lowValue = e.getLow() * mAnimator.getPhaseY(); @@ -362,5 +344,4 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } } - } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index be8d98e476..7718b95e2c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -124,8 +124,7 @@ else if (renderer instanceof ScatterChartRenderer) else if (renderer instanceof BubbleChartRenderer) data = ((BubbleChartRenderer)renderer).mChart.getBubbleData(); - int dataIndex = data == null - ? -1 + int dataIndex = data == null ? -1 : ((CombinedData)chart.getData()).getAllData().indexOf(data); ArrayList dataIndices = new ArrayList<>(); From 6cb3034b0ca39f787729823d7511bbe9486e0f11 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 12:17:03 +0200 Subject: [PATCH 0989/1390] Fix minmax calculations for realm implementation --- .../data/realm/base/RealmBaseDataSet.java | 37 ++++---------- .../realm/implementation/RealmBarDataSet.java | 20 ++------ .../implementation/RealmBubbleDataSet.java | 48 +++---------------- .../implementation/RealmCandleDataSet.java | 20 ++------ 4 files changed, 22 insertions(+), 103 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 3e06759f66..7a55da224d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -28,24 +28,24 @@ public abstract class RealmBaseDataSet e protected List mValues; /** - * maximum y-value in the y-value array + * maximum y-value in the value array */ - protected float mYMax = 0.0f; + protected float mYMax = -Float.MAX_VALUE; /** - * the minimum y-value in the y-value array + * minimum y-value in the value array */ - protected float mYMin = 0.0f; + protected float mYMin = Float.MAX_VALUE; /** * maximum x-value in the value array */ - protected float mXMax = 0.0f; + protected float mXMax = -Float.MAX_VALUE; /** * minimum x-value in the value array */ - protected float mXMin = 0.0f; + protected float mXMin = Float.MAX_VALUE; /** * fieldname of the column that contains the y-values of this dataset @@ -130,33 +130,16 @@ public int getEntryCount() { @Override public void calcMinMax() { - if (mValues == null) - return; - - if (mValues.size() == 0) + if (mValues == null || mValues.isEmpty()) return; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; for (S e : mValues) { - - if (e != null && !Float.isNaN(e.getY())) { - calcMinMax(e); - } - } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if (mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; + calcMinMax(e); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index f74379f5a6..13254d28c7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -107,17 +107,13 @@ public BarEntry buildEntryFromResultObject(T realmObject, float x) { @Override public void calcMinMax() { - if (mValues == null) + if (mValues == null || mValues.isEmpty()) return; - if (mValues.size() == 0) - return; - - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; for (BarEntry e : mValues) { @@ -146,16 +142,6 @@ public void calcMinMax() { mXMax = e.getX(); } } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if (mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } private void calcStackSize() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 05a7ff523d..27c4b308e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -65,60 +65,24 @@ public BubbleEntry buildEntryFromResultObject(T realmObject, float x) { @Override public void calcMinMax() { - if (mValues == null) + if (mValues == null || mValues.isEmpty()) return; - if (mValues.size() == 0) - return; - - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; - // need chart width to guess this properly - - for (BubbleEntry entry : mValues) { - - float ymin = entry.getY(); - float ymax = entry.getY(); - - if (ymin < mYMin) { - mYMin = ymin; - } - - if (ymax > mYMax) { - mYMax = ymax; - } - - final float xmin = entry.getX(); - final float xmax = entry.getX(); - - if (xmin < mXMin) { - mXMin = xmin; - } + for (BubbleEntry e : mValues) { - if (xmax > mXMax) { - mXMax = xmax; - } + calcMinMax(e); - final float size = entry.getSize(); + final float size = e.getSize(); if (size > mMaxSize) { mMaxSize = size; } } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if(mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 1328fb1e4f..1c08290656 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -137,17 +137,13 @@ public CandleEntry buildEntryFromResultObject(T realmObject, float x) { @Override public void calcMinMax() { - if (mValues == null) + if (mValues == null || mValues.isEmpty()) return; - if (mValues.size() == 0) - return; - - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; - - mXMin = Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; for (CandleEntry e : mValues) { @@ -163,16 +159,6 @@ public void calcMinMax() { if (e.getX() > mXMax) mXMax = e.getX(); } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - - if (mXMin == Float.MAX_VALUE) { - mXMin = 0.f; - mXMax = 0.f; - } } /** From 2e5217edefc80ccbe3307d5a3cdff07adeb64337 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 12:23:58 +0200 Subject: [PATCH 0990/1390] Cleanup realm --- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 3 +-- .../realm/RealmWikiExample.java | 2 -- .../realm/implementation/RealmBarData.java | 21 ------------------- .../realm/implementation/RealmBubbleData.java | 21 ------------------- .../realm/implementation/RealmCandleData.java | 21 ------------------- .../realm/implementation/RealmLineData.java | 21 ------------------- .../realm/implementation/RealmPieData.java | 19 ----------------- .../realm/implementation/RealmRadarData.java | 21 ------------------- .../implementation/RealmScatterData.java | 21 ------------------- 14 files changed, 6 insertions(+), 154 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index a03a1ad959..54e4c55bfd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -50,7 +50,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "value"); // stacked entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); set.setLabel("Realm BarDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index 24e3931e6b..c2c2003d2e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "value", "bubbleSize"); + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); set.setColors(ColorTemplate.COLORFUL_COLORS, 110); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index b73d122855..4e04cf09df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "value"); + RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); set.setDrawCubic(false); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 8a2ca4545a..8bcda98356 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -54,7 +54,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "value", "label"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index b4cb14840f..fe408bdc00 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -56,7 +56,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "value"); // stacked entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "yValue"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index caa0190922..d89545a949 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.implementation.RealmScatterData; import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -54,7 +53,7 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "value"); + RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 06408f6878..c31e6b238c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -9,9 +9,7 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineData; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java deleted file mode 100644 index a230385032..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmBarData extends BarData { - - public RealmBarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java deleted file mode 100644 index ec23ec516b..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmBubbleData extends BubbleData { - - public RealmBubbleData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - ////RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java deleted file mode 100644 index fbe2cb6a92..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmCandleData extends CandleData { - - public RealmCandleData(RealmResults result,String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java deleted file mode 100644 index cee63fa6cc..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmLineData extends LineData { - - public RealmLineData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java deleted file mode 100644 index 3a08452813..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieData.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmPieData extends PieData { - - public RealmPieData(RealmResults result,String xPositionField, String xLabelField, IPieDataSet dataSet) { - super(dataSet); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java deleted file mode 100644 index e2a1d95811..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmRadarData extends RadarData{ - - public RealmRadarData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java deleted file mode 100644 index 480455c30c..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterData.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.base.RealmUtils; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; - -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public class RealmScatterData extends ScatterData { - - public RealmScatterData(RealmResults result, String xPositionField, String xLabelField, List dataSets) { - super(dataSets); - //RealmUtils.toXVals(result, xPositionField, xLabelField) - } -} From df91cedee3108d56498d4613ff4d9fe47d4ec858 Mon Sep 17 00:00:00 2001 From: wajdi chamakhi Date: Thu, 9 Jun 2016 12:09:16 +0100 Subject: [PATCH 0991/1390] Adding control on text Boldness in XAxis, YAxis, Limit Legends --- .../charting/components/ComponentBase.java | 23 +++++++++++++++++++ .../charting/renderer/LegendRenderer.java | 2 ++ .../charting/renderer/XAxisRenderer.java | 4 ++++ .../XAxisRendererHorizontalBarChart.java | 3 +++ .../renderer/XAxisRendererRadarChart.java | 1 + .../charting/renderer/YAxisRenderer.java | 2 ++ .../YAxisRendererHorizontalBarChart.java | 4 +++- .../renderer/YAxisRendererRadarChart.java | 1 + 8 files changed, 39 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 713f89dd79..5c0c596508 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -43,6 +43,11 @@ public abstract class ComponentBase { */ protected int mTextColor = Color.BLACK; + /** + * the text style boldness {Default = false} + */ + protected boolean mTextBold = false; + public ComponentBase() { } @@ -130,6 +135,24 @@ public float getTextSize() { return mTextSize; } + /** + * set the text to be bold + * + * @param bold + */ + public void setTextBold(boolean bold) { + mTextBold = bold; + } + + /** + * returns the text boldness + * + * @return + */ + public boolean getTextBold() { + return mTextBold; + } + /** * Sets the text color to use for the labels. Make sure to use * getResources().getColor(...) when using a color from the resources. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index f005a1f2ac..a35653446e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -167,6 +167,7 @@ public void computeLegend(ChartData data) { mLegendLabelPaint.setTypeface(tf); mLegendLabelPaint.setTextSize(mLegend.getTextSize()); + mLegendLabelPaint.setFakeBoldText(mLegend.getTextBold()); mLegendLabelPaint.setColor(mLegend.getTextColor()); // calculate all dimensions of the mLegend @@ -184,6 +185,7 @@ public void renderLegend(Canvas c) { mLegendLabelPaint.setTypeface(tf); mLegendLabelPaint.setTextSize(mLegend.getTextSize()); + mLegendLabelPaint.setFakeBoldText(mLegend.getTextBold()); mLegendLabelPaint.setColor(mLegend.getTextColor()); float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index f3e0ac40b3..a8b6056f81 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -36,6 +36,7 @@ public void computeAxis(float xValMaximumLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); StringBuilder widthText = new StringBuilder(); @@ -82,6 +83,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); if (mXAxis.getPosition() == XAxisPosition.TOP) { @@ -293,6 +295,8 @@ public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position mLimitLinePaint.setColor(limitLine.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(limitLine.getTextSize()); + mLimitLinePaint.setFakeBoldText(limitLine.getTextBold()); + float xOffset = limitLine.getLineWidth() + limitLine.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index e862263520..0fe0f46ad8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -31,6 +31,7 @@ public void computeAxis(float xValAverageLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mXAxis.setValues(xValues); String longest = mXAxis.getLongestLabel(); @@ -61,6 +62,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); if (mXAxis.getPosition() == XAxisPosition.TOP) { @@ -237,6 +239,7 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); + mLimitLinePaint.setFakeBoldText(l.getTextBold()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 50a2fc7dd4..228e818d83 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -30,6 +30,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); float sliceangle = mChart.getSliceAngle(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index fdae353e4b..9e37d71e00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -193,6 +193,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); float xoffset = mYAxis.getXOffset(); @@ -381,6 +382,7 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTypeface(l.getTypeface()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); + mLimitLinePaint.setFakeBoldText(l.getTextBold()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index bcd63778a0..098542f3fc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -7,7 +7,6 @@ import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; @@ -78,6 +77,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); mAxisLabelPaint.setTextAlign(Align.CENTER); @@ -140,6 +140,7 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); for (int i = 0; i < mYAxis.mEntryCount; i++) { @@ -243,6 +244,7 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTypeface(l.getTypeface()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); + mLimitLinePaint.setFakeBoldText(l.getTextBold()); float xOffset = l.getLineWidth() + l.getXOffset(); float yOffset = Utils.convertDpToPixel(2f) + l.getYOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 66ddd3ceea..220a4735d2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -137,6 +137,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); PointF center = mChart.getCenterOffsets(); From e5af5692e4689061c2a98bda8df1b10998222e82 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 18:04:01 +0200 Subject: [PATCH 0992/1390] Improvements to example --- .../mpchartexample/BarChartActivity.java | 2 +- .../mpchartexample/ScrollViewActivity.java | 1 + .../mpchartexample/StackedBarActivity.java | 1 + .../custom/DayAxisValueFormatter.java | 5 +---- .../fragments/ComplexityFragment.java | 1 - .../mpchartexample/fragments/SimpleFragment.java | 16 ++-------------- .../mikephil/charting/utils/FileUtils.java | 2 +- 7 files changed, 7 insertions(+), 21 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 448b0f8ba5..410ffbdc82 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -224,7 +224,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - float start = 1f; + float start = 0f; mChart.getXAxis().setAxisMinValue(start); mChart.getXAxis().setAxisMaxValue(start + count + 2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index f04d843904..617a25b2e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -45,6 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setEnabled(false); setData(10); + mChart.setFitBars(true); } private void setData(int count) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 24038acbe9..ae17135bad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -210,6 +210,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.setData(data); } + mChart.setFitBars(true); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 4299f48bce..11e411a7c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -26,9 +26,6 @@ public String getFormattedValue(float value, AxisBase axis) { int days = (int) value; - if (days == 0) - return ""; - int year = determineYear(days); int month = determineMonth(days); @@ -72,7 +69,7 @@ public String getFormattedValue(float value, AxisBase axis) { break; } - return dayOfMonth + appendix + " " + monthName; + return dayOfMonth == 0 ? "" : dayOfMonth + appendix + " " + monthName; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 8213f4f017..98b904b2b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -41,7 +41,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 2e837b1a19..3d4d9893be 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -54,7 +54,7 @@ protected BarData generateBarData(int dataSets, float range, int count) { // entries = FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "stacked_bars.txt"); for(int j = 0; j < count; j++) { - entries.add(new BarEntry((float) (Math.random() * range) + range / 4, j)); + entries.add(new BarEntry(j, (float) (Math.random() * range) + range / 4)); } BarDataSet ds = new BarDataSet(entries, getLabel(i)); @@ -78,7 +78,7 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) ArrayList entries = new ArrayList(); for(int j = 0; j < count; j++) { - entries.add(new Entry((float) (Math.random() * range) + range / 4, j)); + entries.add(new Entry(j, (float) (Math.random() * range) + range / 4)); } ScatterDataSet ds = new ScatterDataSet(entries, getLabel(i)); @@ -122,11 +122,6 @@ protected PieData generatePieData() { protected LineData generateLineData() { -// DataSet ds1 = new DataSet(n, "O(n)"); -// DataSet ds2 = new DataSet(nlogn, "O(nlogn)"); -// DataSet ds3 = new DataSet(nsquare, "O(n\u00B2)"); -// DataSet ds4 = new DataSet(nthree, "O(n\u00B3)"); - ArrayList sets = new ArrayList(); LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "sine.txt"), "Sine function"); @@ -145,13 +140,6 @@ protected LineData generateLineData() { sets.add(ds1); sets.add(ds2); -// sets.add(FileUtils.dataSetFromAssets(getActivity().getAssets(), "n.txt")); -// sets.add(FileUtils.dataSetFromAssets(getActivity().getAssets(), "nlogn.txt")); -// sets.add(FileUtils.dataSetFromAssets(getActivity().getAssets(), "square.txt")); -// sets.add(FileUtils.dataSetFromAssets(getActivity().getAssets(), "three.txt")); - - int max = Math.max(sets.get(0).getEntryCount(), sets.get(1).getEntryCount()); - LineData d = new LineData(sets); d.setValueTypeface(tf); return d; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java index dac8573d5d..5aff51ff84 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FileUtils.java @@ -122,7 +122,7 @@ public static List loadEntriesFromAssets(AssetManager am, String path) { String[] split = line.split("#"); if (split.length <= 2) { - entries.add(new Entry(Float.parseFloat(split[0]), Integer.parseInt(split[1]))); + entries.add(new Entry(Float.parseFloat(split[1]), Float.parseFloat(split[0]))); } else { float[] vals = new float[split.length - 1]; From b0f5ec1bf1ede58cfa02fff176a4dd896d390827 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 9 Jun 2016 18:17:32 +0200 Subject: [PATCH 0993/1390] Example cleanup and improvements --- .../mpchartexample/AnotherBarActivity.java | 8 -------- .../mpchartexample/BarChartActivity.java | 13 ++++--------- .../BarChartActivityMultiDataset.java | 17 ++++------------- .../mpchartexample/BarChartActivitySinus.java | 11 +++-------- .../mpchartexample/BubbleChartActivity.java | 13 ++++--------- .../CandleStickChartActivity.java | 8 -------- .../mpchartexample/CombinedChartActivity.java | 1 + .../mpchartexample/CubicLineChartActivity.java | 9 ++------- .../HorizontalBarChartActivity.java | 13 ++++--------- .../mpchartexample/LineChartActivity2.java | 11 ++++------- .../mpchartexample/LineChartTime.java | 10 ++-------- .../ListViewBarChartActivity.java | 12 ++++-------- .../mpchartexample/PieChartActivity.java | 8 ++------ .../mpchartexample/RadarChartActivitry.java | 16 +++++----------- .../RealtimeLineChartActivity.java | 8 +++----- .../mpchartexample/ScatterChartActivity.java | 12 ++++-------- .../mpchartexample/notimportant/DemoBase.java | 15 +++++++++++++++ 17 files changed, 61 insertions(+), 124 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 4b12f8c98c..7e867af488 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -73,14 +73,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.animateY(2500); mChart.getLegend().setEnabled(false); - - // Legend l = mChart.getLegend(); - // l.setPosition(LegendPosition.BELOW_CHART_CENTER); - // l.setFormSize(8f); - // l.setFormToTextSpace(4f); - // l.setXEntrySpace(6f); - - // mChart.setDrawLegend(false); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 410ffbdc82..57d28ce0fb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.graphics.PointF; import android.graphics.RectF; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -47,8 +46,6 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListene private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - private Typeface mTf; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -80,11 +77,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTf); + xAxis.setTypeface(mTfLight); xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day xAxis.setLabelCount(7); @@ -93,7 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { AxisValueFormatter custom = new MyAxisValueFormatter(); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTf); + leftAxis.setTypeface(mTfLight); leftAxis.setLabelCount(8, false); leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); @@ -102,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTf); + rightAxis.setTypeface(mTfLight); rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); @@ -254,7 +249,7 @@ private void setData(int count, float range) { BarData data = new BarData(dataSets); data.setValueTextSize(10f); - data.setValueTypeface(mTf); + data.setValueTypeface(mTfLight); data.setBarWidth(0.9f); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index e49e2ecadd..e43c4f33d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -38,8 +37,6 @@ public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarC private BarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -74,27 +71,21 @@ protected void onCreate(Bundle savedInstanceState) { // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - // define an offset to change the original position of the marker - // (optional) - // mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight()); - // set the marker to the chart mChart.setMarkerView(mv); mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); - l.setTypeface(tf); + l.setTypeface(mTfLight); l.setYOffset(0f); l.setYEntrySpace(0f); l.setTextSize(8f); XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); + xl.setTypeface(mTfLight); xl.setGranularity(1f); xl.setCenterAxisLabels(true); xl.setValueFormatter(new AxisValueFormatter() { @@ -110,7 +101,7 @@ public int getDecimalDigits() { }); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(tf); + leftAxis.setTypeface(mTfLight); leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); leftAxis.setSpaceTop(30f); @@ -253,7 +244,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { data.setValueFormatter(new LargeValueFormatter()); // add space between the dataset groups in percent of bar-width - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 31937a7a31..a61c357b13 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -34,8 +33,6 @@ public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeLi private SeekBar mSeekBarX; private TextView tvX; - private Typeface mTf; - private List mSinusData; @Override @@ -73,13 +70,11 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XAxis xAxis = mChart.getXAxis(); xAxis.setEnabled(false); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTf); + leftAxis.setTypeface(mTfLight); leftAxis.setLabelCount(6, false); leftAxis.setAxisMinValue(-2.5f); leftAxis.setAxisMaxValue(2.5f); @@ -88,7 +83,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTf); + rightAxis.setTypeface(mTfLight); rightAxis.setLabelCount(6, false); rightAxis.setAxisMinValue(-2.5f); rightAxis.setAxisMaxValue(2.5f); @@ -222,7 +217,7 @@ private void setData(int count) { BarData data = new BarData(set); data.setValueTextSize(10f); - data.setValueTypeface(mTf); + data.setValueTypeface(mTfLight); data.setDrawValues(false); data.setBarWidth(0.8f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index fb46034d5f..72e09797f5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -36,8 +35,6 @@ public class BubbleChartActivity extends DemoBase implements OnSeekBarChangeList private BubbleChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -58,8 +55,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BubbleChart) findViewById(R.id.chart1); mChart.setDescription(""); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); @@ -78,10 +73,10 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); - l.setTypeface(tf); + l.setTypeface(mTfLight); YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); + yl.setTypeface(mTfLight); yl.setSpaceTop(30f); yl.setSpaceBottom(30f); yl.setDrawZeroLine(false); @@ -90,7 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setPosition(XAxis.XAxisPosition.BOTTOM); - xl.setTypeface(tf); + xl.setTypeface(mTfLight); } @Override @@ -205,7 +200,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a data object with the datasets BubbleData data = new BubbleData(dataSets); data.setDrawValues(false); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); data.setValueTextSize(8f); data.setValueTextColor(Color.WHITE); data.setHighlightCircleWidth(1.5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 51e7aa6bf9..1a9d899624 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -80,14 +80,6 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(100); mChart.getLegend().setEnabled(false); - - // Legend l = mChart.getLegend(); - // l.setPosition(LegendPosition.BELOW_CHART_CENTER); - // l.setFormSize(8f); - // l.setFormToTextSpace(4f); - // l.setXEntrySpace(6f); - - // mChart.setDrawLegend(false); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index aacced57f3..49adb19e7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -95,6 +95,7 @@ public int getDecimalDigits() { data.setData(generateBubbleData()); data.setData(generateScatterData()); data.setData(generateCandleData()); + data.setValueTypeface(mTfLight); xAxis.setAxisMaxValue(data.getXMax() + 0.25f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 10e874ac48..a775b5d8fb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -32,8 +31,6 @@ public class CubicLineChartActivity extends DemoBase implements OnSeekBarChangeL private LineChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -73,13 +70,11 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XAxis x = mChart.getXAxis(); x.setEnabled(false); YAxis y = mChart.getAxisLeft(); - y.setTypeface(tf); + y.setTypeface(mTfLight); y.setLabelCount(6, false); y.setTextColor(Color.WHITE); y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); @@ -307,7 +302,7 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv // create a data object with the datasets LineData data = new LineData(set1); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); data.setValueTextSize(9f); data.setDrawValues(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 301501f77f..5151b48d85 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -4,7 +4,6 @@ import android.annotation.SuppressLint; import android.graphics.PointF; import android.graphics.RectF; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -40,8 +39,6 @@ public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarCha private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - private Typeface tf; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -77,25 +74,23 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - XAxis xl = mChart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(tf); + xl.setTypeface(mTfLight); xl.setDrawAxisLine(true); xl.setDrawGridLines(false); xl.setGridLineWidth(0.3f); xl.setGranularity(10f); YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); + yl.setTypeface(mTfLight); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); YAxis yr = mChart.getAxisRight(); - yr.setTypeface(tf); + yr.setTypeface(mTfLight); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); yr.setAxisMinValue(0f); // this replaces setStartAtZero(true) @@ -247,7 +242,7 @@ private void setData(int count, float range) { BarData data = new BarData(dataSets); data.setValueTextSize(10f); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); data.setBarWidth(barWidth); mChart.setData(data); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index e114db8521..24972f36ff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -86,29 +85,27 @@ protected void onCreate(Bundle savedInstanceState) { mChart.animateX(2500); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - // get the legend (only possible after setting data) Legend l = mChart.getLegend(); // modify the legend ... // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); - l.setTypeface(tf); + l.setTypeface(mTfLight); l.setTextSize(11f); l.setTextColor(Color.WHITE); l.setPosition(LegendPosition.BELOW_CHART_LEFT); // l.setYOffset(11f); XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(tf); + xAxis.setTypeface(mTfLight); xAxis.setTextSize(11f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(tf); + leftAxis.setTypeface(mTfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setAxisMaxValue(200f); leftAxis.setAxisMinValue(0f); @@ -116,7 +113,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setGranularityEnabled(true); YAxis rightAxis = mChart.getAxisRight(); - rightAxis.setTypeface(tf); + rightAxis.setTypeface(mTfLight); rightAxis.setTextColor(Color.RED); rightAxis.setAxisMaxValue(900); rightAxis.setAxisMinValue(-200); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 5ab32778eb..7d833625aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -2,11 +2,9 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; -import android.view.View; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -16,8 +14,6 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; @@ -79,15 +75,13 @@ protected void onCreate(Bundle savedInstanceState) { setData(100, 30); mChart.invalidate(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); - // get the legend (only possible after setting data) Legend l = mChart.getLegend(); l.setEnabled(false); XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); - xAxis.setTypeface(tf); + xAxis.setTypeface(mTfLight); xAxis.setTextSize(10f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); @@ -112,7 +106,7 @@ public int getDecimalDigits() { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); - leftAxis.setTypeface(tf); + leftAxis.setTypeface(mTfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 84360bd7b5..c3eb7fbf5e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -56,12 +56,8 @@ protected void onCreate(Bundle savedInstanceState) { private class ChartDataAdapter extends ArrayAdapter { - private Typeface mTf; - public ChartDataAdapter(Context context, List objects) { super(context, 0, objects); - - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); } @Override @@ -86,23 +82,23 @@ public View getView(int position, View convertView, ViewGroup parent) { } // apply styling - data.setValueTypeface(mTf); + data.setValueTypeface(mTfLight); data.setValueTextColor(Color.BLACK); holder.chart.setDescription(""); holder.chart.setDrawGridBackground(false); XAxis xAxis = holder.chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTf); + xAxis.setTypeface(mTfLight); xAxis.setDrawGridLines(false); YAxis leftAxis = holder.chart.getAxisLeft(); - leftAxis.setTypeface(mTf); + leftAxis.setTypeface(mTfLight); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(15f); YAxis rightAxis = holder.chart.getAxisRight(); - rightAxis.setTypeface(mTf); + rightAxis.setTypeface(mTfLight); rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(15f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 38d4799b99..c33fb9aadf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -39,8 +39,6 @@ public class PieChartActivity extends DemoBase implements OnSeekBarChangeListene private PieChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -67,9 +65,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDragDecelerationFrictionCoef(0.95f); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); + mChart.setCenterTextTypeface(mTfLight); mChart.setCenterText(generateCenterSpannableText()); mChart.setDrawHoleEnabled(true); @@ -228,7 +224,7 @@ private void setData(int count, float range) { data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); mChart.setData(data); // undo all highlights diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 17866470b1..0d3cacf35a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -24,8 +23,6 @@ import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -34,7 +31,6 @@ public class RadarChartActivitry extends DemoBase { private RadarChart mChart; - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -43,10 +39,8 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_radarchart_noseekbar); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); - TextView tv = (TextView) findViewById(R.id.textView); - tv.setTypeface(tf); + tv.setTypeface(mTfLight); tv.setTextColor(Color.WHITE); tv.setBackgroundColor(Color.rgb(60, 65, 82)); @@ -76,7 +70,7 @@ protected void onCreate(Bundle savedInstanceState) { Easing.EasingOption.EaseInOutQuad); XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(tf); + xAxis.setTypeface(mTfLight); xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); @@ -96,7 +90,7 @@ public int getDecimalDigits() { xAxis.setTextColor(Color.WHITE); YAxis yAxis = mChart.getYAxis(); - yAxis.setTypeface(tf); + yAxis.setTypeface(mTfLight); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setAxisMinValue(0f); @@ -105,7 +99,7 @@ public int getDecimalDigits() { Legend l = mChart.getLegend(); l.setPosition(LegendPosition.ABOVE_CHART_CENTER); - l.setTypeface(tf); + l.setTypeface(mTfLight); l.setXEntrySpace(7f); l.setYEntrySpace(5f); l.setTextColor(Color.WHITE); @@ -255,7 +249,7 @@ public void setData() { sets.add(set2); RadarData data = new RadarData(sets); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); data.setValueTextSize(8f); data.setDrawValues(false); data.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 2ec8b19e45..ab72539792 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -64,26 +64,24 @@ protected void onCreate(Bundle savedInstanceState) { // add empty data mChart.setData(data); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - // get the legend (only possible after setting data) Legend l = mChart.getLegend(); // modify the legend ... // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); - l.setTypeface(tf); + l.setTypeface(mTfLight); l.setTextColor(Color.WHITE); XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); + xl.setTypeface(mTfLight); xl.setTextColor(Color.WHITE); xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); xl.setEnabled(true); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(tf); + leftAxis.setTypeface(mTfLight); leftAxis.setTextColor(Color.WHITE); leftAxis.setAxisMaxValue(100f); leftAxis.setAxisMinValue(0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 7c5652f109..a0b3103e1e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -35,8 +35,6 @@ public class ScatterChartActivity extends DemoBase implements OnSeekBarChangeLis private ScatterChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - - private Typeface tf; @Override protected void onCreate(Bundle savedInstanceState) { @@ -57,8 +55,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (ScatterChart) findViewById(R.id.chart1); mChart.setDescription(""); - tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); @@ -77,16 +73,16 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); - l.setTypeface(tf); + l.setTypeface(mTfLight); YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); + yl.setTypeface(mTfLight); yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); + xl.setTypeface(mTfLight); xl.setDrawGridLines(false); } @@ -205,7 +201,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a data object with the datasets ScatterData data = new ScatterData(dataSets); - data.setValueTypeface(tf); + data.setValueTypeface(mTfLight); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index 7141be0aaa..59b73b1ad7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -1,6 +1,10 @@ package com.xxmassdeveloper.mpchartexample.notimportant; +import android.graphics.Typeface; +import android.os.Bundle; +import android.renderscript.Type; +import android.support.annotation.Nullable; import android.support.v4.app.FragmentActivity; import com.xxmassdeveloper.mpchartexample.R; @@ -23,6 +27,17 @@ public abstract class DemoBase extends FragmentActivity { "Party Y", "Party Z" }; + protected Typeface mTfRegular; + protected Typeface mTfLight; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mTfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + mTfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); + } + protected float getRandom(float range, float startsfrom) { return (float) (Math.random() * range) + startsfrom; } From 95dd249cf349778ff111193d61d64e08016a8843 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 14:12:44 +0200 Subject: [PATCH 0994/1390] Fixes related to slice space #1857, #1856, #1807, #1699, #1665, #1660, ... --- .../mpchartexample/PieChartActivity.java | 9 ++++---- .../charting/renderer/BarChartRenderer.java | 3 +-- .../charting/renderer/PieChartRenderer.java | 21 +++++++++++++++++-- .../charting/utils/ViewPortHandler.java | 12 ++++++++++- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index c33fb9aadf..d050f2d410 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -163,7 +163,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleSpin: { - mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption.EaseInCubic); + mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption + .EaseInCubic); break; } } @@ -183,16 +184,16 @@ private void setData(int count, float range) { float mult = range; - ArrayList yVals1 = new ArrayList(); + ArrayList values = new ArrayList(); // IMPORTANT: In a PieChart, no values (Entry) should have the same // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < count + 1; i++) { - yVals1.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); + values.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); } - PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); + PieDataSet dataSet = new PieDataSet(values, "Election Results"); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 27cfb77aa5..1698113de3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -235,8 +235,7 @@ public void drawValues(Canvas c) { drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), - dataSet.getValueTextColor - (j / 4)); + dataSet.getValueTextColor(j / 4)); } // if we have stacks diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 4c8fa78747..58973f0158 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -178,6 +178,22 @@ protected float calculateMinimumRadiusForSpacedSlice( return spacedRadius; } + /** + * Calculates the sliceSpace to use based on visible values and their size compared to the set sliceSpace. + * + * @param dataSet + * @return + */ + protected float getSliceSpace(IPieDataSet dataSet) { + + float spaceSizeRatio = dataSet.getSliceSpace() / mViewPortHandler.getSmallestContentExtension(); + float minValueRatio = dataSet.getYMin() / mChart.getData().getYValueSum() * 2; + + float sliceSpace = spaceSizeRatio > minValueRatio ? 0f : dataSet.getSliceSpace(); + + return sliceSpace; + } + protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = 0; @@ -205,7 +221,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } } - final float sliceSpace = visibleAngleCount <= 1 ? 0.f : dataSet.getSliceSpace(); + final float sliceSpace = visibleAngleCount <= 1 ? 0.f : getSliceSpace(dataSet); for (int j = 0; j < entryCount; j++) { @@ -411,6 +427,8 @@ public void drawValues(Canvas c) { float offset = Utils.convertDpToPixel(5.f); + final float sliceSpace = getSliceSpace(dataSet); + for (int j = 0; j < entryCount; j++) { PieEntry entry = dataSet.getEntryForIndex(j); @@ -421,7 +439,6 @@ public void drawValues(Canvas c) { angle = absoluteAngles[xIndex - 1] * phaseX; final float sliceAngle = drawAngles[xIndex]; - final float sliceSpace = dataSet.getSliceSpace(); final float sliceSpaceMiddleAngle = sliceSpace / (Utils.FDEG2RAD * labelRadius); // offset needed to center the drawn text in the slice diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 47ff9aa02e..e7cfac56b3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -8,7 +8,8 @@ import android.view.View; /** - * Class that contains information about the charts current viewport settings, including offsets, scale & translation levels, ... + * Class that contains information about the charts current viewport settings, including offsets, scale & translation + * levels, ... * * @author Philipp Jahoda */ @@ -173,6 +174,15 @@ public float getChartWidth() { return mChartWidth; } + /** + * Returns the smallest extension of the content rect (width or height). + * + * @return + */ + public float getSmallestContentExtension() { + return Math.min(mContentRect.width(), mContentRect.height()); + } + /** * ################ ################ ################ ################ */ From 4826f3be24e2b36f4d0f3a294536628d381bb7cb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 15:52:17 +0200 Subject: [PATCH 0995/1390] Improved combined example, add grouped bars --- .../mpchartexample/CombinedChartActivity.java | 39 +++++++++++++------ .../mikephil/charting/charts/BarChart.java | 3 +- .../mikephil/charting/data/BarData.java | 3 +- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 49adb19e7f..5034bd126b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -132,21 +132,36 @@ private LineData generateLineData() { private BarData generateBarData() { - BarData d = new BarData(); - d.setBarWidth(0.9f); + ArrayList entries1 = new ArrayList(); + ArrayList entries2 = new ArrayList(); - ArrayList entries = new ArrayList(); + for (int index = 0; index < itemcount; index++) { + entries1.add(new BarEntry(0, getRandom(25, 25))); + entries2.add(new BarEntry(0, getRandom(25, 25))); + } - for (int index = 0; index < itemcount; index++) - entries.add(new BarEntry(index + 0.5f, getRandom(25, 25))); + BarDataSet set1 = new BarDataSet(entries1, "Bar 1"); + set1.setColor(Color.rgb(60, 220, 78)); + set1.setValueTextColor(Color.rgb(60, 220, 78)); + set1.setValueTextSize(10f); + set1.setAxisDependency(YAxis.AxisDependency.LEFT); - BarDataSet set = new BarDataSet(entries, "Bar DataSet"); - set.setColor(Color.rgb(60, 220, 78)); - set.setValueTextColor(Color.rgb(60, 220, 78)); - set.setValueTextSize(10f); - d.addDataSet(set); + BarDataSet set2 = new BarDataSet(entries2, "Bar 2"); + set2.setColor(Color.rgb(61, 165, 255)); + set2.setValueTextColor(Color.rgb(61, 165, 255)); + set2.setValueTextSize(10f); + set2.setAxisDependency(YAxis.AxisDependency.LEFT); - set.setAxisDependency(YAxis.AxisDependency.LEFT); + float groupSpace = 0.06f; + float barSpace = 0.02f; // x2 dataset + float barWidth = 0.45f; // x2 dataset + // (0.45 + 0.02) * 2 + 0.06 = 1.00 -> interval per "group" + + BarData d = new BarData(set1, set2); + d.setBarWidth(barWidth); + + // make this BarData object grouped + d.groupBars(0, groupSpace, barSpace); // start at x = 0 return d; } @@ -198,7 +213,7 @@ protected BubbleData generateBubbleData() { for (int index = 0; index < itemcount; index++) { float y = getRandom(10, 105); - float size = getRandom(50, 105); + float size = getRandom(100, 105); entries.add(new BubbleEntry(index + 0.5f, y, size)); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index c5bd2c8fdc..60b15cc8c2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -201,7 +201,8 @@ public void setFitBars(boolean enabled) { /** * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. - * Leaves space as specified by the parameters. + * Previously set x-positions of entries will be overwritten. Leaves space between bars and groups as specified + * by the parameters. * Calls notifyDataSetChanged() afterwards. * * @param fromX the starting point on the x-axis where the grouping should begin diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 92109c7a2c..2cc22c8b72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -45,7 +45,8 @@ public float getBarWidth() { /** * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. - * Leaves space as specified by the parameters. + * Previously set x-positions of entries will be overwritten. Leaves space between bars and groups as specified + * by the parameters. * Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method. * * @param fromX the starting point on the x-axis where the grouping should begin From 694eb49162d06193067bb07f23456c865cc40a9e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 16:03:19 +0200 Subject: [PATCH 0996/1390] Fix issue in LegendRenderer --- .../mikephil/charting/data/CandleDataSet.java | 8 +++---- .../charting/renderer/LegendRenderer.java | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 124a6a3253..5288d7e3a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -55,23 +55,23 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im /** * color for open == close */ - protected int mNeutralColor = ColorTemplate.COLOR_NONE; + protected int mNeutralColor = ColorTemplate.COLOR_SKIP; /** * color for open < close */ - protected int mIncreasingColor = ColorTemplate.COLOR_NONE; + protected int mIncreasingColor = ColorTemplate.COLOR_SKIP; /** * color for open > close */ - protected int mDecreasingColor = ColorTemplate.COLOR_NONE; + protected int mDecreasingColor = ColorTemplate.COLOR_SKIP; /** * shadow line color, set -1 for backward compatibility and uses default * color */ - protected int mShadowColor = ColorTemplate.COLOR_NONE; + protected int mShadowColor = ColorTemplate.COLOR_SKIP; public CandleDataSet(List yVals, String label) { super(yVals, label); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 9092f42857..c3eccae292 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; @@ -124,10 +125,15 @@ public void computeLegend(ChartData data) { labels.add(pds.getLabel()); } - } else if(dataSet instanceof ICandleDataSet && ((ICandleDataSet) dataSet).getDecreasingColor() != ColorTemplate.COLOR_NONE) { + } else if (dataSet instanceof ICandleDataSet && ((ICandleDataSet) dataSet).getDecreasingColor() != + ColorTemplate.COLOR_NONE) { + + int decreasingColor = ((ICandleDataSet) dataSet).getDecreasingColor(); + colors.add(decreasingColor); + + int increasingColor = ((ICandleDataSet) dataSet).getIncreasingColor(); + colors.add(increasingColor); - colors.add(((ICandleDataSet) dataSet).getDecreasingColor()); - colors.add(((ICandleDataSet) dataSet).getIncreasingColor()); labels.add(null); labels.add(dataSet.getLabel()); @@ -252,7 +258,7 @@ public void renderLegend(Canvas c) { : mLegend.mNeededWidth / 2.0 - xoffset); } - break; + break; } switch (orientation) { @@ -288,8 +294,8 @@ public void renderLegend(Canvas c) { } if (posX == originPosX && - horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER && - lineIndex < calculatedLineSizes.length) { + horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER && + lineIndex < calculatedLineSizes.length) { posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT ? calculatedLineSizes[lineIndex].width : -calculatedLineSizes[lineIndex].width) / 2.f; @@ -311,7 +317,8 @@ public void renderLegend(Canvas c) { if (!isStacked) { if (drawingForm) - posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -formToTextSpace : formToTextSpace; + posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -formToTextSpace : + formToTextSpace; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) posX -= calculatedLabelSizes[i].width; From 82ca5e7e91fec244dc33c35650c9abf4d73f3c7a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 16:55:13 +0200 Subject: [PATCH 0997/1390] Highlighter cleanup --- .../charting/highlight/BarHighlighter.java | 18 +---- .../charting/highlight/ChartHighlighter.java | 76 ++++++++++++------- .../highlight/CombinedHighlighter.java | 12 +-- .../highlight/HorizontalBarHighlighter.java | 2 +- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 1d23073740..0b40dc0062 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -1,17 +1,11 @@ package com.github.mikephil.charting.highlight; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; -import com.github.mikephil.charting.utils.Utils; - -import java.util.List; /** * Created by Philipp Jahoda on 22/07/15. @@ -60,11 +54,7 @@ public Highlight getHighlight(float x, float y) { * @param yValue * @return */ - protected Highlight getStackedHighlight( - SelectionDetail selectionDetail, - IBarDataSet set, - float xVal, - double yValue) { + protected Highlight getStackedHighlight(SelectionDetail selectionDetail, IBarDataSet set, float xVal, double yValue) { BarEntry entry = set.getEntryForXPos(xVal); @@ -159,7 +149,7 @@ protected Range[] getRanges(BarEntry entry) { } @Override - protected float getDistance(float x, float y, float selX, float selY) { - return Math.abs(x - selX); + protected float getDistance(float x1, float y1, float x2, float y2) { + return Math.abs(x1 - x2); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index bc9a2aa84c..99a9c757eb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; -import com.github.mikephil.charting.utils.Utils; /** * Created by Philipp Jahoda on 21/07/15. @@ -69,14 +68,14 @@ protected PointD getValsForTouch(float x, float y) { */ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { - List valsAtIndex = getSelectionDetailsAtIndex(xVal); + List closestValues = getSelectionDetailsAtXPos(xVal); - float leftdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); - float rightdist = getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); + float leftAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.LEFT); + float rightAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.RIGHT); - YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; + YAxis.AxisDependency axis = leftAxisMinDist < rightAxisMinDist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - SelectionDetail detail = getClosestSelectionDetailByPixel(valsAtIndex, x, y, axis, mChart + SelectionDetail detail = getClosestSelectionDetailByPixel(closestValues, x, y, axis, mChart .getMaxHighlightDistance()); return detail; @@ -86,26 +85,24 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { * Returns the minimum distance from a touch value (in pixels) to the * closest value (in pixels) that is displayed in the chart. * - * @param valsAtIndex + * @param closestValues * @param pos * @param axis * @return */ - protected float getMinimumDistance(List valsAtIndex, - float pos, - YAxis.AxisDependency axis) { + protected float getMinimumDistance(List closestValues, float pos, YAxis.AxisDependency axis) { float distance = Float.MAX_VALUE; - for (int i = 0; i < valsAtIndex.size(); i++) { + for (int i = 0; i < closestValues.size(); i++) { - SelectionDetail sel = valsAtIndex.get(i); + SelectionDetail sel = closestValues.get(i); if (sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs(getSelectionPos(sel) - pos); - if (cdistance < distance) { - distance = cdistance; + float tempDistance = Math.abs(getSelectionPos(sel) - pos); + if (tempDistance < distance) { + distance = tempDistance; } } } @@ -118,12 +115,13 @@ protected float getSelectionPos(SelectionDetail sel) { } /** - * Returns a list of SelectionDetail object corresponding to the given xVal. + * Returns a list of SelectionDetail objects representing the entries closest to the given xVal. + * The returned list contains two objects per DataSet (closest rounding up, closest rounding down). * * @param xVal * @return */ - protected List getSelectionDetailsAtIndex(float xVal) { + protected List getSelectionDetailsAtXPos(float xVal) { List vals = new ArrayList(); @@ -137,14 +135,23 @@ protected List getSelectionDetailsAtIndex(float xVal) { if (!dataSet.isHighlightEnabled()) continue; - vals.add(getDetails(dataSet, i, xVal, DataSet.Rounding.UP)); - vals.add(getDetails(dataSet, i, xVal, DataSet.Rounding.DOWN)); + vals.add(getDetail(dataSet, i, xVal, DataSet.Rounding.UP)); + vals.add(getDetail(dataSet, i, xVal, DataSet.Rounding.DOWN)); } return vals; } - protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + /** + * Returns the SelectionDetail object corresponding to the selected xValue and dataSetIndex. + * + * @param set + * @param dataSetIndex + * @param xVal + * @param rounding + * @return + */ + protected SelectionDetail getDetail(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { final Entry e = set.getEntryForXPos(xVal, rounding); @@ -160,20 +167,22 @@ protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, * Returns the SelectionDetail of the DataSet that contains the closest value on the * y-axis. * - * @param valsAtIndex all the values at a specific index + * @param closestValues contains two values per DataSet closest to the selected x-position (determined by rounding up and + * down) + * @param x + * @param y + * @param axis the closest axis * @return */ - public SelectionDetail getClosestSelectionDetailByPixel( - List valsAtIndex, - float x, float y, - YAxis.AxisDependency axis, float minSelectionDistance) { + public SelectionDetail getClosestSelectionDetailByPixel(List closestValues, float x, float y, + YAxis.AxisDependency axis, float minSelectionDistance) { SelectionDetail closest = null; float distance = minSelectionDistance; - for (int i = 0; i < valsAtIndex.size(); i++) { + for (int i = 0; i < closestValues.size(); i++) { - SelectionDetail sel = valsAtIndex.get(i); + SelectionDetail sel = closestValues.get(i); if (axis == null || sel.dataSet.getAxisDependency() == axis) { @@ -189,7 +198,16 @@ public SelectionDetail getClosestSelectionDetailByPixel( return closest; } - protected float getDistance(float x, float y, float selX, float selY) { - return (float) Math.hypot(x - selX, y - selY); + /** + * Calculates the distance between the two given points. + * + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @return + */ + protected float getDistance(float x1, float y1, float x2, float y2) { + return (float) Math.hypot(x1 - x2, y1 - y2); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 78aa797458..2c12598a45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -19,14 +19,8 @@ public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { super(chart); } - /** - * Returns a list of SelectionDetail object corresponding to the given xValue. - * - * @param xVal - * @return - */ @Override - protected List getSelectionDetailsAtIndex(float xVal) { + protected List getSelectionDetailsAtXPos(float xVal) { List vals = new ArrayList(); @@ -45,11 +39,11 @@ protected List getSelectionDetailsAtIndex(float xVal) { if (!dataSet.isHighlightEnabled()) continue; - SelectionDetail s1 = getDetails(dataSet, j, xVal, DataSet.Rounding.UP); + SelectionDetail s1 = getDetail(dataSet, j, xVal, DataSet.Rounding.UP); s1.dataIndex = i; vals.add(s1); - SelectionDetail s2 = getDetails(dataSet, j, xVal, DataSet.Rounding.DOWN); + SelectionDetail s2 = getDetail(dataSet, j, xVal, DataSet.Rounding.DOWN); s2.dataIndex = i; vals.add(s2); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 5e3cbdd3fb..73c420c4a7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -51,7 +51,7 @@ public Highlight getHighlight(float x, float y) { } @Override - protected SelectionDetail getDetails(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected SelectionDetail getDetail(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { final Entry e = set.getEntryForXPos(xVal, rounding); From 858600dcd2666cb7b563a808c088d8a42e8df7c1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 16:59:18 +0200 Subject: [PATCH 0998/1390] Cleanup renderers --- .../BarLineScatterCandleBubbleRenderer.java | 21 +++- .../renderer/CombinedChartRenderer.java | 2 - .../charting/renderer/DataRenderer.java | 1 - .../charting/renderer/LegendRenderer.java | 1 - .../charting/renderer/RadarChartRenderer.java | 8 -- .../renderer/ScatterChartRenderer.java | 1 - .../XAxisRendererHorizontalBarChart.java | 1 - .../charting/renderer/YAxisRenderer.java | 101 ------------------ .../YAxisRendererHorizontalBarChart.java | 1 - 9 files changed, 16 insertions(+), 121 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 9b6fdfabd6..b21cbef0e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -24,8 +24,7 @@ public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandle * @param dataSet * @return */ - protected XBounds getXBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet - dataSet) { + protected XBounds getXBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { return new XBounds(chart, dataSet); } @@ -34,15 +33,27 @@ protected XBounds getXBounds(BarLineScatterCandleBubbleDataProvider chart, IBarL */ protected class XBounds { - /** minimum visible entry index */ + /** + * minimum visible entry index + */ public final int min; - /** maximum visible entry index */ + /** + * maximum visible entry index + */ public final int max; - /** range of visible entry indices */ + /** + * range of visible entry indices + */ public final int range; + /** + * Calculates the minimum and maximum x values as well as the range between them. + * + * @param chart + * @param dataSet + */ public XBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 7718b95e2c..1f79868185 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -9,8 +9,6 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index c1822a7c05..39afe9389a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -8,7 +8,6 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index c3eccae292..0add1004e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -2,7 +2,6 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index ebf8435696..d593af582c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -139,14 +139,6 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { // draw the line (only if filled is disabled or alpha is below 255) if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) c.drawPath(surface, mRenderPaint); -// -// // draw filled -// if (dataSet.isDrawFilledEnabled()) { -// mRenderPaint.setStyle(Paint.Style.FILL); -// mRenderPaint.setAlpha(dataSet.getFillAlpha()); -// c.drawPath(surface, mRenderPaint); -// mRenderPaint.setAlpha(255); -// } } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index c3583c6579..94c881c82a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -4,7 +4,6 @@ import android.graphics.Canvas; import android.graphics.Paint.Style; import android.graphics.Path; -import android.graphics.Point; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.ScatterBuffer; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 10332ab99a..9f070e8ed0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -11,7 +11,6 @@ import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 27d56b63a1..f626ac752e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -40,107 +40,6 @@ public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer t } } -// @Override -// protected void computeAxisValues(float min, float max) { -// -// float yMin = min; -// float yMax = max; -// -// int labelCount = mYAxis.getLabelCount(); -// double range = Math.abs(yMax - yMin); -// -// if (labelCount == 0 || range <= 0) { -// mYAxis.mEntries = new float[]{}; -// mYAxis.mEntryCount = 0; -// return; -// } -// -// // Find out how much spacing (in y value space) between axis values -// double rawInterval = range / labelCount; -// double interval = Utils.roundToNextSignificant(rawInterval); -// -// // If granularity is enabled, then do not allow the interval to go below specified granularity. -// // This is used to avoid repeated values when rounding values for display. -// if (mYAxis.isGranularityEnabled()) -// interval = interval < mYAxis.getGranularity() ? mYAxis.getGranularity() : interval; -// -// // Normalize interval -// double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); -// int intervalSigDigit = (int) (interval / intervalMagnitude); -// if (intervalSigDigit > 5) { -// // Use one order of magnitude higher, to avoid intervals like 0.9 or -// // 90 -// interval = Math.floor(10 * intervalMagnitude); -// } -// -// // force label count -// if (mYAxis.isForceLabelsEnabled()) { -// -// float step = (float) range / (float) (labelCount - 1); -// mYAxis.mEntryCount = labelCount; -// -// if (mYAxis.mEntries.length < labelCount) { -// // Ensure stops contains at least numStops elements. -// mYAxis.mEntries = new float[labelCount]; -// } -// -// float v = min; -// -// for (int i = 0; i < labelCount; i++) { -// mYAxis.mEntries[i] = v; -// v += step; -// } -// -// // no forced count -// } else { -// -// // if the labels should only show min and max -// if (mYAxis.isShowOnlyMinMaxEnabled()) { -// -// mYAxis.mEntryCount = 2; -// mYAxis.mEntries = new float[2]; -// mYAxis.mEntries[0] = yMin; -// mYAxis.mEntries[1] = yMax; -// -// } else { -// -// double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; -// double last = interval == 0.0 ? 0.0 : Utils.nextUp(Math.floor(yMax / interval) * interval); -// -// double f; -// int i; -// int n = 0; -// if (interval != 0.0) { -// for (f = first; f <= last; f += interval) { -// ++n; -// } -// } -// -// mYAxis.mEntryCount = n; -// -// if (mYAxis.mEntries.length < n) { -// // Ensure stops contains at least numStops elements. -// mYAxis.mEntries = new float[n]; -// } -// -// for (f = first, i = 0; i < n; f += interval, ++i) { -// -// if (f == 0.0) // Fix for negative zero case (Where value == -0.0, and 0.0 == -0.0) -// f = 0.0; -// -// mYAxis.mEntries[i] = (float) f; -// } -// } -// } -// -// // set decimals -// if (interval < 1) { -// mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); -// } else { -// mYAxis.mDecimals = 0; -// } -// } - /** * draws the y-axis labels to the screen */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 1bb4598831..c1f510a3cf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -7,7 +7,6 @@ import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; From c28b41b05ed9d22aaac4816eccd46602cf3803dd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 10 Jun 2016 23:35:29 +0200 Subject: [PATCH 0999/1390] Work on highlighting --- .../mpchartexample/CombinedChartActivity.java | 7 +++++-- .../mikephil/charting/charts/BarChart.java | 1 - .../github/mikephil/charting/charts/Chart.java | 5 +++-- .../mikephil/charting/charts/CombinedChart.java | 2 +- .../charting/highlight/ChartHighlighter.java | 10 ++-------- .../charting/highlight/CombinedHighlighter.java | 17 +++++++++++++++-- .../charting/highlight/Highlighter.java | 16 ++++++++++++++++ 7 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 5034bd126b..5ce21a6a3f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -36,6 +36,7 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.Arrays; public class CombinedChartActivity extends DemoBase { @@ -137,7 +138,9 @@ private BarData generateBarData() { for (int index = 0; index < itemcount; index++) { entries1.add(new BarEntry(0, getRandom(25, 25))); - entries2.add(new BarEntry(0, getRandom(25, 25))); + + // stacked + entries2.add(new BarEntry(0, new float[]{getRandom(13, 12), getRandom(13, 12)})); } BarDataSet set1 = new BarDataSet(entries1, "Bar 1"); @@ -147,7 +150,7 @@ private BarData generateBarData() { set1.setAxisDependency(YAxis.AxisDependency.LEFT); BarDataSet set2 = new BarDataSet(entries2, "Bar 2"); - set2.setColor(Color.rgb(61, 165, 255)); + set2.setColors(new int[]{Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)}); set2.setValueTextColor(Color.rgb(61, 165, 255)); set2.setValueTextSize(10f); set2.setAxisDependency(YAxis.AxisDependency.LEFT); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 60b15cc8c2..dae084571f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -187,7 +187,6 @@ public BarData getBarData() { return mData; } - /** * Adds half of the bar width to each side of the x-axis range in order to allow the bars of the barchart to be * fully displayed. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ddcb1f8485..6da5c21d74 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -37,6 +37,7 @@ import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.highlight.Highlighter; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; @@ -162,7 +163,7 @@ public abstract class Chart { +public class ChartHighlighter implements Highlighter { /** * instance of the data-provider @@ -25,13 +25,7 @@ public ChartHighlighter(T chart) { this.mChart = chart; } - /** - * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. - * - * @param x - * @param y - * @return - */ + @Override public Highlight getHighlight(float x, float y) { float xVal = (float) getValsForTouch(x, y).x; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 2c12598a45..424f6e4af6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; @@ -13,10 +14,22 @@ /** * Created by Philipp Jahoda on 12/09/15. */ -public class CombinedHighlighter extends ChartHighlighter { +public class CombinedHighlighter extends ChartHighlighter implements Highlighter { - public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { + protected BarHighlighter barHighlighter; + + public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart, BarDataProvider barChart) { super(chart); + barHighlighter = new BarHighlighter(barChart); + } + + @Override + public Highlight getHighlight(float x, float y) { + + Highlight h1 = super.getHighlight(x, y); + Highlight h2 = barHighlighter.getHighlight(x, y); + + return h1; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java new file mode 100644 index 0000000000..cee50a9e57 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java @@ -0,0 +1,16 @@ +package com.github.mikephil.charting.highlight; + +/** + * Created by philipp on 10/06/16. + */ +public interface Highlighter { + + /** + * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. + * + * @param x + * @param y + * @return + */ + Highlight getHighlight(float x, float y); +} From f283de16983595235c4efc213f88f927adb7f383 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Jun 2016 00:07:53 +0200 Subject: [PATCH 1000/1390] Work on highlight --- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/highlight/BarHighlighter.java | 9 +++++-- .../charting/highlight/ChartHighlighter.java | 18 +++++++++---- .../highlight/CombinedHighlighter.java | 6 ++++- .../charting/highlight/Highlight.java | 25 +++++++------------ .../highlight/HorizontalBarHighlighter.java | 3 +-- 6 files changed, 36 insertions(+), 27 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 6da5c21d74..86795eaa34 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -633,7 +633,7 @@ public void highlightValue(Highlight high, boolean callListener) { } else { if (this instanceof BarLineChartBase && ((BarLineChartBase) this).isHighlightFullBarEnabled()) - high = new Highlight(high.getX(), Float.NaN, -1, -1, -1); + high = new Highlight(high.getX(), Float.NaN, -1, -1); // set the indices to highlight mIndicesToHighlight = new Highlight[]{ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 0b40dc0062..981063b710 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -2,6 +2,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.PointD; @@ -40,8 +41,7 @@ public Highlight getHighlight(float x, float y) { selectionDetail.xValue, selectionDetail.yValue, selectionDetail.dataIndex, - selectionDetail.dataSetIndex, - -1); + selectionDetail.dataSetIndex); } /** @@ -152,4 +152,9 @@ protected Range[] getRanges(BarEntry entry) { protected float getDistance(float x1, float y1, float x2, float y2) { return Math.abs(x1 - x2); } + + @Override + protected BarLineScatterCandleBubbleData getData() { + return mChart.getBarData(); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index a2700840a3..9b50cf6842 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -4,6 +4,8 @@ import java.util.List; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; +import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -69,8 +71,7 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { YAxis.AxisDependency axis = leftAxisMinDist < rightAxisMinDist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - SelectionDetail detail = getClosestSelectionDetailByPixel(closestValues, x, y, axis, mChart - .getMaxHighlightDistance()); + SelectionDetail detail = getClosestSelectionDetailByPixel(closestValues, x, y, axis, mChart.getMaxHighlightDistance()); return detail; } @@ -119,11 +120,14 @@ protected List getSelectionDetailsAtXPos(float xVal) { List vals = new ArrayList(); - if (mChart.getData() == null) return vals; + BarLineScatterCandleBubbleData data = getData(); - for (int i = 0, dataSetCount = mChart.getData().getDataSetCount(); i < dataSetCount; i++) { + if (data == null) + return vals; - IDataSet dataSet = mChart.getData().getDataSetByIndex(i); + for (int i = 0, dataSetCount = data.getDataSetCount(); i < dataSetCount; i++) { + + IDataSet dataSet = data.getDataSetByIndex(i); // dont include datasets that cannot be highlighted if (!dataSet.isHighlightEnabled()) @@ -204,4 +208,8 @@ public SelectionDetail getClosestSelectionDetailByPixel(List cl protected float getDistance(float x1, float y1, float x2, float y2) { return (float) Math.hypot(x1 - x2, y1 - y2); } + + protected BarLineScatterCandleBubbleData getData() { + return mChart.getData(); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 424f6e4af6..14a5bf832d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -29,7 +29,11 @@ public Highlight getHighlight(float x, float y) { Highlight h1 = super.getHighlight(x, y); Highlight h2 = barHighlighter.getHighlight(x, y); - return h1; + return getClosest(x, y, h1, h2); + } + + protected Highlight getClosest(float x, float y, Highlight... highs) { + return null; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index f46329f336..daf967b2af 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -14,6 +14,12 @@ public class Highlight { /** the y-value of the highlighted value */ private float mY = Float.NaN; + /** the x-pixel of the highlight */ + private float mXPx; + + /** the y-pixel of the highlight */ + private float mYPx; + /** the index of the data object - in case it refers to more than one */ private int mDataIndex; @@ -40,20 +46,6 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex) { this.mDataIndex = dataIndex; this.mDataSetIndex = dataSetIndex; } - /** - * Constructor, only used for stacked-barchart. - * - * @param x the x-value of the highlighted value on the x-axis - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to - * @param dataSetIndex the index of the DataSet the highlighted value belongs to - * @param stackIndex references which value of a stacked-bar entry has been - * selected - */ - public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex) { - this(x, y, dataIndex, dataSetIndex); - mStackIndex = stackIndex; - } /** * Constructor, only used for stacked-barchart. @@ -67,7 +59,8 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd * @param range the range the selected stack-value is in */ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex, Range range) { - this(x, y, dataIndex, dataSetIndex, stackIndex); + this(x, y, dataIndex, dataSetIndex); + this.mStackIndex = stackIndex; this.mRange = range; } @@ -78,7 +71,7 @@ public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackInd * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ public Highlight(float x, int dataSetIndex) { - this(x, Float.NaN, 0, dataSetIndex, -1); + this(x, Float.NaN, 0, dataSetIndex); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 73c420c4a7..7cdea1f930 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -46,8 +46,7 @@ public Highlight getHighlight(float x, float y) { selectionDetail.xValue, selectionDetail.yValue, selectionDetail.dataIndex, - selectionDetail.dataSetIndex, - -1); + selectionDetail.dataSetIndex); } @Override From 4b00e83479c1ed28b5a80b514a58331c9c07cc67 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Jun 2016 00:44:54 +0200 Subject: [PATCH 1001/1390] Remove SelectionDetail class --- .../mikephil/charting/charts/Chart.java | 3 +- .../charting/charts/PieRadarChartBase.java | 65 ++++++---- .../charting/highlight/BarHighlighter.java | 42 +++---- .../charting/highlight/ChartHighlighter.java | 72 +++++------ .../highlight/CombinedHighlighter.java | 42 +++++-- .../charting/highlight/Highlight.java | 119 +++++++++++++----- .../highlight/HorizontalBarHighlighter.java | 27 ++-- .../listener/PieRadarChartTouchListener.java | 3 +- .../charting/utils/SelectionDetail.java | 40 ------ .../github/mikephil/charting/utils/Utils.java | 21 ++-- 10 files changed, 228 insertions(+), 206 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 86795eaa34..c1e8f55fc7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -31,6 +31,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultValueFormatter; @@ -633,7 +634,7 @@ public void highlightValue(Highlight high, boolean callListener) { } else { if (this instanceof BarLineChartBase && ((BarLineChartBase) this).isHighlightFullBarEnabled()) - high = new Highlight(high.getX(), Float.NaN, -1, -1); + high = new Highlight(high.getX(), Float.NaN, Float.NaN, Float.NaN, -1, YAxis.AxisDependency.LEFT); // set the indices to highlight mIndicesToHighlight = new Highlight[]{ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 749346e38b..ca98146ef0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -17,9 +17,9 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; -import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -27,22 +27,30 @@ /** * Baseclass of PieChart and RadarChart. - * + * * @author Philipp Jahoda */ public abstract class PieRadarChartBase>> extends Chart { - /** holds the normalized version of the current rotation angle of the chart */ + /** + * holds the normalized version of the current rotation angle of the chart + */ private float mRotationAngle = 270f; - /** holds the raw version of the current rotation angle of the chart */ + /** + * holds the raw version of the current rotation angle of the chart + */ private float mRawRotationAngle = 270f; - /** flag that indicates if rotation is enabled or not */ + /** + * flag that indicates if rotation is enabled or not + */ protected boolean mRotateEnabled = true; - /** Sets the minimum offset (padding) around the chart, defaults to 0.f */ + /** + * Sets the minimum offset (padding) around the chart, defaults to 0.f + */ protected float mMinOffset = 0.f; public PieRadarChartBase(Context context) { @@ -115,8 +123,7 @@ public void calculateOffsets() { mLegend.getFormSize() + mLegend.getFormToTextSpace(); switch (mLegend.getOrientation()) { - case VERTICAL: - { + case VERTICAL: { float xLegendOffset = 0.f; if (mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.LEFT @@ -182,7 +189,7 @@ public void calculateOffsets() { break; } } - break; + break; case HORIZONTAL: float yLegendOffset = 0.f; @@ -247,7 +254,7 @@ public void calculateOffsets() { * returns the angle relative to the chart center for the given point on the * chart in degrees. The angle is always between 0 and 360°, 0° is NORTH, * 90° is EAST, ... - * + * * @param x * @param y * @return @@ -278,10 +285,10 @@ public float getAngleForPoint(float x, float y) { /** * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. - * + * * @param center * @param dist - * @param angle in degrees, converted to radians internally + * @param angle in degrees, converted to radians internally * @return */ protected PointF getPosition(PointF center, float dist, float angle) { @@ -329,7 +336,7 @@ public float distanceToCenter(float x, float y) { /** * Returns the xIndex for the given angle around the center of the chart. * Returns -1 if not found / outofbounds. - * + * * @param angle * @return */ @@ -338,7 +345,7 @@ public float distanceToCenter(float x, float y) { /** * Set an offset for the rotation of the RadarChart in degrees. Default 270f * --> top (NORTH) - * + * * @param angle */ public void setRotationAngle(float angle) { @@ -371,7 +378,7 @@ public float getRotationAngle() { /** * Set this to true to enable the rotation / spinning of the chart by touch. * Set it to false to disable it. Default: true - * + * * @param enabled */ public void setRotationEnabled(boolean enabled) { @@ -380,26 +387,30 @@ public void setRotationEnabled(boolean enabled) { /** * Returns true if rotation of the chart by touch is enabled, false if not. - * + * * @return */ public boolean isRotationEnabled() { return mRotateEnabled; } - /** Gets the minimum offset (padding) around the chart, defaults to 0.f */ + /** + * Gets the minimum offset (padding) around the chart, defaults to 0.f + */ public float getMinOffset() { return mMinOffset; } - /** Sets the minimum offset (padding) around the chart, defaults to 0.f */ + /** + * Sets the minimum offset (padding) around the chart, defaults to 0.f + */ public void setMinOffset(float minOffset) { mMinOffset = minOffset; } /** * returns the diameter of the pie- or radar-chart - * + * * @return */ public float getDiameter() { @@ -413,14 +424,14 @@ public float getDiameter() { /** * Returns the radius of the chart in pixels. - * + * * @return */ public abstract float getRadius(); /** * Returns the required offset for the chart legend. - * + * * @return */ protected abstract float getRequiredLegendOffset(); @@ -428,7 +439,7 @@ public float getDiameter() { /** * Returns the base offset needed for the chart without calculating the * legend size. - * + * * @return */ protected abstract float getRequiredBaseOffset(); @@ -446,16 +457,16 @@ public float getYChartMin() { } /** - * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail + * Returns an array of Highlight objects for the given x-index. The Highlight * objects give information about the value at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * * @return */ - public List getSelectionDetailsAtIndex(int xIndex) { + public List getSelectionDetailsAtIndex(int xIndex) { - List vals = new ArrayList(); + List vals = new ArrayList(); for (int i = 0; i < mData.getDataSetCount(); i++) { @@ -466,7 +477,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { if (Float.isNaN(yVal)) continue; - vals.add(new SelectionDetail(0f, yVal, i, dataSet)); + vals.add(new Highlight(0f, yVal, 0f, 0f, i, dataSet.getAxisDependency())); } return vals; @@ -479,7 +490,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { /** * Applys a spin animation to the Chart. - * + * * @param durationmillis * @param fromangle * @param toangle diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 981063b710..8d6b971561 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.PointD; -import com.github.mikephil.charting.utils.SelectionDetail; /** * Created by Philipp Jahoda on 22/07/15. @@ -24,37 +23,33 @@ public Highlight getHighlight(float x, float y) { PointD pos = getValsForTouch(x, y); - SelectionDetail selectionDetail = getSelectionDetail((float) pos.x, x, y); - if (selectionDetail == null) + Highlight high = getHighlightForX((float) pos.x, x, y); + if (high == null) return null; - IBarDataSet set = barData.getDataSetByIndex(selectionDetail.dataSetIndex); + IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex()); if (set.isStacked()) { - return getStackedHighlight(selectionDetail, + return getStackedHighlight(high, set, (float) pos.x, (float) pos.y); } - return new Highlight( - selectionDetail.xValue, - selectionDetail.yValue, - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); + return high; } /** * This method creates the Highlight object that also indicates which value of a stacked BarEntry has been * selected. * - * @param selectionDetail the selection detail to work with looking for stacked values + * @param high the Highlight to work with looking for stacked values * @param set * @param xVal - * @param yValue + * @param yVal * @return */ - protected Highlight getStackedHighlight(SelectionDetail selectionDetail, IBarDataSet set, float xVal, double yValue) { + protected Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) { BarEntry entry = set.getEntryForXPos(xVal); @@ -63,23 +58,26 @@ protected Highlight getStackedHighlight(SelectionDetail selectionDetail, IBarDat // not stacked if (entry.getYVals() == null) { - return new Highlight(entry.getX(), - entry.getY(), - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); + return high; } else { Range[] ranges = getRanges(entry); if (ranges.length > 0) { - int stackIndex = getClosestStackIndex(ranges, (float) yValue); - return new Highlight( + int stackIndex = getClosestStackIndex(ranges, yVal); + + + Highlight stackedHigh = new Highlight( entry.getX(), entry.getPositiveSum() - entry.getNegativeSum(), - selectionDetail.dataIndex, - selectionDetail.dataSetIndex, + high.getXPx(), + high.getYPx(), + high.getDataSetIndex(), stackIndex, - ranges[stackIndex] + ranges[stackIndex], + high.getAxis() ); + + return stackedHigh; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 9b50cf6842..035087cb1e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -5,13 +5,11 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; -import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.PointD; -import com.github.mikephil.charting.utils.SelectionDetail; /** * Created by Philipp Jahoda on 21/07/15. @@ -32,14 +30,8 @@ public Highlight getHighlight(float x, float y) { float xVal = (float) getValsForTouch(x, y).x; - SelectionDetail selectionDetail = getSelectionDetail(xVal, x, y); - if (selectionDetail == null) - return null; - - return new Highlight(selectionDetail.xValue, - selectionDetail.yValue, - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); + Highlight high = getHighlightForX(xVal, x, y); + return high; } /** @@ -56,22 +48,23 @@ protected PointD getValsForTouch(float x, float y) { } /** - * Returns the corresponding SelectionDetail for a given xVal and y-touch position in pixels. + * Returns the corresponding Highlight for a given xVal and x- and y-touch position in pixels. * * @param xVal + * @param x * @param y * @return */ - protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { + protected Highlight getHighlightForX(float xVal, float x, float y) { - List closestValues = getSelectionDetailsAtXPos(xVal); + List closestValues = getHighlightsAtXPos(xVal); float leftAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.LEFT); float rightAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.RIGHT); YAxis.AxisDependency axis = leftAxisMinDist < rightAxisMinDist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - SelectionDetail detail = getClosestSelectionDetailByPixel(closestValues, x, y, axis, mChart.getMaxHighlightDistance()); + Highlight detail = getClosestHighlightByPixel(closestValues, x, y, axis, mChart.getMaxHighlightDistance()); return detail; } @@ -85,17 +78,17 @@ protected SelectionDetail getSelectionDetail(float xVal, float x, float y) { * @param axis * @return */ - protected float getMinimumDistance(List closestValues, float pos, YAxis.AxisDependency axis) { + protected float getMinimumDistance(List closestValues, float pos, YAxis.AxisDependency axis) { float distance = Float.MAX_VALUE; for (int i = 0; i < closestValues.size(); i++) { - SelectionDetail sel = closestValues.get(i); + Highlight high = closestValues.get(i); - if (sel.dataSet.getAxisDependency() == axis) { + if (high.getAxis() == axis) { - float tempDistance = Math.abs(getSelectionPos(sel) - pos); + float tempDistance = Math.abs(getHighlightPos(high) - pos); if (tempDistance < distance) { distance = tempDistance; } @@ -105,20 +98,20 @@ protected float getMinimumDistance(List closestValues, float po return distance; } - protected float getSelectionPos(SelectionDetail sel) { - return sel.yPx; + protected float getHighlightPos(Highlight h) { + return h.getYPx(); } /** - * Returns a list of SelectionDetail objects representing the entries closest to the given xVal. + * Returns a list of Highlight objects representing the entries closest to the given xVal. * The returned list contains two objects per DataSet (closest rounding up, closest rounding down). * * @param xVal * @return */ - protected List getSelectionDetailsAtXPos(float xVal) { + protected List getHighlightsAtXPos(float xVal) { - List vals = new ArrayList(); + List vals = new ArrayList(); BarLineScatterCandleBubbleData data = getData(); @@ -133,15 +126,15 @@ protected List getSelectionDetailsAtXPos(float xVal) { if (!dataSet.isHighlightEnabled()) continue; - vals.add(getDetail(dataSet, i, xVal, DataSet.Rounding.UP)); - vals.add(getDetail(dataSet, i, xVal, DataSet.Rounding.DOWN)); + vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.UP)); + vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); } return vals; } /** - * Returns the SelectionDetail object corresponding to the selected xValue and dataSetIndex. + * Returns the Highlight object corresponding to the selected xValue and dataSetIndex. * * @param set * @param dataSetIndex @@ -149,7 +142,7 @@ protected List getSelectionDetailsAtXPos(float xVal) { * @param rounding * @return */ - protected SelectionDetail getDetail(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { final Entry e = set.getEntryForXPos(xVal, rounding); @@ -158,36 +151,37 @@ protected SelectionDetail getDetail(IDataSet set, int dataSetIndex, float xVal, PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); - return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); + return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } /** - * Returns the SelectionDetail of the DataSet that contains the closest value on the + * Returns the Highlight of the DataSet that contains the closest value on the * y-axis. * - * @param closestValues contains two values per DataSet closest to the selected x-position (determined by rounding up and - * down) + * @param closestValues contains two Highlight objects per DataSet closest to the selected x-position (determined by + * rounding up an down) * @param x * @param y - * @param axis the closest axis + * @param axis the closest axis + * @param minSelectionDistance * @return */ - public SelectionDetail getClosestSelectionDetailByPixel(List closestValues, float x, float y, - YAxis.AxisDependency axis, float minSelectionDistance) { + public Highlight getClosestHighlightByPixel(List closestValues, float x, float y, + YAxis.AxisDependency axis, float minSelectionDistance) { - SelectionDetail closest = null; + Highlight closest = null; float distance = minSelectionDistance; for (int i = 0; i < closestValues.size(); i++) { - SelectionDetail sel = closestValues.get(i); + Highlight high = closestValues.get(i); - if (axis == null || sel.dataSet.getAxisDependency() == axis) { + if (axis == null || high.getAxis() == axis) { - float cDistance = getDistance(x, y, sel.xPx, sel.yPx); + float cDistance = getDistance(x, y, high.getXPx(), high.getYPx()); if (cDistance < distance) { - closest = sel; + closest = high; distance = cDistance; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 14a5bf832d..dd66eb396d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; -import com.github.mikephil.charting.utils.SelectionDetail; import java.util.ArrayList; import java.util.List; @@ -16,30 +15,47 @@ */ public class CombinedHighlighter extends ChartHighlighter implements Highlighter { + /** + * bar highlighter for supporting stacked highlighting + */ protected BarHighlighter barHighlighter; public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart, BarDataProvider barChart) { super(chart); - barHighlighter = new BarHighlighter(barChart); + barHighlighter = barChart.getBarData() == null ? null : new BarHighlighter(barChart); } @Override public Highlight getHighlight(float x, float y) { Highlight h1 = super.getHighlight(x, y); - Highlight h2 = barHighlighter.getHighlight(x, y); + Highlight h2 = barHighlighter == null ? null : barHighlighter.getHighlight(x, y); - return getClosest(x, y, h1, h2); + return (h2 != null && h2.isStacked()) ? h2 : h1; } - protected Highlight getClosest(float x, float y, Highlight... highs) { - return null; - } +// protected Highlight getClosest(float x, float y, Highlight... highs) { +// +// Highlight closest = null; +// float minDistance = Float.MAX_VALUE; +// +// for (Highlight high : highs) { +// +// float tempDistance = getDistance(x, y, high.getXPx(), high.getYPx()); +// +// if (tempDistance < minDistance) { +// minDistance = tempDistance; +// closest = high; +// } +// } +// +// return closest; +// } @Override - protected List getSelectionDetailsAtXPos(float xVal) { + protected List getHighlightsAtXPos(float xVal) { - List vals = new ArrayList(); + List vals = new ArrayList(); CombinedData data = (CombinedData) mChart.getData(); @@ -56,12 +72,12 @@ protected List getSelectionDetailsAtXPos(float xVal) { if (!dataSet.isHighlightEnabled()) continue; - SelectionDetail s1 = getDetail(dataSet, j, xVal, DataSet.Rounding.UP); - s1.dataIndex = i; + Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.UP); + s1.setDataIndex(i); vals.add(s1); - SelectionDetail s2 = getDetail(dataSet, j, xVal, DataSet.Rounding.DOWN); - s2.dataIndex = i; + Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); + s2.setDataIndex(i); vals.add(s2); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index daf967b2af..d023c935ab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -1,77 +1,96 @@ package com.github.mikephil.charting.highlight; +import com.github.mikephil.charting.components.YAxis; + /** * Contains information needed to determine the highlighted value. - * + * * @author Philipp Jahoda */ public class Highlight { - /** the x-value of the highlighted value */ + /** + * the x-value of the highlighted value + */ private float mX = Float.NaN; - /** the y-value of the highlighted value */ + /** + * the y-value of the highlighted value + */ private float mY = Float.NaN; - /** the x-pixel of the highlight */ + /** + * the x-pixel of the highlight + */ private float mXPx; - /** the y-pixel of the highlight */ + /** + * the y-pixel of the highlight + */ private float mYPx; - /** the index of the data object - in case it refers to more than one */ + /** + * the index of the data object - in case it refers to more than one + */ private int mDataIndex; - /** the index of the dataset the highlighted value is in */ + /** + * the index of the dataset the highlighted value is in + */ private int mDataSetIndex; - /** index which value of a stacked bar entry is highlighted, default -1 */ + /** + * index which value of a stacked bar entry is highlighted, default -1 + */ private int mStackIndex = -1; - /** the range of the bar that is selected (only for stacked-barchart) */ + /** + * the range of the bar that is selected (only for stacked-barchart) + */ private Range mRange; /** - * constructor - * - * @param x the x-value of the highlighted value - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to - * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * the axis the highlighted value belongs to */ - public Highlight(float x, float y, int dataIndex, int dataSetIndex) { + private YAxis.AxisDependency axis; + + public Highlight(float x, int dataSetIndex) { this.mX = x; - this.mY = y; - this.mDataIndex = dataIndex; this.mDataSetIndex = dataSetIndex; } /** - * Constructor, only used for stacked-barchart. + * constructor * - * @param x the index of the highlighted value on the x-axis - * @param y the y-value of the highlighted value - * @param dataIndex the index of the Data the highlighted value belongs to + * @param x the x-value of the highlighted value + * @param y the y-value of the highlighted value * @param dataSetIndex the index of the DataSet the highlighted value belongs to - * @param stackIndex references which value of a stacked-bar entry has been - * selected - * @param range the range the selected stack-value is in */ - public Highlight(float x, float y, int dataIndex, int dataSetIndex, int stackIndex, Range range) { - this(x, y, dataIndex, dataSetIndex); - this.mStackIndex = stackIndex; - this.mRange = range; + public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis.AxisDependency axis) { + this.mX = x; + this.mY = y; + this.mXPx = xPx; + this.mYPx = yPx; + this.mDataSetIndex = dataSetIndex; + this.axis = axis; } /** * Constructor, only used for stacked-barchart. * - * @param x the x-value of the highlighted value on the x-axis + * @param x the index of the highlighted value on the x-axis + * @param y the y-value of the highlighted value * @param dataSetIndex the index of the DataSet the highlighted value belongs to + * @param stackIndex references which value of a stacked-bar entry has been + * selected + * @param range the range the selected stack-value is in */ - public Highlight(float x, int dataSetIndex) { - this(x, Float.NaN, 0, dataSetIndex); + public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, Range range, + YAxis.AxisDependency axis) { + this(x, y, xPx, yPx, dataSetIndex, axis); + this.mStackIndex = stackIndex; + this.mRange = range; } /** @@ -92,6 +111,20 @@ public float getY() { return mY; } + /** + * returns the x-position of the highlight in pixels + */ + public float getXPx() { + return mXPx; + } + + /** + * returns the y-position of the highlight in pixels + */ + public float getYPx() { + return mYPx; + } + /** * the index of the data object - in case it refers to more than one * @@ -101,6 +134,10 @@ public int getDataIndex() { return mDataIndex; } + public void setDataIndex(int mDataIndex) { + this.mDataIndex = mDataIndex; + } + /** * returns the index of the DataSet the highlighted value is in * @@ -113,7 +150,7 @@ public int getDataSetIndex() { /** * Only needed if a stacked-barchart entry was highlighted. References the * selected value within the stacked-entry. - * + * * @return */ public int getStackIndex() { @@ -122,16 +159,30 @@ public int getStackIndex() { /** * Returns the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart) + * * @return */ public Range getRange() { return mRange; } + public boolean isStacked() { + return mStackIndex >= 0; + } + + /** + * Returns the axis the highlighted value belongs to. + * + * @return + */ + public YAxis.AxisDependency getAxis() { + return axis; + } + /** * Returns true if this highlight object is equal to the other (compares * xIndex and dataSetIndex) - * + * * @param h * @return */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 7cdea1f930..c9f89dbe2f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,6 +1,5 @@ package com.github.mikephil.charting.highlight; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -8,10 +7,6 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.PointD; -import com.github.mikephil.charting.utils.SelectionDetail; -import com.github.mikephil.charting.utils.Utils; - -import java.util.List; /** * Created by Philipp Jahoda on 22/07/15. @@ -29,38 +24,34 @@ public Highlight getHighlight(float x, float y) { PointD pos = getValsForTouch(y, x); - SelectionDetail selectionDetail = getSelectionDetail((float) pos.y, y, x); - if (selectionDetail == null) + Highlight high = getHighlightForX((float) pos.y, y, x); + if (high == null) return null; - IBarDataSet set = barData.getDataSetByIndex(selectionDetail.dataSetIndex); + IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex()); if (set.isStacked()) { - return getStackedHighlight(selectionDetail, + return getStackedHighlight(high, set, (float) pos.y, (float) pos.x); } - return new Highlight( - selectionDetail.xValue, - selectionDetail.yValue, - selectionDetail.dataIndex, - selectionDetail.dataSetIndex); + return high; } @Override - protected SelectionDetail getDetail(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { final Entry e = set.getEntryForXPos(xVal, rounding); PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX()); - return new SelectionDetail((float) pixels.x, (float) pixels.y, e.getX(), e.getY(), dataSetIndex, set); + return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } @Override - protected float getDistance(float x, float y, float selX, float selY) { - return Math.abs(y - selY); + protected float getDistance(float x1, float y1, float x2, float y2) { + return Math.abs(y1 - y2); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index d40e2fdb4e..ca125dba41 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -11,7 +11,6 @@ import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -183,7 +182,7 @@ public boolean onSingleTapUp(MotionEvent e) { } else { - List valsAtIndex = mChart.getSelectionDetailsAtIndex(index); + List valsAtIndex = mChart.getSelectionDetailsAtIndex(index); int dataSetIndex = 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java deleted file mode 100644 index 0adeb4b787..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/SelectionDetail.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.github.mikephil.charting.utils; - -import com.github.mikephil.charting.interfaces.datasets.IDataSet; - -/** - * Class that encapsulates information of a value that has been - * selected/highlighted and its DataSet index. The SelectionDetail objects give - * information about the value at the selected index and the DataSet it belongs - * to. Needed only for highlighting onTouch(). - * - * @author Philipp Jahoda - */ -public class SelectionDetail { - - public float yPx; - public float xPx; - public float yValue; - public float xValue; - public int dataIndex; - public int dataSetIndex; - public IDataSet dataSet; - - public SelectionDetail(float xPx, float yPx, float xValue, float yValue, int dataIndex, int dataSetIndex, IDataSet set) { - this.xPx = xPx; - this.yPx = yPx; - this.xValue = xValue; - this.yValue = yValue; - this.dataIndex = dataIndex; - this.dataSetIndex = dataSetIndex; - this.dataSet = set; - } - - public SelectionDetail(float xPx, float yPx, float xValue, float yValue, int dataSetIndex, IDataSet set) { - this(xPx, yPx, xValue, yValue, 0, dataSetIndex, set); - } - - public SelectionDetail(float xValue, float yValue, int dataSetIndex, IDataSet set) { - this(Float.NaN, Float.NaN, xValue, yValue, 0, dataSetIndex, set); - } -} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 4e5fb6ac00..e375bd1534 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; import java.util.List; @@ -388,15 +389,15 @@ public static double nextUp(double d) { * @param valsAtIndex all the values at a specific index * @return */ - public static int getClosestDataSetIndexByValue(List valsAtIndex, float value, - AxisDependency axis) { + public static int getClosestDataSetIndexByValue(List valsAtIndex, float value, + AxisDependency axis) { - SelectionDetail sel = getClosestSelectionDetailByValue(valsAtIndex, value, axis); + Highlight sel = getClosestSelectionDetailByValue(valsAtIndex, value, axis); if (sel == null) return -Integer.MAX_VALUE; - return sel.dataSetIndex; + return sel.getDataSetIndex(); } /** @@ -406,21 +407,21 @@ public static int getClosestDataSetIndexByValue(List valsAtInde * @param valsAtIndex all the values at a specific index * @return */ - public static SelectionDetail getClosestSelectionDetailByValue( - List valsAtIndex, + public static Highlight getClosestSelectionDetailByValue( + List valsAtIndex, float value, AxisDependency axis) { - SelectionDetail closest = null; + Highlight closest = null; float distance = Float.MAX_VALUE; for (int i = 0; i < valsAtIndex.size(); i++) { - SelectionDetail sel = valsAtIndex.get(i); + Highlight sel = valsAtIndex.get(i); - if (axis == null || sel.dataSet.getAxisDependency() == axis) { + if (axis == null || sel.getAxis() == axis) { - float cdistance = Math.abs(sel.yValue - value); + float cdistance = Math.abs(sel.getY() - value); if (cdistance < distance) { closest = sel; distance = cdistance; From 0d9c8545f2efe476214096801c72544653a384d3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Jun 2016 23:44:30 +0200 Subject: [PATCH 1002/1390] Work on combined highlighting --- .../mpchartexample/CombinedChartActivity.java | 3 +- .../charting/charts/CombinedChart.java | 10 ++- .../mikephil/charting/data/CombinedData.java | 8 ++ .../charting/highlight/BarHighlighter.java | 13 +-- .../charting/highlight/ChartHighlighter.java | 16 ++-- .../highlight/CombinedHighlighter.java | 88 ++++++++++--------- .../charting/highlight/Highlight.java | 2 +- .../dataprovider/CombinedDataProvider.java | 11 +++ .../renderer/BubbleChartRenderer.java | 2 +- 9 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CombinedDataProvider.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 5ce21a6a3f..237d7d6cfc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -149,7 +149,8 @@ private BarData generateBarData() { set1.setValueTextSize(10f); set1.setAxisDependency(YAxis.AxisDependency.LEFT); - BarDataSet set2 = new BarDataSet(entries2, "Bar 2"); + BarDataSet set2 = new BarDataSet(entries2, ""); + set2.setStackLabels(new String[]{"Stack 1", "Stack 2"}); set2.setColors(new int[]{Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)}); set2.setValueTextColor(Color.rgb(61, 165, 255)); set2.setValueTextSize(10f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index d33dec05c9..710c82e4a5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -25,8 +26,7 @@ * * @author Philipp Jahoda */ -public class CombinedChart extends BarLineChartBase implements LineDataProvider, - BarDataProvider, ScatterDataProvider, CandleDataProvider, BubbleDataProvider { +public class CombinedChart extends BarLineChartBase implements CombinedDataProvider { // /** // * flag that enables or disables the highlighting arrow @@ -82,11 +82,17 @@ protected void init() { // mViewPortHandler); } + @Override + public CombinedData getCombinedData() { + return mData; + } + @Override public void setData(CombinedData data) { mData = null; mRenderer = null; super.setData(data); + setHighlighter(new CombinedHighlighter(this, this)); mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); mRenderer.initBuffers(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index fc1b566a07..33cacc304a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -97,6 +97,10 @@ public List getAllData() { return data; } + public ChartData getDataByIndex(int index) { + return getAllData().get(index); + } + @Override public void notifyDataChanged() { if (mLineData != null) @@ -145,4 +149,8 @@ public Entry getEntryForHighlight(Highlight highlight) { return null; } } + + public int getDataIndex(ChartData data) { + return getAllData().indexOf(data); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 8d6b971561..9f39fc599f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -49,7 +49,7 @@ public Highlight getHighlight(float x, float y) { * @param yVal * @return */ - protected Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) { + public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) { BarEntry entry = set.getEntryForXPos(xVal); @@ -65,15 +65,18 @@ protected Highlight getStackedHighlight(Highlight high, IBarDataSet set, float x if (ranges.length > 0) { int stackIndex = getClosestStackIndex(ranges, yVal); + Range range = ranges[stackIndex]; + + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), range.to); Highlight stackedHigh = new Highlight( entry.getX(), - entry.getPositiveSum() - entry.getNegativeSum(), - high.getXPx(), - high.getYPx(), + entry.getY(), + (float) pixels.x, + (float) pixels.y, high.getDataSetIndex(), stackIndex, - ranges[stackIndex], + range, high.getAxis() ); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 035087cb1e..9674504d4b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -1,16 +1,16 @@ package com.github.mikephil.charting.highlight; -import java.util.ArrayList; -import java.util.List; - import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.PointD; +import java.util.ArrayList; +import java.util.List; + /** * Created by Philipp Jahoda on 21/07/15. */ @@ -57,7 +57,7 @@ protected PointD getValsForTouch(float x, float y) { */ protected Highlight getHighlightForX(float xVal, float x, float y) { - List closestValues = getHighlightsAtXPos(xVal); + List closestValues = getHighlightsAtXPos(xVal, x, y); float leftAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.LEFT); float rightAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.RIGHT); @@ -106,10 +106,12 @@ protected float getHighlightPos(Highlight h) { * Returns a list of Highlight objects representing the entries closest to the given xVal. * The returned list contains two objects per DataSet (closest rounding up, closest rounding down). * - * @param xVal + * @param xVal the transformed x-value of the x-touch position + * @param x touch position + * @param y touch position * @return */ - protected List getHighlightsAtXPos(float xVal) { + protected List getHighlightsAtXPos(float xVal, float x, float y) { List vals = new ArrayList(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index dd66eb396d..418d7a38e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -1,11 +1,11 @@ package com.github.mikephil.charting.highlight; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import java.util.ArrayList; import java.util.List; @@ -13,25 +13,61 @@ /** * Created by Philipp Jahoda on 12/09/15. */ -public class CombinedHighlighter extends ChartHighlighter implements Highlighter { +public class CombinedHighlighter extends ChartHighlighter implements Highlighter { /** * bar highlighter for supporting stacked highlighting */ protected BarHighlighter barHighlighter; - public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart, BarDataProvider barChart) { + public CombinedHighlighter(CombinedDataProvider chart, BarDataProvider barChart) { super(chart); + + // if there is BarData, create a BarHighlighter barHighlighter = barChart.getBarData() == null ? null : new BarHighlighter(barChart); } @Override - public Highlight getHighlight(float x, float y) { + protected List getHighlightsAtXPos(float xVal, float x, float y) { + + List vals = new ArrayList(); + + List dataObjects = mChart.getCombinedData().getAllData(); + + for (int i = 0; i < dataObjects.size(); i++) { + + ChartData dataObject = dataObjects.get(i); + + // in case of BarData, let the BarHighlighter take over + if (barHighlighter != null && dataObject instanceof BarData) { + Highlight high = barHighlighter.getHighlight(x, y); + + if (high != null) { + high.setDataIndex(i); + vals.add(high); + } + } else { - Highlight h1 = super.getHighlight(x, y); - Highlight h2 = barHighlighter == null ? null : barHighlighter.getHighlight(x, y); + for (int j = 0, dataSetCount = dataObject.getDataSetCount(); j < dataSetCount; j++) { - return (h2 != null && h2.isStacked()) ? h2 : h1; + IDataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); + + // don't include datasets that cannot be highlighted + if (!dataSet.isHighlightEnabled()) + continue; + + Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.UP); + s1.setDataIndex(i); + vals.add(s1); + + Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); + s2.setDataIndex(i); + vals.add(s2); + } + } + } + + return vals; } // protected Highlight getClosest(float x, float y, Highlight... highs) { @@ -41,6 +77,9 @@ public Highlight getHighlight(float x, float y) { // // for (Highlight high : highs) { // +// if (high == null) +// continue; +// // float tempDistance = getDistance(x, y, high.getXPx(), high.getYPx()); // // if (tempDistance < minDistance) { @@ -51,37 +90,4 @@ public Highlight getHighlight(float x, float y) { // // return closest; // } - - @Override - protected List getHighlightsAtXPos(float xVal) { - - List vals = new ArrayList(); - - CombinedData data = (CombinedData) mChart.getData(); - - // get all chartdata objects - List dataObjects = data.getAllData(); - - for (int i = 0; i < dataObjects.size(); i++) { - - for (int j = 0, dataSetCount = dataObjects.get(i).getDataSetCount(); j < dataSetCount; j++) { - - IDataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); - - // don't include datasets that cannot be highlighted - if (!dataSet.isHighlightEnabled()) - continue; - - Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.UP); - s1.setDataIndex(i); - vals.add(s1); - - Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); - s2.setDataIndex(i); - vals.add(s2); - } - } - - return vals; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index d023c935ab..6a9be2af34 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -33,7 +33,7 @@ public class Highlight { /** * the index of the data object - in case it refers to more than one */ - private int mDataIndex; + private int mDataIndex = -1; /** * the index of the dataset the highlighted value is in diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CombinedDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CombinedDataProvider.java new file mode 100644 index 0000000000..574d26a2a2 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/CombinedDataProvider.java @@ -0,0 +1,11 @@ +package com.github.mikephil.charting.interfaces.dataprovider; + +import com.github.mikephil.charting.data.CombinedData; + +/** + * Created by philipp on 11/06/16. + */ +public interface CombinedDataProvider extends LineDataProvider, BarDataProvider, BubbleDataProvider, CandleDataProvider, ScatterDataProvider { + + CombinedData getCombinedData(); +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index b23cf3721e..7cf908ab8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -199,7 +199,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (dataSet == null || !dataSet.isHighlightEnabled()) continue; - final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(high); + final BubbleEntry entry = dataSet.getEntryForXPos(high.getX()); if (entry == null) continue; From 2b886a463e85a0e35e9641b75250b0460b6307c8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Jun 2016 16:11:37 +0200 Subject: [PATCH 1003/1390] Work on improving pie and radar highlighting --- .../mikephil/charting/charts/BarChart.java | 1 + .../charting/charts/BarLineChartBase.java | 53 ++++-------- .../mikephil/charting/charts/Chart.java | 29 +++++-- .../mikephil/charting/charts/PieChart.java | 18 ++-- .../charting/charts/PieRadarChartBase.java | 32 +------ .../mikephil/charting/charts/RadarChart.java | 34 ++++---- .../charting/highlight/PieHighlighter.java | 25 ++++++ .../highlight/PieRadarHighlighter.java | 66 ++++++++++++++ .../charting/highlight/RadarHighlighter.java | 85 +++++++++++++++++++ .../listener/PieRadarChartTouchListener.java | 61 +------------ .../charting/renderer/PieChartRenderer.java | 17 ++-- .../charting/renderer/RadarChartRenderer.java | 28 +----- 12 files changed, 259 insertions(+), 190 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieHighlighter.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index dae084571f..fbcf5ccc0b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index a4cf5b3b0b..ceeccd2b1a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -516,23 +516,24 @@ public void calculateOffsets() { prepareValuePxMatrix(); } - @Override - protected float[] getMarkerPosition(Entry e, Highlight highlight) { - - int dataSetIndex = highlight.getDataSetIndex(); - float xPos = e.getX(); - float yPos = e.getY() * mAnimator.getPhaseY(); - - // position of the marker depends on selected value index and value - float[] pts = new float[]{ - xPos, yPos - }; - - getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) - .pointValuesToPixel(pts); - - return pts; - } +// @Override +// protected float[] getMarkerPosition(Highlight high) { +// return new float[] { high.getXPx(), high.getYPx() }; +// +// int dataSetIndex = highlight.getDataSetIndex(); +// float xPos = e.getX(); +// float yPos = e.getY() * mAnimator.getPhaseY(); +// +// // position of the marker depends on selected value index and value +// float[] pts = new float[]{ +// xPos, yPos +// }; +// +// getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) +// .pointValuesToPixel(pts); +// +// return pts; +// } /** * draws the grid background @@ -1180,24 +1181,6 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { mKeepPositionOnRotation = keepPositionOnRotation; } - /** - * Returns the Highlight object (contains x-index and DataSet index) of the - * selected value at the given touch point inside the Line-, Scatter-, or - * CandleStick-Chart. - * - * @param x - * @param y - * @return - */ - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else - return getHighlighter().getHighlight(x, y); - } - /** * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index c1e8f55fc7..92812576fd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -664,6 +664,24 @@ public void highlightTouch(Highlight high) { highlightValue(high, true); } + /** + * Returns the Highlight object (contains x-index and DataSet index) of the + * selected value at the given touch point inside the Line-, Scatter-, or + * CandleStick-Chart. + * + * @param x + * @param y + * @return + */ + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else + return getHighlighter().getHighlight(x, y); + } + /** * Set a new (e.g. custom) ChartTouchListener NOTE: make sure to * setTouchEnabled(true); if you need touch gestures on the chart @@ -711,7 +729,7 @@ protected void drawMarkers(Canvas canvas) { if (e == null || entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) continue; - float[] pos = getMarkerPosition(e, highlight); + float[] pos = getMarkerPosition(highlight); // check bounds if (!mViewPortHandler.isInBounds(pos[0], pos[1])) @@ -736,13 +754,14 @@ protected void drawMarkers(Canvas canvas) { /** * Returns the actual position in pixels of the MarkerView for the given - * Entry in the given DataSet. + * Highlight object. * - * @param e - * @param highlight + * @param high * @return */ - protected abstract float[] getMarkerPosition(Entry e, Highlight highlight); + protected float[] getMarkerPosition(Highlight high) { + return new float[]{high.getXPx(), high.getYPx()}; + } /** * ################ ################ ################ ################ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 7440ca3141..f070da9988 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.highlight.PieHighlighter; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; @@ -111,6 +112,8 @@ protected void init() { mRenderer = new PieChartRenderer(this, mAnimator, mViewPortHandler); mXAxis = null; + + mHighlighter = new PieHighlighter(this); } @Override @@ -165,7 +168,7 @@ protected void calcMinMax() { } @Override - protected float[] getMarkerPosition(Entry e, Highlight highlight) { + protected float[] getMarkerPosition(Highlight highlight) { PointF center = getCenterCircleBox(); float r = getRadius(); @@ -233,24 +236,21 @@ private void calcAngles() { } /** - * checks if the given index in the given DataSet is set for highlighting or - * not + * Checks if the given index is set to be highlighted. * - * @param xIndex - * @param dataSetIndex + * @param index * @return */ - public boolean needsHighlight(int xIndex, int dataSetIndex) { + public boolean needsHighlight(int index) { // no highlight - if (!valuesToHighlight() || dataSetIndex < 0) + if (!valuesToHighlight()) return false; for (int i = 0; i < mIndicesToHighlight.length; i++) // check if the xvalue for the given dataset needs highlight - if (mIndicesToHighlight[i].getX() == xIndex - && mIndicesToHighlight[i].getDataSetIndex() == dataSetIndex) + if ((int) mIndicesToHighlight[i].getX() == index) return true; return false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index ca98146ef0..6a82bc13a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -22,9 +22,6 @@ import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; -import java.util.List; - /** * Baseclass of PieChart and RadarChart. * @@ -291,7 +288,7 @@ public float getAngleForPoint(float x, float y) { * @param angle in degrees, converted to radians internally * @return */ - protected PointF getPosition(PointF center, float dist, float angle) { + public PointF getPosition(PointF center, float dist, float angle) { PointF p = new PointF((float) (center.x + dist * Math.cos(Math.toRadians(angle))), (float) (center.y + dist * Math.sin(Math.toRadians(angle)))); @@ -456,33 +453,6 @@ public float getYChartMin() { return 0; } - /** - * Returns an array of Highlight objects for the given x-index. The Highlight - * objects give information about the value at the selected index and the - * DataSet it belongs to. INFORMATION: This method does calculations at - * runtime. Do not over-use in performance critical situations. - * - * @return - */ - public List getSelectionDetailsAtIndex(int xIndex) { - - List vals = new ArrayList(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - IDataSet dataSet = mData.getDataSetByIndex(i); - - // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValueForXValue(xIndex); - if (Float.isNaN(yVal)) - continue; - - vals.add(new Highlight(0f, yVal, 0f, 0f, i, dataSet.getAxisDependency())); - } - - return vals; - } - /** * ################ ################ ################ ################ */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index fb9d9fb46c..27c36fbad1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.highlight.RadarHighlighter; import com.github.mikephil.charting.renderer.RadarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererRadarChart; import com.github.mikephil.charting.renderer.YAxisRendererRadarChart; @@ -93,6 +94,8 @@ protected void init() { mRenderer = new RadarChartRenderer(this, mAnimator, mViewPortHandler); mYAxisRenderer = new YAxisRendererRadarChart(mViewPortHandler, mYAxis, this); mXAxisRenderer = new XAxisRendererRadarChart(mViewPortHandler, mXAxis, this); + + mHighlighter = new RadarHighlighter(this); } @Override @@ -103,20 +106,21 @@ protected void calcMinMax() { mXAxis.calculate(0, mData.getMaxEntryCountSet().getEntryCount()); } - @Override - protected float[] getMarkerPosition(Entry e, Highlight highlight) { - - float angle = getSliceAngle() * e.getX() * mAnimator.getPhaseX() + getRotationAngle(); - float val = e.getY() * getFactor() * mAnimator.getPhaseY(); - PointF c = getCenterOffsets(); - - PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), - (float) (c.y + val * Math.sin(Math.toRadians(angle)))); - - return new float[]{ - p.x, p.y - }; - } +// @Override +// protected float[] getMarkerPosition(Highlight highlight) { +// return null; +// +//// float angle = getSliceAngle() * e.getX() * mAnimator.getPhaseX() + getRotationAngle(); +//// float val = e.getY() * getFactor() * mAnimator.getPhaseY(); +//// PointF c = getCenterOffsets(); +//// +//// PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), +//// (float) (c.y + val * Math.sin(Math.toRadians(angle)))); +//// +//// return new float[]{ +//// p.x, p.y +//// }; +// } @Override public void notifyDataSetChanged() { @@ -197,7 +201,7 @@ public int getIndexForAngle(float angle) { float sliceangle = getSliceAngle(); - for (int i = 0; i < mData.getEntryCount(); i++) { + for (int i = 0; i < mData.getMaxEntryCountSet().getEntryCount(); i++) { if (sliceangle * (i + 1) - sliceangle / 2f > a) return i; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieHighlighter.java new file mode 100644 index 0000000000..b4c5a1b24b --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieHighlighter.java @@ -0,0 +1,25 @@ +package com.github.mikephil.charting.highlight; + +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; + +/** + * Created by philipp on 12/06/16. + */ +public class PieHighlighter extends PieRadarHighlighter { + + public PieHighlighter(PieChart chart) { + super(chart); + } + + @Override + protected Highlight getClosestHighlight(int index, float x, float y) { + + IPieDataSet set = mChart.getData().getDataSet(); + + final Entry entry = set.getEntryForIndex(index); + + return new Highlight(index, entry.getY(), x, y, 0, set.getAxisDependency()); + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java new file mode 100644 index 0000000000..029212c84e --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java @@ -0,0 +1,66 @@ +package com.github.mikephil.charting.highlight; + +import android.graphics.PointF; + +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.charts.PieRadarChartBase; +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by philipp on 12/06/16. + */ +public abstract class PieRadarHighlighter implements Highlighter { + + protected T mChart; + + public PieRadarHighlighter(T chart) { + this.mChart = chart; + } + + @Override + public Highlight getHighlight(float x, float y) { + + float touchDistanceToCenter = mChart.distanceToCenter(x, y); + + // check if a slice was touched + if (touchDistanceToCenter > mChart.getRadius()) { + + // if no slice was touched, highlight nothing + return null; + + } else { + + float angle = mChart.getAngleForPoint(x, y); + + if (mChart instanceof PieChart) { + angle /= mChart.getAnimator().getPhaseY(); + } + + int index = mChart.getIndexForAngle(angle); + + // check if the index could be found + if (index < 0 || index >= mChart.getData().getMaxEntryCountSet().getEntryCount()) { + return null; + + } else { + return getClosestHighlight(index, x, y); + } + } + } + + /** + * Returns the closest Highlight object of the given objects based on the touch position inside the chart. + * + * @param index + * @param x + * @param y + * @return + */ + protected abstract Highlight getClosestHighlight(int index, float x, float y); +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java new file mode 100644 index 0000000000..ab49232c89 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -0,0 +1,85 @@ +package com.github.mikephil.charting.highlight; + +import android.graphics.PointF; + +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by philipp on 12/06/16. + */ +public class RadarHighlighter extends PieRadarHighlighter { + + public RadarHighlighter(RadarChart chart) { + super(chart); + } + + @Override + protected Highlight getClosestHighlight(int index, float x, float y) { + + List highlights = getHighlightsAtIndex(index); + + float distanceToCenter = mChart.distanceToCenter(x, y) / mChart.getFactor(); + + Highlight closest = null; + float distance = Float.MAX_VALUE; + + for (int i = 0; i < highlights.size(); i++) { + + Highlight high = highlights.get(i); + + float cdistance = Math.abs(high.getY() - distanceToCenter); + if (cdistance < distance) { + closest = high; + distance = cdistance; + } + } + + return closest; + } + + /** + * Returns an array of Highlight objects for the given index. The Highlight + * objects give information about the value at the selected index and the + * DataSet it belongs to. INFORMATION: This method does calculations at + * runtime. Do not over-use in performance critical situations. + * + * @param index + * @return + */ + protected List getHighlightsAtIndex(int index) { + + List vals = new ArrayList(); + + float phaseX = mChart.getAnimator().getPhaseX(); + float phaseY = mChart.getAnimator().getPhaseY(); + float sliceangle = mChart.getSliceAngle(); + float factor = mChart.getFactor(); + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + IDataSet dataSet = mChart.getData().getDataSetByIndex(i); + + final Entry entry = dataSet.getEntryForIndex(index); + + float y = (entry.getY() - mChart.getYChartMin()); + + if (Float.isNaN(y)) + continue; + + PointF p = Utils.getPosition( + mChart.getCenterOffsets(), + y * factor * phaseY, + sliceangle * index * phaseX + mChart.getRotationAngle()); + + vals.add(new Highlight(entry.getX(), entry.getY(), p.x, p.y, i, dataSet.getAxisDependency())); + } + + return vals; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index ca125dba41..c6d82d6193 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -7,14 +7,11 @@ import android.view.View; import android.view.animation.AnimationUtils; -import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieRadarChartBase; -import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; -import java.util.List; /** * Touchlistener for the PieChart. @@ -150,62 +147,8 @@ public boolean onSingleTapUp(MotionEvent e) { return false; } - float distance = mChart.distanceToCenter(e.getX(), e.getY()); - - // check if a slice was touched - if (distance > mChart.getRadius()) { - - // if no slice was touched, highlight nothing - - if (mLastHighlighted == null) - mChart.highlightValues(null); // no listener callback - else - mChart.highlightTouch(null); // listener callback - - mLastHighlighted = null; - - } else { - - float angle = mChart.getAngleForPoint(e.getX(), e.getY()); - - if (mChart instanceof PieChart) { - angle /= mChart.getAnimator().getPhaseY(); - } - - int index = mChart.getIndexForAngle(angle); - - // check if the index could be found - if (index < 0) { - - mChart.highlightValues(null); - mLastHighlighted = null; - - } else { - - List valsAtIndex = mChart.getSelectionDetailsAtIndex(index); - - int dataSetIndex = 0; - - // get the dataset that is closest to the selection (PieChart - // only - // has one DataSet) - if (mChart instanceof RadarChart) { - - dataSetIndex = Utils.getClosestDataSetIndexByValue( - valsAtIndex, - distance / ((RadarChart) mChart).getFactor(), - null); - } - - if (dataSetIndex < 0) { - mChart.highlightValues(null); - mLastHighlighted = null; - } else { - Highlight h = new Highlight(index, dataSetIndex); - performHighlight(h, e); - } - } - } + Highlight high = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); + performHighlight(high, e); return true; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 58973f0158..05c9d531ed 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -233,8 +233,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { // draw only if the value is greater than zero if ((Math.abs(e.getY()) > 0.000001)) { - if (!mChart.needsHighlight((int) e.getX(), - mChart.getData().getIndexOfDataSet(dataSet))) { + if (!mChart.needsHighlight(j)) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; @@ -712,17 +711,15 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { // get the index to highlight - float x = indices[i].getX(); + int index = (int) indices[i].getX(); - if (x >= drawAngles.length) + if (index >= drawAngles.length) continue; IPieDataSet set = mChart.getData() .getDataSetByIndex(indices[i] .getDataSetIndex()); - int entryIndex = set.getEntryIndex(x, DataSet.Rounding.CLOSEST); - if (set == null || !set.isHighlightEnabled()) continue; @@ -735,14 +732,14 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - if (x == 0) + if (index == 0) angle = 0.f; else - angle = absoluteAngles[entryIndex - 1] * phaseX; + angle = absoluteAngles[index - 1] * phaseX; final float sliceSpace = visibleAngleCount <= 1 ? 0.f : set.getSliceSpace(); - float sliceAngle = drawAngles[entryIndex]; + float sliceAngle = drawAngles[index]; float innerRadius = userInnerRadius; float shift = set.getSelectionShift(); @@ -752,7 +749,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(set.getColor(entryIndex)); + mRenderPaint.setColor(set.getColor(index)); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index d593af582c..42a934f0ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -239,14 +239,6 @@ protected void drawWeb(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - float phaseX = mAnimator.getPhaseX(); - float phaseY = mAnimator.getPhaseY(); - - float sliceangle = mChart.getSliceAngle(); - float factor = mChart.getFactor(); - - PointF center = mChart.getCenterOffsets(); - for (int i = 0; i < indices.length; i++) { IRadarDataSet set = mChart.getData() @@ -256,24 +248,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - // get the index to highlight - float x = indices[i].getX(); - - Entry e = set.getEntryForXPos(x); - if (e == null || e.getX() != x) - continue; - - int j = set.getEntryIndex(e); - float y = (e.getY() - mChart.getYChartMin()); - - if (Float.isNaN(y)) - continue; - - PointF p = Utils.getPosition( - center, - y * factor * phaseY, - sliceangle * j * phaseX + mChart.getRotationAngle()); - + Highlight high = indices[i]; + PointF p = new PointF(high.getXPx(), high.getYPx()); // draw the lines drawHighlightLines(c, p.x, p.y, set); From dfc0b46f4860a9e85e511186b2ded49b512c4764 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Jun 2016 16:16:51 +0200 Subject: [PATCH 1004/1390] Improve OnChartValueSelectedListener --- .../mpchartexample/BarChartActivity.java | 2 +- .../BarChartActivityMultiDataset.java | 4 ++-- .../mpchartexample/BubbleChartActivity.java | 4 ++-- .../mpchartexample/DrawChartActivity.java | 4 ++-- .../mpchartexample/DynamicalAddingActivity.java | 2 +- .../mpchartexample/HorizontalBarChartActivity.java | 4 ++-- .../mpchartexample/InvertedLineChartActivity.java | 4 ++-- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 4 ++-- .../mpchartexample/MultiLineChartActivity.java | 4 ++-- .../mpchartexample/PieChartActivity.java | 6 +++--- .../mpchartexample/PiePolylineChartActivity.java | 4 ++-- .../mpchartexample/RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 4 ++-- .../mpchartexample/StackedBarActivity.java | 2 +- .../mpchartexample/StackedBarActivityNegative.java | 2 +- .../com/github/mikephil/charting/charts/Chart.java | 2 +- .../mikephil/charting/highlight/Highlight.java | 2 +- .../listener/OnChartValueSelectedListener.java | 14 ++++++-------- 19 files changed, 35 insertions(+), 37 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 57d28ce0fb..ce090da068 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -258,7 +258,7 @@ private void setData(int count, float range) { @SuppressLint("NewApi") @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { if (e == null) return; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index e43c4f33d1..f76fee3b8c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -269,8 +269,8 @@ public void onStopTrackingTouch(SeekBar seekBar) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { - Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + dataSetIndex); + public void onValueSelected(Entry e, Highlight h) { + Log.i("Activity", "Selected: " + e.toString() + ", dataSet: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 72e09797f5..7ffeef9aa6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -210,10 +210,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 4d103bedfc..970ba12909 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -142,10 +142,10 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index a505e4a4f9..2d1cbcd907 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -146,7 +146,7 @@ private void removeDataSet() { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 5151b48d85..e828d4dcf7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -250,13 +250,13 @@ private void setData(int count, float range) { @SuppressLint("NewApi") @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { if (e == null) return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(dataSetIndex) + PointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); Log.i("bounds", bounds.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index a28c7b1630..1f760f871e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -230,10 +230,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index bfa5c2dde2..fd8c8f9e4f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -433,7 +433,7 @@ public void onChartTranslate(MotionEvent me, float dX, float dY) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); Log.i("LOWHIGH", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); Log.i("MIN MAX", "xmin: " + mChart.getXChartMin() + ", xmax: " + mChart.getXChartMax() + ", ymin: " + mChart.getYChartMin() + ", ymax: " + mChart.getYChartMax()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 24972f36ff..afdf3eadd7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -357,10 +357,10 @@ private void setData(int count, float range) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); - mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 500); + mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(h.getDataSetIndex()).getAxisDependency(), 500); //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 487fd4baa9..8d9060a2b6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -220,10 +220,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index d050f2d410..1da4792f36 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -247,13 +247,13 @@ private SpannableString generateCenterSpannableText() { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { if (e == null) return; Log.i("VAL SELECTED", - "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + "Value: " + e.getY() + ", index: " + h.getX() + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 30a1dcd238..1cbfd58638 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -253,13 +253,13 @@ private SpannableString generateCenterSpannableText() { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { if (e == null) return; Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index ab72539792..5b8d3f6f3e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -204,7 +204,7 @@ public void run() { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index a0b3103e1e..b3821e6b12 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -208,10 +208,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", "Value: " + e.getY() + ", xIndex: " + e.getX() - + ", DataSet index: " + dataSetIndex); + + ", DataSet index: " + h.getDataSetIndex()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index ae17135bad..9b9767001c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -227,7 +227,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { BarEntry entry = (BarEntry) e; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 4bbe293c5f..dc2a8825fc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -206,7 +206,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + public void onValueSelected(Entry e, Highlight h) { BarEntry entry = (BarEntry) e; Log.i("VAL SELECTED", diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 92812576fd..707c9d5e14 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -649,7 +649,7 @@ public void highlightValue(Highlight high, boolean callListener) { mSelectionListener.onNothingSelected(); else { // notify the listener - mSelectionListener.onValueSelected(e, high.getDataSetIndex(), high); + mSelectionListener.onValueSelected(e, high); } } // redraw the chart diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 6a9be2af34..82d2cb695d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -201,7 +201,7 @@ public boolean equalTo(Highlight h) { @Override public String toString() { - return "Highlight, x: " + mX + "y: " + mY + ", dataSetIndex: " + mDataSetIndex + return "Highlight, x: " + mX + ", y: " + mY + ", dataSetIndex: " + mDataSetIndex + ", stackIndex (only stacked barentry): " + mStackIndex; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 4c6da2e8c9..cc73f73802 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -6,21 +6,19 @@ /** * Listener for callbacks when selecting values inside the chart by * touch-gesture. - * + * * @author Philipp Jahoda */ public interface OnChartValueSelectedListener { /** * Called when a value has been selected inside the chart. - * - * @param e The selected Entry. - * @param dataSetIndex The index in the datasets array of the data object - * the Entrys DataSet is in. - * @param h the corresponding highlight object that contains information - * about the highlighted position + * + * @param e The selected Entry + * @param h The corresponding highlight object that contains information + * about the highlighted position */ - void onValueSelected(Entry e, int dataSetIndex, Highlight h); + void onValueSelected(Entry e, Highlight h); /** * Called when nothing has been selected or an "un-select" has been made. From 44d5641fb8e7eab038d2d6651e61cb72918b9d36 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Jun 2016 16:20:52 +0200 Subject: [PATCH 1005/1390] Fix issue in selection callback --- .../java/com/github/mikephil/charting/data/PieData.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index 801114943c..dc920bae50 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import java.util.ArrayList; @@ -62,6 +63,11 @@ public IPieDataSet getDataSetByLabel(String label, boolean ignorecase) { : null : label.equals(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null; } + @Override + public Entry getEntryForHighlight(Highlight highlight) { + return getDataSet().getEntryForIndex((int) highlight.getX()); + } + /** * Returns the sum of all values in this PieData object. * From e853a80f782c8283874a7d164569a80b5469f998 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Jun 2016 16:23:01 +0200 Subject: [PATCH 1006/1390] Unused method cleanup --- .../mikephil/charting/data/DataSet.java | 11 ---- .../data/realm/base/RealmBaseDataSet.java | 12 ----- .../interfaces/datasets/IDataSet.java | 11 ---- .../github/mikephil/charting/utils/Utils.java | 52 ------------------- 4 files changed, 86 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 0abdb49fdf..42571e95de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -295,17 +295,6 @@ public int getEntryIndex(float xPos, Rounding rounding) { return high; } - @Override - public float getYValueForXValue(float xVal) { - - Entry e = getEntryForXPos(xVal); - - if (e != null && e.getX() == xVal) - return e.getY(); - else - return Float.NaN; - } - /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 7a55da224d..43927dd934 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -252,18 +252,6 @@ public int getEntryIndex(S e) { return mValues.indexOf(e); } - @Override - public float getYValueForXValue(float xVal) { - //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(mXValuesField, xIndex).findFirst()) - // .getFloat(mYValuesField); - Entry e = getEntryForXPos(xVal); - - if (e != null && e.getX() == xVal) - return e.getY(); - else - return Float.NaN; - } - @Override public boolean addEntry(S e) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 49a78d7e52..a9d60e870c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -123,17 +123,6 @@ public interface IDataSet { */ int getEntryIndex(T e); - /** - * Returns the value of the Entry object at the given xPos. Returns - * Float.NaN if no value is at the given xPos. INFORMATION: This method - * does calculations at runtime. Do not over-use in performance critical - * situations. - * - * @param xPos - * @return - */ - float getYValueForXValue(float xPos); - /** * This method returns the actual diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index e375bd1534..ea249d95f2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -19,10 +19,8 @@ import android.view.View; import android.view.ViewConfiguration; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.highlight.Highlight; import java.util.List; @@ -382,56 +380,6 @@ public static double nextUp(double d) { } } - /** - * Returns the index of the DataSet that contains the closest value on the - * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. - * - * @param valsAtIndex all the values at a specific index - * @return - */ - public static int getClosestDataSetIndexByValue(List valsAtIndex, float value, - AxisDependency axis) { - - Highlight sel = getClosestSelectionDetailByValue(valsAtIndex, value, axis); - - if (sel == null) - return -Integer.MAX_VALUE; - - return sel.getDataSetIndex(); - } - - /** - * Returns the SelectionDetail of the DataSet that contains the closest value on the - * y-axis. - * - * @param valsAtIndex all the values at a specific index - * @return - */ - public static Highlight getClosestSelectionDetailByValue( - List valsAtIndex, - float value, - AxisDependency axis) { - - Highlight closest = null; - float distance = Float.MAX_VALUE; - - for (int i = 0; i < valsAtIndex.size(); i++) { - - Highlight sel = valsAtIndex.get(i); - - if (axis == null || sel.getAxis() == axis) { - - float cdistance = Math.abs(sel.getY() - value); - if (cdistance < distance) { - closest = sel; - distance = cdistance; - } - } - } - - return closest; - } - /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. From 8a37bbda380977443fb01043b642c2605eeb4fb7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 13 Jun 2016 20:13:30 +0200 Subject: [PATCH 1007/1390] Work on highlight rendering and markerview --- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/charts/HorizontalBarChart.java | 16 ++-- .../charting/highlight/Highlight.java | 39 ++++++++ .../charting/highlight/RadarHighlighter.java | 2 +- .../charting/renderer/BarChartRenderer.java | 94 ++++++------------- .../BarLineScatterCandleBubbleRenderer.java | 22 +++++ .../renderer/BubbleChartRenderer.java | 92 ++++++++---------- .../renderer/CandleStickChartRenderer.java | 40 +++----- .../renderer/HorizontalBarChartRenderer.java | 7 ++ .../charting/renderer/LineChartRenderer.java | 33 +++---- .../charting/renderer/RadarChartRenderer.java | 45 ++++++--- .../renderer/ScatterChartRenderer.java | 33 +++---- 12 files changed, 215 insertions(+), 210 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 707c9d5e14..b6c652a5b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -760,7 +760,7 @@ protected void drawMarkers(Canvas canvas) { * @return */ protected float[] getMarkerPosition(Highlight high) { - return new float[]{high.getXPx(), high.getYPx()}; + return new float[]{high.getDrawX(), high.getDrawY()}; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index a7a1cdf687..f95132769b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.Matrix; import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; @@ -126,9 +125,14 @@ public void calculateOffsets() { @Override protected void prepareValuePxMatrix() { mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mXAxis.mAxisRange, - mXAxis.mAxisMinimum); + mXAxis.mAxisMinimum); mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mXAxis.mAxisRange, - mXAxis.mAxisMinimum); + mXAxis.mAxisMinimum); + } + + @Override + protected float[] getMarkerPosition(Highlight high) { + return new float[]{high.getDrawY(), high.getDrawX()}; } @Override @@ -181,7 +185,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { public Highlight getHighlightByTouchPoint(float x, float y) { if (mData == null) { - if(mLogEnabled) + if (mLogEnabled) Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } else @@ -191,14 +195,14 @@ public Highlight getHighlightByTouchPoint(float x, float y) { @Override public float getLowestVisibleX() { PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom()); + mViewPortHandler.contentBottom()); return (float) Math.max(mXAxis.mAxisMinimum, pos.y); } @Override public float getHighestVisibleX() { PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentTop()); + mViewPortHandler.contentTop()); return (float) Math.min(mXAxis.mAxisMaximum, pos.y); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 82d2cb695d..f8989a4da7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -55,6 +55,16 @@ public class Highlight { */ private YAxis.AxisDependency axis; + /** + * the x-position (pixels) on which this highlight object was last drawn + */ + private float mDrawX; + + /** + * the y-position (pixels) on which this highlight object was last drawn + */ + private float mDrawY; + public Highlight(float x, int dataSetIndex) { this.mX = x; this.mDataSetIndex = dataSetIndex; @@ -179,6 +189,35 @@ public YAxis.AxisDependency getAxis() { return axis; } + /** + * Sets the x- and y-position (pixels) where this highlight was last drawn. + * + * @param x + * @param y + */ + public void setDraw(float x, float y) { + this.mDrawX = x; + this.mDrawY = y; + } + + /** + * Returns the x-position in pixels where this highlight object was last drawn. + * + * @return + */ + public float getDrawX() { + return mDrawX; + } + + /** + * Returns the y-position in pixels where this highlight object was last drawn. + * + * @return + */ + public float getDrawY() { + return mDrawY; + } + /** * Returns true if this highlight object is equal to the other (compares * xIndex and dataSetIndex) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java index ab49232c89..c113d7d26d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -77,7 +77,7 @@ protected List getHighlightsAtIndex(int index) { y * factor * phaseY, sliceangle * index * phaseX + mChart.getRotationAngle()); - vals.add(new Highlight(entry.getX(), entry.getY(), p.x, p.y, i, dataSet.getAxisDependency())); + vals.add(new Highlight(index, entry.getY(), p.x, p.y, i, dataSet.getAxisDependency())); } return vals; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 1698113de3..ae6e12d793 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -19,7 +19,7 @@ import java.util.List; -public class BarChartRenderer extends DataRenderer { +public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer { protected BarDataProvider mChart; @@ -328,82 +328,48 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight high : indices) { - final int minDataSetIndex = high.getDataSetIndex() == -1 - ? 0 - : high.getDataSetIndex(); - final int maxDataSetIndex = high.getDataSetIndex() == -1 - ? barData.getDataSetCount() - : (high.getDataSetIndex() + 1); - if (maxDataSetIndex - minDataSetIndex < 1) continue; + IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex()); - for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { + if (set == null || !set.isHighlightEnabled()) + continue; - IBarDataSet set = barData.getDataSetByIndex(dataSetIndex); + BarEntry e = set.getEntryForXPos(high.getX()); - if (set == null || !set.isHighlightEnabled()) - continue; - - Transformer trans = mChart.getTransformer(set.getAxisDependency()); + if (!isInBoundsX(e, set)) + continue; - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setAlpha(set.getHighLightAlpha()); + Transformer trans = mChart.getTransformer(set.getAxisDependency()); - float x = high.getX(); + mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setAlpha(set.getHighLightAlpha()); - BarEntry e = set.getEntryForXPos(x); - float entryIndex = set.getEntryIndex(e); + boolean isStack = high.getStackIndex() < 0 ? false : true; - if (e == null || entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) - continue; + final float y1; + final float y2; - boolean isStack = high.getStackIndex() < 0 ? false : true; + if (isStack) { + y1 = high.getRange().from; + y2 = high.getRange().to; + } else { + y1 = e.getY(); + y2 = 0.f; + } - final float y1; - final float y2; + prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); - if (isStack) { - y1 = high.getRange().from; - y2 = high.getRange().to; - } else { - y1 = e.getY(); - y2 = 0.f; - } + setHighlightDrawPos(high, mBarRect); - prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans); - - c.drawRect(mBarRect, mHighlightPaint); - -// if (mChart.isDrawHighlightArrowEnabled()) { -// -// mHighlightPaint.setAlpha(255); -// -// // distance between highlight arrow and bar -// float offsetY = mAnimator.getPhaseY() * 0.07f; -// -// float[] values = new float[9]; -// trans.getPixelToValueMatrix().getValues(values); -// final float xToYRel = Math.abs( -// values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); -// -// final float arrowWidth = barData.getBarWidth(); -// final float arrowWidthHalf = arrowWidth / 2f; -// final float arrowHeight = arrowWidth * xToYRel; -// -// final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); -// -// Path arrow = new Path(); -// arrow.moveTo(e.getX() - arrowWidthHalf, yArrow + offsetY + arrowHeight); -// arrow.lineTo(e.getX(), yArrow + offsetY); -// arrow.lineTo(e.getX() + arrowWidthHalf, yArrow + offsetY + arrowHeight); -// -// trans.pathValueToPixel(arrow); -// c.drawPath(arrow, mHighlightPaint); -// } - } + c.drawRect(mBarRect, mHighlightPaint); } + } + /** + * Sets the drawing position of the highlight object based on the riven bar-rect. + * @param high + */ + protected void setHighlightDrawPos(Highlight high, RectF bar) { + high.setDraw(bar.centerX(), bar.top); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index b21cbef0e4..60697eac7a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.renderer; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; @@ -17,6 +18,27 @@ public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandle super(animator, viewPortHandler); } + /** + * Checks if the provided entry object is in bounds for drawing considering the current animation phase. + * + * @param e + * @param set + * @return + */ + protected boolean isInBoundsX(Entry e, IBarLineScatterCandleBubbleDataSet set) { + + if (e == null) + return false; + + float entryIndex = set.getEntryIndex(e); + + if (e == null || entryIndex >= set.getEntryCount() * mAnimator.getPhaseX()) { + return false; + } else { + return true; + } + } + /** * Calculates and returns the x-bounds for the given DataSet in terms of index in their values array. This * includes minimum and maximum visible x, as well as range. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 7cf908ab8a..18884fd7ce 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -184,76 +184,62 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight high : indices) { - final int minDataSetIndex = high.getDataSetIndex() == -1 - ? 0 - : high.getDataSetIndex(); - final int maxDataSetIndex = high.getDataSetIndex() == -1 - ? bubbleData.getDataSetCount() - : (high.getDataSetIndex() + 1); - if (maxDataSetIndex - minDataSetIndex < 1) continue; + IBubbleDataSet set = bubbleData.getDataSetByIndex(high.getDataSetIndex()); - for (int dataSetIndex = minDataSetIndex; dataSetIndex < maxDataSetIndex; dataSetIndex++) { - - IBubbleDataSet dataSet = bubbleData.getDataSetByIndex(dataSetIndex); - - if (dataSet == null || !dataSet.isHighlightEnabled()) - continue; - - final BubbleEntry entry = dataSet.getEntryForXPos(high.getX()); + if (set == null || !set.isHighlightEnabled()) + continue; - if (entry == null) - continue; + final BubbleEntry entry = set.getEntryForXPos(high.getX()); - XBounds bounds = getXBounds(mChart, dataSet); + if (!isInBoundsX(entry, set)) + continue; - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + Transformer trans = mChart.getTransformer(set.getAxisDependency()); - sizeBuffer[0] = 0f; - sizeBuffer[2] = 1f; + sizeBuffer[0] = 0f; + sizeBuffer[2] = 1f; - trans.pointValuesToPixel(sizeBuffer); + trans.pointValuesToPixel(sizeBuffer); - boolean normalizeSize = dataSet.isNormalizeSizeEnabled(); + boolean normalizeSize = set.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs( - mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); - final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); + final float maxBubbleHeight = Math.abs( + mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - pointBuffer[0] = entry.getX(); - pointBuffer[1] = (entry.getY()) * phaseY; - trans.pointValuesToPixel(pointBuffer); + pointBuffer[0] = entry.getX(); + pointBuffer[1] = (entry.getY()) * phaseY; + trans.pointValuesToPixel(pointBuffer); - float shapeHalf = getShapeSize(entry.getSize(), - dataSet.getMaxSize(), - referenceSize, - normalizeSize) / 2f; + high.setDraw(pointBuffer[0], pointBuffer[1]); - if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) - || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) - continue; + float shapeHalf = getShapeSize(entry.getSize(), + set.getMaxSize(), + referenceSize, + normalizeSize) / 2f; - if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) - continue; + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; - if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) - break; + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) + continue; - if (high.getX() < bounds.min || high.getX() > bounds.max) - continue; + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; - final int originalColor = dataSet.getColor((int) entry.getX()); + final int originalColor = set.getColor((int) entry.getX()); - Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), - Color.blue(originalColor), _hsvBuffer); - _hsvBuffer[2] *= 0.5f; - final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), + Color.blue(originalColor), _hsvBuffer); + _hsvBuffer[2] *= 0.5f; + final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); - mHighlightPaint.setColor(color); - mHighlightPaint.setStrokeWidth(dataSet.getHighlightCircleWidth()); - c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); - } + mHighlightPaint.setColor(color); + mHighlightPaint.setStrokeWidth(set.getHighlightCircleWidth()); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 9ced6efa05..294dcedf74 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -308,40 +308,26 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight high : indices) { - final int minDataSetIndex = high.getDataSetIndex() == -1 - ? 0 - : high.getDataSetIndex(); - final int maxDataSetIndex = high.getDataSetIndex() == -1 - ? candleData.getDataSetCount() - : (high.getDataSetIndex() + 1); - if (maxDataSetIndex - minDataSetIndex < 1) continue; + ICandleDataSet set = candleData.getDataSetByIndex(high.getDataSetIndex()); - for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { - - float x = high.getX(); // get the - // x-position - - ICandleDataSet set = mChart.getCandleData().getDataSetByIndex(dataSetIndex); + if (set == null || !set.isHighlightEnabled()) + continue; - if (set == null || !set.isHighlightEnabled()) - continue; + CandleEntry e = set.getEntryForXPos(high.getX()); - CandleEntry e = set.getEntryForXPos(x); + if (!isInBoundsX(e, set)) + continue; - if (e == null) - continue; + float lowValue = e.getLow() * mAnimator.getPhaseY(); + float highValue = e.getHigh() * mAnimator.getPhaseY(); + float y = (lowValue + highValue) / 2f; - float lowValue = e.getLow() * mAnimator.getPhaseY(); - float highValue = e.getHigh() * mAnimator.getPhaseY(); - float y = (lowValue + highValue) / 2f; + PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), y); - PointD px = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); + high.setDraw((float) pix.x, (float) pix.y); - // draw the lines - drawHighlightLines(c, (float) px.x, (float) px.y, set); - } + // draw the lines + drawHighlightLines(c, (float) pix.x, (float) pix.y, set); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 3952b90d90..66f3e96539 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -3,6 +3,7 @@ import android.graphics.Canvas; import android.graphics.Paint.Align; +import android.graphics.RectF; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.BarBuffer; @@ -10,6 +11,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -291,6 +293,11 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHa trans.rectToPixelPhaseHorizontal(mBarRect, mAnimator.getPhaseY()); } + @Override + protected void setHighlightDrawPos(Highlight high, RectF bar) { + high.setDraw(bar.centerY(), bar.right); + } + @Override protected boolean isDrawingValuesAllowed(ChartInterface chart) { return chart.getData().getEntryCount() < chart.getMaxVisibleCount() diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index ac0e57d2de..d6fe125cf1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -622,34 +622,23 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight high : indices) { - final int minDataSetIndex = high.getDataSetIndex() == -1 - ? 0 - : high.getDataSetIndex(); - final int maxDataSetIndex = high.getDataSetIndex() == -1 - ? lineData.getDataSetCount() - : (high.getDataSetIndex() + 1); - if (maxDataSetIndex - minDataSetIndex < 1) continue; + ILineDataSet set = lineData.getDataSetByIndex(high.getDataSetIndex()); - for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { - - ILineDataSet set = lineData.getDataSetByIndex(dataSetIndex); + if (set == null || !set.isHighlightEnabled()) + continue; - if (set == null || !set.isHighlightEnabled()) - continue; + Entry e = set.getEntryForXPos(high.getX()); - float x = high.getX(); - float y = high.getY() * mAnimator.getPhaseY(); + if (!isInBoundsX(e, set)) + continue; - if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) - continue; + PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + .getPhaseY()); - PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); + high.setDraw((float) pix.x, (float) pix.y); - // draw the lines - drawHighlightLines(c, (float) pix.x, (float) pix.y, set); - } + // draw the lines + drawHighlightLines(c, (float) pix.x, (float) pix.y, set); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 42a934f0ef..6029446bda 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -121,7 +121,7 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { surface.close(); - if(dataSet.isDrawFilledEnabled()) { + if (dataSet.isDrawFilledEnabled()) { final Drawable drawable = dataSet.getFillDrawable(); if (drawable != null) { @@ -176,7 +176,8 @@ public void drawValues(Canvas c) { (entry.getY() - mChart.getYChartMin()) * factor * phaseY, sliceangle * j * phaseX + mChart.getRotationAngle()); - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, p.x, p.y - yoffset, dataSet.getValueTextColor(j)); + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, p.x, p.y - yoffset, dataSet.getValueTextColor + (j)); } } } @@ -239,17 +240,33 @@ protected void drawWeb(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { - for (int i = 0; i < indices.length; i++) { + float sliceangle = mChart.getSliceAngle(); + + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); + + PointF center = mChart.getCenterOffsets(); - IRadarDataSet set = mChart.getData() - .getDataSetByIndex(indices[i] - .getDataSetIndex()); + RadarData radarData = mChart.getData(); + + for (Highlight high : indices) { + + IRadarDataSet set = radarData.getDataSetByIndex(high.getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) continue; - Highlight high = indices[i]; - PointF p = new PointF(high.getXPx(), high.getYPx()); + Entry e = set.getEntryForXPos(high.getX()); + + if (!isInBoundsX(e, set)) + continue; + + PointF p = Utils.getPosition(center, + (e.getY() - mChart.getYChartMin()) * factor * mAnimator.getPhaseY(), + sliceangle * high.getX() * mAnimator.getPhaseX() + mChart.getRotationAngle()); + + high.setDraw(p.x, p.y); // draw the lines drawHighlightLines(c, p.x, p.y, set); @@ -280,12 +297,12 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } public void drawHighlightCircle(Canvas c, - PointF point, - float innerRadius, - float outerRadius, - int fillColor, - int strokeColor, - float strokeWidth) { + PointF point, + float innerRadius, + float outerRadius, + int fillColor, + int strokeColor, + float strokeWidth) { c.save(); outerRadius = Utils.convertDpToPixel(outerRadius); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 94c881c82a..c4381aab3c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -355,34 +355,23 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight high : indices) { - final int minDataSetIndex = high.getDataSetIndex() == -1 - ? 0 - : high.getDataSetIndex(); - final int maxDataSetIndex = high.getDataSetIndex() == -1 - ? scatterData.getDataSetCount() - : (high.getDataSetIndex() + 1); - if (maxDataSetIndex - minDataSetIndex < 1) continue; + IScatterDataSet set = scatterData.getDataSetByIndex(high.getDataSetIndex()); - for (int dataSetIndex = minDataSetIndex; - dataSetIndex < maxDataSetIndex; - dataSetIndex++) { + if (set == null || !set.isHighlightEnabled()) + continue; - IScatterDataSet set = scatterData.getDataSetByIndex(dataSetIndex); + Entry e = set.getEntryForXPos(high.getX()); - if (set == null || !set.isHighlightEnabled()) - continue; - - float x = high.getX(); - float y = high.getY() * mAnimator.getPhaseY(); + if (!isInBoundsX(e, set)) + continue; - if (x > mChart.getXChartMax() * mAnimator.getPhaseX()) - continue; + PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + .getPhaseY()); - PointD px = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(x, y); + high.setDraw((float) pix.x, (float) pix.y); - // draw the lines - drawHighlightLines(c, (float) px.x, (float) px.y, set); - } + // draw the lines + drawHighlightLines(c, (float) pix.x, (float) pix.y, set); } } } From 5ff8f9609b28af541b074aa3c6bb18e9c4fdfa81 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 13 Jun 2016 23:19:51 +0200 Subject: [PATCH 1008/1390] More fixes related to MarkerView drawing --- .../mpchartexample/BubbleChartActivity.java | 2 +- .../mpchartexample/RadarChartActivitry.java | 10 ++--- .../mikephil/charting/charts/PieChart.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 17 +++++-- .../mikephil/charting/data/PieEntry.java | 12 +++++ .../mikephil/charting/data/RadarData.java | 6 +++ .../mikephil/charting/data/RadarDataSet.java | 8 ++-- .../mikephil/charting/data/RadarEntry.java | 44 +++++++++++++++++++ .../realm/base/RealmLineRadarDataSet.java | 2 +- .../implementation/RealmLineDataSet.java | 3 +- .../implementation/RealmRadarDataSet.java | 4 +- .../charting/highlight/RadarHighlighter.java | 6 +-- .../interfaces/datasets/IRadarDataSet.java | 4 +- .../charting/renderer/RadarChartRenderer.java | 13 +++--- 14 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarEntry.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 7ffeef9aa6..aabd600026 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -68,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setMaxVisibleValueCount(200); mChart.setPinchZoom(true); - mSeekBarX.setProgress(1); + mSeekBarX.setProgress(10); mSeekBarY.setProgress(50); Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 0d3cacf35a..3a97d4eed8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -17,9 +17,9 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; +import com.github.mikephil.charting.data.RadarEntry; import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; @@ -210,20 +210,20 @@ public void setData() { float min = 20; int cnt = 5; - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); + ArrayList yVals1 = new ArrayList(); + ArrayList yVals2 = new ArrayList(); // IMPORTANT: In a PieChart, no values (Entry) should have the same // xIndex (even if from different DataSets), since no values can be // drawn above each other. for (int i = 0; i < cnt; i++) { float val = (float) (Math.random() * mult) + min; - yVals1.add(new Entry(i, val)); + yVals1.add(new RadarEntry(val)); } for (int i = 0; i < cnt; i++) { float val = (float) (Math.random() * mult) + min; - yVals2.add(new Entry(i, val)); + yVals2.add(new RadarEntry(val)); } RadarDataSet set1 = new RadarDataSet(yVals1, "Last Week"); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index f070da9988..e56ef96b2e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -183,7 +183,7 @@ protected float[] getMarkerPosition(Highlight highlight) { float rotationAngle = getRotationAngle(); - int entryIndex = getData().getDataSet().getEntryIndex(highlight.getX(), DataSet.Rounding.CLOSEST); + int entryIndex = (int) highlight.getX(); // offset needed to center the drawn text in the slice float offset = mDrawAngles[entryIndex] / 2; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 27c36fbad1..ab953d79f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -201,12 +201,21 @@ public int getIndexForAngle(float angle) { float sliceangle = getSliceAngle(); - for (int i = 0; i < mData.getMaxEntryCountSet().getEntryCount(); i++) { - if (sliceangle * (i + 1) - sliceangle / 2f > a) - return i; + int max = mData.getMaxEntryCountSet().getEntryCount(); + + int index = 0; + + for (int i = 0; i < max; i++) { + + float referenceAngle = sliceangle * (i + 1) - sliceangle / 2f; + + if (referenceAngle > a) { + index = i; + break; + } } - return 0; + return index; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java index 52853629fd..6ab31f140c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java @@ -45,6 +45,18 @@ public void setLabel(String label) { this.label = label; } + @Deprecated + @Override + public void setX(float x) { + super.setX(x); + } + + @Deprecated + @Override + public float getX() { + return super.getX(); + } + public PieEntry copy() { PieEntry e = new PieEntry(getY(), label, getData()); return e; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java index 811414139a..0c1dbe5505 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import java.util.ArrayList; @@ -49,4 +50,9 @@ public void setLabels(String... labels) { public List getLabels() { return mLabels; } + + @Override + public Entry getEntryForHighlight(Highlight highlight) { + return getDataSetByIndex(highlight.getDataSetIndex()).getEntryForIndex((int) highlight.getX()); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java index baa81340e1..f18aa8c23a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java @@ -9,7 +9,7 @@ import java.util.ArrayList; import java.util.List; -public class RadarDataSet extends LineRadarDataSet implements IRadarDataSet { +public class RadarDataSet extends LineRadarDataSet implements IRadarDataSet { /// flag indicating whether highlight circle should be drawn or not protected boolean mDrawHighlightCircleEnabled = false; @@ -25,7 +25,7 @@ public class RadarDataSet extends LineRadarDataSet implements IRadarDataS protected float mHighlightCircleOuterRadius = 4.0f; protected float mHighlightCircleStrokeWidth = 2.0f; - public RadarDataSet(List yVals, String label) { + public RadarDataSet(List yVals, String label) { super(yVals, label); } @@ -114,9 +114,9 @@ public void setHighlightCircleStrokeWidth(float strokeWidth) } @Override - public DataSet copy() { + public DataSet copy() { - List yVals = new ArrayList(); + List yVals = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { yVals.add(mValues.get(i).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarEntry.java new file mode 100644 index 0000000000..02fdce7d32 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarEntry.java @@ -0,0 +1,44 @@ +package com.github.mikephil.charting.data; + +import android.annotation.SuppressLint; + +/** + * Created by philipp on 13/06/16. + */ +@SuppressLint("ParcelCreator") +public class RadarEntry extends Entry { + + public RadarEntry(float value) { + super(0f, value); + } + + public RadarEntry(float value, Object data) { + super(0f, value, data); + } + + /** + * This is the same as getY(). Returns the value of the RadarEntry. + * + * @return + */ + public float getValue() { + return getY(); + } + + public RadarEntry copy() { + RadarEntry e = new RadarEntry(getY(), getData()); + return e; + } + + @Deprecated + @Override + public void setX(float x) { + super.setX(x); + } + + @Deprecated + @Override + public float getX() { + return super.getX(); + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index 31010f2489..a7b9cb29d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -14,7 +14,7 @@ /** * Created by Philipp Jahoda on 08/11/15. */ -public abstract class RealmLineRadarDataSet extends RealmLineScatterCandleRadarDataSet implements ILineRadarDataSet { +public abstract class RealmLineRadarDataSet extends RealmLineScatterCandleRadarDataSet implements ILineRadarDataSet { /** the color that is used for filling the line surface */ private int mFillColor = Color.rgb(140, 234, 255); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index c985aee55c..5c4a58d15a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -4,6 +4,7 @@ import android.graphics.Color; import android.graphics.DashPathEffect; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; @@ -21,7 +22,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { +public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { /** Drawing mode for this line dataset **/ private LineDataSet.Mode mMode = LineDataSet.Mode.LINEAR; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 880e68586f..dac3a59c40 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -2,6 +2,8 @@ import android.graphics.Color; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.RadarEntry; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -12,7 +14,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { +public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { /// flag indicating whether highlight circle should be drawn or not protected boolean mDrawHighlightCircleEnabled = false; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java index c113d7d26d..706dab07f4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -69,12 +69,8 @@ protected List getHighlightsAtIndex(int index) { float y = (entry.getY() - mChart.getYChartMin()); - if (Float.isNaN(y)) - continue; - PointF p = Utils.getPosition( - mChart.getCenterOffsets(), - y * factor * phaseY, + mChart.getCenterOffsets(), y * factor * phaseY, sliceangle * index * phaseX + mChart.getRotationAngle()); vals.add(new Highlight(index, entry.getY(), p.x, p.y, i, dataSet.getAxisDependency())); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java index 6d725df7d0..8af00d5376 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java @@ -1,11 +1,11 @@ package com.github.mikephil.charting.interfaces.datasets; -import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.RadarEntry; /** * Created by Philipp Jahoda on 03/11/15. */ -public interface IRadarDataSet extends ILineRadarDataSet { +public interface IRadarDataSet extends ILineRadarDataSet { /// flag indicating whether highlight circle should be drawn or not boolean isDrawHighlightCircleEnabled(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 6029446bda..90b9dcf225 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -10,8 +10,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; +import com.github.mikephil.charting.data.RadarEntry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -97,7 +97,7 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { mRenderPaint.setColor(dataSet.getColor(j)); - Entry e = dataSet.getEntryForIndex(j); + RadarEntry e = dataSet.getEntryForIndex(j); PointF p = Utils.getPosition( center, @@ -169,7 +169,7 @@ public void drawValues(Canvas c) { for (int j = 0; j < dataSet.getEntryCount(); j++) { - Entry entry = dataSet.getEntryForIndex(j); + RadarEntry entry = dataSet.getEntryForIndex(j); PointF p = Utils.getPosition( center, @@ -257,13 +257,14 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - Entry e = set.getEntryForXPos(high.getX()); + RadarEntry e = set.getEntryForIndex((int) high.getX()); if (!isInBoundsX(e, set)) continue; - PointF p = Utils.getPosition(center, - (e.getY() - mChart.getYChartMin()) * factor * mAnimator.getPhaseY(), + float y = (e.getY() - mChart.getYChartMin()); + + PointF p = Utils.getPosition(center, y * factor * mAnimator.getPhaseY(), sliceangle * high.getX() * mAnimator.getPhaseX() + mChart.getRotationAngle()); high.setDraw(p.x, p.y); From 09cfb2334bf54b98f38035d2e4507d52d1fa5097 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 14 Jun 2016 13:18:40 +0200 Subject: [PATCH 1009/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6390228dae..4c784851b8 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Remember: *It's all about the looks.* [**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. -As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) :zap: +As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). From a2e88ebeddd06aaa18042ef287021874035a1653 Mon Sep 17 00:00:00 2001 From: wajdi chamakhi Date: Wed, 15 Jun 2016 12:27:45 +0100 Subject: [PATCH 1010/1390] Author: wajdi chamakhi Date: Wed Jun 15 11:30:11 2016 +0100 Changing ScatterShape from ENUM to HashMap of String . Creating a provider which provides ShapeRenderer. Creating CustomShapeRenderers imlementing ShapeRender with different renderShape() method Replacing the Switch Statement by ShapeRenderer.renderShape(); => Better OOP implementation. Scalable easily. To add new Shape you only need to create a class implementing ShapeRenderer and override renderShape method and then add the class in the provider ScatterChart.registerShapeRenderer(String scatterShapeName, ShapeRenderer shapeRenderer). --- .../mpchartexample/ScatterChartActivity.java | 11 +- .../fragments/SimpleFragment.java | 5 +- .../realm/RealmDatabaseActivityScatter.java | 3 +- .../charting/charts/ScatterChart.java | 63 +++-- .../charting/data/ScatterDataSet.java | 8 +- .../implementation/RealmScatterDataSet.java | 10 +- .../interfaces/datasets/IScatterDataSet.java | 3 +- .../renderer/ScatterChartRenderer.java | 254 +----------------- .../ChevronDownShapeRenderer.java | 56 ++++ .../ShapeRenders/ChevronUpShapeRenderer.java | 55 ++++ .../ShapeRenders/CircleShapeRenderer.java | 75 ++++++ .../ShapeRenders/CrossShapeRenderer.java | 55 ++++ .../renderer/ShapeRenders/ScatterShape.java | 44 +++ .../renderer/ShapeRenders/ShapeRenderer.java | 22 ++ .../ShapeRenders/SquareShapeRenderer.java | 75 ++++++ .../ShapeRenders/TriangleShapeRenderer.java | 90 +++++++ .../renderer/ShapeRenders/XShapeRenderer.java | 57 ++++ 17 files changed, 598 insertions(+), 288 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronDownShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronUpShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CircleShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CrossShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ScatterShape.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/SquareShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/TriangleShapeRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/XShapeRenderer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 95b3954fb8..03d98872d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample; -import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; @@ -13,7 +12,6 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; @@ -21,11 +19,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -191,15 +188,15 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a dataset and give it a type ScatterDataSet set1 = new ScatterDataSet(yVals1, "DS 1"); - set1.setScatterShape(ScatterShape.SQUARE); + set1.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE)); set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); - set2.setScatterShape(ScatterShape.CIRCLE); + set2.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.CIRCLE)); set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); set2.setScatterShapeHoleRadius(4f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); - set3.setScatterShape(ScatterShape.CROSS); + set3.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.CROSS)); set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); set1.setScatterShapeSize(8f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 25d103e8ce..afb80fe802 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -8,8 +8,6 @@ import android.view.View; import android.view.ViewGroup; -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; @@ -24,6 +22,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FileUtils; @@ -71,7 +70,7 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) ArrayList sets = new ArrayList(); - ScatterShape[] shapes = ScatterChart.getAllPossibleShapes(); + String[] shapes = ScatterShape.getAllPossibleShapes(); for(int i = 0; i < dataSets; i++) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index b28bf137a8..470bb7f0e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.realm.implementation.RealmScatterData; import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; @@ -57,7 +58,7 @@ private void setData() { set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); - set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); + set.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.CIRCLE)); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 292568a6b3..f13857e75a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -7,23 +7,63 @@ import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.renderer.ScatterChartRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.ChevronDownShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.ChevronUpShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.CircleShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.CrossShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; +import com.github.mikephil.charting.renderer.ShapeRenders.ShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.SquareShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.TriangleShapeRenderer; +import com.github.mikephil.charting.renderer.ShapeRenders.XShapeRenderer; + +import java.util.HashMap; /** * The ScatterChart. Draws dots, triangles, squares and custom shapes into the * Chart-View. CIRCLE and SCQUARE offer the best performance, TRIANGLE has the * worst performance. - * + * * @author Philipp Jahoda */ public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { + + /** + * Dictionary of ShapeRenderer which are responsible for drawing custom shapes. + * Can add to it your custom shapes. + * CustomShapeRenderer Implements ShapeRenderer{} + */ + private static HashMap shapeRendererList; + + public static void registerShapeRenderer(String scatterShapeName, ShapeRenderer shapeRenderer) { + if (shapeRendererList == null) { + shapeRendererList = new HashMap<>(); + } + shapeRendererList.put(scatterShapeName, shapeRenderer); + } + + public static ShapeRenderer getShapeRenderer(String scatterShapeName) { + if (shapeRendererList == null) { + initShapeRenderer(); + } + return shapeRendererList.get(scatterShapeName); + } + /** - * enum that defines the shape that is drawn where the values are + * Init ShapeRendererList */ - public enum ScatterShape { - SQUARE, CIRCLE, TRIANGLE, CROSS, X, + private static void initShapeRenderer() { + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE), new SquareShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CIRCLE), new CircleShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.TRIANGLE), new TriangleShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CROSS), new CrossShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.X), new XShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CHEVRON_UP), new ChevronUpShapeRenderer()); + registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CHEVRON_DOWN), new ChevronDownShapeRenderer()); } + public ScatterChart(Context context) { super(context); } @@ -36,6 +76,7 @@ public ScatterChart(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } + @Override protected void init() { super.init(); @@ -55,18 +96,10 @@ protected void calcMinMax() { mXAxis.mAxisRange = Math.abs(mXAxis.mAxisMaximum - mXAxis.mAxisMinimum); } - /** - * Returns all possible predefined ScatterShapes. - * - * @return - */ - public static ScatterShape[] getAllPossibleShapes() { - return new ScatterShape[] { - ScatterShape.SQUARE, ScatterShape.CIRCLE, ScatterShape.TRIANGLE, ScatterShape.CROSS - }; - } public ScatterData getScatterData() { return mData; - }; + } + + ; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 199a20638b..3281fd0d54 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -1,8 +1,8 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; import java.util.ArrayList; @@ -19,7 +19,7 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme * the type of shape that is set to be drawn where the values are at, * default ScatterShape.SQUARE */ - private ScatterShape mScatterShape = ScatterShape.SQUARE; + private String mScatterShape = ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE); /** * The radius of the hole in the shape (applies to Square, Circle and Triangle) @@ -84,12 +84,12 @@ public float getScatterShapeSize() { * * @param shape */ - public void setScatterShape(ScatterShape shape) { + public void setScatterShape(String shape) { mScatterShape = shape; } @Override - public ScatterShape getScatterShape() { + public String getScatterShape() { return mScatterShape; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 88bbc01dc6..e15418852c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -1,13 +1,11 @@ package com.github.mikephil.charting.data.realm.implementation; -import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Utils; -import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; @@ -25,7 +23,7 @@ public class RealmScatterDataSet extends RealmLineScatter * the type of shape that is set to be drawn where the values are at, * default ScatterShape.SQUARE */ - private ScatterChart.ScatterShape mScatterShape = ScatterChart.ScatterShape.SQUARE; + private String mScatterShape = ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE); /** * The radius of the hole in the shape (applies to Square, Circle and Triangle) @@ -89,12 +87,12 @@ public float getScatterShapeSize() { * * @param shape */ - public void setScatterShape(ScatterChart.ScatterShape shape) { + public void setScatterShape(String shape) { mScatterShape = shape; } @Override - public ScatterChart.ScatterShape getScatterShape() { + public String getScatterShape() { return mScatterShape; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java index d3a6d3400d..38742d65fb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java @@ -1,6 +1,5 @@ package com.github.mikephil.charting.interfaces.datasets; -import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; /** @@ -20,7 +19,7 @@ public interface IScatterDataSet extends ILineScatterCandleRadarDataSet { * * @return */ - ScatterChart.ScatterShape getScatterShape(); + String getScatterShape(); /** * Returns radius of the hole in the shape diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 754b260a20..c54c962ec8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -2,18 +2,15 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.graphics.Paint.Style; -import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.ScatterBuffer; -import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; +import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -65,14 +62,9 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { float phaseY = mAnimator.getPhaseY(); final float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); - final float shapeHalf = shapeSize / 2f; - final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); - final float shapeHoleSize = shapeHoleSizeHalf * 2.f; final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); - final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; - final float shapeStrokeSizeHalf = shapeStrokeSize / 2.f; - ScatterShape shape = dataSet.getScatterShape(); + String shape = dataSet.getScatterShape(); ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet( dataSet)]; @@ -81,248 +73,10 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { trans.pointValuesToPixel(buffer.buffer); - switch (shape) { - case SQUARE: + ScatterChart.getShapeRenderer(shape) + .renderShape(c, dataSet,mViewPortHandler, buffer, mRenderPaint, shapeHoleColor, shapeSize); - for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - mRenderPaint.setColor(dataSet.getColor(i / 2)); - - if (shapeHoleSize > 0.0) { - mRenderPaint.setStyle(Style.STROKE); - mRenderPaint.setStrokeWidth(shapeStrokeSize); - - c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf - shapeStrokeSizeHalf, - buffer.buffer[i + 1] - shapeHoleSizeHalf - shapeStrokeSizeHalf, - buffer.buffer[i] + shapeHoleSizeHalf + shapeStrokeSizeHalf, - buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, - mRenderPaint); - - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - mRenderPaint.setStyle(Style.FILL); - - mRenderPaint.setColor(shapeHoleColor); - c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf, - buffer.buffer[i + 1] - shapeHoleSizeHalf, - buffer.buffer[i] + shapeHoleSizeHalf, - buffer.buffer[i + 1] + shapeHoleSizeHalf, - mRenderPaint); - } - - } else { - mRenderPaint.setStyle(Style.FILL); - - c.drawRect(buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); - } - } - - break; - - case CIRCLE: - - for (int i = 0; i < buffer.size(); i += 2) { - - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - mRenderPaint.setColor(dataSet.getColor(i / 2)); - - if (shapeHoleSize > 0.0) { - mRenderPaint.setStyle(Style.STROKE); - mRenderPaint.setStrokeWidth(shapeStrokeSize); - - c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHoleSizeHalf + shapeStrokeSizeHalf, - mRenderPaint); - - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - mRenderPaint.setStyle(Style.FILL); - - mRenderPaint.setColor(shapeHoleColor); - c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHoleSizeHalf, - mRenderPaint); - } - } else { - mRenderPaint.setStyle(Style.FILL); - - c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHalf, - mRenderPaint); - } - } - break; - - case TRIANGLE: - - mRenderPaint.setStyle(Style.FILL); - - // create a triangle path - Path tri = new Path(); - - for (int i = 0; i < buffer.size(); i += 2) { - - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - mRenderPaint.setColor(dataSet.getColor(i / 2)); - - tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); - tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); - tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); - - if (shapeHoleSize > 0.0) { - tri.lineTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); - - tri.moveTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); - tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - } - - tri.close(); - - c.drawPath(tri, mRenderPaint); - tri.reset(); - - if (shapeHoleSize > 0.0 && - shapeHoleColor != ColorTemplate.COLOR_NONE) { - - mRenderPaint.setColor(shapeHoleColor); - - tri.moveTo(buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); - tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.close(); - - c.drawPath(tri, mRenderPaint); - tri.reset(); - } - } - break; - - case CROSS: - - mRenderPaint.setStyle(Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - - for (int i = 0; i < buffer.size(); i += 2) { - - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - mRenderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1], - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1], - mRenderPaint); - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i], - buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); - } - break; - - case X: - - mRenderPaint.setStyle(Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - - for (int i = 0; i < buffer.size(); i += 2) { - - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - mRenderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); - c.drawLine( - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); - } - break; - - default: - break; - } - - // else { // draw the custom-shape - // - // Path customShape = dataSet.getCustomScatterShape(); - // - // for (int j = 0; j < entries.size() * mAnimator.getPhaseX(); j += 2) { - // - // Entry e = entries.get(j / 2); - // - // if (!fitsBounds(e.getXIndex(), mMinX, mMaxX)) - // continue; - // - // if (customShape == null) - // return; - // - // mRenderPaint.setColor(dataSet.getColor(j)); - // - // Path newPath = new Path(customShape); - // newPath.offset(e.getXIndex(), e.getVal()); - // - // // transform the provided custom path - // trans.pathValueToPixel(newPath); - // c.drawPath(newPath, mRenderPaint); - // } - // } } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronDownShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronDownShapeRenderer.java new file mode 100644 index 0000000000..5ba5e00425 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronDownShapeRenderer.java @@ -0,0 +1,56 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class ChevronDownShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + final float shapeHalf = shapeSize / 2f; + + + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] + (2 * shapeHalf), + buffer.buffer[i] + (2 * shapeHalf), + buffer.buffer[i + 1], + mRenderPaint); + + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] + (2 * shapeHalf), + buffer.buffer[i] - (2 * shapeHalf), + buffer.buffer[i + 1], + mRenderPaint); + } + + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronUpShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronUpShapeRenderer.java new file mode 100644 index 0000000000..3b4610282b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ChevronUpShapeRenderer.java @@ -0,0 +1,55 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class ChevronUpShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + final float shapeHalf = shapeSize / 2f; + + + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] - (2 * shapeHalf), + buffer.buffer[i] + (2 * shapeHalf), + buffer.buffer[i + 1], + mRenderPaint); + + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] - (2 * shapeHalf), + buffer.buffer[i] - (2 * shapeHalf), + buffer.buffer[i + 1], + mRenderPaint); + } + + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CircleShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CircleShapeRenderer.java new file mode 100644 index 0000000000..44151db4c0 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CircleShapeRenderer.java @@ -0,0 +1,75 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class CircleShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + final float shapeHalf = shapeSize / 2f; + final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); + final float shapeHoleSize = shapeHoleSizeHalf * 2.f; + final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; + final float shapeStrokeSizeHalf = shapeStrokeSize / 2.f; + + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + if (shapeSize > 0.0) { + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(shapeStrokeSize); + + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHoleSizeHalf + shapeStrokeSizeHalf, + mRenderPaint); + + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + mRenderPaint.setStyle(Paint.Style.FILL); + + mRenderPaint.setColor(shapeHoleColor); + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHoleSizeHalf, + mRenderPaint); + } + } else { + mRenderPaint.setStyle(Paint.Style.FILL); + + c.drawCircle( + buffer.buffer[i], + buffer.buffer[i + 1], + shapeHalf, + mRenderPaint); + } + } + + } + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CrossShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CrossShapeRenderer.java new file mode 100644 index 0000000000..44eeaa7a5b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/CrossShapeRenderer.java @@ -0,0 +1,55 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class CrossShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + final float shapeHalf = shapeSize / 2f; + + + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + c.drawLine( + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1], + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1], + mRenderPaint); + c.drawLine( + buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i], + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + } + + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ScatterShape.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ScatterShape.java new file mode 100644 index 0000000000..76943260d0 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ScatterShape.java @@ -0,0 +1,44 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 10:12 + */ +public class ScatterShape { + + + public static final String SQUARE = "SQUARE"; + public static final String CIRCLE = "CIRCLE"; + public static final String TRIANGLE = "TRIANGLE"; + public static final String CROSS = "CROSS"; + public static final String X = "X"; + public static final String CHEVRON_UP = "CHEVRON_UP"; + public static final String CHEVRON_DOWN = "CHEVRON_DOWN"; + + private static Map scatterShapeNames; + + public static Map getScatterShapeNames() { + if (scatterShapeNames == null) { + scatterShapeNames = new HashMap<>(); + scatterShapeNames.put(SQUARE, SQUARE); + scatterShapeNames.put(CIRCLE, CIRCLE); + scatterShapeNames.put(TRIANGLE, TRIANGLE); + scatterShapeNames.put(CROSS, CROSS); + scatterShapeNames.put(X, X); + scatterShapeNames.put(CHEVRON_UP, CHEVRON_UP); + scatterShapeNames.put(CHEVRON_DOWN, CHEVRON_DOWN); + } + return scatterShapeNames; + } + + public static String[] getAllPossibleShapes() { + String[] possibleShapes = new String[getScatterShapeNames().size()]; + for (int i = 0; i < getScatterShapeNames().size(); i++) { + possibleShapes[i] = getScatterShapeNames().get(i); + } + return possibleShapes; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ShapeRenderer.java new file mode 100644 index 0000000000..0c61eab11b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/ShapeRenderer.java @@ -0,0 +1,22 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:07 + */ +public interface ShapeRenderer { + + void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize); + + + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/SquareShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/SquareShapeRenderer.java new file mode 100644 index 0000000000..a801dd28e5 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/SquareShapeRenderer.java @@ -0,0 +1,75 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class SquareShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + final float shapeHalf = shapeSize / 2f; + final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); + final float shapeHoleSize = shapeHoleSizeHalf * 2.f; + final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; + final float shapeStrokeSizeHalf = shapeStrokeSize / 2.f; + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + if (shapeSize > 0.0) { + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(shapeStrokeSize); + + c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf - shapeStrokeSizeHalf, + buffer.buffer[i + 1] - shapeHoleSizeHalf - shapeStrokeSizeHalf, + buffer.buffer[i] + shapeHoleSizeHalf + shapeStrokeSizeHalf, + buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, + mRenderPaint); + + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { + mRenderPaint.setStyle(Paint.Style.FILL); + + mRenderPaint.setColor(shapeHoleColor); + c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf, + buffer.buffer[i + 1] - shapeHoleSizeHalf, + buffer.buffer[i] + shapeHoleSizeHalf, + buffer.buffer[i + 1] + shapeHoleSizeHalf, + mRenderPaint); + } + + } else { + mRenderPaint.setStyle(Paint.Style.FILL); + + c.drawRect(buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + } + } + } + + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/TriangleShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/TriangleShapeRenderer.java new file mode 100644 index 0000000000..7f67a4b7ec --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/TriangleShapeRenderer.java @@ -0,0 +1,90 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class TriangleShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + + final float shapeHalf = shapeSize / 2f; + final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); + final float shapeHoleSize = shapeHoleSizeHalf * 2.f; + final float shapeStrokeSize = (shapeSize - shapeHoleSize) / 2.f; + + + mRenderPaint.setStyle(Paint.Style.FILL); + + // create a triangle path + Path tri = new Path(); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); + tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); + tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); + + if (shapeSize > 0.0) { + tri.lineTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); + + tri.moveTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); + tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + } + + tri.close(); + + c.drawPath(tri, mRenderPaint); + tri.reset(); + + if (shapeSize > 0.0 && + shapeHoleColor != ColorTemplate.COLOR_NONE) { + + mRenderPaint.setColor(shapeHoleColor); + + tri.moveTo(buffer.buffer[i], + buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); + tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, + buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); + tri.close(); + + c.drawPath(tri, mRenderPaint); + tri.reset(); + } + } + + } + +} \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/XShapeRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/XShapeRenderer.java new file mode 100644 index 0000000000..193483a413 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ShapeRenders/XShapeRenderer.java @@ -0,0 +1,57 @@ +package com.github.mikephil.charting.renderer.ShapeRenders; + +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.github.mikephil.charting.buffer.ScatterBuffer; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by wajdic on 15/06/2016. + * Created at Time 09:08 + */ +public class XShapeRenderer implements ShapeRenderer { + + + @Override + public void renderShape( + Canvas c, IScatterDataSet dataSet, + ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final int shapeHoleColor, final float shapeSize) { + + final float shapeHalf = shapeSize / 2f; + + + + mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + + for (int i = 0; i < buffer.size(); i += 2) { + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + break; + + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + continue; + + mRenderPaint.setColor(dataSet.getColor(i / 2)); + + c.drawLine( + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + c.drawLine( + buffer.buffer[i] + shapeHalf, + buffer.buffer[i + 1] - shapeHalf, + buffer.buffer[i] - shapeHalf, + buffer.buffer[i + 1] + shapeHalf, + mRenderPaint); + } + + } + +} \ No newline at end of file From 53e57db56205eb027cd135ab7cef2e05dd0fb978 Mon Sep 17 00:00:00 2001 From: wajdi chamakhi Date: Wed, 15 Jun 2016 14:20:18 +0100 Subject: [PATCH 1011/1390] Adding The Enum Patern Back --- .../mpchartexample/ScatterChartActivity.java | 4 +- .../charting/charts/ScatterChart.java | 40 +++++++++++++++---- .../charting/data/ScatterDataSet.java | 12 ++++++ .../implementation/RealmScatterDataSet.java | 12 ++++++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 03d98872d1..4929eb069b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -188,10 +188,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a dataset and give it a type ScatterDataSet set1 = new ScatterDataSet(yVals1, "DS 1"); - set1.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE)); + set1.setScatterShape(ScatterChart.ScatterShape.SQUARE); set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); - set2.setScatterShape(ScatterShape.getScatterShapeNames().get(ScatterShape.CIRCLE)); + set2.setScatterShape(ScatterChart.ScatterShape.CIRCLE); set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); set2.setScatterShapeHoleRadius(4f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index f13857e75a..6645b4c322 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -11,7 +11,6 @@ import com.github.mikephil.charting.renderer.ShapeRenders.ChevronUpShapeRenderer; import com.github.mikephil.charting.renderer.ShapeRenders.CircleShapeRenderer; import com.github.mikephil.charting.renderer.ShapeRenders.CrossShapeRenderer; -import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.renderer.ShapeRenders.ShapeRenderer; import com.github.mikephil.charting.renderer.ShapeRenders.SquareShapeRenderer; import com.github.mikephil.charting.renderer.ShapeRenders.TriangleShapeRenderer; @@ -54,16 +53,41 @@ public static ShapeRenderer getShapeRenderer(String scatterShapeName) { * Init ShapeRendererList */ private static void initShapeRenderer() { - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.SQUARE), new SquareShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CIRCLE), new CircleShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.TRIANGLE), new TriangleShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CROSS), new CrossShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.X), new XShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CHEVRON_UP), new ChevronUpShapeRenderer()); - registerShapeRenderer(ScatterShape.getScatterShapeNames().get(ScatterShape.CHEVRON_DOWN), new ChevronDownShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.SQUARE), new SquareShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CIRCLE), new CircleShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.TRIANGLE), new TriangleShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CROSS), new CrossShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.X), new XShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CHEVRON_UP), new ChevronUpShapeRenderer()); + registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CHEVRON_DOWN), new ChevronDownShapeRenderer()); } + /** + * enum that defines the shape that is drawn where the values are + */ + public enum ScatterShape { + SQUARE, CIRCLE, TRIANGLE, CROSS, X, + } + + /** + * Returns all possible predefined ScatterShapes. + * + * @return ScatterShape to array + */ + public static ScatterShape[] getAllPossibleShapes() { + return new ScatterShape[] { + ScatterShape.SQUARE, ScatterShape.CIRCLE, ScatterShape.TRIANGLE, ScatterShape.CROSS + }; + } + public ScatterChart(Context context) { super(context); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 3281fd0d54..74a4d6ecd9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape; import com.github.mikephil.charting.utils.ColorTemplate; @@ -79,6 +80,17 @@ public float getScatterShapeSize() { return mShapeSize; } + + /** + * Sets the shape that is drawn on the position where the values are at. + * + * @param shape + */ + public void setScatterShape(ScatterChart.ScatterShape shape) { + mScatterShape = shape.toString(); + } + + /** * Sets the shape that is drawn on the position where the values are at. * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index e15418852c..8aaa816539 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.data.realm.implementation; +import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -80,6 +81,17 @@ public float getScatterShapeSize() { return mShapeSize; } + + /** + * Sets the shape that is drawn on the position where the values are at. + * + * @param shape + */ + public void setScatterShape(ScatterChart.ScatterShape shape) { + mScatterShape = shape.toString(); + } + + /** * Sets the shape that is drawn on the position where the values are at. If * "CUSTOM" is chosen, you need to call setCustomScatterShape(...) and From bda3ccee35d3fb3c20db255a8332a3eacfbc594a Mon Sep 17 00:00:00 2001 From: wajdi chamakhi Date: Wed, 15 Jun 2016 14:25:20 +0100 Subject: [PATCH 1012/1390] Init shapeRendererList optimisation --- .../mikephil/charting/charts/ScatterChart.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 6645b4c322..b0253a5606 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -37,7 +37,7 @@ public class ScatterChart extends BarLineChartBase implements Scatt public static void registerShapeRenderer(String scatterShapeName, ShapeRenderer shapeRenderer) { if (shapeRendererList == null) { - shapeRendererList = new HashMap<>(); + initShapeRenderer(); } shapeRendererList.put(scatterShapeName, shapeRenderer); } @@ -53,19 +53,20 @@ public static ShapeRenderer getShapeRenderer(String scatterShapeName) { * Init ShapeRendererList */ private static void initShapeRenderer() { - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList = new HashMap<>(); + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.SQUARE), new SquareShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CIRCLE), new CircleShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.TRIANGLE), new TriangleShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CROSS), new CrossShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.X), new XShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CHEVRON_UP), new ChevronUpShapeRenderer()); - registerShapeRenderer(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() + shapeRendererList.put(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.getScatterShapeNames() .get(com.github.mikephil.charting.renderer.ShapeRenders.ScatterShape.CHEVRON_DOWN), new ChevronDownShapeRenderer()); } From 84160773ed0960303566da571e3cba0bc89a3908 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 15 Jun 2016 21:07:02 +0200 Subject: [PATCH 1013/1390] Fixes related to combinedchart #1853 --- MPChartExample/res/menu/combined.xml | 5 +- .../mpchartexample/CombinedChartActivity.java | 15 ++- .../mikephil/charting/charts/Chart.java | 18 +-- .../charting/charts/CombinedChart.java | 23 ---- .../mikephil/charting/data/ChartData.java | 12 +- .../mikephil/charting/data/CombinedData.java | 125 +++++++++++++++--- .../highlight/CombinedHighlighter.java | 3 +- 7 files changed, 139 insertions(+), 62 deletions(-) diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/res/menu/combined.xml index 9b034d7f4f..7e37ba0d83 100644 --- a/MPChartExample/res/menu/combined.xml +++ b/MPChartExample/res/menu/combined.xml @@ -9,5 +9,8 @@ android:id="@+id/actionToggleBarValues" android:title="Toggle bar Values"> - + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 237d7d6cfc..068491927f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -125,7 +125,7 @@ private LineData generateLineData() { set.setValueTextColor(Color.rgb(240, 238, 70)); set.setAxisDependency(YAxis.AxisDependency.LEFT); - + this.set1 = set; d.addDataSet(set); return d; @@ -209,6 +209,9 @@ protected CandleData generateCandleData() { return d; } + private LineDataSet set1; + private BubbleDataSet set2; + protected BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); @@ -227,6 +230,7 @@ protected BubbleData generateBubbleData() { set.setValueTextColor(Color.WHITE); set.setHighlightCircleWidth(1.5f); set.setDrawValues(true); + this.set2 = set; bd.addDataSet(set); return bd; @@ -259,6 +263,15 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionRemoveDataSet: { + + int rnd = (int) getRandom(mChart.getData().getDataSetCount(), 0); + mChart.getData().removeDataSet(mChart.getData().getDataSetByIndex(rnd)); + mChart.getData().notifyDataChanged(); + mChart.notifyDataSetChanged(); + mChart.invalidate(); + break; + } } return true; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index b6c652a5b6..42e4c880df 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -572,14 +572,14 @@ public void highlightValues(Highlight[] highs) { } /** - * Highlights the value at the given x-index in the given DataSet. Provide - * -1 as the x-index or dataSetIndex to undo all highlighting. + * Highlights the value at the given x-position in the given DataSet. Provide + * -1 as the dataSetIndex to undo all highlighting. This will trigger a callback to the OnChartValueSelectedListener. * - * @param xIndex + * @param x * @param dataSetIndex */ - public void highlightValue(int xIndex, int dataSetIndex) { - highlightValue(xIndex, dataSetIndex, true); + public void highlightValue(float x, int dataSetIndex) { + highlightValue(x, dataSetIndex, true); } /** @@ -656,14 +656,6 @@ public void highlightValue(Highlight high, boolean callListener) { invalidate(); } - /** - * Deprecated. Calls highlightValue(high, true) - */ - @Deprecated - public void highlightTouch(Highlight high) { - highlightValue(high, true); - } - /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index 710c82e4a5..49e42267a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -11,13 +11,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; -import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; -import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; -import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; -import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; -import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.renderer.CombinedChartRenderer; /** @@ -28,11 +22,6 @@ */ public class CombinedChart extends BarLineChartBase implements CombinedDataProvider { -// /** -// * flag that enables or disables the highlighting arrow -// */ -// private boolean mDrawHighlightArrow = false; - /** * if set to true, all values are drawn above their bars, instead of below * their top @@ -77,9 +66,6 @@ protected void init() { // Old default behaviour setHighlightFullBarEnabled(true); - - // mRenderer = new CombinedChartRenderer(this, mAnimator, - // mViewPortHandler); } @Override @@ -142,15 +128,6 @@ public boolean isDrawValueAboveBarEnabled() { return mDrawValueAboveBar; } -// /** -// * set this to true to draw the highlightning arrow -// * -// * @param enabled -// */ -// public void setDrawHighlightArrow(boolean enabled) { -// mDrawHighlightArrow = enabled; -// } - /** * If set to true, all values are drawn above their bars, instead of below * their top. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0938fb1f11..fa66f4744e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -139,7 +139,7 @@ public void calcMinMax() { mRightAxisMin = Float.MAX_VALUE; // left axis - T firstLeft = getFirstLeft(); + T firstLeft = getFirstLeft(mDataSets); if (firstLeft != null) { @@ -158,7 +158,7 @@ public void calcMinMax() { } // right axis - T firstRight = getFirstRight(); + T firstRight = getFirstRight(mDataSets); if (firstRight != null) { @@ -613,8 +613,8 @@ public int getIndexOfDataSet(T dataSet) { * * @return */ - public T getFirstLeft() { - for (T dataSet : mDataSets) { + protected T getFirstLeft(List sets) { + for (T dataSet : sets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; } @@ -627,8 +627,8 @@ public T getFirstLeft() { * * @return */ - public T getFirstRight() { - for (T dataSet : mDataSets) { + public T getFirstRight(List sets) { + for (T dataSet : sets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 33cacc304a..37ab1e4bdb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -1,6 +1,9 @@ package com.github.mikephil.charting.data; +import android.util.Log; + +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -11,7 +14,7 @@ /** * Data object that allows the combination of Line-, Bar-, Scatter-, Bubble- and * CandleData. Used in the CombinedChart class. - * + * * @author Philipp Jahoda */ public class CombinedData extends BarLineScatterCandleBubbleData> { @@ -28,34 +31,81 @@ public CombinedData() { public void setData(LineData data) { mLineData = data; - mDataSets.addAll(data.getDataSets()); init(); } public void setData(BarData data) { mBarData = data; - mDataSets.addAll(data.getDataSets()); init(); } public void setData(ScatterData data) { mScatterData = data; - mDataSets.addAll(data.getDataSets()); init(); } public void setData(CandleData data) { mCandleData = data; - mDataSets.addAll(data.getDataSets()); init(); } public void setData(BubbleData data) { mBubbleData = data; - mDataSets.addAll(data.getDataSets()); init(); } + @Override + public void calcMinMax() { + + mDataSets = new ArrayList<>(); + + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + + mLeftAxisMax = -Float.MAX_VALUE; + mLeftAxisMin = Float.MAX_VALUE; + mRightAxisMax = -Float.MAX_VALUE; + mRightAxisMin = Float.MAX_VALUE; + + List allData = getAllData(); + + for (ChartData data : allData) { + + data.calcMinMax(); + + List> sets = data.getDataSets(); + mDataSets.addAll(sets); + + if (data.getYMax() > mYMax) + mYMax = data.getYMax(); + + if (data.getYMin() < mYMin) + mYMin = data.getYMin(); + + if (data.getXMax() > mXMax) + mXMax = data.getXMax(); + + if (data.getXMin() < mXMin) + mXMin = data.getXMin(); + + if (data.mLeftAxisMax > mLeftAxisMax) + mLeftAxisMax = data.mLeftAxisMax; + + if (data.mLeftAxisMin < mLeftAxisMin) + mLeftAxisMin = data.mLeftAxisMin; + + if (data.mRightAxisMax > mRightAxisMax) + mRightAxisMax = data.mRightAxisMax; + + if (data.mRightAxisMin < mRightAxisMin) + mRightAxisMin = data.mRightAxisMin; + + } + + } + public BubbleData getBubbleData() { return mBubbleData; } @@ -78,26 +128,27 @@ public CandleData getCandleData() { /** * Returns all data objects in row: line-bar-scatter-candle-bubble if not null. + * * @return */ - public List getAllData() { + public List getAllData() { - List data = new ArrayList(); - if(mLineData != null) + List data = new ArrayList(); + if (mLineData != null) data.add(mLineData); - if(mBarData != null) + if (mBarData != null) data.add(mBarData); - if(mScatterData != null) + if (mScatterData != null) data.add(mScatterData); - if(mCandleData != null) + if (mCandleData != null) data.add(mCandleData); - if(mBubbleData != null) + if (mBubbleData != null) data.add(mBubbleData); return data; } - public ChartData getDataByIndex(int index) { + public BarLineScatterCandleBubbleData getDataByIndex(int index) { return getAllData().get(index); } @@ -126,7 +177,7 @@ public void notifyDataChanged() { @Override public Entry getEntryForHighlight(Highlight highlight) { - List dataObjects = getAllData(); + List dataObjects = getAllData(); if (highlight.getDataIndex() >= dataObjects.size()) return null; @@ -142,9 +193,9 @@ public Entry getEntryForHighlight(Highlight highlight) { List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) .getEntriesForXPos(highlight.getX()); for (Object entry : entries) - if (((Entry)entry).getY() == highlight.getY() || + if (((Entry) entry).getY() == highlight.getY() || Float.isNaN(highlight.getY())) - return (Entry)entry; + return (Entry) entry; return null; } @@ -153,4 +204,44 @@ public Entry getEntryForHighlight(Highlight highlight) { public int getDataIndex(ChartData data) { return getAllData().indexOf(data); } + + @Override + public boolean removeDataSet(IBarLineScatterCandleBubbleDataSet d) { + + List datas = getAllData(); + + boolean success = false; + + for (ChartData data : datas) { + + success = data.removeDataSet(d); + + if (success) { + break; + } + } + + return success; + } + + @Deprecated + @Override + public boolean removeDataSet(int index) { + Log.e("MPAndroidChart", "removeDataSet(int index) not supported for CombinedData"); + return false; + } + + @Deprecated + @Override + public boolean removeEntry(Entry e, int dataSetIndex) { + Log.e("MPAndroidChart", "removeEntry(...) not supported for CombinedData"); + return false; + } + + @Deprecated + @Override + public boolean removeEntry(float xPos, int dataSetIndex) { + Log.e("MPAndroidChart", "removeEntry(...) not supported for CombinedData"); + return false; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 418d7a38e4..b8500fb092 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; @@ -32,7 +33,7 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { List vals = new ArrayList(); - List dataObjects = mChart.getCombinedData().getAllData(); + List dataObjects = mChart.getCombinedData().getAllData(); for (int i = 0; i < dataObjects.size(); i++) { From a3720feb0e714a8cbf6437cf6383c4d88089b403 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 15 Jun 2016 23:44:53 +0200 Subject: [PATCH 1014/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4c784851b8..c6b0c386ff 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,8 @@ Donations - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! +If you just want to be nice, you can check out my [**Amazon-Wishlist**]( https://www.amazon.de/registry/wishlist/2DYHJ69VMF8HM/ref=cm_sw_em_r_mt_ws_WVCyxb4KKQ2G6). + ## 3rd party bindings From fb4590e6b002ee765e35e729b3619c235902b045 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 16 Jun 2016 10:07:12 +0200 Subject: [PATCH 1015/1390] Fix #1862 --- .../src/com/github/mikephil/charting/components/YAxis.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 0846a670a7..4b14b91c86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -208,7 +208,7 @@ public boolean isGranularityEnabled() { * @param enabled */ public void setGranularityEnabled(boolean enabled) { - mGranularityEnabled = true; + mGranularityEnabled = enabled; } /** From 4c4c76b1c7213a2eed9bfa02881ae75b9c92ae8d Mon Sep 17 00:00:00 2001 From: wajdi chamakhi Date: Thu, 16 Jun 2016 09:23:23 +0100 Subject: [PATCH 1016/1390] remove Boldness --- .../charting/components/ComponentBase.java | 21 ------------------- .../charting/renderer/LegendRenderer.java | 2 -- .../charting/renderer/XAxisRenderer.java | 3 --- .../XAxisRendererHorizontalBarChart.java | 3 --- .../renderer/XAxisRendererRadarChart.java | 1 - .../charting/renderer/YAxisRenderer.java | 2 -- .../YAxisRendererHorizontalBarChart.java | 3 --- .../renderer/YAxisRendererRadarChart.java | 1 - 8 files changed, 36 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 5c0c596508..99e9c7a41b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -43,10 +43,6 @@ public abstract class ComponentBase { */ protected int mTextColor = Color.BLACK; - /** - * the text style boldness {Default = false} - */ - protected boolean mTextBold = false; public ComponentBase() { @@ -135,23 +131,6 @@ public float getTextSize() { return mTextSize; } - /** - * set the text to be bold - * - * @param bold - */ - public void setTextBold(boolean bold) { - mTextBold = bold; - } - - /** - * returns the text boldness - * - * @return - */ - public boolean getTextBold() { - return mTextBold; - } /** * Sets the text color to use for the labels. Make sure to use diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index a35653446e..f005a1f2ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -167,7 +167,6 @@ public void computeLegend(ChartData data) { mLegendLabelPaint.setTypeface(tf); mLegendLabelPaint.setTextSize(mLegend.getTextSize()); - mLegendLabelPaint.setFakeBoldText(mLegend.getTextBold()); mLegendLabelPaint.setColor(mLegend.getTextColor()); // calculate all dimensions of the mLegend @@ -185,7 +184,6 @@ public void renderLegend(Canvas c) { mLegendLabelPaint.setTypeface(tf); mLegendLabelPaint.setTextSize(mLegend.getTextSize()); - mLegendLabelPaint.setFakeBoldText(mLegend.getTextBold()); mLegendLabelPaint.setColor(mLegend.getTextColor()); float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index a8b6056f81..9610d3b393 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -36,7 +36,6 @@ public void computeAxis(float xValMaximumLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); StringBuilder widthText = new StringBuilder(); @@ -83,7 +82,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); if (mXAxis.getPosition() == XAxisPosition.TOP) { @@ -295,7 +293,6 @@ public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position mLimitLinePaint.setColor(limitLine.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(limitLine.getTextSize()); - mLimitLinePaint.setFakeBoldText(limitLine.getTextBold()); float xOffset = limitLine.getLineWidth() + limitLine.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 0fe0f46ad8..e862263520 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -31,7 +31,6 @@ public void computeAxis(float xValAverageLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mXAxis.setValues(xValues); String longest = mXAxis.getLongestLabel(); @@ -62,7 +61,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); if (mXAxis.getPosition() == XAxisPosition.TOP) { @@ -239,7 +237,6 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - mLimitLinePaint.setFakeBoldText(l.getTextBold()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 228e818d83..50a2fc7dd4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -30,7 +30,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mXAxis.getTextBold()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); float sliceangle = mChart.getSliceAngle(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 9e37d71e00..fdae353e4b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -193,7 +193,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); float xoffset = mYAxis.getXOffset(); @@ -382,7 +381,6 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTypeface(l.getTypeface()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - mLimitLinePaint.setFakeBoldText(l.getTextBold()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 098542f3fc..78a42f79b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -77,7 +77,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); mAxisLabelPaint.setTextAlign(Align.CENTER); @@ -140,7 +139,6 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); for (int i = 0; i < mYAxis.mEntryCount; i++) { @@ -244,7 +242,6 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTypeface(l.getTypeface()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - mLimitLinePaint.setFakeBoldText(l.getTextBold()); float xOffset = l.getLineWidth() + l.getXOffset(); float yOffset = Utils.convertDpToPixel(2f) + l.getYOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 220a4735d2..66ddd3ceea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -137,7 +137,6 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setFakeBoldText(mYAxis.getTextBold()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); PointF center = mChart.getCenterOffsets(); From 3aa4daae3201c2d997c07f7e5ccfe360c0a1e27f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 17 Jun 2016 21:53:30 +0200 Subject: [PATCH 1017/1390] Add feature allowing customization of dragTriggerDistance #1721 --- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/Chart.java | 9 ++++ .../listener/BarLineChartTouchListener.java | 49 ++++++++++--------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index ceeccd2b1a..3e907e3deb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -169,7 +169,7 @@ protected void init() { setHighlighter(new ChartHighlighter(this)); - mChartTouchListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); + mChartTouchListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch(), 3f); mGridBackgroundPaint = new Paint(); mGridBackgroundPaint.setStyle(Style.FILL); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 7146ee60a3..b09a2705a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -684,6 +684,15 @@ public void setOnTouchListener(ChartTouchListener l) { this.mChartTouchListener = l; } + /** + * Returns an instance of the currently active touch listener. + * + * @return + */ + public ChartTouchListener getOnTouchListener() { + return mChartTouchListener; + } + /** * ################ ################ ################ ################ */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 02713af88a..620db7b45c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.listener; import android.annotation.SuppressLint; @@ -26,7 +25,8 @@ * * @author Philipp Jahoda */ -public class BarLineChartTouchListener extends ChartTouchListener>>> { +public class BarLineChartTouchListener extends ChartTouchListener>>> { /** * the original touch-matrix from the chart @@ -73,12 +73,20 @@ public class BarLineChartTouchListener extends ChartTouchListener>> chart, Matrix touchMatrix) { + /** + * Constructor with initialization parameters. + * + * @param chart instance of the chart + * @param touchMatrix the touch-matrix of the chart + * @param dragTriggerDistance the minimum movement distance that will be interpreted as a "drag" gesture in dp (3dp equals + * to about 9 pixels on a 5.5" FHD screen) + */ + public BarLineChartTouchListener(BarLineChartBase>> chart, Matrix touchMatrix, float dragTriggerDistance) { super(chart); this.mMatrix = touchMatrix; - // this equals to about 9 pixels on a 5.5" FHD screen - this.mDragTriggerDist = Utils.convertDpToPixel(3f); + this.mDragTriggerDist = Utils.convertDpToPixel(dragTriggerDistance); this.mMinScalePointerDistance = Utils.convertDpToPixel(3.5f); } @@ -207,7 +215,8 @@ public boolean onTouch(View v, MotionEvent event) { mDecelerationCurrentPoint = new PointF(event.getX(), event.getY()); mDecelerationVelocity = new PointF(velocityX, velocityY); - Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google + Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by + // Google } } @@ -513,6 +522,16 @@ public Matrix getMatrix() { return mMatrix; } + /** + * Sets the minimum distance that will be interpreted as a "drag" by the chart in dp. + * Default: 3dp + * + * @param dragTriggerDistance + */ + public void setDragTriggerDist(float dragTriggerDistance) { + this.mDragTriggerDist = Utils.convertDpToPixel(dragTriggerDistance); + } + @Override public boolean onDoubleTap(MotionEvent e) { @@ -573,21 +592,6 @@ public boolean onSingleTapUp(MotionEvent e) { return super.onSingleTapUp(e); } -// @Override -// public boolean onSingleTapConfirmed(MotionEvent e) { -// -// mLastGesture = ChartGesture.SINGLE_TAP; -// -// OnChartGestureListener l = mChart.getOnChartGestureListener(); -// -// if (l != null) { -// l.onChartSingleTapped(e); -// l.onChartGestureEnd(e, mLastGesture); -// } -// -// return super.onSingleTapConfirmed(e); -// } - @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { @@ -624,7 +628,8 @@ public void computeScroll() { mDecelerationCurrentPoint.x += distanceX; mDecelerationCurrentPoint.y += distanceY; - MotionEvent event = MotionEvent.obtain(currentTime, currentTime, MotionEvent.ACTION_MOVE, mDecelerationCurrentPoint.x, mDecelerationCurrentPoint.y, 0); + MotionEvent event = MotionEvent.obtain(currentTime, currentTime, MotionEvent.ACTION_MOVE, mDecelerationCurrentPoint.x, + mDecelerationCurrentPoint.y, 0); performDrag(event); event.recycle(); mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, false); From bb0ad3ac22cdfe1a25133b9979f018d271c86179 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 00:33:26 +0200 Subject: [PATCH 1018/1390] Fix bug related to inverted axis & scrolling #1829 --- .../listener/BarLineChartTouchListener.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 620db7b45c..e82f3cd77c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -296,8 +296,7 @@ private void performDrag(MotionEvent event) { float dX, dY; // check if axis is inverted - if (mChart.isAnyAxisInverted() && mClosestDataSetToTouch != null - && mChart.getAxis(mClosestDataSetToTouch.getAxisDependency()).isInverted()) { + if (inverted()) { // if there is an inverted horizontalbarchart if (mChart instanceof HorizontalBarChart) { @@ -498,8 +497,7 @@ public PointF getTrans(float x, float y) { float yTrans = 0f; // check if axis is inverted - if (mChart.isAnyAxisInverted() && mClosestDataSetToTouch != null - && mChart.isInverted(mClosestDataSetToTouch.getAxisDependency())) { + if (inverted()) { yTrans = -(y - vph.offsetTop()); } else { yTrans = -(mChart.getMeasuredHeight() - y - vph.offsetBottom()); @@ -508,6 +506,16 @@ public PointF getTrans(float x, float y) { return new PointF(xTrans, yTrans); } + /** + * Returns true if the current touch situation should be interpreted as inverted, false if not. + * + * @return + */ + private boolean inverted() { + return (mClosestDataSetToTouch == null && mChart.isAnyAxisInverted()) || (mClosestDataSetToTouch != null + && mChart.isInverted(mClosestDataSetToTouch.getAxisDependency())); + } + /** * ################ ################ ################ ################ */ From 735a9b9c98ab555373de99ccd3f420f27f470e47 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 00:44:51 +0200 Subject: [PATCH 1019/1390] Fixes related to no data text #1749 --- .../com/github/mikephil/charting/charts/Chart.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index b09a2705a3..27223cd3e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -300,16 +300,13 @@ public void onAnimationUpdate(ValueAnimator animation) { */ public void setData(T data) { + mData = data; + mOffsetsCalculated = false; + if (data == null) { - Log.e(LOG_TAG, - "Cannot set data for chart. Provided data object is null."); return; } - // LET THE CHART KNOW THERE IS DATA - mOffsetsCalculated = false; - mData = data; - // calculate how many digits are needed calculateFormatter(data.getYMin(), data.getYMax()); @@ -331,13 +328,14 @@ public void setData(T data) { */ public void clear() { mData = null; + mOffsetsCalculated = false; mIndicesToHighlight = null; invalidate(); } /** - * Removes all DataSets (and thereby Entries) from the chart. Does not - * remove the x-values. Also refreshes the chart by calling invalidate(). + * Removes all DataSets (and thereby Entries) from the chart. Does not set the data object to null. Also refreshes the + * chart by calling invalidate(). */ public void clearValues() { mData.clearValues(); From f75ea845e0111f4388384eb8e5e859e78c9a6177 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 00:56:04 +0200 Subject: [PATCH 1020/1390] Work on scatterdataset copy --- .../com/github/mikephil/charting/data/ScatterDataSet.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index 4c9cbe8c6f..b07897d6c3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -53,13 +53,16 @@ public DataSet copy() { } ScatterDataSet copied = new ScatterDataSet(yVals, getLabel()); + copied.mDrawValues = mDrawValues; + copied.mValueColors = mValueColors; copied.mColors = mColors; copied.mShapeSize = mShapeSize; copied.mScatterShape = mScatterShape; copied.mScatterShapeHoleRadius = mScatterShapeHoleRadius; copied.mScatterShapeHoleColor = mScatterShapeHoleColor; - //copied.mCustomScatterPath = mCustomScatterPath; + copied.mHighlightLineWidth = mHighlightLineWidth; copied.mHighLightColor = mHighLightColor; + copied.mHighlightDashPathEffect = mHighlightDashPathEffect; return copied; } From 8a6139b1fbe77f875a900158087128f691d8a2e9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 12:18:43 +0200 Subject: [PATCH 1021/1390] Fixes related to DefaultValueFormatter #1809 --- .../BarChartActivityMultiDataset.java | 2 +- .../mikephil/charting/charts/Chart.java | 16 +++++------ .../mikephil/charting/data/BaseDataSet.java | 7 ++++- .../formatter/AxisValueFormatter.java | 2 +- .../formatter/DefaultValueFormatter.java | 28 +++++++++++++++++-- .../interfaces/datasets/IDataSet.java | 7 +++++ .../github/mikephil/charting/utils/Utils.java | 18 ------------ 7 files changed, 49 insertions(+), 31 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index f76fee3b8c..a75182bce8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -195,7 +195,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); - float mult = mSeekBarY.getProgress() * 1000f; + float mult = mSeekBarY.getProgress() * 100000f; for (int i = startYear; i < endYear; i++) { float val = (float) (Math.random() * mult) + 3; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 27223cd3e9..6b16ab3713 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -100,7 +100,7 @@ public abstract class Chart { */ ValueFormatter getValueFormatter(); + /** + * Returns true if the valueFormatter object of this DataSet is null. + * + * @return + */ + boolean needsFormatter(); + /** * Sets the color the value-labels of this DataSet should have. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index ea249d95f2..3da44084b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -19,9 +19,6 @@ import android.view.View; import android.view.ViewConfiguration; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; - import java.util.List; /** @@ -380,21 +377,6 @@ public static double nextUp(double d) { } } - /** - * If this component has no ValueFormatter or is only equipped with the - * default one (no custom set), return true. - * - * @return - */ - public static boolean needsDefaultFormatter(ValueFormatter formatter) { - if (formatter == null) - return true; - if (formatter instanceof DefaultValueFormatter) - return true; - - return false; - } - /** * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. From 005c166e0797bb00382252693d4087303eb72fc3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 12:24:56 +0200 Subject: [PATCH 1022/1390] Cleanup --- .../mpchartexample/custom/DayAxisValueFormatter.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 11e411a7c9..8e906c4921 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -32,10 +32,6 @@ public String getFormattedValue(float value, AxisBase axis) { String monthName = mMonths[month % mMonths.length]; String yearName = String.valueOf(year); - if (year == 2017) { - System.out.println(""); - } - if (chart.getVisibleXRange() > 30 * axis.getLabelCount()) { return monthName + " " + yearName; From 19265217bd1702e34bc4743ecce189648aec76e6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 18 Jun 2016 16:09:22 +0200 Subject: [PATCH 1023/1390] Provide example for #1865 --- MPChartExample/AndroidManifest.xml | 1 + .../mpchartexample/FilledLineActivity.java | 150 ++++++++++++++++++ .../notimportant/MainActivity.java | 8 + 3 files changed, 159 insertions(+) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index c0e6931a4c..e07a8bdfda 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -64,6 +64,7 @@ + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java new file mode 100644 index 0000000000..ece33d8964 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -0,0 +1,150 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class FilledLineActivity extends DemoBase { + + private LineChart mChart; + private int mFillColor = Color.argb(150, 51, 181, 229); + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart_noseekbar); + + mChart = (LineChart) findViewById(R.id.chart1); + mChart.setBackgroundColor(Color.WHITE); + mChart.setGridBackgroundColor(mFillColor); + mChart.setDrawGridBackground(true); + + mChart.setDrawBorders(true); + + // no description text + mChart.setDescription(""); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(false); + + Legend l = mChart.getLegend(); + l.setEnabled(false); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setEnabled(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.setAxisMaxValue(900f); + leftAxis.setAxisMinValue(-250f); + leftAxis.setDrawAxisLine(false); + leftAxis.setDrawZeroLine(false); + leftAxis.setDrawGridLines(false); + + mChart.getAxisRight().setEnabled(false); + + // add data + setData(100, 60); + + mChart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 50;// + (float) + // ((mult * + // 0.1) / 10); + yVals1.add(new Entry(i, val)); + } + + ArrayList yVals2 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 450;// + (float) + // ((mult * + // 0.1) / 10); + yVals2.add(new Entry(i, val)); + } + + LineDataSet set1, set2; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); + set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); + set1.setValues(yVals1); + set2.setValues(yVals2); + mChart.getData().notifyDataChanged(); + mChart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(yVals1, "DataSet 1"); + + set1.setAxisDependency(YAxis.AxisDependency.LEFT); + set1.setColor(Color.rgb(255, 241, 46)); + set1.setDrawCircles(false); + set1.setLineWidth(2f); + set1.setCircleRadius(3f); + set1.setFillAlpha(255); + set1.setDrawFilled(true); + set1.setFillColor(Color.WHITE); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + set1.setFillFormatter(new FillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return mChart.getAxisLeft().getAxisMinimum(); + } + }); + + // create a dataset and give it a type + set2 = new LineDataSet(yVals2, "DataSet 2"); + set2.setAxisDependency(YAxis.AxisDependency.LEFT); + set2.setColor(Color.rgb(255, 241, 46)); + set2.setDrawCircles(false); + set2.setLineWidth(2f); + set2.setCircleRadius(3f); + set2.setFillAlpha(255); + set2.setDrawFilled(true); + set2.setFillColor(Color.WHITE); + set2.setDrawCircleHole(false); + set2.setHighLightColor(Color.rgb(244, 117, 117)); + set2.setFillFormatter(new FillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return mChart.getAxisLeft().getAxisMaximum(); + } + }); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); // add the datasets + dataSets.add(set2); + + // create a data object with the datasets + LineData data = new LineData(dataSets); + data.setDrawValues(false); + + // set data + mChart.setData(data); + } + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 1cf582ce6d..a462f4517c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -24,6 +24,7 @@ import com.xxmassdeveloper.mpchartexample.CombinedChartActivity; import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity; +import com.xxmassdeveloper.mpchartexample.FilledLineActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; @@ -139,6 +140,9 @@ protected void onCreate(Bundle savedInstanceState) { "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds."); time.isNew = true; objects.add(time); + objects.add(new ContentItem( + "Filled LineChart", + "This demonstrates how to fill an area between two LineDataSets.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -274,6 +278,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, LineChartTime.class); startActivity(i); break; + case 30: + i = new Intent(this, FilledLineActivity.class); + startActivity(i); + break; } From 2dc7207f1348e0e46e39f85f983403ea271233e2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 19 Jun 2016 21:19:08 +0200 Subject: [PATCH 1024/1390] Fix weird nullpointer #1404 --- .../github/mikephil/charting/highlight/ChartHighlighter.java | 1 + .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 9674504d4b..8e9eeafb25 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -202,6 +202,7 @@ public Highlight getClosestHighlightByPixel(List closestValues, float * @return */ protected float getDistance(float x1, float y1, float x2, float y2) { + //return Math.abs(x1 - x2); return (float) Math.hypot(x1 - x2, y1 - y2); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 05c9d531ed..4391cd151c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -590,7 +590,7 @@ public void drawExtras(Canvas c) { */ protected void drawHole(Canvas c) { - if (mChart.isDrawHoleEnabled()) { + if (mChart.isDrawHoleEnabled() && mBitmapCanvas != null) { float radius = mChart.getRadius(); float holeRadius = radius * (mChart.getHoleRadius() / 100); From 95bd8a580e562251b090f23acfc4a18d6c87b799 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 19 Jun 2016 21:35:23 +0200 Subject: [PATCH 1025/1390] Improvements regarding highlighting, issue #1335 --- .../mpchartexample/CubicLineChartActivity.java | 1 + .../java/com/github/mikephil/charting/charts/Chart.java | 4 ++-- .../mikephil/charting/highlight/BarHighlighter.java | 9 +++++---- .../mikephil/charting/highlight/ChartHighlighter.java | 5 +++-- .../mikephil/charting/highlight/CombinedHighlighter.java | 8 ++++---- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index a775b5d8fb..2fc7d2b210 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -69,6 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setPinchZoom(false); mChart.setDrawGridBackground(false); + mChart.setMaxHighlightDistance(300); XAxis x = mChart.getXAxis(); x.setEnabled(false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 6b16ab3713..58995395db 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -230,7 +230,7 @@ public void onAnimationUpdate(ValueAnimator animation) { // initialize the utils Utils.init(getContext()); - mMaxHighlightDistance = Utils.convertDpToPixel(70f); + mMaxHighlightDistance = Utils.convertDpToPixel(100f); mViewPortHandler = new ViewPortHandler(); @@ -496,7 +496,7 @@ public float getMaxHighlightDistance() { /** * Sets the maximum distance in screen dp a touch can be away from an entry to cause it to get highlighted. - * Default: 70dp + * Default: 100dp * * @param distDp */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 9f39fc599f..a1efc8df88 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -18,14 +18,15 @@ public BarHighlighter(BarDataProvider chart) { @Override public Highlight getHighlight(float x, float y) { + Highlight high = super.getHighlight(x, y); - BarData barData = mChart.getBarData(); + if(high == null) { + return null; + } PointD pos = getValsForTouch(x, y); - Highlight high = getHighlightForX((float) pos.x, x, y); - if (high == null) - return null; + BarData barData = mChart.getBarData(); IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex()); if (set.isStacked()) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 8e9eeafb25..58ea3cbc67 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -128,8 +128,8 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { if (!dataSet.isHighlightEnabled()) continue; - vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.UP)); - vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); + vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST)); + //vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); } return vals; @@ -202,6 +202,7 @@ public Highlight getClosestHighlightByPixel(List closestValues, float * @return */ protected float getDistance(float x1, float y1, float x2, float y2) { + //return Math.abs(y1 - y2); //return Math.abs(x1 - x2); return (float) Math.hypot(x1 - x2, y1 - y2); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index b8500fb092..c9ba0b4e6d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -57,13 +57,13 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { if (!dataSet.isHighlightEnabled()) continue; - Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.UP); + Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.CLOSEST); s1.setDataIndex(i); vals.add(s1); - Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); - s2.setDataIndex(i); - vals.add(s2); +// Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); +// s2.setDataIndex(i); +// vals.add(s2); } } } From adfc9a5c77597152f5865be9836ea31d1c9f08a4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 19 Jun 2016 21:42:38 +0200 Subject: [PATCH 1026/1390] Fix issue related to values not being drawn --- .../java/com/github/mikephil/charting/utils/Transformer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 6d16b2107e..e6e3bc17af 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -131,7 +131,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, */ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY, int from, int to) { - final int count = (int) Math.ceil(to - from) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; + final int count = (to - from + 1) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; float[] valuePoints = new float[count]; @@ -189,7 +189,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, public float[] generateTransformedValuesCandle(ICandleDataSet data, float phaseX, float phaseY, int from, int to) { - final int count = (int) Math.ceil((to - from) * phaseX) * 2; + final int count = (int) ((to - from) * phaseX + 1) * 2; float[] valuePoints = new float[count]; From c18a2e270cc5d8cbdc9ca65e3863530d6e02b40e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 19 Jun 2016 21:53:31 +0200 Subject: [PATCH 1027/1390] Improvements to scatter value rendering --- .../charting/highlight/ChartHighlighter.java | 9 ++++++++- .../charting/renderer/ScatterChartRenderer.java | 10 ++++++---- .../github/mikephil/charting/utils/Transformer.java | 12 +++++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 58ea3cbc67..0deaea5ebf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -59,6 +59,10 @@ protected Highlight getHighlightForX(float xVal, float x, float y) { List closestValues = getHighlightsAtXPos(xVal, x, y); + if(closestValues.isEmpty()) { + return null; + } + float leftAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.LEFT); float rightAxisMinDist = getMinimumDistance(closestValues, y, YAxis.AxisDependency.RIGHT); @@ -128,7 +132,10 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { if (!dataSet.isHighlightEnabled()) continue; - vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST)); + Highlight high = buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST); + + if(high != null) + vals.add(high); //vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index c4381aab3c..c0a07fe1f1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -319,13 +319,15 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); + XBounds bounds = getXBounds(mChart, dataSet); + float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesScatter(dataSet, - mAnimator.getPhaseY()); + mAnimator.getPhaseX(), mAnimator.getPhaseY(), bounds.min, bounds.max); float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); - for (int j = 0; j < positions.length * mAnimator.getPhaseX(); j += 2) { + for (int j = 0; j < positions.length; j += 2) { if (!mViewPortHandler.isInBoundsRight(positions[j])) break; @@ -335,10 +337,10 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; - Entry entry = dataSet.getEntryForIndex(j / 2); + Entry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, positions[j], - positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2)); + positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + bounds.min)); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index e6e3bc17af..392d35e53b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -102,14 +102,16 @@ public void prepareMatrixOffset(boolean inverted) { * @param data * @return */ - public float[] generateTransformedValuesScatter(IScatterDataSet data, - float phaseY) { + public float[] generateTransformedValuesScatter(IScatterDataSet data, float phaseX, + float phaseY, int from, int to) { - float[] valuePoints = new float[data.getEntryCount() * 2]; + final int count = (int) ((to - from) * phaseX + 1) * 2; - for (int j = 0; j < valuePoints.length; j += 2) { + float[] valuePoints = new float[count]; - Entry e = data.getEntryForIndex(j / 2); + for (int j = 0; j < count; j += 2) { + + Entry e = data.getEntryForIndex(j / 2 + from); if (e != null) { valuePoints[j] = e.getX(); From 82d5fde6f2e8fc7ef1f90257de3671bac6d2d544 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 19 Jun 2016 23:51:25 +0200 Subject: [PATCH 1028/1390] Add feature that allows different styling for value and entry labels (former slice-text) --- .../mpchartexample/PieChartActivity.java | 7 ++- .../PiePolylineChartActivity.java | 2 +- .../mikephil/charting/charts/PieChart.java | 54 +++++++++++++++---- .../charting/renderer/PieChartRenderer.java | 53 ++++++++++++------ .../mikephil/charting/utils/Transformer.java | 2 - 5 files changed, 89 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 1da4792f36..9027e5baa9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -100,6 +100,11 @@ protected void onCreate(Bundle savedInstanceState) { l.setXEntrySpace(7f); l.setYEntrySpace(0f); l.setYOffset(0f); + + // entry label styling + mChart.setEntryLabelColor(Color.WHITE); + mChart.setEntryLabelTypeface(mTfRegular); + mChart.setEntryLabelTextSize(12f); } @Override @@ -137,7 +142,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleXVals: { - mChart.setDrawSliceText(!mChart.isDrawSliceTextEnabled()); + mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 1cbfd58638..cae2d2de89 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -141,7 +141,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleXVals: { - mChart.setDrawSliceText(!mChart.isDrawSliceTextEnabled()); + mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); mChart.invalidate(); break; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index e56ef96b2e..4b2170ff95 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -10,8 +10,6 @@ import android.util.AttributeSet; import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.PieHighlighter; @@ -35,9 +33,9 @@ public class PieChart extends PieRadarChartBase { private RectF mCircleBox = new RectF(); /** - * flag indicating if the x-labels should be drawn or not + * flag indicating if entry labels should be drawn or not */ - private boolean mDrawXLabels = true; + private boolean mDrawEntryLabels = true; /** * array that holds the width of each pie-slice in degrees @@ -560,21 +558,59 @@ public void setTransparentCircleAlpha(int alpha) { } /** - * set this to true to draw the x-value text into the pie slices + * Set this to true to draw the entry labels into the pie slices (Provided by the getLabel() method of the PieEntry class). + * Deprecated -> use setDrawEntryLabels(...) instead. * * @param enabled */ + @Deprecated public void setDrawSliceText(boolean enabled) { - mDrawXLabels = enabled; + mDrawEntryLabels = enabled; + } + + /** + * Set this to true to draw the entry labels into the pie slices (Provided by the getLabel() method of the PieEntry class). + * + * @param enabled + */ + public void setDrawEntryLabels(boolean enabled) { + mDrawEntryLabels = enabled; } /** - * returns true if drawing x-values is enabled, false if not + * Returns true if drawing the entry labels is enabled, false if not. * * @return */ - public boolean isDrawSliceTextEnabled() { - return mDrawXLabels; + public boolean isDrawEntryLabelsEnabled() { + return mDrawEntryLabels; + } + + /** + * Sets the color the entry labels are drawn with. + * + * @param color + */ + public void setEntryLabelColor(int color) { + ((PieChartRenderer) mRenderer).getPaintEntryLabels().setColor(color); + } + + /** + * Sets a custom Typeface for the drawing of the entry labels. + * + * @param tf + */ + public void setEntryLabelTypeface(Typeface tf) { + ((PieChartRenderer) mRenderer).getPaintEntryLabels().setTypeface(tf); + } + + /** + * Sets the size of the entry labels in dp. Default: 13dp + * + * @param size + */ + public void setEntryLabelTextSize(float size) { + ((PieChartRenderer) mRenderer).getPaintEntryLabels().setTextSize(Utils.convertDpToPixel(size)); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 4391cd151c..2f8b127d20 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -18,7 +18,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; @@ -51,6 +50,11 @@ public class PieChartRenderer extends DataRenderer { */ private TextPaint mCenterTextPaint; + /** + * paint object used for drwing the slice-text + */ + private Paint mEntryLabelsPaint; + private StaticLayout mCenterTextLayout; private CharSequence mCenterTextLastValue; private RectF mCenterTextLastBounds = new RectF(); @@ -85,6 +89,11 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mValuePaint.setColor(Color.WHITE); mValuePaint.setTextAlign(Align.CENTER); + mEntryLabelsPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mEntryLabelsPaint.setColor(Color.WHITE); + mEntryLabelsPaint.setTextAlign(Align.CENTER); + mEntryLabelsPaint.setTextSize(Utils.convertDpToPixel(13f)); + mValueLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mValueLinePaint.setStyle(Style.STROKE); } @@ -101,6 +110,10 @@ public TextPaint getPaintCenterText() { return mCenterTextPaint; } + public Paint getPaintEntryLabels() { + return mEntryLabelsPaint; + } + @Override public void initBuffers() { // TODO Auto-generated method stub @@ -392,7 +405,7 @@ public void drawValues(Canvas c) { float yValueSum = data.getYValueSum(); - boolean drawXVals = mChart.isDrawSliceTextEnabled(); + boolean drawEntryLabels = mChart.isDrawEntryLabelsEnabled(); float angle; int xIndex = 0; @@ -403,9 +416,9 @@ public void drawValues(Canvas c) { IPieDataSet dataSet = dataSets.get(i); - final boolean drawYVals = dataSet.isDrawValuesEnabled(); + final boolean drawValues = dataSet.isDrawValuesEnabled(); - if (!drawYVals && !drawXVals) + if (!drawValues && !drawEntryLabels) continue; final PieDataSet.ValuePosition xValuePosition = dataSet.getXValuePosition(); @@ -453,13 +466,13 @@ public void drawValues(Canvas c) { final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD); - final boolean drawXOutside = drawXVals && + final boolean drawXOutside = drawEntryLabels && xValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE; - final boolean drawYOutside = drawYVals && + final boolean drawYOutside = drawValues && yValuePosition == PieDataSet.ValuePosition.OUTSIDE_SLICE; - final boolean drawXInside = drawXVals && + final boolean drawXInside = drawEntryLabels && xValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE; - final boolean drawYInside = drawYVals && + final boolean drawYInside = drawValues && yValuePosition == PieDataSet.ValuePosition.INSIDE_SLICE; if (drawXOutside || drawYOutside) { @@ -523,14 +536,12 @@ public void drawValues(Canvas c) { dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entry.getLabel() != null) { - c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight, - mValuePaint); + drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight); } } else if (drawXOutside) { if (j < data.getEntryCount() && entry.getLabel() != null) { - mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f, mValuePaint); + drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f); } } else if (drawYOutside) { @@ -552,14 +563,12 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entry.getLabel() != null) { - c.drawText(entry.getLabel(), x, y + lineHeight, - mValuePaint); + drawEntryLabel(c, entry.getLabel(), x, y + lineHeight); } } else if (drawXInside) { if (j < data.getEntryCount() && entry.getLabel() != null) { - mValuePaint.setColor(dataSet.getValueTextColor(j)); - c.drawText(entry.getLabel(), x, y + lineHeight / 2f, mValuePaint); + drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f); } } else if (drawYInside) { @@ -574,6 +583,18 @@ public void drawValues(Canvas c) { c.restore(); } + /** + * Draws an entry label at the specified position. + * + * @param c + * @param label + * @param x + * @param y + */ + protected void drawEntryLabel(Canvas c, String label, float x, float y) { + c.drawText(label, x, y, mEntryLabelsPaint); + } + @Override public void drawExtras(Canvas c) { // drawCircles(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 392d35e53b..8604d56cbd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -5,10 +5,8 @@ import android.graphics.Path; import android.graphics.RectF; -import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; From 72890afc106054ae5d63ebc9b819612d269facf9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 20 Jun 2016 20:50:09 +0200 Subject: [PATCH 1029/1390] Minor fixes related to double tap highlight --- .../mpchartexample/CombinedChartActivity.java | 5 ----- .../charting/listener/BarLineChartTouchListener.java | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 068491927f..5c244de75b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -125,7 +125,6 @@ private LineData generateLineData() { set.setValueTextColor(Color.rgb(240, 238, 70)); set.setAxisDependency(YAxis.AxisDependency.LEFT); - this.set1 = set; d.addDataSet(set); return d; @@ -209,9 +208,6 @@ protected CandleData generateCandleData() { return d; } - private LineDataSet set1; - private BubbleDataSet set2; - protected BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); @@ -230,7 +226,6 @@ protected BubbleData generateBubbleData() { set.setValueTextColor(Color.WHITE); set.setHighlightCircleWidth(1.5f); set.setDrawValues(true); - this.set2 = set; bd.addDataSet(set); return bd; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index e82f3cd77c..0fe3ef94ac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -552,7 +552,7 @@ public boolean onDoubleTap(MotionEvent e) { } // check if double-tap zooming is enabled - if (mChart.isDoubleTapToZoomEnabled()) { + if (mChart.isDoubleTapToZoomEnabled() && mChart.getData().getEntryCount() > 0) { PointF trans = getTrans(e.getX(), e.getY()); From ded930a2fa99a2e48d86704607d1e19aa60f12b7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 21 Jun 2016 09:39:48 +0200 Subject: [PATCH 1030/1390] Work on viewport modifications for horizontal barchart (issue #1842) --- MPChartExample/build.gradle | 2 +- .../charting/charts/BarLineChartBase.java | 21 +++++++++---------- .../charting/charts/HorizontalBarChart.java | 20 ++++++++++++++++++ .../charting/utils/ViewPortHandler.java | 14 +++++++++++++ 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index dd8194aa12..13914819a6 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -57,5 +57,5 @@ dependencies { compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) - //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' + //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 3e907e3deb..428530bf70 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -719,7 +719,7 @@ public void setScaleMinima(float scaleX, float scaleY) { /** * Sets the size of the area (range on the x-axis) that should be maximum * visible at once (no further zooming out allowed). If this is e.g. set to - * 10, no more than 10 values on the x-axis can be viewed at once without + * 10, no more than a range of 10 on the x-axis can be viewed at once without * scrolling. * * @param maxXRange The maximum visible range of x-values. @@ -732,7 +732,7 @@ public void setVisibleXRangeMaximum(float maxXRange) { /** * Sets the size of the area (range on the x-axis) that should be minimum * visible at once (no further zooming in allowed). If this is e.g. set to - * 10, no less than 10 values on the x-axis can be viewed at once without + * 10, no less than a range of 10 on the x-axis can be viewed at once without * scrolling. * * @param minXRange The minimum visible range of x-values. @@ -743,9 +743,8 @@ public void setVisibleXRangeMinimum(float minXRange) { } /** - * Limits the maximum and minimum value count that can be visible by - * pinching and zooming. e.g. minRange=10, maxRange=100 no less than 10 - * values and no more that 100 values can be viewed at once without + * Limits the maximum and minimum x range that can be visible by pinching and zooming. e.g. minRange=10, maxRange=100 the + * smallest range to be displayed at once is 10, and no more than a range of 100 values can be viewed at once without * scrolling * * @param minXRange @@ -770,14 +769,14 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { } /** - * Moves the left side of the current viewport to the specified x-index. + * Moves the left side of the current viewport to the specified x-position. * This also refreshes the chart by calling invalidate(). * - * @param xIndex + * @param xValue */ - public void moveViewToX(float xIndex) { + public void moveViewToX(float xValue) { - Runnable job = new MoveViewJob(mViewPortHandler, xIndex, 0f, + Runnable job = new MoveViewJob(mViewPortHandler, xValue, 0f, getTransformer(AxisDependency.LEFT), this); addViewportJob(job); @@ -802,7 +801,7 @@ public void moveViewToY(float yValue, AxisDependency axis) { /** * This will move the left side of the current viewport to the specified - * x value on the x-axis, and center the viewport to the specified y value on the y-axis. + * x-value on the x-axis, and center the viewport to the specified y value on the y-axis. * This also refreshes the chart by calling invalidate(). * * @param xValue @@ -820,7 +819,7 @@ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { } /** - * This will move the left side of the current viewport to the specified x value + * This will move the left side of the current viewport to the specified x-value * and center the viewport to the y value animated. * This also refreshes the chart by calling invalidate(). * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index f95132769b..0c378df0db 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -7,6 +7,7 @@ import android.util.Log; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; @@ -205,4 +206,23 @@ public float getHighestVisibleX() { mViewPortHandler.contentTop()); return (float) Math.min(mXAxis.mAxisMaximum, pos.y); } + + @Override + public void setVisibleXRangeMaximum(float maxXRange) { + float xScale = mXAxis.mAxisRange / (maxXRange); + mViewPortHandler.setMinimumScaleY(xScale); + } + + @Override + public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { + float yScale = getDeltaY(axis) / maxYRange; + mViewPortHandler.setMinimumScaleX(yScale); + } + + @Override + public void setVisibleXRange(float minXRange, float maxXRange) { + float maxScale = mXAxis.mAxisRange / minXRange; + float minScale = mXAxis.mAxisRange / maxXRange; + mViewPortHandler.setMinMaxScaleY(minScale, maxScale); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index e7cfac56b3..d58f3f09ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -509,6 +509,20 @@ public void setMaximumScaleY(float yScale) { limitTransAndScale(mMatrixTouch, mContentRect); } + public void setMinMaxScaleY(float minScaleY, float maxScaleY) { + + if (minScaleY < 1f) + minScaleY = 1f; + + if (maxScaleY == 0.f) + maxScaleY = Float.MAX_VALUE; + + mMinScaleX = minScaleY; + mMaxScaleX = maxScaleY; + + limitTransAndScale(mMatrixTouch, mContentRect); + } + /** * Returns the charts-touch matrix used for translation and scale on touch. * From f83a7e3b26ddaf4b68ffacb59fe67c9e3b55fe2d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 21 Jun 2016 11:11:49 +0200 Subject: [PATCH 1031/1390] Minor changes to highlighting --- .../java/com/github/mikephil/charting/charts/Chart.java | 2 +- .../github/mikephil/charting/highlight/Highlight.java | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 58995395db..e2d40d87c5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -632,7 +632,7 @@ public void highlightValue(Highlight high, boolean callListener) { } else { if (this instanceof BarLineChartBase && ((BarLineChartBase) this).isHighlightFullBarEnabled()) - high = new Highlight(high.getX(), Float.NaN, Float.NaN, Float.NaN, -1, YAxis.AxisDependency.LEFT); + high = new Highlight(high.getX(), -1); // set the indices to highlight mIndicesToHighlight = new Highlight[]{ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index f8989a4da7..021f80cce8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -70,6 +70,11 @@ public Highlight(float x, int dataSetIndex) { this.mDataSetIndex = dataSetIndex; } + public Highlight(float x, int dataSetIndex, int stackIndex) { + this(x, dataSetIndex); + this.mStackIndex = stackIndex; + } + /** * constructor * @@ -77,7 +82,7 @@ public Highlight(float x, int dataSetIndex) { * @param y the y-value of the highlighted value * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ - public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis.AxisDependency axis) { + protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis.AxisDependency axis) { this.mX = x; this.mY = y; this.mXPx = xPx; @@ -96,7 +101,7 @@ public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis * selected * @param range the range the selected stack-value is in */ - public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, Range range, + protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, Range range, YAxis.AxisDependency axis) { this(x, y, xPx, yPx, dataSetIndex, axis); this.mStackIndex = stackIndex; From 6878220e2e798e8c4e0b20e39bb051633b9c96ea Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 22 Jun 2016 01:06:56 +0200 Subject: [PATCH 1032/1390] Improvements to chart highlighting --- .../mikephil/charting/charts/BarChart.java | 12 +++ .../mikephil/charting/data/BarEntry.java | 47 ++++++++++++ .../charting/highlight/BarHighlighter.java | 73 +++++++++---------- .../charting/highlight/ChartHighlighter.java | 1 - .../charting/highlight/Highlight.java | 19 +---- .../charting/renderer/BarChartRenderer.java | 10 ++- 6 files changed, 102 insertions(+), 60 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index fbcf5ccc0b..a8c166d5a5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -183,6 +183,18 @@ public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; } + /** + * Highlights the value at the given x-position in the given DataSet. Provide + * -1 as the dataSetIndex to undo all highlighting. + * + * @param x + * @param dataSetIndex + * @param stackIndex the index inside the stack - only relevant for stacked entries + */ + public void highlightValue(float x, int dataSetIndex, int stackIndex) { + highlightValue(new Highlight(x, dataSetIndex, stackIndex), false); + } + @Override public BarData getBarData() { return mData; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index 97358ae378..c884098d31 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -2,6 +2,8 @@ import android.annotation.SuppressLint; +import com.github.mikephil.charting.highlight.Range; + /** * Entry class for the BarChart. (especially stacked bars) * @@ -15,6 +17,11 @@ public class BarEntry extends Entry { */ private float[] mYVals; + /** + * the ranges for the individual stack values - automatically calculated + */ + private Range[] mRanges; + /** * the sum of all negative values this entry (if stacked) contains */ @@ -35,6 +42,7 @@ public BarEntry(float x, float[] vals) { super(x, calcSum(vals)); this.mYVals = vals; + calcRanges(); calcPosNegSum(); } @@ -59,6 +67,7 @@ public BarEntry(float x, float[] vals, String label) { super(x, calcSum(vals), label); this.mYVals = vals; + calcRanges(); calcPosNegSum(); } @@ -102,6 +111,7 @@ public void setVals(float[] vals) { setY(calcSum(vals)); mYVals = vals; calcPosNegSum(); + calcRanges(); } /** @@ -114,6 +124,15 @@ public float getY() { return super.getY(); } + /** + * Returns the ranges of the individual stack-entries. Will return null if this entry is not stacked. + * + * @return + */ + public Range[] getRanges() { + return mRanges; + } + /** * Returns true if this BarEntry is stacked (has a values array), false if not. * @@ -197,4 +216,32 @@ private static float calcSum(float[] vals) { return sum; } + + protected void calcRanges() { + + float[] values = getYVals(); + + if (values == null || values.length == 0) + return; + + mRanges = new Range[values.length]; + + float negRemain = -getNegativeSum(); + float posRemain = 0f; + + for (int i = 0; i < mRanges.length; i++) { + + float value = values[i]; + + if (value < 0) { + mRanges[i] = new Range(negRemain, negRemain + Math.abs(value)); + negRemain += Math.abs(value); + } else { + mRanges[i] = new Range(posRemain, posRemain + value); + posRemain += value; + } + } + } } + + diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index a1efc8df88..048db03299 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -61,14 +61,12 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal if (entry.getYVals() == null) { return high; } else { - Range[] ranges = getRanges(entry); + Range[] ranges = entry.getRanges(); if (ranges.length > 0) { int stackIndex = getClosestStackIndex(ranges, yVal); - Range range = ranges[stackIndex]; - - PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), range.to); + PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), ranges[stackIndex].to); Highlight stackedHigh = new Highlight( entry.getX(), @@ -77,7 +75,6 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal (float) pixels.y, high.getDataSetIndex(), stackIndex, - range, high.getAxis() ); @@ -116,39 +113,39 @@ protected int getClosestStackIndex(Range[] ranges, float value) { return (value > ranges[length].to) ? length : 0; } - /** - * Splits up the stack-values of the given bar-entry into Range objects. - * - * @param entry - * @return - */ - protected Range[] getRanges(BarEntry entry) { - - float[] values = entry.getYVals(); - - if (values == null || values.length == 0) - return new Range[0]; - - Range[] ranges = new Range[values.length]; - - float negRemain = -entry.getNegativeSum(); - float posRemain = 0f; - - for (int i = 0; i < ranges.length; i++) { - - float value = values[i]; - - if (value < 0) { - ranges[i] = new Range(negRemain, negRemain + Math.abs(value)); - negRemain += Math.abs(value); - } else { - ranges[i] = new Range(posRemain, posRemain + value); - posRemain += value; - } - } - - return ranges; - } +// /** +// * Splits up the stack-values of the given bar-entry into Range objects. +// * +// * @param entry +// * @return +// */ +// protected Range[] getRanges(BarEntry entry) { +// +// float[] values = entry.getYVals(); +// +// if (values == null || values.length == 0) +// return new Range[0]; +// +// Range[] ranges = new Range[values.length]; +// +// float negRemain = -entry.getNegativeSum(); +// float posRemain = 0f; +// +// for (int i = 0; i < ranges.length; i++) { +// +// float value = values[i]; +// +// if (value < 0) { +// ranges[i] = new Range(negRemain, negRemain + Math.abs(value)); +// negRemain += Math.abs(value); +// } else { +// ranges[i] = new Range(posRemain, posRemain + value); +// posRemain += value; +// } +// } +// +// return ranges; +// } @Override protected float getDistance(float x1, float y1, float x2, float y2) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 0deaea5ebf..ced7150c94 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -33,7 +33,6 @@ public Highlight getHighlight(float x, float y) { Highlight high = getHighlightForX(xVal, x, y); return high; } - /** * Returns the corresponding xPos for a given touch-position in pixels. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 021f80cce8..5599882ce7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -45,11 +45,6 @@ public class Highlight { */ private int mStackIndex = -1; - /** - * the range of the bar that is selected (only for stacked-barchart) - */ - private Range mRange; - /** * the axis the highlighted value belongs to */ @@ -99,13 +94,10 @@ protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YA * @param dataSetIndex the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected - * @param range the range the selected stack-value is in */ - protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, Range range, - YAxis.AxisDependency axis) { + protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, YAxis.AxisDependency axis) { this(x, y, xPx, yPx, dataSetIndex, axis); this.mStackIndex = stackIndex; - this.mRange = range; } /** @@ -172,15 +164,6 @@ public int getStackIndex() { return mStackIndex; } - /** - * Returns the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart) - * - * @return - */ - public Range getRange() { - return mRange; - } - public boolean isStacked() { return mStackIndex >= 0; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index ae6e12d793..94bd9a47b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.Transformer; @@ -343,14 +344,17 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mHighlightPaint.setColor(set.getHighLightColor()); mHighlightPaint.setAlpha(set.getHighLightAlpha()); - boolean isStack = high.getStackIndex() < 0 ? false : true; + boolean isStack = (high.getStackIndex() >= 0 && e.isStacked()) ? true : false; final float y1; final float y2; if (isStack) { - y1 = high.getRange().from; - y2 = high.getRange().to; + + Range range = e.getRanges()[high.getStackIndex()]; + + y1 = range.from; + y2 = range.to; } else { y1 = e.getY(); y2 = 0.f; From cb0226b2312dcd69c16d4dc0825f02c72471a8d8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 23 Jun 2016 15:11:19 +0200 Subject: [PATCH 1033/1390] Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a6fb7cac57..2e4d5b866c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # How to contribute -Bug-fixes and features often come from users of the Charts framework, and improving it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we +Bug-fixes and features often come from users of the MPAndroidChart library and improve it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. @@ -46,4 +46,4 @@ If you are reporting a bug which can be observed visually, please add to your is For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket. In this case, it is appropriate to start the first line of a commit with '(doc)' instead of -a ticket number. Even the default commit message the GitHub generates is fine with us. \ No newline at end of file +a ticket number. Even the default commit message the GitHub generates is fine with us. From 0eb69d246c567cdefe029a957c0a627504a95073 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jun 2016 23:01:05 +0200 Subject: [PATCH 1034/1390] Changes related to highlight full bar --- .../mpchartexample/CombinedChartActivity.java | 1 + .../mpchartexample/StackedBarActivity.java | 1 + .../StackedBarActivityNegative.java | 1 + .../mikephil/charting/charts/BarChart.java | 24 +++++++++++++++++++ .../charting/charts/BarLineChartBase.java | 22 ----------------- .../mikephil/charting/charts/Chart.java | 4 ---- .../charting/charts/CombinedChart.java | 24 +++++++++++++++++++ .../dataprovider/BarDataProvider.java | 1 + .../charting/renderer/BarChartRenderer.java | 2 +- 9 files changed, 53 insertions(+), 27 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 5c244de75b..519a15d219 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -55,6 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setBackgroundColor(Color.WHITE); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); + mChart.setHighlightFullBarEnabled(false); // draw bars behind lines mChart.setDrawOrder(new DrawOrder[]{ diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 9b9767001c..5c562190bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -69,6 +69,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(false); + mChart.setHighlightFullBarEnabled(false); // change the position of the y-labels YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index dc2a8825fc..200c012771 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -56,6 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); + mChart.setHighlightFullBarEnabled(false); mChart.getAxisLeft().setEnabled(false); mChart.getAxisRight().setAxisMaxValue(25f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index a8c166d5a5..fd38dea483 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -27,6 +27,11 @@ public class BarChart extends BarLineChartBase implements BarDataProvid */ private boolean mDrawHighlightArrow = false; + /** + * flag that indicates whether the highlight should be full-bar oriented, or single-value? + */ + protected boolean mHighlightFullBarEnabled = false; + /** * if set to true, all values are drawn above their bars, instead of below their top */ @@ -183,6 +188,25 @@ public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; } + /** + * Set this to true to make the highlight operation full-bar oriented, + * false to make it highlight single values (relevant only for stacked). + * Default: false + * + * @param enabled + */ + public void setHighlightFullBarEnabled(boolean enabled) { + mHighlightFullBarEnabled = enabled; + } + + /** + * @return true the highlight operation is be full-bar oriented, false if single-value + */ + @Override + public boolean isHighlightFullBarEnabled() { + return mHighlightFullBarEnabled; + } + /** * Highlights the value at the given x-position in the given DataSet. Provide * -1 as the dataSetIndex to undo all highlighting. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 428530bf70..478452d6ad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -77,11 +77,6 @@ public abstract class BarLineChartBase implements Com */ private boolean mDrawValueAboveBar = true; + + /** + * flag that indicates whether the highlight should be full-bar oriented, or single-value? + */ + protected boolean mHighlightFullBarEnabled = false; + /** * if set to true, a grey area is drawn behind each bar that indicates the * maximum value @@ -149,6 +155,24 @@ public void setDrawBarShadow(boolean enabled) { mDrawBarShadow = enabled; } + /** + * Set this to true to make the highlight operation full-bar oriented, + * false to make it highlight single values (relevant only for stacked). + * + * @param enabled + */ + public void setHighlightFullBarEnabled(boolean enabled) { + mHighlightFullBarEnabled = enabled; + } + + /** + * @return true the highlight operation is be full-bar oriented, false if single-value + */ + @Override + public boolean isHighlightFullBarEnabled() { + return mHighlightFullBarEnabled; + } + /** * Returns the currently set draw order. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java index 631060d2d6..9dfee07f9c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java @@ -7,4 +7,5 @@ public interface BarDataProvider extends BarLineScatterCandleBubbleDataProvider BarData getBarData(); boolean isDrawBarShadowEnabled(); boolean isDrawValueAboveBarEnabled(); + boolean isHighlightFullBarEnabled(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 94bd9a47b9..471ed7e558 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -349,7 +349,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float y1; final float y2; - if (isStack) { + if (isStack && !mChart.isHighlightFullBarEnabled()) { Range range = e.getRanges()[high.getStackIndex()]; From 5f8eb44d9f1f60099544ecc23a9ba2d2ffe5bccf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jun 2016 23:10:03 +0200 Subject: [PATCH 1035/1390] Fixes related to highlight rendering --- .../github/mikephil/charting/data/BarEntry.java | 2 +- .../charting/renderer/BarChartRenderer.java | 17 +++++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index c884098d31..023a159750 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -234,7 +234,7 @@ protected void calcRanges() { float value = values[i]; if (value < 0) { - mRanges[i] = new Range(negRemain, negRemain + Math.abs(value)); + mRanges[i] = new Range(negRemain, negRemain + value); negRemain += Math.abs(value); } else { mRanges[i] = new Range(posRemain, posRemain + value); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 471ed7e558..cffcc1c3da 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -349,12 +349,21 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float y1; final float y2; - if (isStack && !mChart.isHighlightFullBarEnabled()) { + if (isStack) { - Range range = e.getRanges()[high.getStackIndex()]; + if(mChart.isHighlightFullBarEnabled()) { + + y1 = e.getPositiveSum(); + y2 = -e.getNegativeSum(); + + } else { + + Range range = e.getRanges()[high.getStackIndex()]; + + y1 = range.from; + y2 = range.to; + } - y1 = range.from; - y2 = range.to; } else { y1 = e.getY(); y2 = 0.f; From f345d164ce4f6a6bceb40b78b1ca8f607ce8d8e6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 25 Jun 2016 11:00:29 +0200 Subject: [PATCH 1036/1390] Fix issue related to horizontal dashed grid lines #1756 --- .../HorizontalBarChartActivity.java | 1 - .../mpchartexample/LineChartActivity1.java | 2 + .../mikephil/charting/charts/BarChart.java | 31 ++------------- .../charting/renderer/XAxisRenderer.java | 39 ++++++++++++------- .../XAxisRendererHorizontalBarChart.java | 29 +++----------- 5 files changed, 37 insertions(+), 65 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index e828d4dcf7..2d3018a48a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -79,7 +79,6 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(mTfLight); xl.setDrawAxisLine(true); xl.setDrawGridLines(false); - xl.setGridLineWidth(0.3f); xl.setGranularity(10f); YAxis yl = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index fd8c8f9e4f..ade229807e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -104,9 +104,11 @@ protected void onCreate(Bundle savedInstanceState) { llXAxis.setTextSize(10f); XAxis xAxis = mChart.getXAxis(); + xAxis.enableGridDashedLine(10f, 10f, 0f); //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); //xAxis.addLimitLine(llXAxis); // add x-axis limit line + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); LimitLine ll1 = new LimitLine(130f, "Upper Limit"); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index fd38dea483..9b437c9028 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; @@ -22,11 +21,6 @@ */ public class BarChart extends BarLineChartBase implements BarDataProvider { - /** - * flag that enables or disables the highlighting arrow - */ - private boolean mDrawHighlightArrow = false; - /** * flag that indicates whether the highlight should be full-bar oriented, or single-value? */ @@ -133,24 +127,6 @@ public RectF getBarBounds(BarEntry e) { return bounds; } -// /** -// * set this to true to draw the highlightning arrow -// * -// * @param enabled -// */ -// public void setDrawHighlightArrow(boolean enabled) { -// mDrawHighlightArrow = enabled; -// } -// -// /** -// * returns true if drawing the highlighting arrow is enabled, false if not -// * -// * @return -// */ -// public boolean isDrawHighlightArrowEnabled() { -// return mDrawHighlightArrow; -// } - /** * If set to true, all values are drawn above their bars, instead of below their top. * @@ -189,8 +165,9 @@ public boolean isDrawBarShadowEnabled() { } /** - * Set this to true to make the highlight operation full-bar oriented, - * false to make it highlight single values (relevant only for stacked). + * Set this to true to make the highlight operation full-bar oriented, false to make it highlight single values (relevant + * only for stacked). If enabled, highlighting operations will highlight the whole bar, even if only a single stack entry + * was tapped. * Default: false * * @param enabled @@ -213,7 +190,7 @@ public boolean isHighlightFullBarEnabled() { * * @param x * @param dataSetIndex - * @param stackIndex the index inside the stack - only relevant for stacked entries + * @param stackIndex the index inside the stack - only relevant for stacked entries */ public void highlightValue(float x, int dataSetIndex, int stackIndex) { highlightValue(new Highlight(x, dataSetIndex, stackIndex), false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index dd17aec6c4..e0a2352cf5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -33,6 +33,12 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } + protected void setupGridPaint() { + mGridPaint.setColor(mXAxis.getGridColor()); + mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); + mGridPaint.setPathEffect(mXAxis.getGridDashPathEffect()); + } + @Override public void computeAxis(float min, float max, boolean inverted) { @@ -223,34 +229,39 @@ public void renderGridLines(Canvas c) { float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { - // only fill x values positions[i] = mXAxis.mEntries[i / 2]; + positions[i + 1] = mXAxis.mEntries[i / 2]; } mTrans.pointValuesToPixel(positions); - mGridPaint.setColor(mXAxis.getGridColor()); - mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - mGridPaint.setPathEffect(mXAxis.getGridDashPathEffect()); + setupGridPaint(); Path gridLinePath = new Path(); for (int i = 0; i < positions.length; i += 2) { - float x = positions[i]; + drawGridLine(c, positions[i], positions[i + 1], gridLinePath); + } + } - if (x >= mViewPortHandler.offsetLeft() - && x <= mViewPortHandler.getChartWidth()) { + /** + * Draws the grid line at the specified position using the provided path. + * + * @param c + * @param x + * @param y + * @param gridLinePath + */ + protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { - gridLinePath.moveTo(x, mViewPortHandler.contentBottom()); - gridLinePath.lineTo(x, mViewPortHandler.contentTop()); + gridLinePath.moveTo(x, mViewPortHandler.contentBottom()); + gridLinePath.lineTo(x, mViewPortHandler.contentTop()); - // draw a path because lines don't support dashing on lower android versions - c.drawPath(gridLinePath, mGridPaint); - } + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); - gridLinePath.reset(); - } + gridLinePath.reset(); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9f070e8ed0..526e4ef7fd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -152,32 +152,15 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } @Override - public void renderGridLines(Canvas c) { + protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { - if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) - return; - - mGridPaint.setColor(mXAxis.getGridColor()); - mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); - - float[] positions = new float[mXAxis.mEntryCount * 2]; - - for (int i = 0; i < positions.length; i += 2) { - positions[i + 1] = mXAxis.mEntries[i / 2]; - } - - mTrans.pointValuesToPixel(positions); - - for (int i = 0; i < positions.length; i += 2) { - - float y = positions[i + 1]; + gridLinePath.moveTo(mViewPortHandler.contentRight(), y); + gridLinePath.lineTo(mViewPortHandler.contentLeft(), y); - if (mViewPortHandler.isInBoundsY(y)) { + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); - c.drawLine(mViewPortHandler.contentLeft(), y, - mViewPortHandler.contentRight(), y, mGridPaint); - } - } + gridLinePath.reset(); } @Override From b5bfc3e2bd05c31a1b7ec18d3950a252cc86097c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jun 2016 00:24:19 +0200 Subject: [PATCH 1037/1390] Fixes related to setting visible axis range for horizontal barchart --- .../HorizontalBarChartActivity.java | 3 +- .../charting/charts/BarLineChartBase.java | 30 +++++++++++++++-- .../charting/charts/HorizontalBarChart.java | 33 ++++++++++++++++--- .../charting/utils/ViewPortHandler.java | 4 +-- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 2d3018a48a..411a0de200 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -111,7 +111,8 @@ protected void onCreate(Bundle savedInstanceState) { l.setFormSize(8f); l.setXEntrySpace(4f); - // mChart.setDrawLegend(false); +// mChart.setVisibleXRange(50, 10); +// mChart.moveViewToX(20); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 478452d6ad..1004f7b659 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -746,8 +746,8 @@ public void setVisibleXRangeMinimum(float minXRange) { * @param maxXRange */ public void setVisibleXRange(float minXRange, float maxXRange) { - float maxScale = mXAxis.mAxisRange / minXRange; - float minScale = mXAxis.mAxisRange / maxXRange; + float minScale = mXAxis.mAxisRange / minXRange; + float maxScale = mXAxis.mAxisRange / maxXRange; mViewPortHandler.setMinMaxScaleX(minScale, maxScale); } @@ -756,13 +756,37 @@ public void setVisibleXRange(float minXRange, float maxXRange) { * visible at once. * * @param maxYRange the maximum visible range on the y-axis - * @param axis - the axis for which this limit should apply + * @param axis the axis for which this limit should apply */ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { float yScale = getDeltaY(axis) / maxYRange; mViewPortHandler.setMinimumScaleY(yScale); } + /** + * Sets the size of the area (range on the y-axis) that should be minimum visible at once, no further zooming in possible. + * + * @param minYRange + * @param axis the axis for which this limit should apply + */ + public void setVisibleYRangeMinimum(float minYRange, AxisDependency axis) { + float yScale = getDeltaY(axis) / minYRange; + mViewPortHandler.setMaximumScaleY(yScale); + } + + /** + * Limits the maximum and minimum y range that can be visible by pinching and zooming. + * + * @param minYRange + * @param maxYRange + * @param axis + */ + public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency axis) { + float minScale = getDeltaY(axis) / minYRange; + float maxScale = getDeltaY(axis) / maxYRange; + mViewPortHandler.setMinMaxScaleY(minScale, maxScale); + } + /** * Moves the left side of the current viewport to the specified x-position. * This also refreshes the chart by calling invalidate(). diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 0c378df0db..56064ae2aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -7,13 +7,13 @@ import android.util.Log; import com.github.mikephil.charting.components.XAxis.XAxisPosition; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.HorizontalBarHighlighter; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; @@ -207,12 +207,29 @@ public float getHighestVisibleX() { return (float) Math.min(mXAxis.mAxisMaximum, pos.y); } + /** + * ###### VIEWPORT METHODS BELOW THIS ###### + */ + @Override public void setVisibleXRangeMaximum(float maxXRange) { float xScale = mXAxis.mAxisRange / (maxXRange); mViewPortHandler.setMinimumScaleY(xScale); } + @Override + public void setVisibleXRangeMinimum(float minXRange) { + float xScale = mXAxis.mAxisRange / (minXRange); + mViewPortHandler.setMaximumScaleY(xScale); + } + + @Override + public void setVisibleXRange(float minXRange, float maxXRange) { + float minScale = mXAxis.mAxisRange / minXRange; + float maxScale = mXAxis.mAxisRange / maxXRange; + mViewPortHandler.setMinMaxScaleY(minScale, maxScale); + } + @Override public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { float yScale = getDeltaY(axis) / maxYRange; @@ -220,9 +237,15 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { } @Override - public void setVisibleXRange(float minXRange, float maxXRange) { - float maxScale = mXAxis.mAxisRange / minXRange; - float minScale = mXAxis.mAxisRange / maxXRange; - mViewPortHandler.setMinMaxScaleY(minScale, maxScale); + public void setVisibleYRangeMinimum(float minYRange, AxisDependency axis) { + float yScale = getDeltaY(axis) / minYRange; + mViewPortHandler.setMaximumScaleX(yScale); + } + + @Override + public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency axis) { + float minScale = getDeltaY(axis) / minYRange; + float maxScale = getDeltaY(axis) / maxYRange; + mViewPortHandler.setMinMaxScaleX(minScale, maxScale); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index d58f3f09ae..5ee48a8eed 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -517,8 +517,8 @@ public void setMinMaxScaleY(float minScaleY, float maxScaleY) { if (maxScaleY == 0.f) maxScaleY = Float.MAX_VALUE; - mMinScaleX = minScaleY; - mMaxScaleX = maxScaleY; + mMinScaleY = minScaleY; + mMaxScaleY = maxScaleY; limitTransAndScale(mMatrixTouch, mContentRect); } From 3b0be740cd2fa10cc5f550fee72de17783f87722 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jun 2016 10:05:54 +0200 Subject: [PATCH 1038/1390] Add example for half-piechart --- MPChartExample/AndroidManifest.xml | 1 + .../res/layout/activity_piechart_half.xml | 11 ++ .../mpchartexample/HalfPieChartActivity.java | 134 ++++++++++++++++++ .../notimportant/MainActivity.java | 8 ++ .../mikephil/charting/charts/PieChart.java | 21 +++ .../charting/renderer/PieChartRenderer.java | 12 +- 6 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 MPChartExample/res/layout/activity_piechart_half.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index e07a8bdfda..863e2ba381 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -65,6 +65,7 @@ + diff --git a/MPChartExample/res/layout/activity_piechart_half.xml b/MPChartExample/res/layout/activity_piechart_half.xml new file mode 100644 index 0000000000..52c62806b0 --- /dev/null +++ b/MPChartExample/res/layout/activity_piechart_half.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java new file mode 100644 index 0000000000..46967097f0 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -0,0 +1,134 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Point; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.view.Display; +import android.view.WindowManager; +import android.widget.RelativeLayout; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.data.PieEntry; +import com.github.mikephil.charting.formatter.PercentFormatter; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class HalfPieChartActivity extends DemoBase { + + private PieChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_piechart_half); + + mChart = (PieChart) findViewById(R.id.chart1); + mChart.setBackgroundColor(Color.WHITE); + + moveOffScreen(); + + mChart.setUsePercentValues(true); + mChart.setDescription(""); + + mChart.setCenterTextTypeface(mTfLight); + mChart.setCenterText(generateCenterSpannableText()); + + mChart.setDrawHoleEnabled(true); + mChart.setHoleColor(Color.WHITE); + + mChart.setTransparentCircleColor(Color.WHITE); + mChart.setTransparentCircleAlpha(110); + + mChart.setHoleRadius(58f); + mChart.setTransparentCircleRadius(61f); + + mChart.setDrawCenterText(true); + + mChart.setRotationEnabled(false); + mChart.setHighlightPerTapEnabled(true); + + mChart.setMaxAngle(180f); // HALF CHART + mChart.setRotationAngle(180f); + mChart.setCenterTextOffset(0, -20); + + setData(4, 100); + + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.ABOVE_CHART_CENTER); + l.setXEntrySpace(7f); + l.setYEntrySpace(0f); + l.setYOffset(0f); + + // entry label styling + mChart.setEntryLabelColor(Color.WHITE); + mChart.setEntryLabelTypeface(mTfRegular); + mChart.setEntryLabelTextSize(12f); + } + + private void setData(int count, float range) { + + ArrayList values = new ArrayList(); + + for (int i = 0; i < count; i++) { + values.add(new PieEntry((float) ((Math.random() * range) + range / 5), mParties[i % mParties.length])); + } + + PieDataSet dataSet = new PieDataSet(values, "Election Results"); + dataSet.setSliceSpace(3f); + dataSet.setSelectionShift(5f); + + dataSet.setColors(ColorTemplate.MATERIAL_COLORS); + //dataSet.setSelectionShift(0f); + + PieData data = new PieData(dataSet); + data.setValueFormatter(new PercentFormatter()); + data.setValueTextSize(11f); + data.setValueTextColor(Color.WHITE); + data.setValueTypeface(mTfLight); + mChart.setData(data); + + mChart.invalidate(); + } + + private SpannableString generateCenterSpannableText() { + + SpannableString s = new SpannableString("MPAndroidChart\ndeveloped by Philipp Jahoda"); + s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); + s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); + s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); + s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); + s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0); + return s; + } + + private void moveOffScreen() { + + Display display = getWindowManager().getDefaultDisplay(); + int height = display.getHeight(); // deprecated + + int offset = (int)(height * 0.65); /* or whatever */ + + RelativeLayout.LayoutParams rlParams = + (RelativeLayout.LayoutParams)mChart.getLayoutParams(); + rlParams.setMargins(0, 0, 0, -offset); + mChart.setLayoutParams(rlParams); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index a462f4517c..617e43c021 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -25,6 +25,7 @@ import com.xxmassdeveloper.mpchartexample.CubicLineChartActivity; import com.xxmassdeveloper.mpchartexample.DynamicalAddingActivity; import com.xxmassdeveloper.mpchartexample.FilledLineActivity; +import com.xxmassdeveloper.mpchartexample.HalfPieChartActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; @@ -143,6 +144,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Filled LineChart", "This demonstrates how to fill an area between two LineDataSets.")); + objects.add(new ContentItem( + "Half PieChart", + "This demonstrates how to create a 180 degree PieChart.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -282,6 +286,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, FilledLineActivity.class); startActivity(i); break; + case 31: + i = new Intent(this, HalfPieChartActivity.class); + startActivity(i); + break; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 4b2170ff95..232fe48ea8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -72,6 +72,8 @@ public class PieChart extends PieRadarChartBase { */ private CharSequence mCenterText = ""; + private PointF mCenterTextOffset = new PointF(0, 0); + /** * indicates the size of the hole in the center of the piechart, default: * radius / 2 @@ -489,6 +491,25 @@ public void setCenterTextSizePixels(float sizePixels) { ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize(sizePixels); } + /** + * Sets the offset the center text should have from it's original position in dp. Default x = 0, y = 0 + * + * @param x + * @param y + */ + public void setCenterTextOffset(float x, float y) { + mCenterTextOffset = new PointF(Utils.convertDpToPixel(x), Utils.convertDpToPixel(y)); + } + + /** + * Returns the offset on the x- and y-axis the center text has in dp. + * + * @return + */ + public PointF getCenterTextOffset() { + return mCenterTextOffset; + } + /** * Sets the color of the center text of the PieChart. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 2f8b127d20..8eb5311ee9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -656,16 +656,20 @@ protected void drawCenterText(Canvas c) { if (mChart.isDrawCenterTextEnabled() && centerText != null) { PointF center = mChart.getCenterCircleBox(); + PointF offset = mChart.getCenterTextOffset(); + + float x = center.x + offset.x; + float y = center.y + offset.y; float innerRadius = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); RectF holeRect = mRectBuffer[0]; - holeRect.left = center.x - innerRadius; - holeRect.top = center.y - innerRadius; - holeRect.right = center.x + innerRadius; - holeRect.bottom = center.y + innerRadius; + holeRect.left = x - innerRadius; + holeRect.top = y - innerRadius; + holeRect.right = x + innerRadius; + holeRect.bottom = y + innerRadius; RectF boundingRect = mRectBuffer[1]; boundingRect.set(holeRect); From 98e090ca19c73c263d1df46d668e557b579117dc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jun 2016 10:30:16 +0200 Subject: [PATCH 1039/1390] Minor example adjustments --- .../mpchartexample/HalfPieChartActivity.java | 2 +- .../mpchartexample/PieChartActivity.java | 17 +++++++------ .../PiePolylineChartActivity.java | 17 +++++++------ .../mpchartexample/RadarChartActivitry.java | 24 +++++++++---------- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 46967097f0..487da96b7e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -124,7 +124,7 @@ private void moveOffScreen() { Display display = getWindowManager().getDefaultDisplay(); int height = display.getHeight(); // deprecated - int offset = (int)(height * 0.65); /* or whatever */ + int offset = (int)(height * 0.65); /* percent to move */ RelativeLayout.LayoutParams rlParams = (RelativeLayout.LayoutParams)mChart.getLayoutParams(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 9027e5baa9..b77bbd1d18 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -90,7 +90,7 @@ protected void onCreate(Bundle savedInstanceState) { // add a selection listener mChart.setOnChartValueSelectedListener(this); - setData(3, 100); + setData(4, 100); mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); // mChart.spin(2000, 0, 360); @@ -179,7 +179,7 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvX.setText("" + (mSeekBarX.getProgress())); tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); @@ -189,16 +189,15 @@ private void setData(int count, float range) { float mult = range; - ArrayList values = new ArrayList(); + ArrayList entries = new ArrayList(); - // IMPORTANT: In a PieChart, no values (Entry) should have the same - // xIndex (even if from different DataSets), since no values can be - // drawn above each other. - for (int i = 0; i < count + 1; i++) { - values.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < count ; i++) { + entries.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); } - PieDataSet dataSet = new PieDataSet(values, "Election Results"); + PieDataSet dataSet = new PieDataSet(entries, "Election Results"); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index cae2d2de89..6db7f80e29 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { // add a selection listener mChart.setOnChartValueSelectedListener(this); - setData(3, 100); + setData(4, 100); mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); // mChart.spin(2000, 0, 360); @@ -173,7 +173,7 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvX.setText("" + (mSeekBarX.getProgress())); tvY.setText("" + (mSeekBarY.getProgress())); setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); @@ -183,16 +183,15 @@ private void setData(int count, float range) { float mult = range; - ArrayList yVals1 = new ArrayList(); + ArrayList entries = new ArrayList(); - // IMPORTANT: In a PieChart, no values (Entry) should have the same - // xIndex (even if from different DataSets), since no values can be - // drawn above each other. - for (int i = 0; i < count + 1; i++) { - yVals1.add(new PieEntry((float) (Math.random() * mult) + mult / 5, mParties[i % mParties.length])); + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < count; i++) { + entries.add(new PieEntry((float) (Math.random() * mult) + mult / 5, mParties[i % mParties.length])); } - PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); + PieDataSet dataSet = new PieDataSet(entries, "Election Results"); dataSet.setSliceSpace(3f); dataSet.setSelectionShift(5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 3a97d4eed8..97b871a0da 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -77,6 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setValueFormatter(new AxisValueFormatter() { private String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; + @Override public String getFormattedValue(float value, AxisBase axis) { return mActivities[(int) value % mActivities.length]; @@ -210,23 +211,20 @@ public void setData() { float min = 20; int cnt = 5; - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); + ArrayList entries1 = new ArrayList(); + ArrayList entries2 = new ArrayList(); - // IMPORTANT: In a PieChart, no values (Entry) should have the same - // xIndex (even if from different DataSets), since no values can be - // drawn above each other. + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. for (int i = 0; i < cnt; i++) { - float val = (float) (Math.random() * mult) + min; - yVals1.add(new RadarEntry(val)); - } + float val1 = (float) (Math.random() * mult) + min; + entries1.add(new RadarEntry(val1)); - for (int i = 0; i < cnt; i++) { - float val = (float) (Math.random() * mult) + min; - yVals2.add(new RadarEntry(val)); + float val2 = (float) (Math.random() * mult) + min; + entries2.add(new RadarEntry(val2)); } - RadarDataSet set1 = new RadarDataSet(yVals1, "Last Week"); + RadarDataSet set1 = new RadarDataSet(entries1, "Last Week"); set1.setColor(Color.rgb(103, 110, 129)); set1.setFillColor(Color.rgb(103, 110, 129)); set1.setDrawFilled(true); @@ -235,7 +233,7 @@ public void setData() { set1.setDrawHighlightCircleEnabled(true); set1.setDrawHighlightIndicators(false); - RadarDataSet set2 = new RadarDataSet(yVals2, "This Week"); + RadarDataSet set2 = new RadarDataSet(entries2, "This Week"); set2.setColor(Color.rgb(121, 162, 175)); set2.setFillColor(Color.rgb(121, 162, 175)); set2.setDrawFilled(true); From eb76d21fe053e370435b57c49e5793d68f18ba7d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jun 2016 11:54:43 +0200 Subject: [PATCH 1040/1390] Cleanup --- .../HorizontalBarChartActivity.java | 3 -- .../charting/charts/BarLineChartBase.java | 54 +++++++++---------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 411a0de200..64b9be2ea5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -110,9 +110,6 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.BELOW_CHART_LEFT); l.setFormSize(8f); l.setXEntrySpace(4f); - -// mChart.setVisibleXRange(50, 10); -// mChart.moveViewToX(20); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 1004f7b659..4f9c565d18 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -801,23 +801,6 @@ public void moveViewToX(float xValue) { addViewportJob(job); } - /** - * Centers the viewport to the specified y value on the y-axis. - * This also refreshes the chart by calling invalidate(). - * - * @param yValue - * @param axis - which axis should be used as a reference for the y-axis - */ - public void moveViewToY(float yValue, AxisDependency axis) { - - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - - Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f, - getTransformer(axis), this); - - addViewportJob(job); - } - /** * This will move the left side of the current viewport to the specified * x-value on the x-axis, and center the viewport to the specified y value on the y-axis. @@ -829,9 +812,9 @@ public void moveViewToY(float yValue, AxisDependency axis) { */ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new MoveViewJob(mViewPortHandler, xValue, yValue + valsInView / 2f, + Runnable job = new MoveViewJob(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this); addViewportJob(job); @@ -854,9 +837,9 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xValue, yValue + valsInView / 2f, + Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); @@ -865,6 +848,23 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, } } + /** + * Centers the viewport to the specified y value on the y-axis. + * This also refreshes the chart by calling invalidate(). + * + * @param yValue + * @param axis - which axis should be used as a reference for the y-axis + */ + public void centerViewToY(float yValue, AxisDependency axis) { + + float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + + Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f, + getTransformer(axis), this); + + addViewportJob(job); + } + /** * This will move the center of the current viewport to the specified * x and y value. @@ -876,11 +876,11 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, */ public void centerViewTo(float xValue, float yValue, AxisDependency axis) { - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); + float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new MoveViewJob(mViewPortHandler, - xValue - xsInView / 2f, yValue + valsInView / 2f, + xValue - xInView / 2f, yValue + yInView / 2f, getTransformer(axis), this); addViewportJob(job); @@ -902,11 +902,11 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - float xsInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); + float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = new AnimatedMoveViewJob(mViewPortHandler, - xValue - xsInView / 2f, yValue + valsInView / 2f, + xValue - xInView / 2f, yValue + yInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); From f01b90668be552ec5139264cda72c0924a5451e3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jun 2016 21:05:41 +0200 Subject: [PATCH 1041/1390] Work on horizontalbarchart --- .../HorizontalBarChartActivity.java | 2 ++ .../mikephil/charting/charts/Chart.java | 4 +-- .../charting/charts/HorizontalBarChart.java | 5 +++- .../utils/HorizontalViewPortHandler.java | 29 +++++++++++++++++++ 4 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/HorizontalViewPortHandler.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 64b9be2ea5..6b891178bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -110,6 +110,8 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.BELOW_CHART_LEFT); l.setFormSize(8f); l.setXEntrySpace(4f); + + mChart.setVisibleXRange(10, 50); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 69b2478449..ce5d42ea65 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -168,7 +168,7 @@ public abstract class Chart Date: Mon, 27 Jun 2016 12:29:49 +0200 Subject: [PATCH 1042/1390] Changes to custom scatter rendering --- .../HorizontalBarChartActivity.java | 2 - .../mpchartexample/ScatterChartActivity.java | 3 +- .../custom/CustomScatterShapeRenderer.java | 2 - .../charting/charts/CombinedChart.java | 15 ---- .../charting/charts/ScatterChart.java | 74 +------------------ .../charting/data/ScatterDataSet.java | 35 +++++---- .../implementation/RealmScatterDataSet.java | 36 ++++----- .../dataprovider/ScatterDataProvider.java | 17 ----- .../interfaces/datasets/IScatterDataSet.java | 13 ++-- .../OnChartValueSelectedListener.java | 2 +- .../renderer/ScatterChartRenderer.java | 9 +-- .../scatter/ChevronDownShapeRenderer.java | 18 ++--- .../scatter/ChevronUpShapeRenderer.java | 18 ++--- .../renderer/scatter/SquareShapeRenderer.java | 29 ++++---- .../scatter/TriangleShapeRenderer.java | 22 +++--- .../charting/utils/ShapeRendererHandler.java | 57 ++++++++++++++ 16 files changed, 151 insertions(+), 201 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 6b891178bc..64b9be2ea5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -110,8 +110,6 @@ protected void onCreate(Bundle savedInstanceState) { l.setPosition(LegendPosition.BELOW_CHART_LEFT); l.setFormSize(8f); l.setXEntrySpace(4f); - - mChart.setVisibleXRange(10, 50); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 40547c4cd5..b288b162e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -54,7 +54,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (ScatterChart) findViewById(R.id.chart1); mChart.setDescription(""); - mChart.addShapeRenderer(new CustomScatterShapeRenderer(), CustomScatterShapeRenderer.IDENTIFIER); mChart.setOnChartValueSelectedListener(this); @@ -188,7 +187,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set2.setScatterShapeHoleRadius(3f); set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); - set3.setScatterShape(CustomScatterShapeRenderer.IDENTIFIER); + set3.setShapeRenderer(new CustomScatterShapeRenderer()); set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); set1.setScatterShapeSize(8f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java index 15a9ed0b7d..25cd41b1a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java @@ -14,8 +14,6 @@ */ public class CustomScatterShapeRenderer implements ShapeRenderer { - public static final String IDENTIFIER = "single_line"; - @Override public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint renderPaint, float shapeSize) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index d0754132cc..5f578c5d83 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.highlight.CombinedHighlighter; import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; import com.github.mikephil.charting.renderer.CombinedChartRenderer; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; /** * This chart class allows the combination of lines, bars, scatter and candle @@ -23,8 +22,6 @@ */ public class CombinedChart extends BarLineChartBase implements CombinedDataProvider { - private ScatterChart.ShapeRendererHandler mShapeRendererHandler; - /** * if set to true, all values are drawn above their bars, instead of below * their top @@ -71,8 +68,6 @@ public CombinedChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); - mShapeRendererHandler = new ScatterChart.ShapeRendererHandler(); - setHighlighter(new CombinedHighlighter(this, this)); // Old default behaviour @@ -129,16 +124,6 @@ public BubbleData getBubbleData() { return mData.getBubbleData(); } - @Override - public void addShapeRenderer(ShapeRenderer shapeRenderer, String shapeIdentifier) { - mShapeRendererHandler.addShapeRenderer(shapeRenderer, shapeIdentifier); - } - - @Override - public ShapeRenderer getShapeRenderer(String shapeIdentifier) { - return mShapeRendererHandler.getShapeRenderer(shapeIdentifier); - } - @Override public boolean isDrawBarShadowEnabled() { return mDrawBarShadow; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 48f4fe3708..cbaf0694b0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -7,16 +7,6 @@ import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.renderer.ScatterChartRenderer; -import com.github.mikephil.charting.renderer.scatter.ChevronDownShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.ChevronUpShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.CircleShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.CrossShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.TriangleShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.XShapeRenderer; - -import java.util.HashMap; /** * The ScatterChart. Draws dots, triangles, squares and custom shapes into the @@ -27,9 +17,6 @@ */ public class ScatterChart extends BarLineChartBase implements ScatterDataProvider { - protected ShapeRendererHandler mShapeRendererHandler; - - public ScatterChart(Context context) { super(context); } @@ -47,8 +34,6 @@ public ScatterChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); - mShapeRendererHandler = new ShapeRendererHandler(); - mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); } @@ -57,17 +42,8 @@ public ScatterData getScatterData() { return mData; } - @Override - public void addShapeRenderer(ShapeRenderer shapeRenderer, String shapeIdentifier) { - mShapeRendererHandler.addShapeRenderer(shapeRenderer, shapeIdentifier); - } - - @Override - public ShapeRenderer getShapeRenderer(String shapeIdentifier) { - return mShapeRendererHandler.getShapeRenderer(shapeIdentifier); - } - public enum ScatterShape { + SQUARE("SQUARE"), CIRCLE("CIRCLE"), TRIANGLE("TRIANGLE"), CROSS("CROSS"), X("X"), CHEVRON_UP("CHEVRON_UP"), CHEVRON_DOWN("CHEVRON_DOWN"); @@ -86,52 +62,4 @@ public static ScatterShape[] getAllDefaultShapes() { return new ScatterShape[]{SQUARE, CIRCLE, TRIANGLE, CROSS, X, CHEVRON_UP, CHEVRON_DOWN}; } } - - - /** - * Handler class for all different ShapeRenderers. - */ - protected static class ShapeRendererHandler { - - /** - * Dictionary of ShapeRenderer which are responsible for drawing custom shapes. - * Can add to it your custom shapes. - * CustomShapeRenderer Implements ShapeRenderer{} - */ - protected HashMap shapeRendererList; - - public ShapeRendererHandler() { - initShapeRenderers(); - } - - /** - * Adds a new ShapeRenderer and the shapeIdentifier it is responsible for drawing. - * This shapeIdentifier should correspond to a DataSet with the same identifier. - * - * @param shapeRenderer - * @param shapeIdentifier - */ - public void addShapeRenderer(ShapeRenderer shapeRenderer, String shapeIdentifier) { - shapeRendererList.put(shapeIdentifier, shapeRenderer); - } - - public ShapeRenderer getShapeRenderer(String shapeIdentifier) { - return shapeRendererList.get(shapeIdentifier); - } - - /** - * Init default ShapeRenderers. - */ - protected void initShapeRenderers() { - shapeRendererList = new HashMap<>(); - - shapeRendererList.put(ScatterShape.SQUARE.toString(), new SquareShapeRenderer()); - shapeRendererList.put(ScatterShape.CIRCLE.toString(), new CircleShapeRenderer()); - shapeRendererList.put(ScatterShape.TRIANGLE.toString(), new TriangleShapeRenderer()); - shapeRendererList.put(ScatterShape.CROSS.toString(), new CrossShapeRenderer()); - shapeRendererList.put(ScatterShape.X.toString(), new XShapeRenderer()); - shapeRendererList.put(ScatterShape.CHEVRON_UP.toString(), new ChevronUpShapeRenderer()); - shapeRendererList.put(ScatterShape.CHEVRON_DOWN.toString(), new ChevronDownShapeRenderer()); - } - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index 1d07f20cbb..01f2933d3f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -1,9 +1,14 @@ package com.github.mikephil.charting.data; +import android.graphics.drawable.shapes.Shape; + import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.ShapeRendererHandler; import java.util.ArrayList; import java.util.List; @@ -16,10 +21,9 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme private float mShapeSize = 15f; /** - * the type of shape that is set to be drawn where the values are at, - * default ScatterShape.SQUARE + * Renderer responsible for rendering this DataSet, default: square */ - private String mScatterShape = ScatterChart.ScatterShape.SQUARE.toString(); + protected ShapeRenderer mShapeRenderer = new SquareShapeRenderer(); /** * The radius of the hole in the shape (applies to Square, Circle and Triangle) @@ -57,7 +61,7 @@ public DataSet copy() { copied.mValueColors = mValueColors; copied.mColors = mColors; copied.mShapeSize = mShapeSize; - copied.mScatterShape = mScatterShape; + copied.mShapeRenderer = mShapeRenderer; copied.mScatterShapeHoleRadius = mScatterShapeHoleRadius; copied.mScatterShapeHoleColor = mScatterShapeHoleColor; copied.mHighlightLineWidth = mHighlightLineWidth; @@ -82,30 +86,31 @@ public float getScatterShapeSize() { return mShapeSize; } - /** - * Sets the shapeIdentifier that this DataSet should be drawn with. - * Make sure the ScatterChart has a renderer capable of rendering the provided identifier. + * Sets the ScatterShape this DataSet should be drawn with. This will search for an available ShapeRenderer and set this + * renderer for the DataSet. * * @param shape */ public void setScatterShape(ScatterChart.ScatterShape shape) { - mScatterShape = shape.toString(); + + ShapeRendererHandler handler = new ShapeRendererHandler(); + mShapeRenderer = handler.getShapeRenderer(shape); } /** - * Sets the shapeIdentifier that this DataSet should be drawn with. - * Make sure the ScatterChart has a renderer capable of rendering the provided identifier. + * Sets a new ShapeRenderer responsible for drawing this DataSet. + * This can also be used to set a custom ShapeRenderer aside from the default ones. * - * @param shapeIdentifier + * @param shapeRenderer */ - public void setScatterShape(String shapeIdentifier) { - mScatterShape = shapeIdentifier; + public void setShapeRenderer(ShapeRenderer shapeRenderer) { + mShapeRenderer = shapeRenderer; } @Override - public String getScatterShape() { - return mScatterShape; + public ShapeRenderer getShapeRenderer() { + return mShapeRenderer; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 9b1795b5f9..2c05c8d246 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -4,7 +4,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.ShapeRendererHandler; import io.realm.RealmObject; import io.realm.RealmResults; @@ -15,15 +18,14 @@ public class RealmScatterDataSet extends RealmLineScatterCandleRadarDataSet implements IScatterDataSet { /** - * the size the scattershape will have, in density pixels + * Renderer responsible for rendering this DataSet, default: square */ - private float mShapeSize = 10f; + protected ShapeRenderer mShapeRenderer = new SquareShapeRenderer(); /** - * the type of shape that is set to be drawn where the values are at, - * default ScatterShape.SQUARE + * the size the scattershape will have, in density pixels */ - private String mScatterShape = ScatterChart.ScatterShape.SQUARE.toString(); + private float mShapeSize = 10f; /** * The radius of the hole in the shape (applies to Square, Circle and Triangle) @@ -80,31 +82,31 @@ public float getScatterShapeSize() { return mShapeSize; } - /** - * Sets the shape that is drawn on the position where the values are at. + * Sets the ScatterShape this DataSet should be drawn with. This will search for an available ShapeRenderer and set this + * renderer for the DataSet. * * @param shape */ public void setScatterShape(ScatterChart.ScatterShape shape) { - mScatterShape = shape.toString(); - } + ShapeRendererHandler handler = new ShapeRendererHandler(); + mShapeRenderer = handler.getShapeRenderer(shape); + } /** - * Sets the shape that is drawn on the position where the values are at. If - * "CUSTOM" is chosen, you need to call setCustomScatterShape(...) and - * provide a path object that is drawn as the custom scattershape. + * Sets a new ShapeRenderer responsible for drawing this DataSet. + * This can also be used to set a custom ShapeRenderer aside from the default ones. * - * @param shape + * @param shapeRenderer */ - public void setScatterShape(String shape) { - mScatterShape = shape; + public void setShapeRenderer(ShapeRenderer shapeRenderer) { + mShapeRenderer = shapeRenderer; } @Override - public String getScatterShape() { - return mScatterShape; + public ShapeRenderer getShapeRenderer() { + return mShapeRenderer; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java index 2c43ec0491..e89110cdb9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java @@ -6,21 +6,4 @@ public interface ScatterDataProvider extends BarLineScatterCandleBubbleDataProvider { ScatterData getScatterData(); - - /** - * Adds a new ShapeRenderer and the shapeIdentifier it is responsible for drawing. - * This shapeIdentifier should correspond to a DataSet with the same identifier. - * - * @param shapeRenderer - * @param shapeIdentifier - */ - void addShapeRenderer(ShapeRenderer shapeRenderer, String shapeIdentifier); - - /** - * Returns the corresponding ShapeRenderer for the given identifier. - * - * @param shapeIdentifier - * @return - */ - ShapeRenderer getShapeRenderer(String shapeIdentifier); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java index 38742d65fb..ac838a4d2e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; /** * Created by philipp on 21/10/15. @@ -15,23 +16,23 @@ public interface IScatterDataSet extends ILineScatterCandleRadarDataSet { float getScatterShapeSize(); /** - * Returns all the different scattershapes the chart uses + * Returns radius of the hole in the shape * * @return */ - String getScatterShape(); + float getScatterShapeHoleRadius(); /** - * Returns radius of the hole in the shape + * Returns the color for the hole in the shape * * @return */ - float getScatterShapeHoleRadius(); + int getScatterShapeHoleColor(); /** - * Returns the color for the hole in the shape + * Returns the ShapeRenderer responsible for rendering this DataSet. * * @return */ - int getScatterShapeHoleColor(); + ShapeRenderer getShapeRenderer(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index cc73f73802..7f50232b7e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -16,7 +16,7 @@ public interface OnChartValueSelectedListener { * * @param e The selected Entry * @param h The corresponding highlight object that contains information - * about the highlighted position + * about the highlighted position such as dataSetIndex, ... */ void onValueSelected(Entry e, Highlight h); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index f46567ac3f..c9ffbaf3cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -24,8 +24,7 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer { protected ScatterBuffer[] mScatterBuffers; - public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; } @@ -64,15 +63,13 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { final float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); - ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet( - dataSet)]; + ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet(dataSet)]; buffer.setPhases(phaseX, phaseY); buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); - String shape = dataSet.getScatterShape(); - ShapeRenderer renderer = mChart.getShapeRenderer(shape); + ShapeRenderer renderer = dataSet.getShapeRenderer(); if (renderer != null) { renderer.renderShape(c, dataSet, mViewPortHandler, buffer, mRenderPaint, shapeSize); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java index 75fcd0613f..8d4bfb6c85 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java @@ -18,37 +18,37 @@ public class ChevronDownShapeRenderer implements ShapeRenderer { @Override public void renderShape( Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); c.drawLine( buffer.buffer[i], buffer.buffer[i + 1] + (2 * shapeHalf), buffer.buffer[i] + (2 * shapeHalf), buffer.buffer[i + 1], - mRenderPaint); + renderPaint); c.drawLine( buffer.buffer[i], buffer.buffer[i + 1] + (2 * shapeHalf), buffer.buffer[i] - (2 * shapeHalf), buffer.buffer[i + 1], - mRenderPaint); + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java index 3fc52fc210..459e307cf9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java @@ -17,37 +17,37 @@ public class ChevronUpShapeRenderer implements ShapeRenderer { @Override public void renderShape(Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); c.drawLine( buffer.buffer[i], buffer.buffer[i + 1] - (2 * shapeHalf), buffer.buffer[i] + (2 * shapeHalf), buffer.buffer[i + 1], - mRenderPaint); + renderPaint); c.drawLine( buffer.buffer[i], buffer.buffer[i + 1] - (2 * shapeHalf), buffer.buffer[i] - (2 * shapeHalf), buffer.buffer[i + 1], - mRenderPaint); + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java index a728f2bdda..184e77a449 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java @@ -17,9 +17,8 @@ public class SquareShapeRenderer implements ShapeRenderer { @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); @@ -31,44 +30,44 @@ public void renderShape( for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); if (shapeSize > 0.0) { - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(shapeStrokeSize); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(shapeStrokeSize); c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf - shapeStrokeSizeHalf, buffer.buffer[i + 1] - shapeHoleSizeHalf - shapeStrokeSizeHalf, buffer.buffer[i] + shapeHoleSizeHalf + shapeStrokeSizeHalf, buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, - mRenderPaint); + renderPaint); if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - mRenderPaint.setStyle(Paint.Style.FILL); + renderPaint.setStyle(Paint.Style.FILL); - mRenderPaint.setColor(shapeHoleColor); + renderPaint.setColor(shapeHoleColor); c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf, buffer.buffer[i + 1] - shapeHoleSizeHalf, buffer.buffer[i] + shapeHoleSizeHalf, buffer.buffer[i + 1] + shapeHoleSizeHalf, - mRenderPaint); + renderPaint); } } else { - mRenderPaint.setStyle(Paint.Style.FILL); + renderPaint.setStyle(Paint.Style.FILL); c.drawRect(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); + renderPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java index e03b441483..0b5a996bad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java @@ -18,10 +18,8 @@ public class TriangleShapeRenderer implements ShapeRenderer { @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { - + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); @@ -30,21 +28,21 @@ public void renderShape( final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); - mRenderPaint.setStyle(Paint.Style.FILL); + renderPaint.setStyle(Paint.Style.FILL); // create a triangle path Path tri = new Path(); for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); @@ -65,13 +63,13 @@ public void renderShape( tri.close(); - c.drawPath(tri, mRenderPaint); + c.drawPath(tri, renderPaint); tri.reset(); if (shapeSize > 0.0 && shapeHoleColor != ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(shapeHoleColor); + renderPaint.setColor(shapeHoleColor); tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); @@ -81,7 +79,7 @@ public void renderShape( buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); tri.close(); - c.drawPath(tri, mRenderPaint); + c.drawPath(tri, renderPaint); tri.reset(); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java new file mode 100644 index 0000000000..a482c44f7e --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java @@ -0,0 +1,57 @@ +package com.github.mikephil.charting.utils; + +import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.renderer.scatter.ChevronDownShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.ChevronUpShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.CircleShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.CrossShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.TriangleShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.XShapeRenderer; + +import java.util.HashMap; + +/** + * Created by Philipp Jahoda on 27/06/16. + */ +public final class ShapeRendererHandler { + + /** + * Dictionary of ShapeRenderer which are responsible for drawing custom shapes. + * Can add to it your custom shapes. + * CustomShapeRenderer Implements ShapeRenderer{} + */ + protected HashMap shapeRendererList; + + /** + * Constructor + */ + public ShapeRendererHandler() { + initShapeRenderers(); + } + /** + * Returns the corresponding ShapeRenderer for a given ScatterShape. + * + * @param shape + * @return + */ + public ShapeRenderer getShapeRenderer(ScatterChart.ScatterShape shape) { + return shapeRendererList.get(shape.toString()); + } + + /** + * Init default ShapeRenderers. + */ + protected void initShapeRenderers() { + shapeRendererList = new HashMap<>(); + + shapeRendererList.put(ScatterChart.ScatterShape.SQUARE.toString(), new SquareShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.CIRCLE.toString(), new CircleShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.TRIANGLE.toString(), new TriangleShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.CROSS.toString(), new CrossShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.X.toString(), new XShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.CHEVRON_UP.toString(), new ChevronUpShapeRenderer()); + shapeRendererList.put(ScatterChart.ScatterShape.CHEVRON_DOWN.toString(), new ChevronDownShapeRenderer()); + } +} From 1b4e9be07f459c340029e092a68013315030b490 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 27 Jun 2016 12:34:23 +0200 Subject: [PATCH 1043/1390] Code cleanup and documentation --- .../scatter/ChevronDownShapeRenderer.java | 5 ++-- .../scatter/ChevronUpShapeRenderer.java | 4 +-- .../renderer/scatter/CircleShapeRenderer.java | 30 +++++++++---------- .../renderer/scatter/CrossShapeRenderer.java | 21 +++++++------ .../renderer/scatter/ShapeRenderer.java | 10 +++---- .../renderer/scatter/XShapeRenderer.java | 21 +++++++------ .../charting/utils/ShapeRendererHandler.java | 2 ++ 7 files changed, 45 insertions(+), 48 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java index 8d4bfb6c85..d293b28481 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java @@ -16,9 +16,8 @@ public class ChevronDownShapeRenderer implements ShapeRenderer { @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java index 459e307cf9..4eb9db7942 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java @@ -16,8 +16,8 @@ public class ChevronUpShapeRenderer implements ShapeRenderer { @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, - ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java index 4173a97c07..449bd9fe96 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java @@ -15,11 +15,9 @@ */ public class CircleShapeRenderer implements ShapeRenderer { - @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); @@ -31,43 +29,43 @@ public void renderShape( for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); if (shapeSize > 0.0) { - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(shapeStrokeSize); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(shapeStrokeSize); c.drawCircle( buffer.buffer[i], buffer.buffer[i + 1], shapeHoleSizeHalf + shapeStrokeSizeHalf, - mRenderPaint); + renderPaint); if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - mRenderPaint.setStyle(Paint.Style.FILL); + renderPaint.setStyle(Paint.Style.FILL); - mRenderPaint.setColor(shapeHoleColor); + renderPaint.setColor(shapeHoleColor); c.drawCircle( buffer.buffer[i], buffer.buffer[i + 1], shapeHoleSizeHalf, - mRenderPaint); + renderPaint); } } else { - mRenderPaint.setStyle(Paint.Style.FILL); + renderPaint.setStyle(Paint.Style.FILL); c.drawCircle( buffer.buffer[i], buffer.buffer[i + 1], shapeHalf, - mRenderPaint); + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java index a50e6b55c8..45db656677 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java @@ -16,39 +16,38 @@ public class CrossShapeRenderer implements ShapeRenderer { @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); c.drawLine( buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1], buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1], - mRenderPaint); + renderPaint); c.drawLine( buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i], buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java index c3808beb69..3fb23f7718 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java @@ -17,11 +17,11 @@ public interface ShapeRenderer { /** * Renders the provided ScatterDataSet with a shape. * - * @param c - * @param dataSet - * @param viewPortHandler - * @param buffer - * @param renderPaint + * @param c Canvas object for drawing the shape + * @param dataSet the DataSet to be drawn + * @param viewPortHandler contains information about the current state of the view + * @param buffer buffer containing the transformed values of all entries in the DataSet + * @param renderPaint Paint object used for styling and drawing * @param shapeSize */ void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java index 1b4ba25586..2dbac6a974 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java @@ -16,38 +16,37 @@ public class XShapeRenderer implements ShapeRenderer { @Override - public void renderShape( - Canvas c, IScatterDataSet dataSet, - ViewPortHandler mViewPortHandler, ScatterBuffer buffer, Paint mRenderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint + renderPaint, final float shapeSize) { final float shapeHalf = shapeSize / 2f; - mRenderPaint.setStyle(Paint.Style.STROKE); - mRenderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); for (int i = 0; i < buffer.size(); i += 2) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[i])) + if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) break; - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !mViewPortHandler.isInBoundsY(buffer.buffer[i + 1])) + if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) + || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) continue; - mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderPaint.setColor(dataSet.getColor(i / 2)); c.drawLine( buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); + renderPaint); c.drawLine( buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] - shapeHalf, buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf, - mRenderPaint); + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java index a482c44f7e..0cef75f151 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java @@ -14,6 +14,7 @@ /** * Created by Philipp Jahoda on 27/06/16. + * Class allowing to determine the corresponding ShapeRenderer for a given ScatterShape. */ public final class ShapeRendererHandler { @@ -30,6 +31,7 @@ public final class ShapeRendererHandler { public ShapeRendererHandler() { initShapeRenderers(); } + /** * Returns the corresponding ShapeRenderer for a given ScatterShape. * From f54631175ec2621cf00f1f1e81342da3f188912a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 27 Jun 2016 17:20:50 +0200 Subject: [PATCH 1044/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c6b0c386ff..f68b32c8c0 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ If you are having questions or problems, you should: - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) + - Check this: ["how not to contribute"](https://github.com/PhilJay/MPAndroidChart/wiki/How-not-to-contribute) Please do not expect answers to your questions if you have not considered all above mentioned approaches in advance. From a233e389783ed2ec308bd4d0af372617981b0e2e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 27 Jun 2016 23:47:32 +0200 Subject: [PATCH 1045/1390] Remove Realm related classes from project --- MPChartExample/AndroidManifest.xml | 2 +- MPChartExample/build.gradle | 7 +- .../realm/RealmBaseActivity.java | 22 +- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityCandle.java | 2 +- .../RealmDatabaseActivityHorizontalBar.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 4 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../realm/RealmMainActivity.java | 12 + .../realm/RealmWikiExample.java | 2 +- MPChartLib/build.gradle | 6 +- ...ealmBarLineScatterCandleBubbleDataSet.java | 49 --- .../data/realm/base/RealmBaseDataSet.java | 379 ------------------ .../realm/base/RealmLineRadarDataSet.java | 123 ------ .../RealmLineScatterCandleRadarDataSet.java | 123 ------ .../charting/data/realm/base/RealmUtils.java | 30 -- .../realm/implementation/RealmBarDataSet.java | 253 ------------ .../implementation/RealmBubbleDataSet.java | 129 ------ .../implementation/RealmCandleDataSet.java | 316 --------------- .../implementation/RealmLineDataSet.java | 371 ----------------- .../realm/implementation/RealmPieDataSet.java | 201 ---------- .../implementation/RealmRadarDataSet.java | 143 ------- .../implementation/RealmScatterDataSet.java | 139 ------- build.gradle | 2 +- settings.gradle | 2 + 28 files changed, 42 insertions(+), 2287 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 863e2ba381..ab730cd2bd 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -5,7 +5,7 @@ android:versionName="3.0.0" > diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 13914819a6..0cebfdf441 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,10 +1,11 @@ apply plugin: 'com.android.application' +apply plugin: 'realm-android' android { compileSdkVersion 23 buildToolsVersion '23.0.2' defaultConfig { - minSdkVersion 8 + minSdkVersion 16 targetSdkVersion 23 versionCode 52 versionName '3.0.0' @@ -54,8 +55,8 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':MPChartLib') // remove this if you only imported the example project + compile project(':MPChartLib-Realm') compile 'com.android.support:appcompat-v7:23.1.1' - compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) + //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 05aa742864..d4fef69576 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -83,15 +83,11 @@ protected void styleData(ChartData data) { protected void onResume() { super.onResume(); - RealmConfiguration config = new RealmConfiguration.Builder(this) - .name("myrealm.realm") - .build(); + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); - Realm.deleteRealm(config); - - Realm.setDefaultConfiguration(config); - - mRealm = Realm.getInstance(config); + mRealm = Realm.getDefaultInstance(); } @Override @@ -104,7 +100,7 @@ protected void writeToDB(int objectCount) { mRealm.beginTransaction(); - mRealm.clear(RealmDemoData.class); + mRealm.delete(RealmDemoData.class); for (int i = 0; i < objectCount; i++) { @@ -121,7 +117,7 @@ protected void writeToDBStack(int objectCount) { mRealm.beginTransaction(); - mRealm.clear(RealmDemoData.class); + mRealm.delete(RealmDemoData.class); for (int i = 0; i < objectCount; i++) { @@ -140,7 +136,7 @@ protected void writeToDBCandle(int objectCount) { mRealm.beginTransaction(); - mRealm.clear(RealmDemoData.class); + mRealm.delete(RealmDemoData.class); for (int i = 0; i < objectCount; i++) { @@ -168,7 +164,7 @@ protected void writeToDBBubble(int objectCount) { mRealm.beginTransaction(); - mRealm.clear(RealmDemoData.class); + mRealm.delete(RealmDemoData.class); for (int i = 0; i < objectCount; i++) { @@ -186,7 +182,7 @@ protected void writeToDBPie() { mRealm.beginTransaction(); - mRealm.clear(RealmDemoData.class); + mRealm.delete(RealmDemoData.class); float value1 = 15f + (float) (Math.random() * 8f); float value2 = 15f + (float) (Math.random() * 8f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 54e4c55bfd..c87290050d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -47,7 +47,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index c2c2003d2e..d0aa25b864 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -51,7 +51,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 1dd544fcce..a388df3741 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -51,7 +51,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); set.setLabel("Realm CandleDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 2c6081e40c..32d1234fe2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -51,7 +51,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 4e04cf09df..6d2396c22b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -52,7 +52,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); set.setDrawCubic(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 8bcda98356..7b1eb675d9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -51,7 +51,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index fe408bdc00..411f4b6ac9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -53,10 +53,10 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "xValue", "yValue"); // stacked entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index d89545a949..14175ac73a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -51,7 +51,7 @@ protected void onResume() { private void setData() { - RealmResults result = mRealm.allObjects(RealmDemoData.class); + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); set.setLabel("Realm ScatterDataSet"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java index fc1ca357e2..3198320272 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -17,6 +17,9 @@ import java.util.ArrayList; +import io.realm.Realm; +import io.realm.RealmConfiguration; + /** * Created by Philipp Jahoda on 07/12/15. */ @@ -52,6 +55,15 @@ protected void onCreate(Bundle savedInstanceState) { lv.setAdapter(adapter); lv.setOnItemClickListener(this); + + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); + + Realm realm = Realm.getDefaultInstance(); + realm.beginTransaction(); + realm.deleteAll(); + realm.commitTransaction(); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index c31e6b238c..7682bca957 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -81,7 +81,7 @@ protected void onResume() { private void setData() { // LINE-CHART - final RealmResults results = mRealm.allObjects(Score.class); + final RealmResults results = mRealm.where(Score.class).findAll(); AxisValueFormatter formatter = new AxisValueFormatter() { diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index a5b0ca19e3..f8f8455805 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.library' apply plugin: 'maven' -apply plugin: 'com.github.dcendents.android-maven' +//apply plugin: 'com.github.dcendents.android-maven' //apply plugin: 'realm-android' android { @@ -8,7 +8,7 @@ android { buildToolsVersion '23.0.2' // resourcePrefix 'mpcht' defaultConfig { - minSdkVersion 8 + minSdkVersion 9 targetSdkVersion 23 versionCode 3 versionName '3.0.0' @@ -36,7 +36,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' - provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API + //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API testCompile 'junit:junit:4.12' testCompile "org.mockito:mockito-core:1.9.5" } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java deleted file mode 100644 index 55e33227c9..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.github.mikephil.charting.data.realm.base; - -import android.graphics.Color; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 08/11/15. - */ -public abstract class RealmBarLineScatterCandleBubbleDataSet extends RealmBaseDataSet implements IBarLineScatterCandleBubbleDataSet { - - /** default highlight color */ - protected int mHighLightColor = Color.rgb(255, 187, 115); - - public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String yValuesField) { - super(results, yValuesField); - } - - /** - * Constructor that takes the realm RealmResults, sorts & stores them. - * - * @param results - * @param xValuesField - * @param yValuesField - */ - public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String xValuesField, String yValuesField) { - super(results, xValuesField, yValuesField); - } - - /** - * Sets the color that is used for drawing the highlight indicators. Dont - * forget to resolve the color using getResources().getColor(...) or - * Color.rgb(...). - * - * @param color - */ - public void setHighLightColor(int color) { - mHighLightColor = color; - } - - @Override - public int getHighLightColor() { - return mHighLightColor; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java deleted file mode 100644 index 43927dd934..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ /dev/null @@ -1,379 +0,0 @@ -package com.github.mikephil.charting.data.realm.base; - -import com.github.mikephil.charting.data.BaseDataSet; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; - -import java.util.ArrayList; -import java.util.List; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.Sort; - -/** - * Created by Philipp Jahoda on 06/11/15. - */ -public abstract class RealmBaseDataSet extends BaseDataSet { - - /** - * a list of queried realm objects - */ - protected RealmResults results; - - /** - * a cached list of all data read from the database - */ - protected List mValues; - - /** - * maximum y-value in the value array - */ - protected float mYMax = -Float.MAX_VALUE; - - /** - * minimum y-value in the value array - */ - protected float mYMin = Float.MAX_VALUE; - - /** - * maximum x-value in the value array - */ - protected float mXMax = -Float.MAX_VALUE; - - /** - * minimum x-value in the value array - */ - protected float mXMin = Float.MAX_VALUE; - - /** - * fieldname of the column that contains the y-values of this dataset - */ - protected String mYValuesField; - - /** - * fieldname of the column that contains the x-values of this dataset - */ - protected String mXValuesField; - - public RealmBaseDataSet(RealmResults results, String yValuesField) { - this.results = results; - this.mYValuesField = yValuesField; - this.mValues = new ArrayList(); - - if (mXValuesField != null) - this.results.sort(mXValuesField, Sort.ASCENDING); - } - - /** - * Constructor that takes the realm RealmResults, sorts & stores them. - * - * @param results - * @param xValuesField - * @param yValuesField - */ - public RealmBaseDataSet(RealmResults results, String xValuesField, String yValuesField) { - this.results = results; - this.mYValuesField = yValuesField; - this.mXValuesField = xValuesField; - this.mValues = new ArrayList(); - - if (mXValuesField != null) - this.results.sort(mXValuesField, Sort.ASCENDING); - } - - /** - * Rebuilds the DataSet based on the given RealmResults. - */ - public void build(RealmResults results) { - - int xIndex = 0; - for (T object : results) { - mValues.add(buildEntryFromResultObject(object, xIndex++)); - } - } - - public S buildEntryFromResultObject(T realmObject, float x) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - return (S) new Entry(mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), dynamicObject.getFloat(mYValuesField)); - } - - @Override - public float getYMin() { - //return results.min(mYValuesField).floatValue(); - return mYMin; - } - - @Override - public float getYMax() { - //return results.max(mYValuesField).floatValue(); - return mYMax; - } - - @Override - public float getXMin() { - return mXMin; - } - - @Override - public float getXMax() { - return mXMax; - } - - @Override - public int getEntryCount() { - return mValues.size(); - } - - @Override - public void calcMinMax() { - - if (mValues == null || mValues.isEmpty()) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (S e : mValues) { - calcMinMax(e); - } - } - - /** - * Updates the min and max x and y value of this DataSet based on the given Entry. - * - * @param e - */ - protected void calcMinMax(S e) { - - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); - - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); - } - - @Override - public S getEntryForXPos(float xPos) { - //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mXValuesField, xIndex).findFirst()); - //return new Entry(o.getFloat(mYValuesField), o.getInt(mXValuesField)); - return getEntryForXPos(xPos, DataSet.Rounding.CLOSEST); - } - - @Override - public S getEntryForXPos(float xPos, DataSet.Rounding rounding) { - int index = getEntryIndex(xPos, rounding); - if (index > -1) - return mValues.get(index); - return null; - } - - @Override - public List getEntriesForXPos(float xVal) { - - List entries = new ArrayList<>(); - -// { -// T object = results.get(xVal); -// if (object != null) -// entries.add(buildEntryFromResultObject(object, xVal)); -// } else - - if (mXValuesField != null) { - RealmResults foundObjects = results.where().equalTo(mXValuesField, xVal).findAll(); - - for (T e : foundObjects) - entries.add(buildEntryFromResultObject(e, xVal)); - } - - return entries; - } - - @Override - public S getEntryForIndex(int index) { - //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); - //return new Entry(o.getFloat(mYValuesField), o.getInt(mXValuesField)); - return mValues.get(index); - } - - @Override - public int getEntryIndex(float xPos, DataSet.Rounding rounding) { - - int low = 0; - int high = mValues.size() - 1; - int closest = -1; - - while (low <= high) { - int m = (high + low) / 2; - - if (xPos == mValues.get(m).getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xPos) - m--; - - return m; - } - - if (xPos > mValues.get(m).getX()) - low = m + 1; - else - high = m - 1; - - closest = m; - } - - if (closest != -1) { - float closestXPos = mValues.get(closest).getX(); - if (rounding == DataSet.Rounding.UP) { - if (closestXPos < xPos && closest < mValues.size() - 1) { - ++closest; - } - } else if (rounding == DataSet.Rounding.DOWN) { - if (closestXPos > xPos && closest > 0) { - --closest; - } - } - } - - return closest; - } - - @Override - public int getEntryIndex(S e) { - return mValues.indexOf(e); - } - - @Override - public boolean addEntry(S e) { - - if (e == null) - return false; - - float val = e.getY(); - - if (mValues == null) { - mValues = new ArrayList(); - } - - calcMinMax(e); - - // add the entry - mValues.add(e); - return true; - } - - @Override - public boolean removeEntry(S e) { - - if (e == null) - return false; - - if (mValues == null) - return false; - - // remove the entry - boolean removed = mValues.remove(e); - - if (removed) { - calcMinMax(); - } - - return removed; - } - - @Override - public void addEntryOrdered(S e) { - - if (e == null) - return; - - float val = e.getY(); - - if (mValues == null) { - mValues = new ArrayList(); - } - - if (mValues.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } - - if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { - int closestIndex = getEntryIndex(e.getX(), DataSet.Rounding.UP); - mValues.add(closestIndex, e); - return; - } - - mValues.add(e); - } - - /** - * Returns the List of values that has been extracted from the RealmResults - * using the provided fieldnames. - * - * @return - */ - public List getValues() { - return mValues; - } - - @Override - public void clear() { - mValues.clear(); - notifyDataSetChanged(); - } - - public RealmResults getResults() { - return results; - } - - /** - * Returns the fieldname that represents the "y-values" in the realm-data. - * - * @return - */ - public String getYValuesField() { - return mYValuesField; - } - - /** - * Sets the field name that is used for getting the y-values out of the RealmResultSet. - * - * @param yValuesField - */ - public void setYValuesField(String yValuesField) { - this.mYValuesField = yValuesField; - } - - /** - * Returns the fieldname that represents the "x-values" in the realm-data. - * - * @return - */ - public String getXValuesField() { - return mXValuesField; - } - - /** - * Sets the field name that is used for getting the x-values out of the RealmResultSet. - * - * @param xValuesField - */ - public void setXValuesField(String xValuesField) { - this.mXValuesField = xValuesField; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java deleted file mode 100644 index a7b9cb29d8..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.github.mikephil.charting.data.realm.base; - -import android.graphics.Color; -import android.graphics.drawable.Drawable; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.ILineRadarDataSet; -import com.github.mikephil.charting.utils.Utils; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 08/11/15. - */ -public abstract class RealmLineRadarDataSet extends RealmLineScatterCandleRadarDataSet implements ILineRadarDataSet { - - /** the color that is used for filling the line surface */ - private int mFillColor = Color.rgb(140, 234, 255); - - /** the drawable to be used for filling the line surface*/ - protected Drawable mFillDrawable; - - /** transparency used for filling line surface */ - private int mFillAlpha = 85; - - /** the width of the drawn data lines */ - private float mLineWidth = 2.5f; - - /** if true, the data will also be drawn filled */ - private boolean mDrawFilled = false; - - - public RealmLineRadarDataSet(RealmResults results, String yValuesField) { - super(results, yValuesField); - } - - /** - * Constructor that takes the realm RealmResults, sorts & stores them. - * - * @param results - * @param yValuesField - * @param xIndexField - */ - public RealmLineRadarDataSet(RealmResults results, String yValuesField, String xIndexField) { - super(results, yValuesField, xIndexField); - } - - @Override - public int getFillColor() { - return mFillColor; - } - - /** - * sets the color that is used for filling the line surface - * - * @param color - */ - public void setFillColor(int color) { - mFillColor = color; - mFillDrawable = null; - } - - @Override - public Drawable getFillDrawable() { - return mFillDrawable; - } - - /** - * Sets the drawable to be used to fill the area below the line. - * - * @param drawable - */ - public void setFillDrawable(Drawable drawable) { - this.mFillDrawable = drawable; - } - - @Override - public int getFillAlpha() { - return mFillAlpha; - } - - /** - * sets the alpha value (transparency) that is used for filling the line - * surface (0-255), default: 85 - * - * @param alpha - */ - public void setFillAlpha(int alpha) { - mFillAlpha = alpha; - } - - /** - * set the line width of the chart (min = 0.2f, max = 10f); default 1f NOTE: - * thinner line == better performance, thicker line == worse performance - * - * @param width - */ - public void setLineWidth(float width) { - - if (width < 0.2f) - width = 0.2f; - if (width > 10.0f) - width = 10.0f; - mLineWidth = Utils.convertDpToPixel(width); - } - - @Override - public float getLineWidth() { - return mLineWidth; - } - - @Override - public void setDrawFilled(boolean filled) { - mDrawFilled = filled; - } - - @Override - public boolean isDrawFilledEnabled() { - return mDrawFilled; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java deleted file mode 100644 index 1f0c4b064b..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.github.mikephil.charting.data.realm.base; - -import android.graphics.DashPathEffect; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.ILineScatterCandleRadarDataSet; -import com.github.mikephil.charting.utils.Utils; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 08/11/15. - */ -public abstract class RealmLineScatterCandleRadarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements ILineScatterCandleRadarDataSet { - - protected boolean mDrawVerticalHighlightIndicator = true; - protected boolean mDrawHorizontalHighlightIndicator = true; - - /** the width of the highlight indicator lines */ - protected float mHighlightLineWidth = 0.5f; - - /** the path effect for dashed highlight-lines */ - protected DashPathEffect mHighlightDashPathEffect = null; - - public RealmLineScatterCandleRadarDataSet(RealmResults results, String yValuesField) { - super(results, yValuesField); - } - - /** - * Constructor that takes the realm RealmResults, sorts & stores them. - * - * @param results - * @param xValueField - * @param yValuesField - */ - public RealmLineScatterCandleRadarDataSet(RealmResults results, String xValueField, String yValuesField) { - super(results, xValueField, yValuesField); - } - - /** - * Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn. - * @param enabled - */ - public void setDrawHorizontalHighlightIndicator(boolean enabled) { - this.mDrawHorizontalHighlightIndicator = enabled; - } - - /** - * Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn. - * @param enabled - */ - public void setDrawVerticalHighlightIndicator(boolean enabled) { - this.mDrawVerticalHighlightIndicator = enabled; - } - - /** - * Enables / disables both vertical and horizontal highlight-indicators. - * @param enabled - */ - public void setDrawHighlightIndicators(boolean enabled) { - setDrawVerticalHighlightIndicator(enabled); - setDrawHorizontalHighlightIndicator(enabled); - } - - @Override - public boolean isVerticalHighlightIndicatorEnabled() { - return mDrawVerticalHighlightIndicator; - } - - @Override - public boolean isHorizontalHighlightIndicatorEnabled() { - return mDrawHorizontalHighlightIndicator; - } - - /** - * Sets the width of the highlight line in dp. - * @param width - */ - public void setHighlightLineWidth(float width) { - mHighlightLineWidth = Utils.convertDpToPixel(width); - } - - @Override - public float getHighlightLineWidth() { - return mHighlightLineWidth; - } - - /** - * Enables the highlight-line to be drawn in dashed mode, e.g. like this "- - - - - -" - * - * @param lineLength the length of the line pieces - * @param spaceLength the length of space inbetween the line-pieces - * @param phase offset, in degrees (normally, use 0) - */ - public void enableDashedHighlightLine(float lineLength, float spaceLength, float phase) { - mHighlightDashPathEffect = new DashPathEffect(new float[] { - lineLength, spaceLength - }, phase); - } - - /** - * Disables the highlight-line to be drawn in dashed mode. - */ - public void disableDashedHighlightLine() { - mHighlightDashPathEffect = null; - } - - /** - * Returns true if the dashed-line effect is enabled for highlight lines, false if not. - * Default: disabled - * - * @return - */ - public boolean isDashedHighlightLineEnabled() { - return mHighlightDashPathEffect == null ? false : true; - } - - @Override - public DashPathEffect getDashPathEffectHighlight() { - return mHighlightDashPathEffect; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java deleted file mode 100644 index 6e7d0558bc..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/base/RealmUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.github.mikephil.charting.data.realm.base; - -/** - * Created by Philipp Jahoda on 19/12/15. - */ -public final class RealmUtils { - -// /** -// * Transforms the given Realm-ResultSet into a String array by using the provided xValuesField. -// * -// * @param result -// * @param xPositionField -// * @param xLabelField -// * @return -// */ -// public static List toXVals(RealmResults result, String xPositionField, String xLabelField) { -// -// List xVals = new ArrayList(); -// -// for (RealmObject object : result) { -// -// DynamicRealmObject dynamicObject = new DynamicRealmObject(object); -// -// XAxisValue val = new XAxisValue(dynamicObject.getDouble(xPositionField), dynamicObject.getString(xLabelField)); -// xVals.add(val); -// } -// -// return xVals; -// } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java deleted file mode 100644 index 13254d28c7..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ /dev/null @@ -1,253 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import android.graphics.Color; - -import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; - -import io.realm.DynamicRealmObject; -import io.realm.RealmFieldType; -import io.realm.RealmList; -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet - implements IBarDataSet { - - private String mStackValueFieldName; - - /** - * the maximum number of bars that are stacked upon each other, this value - * is calculated from the Entries that are added to the DataSet - */ - private int mStackSize = 1; - - /** - * the color used for drawing the bar shadows - */ - private int mBarShadowColor = Color.rgb(215, 215, 215); - - private float mBarBorderWidth = 0.0f; - - private int mBarBorderColor = Color.BLACK; - - /** - * the alpha value used to draw the highlight indicator bar - */ - private int mHighLightAlpha = 120; - - /** - * array of labels used to describe the different values of the stacked bars - */ - private String[] mStackLabels = new String[]{ - "Stack" - }; - - public RealmBarDataSet(RealmResults results, String xValuesField, String yValuesField) { - super(results, xValuesField, yValuesField); - mHighLightColor = Color.rgb(0, 0, 0); - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for supporting stacked values. - * - * @param results - * @param xValuesField - * @param yValuesField - * @param stackValueFieldName - */ - public RealmBarDataSet(RealmResults results, String xValuesField, String yValuesField, String - stackValueFieldName) { - super(results, xValuesField, yValuesField); - this.mStackValueFieldName = stackValueFieldName; - mHighLightColor = Color.rgb(0, 0, 0); - - build(this.results); - calcMinMax(); - } - - @Override - public void build(RealmResults results) { - - super.build(results); - - calcStackSize(); - } - - @Override - public BarEntry buildEntryFromResultObject(T realmObject, float x) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - if (dynamicObject.getFieldType(mYValuesField) == RealmFieldType.LIST) { - - RealmList list = dynamicObject.getList(mYValuesField); - float[] values = new float[list.size()]; - - int i = 0; - for (DynamicRealmObject o : list) { - values[i] = o.getFloat(mStackValueFieldName); - i++; - } - - return new BarEntry( - mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), values); - } else { - float value = dynamicObject.getFloat(mYValuesField); - return new BarEntry(mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), value); - } - } - - @Override - public void calcMinMax() { - - if (mValues == null || mValues.isEmpty()) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (BarEntry e : mValues) { - - if (e != null && !Float.isNaN(e.getY())) { - - if (e.getYVals() == null) { - - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); - } else { - - if (-e.getNegativeSum() < mYMin) - mYMin = -e.getNegativeSum(); - - if (e.getPositiveSum() > mYMax) - mYMax = e.getPositiveSum(); - } - - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); - } - } - } - - private void calcStackSize() { - - for (int i = 0; i < mValues.size(); i++) { - - float[] vals = mValues.get(i).getYVals(); - - if (vals != null && vals.length > mStackSize) - mStackSize = vals.length; - } - } - - @Override - public int getStackSize() { - return mStackSize; - } - - @Override - public boolean isStacked() { - return mStackSize > 1 ? true : false; - } - - /** - * Sets the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum value. Don't for get to - * use getResources().getColor(...) to set this. Or Color.rgb(...). - * - * @param color - */ - public void setBarShadowColor(int color) { - mBarShadowColor = color; - } - - @Override - public int getBarShadowColor() { - return mBarShadowColor; - } - - /** - * Sets the width used for drawing borders around the bars. - * If borderWidth == 0, no border will be drawn. - * - * @return - */ - public void setBarBorderWidth(float width) { - mBarBorderWidth = width; - } - - /** - * Returns the width used for drawing borders around the bars. - * If borderWidth == 0, no border will be drawn. - * - * @return - */ - @Override - public float getBarBorderWidth() { - return mBarBorderWidth; - } - - /** - * Sets the color drawing borders around the bars. - * - * @return - */ - public void setBarBorderColor(int color) { - mBarBorderColor = color; - } - - /** - * Returns the color drawing borders around the bars. - * - * @return - */ - @Override - public int getBarBorderColor() { - return mBarBorderColor; - } - - /** - * Set the alpha value (transparency) that is used for drawing the highlight - * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) - * - * @param alpha - */ - public void setHighLightAlpha(int alpha) { - mHighLightAlpha = alpha; - } - - @Override - public int getHighLightAlpha() { - return mHighLightAlpha; - } - - /** - * Sets labels for different values of bar-stacks, in case there are one. - * - * @param labels - */ - public void setStackLabels(String[] labels) { - mStackLabels = labels; - } - - @Override - public String[] getStackLabels() { - return mStackLabels; - } - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java deleted file mode 100644 index 27c4b308e0..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.utils.Utils; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmBubbleDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBubbleDataSet { - - private String mSizeField; - - protected float mMaxSize; - protected boolean mNormalizeSize = true; - - private float mHighlightCircleWidth = 2.5f; - - /** - * Constructor for creating a CandleDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param sizeField the name of the field in your data object that represents the bubble size - */ - public RealmBubbleDataSet(RealmResults result, String yValuesField, String sizeField) { - super(result, yValuesField); - this.mSizeField = sizeField; - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for creating a CandleDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - * @param xIndexField the name of the field in your data object that represents the x-index - * @param sizeField the name of the field in your data object that represents the bubble size - */ - public RealmBubbleDataSet(RealmResults result, String yValuesField, String xIndexField, String sizeField) { - super(result, yValuesField, xIndexField); - this.mSizeField = sizeField; - - build(this.results); - calcMinMax(); - } - - @Override - public BubbleEntry buildEntryFromResultObject(T realmObject, float x) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - return new BubbleEntry( - mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), - dynamicObject.getFloat(mYValuesField), - dynamicObject.getFloat(mSizeField)); - } - - @Override - public void calcMinMax() { - - if (mValues == null || mValues.isEmpty()) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (BubbleEntry e : mValues) { - - calcMinMax(e); - - final float size = e.getSize(); - - if (size > mMaxSize) { - mMaxSize = size; - } - } - } - - @Override - public float getMaxSize() { - return mMaxSize; - } - - @Override - public boolean isNormalizeSizeEnabled() { - return mNormalizeSize; - } - - public void setNormalizeSizeEnabled(boolean normalizeSize) { - mNormalizeSize = normalizeSize; - } - - @Override - public void setHighlightCircleWidth(float width) { - mHighlightCircleWidth = Utils.convertDpToPixel(width); - } - - @Override - public float getHighlightCircleWidth() { - return mHighlightCircleWidth; - } - - /** - * Sets the database fieldname for the bubble size. - * - * @param sizeField - */ - public void setSizeField(String sizeField) { - this.mSizeField = sizeField; - } - - /** - * Returns the database fieldname that stores bubble size. - * - * @return - */ - public String getSizeField() { - return mSizeField; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java deleted file mode 100644 index 1c08290656..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ /dev/null @@ -1,316 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import android.graphics.Paint; - -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Utils; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmCandleDataSet extends RealmLineScatterCandleRadarDataSet - implements ICandleDataSet { - - private String mHighField; - private String mLowField; - private String mOpenField; - private String mCloseField; - - /** - * the width of the shadow of the candle - */ - private float mShadowWidth = 3f; - - /** - * should the candle bars show? - * when false, only "ticks" will show - *

    - * - default: true - */ - private boolean mShowCandleBar = true; - - /** - * the space between the candle entries, default 0.1f (10%) - */ - private float mBarSpace = 0.1f; - - /** - * use candle color for the shadow - */ - private boolean mShadowColorSameAsCandle = false; - - /** - * paint style when open < close - * increasing candlesticks are traditionally hollow - */ - protected Paint.Style mIncreasingPaintStyle = Paint.Style.STROKE; - - /** - * paint style when open > close - * descreasing candlesticks are traditionally filled - */ - protected Paint.Style mDecreasingPaintStyle = Paint.Style.FILL; - - /** - * color for open == close - */ - protected int mNeutralColor = ColorTemplate.COLOR_NONE; - - /** - * color for open < close - */ - protected int mIncreasingColor = ColorTemplate.COLOR_NONE; - - /** - * color for open > close - */ - protected int mDecreasingColor = ColorTemplate.COLOR_NONE; - - /** - * shadow line color, set -1 for backward compatibility and uses default - * color - */ - protected int mShadowColor = ColorTemplate.COLOR_NONE; - - /** - * Constructor for creating a LineDataSet with realm data. - * - * @param result the queried results from the realm database - * @param highField the name of the field in your data object that represents the "high" value - * @param lowField the name of the field in your data object that represents the "low" value - * @param openField the name of the field in your data object that represents the "open" value - * @param closeField the name of the field in your data object that represents the "close" value - */ - public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String - closeField) { - super(result, null); - this.mHighField = highField; - this.mLowField = lowField; - this.mOpenField = openField; - this.mCloseField = closeField; - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for creating a LineDataSet with realm data. - * - * @param result the queried results from the realm database - * @param xValueField the name of the field in your data object that represents the "x" value - * @param highField the name of the field in your data object that represents the "high" value - * @param lowField the name of the field in your data object that represents the "low" value - * @param openField the name of the field in your data object that represents the "open" value - * @param closeField the name of the field in your data object that represents the "close" value - */ - public RealmCandleDataSet(RealmResults result, String xValueField, String highField, String lowField, String openField, String - closeField) { - super(result, xValueField, null); - this.mHighField = highField; - this.mLowField = lowField; - this.mOpenField = openField; - this.mCloseField = closeField; - - build(this.results); - calcMinMax(); - } - - @Override - public CandleEntry buildEntryFromResultObject(T realmObject, float x) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - return new CandleEntry( - mXValuesField == null ? x : dynamicObject.getFloat(mXValuesField), - dynamicObject.getFloat(mHighField), - dynamicObject.getFloat(mLowField), - dynamicObject.getFloat(mOpenField), - dynamicObject.getFloat(mCloseField)); - } - - @Override - public void calcMinMax() { - - if (mValues == null || mValues.isEmpty()) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (CandleEntry e : mValues) { - - if (e.getLow() < mYMin) - mYMin = e.getLow(); - - if (e.getHigh() > mYMax) - mYMax = e.getHigh(); - - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); - } - } - - /** - * Sets the space that is left out on the left and right side of each - * candle, default 0.1f (10%), max 0.45f, min 0f - * - * @param space - */ - public void setBarSpace(float space) { - - if (space < 0f) - space = 0f; - if (space > 0.45f) - space = 0.45f; - - mBarSpace = space; - } - - @Override - public float getBarSpace() { - return mBarSpace; - } - - /** - * Sets the width of the candle-shadow-line in pixels. Default 3f. - * - * @param width - */ - public void setShadowWidth(float width) { - mShadowWidth = Utils.convertDpToPixel(width); - } - - @Override - public float getShadowWidth() { - return mShadowWidth; - } - - /** - * Sets whether the candle bars should show? - * - * @param showCandleBar - */ - public void setShowCandleBar(boolean showCandleBar) { - mShowCandleBar = showCandleBar; - } - - @Override - public boolean getShowCandleBar() { - return mShowCandleBar; - } - - - /** BELOW THIS COLOR HANDLING */ - - /** - * Sets the one and ONLY color that should be used for this DataSet when - * open == close. - * - * @param color - */ - public void setNeutralColor(int color) { - mNeutralColor = color; - } - - @Override - public int getNeutralColor() { - return mNeutralColor; - } - - /** - * Sets the one and ONLY color that should be used for this DataSet when - * open < close. - * - * @param color - */ - public void setIncreasingColor(int color) { - mIncreasingColor = color; - } - - @Override - public int getIncreasingColor() { - return mIncreasingColor; - } - - /** - * Sets the one and ONLY color that should be used for this DataSet when - * open > close. - * - * @param color - */ - public void setDecreasingColor(int color) { - mDecreasingColor = color; - } - - @Override - public int getDecreasingColor() { - return mDecreasingColor; - } - - @Override - public Paint.Style getIncreasingPaintStyle() { - return mIncreasingPaintStyle; - } - - /** - * Sets paint style when open < close - * - * @param paintStyle - */ - public void setIncreasingPaintStyle(Paint.Style paintStyle) { - this.mIncreasingPaintStyle = paintStyle; - } - - @Override - public Paint.Style getDecreasingPaintStyle() { - return mDecreasingPaintStyle; - } - - /** - * Sets paint style when open > close - * - * @param decreasingPaintStyle - */ - public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { - this.mDecreasingPaintStyle = decreasingPaintStyle; - } - - @Override - public int getShadowColor() { - return mShadowColor; - } - - /** - * Sets shadow color for all entries - * - * @param shadowColor - */ - public void setShadowColor(int shadowColor) { - this.mShadowColor = shadowColor; - } - - @Override - public boolean getShadowColorSameAsCandle() { - return mShadowColorSameAsCandle; - } - - /** - * Sets shadow color to be the same color as the candle color - * - * @param shadowColorSameAsCandle - */ - public void setShadowColorSameAsCandle(boolean shadowColorSameAsCandle) { - this.mShadowColorSameAsCandle = shadowColorSameAsCandle; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java deleted file mode 100644 index 5c4a58d15a..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ /dev/null @@ -1,371 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.DashPathEffect; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; -import com.github.mikephil.charting.formatter.DefaultFillFormatter; -import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Utils; - -import java.util.ArrayList; -import java.util.List; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { - - /** Drawing mode for this line dataset **/ - private LineDataSet.Mode mMode = LineDataSet.Mode.LINEAR; - - /** - * List representing all colors that are used for the circles - */ - private List mCircleColors = null; - - /** - * the color of the inner circles - */ - private int mCircleColorHole = Color.WHITE; - - /** - * the radius of the circle-shaped value indicators - */ - private float mCircleRadius = 8f; - - /** the hole radius of the circle-shaped value indicators */ - private float mCircleHoleRadius = 4f; - - /** - * sets the intensity of the cubic lines - */ - private float mCubicIntensity = 0.2f; - - /** - * the path effect of this DataSet that makes dashed lines possible - */ - private DashPathEffect mDashPathEffect = null; - - /** - * formatter for customizing the position of the fill-line - */ - private FillFormatter mFillFormatter = new DefaultFillFormatter(); - - /** - * if true, drawing circles is enabled - */ - private boolean mDrawCircles = true; - - private boolean mDrawCircleHole = true; - - /** - * Constructor for creating a LineDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - */ - public RealmLineDataSet(RealmResults result, String yValuesField) { - super(result, yValuesField); - mCircleColors = new ArrayList(); - - // default color - mCircleColors.add(Color.rgb(140, 234, 255)); - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for creating a LineDataSet with realm data. - * - * @param result the queried results from the realm database - * @param xValuesField the name of the field in your data object that represents the x-axis value - * @param yValuesField the name of the field in your data object that represents the y-axis value - */ - public RealmLineDataSet(RealmResults result, String xValuesField, String yValuesField) { - super(result, xValuesField, yValuesField); - mCircleColors = new ArrayList(); - - // default color - mCircleColors.add(Color.rgb(140, 234, 255)); - - build(this.results); - calcMinMax(); - } - - /** - * Returns the drawing mode for this line dataset - * - * @return - */ - @Override - public LineDataSet.Mode getMode() { - return mMode; - } - - /** - * Returns the drawing mode for this line dataset - * - * @return - */ - public void setMode(LineDataSet.Mode mode) { - mMode = mode; - } - - /** - * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, - * Min = 0.05f = low cubic effect, Default: 0.2f - * - * @param intensity - */ - public void setCubicIntensity(float intensity) { - - if (intensity > 1f) - intensity = 1f; - if (intensity < 0.05f) - intensity = 0.05f; - - mCubicIntensity = intensity; - } - - @Override - public float getCubicIntensity() { - return mCubicIntensity; - } - - /** - * sets the size (radius) of the circle shpaed value indicators, default - * size = 4f - * - * @param size - */ - public void setCircleSize(float size) { - mCircleRadius = Utils.convertDpToPixel(size); - } - - @Override - public float getCircleRadius() { - return mCircleRadius; - } - - /** - * sets the hole radius of the drawn circles. - * Default radius = 2f - * - * @param holeRadius - */ - public void setCircleHoleRadius(float holeRadius) { - mCircleHoleRadius = Utils.convertDpToPixel(holeRadius); - } - - @Override - public float getCircleHoleRadius() { - return mCircleHoleRadius; - } - - /** - * Enables the line to be drawn in dashed mode, e.g. like this - * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. - * Keep in mind that hardware acceleration boosts performance. - * - * @param lineLength the length of the line pieces - * @param spaceLength the length of space in between the pieces - * @param phase offset, in degrees (normally, use 0) - */ - public void enableDashedLine(float lineLength, float spaceLength, float phase) { - mDashPathEffect = new DashPathEffect(new float[]{ - lineLength, spaceLength - }, phase); - } - - /** - * Disables the line to be drawn in dashed mode. - */ - public void disableDashedLine() { - mDashPathEffect = null; - } - - @Override - public boolean isDashedLineEnabled() { - return mDashPathEffect == null ? false : true; - } - - @Override - public DashPathEffect getDashPathEffect() { - return mDashPathEffect; - } - - /** - * set this to true to enable the drawing of circle indicators for this - * DataSet, default true - * - * @param enabled - */ - public void setDrawCircles(boolean enabled) { - this.mDrawCircles = enabled; - } - - @Override - public boolean isDrawCirclesEnabled() { - return mDrawCircles; - } - - @Deprecated - public void setDrawCubic(boolean enabled) { - mMode = enabled ? LineDataSet.Mode.CUBIC_BEZIER : LineDataSet.Mode.LINEAR; - } - - @Deprecated - @Override - public boolean isDrawCubicEnabled() { - return mMode == LineDataSet.Mode.CUBIC_BEZIER; - } - - @Deprecated - public void setDrawStepped(boolean enabled) { - mMode = enabled ? LineDataSet.Mode.STEPPED : LineDataSet.Mode.LINEAR; - } - - @Deprecated - @Override - public boolean isDrawSteppedEnabled() { - return mMode == LineDataSet.Mode.STEPPED; - } - - /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ - - /** - * returns all colors specified for the circles - * - * @return - */ - public List getCircleColors() { - return mCircleColors; - } - - @Override - public int getCircleColor(int index) { - return mCircleColors.get(index % mCircleColors.size()); - } - - /** - * Sets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. Make sure that the colors - * are already prepared (by calling getResources().getColor(...)) before - * adding them to the DataSet. - * - * @param colors - */ - public void setCircleColors(List colors) { - mCircleColors = colors; - } - - /** - * Sets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. Make sure that the colors - * are already prepared (by calling getResources().getColor(...)) before - * adding them to the DataSet. - * - * @param colors - */ - public void setCircleColors(int[] colors) { - this.mCircleColors = ColorTemplate.createColors(colors); - } - - /** - * ets the colors that should be used for the circles of this DataSet. - * Colors are reused as soon as the number of Entries the DataSet represents - * is higher than the size of the colors array. You can use - * "new String[] { R.color.red, R.color.green, ... }" to provide colors for - * this method. Internally, the colors are resolved using - * getResources().getColor(...) - * - * @param colors - */ - public void setCircleColors(int[] colors, Context c) { - - List clrs = new ArrayList(); - - for (int color : colors) { - clrs.add(c.getResources().getColor(color)); - } - - mCircleColors = clrs; - } - - /** - * Sets the one and ONLY color that should be used for this DataSet. - * Internally, this recreates the colors array and adds the specified color. - * - * @param color - */ - public void setCircleColor(int color) { - resetCircleColors(); - mCircleColors.add(color); - } - - /** - * resets the circle-colors array and creates a new one - */ - public void resetCircleColors() { - mCircleColors = new ArrayList(); - } - - /** - * Sets the color of the inner circle of the line-circles. - * - * @param color - */ - public void setCircleColorHole(int color) { - mCircleColorHole = color; - } - - @Override - public int getCircleHoleColor() { - return mCircleColorHole; - } - - /** - * Set this to true to allow drawing a hole in each data circle. - * - * @param enabled - */ - public void setDrawCircleHole(boolean enabled) { - mDrawCircleHole = enabled; - } - - @Override - public boolean isDrawCircleHoleEnabled() { - return mDrawCircleHole; - } - - /** - * Sets a custom FillFormatter to the chart that handles the position of the - * filled-line for each DataSet. Set this to null to use the default logic. - * - * @param formatter - */ - public void setFillFormatter(FillFormatter formatter) { - - if (formatter == null) - mFillFormatter = new DefaultFillFormatter(); - else - mFillFormatter = formatter; - } - - @Override - public FillFormatter getFillFormatter() { - return mFillFormatter; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java deleted file mode 100644 index 985fc1d143..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ /dev/null @@ -1,201 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.data.realm.base.RealmBaseDataSet; -import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; -import com.github.mikephil.charting.utils.Utils; - -import io.realm.DynamicRealmObject; -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { - - /** - * the space in pixels between the chart-slices, default 0f - */ - private float mSliceSpace = 0f; - - /** - * indicates the selection distance of a pie slice - */ - private float mShift = 18f; - - private PieDataSet.ValuePosition mXValuePosition = PieDataSet.ValuePosition.INSIDE_SLICE; - private PieDataSet.ValuePosition mYValuePosition = PieDataSet.ValuePosition.INSIDE_SLICE; - private int mValueLineColor = 0xff000000; - private float mValueLineWidth = 1.0f; - private float mValueLinePart1OffsetPercentage = 75.f; - private float mValueLinePart1Length = 0.3f; - private float mValueLinePart2Length = 0.4f; - private boolean mValueLineVariableLength = true; - - private String mLabelField; - - /** - * Constructor for creating a PieDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - */ - public RealmPieDataSet(RealmResults result, String yValuesField) { - super(result, yValuesField); - - build(this.results); - calcMinMax(); - } - - public RealmPieDataSet(RealmResults result, String yValuesField, String labelField) { - super(result, yValuesField); - this.mLabelField = labelField; - build(this.results); - calcMinMax(); - } - - @Override - public PieEntry buildEntryFromResultObject(T realmObject, float x) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - - if(mLabelField == null) { - return new PieEntry(dynamicObject.getFloat(mYValuesField)); - } else { - return new PieEntry(dynamicObject.getFloat(mYValuesField), dynamicObject.getString(mLabelField)); - } - } - - /** - * Sets the space that is left out between the piechart-slices in dp. - * Default: 0 --> no space, maximum 20f - * - * @param spaceDp - */ - public void setSliceSpace(float spaceDp) { - - if (spaceDp > 20) - spaceDp = 20f; - if (spaceDp < 0) - spaceDp = 0f; - - mSliceSpace = Utils.convertDpToPixel(spaceDp); - } - - @Override - public float getSliceSpace() { - return mSliceSpace; - } - - /** - * sets the distance the highlighted piechart-slice of this DataSet is - * "shifted" away from the center of the chart, default 12f - * - * @param shift - */ - public void setSelectionShift(float shift) { - mShift = Utils.convertDpToPixel(shift); - } - - @Override - public float getSelectionShift() { - return mShift; - } - - @Override - public PieDataSet.ValuePosition getXValuePosition() - { - return mXValuePosition; - } - - public void setXValuePosition(PieDataSet.ValuePosition xValuePosition) - { - this.mXValuePosition = xValuePosition; - } - - @Override - public PieDataSet.ValuePosition getYValuePosition() - { - return mYValuePosition; - } - - public void setYValuePosition(PieDataSet.ValuePosition yValuePosition) - { - this.mYValuePosition = yValuePosition; - } - - /** When valuePosition is OutsideSlice, indicates line color */ - @Override - public int getValueLineColor() - { - return mValueLineColor; - } - - public void setValueLineColor(int valueLineColor) - { - this.mValueLineColor = valueLineColor; - } - - /** When valuePosition is OutsideSlice, indicates line width */ - @Override - public float getValueLineWidth() - { - return mValueLineWidth; - } - - public void setValueLineWidth(float valueLineWidth) - { - this.mValueLineWidth = valueLineWidth; - } - - /** When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size */ - @Override - public float getValueLinePart1OffsetPercentage() - { - return mValueLinePart1OffsetPercentage; - } - - public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) - { - this.mValueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage; - } - - /** When valuePosition is OutsideSlice, indicates length of first half of the line */ - @Override - public float getValueLinePart1Length() - { - return mValueLinePart1Length; - } - - public void setValueLinePart1Length(float valueLinePart1Length) - { - this.mValueLinePart1Length = valueLinePart1Length; - } - - /** When valuePosition is OutsideSlice, indicates length of second half of the line */ - @Override - public float getValueLinePart2Length() - { - return mValueLinePart2Length; - } - - public void setValueLinePart2Length(float valueLinePart2Length) - { - this.mValueLinePart2Length = valueLinePart2Length; - } - - /** When valuePosition is OutsideSlice, this allows variable line length */ - @Override - public boolean isValueLineVariableLength() - { - return mValueLineVariableLength; - } - - public void setValueLineVariableLength(boolean valueLineVariableLength) - { - this.mValueLineVariableLength = valueLineVariableLength; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java deleted file mode 100644 index dac3a59c40..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ /dev/null @@ -1,143 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import android.graphics.Color; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { - - /// flag indicating whether highlight circle should be drawn or not - protected boolean mDrawHighlightCircleEnabled = false; - - protected int mHighlightCircleFillColor = Color.WHITE; - - /// The stroke color for highlight circle. - /// If Utils.COLOR_NONE, the color of the dataset is taken. - protected int mHighlightCircleStrokeColor = ColorTemplate.COLOR_NONE; - - protected int mHighlightCircleStrokeAlpha = (int)(0.3 * 255); - protected float mHighlightCircleInnerRadius = 3.0f; - protected float mHighlightCircleOuterRadius = 4.0f; - protected float mHighlightCircleStrokeWidth = 2.0f; - - /** - * Constructor for creating a RadarDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - */ - public RealmRadarDataSet(RealmResults result, String yValuesField) { - super(result, yValuesField); - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for creating a RadarDataSet with realm data. - * - * @param result the queried results from the realm database - * @param xValuesField the name of the field in your data object that represents the x value - * @param yValuesField the name of the field in your data object that represents the y value - */ - public RealmRadarDataSet(RealmResults result, String xValuesField, String yValuesField) { - super(result, xValuesField, yValuesField); - - build(this.results); - calcMinMax(); - } - - /// Returns true if highlight circle should be drawn, false if not - @Override - public boolean isDrawHighlightCircleEnabled() - { - return mDrawHighlightCircleEnabled; - } - - /// Sets whether highlight circle should be drawn or not - @Override - public void setDrawHighlightCircleEnabled(boolean enabled) - { - mDrawHighlightCircleEnabled = enabled; - } - - @Override - public int getHighlightCircleFillColor() - { - return mHighlightCircleFillColor; - } - - public void setHighlightCircleFillColor(int color) - { - mHighlightCircleFillColor = color; - } - - /// Returns the stroke color for highlight circle. - /// If Utils.COLOR_NONE, the color of the dataset is taken. - @Override - public int getHighlightCircleStrokeColor() - { - return mHighlightCircleStrokeColor; - } - - /// Sets the stroke color for highlight circle. - /// Set to Utils.COLOR_NONE in order to use the color of the dataset; - public void setHighlightCircleStrokeColor(int color) - { - mHighlightCircleStrokeColor = color; - } - - @Override - public int getHighlightCircleStrokeAlpha() - { - return mHighlightCircleStrokeAlpha; - } - - public void setHighlightCircleStrokeAlpha(int alpha) - { - mHighlightCircleStrokeAlpha = alpha; - } - - @Override - public float getHighlightCircleInnerRadius() - { - return mHighlightCircleInnerRadius; - } - - public void setHighlightCircleInnerRadius(float radius) - { - mHighlightCircleInnerRadius = radius; - } - - @Override - public float getHighlightCircleOuterRadius() - { - return mHighlightCircleOuterRadius; - } - - public void setHighlightCircleOuterRadius(float radius) - { - mHighlightCircleOuterRadius = radius; - } - - @Override - public float getHighlightCircleStrokeWidth() - { - return mHighlightCircleStrokeWidth; - } - - public void setHighlightCircleStrokeWidth(float strokeWidth) - { - mHighlightCircleStrokeWidth = strokeWidth; - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java deleted file mode 100644 index 2c05c8d246..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ /dev/null @@ -1,139 +0,0 @@ -package com.github.mikephil.charting.data.realm.implementation; - -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.ShapeRendererHandler; - -import io.realm.RealmObject; -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 07/11/15. - */ -public class RealmScatterDataSet extends RealmLineScatterCandleRadarDataSet implements IScatterDataSet { - - /** - * Renderer responsible for rendering this DataSet, default: square - */ - protected ShapeRenderer mShapeRenderer = new SquareShapeRenderer(); - - /** - * the size the scattershape will have, in density pixels - */ - private float mShapeSize = 10f; - - /** - * The radius of the hole in the shape (applies to Square, Circle and Triangle) - * - default: 0.0 - */ - private float mScatterShapeHoleRadius = 0f; - - /** - * Color for the hole in the shape. - * Setting to `ColorTemplate.COLOR_NONE` will behave as transparent. - * - default: ColorTemplate.COLOR_NONE - */ - private int mScatterShapeHoleColor = ColorTemplate.COLOR_NONE; - - /** - * Constructor for creating a ScatterDataSet with realm data. - * - * @param result the queried results from the realm database - * @param yValuesField the name of the field in your data object that represents the y-value - */ - public RealmScatterDataSet(RealmResults result, String yValuesField) { - super(result, yValuesField); - - build(this.results); - calcMinMax(); - } - - /** - * Constructor for creating a ScatterDataSet with realm data. - * - * @param result the queried results from the realm database - * @param xValuesField the name of the field in your data object that represents the x value - * @param yValuesField the name of the field in your data object that represents the y value - */ - public RealmScatterDataSet(RealmResults result, String xValuesField, String yValuesField) { - super(result, xValuesField, yValuesField); - - build(this.results); - calcMinMax(); - } - - /** - * Sets the size in density pixels the drawn scattershape will have. This - * only applies for non custom shapes. - * - * @param size - */ - public void setScatterShapeSize(float size) { - mShapeSize = size; - } - - @Override - public float getScatterShapeSize() { - return mShapeSize; - } - - /** - * Sets the ScatterShape this DataSet should be drawn with. This will search for an available ShapeRenderer and set this - * renderer for the DataSet. - * - * @param shape - */ - public void setScatterShape(ScatterChart.ScatterShape shape) { - - ShapeRendererHandler handler = new ShapeRendererHandler(); - mShapeRenderer = handler.getShapeRenderer(shape); - } - - /** - * Sets a new ShapeRenderer responsible for drawing this DataSet. - * This can also be used to set a custom ShapeRenderer aside from the default ones. - * - * @param shapeRenderer - */ - public void setShapeRenderer(ShapeRenderer shapeRenderer) { - mShapeRenderer = shapeRenderer; - } - - @Override - public ShapeRenderer getShapeRenderer() { - return mShapeRenderer; - } - - /** - * Sets the radius of the hole in the shape - * - * @param holeRadius - */ - public void setScatterShapeHoleRadius(float holeRadius) { - mScatterShapeHoleRadius = holeRadius; - } - - @Override - public float getScatterShapeHoleRadius() { - return mScatterShapeHoleRadius; - } - - /** - * Sets the color for the hole in the shape - * - * @param holeColor - */ - public void setScatterShapeHoleColor(int holeColor) { - mScatterShapeHoleColor = holeColor; - } - - @Override - public int getScatterShapeHoleColor() { - return mScatterShapeHoleColor; - } -} diff --git a/build.gradle b/build.gradle index f2bd5c0e14..0eb3f4e7bf 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - //classpath "io.realm:realm-gradle-plugin:1.0.0" + classpath "io.realm:realm-gradle-plugin:1.0.1" classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } diff --git a/settings.gradle b/settings.gradle index 6d793f8d10..484b8b3ecd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,7 @@ include 'MPChartLib' //include 'MPAndroidChart-Realm' include 'MPChartExample' +include ':MPChartLib-Realm' +project(':MPChartLib-Realm').projectDir = new File('../MPAndroidChart-Realm/MPChartLib-Realm') From cb6dabbdec6543b28a77d59c4f7c0bbcd9382153 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 12:42:05 -0700 Subject: [PATCH 1046/1390] Eliminate allocs - ObjectPool and Tests (#1892) --- .../mikephil/charting/utils/ObjectPool.java | 218 ++++++++++++++++ .../charting/test/ObjectPoolTest.java | 240 ++++++++++++++++++ 2 files changed, 458 insertions(+) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/ObjectPool.java create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ObjectPool.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ObjectPool.java new file mode 100644 index 0000000000..d1d54371f9 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ObjectPool.java @@ -0,0 +1,218 @@ +package com.github.mikephil.charting.utils; + +import java.util.List; + +/** + * An object pool for recycling of object instances extending Poolable. + * + * + * Cost/Benefit : + * Cost - The pool can only contain objects extending Poolable. + * Benefit - The pool can very quickly determine if an object is elligable for storage without iteration. + * Benefit - The pool can also know if an instance of Poolable is already stored in a different pool instance. + * Benefit - The pool can grow as needed, if it is empty + * Cost - However, refilling the pool when it is empty might incur a time cost with sufficiently large capacity. Set the replenishPercentage to a lower number if this is a concern. + * + * Created by Tony Patino on 6/20/16. + */ +public class ObjectPool { + + private static int ids = 0; + + private int poolId; + private int desiredCapacity; + private Object[] objects; + private int objectsPointer; + private T modelObject; + private float replenishPercentage; + + + /** + * Returns the id of the given pool instance. + * + * @return an integer ID belonging to this pool instance. + */ + public int getPoolId(){ + return poolId; + } + + /** + * Returns an ObjectPool instance, of a given starting capacity, that recycles instances of a given Poolable object. + * + * @param withCapacity A positive integer value. + * @param object An instance of the object that the pool should recycle. + * @return + */ + public static synchronized ObjectPool create(int withCapacity, Poolable object){ + ObjectPool result = new ObjectPool(withCapacity, object); + result.poolId = ids; + ids++; + + return result; + } + + private ObjectPool(int withCapacity, T object){ + if(withCapacity <= 0){ + throw new IllegalArgumentException("Object Pool must be instantiated with a capacity greater than 0!"); + } + this.desiredCapacity = withCapacity; + this.objects = new Object[this.desiredCapacity]; + this.objectsPointer = 0; + this.modelObject = object; + this.replenishPercentage = 1.0f; + this.refillPool(); + } + + /** + * Set the percentage of the pool to replenish on empty. Valid values are between + * 0.00f and 1.00f + * + * @param percentage a value between 0 and 1, representing the percentage of the pool to replenish. + */ + public void setReplenishPercentage(float percentage){ + float p = percentage; + if(p > 1){ + p = 1; + } + else if(p < 0f){ + p = 0f; + } + this.replenishPercentage = p; + } + + public float getReplenishPercentage(){ + return replenishPercentage; + } + + private void refillPool(){ + this.refillPool(this.replenishPercentage); + } + + private void refillPool(float percentage){ + int portionOfCapacity = (int) (desiredCapacity * percentage); + + if(portionOfCapacity < 1){ + portionOfCapacity = 1; + }else if(portionOfCapacity > desiredCapacity){ + portionOfCapacity = desiredCapacity; + } + + for(int i = 0 ; i < portionOfCapacity ; i++){ + this.objects[i] = modelObject.instantiate(); + } + objectsPointer = portionOfCapacity - 1; + } + + /** + * Returns an instance of Poolable. If get() is called with an empty pool, the pool will be + * replenished. If the pool capacity is sufficiently large, this could come at a performance + * cost. + * + * @return An instance of Poolable object T + */ + public synchronized T get(){ + + if(this.objectsPointer == -1 && this.replenishPercentage > 0.0f){ + this.refillPool(); + } + + T result = (T)objects[this.objectsPointer]; + result.currentOwnerId = Poolable.NO_OWNER; + this.objectsPointer--; + + return result; + } + + /** + * Recycle an instance of Poolable that this pool is capable of generating. + * The T instance passed must not already exist inside this or any other ObjectPool instance. + * + * @param object An object of type T to recycle + */ + public synchronized void recycle(T object){ + if(object.currentOwnerId != Poolable.NO_OWNER){ + if(object.currentOwnerId == this.poolId){ + throw new IllegalArgumentException("The object passed is already stored in this pool!"); + }else { + throw new IllegalArgumentException("The object to recycle already belongs to poolId " + object.currentOwnerId + ". Object cannot belong to two different pool instances simultaneously!"); + } + } + + this.objectsPointer++; + if(this.objectsPointer >= objects.length){ + this.resizePool(); + } + + object.currentOwnerId = this.poolId; + objects[this.objectsPointer] = object; + + } + + /** + * Recycle a List of Poolables that this pool is capable of generating. + * The T instances passed must not already exist inside this or any other ObjectPool instance. + * + * @param objects A list of objects of type T to recycle + */ + public synchronized void recycle(List objects){ + while(objects.size() + this.objectsPointer + 1 > this.desiredCapacity){ + this.resizePool(); + } + final int objectsListSize = objects.size(); + + // Not relying on recycle(T object) because this is more performant. + for(int i = 0 ; i < objectsListSize ; i++){ + T object = objects.get(i); + if(object.currentOwnerId != Poolable.NO_OWNER){ + if(object.currentOwnerId == this.poolId){ + throw new IllegalArgumentException("The object passed is already stored in this pool!"); + }else { + throw new IllegalArgumentException("The object to recycle already belongs to poolId " + object.currentOwnerId + ". Object cannot belong to two different pool instances simultaneously!"); + } + } + object.currentOwnerId = this.poolId; + this.objects[this.objectsPointer + 1 + i] = object; + } + this.objectsPointer += objectsListSize; + } + + private void resizePool() { + final int oldCapacity = this.desiredCapacity; + this.desiredCapacity *= 2; + Object[] temp = new Object[this.desiredCapacity]; + for(int i = 0 ; i < oldCapacity ; i++){ + temp[i] = this.objects[i]; + } + this.objects = temp; + } + + /** + * Returns the capacity of this object pool. Note : The pool will automatically resize + * to contain additional objects if the user tries to add more objects than the pool's + * capacity allows, but this comes at a performance cost. + * + * @return The capacity of the pool. + */ + public int getPoolCapacity(){ + return this.objects.length; + } + + /** + * Returns the number of objects remaining in the pool, for diagnostic purposes. + * + * @return The number of objects remaining in the pool. + */ + public int getPoolCount(){ + return this.objectsPointer + 1; + } + + + public static abstract class Poolable{ + + public static int NO_OWNER = -1; + int currentOwnerId = NO_OWNER; + + protected abstract Poolable instantiate(); + + } +} \ No newline at end of file diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java new file mode 100644 index 0000000000..e1dbe81be9 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java @@ -0,0 +1,240 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.utils.ObjectPool; + +import junit.framework.Assert; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by otheruser on 6/28/16. + */ +public class ObjectPoolTest { + + static class TestPoolable extends ObjectPool.Poolable{ + + private static ObjectPool pool; + + static { + pool = ObjectPool.create(4, new TestPoolable(0,0)); + } + + public int foo = 0; + public int bar = 0; + + protected ObjectPool.Poolable instantiate(){ + return new TestPoolable(0,0); + } + + private TestPoolable(int foo, int bar){ + this.foo = foo; + this.bar = bar; + } + + public static TestPoolable getInstance(int foo, int bar){ + TestPoolable result = pool.get(); + result.foo = foo; + result.bar = bar; + return result; + } + + public static void recycleInstance(TestPoolable instance){ + pool.recycle(instance); + } + + public static void recycleInstances(List instances){ + pool.recycle(instances); + } + + public static ObjectPool getPool(){ + return pool; + } + + } + + @Test + public void testObjectPool(){ + + int poolCapacity = TestPoolable.getPool().getPoolCapacity(); + int poolCount = TestPoolable.getPool().getPoolCount(); + TestPoolable testPoolable; + ArrayList testPoolables = new ArrayList<>(); + + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(4, poolCount); + + testPoolable = TestPoolable.getInstance(6,7); + Assert.assertEquals(6, testPoolable.foo); + Assert.assertEquals(7, testPoolable.bar); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(3, poolCount); + + TestPoolable.recycleInstance(testPoolable); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(4, poolCount); + + + testPoolable = TestPoolable.getInstance(20,30); + Assert.assertEquals(20, testPoolable.foo); + Assert.assertEquals(30, testPoolable.bar); + + TestPoolable.recycleInstance(testPoolable); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(4, poolCount); + + testPoolables.add(TestPoolable.getInstance(12,24)); + testPoolables.add(TestPoolable.getInstance(1,2)); + testPoolables.add(TestPoolable.getInstance(3,5)); + testPoolables.add(TestPoolable.getInstance(6,8)); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(0, poolCount); + + + TestPoolable.recycleInstances(testPoolables); + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(4, poolCount); + + testPoolables.clear(); + + + testPoolables.add(TestPoolable.getInstance(12,24)); + testPoolables.add(TestPoolable.getInstance(1,2)); + testPoolables.add(TestPoolable.getInstance(3,5)); + testPoolables.add(TestPoolable.getInstance(6,8)); + testPoolables.add(TestPoolable.getInstance(8,9)); + Assert.assertEquals(12, testPoolables.get(0).foo); + Assert.assertEquals(24, testPoolables.get(0).bar); + Assert.assertEquals(1, testPoolables.get(1).foo); + Assert.assertEquals(2, testPoolables.get(1).bar); + Assert.assertEquals(3, testPoolables.get(2).foo); + Assert.assertEquals(5, testPoolables.get(2).bar); + Assert.assertEquals(6, testPoolables.get(3).foo); + Assert.assertEquals(8, testPoolables.get(3).bar); + Assert.assertEquals(8, testPoolables.get(4).foo); + Assert.assertEquals(9, testPoolables.get(4).bar); + + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(4, poolCapacity); + Assert.assertEquals(3, poolCount); + + TestPoolable.recycleInstances(testPoolables); + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(8, poolCapacity); + Assert.assertEquals(8, poolCount); + + testPoolables.clear(); + + + testPoolables.add(TestPoolable.getInstance(0,0)); + testPoolables.add(TestPoolable.getInstance(6,8)); + testPoolables.add(TestPoolable.getInstance(1,2)); + testPoolables.add(TestPoolable.getInstance(3,5)); + testPoolables.add(TestPoolable.getInstance(8,9)); + testPoolables.add(TestPoolable.getInstance(12,24)); + testPoolables.add(TestPoolable.getInstance(12,24)); + testPoolables.add(TestPoolable.getInstance(12,24)); + testPoolables.add(TestPoolable.getInstance(6,8)); + testPoolables.add(TestPoolable.getInstance(6,8)); + Assert.assertEquals(0, testPoolables.get(0).foo); + Assert.assertEquals(0, testPoolables.get(0).bar); + Assert.assertEquals(6, testPoolables.get(1).foo); + Assert.assertEquals(8, testPoolables.get(1).bar); + Assert.assertEquals(1, testPoolables.get(2).foo); + Assert.assertEquals(2, testPoolables.get(2).bar); + Assert.assertEquals(3, testPoolables.get(3).foo); + Assert.assertEquals(5, testPoolables.get(3).bar); + Assert.assertEquals(8, testPoolables.get(4).foo); + Assert.assertEquals(9, testPoolables.get(4).bar); + Assert.assertEquals(12, testPoolables.get(5).foo); + Assert.assertEquals(24, testPoolables.get(5).bar); + Assert.assertEquals(12, testPoolables.get(6).foo); + Assert.assertEquals(24, testPoolables.get(6).bar); + Assert.assertEquals(12, testPoolables.get(7).foo); + Assert.assertEquals(24, testPoolables.get(7).bar); + Assert.assertEquals(6, testPoolables.get(8).foo); + Assert.assertEquals(8, testPoolables.get(8).bar); + Assert.assertEquals(6, testPoolables.get(9).foo); + Assert.assertEquals(8, testPoolables.get(9).bar); + + for(TestPoolable p : testPoolables){ + TestPoolable.recycleInstance(p); + } + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(16, poolCapacity); + Assert.assertEquals(16, poolCount); + + testPoolable = TestPoolable.getInstance(9001,9001); + Assert.assertEquals(9001, testPoolable.foo); + Assert.assertEquals(9001, testPoolable.bar); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(16, poolCapacity); + Assert.assertEquals(15, poolCount); + + + TestPoolable.recycleInstance(testPoolable); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(16, poolCapacity); + Assert.assertEquals(16, poolCount); + + Exception e = null; + try{ + // expect an exception. + TestPoolable.recycleInstance(testPoolable); + }catch (Exception ex){ + e = ex; + }finally{ + Assert.assertEquals(e.getMessage(), true, e != null); + } + + testPoolables.clear(); + + TestPoolable.getPool().setReplenishPercentage(0.5f); + int i = 16; + while(i > 0){ + testPoolables.add(TestPoolable.getInstance(0,0)); + i--; + } + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(16, poolCapacity); + Assert.assertEquals(0, poolCount); + + testPoolables.add(TestPoolable.getInstance(0,0)); + + poolCapacity = TestPoolable.getPool().getPoolCapacity(); + poolCount = TestPoolable.getPool().getPoolCount(); + Assert.assertEquals(16, poolCapacity); + Assert.assertEquals(7, poolCount); + + + } + +} From d299546ebdfc0cb4d186f0d7ee9fb7564fa45fa7 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 13:54:10 -0700 Subject: [PATCH 1047/1390] Eliminate allocs - FSize pooling (#1892) Replace all "new FSize()" instantiations with FSize.getInstance() / FSize.recycleInstance() pairs. Smarter FSize array usage inside Legend. --- .../mikephil/charting/components/Legend.java | 58 ++++++++++++------ .../charting/renderer/XAxisRenderer.java | 2 + .../XAxisRendererHorizontalBarChart.java | 2 + .../github/mikephil/charting/utils/FSize.java | 41 +++++++++++-- .../github/mikephil/charting/utils/Utils.java | 61 ++++++++++++++++++- 5 files changed, 138 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 77f1710f27..756cc40a13 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -649,7 +649,7 @@ public float getFormToTextSpace() { * sets the space between the form and the actual label/text, converts to dp * internally * - * @param mFormToTextSpace + * @param space */ public void setFormToTextSpace(float space) { this.mFormToTextSpace = Utils.convertDpToPixel(space); @@ -708,7 +708,7 @@ public float getFullWidth(Paint labelpaint) { /** * Calculates the full height of the drawn legend. * - * @param mLegendLabelPaint + * @param labelpaint * @return */ public float getFullHeight(Paint labelpaint) { @@ -815,6 +815,7 @@ public FSize[] getCalculatedLineSizes() { * * @param labelpaint */ + ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { mTextWidthMax = getMaximumEntryWidth(labelpaint); @@ -882,9 +883,22 @@ else if (wasStacked) { float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent; // Prepare arrays for calculated layout - ArrayList calculatedLabelSizes = new ArrayList(labelCount); - ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); - ArrayList calculatedLineSizes = new ArrayList(); + + //ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); + + if(mCalculatedLabelSizes.length != labelCount){ + mCalculatedLabelSizes = new FSize[labelCount]; + } + int calculatedLabelSizesIndex = 0; + + if(mCalculatedLabelBreakPoints.length != labelCount){ + mCalculatedLabelBreakPoints = new Boolean[labelCount]; + } + int calculatedLabelBreakIndex = 0; + + ArrayList calculatedLineSizes = calculatedLineSizesForCalculateDimensions; + FSize.recycleInstances(calculatedLineSizes); + calculatedLineSizes.clear(); // Start calculating layout float maxLineWidth = 0.f; @@ -896,7 +910,8 @@ else if (wasStacked) { boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; - calculatedLabelBreakPoints.add(false); + mCalculatedLabelBreakPoints[calculatedLabelBreakIndex] = false; + calculatedLabelBreakIndex++; if (stackedStartIndex == -1) { // we are not stacking, so required width is for this label @@ -910,14 +925,25 @@ else if (wasStacked) { // grouped forms have null labels if (mLabels[i] != null) { - - calculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i])); + if(mCalculatedLabelSizes[calculatedLabelSizesIndex] == null){ + mCalculatedLabelSizes[calculatedLabelSizesIndex] = Utils.calcTextSize(labelpaint, mLabels[i]); + }else{ + Utils.calcTextSize(labelpaint, mLabels[i], mCalculatedLabelSizes[calculatedLabelSizesIndex]); + } + FSize labelSize = mCalculatedLabelSizes[calculatedLabelSizesIndex]; + calculatedLabelSizesIndex++; requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f; - requiredWidth += calculatedLabelSizes.get(i).width; + requiredWidth += labelSize.width; } else { - calculatedLabelSizes.add(new FSize(0.f, 0.f)); + if(mCalculatedLabelSizes[calculatedLabelSizesIndex] == null){ + mCalculatedLabelSizes[calculatedLabelSizesIndex] = FSize.getInstance(0.f, 0.f); + }else{ + mCalculatedLabelSizes[calculatedLabelSizesIndex].width = 0.f; + mCalculatedLabelSizes[calculatedLabelSizesIndex].height = 0.f; + } + calculatedLabelSizesIndex++; requiredWidth += drawingForm ? mFormSize : 0.f; if (stackedStartIndex == -1) { @@ -942,19 +968,19 @@ else if (wasStacked) { else { // It doesn't fit, we need to wrap a line // Add current line size to array - calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); + calculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); maxLineWidth = Math.max(maxLineWidth, currentLineWidth); // Start a new line - calculatedLabelBreakPoints.set( + mCalculatedLabelBreakPoints[ stackedStartIndex > -1 ? stackedStartIndex - : i, true); + : i] = true; currentLineWidth = requiredWidth; } if (i == labelCount - 1) { // Add last line size to array - calculatedLineSizes.add(new FSize(currentLineWidth, labelLineHeight)); + calculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); maxLineWidth = Math.max(maxLineWidth, currentLineWidth); } } @@ -962,10 +988,6 @@ else if (wasStacked) { stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; } - mCalculatedLabelSizes = calculatedLabelSizes.toArray( - new FSize[calculatedLabelSizes.size()]); - mCalculatedLabelBreakPoints = calculatedLabelBreakPoints - .toArray(new Boolean[calculatedLabelBreakPoints.size()]); mCalculatedLineSizes = calculatedLineSizes .toArray(new FSize[calculatedLineSizes.size()]); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 83c7e9cc3b..e86b38569b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -92,6 +92,8 @@ protected void computeSize() { mXAxis.mLabelHeight = Math.round(labelHeight); mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); + + FSize.recycleInstance(labelRotatedSize); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 526e4ef7fd..b9a43a7454 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -76,6 +76,8 @@ protected void computeSize() { mXAxis.mLabelHeight = Math.round(labelHeight); mXAxis.mLabelRotatedWidth = (int)(labelRotatedSize.width + mXAxis.getXOffset() * 3.5f); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); + + FSize.recycleInstance(labelRotatedSize); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index fa7ff4489a..bdd96775c2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -1,16 +1,46 @@ package com.github.mikephil.charting.utils; +import java.util.List; + /** - * Immutable class for describing width and height dimensions in some arbitrary + * Class for describing width and height dimensions in some arbitrary * unit. Replacement for the android.Util.SizeF which is available only on API >= 21. */ -public final class FSize { +public final class FSize extends ObjectPool.Poolable{ + + // TODO : Encapsulate width & height + + public float width; + public float height; + + private static ObjectPool pool; - public final float width; - public final float height; + static { + pool = ObjectPool.create(500, new FSize(0,0)); + } + + + protected ObjectPool.Poolable instantiate(){ + return new FSize(0,0); + } - public FSize(final float width, final float height) { + public static FSize getInstance(final float width, final float height){ + FSize result = pool.get(); + result.width = width; + result.height = height; + return result; + } + + public static void recycleInstance(FSize instance){ + pool.recycle(instance); + } + + public static void recycleInstances(List instances){ + pool.recycle(instances); + } + + private FSize(final float width, final float height) { this.width = width; this.height = height; } @@ -42,4 +72,5 @@ public String toString() { public int hashCode() { return Float.floatToIntBits(width) ^ Float.floatToIntBits(height); } + } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 3da44084b6..223ea6d8b3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -173,20 +173,39 @@ public static float getLineSpacing(Paint paint) { } /** + * Returns a recyclable FSize instance. * calculates the approximate size of a text, depending on a demo text * avoid repeated calls (e.g. inside drawing methods) * * @param paint * @param demoText - * @return + * @return A Recyclable FSize instance */ public static FSize calcTextSize(Paint paint, String demoText) { + FSize result = FSize.getInstance(0,0); + calcTextSize(paint, demoText, result); + return result; + } + + /** + * calculates the approximate size of a text, depending on a demo text + * avoid repeated calls (e.g. inside drawing methods) + * + * @param paint + * @param demoText + * @param outputFSize An output variable, modified by the function. + */ + public static void calcTextSize(Paint paint, String demoText, FSize outputFSize) { + Rect r = new Rect(); paint.getTextBounds(demoText, 0, demoText.length(), r); - return new FSize(r.width(), r.height()); + outputFSize.width = r.width(); + outputFSize.height = r.height(); + } + /** * Math.pow(...) is very expensive, so avoid calling it and create it * yourself. @@ -494,6 +513,7 @@ public static void drawXAxisValue(Canvas c, String text, float x, float y, translateX -= rotatedSize.width * (anchor.x - 0.5f); translateY -= rotatedSize.height * (anchor.y - 0.5f); + FSize.recycleInstance(rotatedSize); } c.save(); @@ -564,6 +584,7 @@ public static void drawMultilineText(Canvas c, StaticLayout textLayout, translateX -= rotatedSize.width * (anchor.x - 0.5f); translateY -= rotatedSize.height * (anchor.y - 0.5f); + FSize.recycleInstance(rotatedSize); } c.save(); @@ -611,26 +632,60 @@ public static void drawMultilineText(Canvas c, String text, drawMultilineText(c, textLayout, x, y, paint, anchor, angleDegrees); } + /** + * Returns a recyclable FSize instance. + * Represents size of a rotated rectangle by degrees. + * + * @param rectangleSize + * @param degrees + * @return A Recyclable FSize instance + */ public static FSize getSizeOfRotatedRectangleByDegrees(FSize rectangleSize, float degrees) { final float radians = degrees * FDEG2RAD; return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); } + /** + * Returns a recyclable FSize instance. + * Represents size of a rotated rectangle by radians. + * + * @param rectangleSize + * @param radians + * @return A Recyclable FSize instance + */ public static FSize getSizeOfRotatedRectangleByRadians(FSize rectangleSize, float radians) { return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); } + /** + * Returns a recyclable FSize instance. + * Represents size of a rotated rectangle by degrees. + * + * @param rectangleWidth + * @param rectangleHeight + * @param degrees + * @return A Recyclable FSize instance + */ public static FSize getSizeOfRotatedRectangleByDegrees(float rectangleWidth, float rectangleHeight, float degrees) { final float radians = degrees * FDEG2RAD; return getSizeOfRotatedRectangleByRadians(rectangleWidth, rectangleHeight, radians); } + /** + * Returns a recyclable FSize instance. + * Represents size of a rotated rectangle by radians. + * + * @param rectangleWidth + * @param rectangleHeight + * @param radians + * @return A Recyclable FSize instance + */ public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, float rectangleHeight, float radians) { - return new FSize( + return FSize.getInstance( Math.abs(rectangleWidth * (float) Math.cos(radians)) + Math.abs(rectangleHeight * (float) Math.sin(radians)), Math.abs(rectangleWidth * (float) Math.sin(radians)) + Math.abs(rectangleHeight * From fcf26aa6adc44fff8d1700835690d400469ee84c Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 14:26:27 -0700 Subject: [PATCH 1048/1390] Eliminate allocs - PointD pooling (#1892) Replace all "new PointD()" instantiations with PointD.getInstance() / PointD.recycleInstance() pairs. Helper methods overloaded to include void return / output PointD variable signatures. Old methods remain as convenience, with notations that they return recyclable instances. --- .../charting/charts/BarLineChartBase.java | 37 +++++++++++++++---- .../charting/charts/HorizontalBarChart.java | 16 +++++--- .../charting/highlight/BarHighlighter.java | 4 ++ .../charting/highlight/ChartHighlighter.java | 7 +++- .../highlight/HorizontalBarHighlighter.java | 2 + .../charting/renderer/AxisRenderer.java | 3 ++ .../charting/renderer/XAxisRenderer.java | 3 ++ .../XAxisRendererHorizontalBarChart.java | 3 ++ .../YAxisRendererHorizontalBarChart.java | 3 ++ .../github/mikephil/charting/utils/FSize.java | 2 +- .../mikephil/charting/utils/PointD.java | 33 +++++++++++++++-- .../mikephil/charting/utils/Transformer.java | 19 +++++++--- 12 files changed, 107 insertions(+), 25 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 4f9c565d18..2672bf3006 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -682,6 +682,8 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); + PointD.recycleInstance(origin); + } else { Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); } @@ -843,6 +845,8 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); + + PointD.recycleInstance(bounds); } else { Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); } @@ -910,6 +914,8 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); + + PointD.recycleInstance(bounds); } else { Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); } @@ -1183,6 +1189,7 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { } /** + * Returns a recyclable PointD instance * Returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to @@ -1193,10 +1200,17 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { * @return */ public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { - return getTransformer(axis).getValuesByTouchPoint(x, y); + PointD result = PointD.getInstance(0,0); + getValuesByTouchPoint(x,y,axis,result); + return result; + } + + public void getValuesByTouchPoint(float x, float y, AxisDependency axis, PointD outputPoint){ + getTransformer(axis).getValuesByTouchPoint(x, y, outputPoint); } /** + * Returns a recyclable PointD instance * Transforms the given chart values into pixels. This is the opposite * method to getValuesByTouchPoint(...). * @@ -1208,6 +1222,7 @@ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { return getTransformer(axis).getPixelsForValues(x, y); } + PointD pointForGetYValueByTouchPoint = PointD.getInstance(0,0); /** * Returns y value at the given touch position (must not necessarily be * a value contained in one of the datasets) @@ -1217,7 +1232,9 @@ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { * @return */ public float getYValueByTouchPoint(float x, float y, AxisDependency axis) { - return (float) getValuesByTouchPoint(x, y, axis).y; + getValuesByTouchPoint(x, y, axis, pointForGetYValueByTouchPoint); + float result = (float) pointForGetYValueByTouchPoint.y; + return result; } /** @@ -1250,6 +1267,7 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float return null; } + protected PointD posForGetLowestVisibleX = PointD.getInstance(0,0); /** * Returns the lowest x-index (value on the x-axis) that is still visible on * the chart. @@ -1258,11 +1276,13 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float */ @Override public float getLowestVisibleX() { - PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom()); - return (float) Math.max(mXAxis.mAxisMinimum, pos.x); + getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), posForGetLowestVisibleX); + float result = (float) Math.max(mXAxis.mAxisMinimum, posForGetLowestVisibleX.x); + return result; } + protected PointD posForGetHighestVisibleX = PointD.getInstance(0,0); /** * Returns the highest x-index (value on the x-axis) that is still visible * on the chart. @@ -1271,9 +1291,10 @@ public float getLowestVisibleX() { */ @Override public float getHighestVisibleX() { - PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentRight(), - mViewPortHandler.contentBottom()); - return (float) Math.min(mXAxis.mAxisMaximum, pos.x); + getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), posForGetHighestVisibleX); + float result = (float) Math.min(mXAxis.mAxisMaximum, posForGetHighestVisibleX.x); + return result; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index cae72464cc..1c04c22331 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -196,18 +196,22 @@ public Highlight getHighlightByTouchPoint(float x, float y) { return getHighlighter().getHighlight(y, x); // switch x and y } + protected PointD posForGetLowestVisibleX = PointD.getInstance(0,0); @Override public float getLowestVisibleX() { - PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom()); - return (float) Math.max(mXAxis.mAxisMinimum, pos.y); + getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), posForGetLowestVisibleX); + float result = (float) Math.max(mXAxis.mAxisMinimum, posForGetLowestVisibleX.y); + return result; } + protected PointD posForGetHighestVisibleX = PointD.getInstance(0,0); @Override public float getHighestVisibleX() { - PointD pos = getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentTop()); - return (float) Math.min(mXAxis.mAxisMaximum, pos.y); + getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), + mViewPortHandler.contentTop(), posForGetHighestVisibleX); + float result = (float) Math.min(mXAxis.mAxisMaximum, posForGetHighestVisibleX.y); + return result; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 048db03299..c0b58947e1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -37,6 +37,8 @@ public Highlight getHighlight(float x, float y) { (float) pos.y); } + PointD.recycleInstance(pos); + return high; } @@ -78,6 +80,8 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal high.getAxis() ); + PointD.recycleInstance(pixels); + return stackedHigh; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index ced7150c94..90d74b26e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -28,15 +28,20 @@ public ChartHighlighter(T chart) { @Override public Highlight getHighlight(float x, float y) { - float xVal = (float) getValsForTouch(x, y).x; + PointD pos = getValsForTouch(x, y); + float xVal = (float) pos.x; + PointD.recycleInstance(pos); Highlight high = getHighlightForX(xVal, x, y); return high; } + /** + * Returns a recyclable PointD instance. * Returns the corresponding xPos for a given touch-position in pixels. * * @param x + * @param y * @return */ protected PointD getValsForTouch(float x, float y) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index c9f89dbe2f..ce1220027e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -37,6 +37,8 @@ public Highlight getHighlight(float x, float y) { (float) pos.x); } + PointD.recycleInstance(pos); + return high; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index e0d71b7a59..f1d4ff0981 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -133,6 +133,9 @@ public void computeAxis(float min, float max, boolean inverted) { min = (float) p1.y; max = (float) p2.y; } + + PointD.recycleInstance(p1); + PointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index e86b38569b..0e94f55e81 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -58,6 +58,9 @@ public void computeAxis(float min, float max, boolean inverted) { min = (float) p1.x; max = (float) p2.x; } + + PointD.recycleInstance(p1); + PointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index b9a43a7454..a40c75f1b4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -49,6 +49,9 @@ public void computeAxis(float min, float max, boolean inverted) { min = (float) p1.y; max = (float) p2.y; } + + PointD.recycleInstance(p1); + PointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index c1f510a3cf..0f0e707850 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -51,6 +51,9 @@ public void computeAxis(float yMin, float yMax, boolean inverted) { yMin = (float) p2.x; yMax = (float) p1.x; } + + PointD.recycleInstance(p1); + PointD.recycleInstance(p2); } computeAxisValues(yMin, yMax); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index bdd96775c2..89bf6a9a80 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -17,7 +17,7 @@ public final class FSize extends ObjectPool.Poolable{ private static ObjectPool pool; static { - pool = ObjectPool.create(500, new FSize(0,0)); + pool = ObjectPool.create(256, new FSize(0,0)); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java index 7335d771ab..ed5ae61e72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java @@ -1,17 +1,44 @@ package com.github.mikephil.charting.utils; +import java.util.List; + /** * Point encapsulating two double values. * * @author Philipp Jahoda */ -public class PointD { +public class PointD extends ObjectPool.Poolable { + + private static ObjectPool pool; + + static { + pool = ObjectPool.create(64, new PointD(0,0)); + } + + public static PointD getInstance(double x, double y){ + PointD result = pool.get(); + result.x = x; + result.y = y; + return result; + } + + public static void recycleInstance(PointD instance){ + pool.recycle(instance); + } + + public static void recycleInstances(List instances){ + pool.recycle(instances); + } public double x; public double y; - public PointD(double x, double y) { + protected ObjectPool.Poolable instantiate(){ + return new PointD(0,0); + } + + private PointD(double x, double y) { this.x = x; this.y = y; } @@ -22,4 +49,4 @@ public PointD(double x, double y) { public String toString() { return "PointD, x: " + x + ", y: " + y; } -} +} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 8604d56cbd..2134f5981c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -355,7 +355,8 @@ public void pixelsToValue(float[] pixels) { float[] ptsBuffer = new float[2]; /** - * Returns the x and y values in the chart at the given touch point + * Returns a recyclable PointD instance. + * returns the x and y values in the chart at the given touch point * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). @@ -366,18 +367,24 @@ public void pixelsToValue(float[] pixels) { */ public PointD getValuesByTouchPoint(float x, float y) { + PointD result = PointD.getInstance(0,0); + getValuesByTouchPoint(x,y,result); + return result; + } + + public void getValuesByTouchPoint(float x, float y, PointD outputPoint){ + ptsBuffer[0] = x; ptsBuffer[1] = y; pixelsToValue(ptsBuffer); - double xTouchVal = ptsBuffer[0]; - double yTouchVal = ptsBuffer[1]; - - return new PointD(xTouchVal, yTouchVal); + outputPoint.x = ptsBuffer[0]; + outputPoint.y = ptsBuffer[1]; } /** + * Returns a recyclable PointD instance. * Returns the x and y coordinates (pixels) for a given x and y value in the chart. * * @param x @@ -394,7 +401,7 @@ public PointD getPixelsForValues(float x, float y) { double xPx = ptsBuffer[0]; double yPx = ptsBuffer[1]; - return new PointD(xPx, yPx); + return PointD.getInstance(xPx, yPx); } public Matrix getValueMatrix() { From 0f2e2133d33fa27dcf26ad193a952123b19b5788 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 14:48:57 -0700 Subject: [PATCH 1049/1390] Eliminate allocs - Legend arrays (#1892) In addition to creating a resized label sizes array, copy old FSize instances to the new array to cut down on the need to get instances from pool. Recycle to pool if the labels shrank. --- .../github/mikephil/charting/components/Legend.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 756cc40a13..b66d93042e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -887,7 +887,16 @@ else if (wasStacked) { //ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); if(mCalculatedLabelSizes.length != labelCount){ - mCalculatedLabelSizes = new FSize[labelCount]; + FSize[] temp = new FSize[labelCount]; + int count = mCalculatedLabelSizes.length; + for(int i = 0 ; i < count && i < labelCount ; i++){ + temp[i] = mCalculatedLabelSizes[i]; + } + while(count > labelCount){ + count--; + FSize.recycleInstance(mCalculatedLabelSizes[count]); + } + mCalculatedLabelSizes = temp; } int calculatedLabelSizesIndex = 0; From f86c1632a7b9d6eed6dbc8e2f1357c65b7b90359 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 15:48:48 -0700 Subject: [PATCH 1050/1390] Eliminate allocs - MPPointF replace PointF (#1892) In order to have a poolable alternative to PointF, this changeset introduces MPPointF. Convenience methods exist that accept output MPPointF variables for extra savings on pool access. Methods that return recyclable MPPointF instances are documented. --- .../mpchartexample/BarChartActivity.java | 5 +- .../HorizontalBarChartActivity.java | 5 +- .../charting/charts/BarLineChartBase.java | 14 +++- .../mikephil/charting/charts/Chart.java | 24 ++++-- .../charting/charts/HorizontalBarChart.java | 12 ++- .../mikephil/charting/charts/PieChart.java | 21 +++-- .../charting/charts/PieRadarChartBase.java | 30 +++++-- .../charting/highlight/RadarHighlighter.java | 8 +- .../dataprovider/ChartInterface.java | 5 +- .../listener/BarLineChartTouchListener.java | 41 +++++---- .../listener/PieRadarChartTouchListener.java | 3 +- .../charting/renderer/PieChartRenderer.java | 28 +++++-- .../charting/renderer/RadarChartRenderer.java | 78 +++++++++++------ .../charting/renderer/XAxisRenderer.java | 41 ++++----- .../XAxisRendererHorizontalBarChart.java | 42 ++++++---- .../renderer/XAxisRendererRadarChart.java | 17 ++-- .../renderer/YAxisRendererRadarChart.java | 24 ++++-- .../mikephil/charting/utils/MPPointF.java | 83 +++++++++++++++++++ .../github/mikephil/charting/utils/Utils.java | 18 ++-- .../charting/utils/ViewPortHandler.java | 4 +- 20 files changed, 357 insertions(+), 146 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index ce090da068..36dce1166e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -33,6 +33,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -264,7 +265,7 @@ public void onValueSelected(Entry e, Highlight h) { return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e, AxisDependency.LEFT); + MPPointF position = mChart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); @@ -272,6 +273,8 @@ public void onValueSelected(Entry e, Highlight h) { Log.i("x-index", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); + + MPPointF.recycleInstance(position); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 64b9be2ea5..a3ad974eff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -27,6 +27,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -253,11 +254,13 @@ public void onValueSelected(Entry e, Highlight h) { return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); + + MPPointF.recycleInstance(position); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 2672bf3006..de0357d80c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -32,6 +32,7 @@ import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -594,11 +595,13 @@ public void computeScroll() { */ public void zoomIn() { - PointF center = mViewPortHandler.getContentCenter(); + MPPointF center = mViewPortHandler.getContentCenter(); Matrix save = mViewPortHandler.zoomIn(center.x, -center.y); mViewPortHandler.refresh(save, this, false); + MPPointF.recycleInstance(center); + // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. // So we need to recalculate offsets. @@ -611,11 +614,13 @@ public void zoomIn() { */ public void zoomOut() { - PointF center = mViewPortHandler.getContentCenter(); + MPPointF center = mViewPortHandler.getContentCenter(); Matrix save = mViewPortHandler.zoomOut(center.x, -center.y); mViewPortHandler.refresh(save, this, false); + MPPointF.recycleInstance(center); + // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. // So we need to recalculate offsets. @@ -1000,13 +1005,14 @@ public OnDrawListener getDrawListener() { } /** + * Returns a recyclable MPPointF instance. * Returns the position (in pixels) the provided Entry has inside the chart * view or null, if the provided Entry is null. * * @param e * @return */ - public PointF getPosition(Entry e, AxisDependency axis) { + public MPPointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; @@ -1017,7 +1023,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { getTransformer(axis).pointValuesToPixel(vals); - return new PointF(vals[0], vals[1]); + return MPPointF.getInstance(vals[0], vals[1]); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ce5d42ea65..8540e6032a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -45,6 +45,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -450,7 +451,7 @@ protected void onDraw(Canvas canvas) { /** * the custom position of the description text */ - private PointF mDescriptionPosition; + private MPPointF mDescriptionPosition; /** * draws the description text in the bottom right corner of the chart @@ -1043,22 +1044,24 @@ public float getXRange() { } /** + * Returns a recyclable MPPointF instance. * Returns the center point of the chart (the whole View) in pixels. * * @return */ - public PointF getCenter() { - return new PointF(getWidth() / 2f, getHeight() / 2f); + public MPPointF getCenter() { + return MPPointF.getInstance(getWidth() / 2f, getHeight() / 2f); } /** + * Returns a recyclable MPPointF instance. * Returns the center of the chart taking offsets under consideration. * (returns the center of the content rectangle) * * @return */ @Override - public PointF getCenterOffsets() { + public MPPointF getCenterOffsets() { return mViewPortHandler.getContentCenter(); } @@ -1081,7 +1084,12 @@ public void setDescription(String desc) { * @param y - ycoordinate */ public void setDescriptionPosition(float x, float y) { - mDescriptionPosition = new PointF(x, y); + if(mDescriptionPosition == null){ + mDescriptionPosition = MPPointF.getInstance(x,y); + }else { + mDescriptionPosition.x = x; + mDescriptionPosition.y = y; + } } /** @@ -1484,8 +1492,12 @@ public void setHighlighter(ChartHighlighter highlighter) { mHighlighter = highlighter; } + /** + * Returns a recyclable MPPointF instance. + * @return + */ @Override - public PointF getCenterOfView() { + public MPPointF getCenterOfView() { return getCenter(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 1c04c22331..4fbd2e2d41 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; import com.github.mikephil.charting.utils.HorizontalViewPortHandler; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.TransformerHorizontalBarChart; import com.github.mikephil.charting.utils.Utils; @@ -164,8 +165,15 @@ public RectF getBarBounds(BarEntry e) { return bounds; } + /** + * Returns a recyclable MPPointF instance. + * + * @param e + * @param axis + * @return + */ @Override - public PointF getPosition(Entry e, AxisDependency axis) { + public MPPointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; @@ -174,7 +182,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { getTransformer(axis).pointValuesToPixel(vals); - return new PointF(vals[0], vals[1]); + return MPPointF.getInstance(vals[0], vals[1]); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 232fe48ea8..416110e9f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.highlight.PieHighlighter; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.renderer.PieChartRenderer; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import java.util.List; @@ -72,7 +73,7 @@ public class PieChart extends PieRadarChartBase { */ private CharSequence mCenterText = ""; - private PointF mCenterTextOffset = new PointF(0, 0); + private MPPointF mCenterTextOffset = MPPointF.getInstance(0, 0); /** * indicates the size of the hole in the center of the piechart, default: @@ -150,7 +151,7 @@ public void calculateOffsets() { float diameter = getDiameter(); float radius = diameter / 2f; - PointF c = getCenterOffsets(); + MPPointF c = getCenterOffsets(); float shift = mData.getDataSet().getSelectionShift(); @@ -160,6 +161,8 @@ public void calculateOffsets() { c.y - radius + shift, c.x + radius - shift, c.y + radius - shift); + + MPPointF.recycleInstance(c); } @Override @@ -170,7 +173,7 @@ protected void calcMinMax() { @Override protected float[] getMarkerPosition(Highlight highlight) { - PointF center = getCenterCircleBox(); + MPPointF center = getCenterCircleBox(); float r = getRadius(); float off = r / 10f * 3.6f; @@ -196,6 +199,7 @@ protected float[] getMarkerPosition(Highlight highlight) { * Math.sin(Math.toRadians((rotationAngle + mAbsoluteAngles[entryIndex] - offset) * mAnimator.getPhaseY())) + center.y); + MPPointF.recycleInstance(center); return new float[]{x, y}; } @@ -459,8 +463,8 @@ public RectF getCircleBox() { * * @return */ - public PointF getCenterCircleBox() { - return new PointF(mCircleBox.centerX(), mCircleBox.centerY()); + public MPPointF getCenterCircleBox() { + return MPPointF.getInstance(mCircleBox.centerX(), mCircleBox.centerY()); } /** @@ -498,7 +502,8 @@ public void setCenterTextSizePixels(float sizePixels) { * @param y */ public void setCenterTextOffset(float x, float y) { - mCenterTextOffset = new PointF(Utils.convertDpToPixel(x), Utils.convertDpToPixel(y)); + mCenterTextOffset.x = Utils.convertDpToPixel(x); + mCenterTextOffset.y = Utils.convertDpToPixel(y); } /** @@ -506,8 +511,8 @@ public void setCenterTextOffset(float x, float y) { * * @return */ - public PointF getCenterTextOffset() { - return mCenterTextOffset; + public MPPointF getCenterTextOffset() { + return MPPointF.getInstance(mCenterTextOffset.x, mCenterTextOffset.y); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 6a82bc13a8..2cf3da0b66 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; /** @@ -138,7 +139,7 @@ public void calculateOffsets() { float legendWidth = fullLegendWidth + spacing; float legendHeight = mLegend.mNeededHeight + mLegend.mTextHeightMax; - PointF c = getCenter(); + MPPointF center = getCenter(); float bottomX = mLegend.getHorizontalAlignment() == Legend.LegendHorizontalAlignment.RIGHT @@ -147,19 +148,22 @@ public void calculateOffsets() { float bottomY = legendHeight + 15.f; float distLegend = distanceToCenter(bottomX, bottomY); - PointF reference = getPosition(c, getRadius(), + MPPointF reference = getPosition(center, getRadius(), getAngleForPoint(bottomX, bottomY)); float distReference = distanceToCenter(reference.x, reference.y); float minOffset = Utils.convertDpToPixel(5f); - if (bottomY >= c.y && getHeight() - legendWidth > getWidth()) { + if (bottomY >= center.y && getHeight() - legendWidth > getWidth()) { xLegendOffset = legendWidth; } else if (distLegend < distReference) { float diff = distReference - distLegend; xLegendOffset = minOffset + diff; } + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(reference); } } @@ -258,7 +262,7 @@ public void calculateOffsets() { */ public float getAngleForPoint(float x, float y) { - PointF c = getCenterOffsets(); + MPPointF c = getCenterOffsets(); double tx = x - c.x, ty = y - c.y; double length = Math.sqrt(tx * tx + ty * ty); @@ -276,10 +280,13 @@ public float getAngleForPoint(float x, float y) { if (angle > 360f) angle = angle - 360f; + MPPointF.recycleInstance(c); + return angle; } /** + * Returns a recyclable MPPointF instance. * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. * @@ -288,13 +295,18 @@ public float getAngleForPoint(float x, float y) { * @param angle in degrees, converted to radians internally * @return */ - public PointF getPosition(PointF center, float dist, float angle) { + public MPPointF getPosition(MPPointF center, float dist, float angle) { - PointF p = new PointF((float) (center.x + dist * Math.cos(Math.toRadians(angle))), - (float) (center.y + dist * Math.sin(Math.toRadians(angle)))); + MPPointF p = MPPointF.getInstance(0,0); + getPosition(center, dist, angle, p); return p; } + public void getPosition(MPPointF center, float dist, float angle, MPPointF outputPoint){ + outputPoint.x = (float) (center.x + dist * Math.cos(Math.toRadians(angle))); + outputPoint.y = (float) (center.y + dist * Math.sin(Math.toRadians(angle))); + } + /** * Returns the distance of a certain point on the chart to the center of the * chart. @@ -305,7 +317,7 @@ public PointF getPosition(PointF center, float dist, float angle) { */ public float distanceToCenter(float x, float y) { - PointF c = getCenterOffsets(); + MPPointF c = getCenterOffsets(); float dist = 0f; @@ -327,6 +339,8 @@ public float distanceToCenter(float x, float y) { // pythagoras dist = (float) Math.sqrt(Math.pow(xDist, 2.0) + Math.pow(yDist, 2.0)); + MPPointF.recycleInstance(c); + return dist; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java index 706dab07f4..c322980b89 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -61,6 +62,7 @@ protected List getHighlightsAtIndex(int index) { float sliceangle = mChart.getSliceAngle(); float factor = mChart.getFactor(); + MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { IDataSet dataSet = mChart.getData().getDataSetByIndex(i); @@ -69,11 +71,11 @@ protected List getHighlightsAtIndex(int index) { float y = (entry.getY() - mChart.getYChartMin()); - PointF p = Utils.getPosition( + Utils.getPosition( mChart.getCenterOffsets(), y * factor * phaseY, - sliceangle * index * phaseX + mChart.getRotationAngle()); + sliceangle * index * phaseX + mChart.getRotationAngle(), pOut); - vals.add(new Highlight(index, entry.getY(), p.x, p.y, i, dataSet.getAxisDependency())); + vals.add(new Highlight(index, entry.getY(), pOut.x, pOut.y, i, dataSet.getAxisDependency())); } return vals; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 1083e34863..a4618554bb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; /** @@ -56,9 +57,9 @@ public interface ChartInterface { int getHeight(); - PointF getCenterOfView(); + MPPointF getCenterOfView(); - PointF getCenterOffsets(); + MPPointF getCenterOffsets(); RectF getContentRect(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 0fe3ef94ac..f1a8241dc4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -41,12 +42,12 @@ public class BarLineChartTouchListener extends ChartTouchListener mMinScalePointerDistance) { // get the translation - PointF t = getTrans(mTouchPointCenter.x, mTouchPointCenter.y); + MPPointF t = getTrans(mTouchPointCenter.x, mTouchPointCenter.y); ViewPortHandler h = mChart.getViewPortHandler(); // take actions depending on the activated touch mode @@ -408,6 +414,8 @@ private void performZoom(MotionEvent event) { l.onChartScale(event, 1f, scaleY); } } + + MPPointF.recycleInstance(t); } } } @@ -439,10 +447,11 @@ private void performHighlightDrag(MotionEvent e) { * @param point * @param event */ - private static void midPoint(PointF point, MotionEvent event) { + private static void midPoint(MPPointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); - point.set(x / 2f, y / 2f); + point.x = (x / 2f); + point.y = (y / 2f); } /** @@ -482,6 +491,7 @@ private static float getYDist(MotionEvent e) { } /** + * Returns a recyclable MPPointF instance. * returns the correct translation depending on the provided x and y touch * points * @@ -489,7 +499,7 @@ private static float getYDist(MotionEvent e) { * @param y * @return */ - public PointF getTrans(float x, float y) { + public MPPointF getTrans(float x, float y) { ViewPortHandler vph = mChart.getViewPortHandler(); @@ -503,7 +513,7 @@ public PointF getTrans(float x, float y) { yTrans = -(mChart.getMeasuredHeight() - y - vph.offsetBottom()); } - return new PointF(xTrans, yTrans); + return MPPointF.getInstance(xTrans, yTrans); } /** @@ -554,13 +564,15 @@ public boolean onDoubleTap(MotionEvent e) { // check if double-tap zooming is enabled if (mChart.isDoubleTapToZoomEnabled() && mChart.getData().getEntryCount() > 0) { - PointF trans = getTrans(e.getX(), e.getY()); + MPPointF trans = getTrans(e.getX(), e.getY()); mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); if (mChart.isLogEnabled()) Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); + + MPPointF.recycleInstance(trans); } return super.onDoubleTap(e); @@ -615,7 +627,8 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve } public void stopDeceleration() { - mDecelerationVelocity = new PointF(0.f, 0.f); + mDecelerationVelocity.x = 0; + mDecelerationVelocity.y = 0; } public void computeScroll() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index c6d82d6193..527617472a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -20,7 +21,7 @@ */ public class PieRadarChartTouchListener extends ChartTouchListener> { - private PointF mTouchStartPoint = new PointF(); + private MPPointF mTouchStartPoint = MPPointF.getInstance(0,0); /** * the angle where the dragging started diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 8eb5311ee9..2466078ce4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -26,6 +26,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -152,7 +153,7 @@ public void drawData(Canvas c) { private RectF mInnerRectBuffer = new RectF(); protected float calculateMinimumRadiusForSpacedSlice( - PointF center, + MPPointF center, float radius, float angle, float arcStartPointX, @@ -219,7 +220,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { final int entryCount = dataSet.getEntryCount(); final float[] drawAngles = mChart.getDrawAngles(); - final PointF center = mChart.getCenterCircleBox(); + final MPPointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); final float userInnerRadius = drawInnerArc @@ -375,12 +376,14 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { angle += sliceAngle * phaseX; } + + MPPointF.recycleInstance(center); } @Override public void drawValues(Canvas c) { - PointF center = mChart.getCenterCircleBox(); + MPPointF center = mChart.getCenterCircleBox(); // get whole the radius float radius = mChart.getRadius(); @@ -579,7 +582,7 @@ public void drawValues(Canvas c) { xIndex++; } } - + MPPointF.recycleInstance(center); c.restore(); } @@ -615,7 +618,7 @@ protected void drawHole(Canvas c) { float radius = mChart.getRadius(); float holeRadius = radius * (mChart.getHoleRadius() / 100); - PointF center = mChart.getCenterCircleBox(); + MPPointF center = mChart.getCenterCircleBox(); if (Color.alpha(mHolePaint.getColor()) > 0) { // draw the hole-circle @@ -642,6 +645,7 @@ protected void drawHole(Canvas c) { // reset alpha mTransparentCirclePaint.setAlpha(alpha); } + MPPointF.recycleInstance(center); } } @@ -655,8 +659,8 @@ protected void drawCenterText(Canvas c) { if (mChart.isDrawCenterTextEnabled() && centerText != null) { - PointF center = mChart.getCenterCircleBox(); - PointF offset = mChart.getCenterTextOffset(); + MPPointF center = mChart.getCenterCircleBox(); + MPPointF offset = mChart.getCenterTextOffset(); float x = center.x + offset.x; float y = center.y + offset.y; @@ -710,6 +714,9 @@ protected void drawCenterText(Canvas c) { mCenterTextLayout.draw(c); c.restore(); + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(offset); } } @@ -724,7 +731,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); - final PointF center = mChart.getCenterCircleBox(); + final MPPointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); final float userInnerRadius = drawInnerArc @@ -901,6 +908,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); } + + MPPointF.recycleInstance(center); } /** @@ -921,7 +930,7 @@ protected void drawRoundedSlices(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - PointF center = mChart.getCenterCircleBox(); + MPPointF center = mChart.getCenterCircleBox(); float r = mChart.getRadius(); // calculate the radius of the "slice-circle" @@ -952,6 +961,7 @@ protected void drawRoundedSlices(Canvas c) { angle += sliceAngle * phaseX; } + MPPointF.recycleInstance(center); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 90b9dcf225..adeaac5851 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -87,8 +88,8 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { // pixels float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); - + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); Path surface = new Path(); boolean hasMovedToPoint = false; @@ -99,19 +100,19 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { RadarEntry e = dataSet.getEntryForIndex(j); - PointF p = Utils.getPosition( + Utils.getPosition( center, (e.getY() - mChart.getYChartMin()) * factor * phaseY, - sliceangle * j * phaseX + mChart.getRotationAngle()); + sliceangle * j * phaseX + mChart.getRotationAngle(), pOut); - if (Float.isNaN(p.x)) + if (Float.isNaN(pOut.x)) continue; if (!hasMovedToPoint) { - surface.moveTo(p.x, p.y); + surface.moveTo(pOut.x, pOut.y); hasMovedToPoint = true; } else - surface.lineTo(p.x, p.y); + surface.lineTo(pOut.x, pOut.y); } if (dataSet.getEntryCount() > mostEntries) { @@ -139,6 +140,9 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { // draw the line (only if filled is disabled or alpha is below 255) if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) c.drawPath(surface, mRenderPaint); + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); } @Override @@ -153,7 +157,8 @@ public void drawValues(Canvas c) { // pixels float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); float yoffset = Utils.convertDpToPixel(5f); @@ -171,15 +176,19 @@ public void drawValues(Canvas c) { RadarEntry entry = dataSet.getEntryForIndex(j); - PointF p = Utils.getPosition( - center, - (entry.getY() - mChart.getYChartMin()) * factor * phaseY, - sliceangle * j * phaseX + mChart.getRotationAngle()); + Utils.getPosition( + center, + (entry.getY() - mChart.getYChartMin()) * factor * phaseY, + sliceangle * j * phaseX + mChart.getRotationAngle(), + pOut); - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, p.x, p.y - yoffset, dataSet.getValueTextColor + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, pOut.x, pOut.y - yoffset, dataSet.getValueTextColor (j)); } } + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); } @Override @@ -196,7 +205,7 @@ protected void drawWeb(Canvas c) { float factor = mChart.getFactor(); float rotationangle = mChart.getRotationAngle(); - PointF center = mChart.getCenterOffsets(); + MPPointF center = mChart.getCenterOffsets(); // draw the web lines that come from the center mWebPaint.setStrokeWidth(mChart.getWebLineWidth()); @@ -206,15 +215,18 @@ protected void drawWeb(Canvas c) { final int xIncrements = 1 + mChart.getSkipWebLineCount(); int maxEntryCount = mChart.getData().getMaxEntryCountSet().getEntryCount(); + MPPointF p = MPPointF.getInstance(0,0); for (int i = 0; i < maxEntryCount; i += xIncrements) { - PointF p = Utils.getPosition( + Utils.getPosition( center, mChart.getYRange() * factor, - sliceangle * i + rotationangle); + sliceangle * i + rotationangle, + p); c.drawLine(center.x, center.y, p.x, p.y, mWebPaint); } + MPPointF.recycleInstance(p); // draw the inner-web mWebPaint.setStrokeWidth(mChart.getWebLineWidthInner()); @@ -223,18 +235,24 @@ protected void drawWeb(Canvas c) { int labelCount = mChart.getYAxis().mEntryCount; + MPPointF p1out = MPPointF.getInstance(0,0); + MPPointF p2out = MPPointF.getInstance(0,0); for (int j = 0; j < labelCount; j++) { for (int i = 0; i < mChart.getData().getEntryCount(); i++) { float r = (mChart.getYAxis().mEntries[j] - mChart.getYChartMin()) * factor; - PointF p1 = Utils.getPosition(center, r, sliceangle * i + rotationangle); - PointF p2 = Utils.getPosition(center, r, sliceangle * (i + 1) + rotationangle); + Utils.getPosition(center, r, sliceangle * i + rotationangle, p1out); + Utils.getPosition(center, r, sliceangle * (i + 1) + rotationangle, p2out); + + c.drawLine(p1out.x, p1out.y, p2out.x, p2out.y, mWebPaint); + - c.drawLine(p1.x, p1.y, p2.x, p2.y, mWebPaint); } } + MPPointF.recycleInstance(p1out); + MPPointF.recycleInstance(p2out); } @Override @@ -246,7 +264,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // pixels float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); RadarData radarData = mChart.getData(); @@ -264,17 +283,19 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float y = (e.getY() - mChart.getYChartMin()); - PointF p = Utils.getPosition(center, y * factor * mAnimator.getPhaseY(), - sliceangle * high.getX() * mAnimator.getPhaseX() + mChart.getRotationAngle()); + Utils.getPosition(center, + y * factor * mAnimator.getPhaseY(), + sliceangle * high.getX() * mAnimator.getPhaseX() + mChart.getRotationAngle(), + pOut); - high.setDraw(p.x, p.y); + high.setDraw(pOut.x, pOut.y); // draw the lines - drawHighlightLines(c, p.x, p.y, set); + drawHighlightLines(c, pOut.x, pOut.y, set); if (set.isDrawHighlightCircleEnabled()) { - if (!Float.isNaN(p.x) && !Float.isNaN(p.y)) { + if (!Float.isNaN(pOut.x) && !Float.isNaN(pOut.y)) { int strokeColor = set.getHighlightCircleStrokeColor(); if (strokeColor == ColorTemplate.COLOR_NONE) { @@ -286,7 +307,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } drawHighlightCircle(c, - p, + pOut, set.getHighlightCircleInnerRadius(), set.getHighlightCircleOuterRadius(), set.getHighlightCircleFillColor(), @@ -295,10 +316,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } } + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); } public void drawHighlightCircle(Canvas c, - PointF point, + MPPointF point, float innerRadius, float outerRadius, int fillColor, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 0e94f55e81..46ccff7124 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -111,32 +112,34 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); + MPPointF pointF = MPPointF.getInstance(0,0); if (mXAxis.getPosition() == XAxisPosition.TOP) { - - drawLabels(c, mViewPortHandler.contentTop() - yoffset, - new PointF(0.5f, 0.9f)); + pointF.x = 0.5f; + pointF.y = 0.9f; + drawLabels(c, mViewPortHandler.contentTop() - yoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { - - drawLabels(c, mViewPortHandler.contentTop() + yoffset + mXAxis.mLabelRotatedHeight, - new PointF(0.5f, 1.0f)); + pointF.x = 0.5f; + pointF.y = 1.0f; + drawLabels(c, mViewPortHandler.contentTop() + yoffset + mXAxis.mLabelRotatedHeight, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - - drawLabels(c, mViewPortHandler.contentBottom() + yoffset, - new PointF(0.5f, 0.0f)); + pointF.x = 0.5f; + pointF.y = 0.0f; + drawLabels(c, mViewPortHandler.contentBottom() + yoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { - - drawLabels(c, mViewPortHandler.contentBottom() - yoffset - mXAxis.mLabelRotatedHeight, - new PointF(0.5f, 0.0f)); + pointF.x = 0.5f; + pointF.y = 0.0f; + drawLabels(c, mViewPortHandler.contentBottom() - yoffset - mXAxis.mLabelRotatedHeight, pointF); } else { // BOTH SIDED - - drawLabels(c, mViewPortHandler.contentTop() - yoffset, - new PointF(0.5f, 1.0f)); - drawLabels(c, mViewPortHandler.contentBottom() + yoffset, - new PointF(0.5f, 0.0f)); + pointF.x = 0.5f; + pointF.y = 1.0f; + drawLabels(c, mViewPortHandler.contentTop() - yoffset, pointF); + pointF.x = 0.5f; + pointF.y = 0.0f; + drawLabels(c, mViewPortHandler.contentBottom() + yoffset, pointF); } } @@ -171,7 +174,7 @@ public void renderAxisLine(Canvas c) { * * @param pos */ - protected void drawLabels(Canvas c, float pos, PointF anchor) { + protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); @@ -221,7 +224,7 @@ protected void drawLabels(Canvas c, float pos, PointF anchor) { } } - protected void drawLabel(Canvas c, String formattedLabel, float x, float y, PointF anchor, float angleDegrees) { + protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) { Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index a40c75f1b4..c66ca164cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -95,37 +96,42 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); - if (mXAxis.getPosition() == XAxisPosition.TOP) { + MPPointF pointF = MPPointF.getInstance(0,0); - drawLabels(c, mViewPortHandler.contentRight() + xoffset, - new PointF(0.0f, 0.5f)); + if (mXAxis.getPosition() == XAxisPosition.TOP) { + pointF.x = 0.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentRight() + xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { - - drawLabels(c, mViewPortHandler.contentRight() - xoffset, - new PointF(1.0f, 0.5f)); + pointF.x = 1.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentRight() - xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - - drawLabels(c, mViewPortHandler.contentLeft() - xoffset, - new PointF(1.0f, 0.5f)); + pointF.x = 1.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentLeft() - xoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { - - drawLabels(c, mViewPortHandler.contentLeft() + xoffset, - new PointF(0.0f, 0.5f)); + pointF.x = 1.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentLeft() + xoffset, pointF); } else { // BOTH SIDED - - drawLabels(c, mViewPortHandler.contentRight() + xoffset, - new PointF(0.0f, 0.5f)); - drawLabels(c, mViewPortHandler.contentLeft() - xoffset, - new PointF(1.0f, 0.5f)); + pointF.x = 0.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentRight() + xoffset, pointF); + pointF.x = 1.0f; + pointF.y = 0.5f; + drawLabels(c, mViewPortHandler.contentLeft() - xoffset, pointF); } + + MPPointF.recycleInstance(pointF); } @Override - protected void drawLabels(Canvas c, float pos, PointF anchor) { + protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 6ccfb09a2a..956e8c7d5c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -6,6 +6,7 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -26,7 +27,7 @@ public void renderAxisLabels(Canvas c) { return; final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); - final PointF drawLabelAnchor = new PointF(0.5f, 0.25f); + final MPPointF drawLabelAnchor = MPPointF.getInstance(0.5f, 0.25f); mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -38,20 +39,24 @@ public void renderAxisLabels(Canvas c) { // pixels float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); - + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < mChart.getData().getMaxEntryCountSet().getEntryCount(); i++) { String label = mXAxis.getValueFormatter().getFormattedValue(i, mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; - PointF p = Utils.getPosition(center, mChart.getYRange() * factor - + mXAxis.mLabelRotatedWidth / 2f, angle); + Utils.getPosition(center, mChart.getYRange() * factor + + mXAxis.mLabelRotatedWidth / 2f, angle, pOut); - drawLabel(c, label, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, + drawLabel(c, label, pOut.x, pOut.y - mXAxis.mLabelRotatedHeight / 2.f, drawLabelAnchor, labelRotationAngleDegrees); } + + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); + MPPointF.recycleInstance(drawLabelAnchor); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 05ac1ab2dd..1393aa2155 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -150,7 +151,8 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); - PointF center = mChart.getCenterOffsets(); + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); float factor = mChart.getFactor(); int labelCount = mYAxis.mEntryCount; @@ -162,12 +164,14 @@ public void renderAxisLabels(Canvas c) { float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; - PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); + Utils.getPosition(center, r, mChart.getRotationAngle(), pOut); String label = mYAxis.getFormattedLabel(j); - c.drawText(label, p.x + 10, p.y, mAxisLabelPaint); + c.drawText(label, pOut.x + 10, pOut.y, mAxisLabelPaint); } + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); } @Override @@ -184,8 +188,8 @@ public void renderLimitLines(Canvas c) { // pixels float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); - + MPPointF center = mChart.getCenterOffsets(); + MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < limitLines.size(); i++) { LimitLine l = limitLines.get(i); @@ -201,19 +205,21 @@ public void renderLimitLines(Canvas c) { Path limitPath = new Path(); + for (int j = 0; j < mChart.getData().getMaxEntryCountSet().getEntryCount(); j++) { - PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); + Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle(), pOut); if (j == 0) - limitPath.moveTo(p.x, p.y); + limitPath.moveTo(pOut.x, pOut.y); else - limitPath.lineTo(p.x, p.y); + limitPath.lineTo(pOut.x, pOut.y); } - limitPath.close(); c.drawPath(limitPath, mLimitLinePaint); } + MPPointF.recycleInstance(center); + MPPointF.recycleInstance(pOut); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java new file mode 100644 index 0000000000..84f5850862 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java @@ -0,0 +1,83 @@ +package com.github.mikephil.charting.utils; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; + +/** + * Created by Tony Patino on 6/24/16. + */ +public class MPPointF extends ObjectPool.Poolable { + private static ObjectPool pool; + + public float x; + public float y; + + static { + pool = ObjectPool.create(32, new MPPointF(0,0)); + } + + private MPPointF(float x, float y){ + this.x = x; + this.y = y; + } + + public static MPPointF getInstance(float x, float y){ + MPPointF result = pool.get(); + result.x = x; + result.y = y; + return result; + } + + public static void recycleInstance(MPPointF instance){ + pool.recycle(instance); + } + + public static void recycleInstances(List instances){ + pool.recycle(instances); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + /** + * Return a new point from the data in the specified parcel. + */ + public MPPointF createFromParcel(Parcel in) { + MPPointF r = new MPPointF(0,0); + r.my_readFromParcel(in); + return r; + } + + /** + * Return an array of rectangles of the specified size. + */ + public MPPointF[] newArray(int size) { + return new MPPointF[size]; + } + }; + + /** + * Set the point's coordinates from the data stored in the specified + * parcel. To write a point to a parcel, call writeToParcel(). + * Provided to support older Android devices. + * + * @param in The parcel to read the point's coordinates from + */ + public void my_readFromParcel(Parcel in) { + x = in.readFloat(); + y = in.readFloat(); + } + + public float getX(){ + return this.x; + } + + public float getY(){ + return this.y; + } + + @Override + protected ObjectPool.Poolable instantiate() { + return new MPPointF(0,0); + } +} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 223ea6d8b3..5ba70d1d1e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -397,6 +397,7 @@ public static double nextUp(double d) { } /** + * Returns a recyclable MPPointF instance. * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. * @@ -405,13 +406,18 @@ public static double nextUp(double d) { * @param angle in degrees, converted to radians internally * @return */ - public static PointF getPosition(PointF center, float dist, float angle) { + public static MPPointF getPosition(MPPointF center, float dist, float angle) { - PointF p = new PointF((float) (center.x + dist * Math.cos(Math.toRadians(angle))), - (float) (center.y + dist * Math.sin(Math.toRadians(angle)))); + MPPointF p = MPPointF.getInstance(0,0); + getPosition(center, dist, angle, p); return p; } + public static void getPosition(MPPointF center, float dist, float angle, MPPointF outputPoint){ + outputPoint.x = (float) (center.x + dist * Math.cos(Math.toRadians(angle))); + outputPoint.y = (float) (center.y + dist * Math.sin(Math.toRadians(angle))); + } + public static void velocityTrackerPointerUpCleanUpIfNecessary(MotionEvent ev, VelocityTracker tracker) { @@ -475,7 +481,7 @@ public static float getNormalizedAngle(float angle) { public static void drawXAxisValue(Canvas c, String text, float x, float y, Paint paint, - PointF anchor, float angleDegrees) { + MPPointF anchor, float angleDegrees) { float drawOffsetX = 0.f; float drawOffsetY = 0.f; @@ -542,7 +548,7 @@ public static void drawXAxisValue(Canvas c, String text, float x, float y, public static void drawMultilineText(Canvas c, StaticLayout textLayout, float x, float y, TextPaint paint, - PointF anchor, float angleDegrees) { + MPPointF anchor, float angleDegrees) { float drawOffsetX = 0.f; float drawOffsetY = 0.f; @@ -620,7 +626,7 @@ public static void drawMultilineText(Canvas c, String text, float x, float y, TextPaint paint, FSize constrainedToSize, - PointF anchor, float angleDegrees) { + MPPointF anchor, float angleDegrees) { StaticLayout textLayout = new StaticLayout( text, 0, text.length(), diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 5ee48a8eed..88dce51460 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -162,8 +162,8 @@ public RectF getContentRect() { return mContentRect; } - public PointF getContentCenter() { - return new PointF(mContentRect.centerX(), mContentRect.centerY()); + public MPPointF getContentCenter() { + return MPPointF.getInstance(mContentRect.centerX(), mContentRect.centerY()); } public float getChartHeight() { From d946f3e3ff65f337d67ed93318da66e9becdee4d Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 16:34:49 -0700 Subject: [PATCH 1051/1390] Eliminate allocs - float array buffers (#1892) Creating field level buffers for frequently instantiated float arrays. Cuts instantiations of many small objects. --- .../charting/charts/BarLineChartBase.java | 11 +++--- .../charting/charts/HorizontalBarChart.java | 5 ++- .../mikephil/charting/charts/PieChart.java | 20 ++++++++--- .../charting/renderer/LineChartRenderer.java | 8 +++-- .../charting/renderer/XAxisRenderer.java | 19 ++++++++-- .../XAxisRendererHorizontalBarChart.java | 14 +++++--- .../charting/renderer/YAxisRenderer.java | 11 ++++-- .../YAxisRendererHorizontalBarChart.java | 12 +++++-- .../mikephil/charting/utils/Transformer.java | 36 ++++++++++++++++--- .../charting/utils/ViewPortHandler.java | 6 +++- 10 files changed, 114 insertions(+), 28 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index de0357d80c..5a2d5c4f56 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1004,6 +1004,7 @@ public OnDrawListener getDrawListener() { return mDrawListener; } + protected float[] mGetPositionBuffer = new float[2]; /** * Returns a recyclable MPPointF instance. * Returns the position (in pixels) the provided Entry has inside the chart @@ -1017,9 +1018,9 @@ public MPPointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; - float[] vals = new float[]{ - e.getX(), e.getY() - }; + float[] vals = mGetPositionBuffer; + vals[0] = e.getX(); + vals[1] = e.getY(); getTransformer(axis).pointValuesToPixel(vals); @@ -1535,11 +1536,13 @@ public Paint getPaint(int which) { return null; } + protected float[] mOnSizeChangedBuffer = new float[2]; @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Saving current position of chart. - float[] pts = new float[2]; + float[] pts = mOnSizeChangedBuffer; + pts[0] = pts[1] = 0; if (mKeepPositionOnRotation) { pts[0] = mViewPortHandler.contentLeft(); pts[1] = mViewPortHandler.contentTop(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 4fbd2e2d41..adba11e527 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -165,6 +165,7 @@ public RectF getBarBounds(BarEntry e) { return bounds; } + protected float[] mGetPositionBuffer = new float[2]; /** * Returns a recyclable MPPointF instance. * @@ -178,7 +179,9 @@ public MPPointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; - float[] vals = new float[]{e.getY(), e.getX()}; + float[] vals = mGetPositionBuffer; + vals[0] = e.getY(); + vals[1] = e.getX(); getTransformer(axis).pointValuesToPixel(vals); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 416110e9f9..5dfd5263ff 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -41,12 +41,12 @@ public class PieChart extends PieRadarChartBase { /** * array that holds the width of each pie-slice in degrees */ - private float[] mDrawAngles; + private float[] mDrawAngles = new float[1]; /** * array that holds the absolute angle in degrees of each slice */ - private float[] mAbsoluteAngles; + private float[] mAbsoluteAngles = new float[1]; /** * if true, the white hole inside the chart will be drawn @@ -210,8 +210,20 @@ private void calcAngles() { int entryCount = mData.getEntryCount(); - mDrawAngles = new float[entryCount]; - mAbsoluteAngles = new float[entryCount]; + if(mDrawAngles.length != entryCount) { + mDrawAngles = new float[entryCount]; + }else{ + for(int i = 0 ; i < entryCount ; i++){ + mDrawAngles[i] = 0; + } + } + if(mAbsoluteAngles.length != entryCount) { + mAbsoluteAngles = new float[entryCount]; + }else{ + for(int i = 0 ; i < entryCount ; i++){ + mAbsoluteAngles[i] = 0; + } + } float yValueSum = mData.getYValueSum(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index d6fe125cf1..9571f56939 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -356,8 +356,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { } else { // only one color per dataset - if (mLineBuffer.length != Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 2) - mLineBuffer = new float[Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 2]; + if (mLineBuffer.length < Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 2) + mLineBuffer = new float[Math.max((entryCount) * pointsPerEntryPair, pointsPerEntryPair) * 4]; Entry e1, e2; @@ -527,6 +527,7 @@ public void drawExtras(Canvas c) { } private Path mCirclePathBuffer = new Path(); + private float[] circlesBuffer = new float[2]; protected void drawCircles(Canvas c) { @@ -534,7 +535,8 @@ protected void drawCircles(Canvas c) { float phaseY = mAnimator.getPhaseY(); - float[] circlesBuffer = new float[2]; + circlesBuffer[0] = 0; + circlesBuffer[1] = 0; List dataSets = mChart.getLineData().getDataSets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 46ccff7124..e309065e0e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -169,6 +169,7 @@ public void renderAxisLine(Canvas c) { } } + protected float[] mDrawLabelsBuffer = new float[2]; /** * draws the x-labels on the specified y-position * @@ -179,7 +180,10 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - float[] positions = new float[mXAxis.mEntryCount * 2]; + if(mDrawLabelsBuffer.length != mAxis.mEntryCount * 2){ + mDrawLabelsBuffer = new float[mXAxis.mEntryCount * 2]; + } + float[] positions = mDrawLabelsBuffer; for (int i = 0; i < positions.length; i += 2) { @@ -189,6 +193,8 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { } else { positions[i] = mXAxis.mEntries[i / 2]; } + // init to 0 + positions[i+1] = 0; } mTrans.pointValuesToPixel(positions); @@ -228,13 +234,17 @@ protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPo Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } + protected float[] mRenderGridLinesBuffer = new float[2]; @Override public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; - float[] positions = new float[mXAxis.mEntryCount * 2]; + if(mRenderGridLinesBuffer.length != mAxis.mEntryCount * 2){ + mRenderGridLinesBuffer = new float[mXAxis.mEntryCount * 2]; + } + float[] positions = mRenderGridLinesBuffer; for (int i = 0; i < positions.length; i += 2) { positions[i] = mXAxis.mEntries[i / 2]; @@ -272,6 +282,7 @@ protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { gridLinePath.reset(); } + protected float[] mRenderLimitLinesBuffer = new float[2]; /** * Draws the LimitLines associated with this axis to the screen. * @@ -285,7 +296,9 @@ public void renderLimitLines(Canvas c) { if (limitLines == null || limitLines.size() <= 0) return; - float[] position = new float[2]; + float[] position = mRenderLimitLinesBuffer; + position[0] = 0; + position[1] = 0; for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index c66ca164cc..4a63c4daf8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -5,7 +5,6 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; -import android.graphics.PointF; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.LimitLine; @@ -130,13 +129,17 @@ public void renderAxisLabels(Canvas c) { MPPointF.recycleInstance(pointF); } + protected float[] mDrawLabelsBuffer = new float[2]; @Override protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - float[] positions = new float[mXAxis.mEntryCount * 2]; + if(mDrawLabelsBuffer.length != mAxis.mEntryCount * 2){ + mDrawLabelsBuffer = new float[mXAxis.mEntryCount * 2]; + } + float[] positions = mDrawLabelsBuffer; for (int i = 0; i < positions.length; i += 2) { @@ -200,7 +203,7 @@ public void renderAxisLine(Canvas c) { } } - /** + /** * Draws the LimitLines associated with this axis to the screen. * This is the standard YAxis renderer using the XAxis limit lines. * @@ -214,7 +217,10 @@ public void renderLimitLines(Canvas c) { if (limitLines == null || limitLines.size() <= 0) return; - float[] pts = new float[2]; + float[] pts = mRenderLimitLinesBuffer; + pts[0] = 0; + pts[1] = 0; + Path limitLinePath = new Path(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index f626ac752e..7b7285e3d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -171,6 +171,7 @@ protected Path linePath(Path p, int i, float[] positions) { return p; } + protected float[] mGetTransformedPositionsBuffer = new float[2]; /** * Transforms the values contained in the axis entries to screen pixels and returns them in form of a float array * of x- and y-coordinates. @@ -179,7 +180,10 @@ protected Path linePath(Path p, int i, float[] positions) { */ protected float[] getTransformedPositions() { - float[] positions = new float[mYAxis.mEntryCount * 2]; + if(mGetTransformedPositionsBuffer.length != mYAxis.mEntryCount * 2){ + mGetTransformedPositionsBuffer = new float[mYAxis.mEntryCount * 2]; + } + float[] positions = mGetTransformedPositionsBuffer; for (int i = 0; i < positions.length; i += 2) { // only fill y values, x values are not needed for y-labels @@ -210,6 +214,7 @@ protected void drawZeroLine(Canvas c) { c.drawPath(zeroLinePath, mZeroLinePaint); } + protected float[] mRenderLimitLinesBuffer = new float[2]; /** * Draws the LimitLines associated with this axis to the screen. * @@ -223,7 +228,9 @@ public void renderLimitLines(Canvas c) { if (limitLines == null || limitLines.size() <= 0) return; - float[] pts = new float[2]; + float[] pts = mRenderLimitLinesBuffer; + pts[0] = 0; + pts[1] = 0; Path limitLinePath = new Path(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 0f0e707850..08d7f9701e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -150,7 +150,10 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo @Override protected float[] getTransformedPositions() { - float[] positions = new float[mYAxis.mEntryCount * 2]; + if(mGetTransformedPositionsBuffer.length != mYAxis.mEntryCount * 2) { + mGetTransformedPositionsBuffer = new float[mYAxis.mEntryCount * 2]; + } + float[] positions = mGetTransformedPositionsBuffer; for (int i = 0; i < positions.length; i += 2) { // only fill x values, y values are not needed for x-labels @@ -188,6 +191,7 @@ protected void drawZeroLine(Canvas c) { c.drawPath(zeroLinePath, mZeroLinePaint); } + protected float[] mRenderLimitLinesBuffer = new float[4]; /** * Draws the LimitLines associated with this axis to the screen. * This is the standard XAxis renderer using the YAxis limit lines. @@ -202,7 +206,11 @@ public void renderLimitLines(Canvas c) { if (limitLines == null || limitLines.size() <= 0) return; - float[] pts = new float[4]; + float[] pts = mRenderLimitLinesBuffer; + pts[0] = 0; + pts[1] = 0; + pts[2] = 0; + pts[3] = 0; Path limitLinePath = new Path(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 2134f5981c..1b07b75c57 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -93,6 +93,7 @@ public void prepareMatrixOffset(boolean inverted) { // mOffsetBottom); } + protected float[] valuePointsForGenerateTransformedValuesScatter = new float[1]; /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the SCATTERCHART. @@ -105,7 +106,10 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas final int count = (int) ((to - from) * phaseX + 1) * 2; - float[] valuePoints = new float[count]; + if(valuePointsForGenerateTransformedValuesScatter.length != count){ + valuePointsForGenerateTransformedValuesScatter = new float[count]; + } + float[] valuePoints = valuePointsForGenerateTransformedValuesScatter; for (int j = 0; j < count; j += 2) { @@ -114,6 +118,9 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; + }else{ + valuePoints[j] = 0; + valuePoints[j + 1] = 0; } } @@ -122,6 +129,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas return valuePoints; } + protected float[] valuePointsForGenerateTransformedValuesBubble = new float[1]; /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BUBBLECHART. @@ -133,7 +141,10 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY final int count = (to - from + 1) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; - float[] valuePoints = new float[count]; + if(valuePointsForGenerateTransformedValuesBubble.length != count){ + valuePointsForGenerateTransformedValuesBubble = new float[count]; + } + float[] valuePoints = valuePointsForGenerateTransformedValuesBubble; for (int j = 0; j < count; j += 2) { @@ -142,6 +153,9 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; + }else{ + valuePoints[j] = 0; + valuePoints[j + 1] = 0; } } @@ -150,6 +164,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY return valuePoints; } + protected float[] valuePointsForGenerateTransformedValuesLine = new float[1]; /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the LINECHART. @@ -162,7 +177,10 @@ public float[] generateTransformedValuesLine(ILineDataSet data, final int count = (int) ((to - from) * phaseX + 1) * 2; - float[] valuePoints = new float[count]; + if(valuePointsForGenerateTransformedValuesLine.length != count){ + valuePointsForGenerateTransformedValuesLine = new float[count]; + } + float[] valuePoints = valuePointsForGenerateTransformedValuesLine; for (int j = 0; j < count; j += 2) { @@ -171,6 +189,9 @@ public float[] generateTransformedValuesLine(ILineDataSet data, if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; + }else{ + valuePoints[j] = 0; + valuePoints[j + 1] = 0; } } @@ -179,6 +200,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, return valuePoints; } + protected float[] valuePointsForGenerateTransformedValuesCandle = new float[1]; /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the CANDLESTICKCHART. @@ -191,7 +213,10 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, final int count = (int) ((to - from) * phaseX + 1) * 2; - float[] valuePoints = new float[count]; + if(valuePointsForGenerateTransformedValuesCandle.length != count){ + valuePointsForGenerateTransformedValuesCandle = new float[count]; + } + float[] valuePoints = valuePointsForGenerateTransformedValuesCandle; for (int j = 0; j < count; j += 2) { @@ -200,6 +225,9 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getHigh() * phaseY; + }else{ + valuePoints[j] = 0; + valuePoints[j + 1] = 0; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 88dce51460..e4efe5c871 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -291,6 +291,7 @@ public Matrix setZoom(float scaleX, float scaleY, float x, float y) { return save; } + protected float[] valsBufferForFitScreen = new float[9]; /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. @@ -303,7 +304,10 @@ public Matrix fitScreen() { Matrix save = new Matrix(); save.set(mMatrixTouch); - float[] vals = new float[9]; + float[] vals = valsBufferForFitScreen; + for(int i = 0 ; i < 9 ; i++){ + vals[i] = 0; + } save.getValues(vals); From 56cfd2b42b67a23834ca68f8d1faae520010a88a Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 17:22:48 -0700 Subject: [PATCH 1052/1390] Eliminate allocs - Matrix and Path buffers (#1892) Created buffers for short lived Matrix and Path objects, resetting them instead of instantiating new ones. Also created some matrix transform methods that accept output Matrix objects to facilitate caching. --- .../charting/charts/BarLineChartBase.java | 18 ++-- .../charting/jobs/AnimatedZoomJob.java | 6 +- .../mikephil/charting/jobs/ZoomJob.java | 6 +- .../charting/renderer/LineChartRenderer.java | 4 +- .../charting/renderer/PieChartRenderer.java | 4 +- .../charting/renderer/RadarChartRenderer.java | 8 +- .../charting/renderer/XAxisRenderer.java | 5 +- .../XAxisRendererHorizontalBarChart.java | 4 +- .../charting/renderer/YAxisRenderer.java | 12 ++- .../YAxisRendererHorizontalBarChart.java | 9 +- .../renderer/YAxisRendererRadarChart.java | 4 +- .../scatter/TriangleShapeRenderer.java | 4 +- .../mikephil/charting/utils/Transformer.java | 4 +- .../charting/utils/ViewPortHandler.java | 99 ++++++++++++------- 14 files changed, 129 insertions(+), 58 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 5a2d5c4f56..642c61e7c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -590,6 +590,7 @@ public void computeScroll() { * VIEWPORT */ + protected Matrix mZoomInMatrixBuffer = new Matrix(); /** * Zooms in by 1.4f, into the charts center. center. */ @@ -597,8 +598,8 @@ public void zoomIn() { MPPointF center = mViewPortHandler.getContentCenter(); - Matrix save = mViewPortHandler.zoomIn(center.x, -center.y); - mViewPortHandler.refresh(save, this, false); + mViewPortHandler.zoomIn(center.x, -center.y, mZoomInMatrixBuffer); + mViewPortHandler.refresh(mZoomInMatrixBuffer, this, false); MPPointF.recycleInstance(center); @@ -609,6 +610,7 @@ public void zoomIn() { postInvalidate(); } + protected Matrix mZoomOutMatrixBuffer = new Matrix(); /** * Zooms out by 0.7f, from the charts center. center. */ @@ -616,8 +618,8 @@ public void zoomOut() { MPPointF center = mViewPortHandler.getContentCenter(); - Matrix save = mViewPortHandler.zoomOut(center.x, -center.y); - mViewPortHandler.refresh(save, this, false); + mViewPortHandler.zoomOut(center.x, -center.y, mZoomOutMatrixBuffer); + mViewPortHandler.refresh(mZoomOutMatrixBuffer, this, false); MPPointF.recycleInstance(center); @@ -628,6 +630,7 @@ public void zoomOut() { postInvalidate(); } + protected Matrix mZoomMatrixBuffer = new Matrix(); /** * Zooms in or out by the given scale factor. x and y are the coordinates * (in pixels) of the zoom center. @@ -638,7 +641,8 @@ public void zoomOut() { * @param y */ public void zoom(float scaleX, float scaleY, float x, float y) { - Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, y); + Matrix save = mZoomMatrixBuffer; + mViewPortHandler.zoom(scaleX, scaleY, x, y, save); mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels @@ -694,12 +698,14 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa } } + protected Matrix mFitScreenMatrixBuffer = new Matrix(); /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. */ public void fitScreen() { - Matrix save = mViewPortHandler.fitScreen(); + Matrix save = mFitScreenMatrixBuffer; + mViewPortHandler.fitScreen(save); mViewPortHandler.refresh(save, this, false); calculateOffsets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index da22c92507..be61ce09f3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -40,13 +40,15 @@ public AnimatedZoomJob(ViewPortHandler viewPortHandler, View v, Transformer tran this.xAxisRange = xAxisRange; } + protected Matrix mOnAnimationUpdateMatrixBuffer = new Matrix(); @Override public void onAnimationUpdate(ValueAnimator animation) { float scaleX = xOrigin + (xValue - xOrigin) * phase; float scaleY = yOrigin + (yValue - yOrigin) * phase; - Matrix save = mViewPortHandler.setZoom(scaleX, scaleY); + Matrix save = mOnAnimationUpdateMatrixBuffer; + mViewPortHandler.setZoom(scaleX, scaleY, save); mViewPortHandler.refresh(save, view, false); float valsInView = yAxis.mAxisRange / mViewPortHandler.getScaleY(); @@ -57,7 +59,7 @@ public void onAnimationUpdate(ValueAnimator animation) { mTrans.pointValuesToPixel(pts); - save = mViewPortHandler.translate(pts); + mViewPortHandler.translate(pts, save); mViewPortHandler.refresh(save, view, true); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java index d9d7e99354..94a8ea1e7b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java @@ -27,10 +27,12 @@ public ZoomJob(ViewPortHandler viewPortHandler, float scaleX, float scaleY, floa this.axisDependency = axis; } + protected Matrix mRunMatrixBuffer = new Matrix(); @Override public void run() { - Matrix save = mViewPortHandler.zoom(scaleX, scaleY); + Matrix save = mRunMatrixBuffer; + mViewPortHandler.zoom(scaleX, scaleY, save); mViewPortHandler.refresh(save, view, false); float valsInView = ((BarLineChartBase) view).getDeltaY(axisDependency) / mViewPortHandler.getScaleY(); @@ -41,7 +43,7 @@ public void run() { mTrans.pointValuesToPixel(pts); - save = mViewPortHandler.translate(pts); + mViewPortHandler.translate(pts, save); mViewPortHandler.refresh(save, view, false); ((BarLineChartBase) view).calculateOffsets(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9571f56939..49536a025b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -431,6 +431,7 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, } } + protected Path mGenerateFilledPathBuffer = new Path(); /** * Generates the path that is used for filled drawing. * @@ -443,7 +444,8 @@ private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) { float phaseY = mAnimator.getPhaseY(); final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; - Path filled = new Path(); + Path filled = mGenerateFilledPathBuffer; + filled.reset(); Entry entry = dataSet.getEntryForIndex(bounds.min); filled.moveTo(entry.getX(), fillMin); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 2466078ce4..f6f0c19b00 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -649,6 +649,7 @@ protected void drawHole(Canvas c) { } } + protected Path mDrawCenterTextPathBuffer = new Path(); /** * draws the description text in the center of the pie chart makes most * sense when center-hole is enabled @@ -705,7 +706,8 @@ protected void drawCenterText(Canvas c) { c.save(); if (Build.VERSION.SDK_INT >= 18) { - Path path = new Path(); + Path path = mDrawCenterTextPathBuffer; + path.reset(); path.addOval(holeRect, Path.Direction.CW); c.clipPath(path); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index adeaac5851..3c54aa7919 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -70,6 +70,7 @@ public void drawData(Canvas c) { } } + protected Path mDrawDataSetSurfacePathBuffer = new Path(); /** * Draws the RadarDataSet * @@ -90,7 +91,8 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet, int mostEntries) { MPPointF center = mChart.getCenterOffsets(); MPPointF pOut = MPPointF.getInstance(0,0); - Path surface = new Path(); + Path surface = mDrawDataSetSurfacePathBuffer; + surface.reset(); boolean hasMovedToPoint = false; @@ -321,6 +323,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { MPPointF.recycleInstance(pOut); } + protected Path mDrawHighlightCirclePathBuffer = new Path(); public void drawHighlightCircle(Canvas c, MPPointF point, float innerRadius, @@ -334,7 +337,8 @@ public void drawHighlightCircle(Canvas c, innerRadius = Utils.convertDpToPixel(innerRadius); if (fillColor != ColorTemplate.COLOR_NONE) { - Path p = new Path(); + Path p = mDrawHighlightCirclePathBuffer; + p.reset(); p.addCircle(point.x, point.y, outerRadius, Path.Direction.CW); if (innerRadius > 0.f) { p.addCircle(point.x, point.y, innerRadius, Path.Direction.CCW); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index e309065e0e..805bdadf8c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -233,7 +233,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { protected void drawLabel(Canvas c, String formattedLabel, float x, float y, MPPointF anchor, float angleDegrees) { Utils.drawXAxisValue(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } - + protected Path mRenderGridLinesPath = new Path(); protected float[] mRenderGridLinesBuffer = new float[2]; @Override public void renderGridLines(Canvas c) { @@ -255,7 +255,8 @@ public void renderGridLines(Canvas c) { setupGridPaint(); - Path gridLinePath = new Path(); + Path gridLinePath = mRenderGridLinesPath; + gridLinePath.reset(); for (int i = 0; i < positions.length; i += 2) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 4a63c4daf8..e050af3c13 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -203,6 +203,7 @@ public void renderAxisLine(Canvas c) { } } + protected Path mRenderLimitLinesPathBuffer = new Path(); /** * Draws the LimitLines associated with this axis to the screen. * This is the standard YAxis renderer using the XAxis limit lines. @@ -221,7 +222,8 @@ public void renderLimitLines(Canvas c) { pts[0] = 0; pts[1] = 0; - Path limitLinePath = new Path(); + Path limitLinePath = mRenderLimitLinesPathBuffer; + limitLinePath.reset(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 7b7285e3d4..b550579d29 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -125,6 +125,7 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo } } + protected Path mRenderGridLinesPath = new Path(); @Override public void renderGridLines(Canvas c) { @@ -139,7 +140,8 @@ public void renderGridLines(Canvas c) { mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); - Path gridLinePath = new Path(); + Path gridLinePath = mRenderGridLinesPath; + gridLinePath.reset(); // draw the grid for (int i = 0; i < positions.length; i += 2) { @@ -194,6 +196,7 @@ protected float[] getTransformedPositions() { return positions; } + protected Path mDrawZeroLinePath = new Path(); /** * Draws the zero line. */ @@ -205,7 +208,8 @@ protected void drawZeroLine(Canvas c) { mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); - Path zeroLinePath = new Path(); + Path zeroLinePath = mDrawZeroLinePath; + zeroLinePath.reset(); zeroLinePath.moveTo(mViewPortHandler.contentLeft(), (float) pos.y - 1); zeroLinePath.lineTo(mViewPortHandler.contentRight(), (float) pos.y - 1); @@ -214,6 +218,7 @@ protected void drawZeroLine(Canvas c) { c.drawPath(zeroLinePath, mZeroLinePaint); } + protected Path mRenderLimitLines = new Path(); protected float[] mRenderLimitLinesBuffer = new float[2]; /** * Draws the LimitLines associated with this axis to the screen. @@ -231,7 +236,8 @@ public void renderLimitLines(Canvas c) { float[] pts = mRenderLimitLinesBuffer; pts[0] = 0; pts[1] = 0; - Path limitLinePath = new Path(); + Path limitLinePath = mRenderLimitLines; + limitLinePath.reset(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 08d7f9701e..21e16ba325 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -173,6 +173,8 @@ protected Path linePath(Path p, int i, float[] positions) { return p; } + protected Path mDrawZeroLinePathBuffer = new Path(); + @Override protected void drawZeroLine(Canvas c) { @@ -182,7 +184,8 @@ protected void drawZeroLine(Canvas c) { mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); - Path zeroLinePath = new Path(); + Path zeroLinePath = mDrawZeroLinePathBuffer; + zeroLinePath.reset(); zeroLinePath.moveTo((float) pos.x - 1, mViewPortHandler.contentTop()); zeroLinePath.lineTo((float) pos.x - 1, mViewPortHandler.contentBottom()); @@ -191,6 +194,7 @@ protected void drawZeroLine(Canvas c) { c.drawPath(zeroLinePath, mZeroLinePaint); } + protected Path mRenderLimitLinesPathBuffer = new Path(); protected float[] mRenderLimitLinesBuffer = new float[4]; /** * Draws the LimitLines associated with this axis to the screen. @@ -211,7 +215,8 @@ public void renderLimitLines(Canvas c) { pts[1] = 0; pts[2] = 0; pts[3] = 0; - Path limitLinePath = new Path(); + Path limitLinePath = mRenderLimitLinesPathBuffer; + limitLinePath.reset(); for (int i = 0; i < limitLines.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 1393aa2155..9a5fd1cd44 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -174,6 +174,7 @@ public void renderAxisLabels(Canvas c) { MPPointF.recycleInstance(pOut); } + private Path mRenderLimitLinesPathBuffer = new Path(); @Override public void renderLimitLines(Canvas c) { @@ -203,7 +204,8 @@ public void renderLimitLines(Canvas c) { float r = (l.getLimit() - mChart.getYChartMin()) * factor; - Path limitPath = new Path(); + Path limitPath = mRenderLimitLinesPathBuffer; + limitPath.reset(); for (int j = 0; j < mChart.getData().getMaxEntryCountSet().getEntryCount(); j++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java index 0b5a996bad..789297d170 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java @@ -16,6 +16,7 @@ */ public class TriangleShapeRenderer implements ShapeRenderer { + protected Path mTrianglePathBuffer = new Path(); @Override public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint @@ -31,7 +32,8 @@ public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewP renderPaint.setStyle(Paint.Style.FILL); // create a triangle path - Path tri = new Path(); + Path tri = mTrianglePathBuffer; + tri.reset(); for (int i = 0; i < buffer.size(); i += 2) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 1b07b75c57..e842084936 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -356,6 +356,7 @@ public void rectValuesToPixel(List rects) { m.mapRect(rects.get(i)); } + protected Matrix mPixelsToValueMatrixBuffer = new Matrix(); /** * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) * into values on the chart. @@ -364,7 +365,8 @@ public void rectValuesToPixel(List rects) { */ public void pixelsToValue(float[] pixels) { - Matrix tmp = new Matrix(); + Matrix tmp = mPixelsToValueMatrixBuffer; + tmp.reset(); // invert all matrixes to convert back to the original value mMatrixOffset.invert(tmp); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index e4efe5c871..9aa8109054 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -198,13 +198,16 @@ public float getSmallestContentExtension() { public Matrix zoomIn(float x, float y) { Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(1.4f, 1.4f, x, y); - + zoomIn(x,y,save); return save; } + public void zoomIn(float x, float y, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.postScale(1.4f, 1.4f, x, y); + } + /** * Zooms out by 0.7f, x and y are the coordinates (in pixels) of the zoom * center. @@ -212,13 +215,16 @@ public Matrix zoomIn(float x, float y) { public Matrix zoomOut(float x, float y) { Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(0.7f, 0.7f, x, y); - + zoomOut(x,y,save); return save; } + public void zoomOut(float x, float y, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.postScale(0.7f, 0.7f, x, y); + } + /** * Post-scales by the specified scale factors. * @@ -229,13 +235,16 @@ public Matrix zoomOut(float x, float y) { public Matrix zoom(float scaleX, float scaleY) { Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(scaleX, scaleY); - + zoom(scaleX,scaleY,save); return save; } + public void zoom(float scaleX, float scaleY, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.postScale(scaleX, scaleY); + } + /** * Post-scales by the specified scale factors. x and y is pivot. * @@ -248,13 +257,16 @@ public Matrix zoom(float scaleX, float scaleY) { public Matrix zoom(float scaleX, float scaleY, float x, float y) { Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.postScale(scaleX, scaleY, x, y); - + zoom(scaleX,scaleY,x,y,save); return save; } + public void zoom(float scaleX, float scaleY, float x, float y, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.postScale(scaleX,scaleY,x,y); + } + /** * Sets the scale factor to the specified values. * @@ -265,13 +277,16 @@ public Matrix zoom(float scaleX, float scaleY, float x, float y) { public Matrix setZoom(float scaleX, float scaleY) { Matrix save = new Matrix(); - save.set(mMatrixTouch); - - save.setScale(scaleX, scaleY); - + setZoom(scaleX,scaleY,save); return save; } + public void setZoom(float scaleX, float scaleY, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.setScale(scaleX,scaleY); + } + /** * Sets the scale factor to the specified values. x and y is pivot. * @@ -292,24 +307,34 @@ public Matrix setZoom(float scaleX, float scaleY, float x, float y) { } protected float[] valsBufferForFitScreen = new float[9]; + /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. */ public Matrix fitScreen() { + Matrix save = new Matrix(); + fitScreen(save); + return save; + } + + /** + * Resets all zooming and dragging and makes the chart fit exactly it's + * bounds. Output Matrix is available for those who wish to cache the object. + */ + public void fitScreen(Matrix outputMatrix){ mMinScaleX = 1f; mMinScaleY = 1f; - Matrix save = new Matrix(); - save.set(mMatrixTouch); + outputMatrix.set(mMatrixTouch); float[] vals = valsBufferForFitScreen; for(int i = 0 ; i < 9 ; i++){ vals[i] = 0; } - save.getValues(vals); + outputMatrix.getValues(vals); // reset all translations and scaling vals[Matrix.MTRANS_X] = 0f; @@ -317,13 +342,11 @@ public Matrix fitScreen() { vals[Matrix.MSCALE_X] = 1f; vals[Matrix.MSCALE_Y] = 1f; - save.setValues(vals); - - return save; + outputMatrix.setValues(vals); } /** - * Post-translates to the specified points. + * Post-translates to the specified points. Less Performant. * * @param transformedPts * @return @@ -331,16 +354,25 @@ public Matrix fitScreen() { public Matrix translate(final float[] transformedPts) { Matrix save = new Matrix(); - save.set(mMatrixTouch); + translate(transformedPts, save); + return save; + } + /** + * Post-translates to the specified points. Output matrix allows for caching objects. + * + * @param transformedPts + * @return + */ + public void translate(final float[] transformedPts, Matrix outputMatrix){ + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); final float x = transformedPts[0] - offsetLeft(); final float y = transformedPts[1] - offsetTop(); - - save.postTranslate(-x, -y); - - return save; + outputMatrix.postTranslate(-x, -y); } + protected Matrix mCenterViewPortMatrixBuffer = new Matrix(); /** * Centers the viewport around the specified position (x-index and y-value) * in the chart. Centering the viewport outside the bounds of the chart is @@ -353,7 +385,8 @@ public Matrix translate(final float[] transformedPts) { */ public void centerViewPort(final float[] transformedPts, final View view) { - Matrix save = new Matrix(); + Matrix save = mCenterViewPortMatrixBuffer; + save.reset(); save.set(mMatrixTouch); final float x = transformedPts[0] - offsetLeft(); From c59b46affc1afdaed31b437caad47617324229be Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 17:39:42 -0700 Subject: [PATCH 1053/1390] Eliminate allocs - Cache drawn circles as bitmaps (#1892) LineChartRenderer now caches drawn circles as bitmaps. ILineDataSet now has a method that returns the number of available colors in the set. --- .../mikephil/charting/data/LineDataSet.java | 4 + .../interfaces/datasets/ILineDataSet.java | 7 + .../charting/renderer/LineChartRenderer.java | 132 ++++++++++++++---- 3 files changed, 114 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index d0d7cb3e82..2b802d9c28 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -252,6 +252,10 @@ public int getCircleColor(int index) { return mCircleColors.get(index % mCircleColors.size()); } + public int getCircleColorCount(){ + return mCircleColors.size(); + } + /** * Sets the colors that should be used for the circles of this DataSet. * Colors are reused as soon as the number of Entries the DataSet represents diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 6f62274b8e..bccf6984d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -52,6 +52,13 @@ public interface ILineDataSet extends ILineRadarDataSet { */ int getCircleColor(int index); + /** + * Returns the number of colors in this DataSet's circle-color array. + * + * @return + */ + int getCircleColorCount(); + /** * Returns true if drawing circles for this DataSet is enabled, false if not * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 49536a025b..2c433fa15f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.PointD; @@ -21,10 +22,42 @@ import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; +import java.util.HashMap; import java.util.List; public class LineChartRenderer extends LineRadarRenderer { + private class DataSetImageCache { + + + private Bitmap[] circleBitmaps; + private int[] circleColors; + + private void ensureCircleCache(int size){ + if(circleBitmaps == null){ + circleBitmaps = new Bitmap[size]; + }else if(circleBitmaps.length < size){ + Bitmap[] tmp = new Bitmap[size]; + for(int i = 0 ; i < circleBitmaps.length ; i++){ + tmp[i] = circleBitmaps[size]; + } + circleBitmaps = tmp; + } + + if(circleColors == null){ + circleColors = new int[size]; + }else if(circleColors.length < size){ + int[] tmp = new int[size]; + for(int i = 0 ; i < circleColors.length ; i++){ + tmp[i] = circleColors[size]; + } + circleColors = tmp; + } + } + + } + + protected LineDataProvider mChart; /** @@ -300,8 +333,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // more than 1 color if (dataSet.getColors().size() > 1) { - if (mLineBuffer.length != pointsPerEntryPair * 2) - mLineBuffer = new float[pointsPerEntryPair * 2]; + if (mLineBuffer.length <= pointsPerEntryPair * 2) + mLineBuffer = new float[pointsPerEntryPair * 4]; for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { @@ -529,23 +562,34 @@ public void drawExtras(Canvas c) { } private Path mCirclePathBuffer = new Path(); - private float[] circlesBuffer = new float[2]; - + private float[] mCirclesBuffer = new float[2]; + private HashMap mImageCaches = new HashMap<>(); protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); float phaseY = mAnimator.getPhaseY(); + float[] circlesBuffer = mCirclesBuffer; circlesBuffer[0] = 0; circlesBuffer[1] = 0; List dataSets = mChart.getLineData().getDataSets(); - - for (int i = 0; i < dataSets.size(); i++) { + final int dataSetCount = dataSets.size(); + for (int i = 0; i < dataSetCount ; i++) { ILineDataSet dataSet = dataSets.get(i); + DataSetImageCache imageCache; + + if(mImageCaches.containsKey(dataSet)){ + imageCache = mImageCaches.get(dataSet); + }else{ + imageCache = new DataSetImageCache(); + mImageCaches.put(dataSet, imageCache); + } + imageCache.ensureCircleCache(dataSet.getCircleColorCount()); + if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -555,6 +599,7 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); XBounds bounds = getXBounds(mChart, dataSet); + int entryCount = dataSet.getEntryCount(); float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); @@ -564,8 +609,8 @@ protected void drawCircles(Canvas c) { boolean drawTransparentCircleHole = drawCircleHole && dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; - for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { - + int boundsRangeCount = bounds.range + bounds.min; + for (int j = bounds.min; j <= boundsRangeCount; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) break; @@ -584,37 +629,66 @@ protected void drawCircles(Canvas c) { !mViewPortHandler.isInBoundsY(circlesBuffer[1])) continue; - mRenderPaint.setColor(dataSet.getCircleColor(j)); - - if (drawTransparentCircleHole) { + final int circleColor = dataSet.getCircleColor(j); + mRenderPaint.setColor(circleColor); - // Begin path for circle with hole - mCirclePathBuffer.reset(); + Bitmap circleBitmap = null; - mCirclePathBuffer.addCircle(circlesBuffer[0], circlesBuffer[1], - circleRadius, - Path.Direction.CW); + final int dataSetColorCount = imageCache.circleColors.length; + int colorIndex; + for(colorIndex = 0 ; colorIndex < dataSetColorCount ; colorIndex++) { + int tempColor = imageCache.circleColors[colorIndex]; + Bitmap tempBitmap = imageCache.circleBitmaps[colorIndex]; + if(tempColor == circleColor) { + circleBitmap = tempBitmap; + break; + }else if(tempBitmap == null){ + break; + } + } - // Cut hole in path - mCirclePathBuffer.addCircle(circlesBuffer[0], circlesBuffer[1], - circleHoleRadius, - Path.Direction.CCW); - // Fill in-between - c.drawPath(mCirclePathBuffer, mRenderPaint); + if(circleBitmap == null){ + Bitmap.Config conf = Bitmap.Config.ARGB_8888; + circleBitmap = Bitmap.createBitmap((int)circleRadius * 2, (int)circleRadius * 2, conf); + Canvas canvas = new Canvas(circleBitmap); + imageCache.circleBitmaps[colorIndex] = circleBitmap; + imageCache.circleColors[colorIndex] = circleColor; - } else { + if(drawTransparentCircleHole){ + // Begin path for circle with hole + mCirclePathBuffer.reset(); - c.drawCircle(circlesBuffer[0], circlesBuffer[1], - circleRadius, - mRenderPaint); + mCirclePathBuffer.addCircle(circleRadius, circleRadius, + circleRadius, + Path.Direction.CW); - if (drawCircleHole) { - c.drawCircle(circlesBuffer[0], circlesBuffer[1], + // Cut hole in path + mCirclePathBuffer.addCircle(circleHoleRadius, circleHoleRadius, circleHoleRadius, - mCirclePaintInner); + Path.Direction.CCW); + + // Fill in-between + canvas.drawPath(mCirclePathBuffer, mRenderPaint); + }else{ + + canvas.drawCircle(circleRadius, circleRadius, + circleRadius, + mRenderPaint); + + if (drawCircleHole) { + canvas.drawCircle(circleRadius, circleRadius, + circleHoleRadius, + mCirclePaintInner); + } } } + + if(circleBitmap != null){ + + c.drawBitmap(circleBitmap, circlesBuffer[0] - circleRadius, circlesBuffer[1] - circleRadius, mRenderPaint); + + } } } } From bd45d73bc6fc6e24d5bf31fbf0072fc6fdd8e247 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Tue, 28 Jun 2016 18:18:49 -0700 Subject: [PATCH 1054/1390] Eliminate allocs - Array Access (#1892) foreach(:) arrays on Android carry the cost that each iteration creates an implicit instantiation. for(;;) arrays are uglier but guarantee that no unwanted allocations occur while iterating. --- .../mikephil/charting/charts/Chart.java | 6 +- .../mikephil/charting/data/BarData.java | 5 +- .../mikephil/charting/data/BubbleData.java | 5 +- .../mikephil/charting/data/ChartData.java | 87 +++++++++++++++---- .../mikephil/charting/data/ScatterData.java | 6 +- .../renderer/BubbleChartRenderer.java | 7 +- .../renderer/CandleStickChartRenderer.java | 6 +- .../charting/renderer/LineChartRenderer.java | 5 +- .../charting/renderer/PieChartRenderer.java | 7 +- .../charting/renderer/RadarChartRenderer.java | 8 +- .../renderer/ScatterChartRenderer.java | 5 +- 11 files changed, 118 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 8540e6032a..6807a57c08 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -306,7 +306,11 @@ public void setData(T data) { // calculate how many digits are needed setupDefaultFormatter(data.getYMin(), data.getYMax()); - for (IDataSet set : mData.getDataSets()) { + IDataSet set; + final List sets = mData.getDataSets(); + final int count = sets.size(); + for(int i = 0 ; i < count ; i++){ + set = (IDataSet)sets.get(i); if (set.needsFormatter() || set.getValueFormatter() == mDefaultFormatter) set.setValueFormatter(mDefaultFormatter); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 2cc22c8b72..609d480d32 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -74,7 +74,10 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { float start = fromX; fromX += groupSpaceWidthHalf; - for (IBarDataSet set : mDataSets) { + IBarDataSet set; + final int setCountJ = mDataSets.size(); + for(int j = 0 ; j < setCountJ ; j++){ + set = mDataSets.get(j); fromX += barSpaceHalf; fromX += barWidthHalf; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java index 0ce345bc90..c7522599a9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java @@ -28,7 +28,10 @@ public BubbleData(List dataSets) { * @param width */ public void setHighlightCircleWidth(float width) { - for (IBubbleDataSet set : mDataSets) { + IBubbleDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setHighlightCircleWidth(width); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index fa66f4744e..0d243c6a1c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -80,9 +80,12 @@ public ChartData(T... dataSets) { */ private List arrayToList(T[] array) { - List list = new ArrayList<>(); + int setsCount = array.length; + List list = new ArrayList<>(setsCount); - for (T set : array) { + T set = null; + for(int i = 0 ; i < setsCount ; i++){ + set = array[i]; list.add(set); } @@ -129,7 +132,10 @@ public void calcMinMax() { mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - for (T set : mDataSets) { + T set; + int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); calcMinMax(set); } @@ -146,7 +152,10 @@ public void calcMinMax() { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - for (IDataSet dataSet : mDataSets) { + IDataSet dataSet; + int dataSetsCount = mDataSets.size(); + for(int i = 0 ; i < dataSetsCount ; i++){ + dataSet = mDataSets.get(i); if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -165,7 +174,10 @@ public void calcMinMax() { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - for (IDataSet dataSet : mDataSets) { + IDataSet dataSet; + int dataSetsCount = mDataSets.size(); + for(int i = 0 ; i < dataSetsCount ; i++){ + dataSet = mDataSets.get(i); if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -614,7 +626,10 @@ public int getIndexOfDataSet(T dataSet) { * @return */ protected T getFirstLeft(List sets) { - for (T dataSet : sets) { + T dataSet; + int setCount = sets.size(); + for(int i = 0 ; i < setCount ; i++){ + dataSet = sets.get(i); if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; } @@ -628,7 +643,10 @@ protected T getFirstLeft(List sets) { * @return */ public T getFirstRight(List sets) { - for (T dataSet : sets) { + T dataSet; + int setCount = sets.size(); + for(int i = 0 ; i < setCount ; i++){ + dataSet = sets.get(i); if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; } @@ -644,7 +662,10 @@ public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setValueFormatter(f); } } @@ -657,7 +678,10 @@ public void setValueFormatter(ValueFormatter f) { * @param color */ public void setValueTextColor(int color) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setValueTextColor(color); } } @@ -669,7 +693,10 @@ public void setValueTextColor(int color) { * @param colors */ public void setValueTextColors(List colors) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setValueTextColors(colors); } } @@ -681,7 +708,10 @@ public void setValueTextColors(List colors) { * @param tf */ public void setValueTypeface(Typeface tf) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setValueTypeface(tf); } } @@ -693,7 +723,10 @@ public void setValueTypeface(Typeface tf) { * @param size */ public void setValueTextSize(float size) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setValueTextSize(size); } } @@ -705,7 +738,10 @@ public void setValueTextSize(float size) { * @param enabled */ public void setDrawValues(boolean enabled) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setDrawValues(enabled); } } @@ -716,7 +752,10 @@ public void setDrawValues(boolean enabled) { * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); set.setHighlightEnabled(enabled); } } @@ -728,7 +767,10 @@ public void setHighlightEnabled(boolean enabled) { * @return */ public boolean isHighlightEnabled() { - for (IDataSet set : mDataSets) { + IDataSet set; + final int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); if (!set.isHighlightEnabled()) return false; } @@ -753,7 +795,10 @@ public void clearValues() { */ public boolean contains(T dataSet) { - for (T set : mDataSets) { + T set; + int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); if (set.equals(dataSet)) return true; } @@ -770,7 +815,10 @@ public int getEntryCount() { int count = 0; - for (T set : mDataSets) { + T set; + int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); count += set.getEntryCount(); } @@ -789,7 +837,10 @@ public T getMaxEntryCountSet() { T max = mDataSets.get(0); - for (T set : mDataSets) { + T set; + int setCount = mDataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = mDataSets.get(i); if (set.getEntryCount() > max.getEntryCount()) max = set; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java index fef13c20fd..f34c5ae3a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java @@ -29,7 +29,11 @@ public float getGreatestShapeSize() { float max = 0f; - for (IScatterDataSet set : mDataSets) { + + IScatterDataSet set; + final int count = mDataSets.size(); + for(int i = 0 ; i < count ; i++){ + set = mDataSets.get(i); float size = set.getScatterShapeSize(); if (size > max) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 18884fd7ce..0712c0f84a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -46,7 +47,11 @@ public void drawData(Canvas c) { BubbleData bubbleData = mChart.getBubbleData(); - for (IBubbleDataSet set : bubbleData.getDataSets()) { + IBubbleDataSet set; + List dataSets = bubbleData.getDataSets(); + int setCount = dataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = dataSets.get(i); if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 294dcedf74..9a1842221e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -44,7 +44,11 @@ public void drawData(Canvas c) { CandleData candleData = mChart.getCandleData(); - for (ICandleDataSet set : candleData.getDataSets()) { + ICandleDataSet set; + List dataSets = candleData.getDataSets(); + int setCount = dataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = dataSets.get(i); if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 2c433fa15f..e099af1b88 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -122,7 +122,10 @@ public void drawData(Canvas c) { LineData lineData = mChart.getLineData(); - for (ILineDataSet set : lineData.getDataSets()) { + ILineDataSet set; + int setCount = lineData.getDataSets().size(); + for(int i = 0 ; i < setCount ; i++){ + set = lineData.getDataSets().get(i); if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index f6f0c19b00..354ea5d4ec 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -142,8 +142,11 @@ public void drawData(Canvas c) { PieData pieData = mChart.getData(); - for (IPieDataSet set : pieData.getDataSets()) { - + IPieDataSet set; + int setCount = pieData.getDataSets().size(); + List dataSet = pieData.getDataSets(); + for(int i = 0 ; i < setCount ; i++){ + set = dataSet.get(i); if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 3c54aa7919..c346c6f6a3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -19,6 +19,8 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.util.List; + public class RadarChartRenderer extends LineRadarRenderer { protected RadarChart mChart; @@ -62,7 +64,11 @@ public void drawData(Canvas c) { int mostEntries = radarData.getMaxEntryCountSet().getEntryCount(); - for (IRadarDataSet set : radarData.getDataSets()) { + IRadarDataSet set; + List dataSets = radarData.getDataSets(); + int setCount = dataSets.size(); + for(int i = 0 ; i < setCount ; i++){ + set = dataSets.get(i); if (set.isVisible() && set.getEntryCount() > 0) { drawDataSet(c, set, mostEntries); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index c9ffbaf3cc..026f975b57 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -47,7 +47,10 @@ public void drawData(Canvas c) { ScatterData scatterData = mChart.getScatterData(); - for (IScatterDataSet set : scatterData.getDataSets()) { + IScatterDataSet set; + int setCount = scatterData.getDataSets().size(); + for(int i = 0 ; i < setCount ; i++){ + set = scatterData.getDataSets().get(i); if (set.isVisible()) drawDataSet(c, set); From 0b72b5588b1770af9ddb756f20b4b4e7169ecf5b Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 16:43:33 -0700 Subject: [PATCH 1055/1390] Eliminate allocs - Cache formatted Strings (#1892) ValueFormatter objects now rely on a FormattedStringCache to return already-formatted Strings. We might want to create primitive-enabled versions since all our values to format are float or double primitives, and the keys are also all primitives. This will eliminate auto-boxing penalties. --- .../BarChartPositiveNegative.java | 7 +-- .../mpchartexample/LineChartTime.java | 6 ++- .../StackedBarActivityNegative.java | 17 ++++--- .../custom/MyAxisValueFormatter.java | 6 ++- .../custom/MyCustomXAxisValueFormatter.java | 14 ++--- .../custom/MyValueFormatter.java | 7 +-- .../custom/RadarMarkerView.java | 6 ++- .../formatter/DefaultAxisValueFormatter.java | 12 +++-- .../formatter/DefaultValueFormatter.java | 11 ++-- .../formatter/FormattedStringCache.java | 51 +++++++++++++++++++ .../formatter/LargeValueFormatter.java | 12 +++-- .../charting/formatter/PercentFormatter.java | 14 +++-- .../formatter/StackedValueFormatter.java | 22 +++++--- 13 files changed, 136 insertions(+), 49 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 1c22ae41c6..a080de8af6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -16,6 +16,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -164,15 +165,15 @@ public Data(float xValue, float yValue, String xAxisValue) { private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter { - private DecimalFormat mFormat; + private FormattedStringCache mFormattedStringCache; public ValueFormatter() { - mFormat = new DecimalFormat("######.0"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("######.0")); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(value); + return mFormattedStringCache.getFormattedString(value, dataSetIndex); } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 7d833625aa..c7893188a3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -91,11 +92,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(60000L); // one minute in millis xAxis.setValueFormatter(new AxisValueFormatter() { - private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); + private FormattedStringCache mFormattedStringCache = new FormattedStringCache(new SimpleDateFormat("dd MMM HH:mm")); @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(new Date((long) value)); + Long v = (long) value; + return mFormattedStringCache.getFormattedString(new Date(v), v); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 200c012771..b1a54cbef1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; @@ -79,11 +80,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(10f); xAxis.setValueFormatter(new AxisValueFormatter() { - private DecimalFormat format = new DecimalFormat("###"); + private FormattedStringCache format = new FormattedStringCache(new DecimalFormat("###")); @Override public String getFormattedValue(float value, AxisBase axis) { - return format.format(value) + "-" + format.format(value + 10); + Float key = value + 10; + return format.getFormattedString(value, value) + "-" + format.getFormattedString(value, key); } @Override @@ -222,22 +224,25 @@ public void onNothingSelected() { private class CustomFormatter implements ValueFormatter, AxisValueFormatter { - private DecimalFormat mFormat; + private FormattedStringCache mFormatValue; + private FormattedStringCache mFormatAxis; public CustomFormatter() { - mFormat = new DecimalFormat("###"); + mFormatValue = new FormattedStringCache<>(new DecimalFormat("###")); + mFormatAxis = new FormattedStringCache<>(new DecimalFormat("###")); } // data @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(Math.abs(value)) + "m"; + return mFormatValue.getFormattedString(value, dataSetIndex) + "m"; } // YAxis @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(Math.abs(value)) + "m"; + Float v = Math.abs(value); + return mFormatAxis.getFormattedString(v,v) + "m"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index ea50fd8fad..06197d7508 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -2,20 +2,22 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.FormattedStringCache; import java.text.DecimalFormat; public class MyAxisValueFormatter implements AxisValueFormatter { private DecimalFormat mFormat; + private FormattedStringCache mFormattedStringCache; public MyAxisValueFormatter() { - mFormat = new DecimalFormat("###,###,###,##0.0"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); } @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(value) + " $"; + return mFormattedStringCache.getFormattedString(value, value) + " $"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 16d5752905..f2018bcdd4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -2,6 +2,7 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -11,13 +12,13 @@ */ public class MyCustomXAxisValueFormatter implements AxisValueFormatter { - private DecimalFormat mFormat; + private FormattedStringCache mFormattedStringCache; private ViewPortHandler mViewPortHandler; public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { mViewPortHandler = viewPortHandler; // maybe do something here or provide parameters in constructor - mFormat = new DecimalFormat("###,###,###,##0.0"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); } @Override @@ -26,14 +27,15 @@ public String getFormattedValue(float value, AxisBase axis) { //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); // e.g. adjust the x-axis values depending on scale / zoom level - if (mViewPortHandler.getScaleX() > 5) + final float xScale = mViewPortHandler.getScaleX(); + if (xScale > 5) return "4"; - else if (mViewPortHandler.getScaleX() > 3) + else if (xScale > 3) return "3"; - else if (mViewPortHandler.getScaleX() > 1) + else if (xScale > 1) return "2"; else - return mFormat.format(value); + return mFormattedStringCache.getFormattedString(value, value); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index a374b60e7f..87cf28f4c3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -8,14 +9,14 @@ public class MyValueFormatter implements ValueFormatter { - private DecimalFormat mFormat; + private FormattedStringCache mFormattedStringCache; public MyValueFormatter() { - mFormat = new DecimalFormat("###,###,###,##0.0"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(value) + " $"; + return mFormattedStringCache.getFormattedString(value, dataSetIndex) + " $"; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index b86e8ba603..b02212d89a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -22,7 +23,7 @@ public class RadarMarkerView extends MarkerView { private TextView tvContent; - private DecimalFormat format = new DecimalFormat("##0"); + private FormattedStringCache mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("##0")); public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); @@ -35,7 +36,8 @@ public RadarMarkerView(Context context, int layoutResource) { // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(format.format(e.getY()) + " %"); + float value = e.getY(); + tvContent.setText(mFormattedStringCache.getFormattedString(value, value) + " %"); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index ad3bb783ee..3369e00693 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -10,9 +10,9 @@ public class DefaultAxisValueFormatter implements AxisValueFormatter { /** - * decimalformat for formatting + * FormattedStringFormat for formatting and caching */ - protected DecimalFormat mFormat; + protected FormattedStringCache mFormattedStringCache; /** * the number of decimal digits this formatter uses @@ -35,13 +35,15 @@ public DefaultAxisValueFormatter(int digits) { b.append("0"); } - mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0" + b.toString())); } @Override public String getFormattedValue(float value, AxisBase axis) { - // avoid memory allocations here (for performance) - return mFormat.format(value); + + // TODO: There should be a better way to do this. Floats are not the best keys... + return mFormattedStringCache.getFormattedString(value, value); + } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 5d23d25f7e..039787113c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -15,9 +15,9 @@ public class DefaultValueFormatter implements ValueFormatter { /** - * DecimalFormat for formatting + * FormattedStringCache for formatting and caching. */ - protected DecimalFormat mFormat; + protected FormattedStringCache mFormattedStringCache; protected int mDecimalDigits; @@ -47,16 +47,15 @@ public void setup(int digits) { b.append("0"); } - mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0" + b.toString())); + } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - // put more logic here ... - // avoid memory allocations here (for performance reasons) + return mFormattedStringCache.getFormattedString(value, dataSetIndex); - return mFormat.format(value); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java new file mode 100644 index 0000000000..047af77571 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java @@ -0,0 +1,51 @@ +package com.github.mikephil.charting.formatter; + +import java.text.Format; +import java.util.HashMap; + +/** + * Created by Tony Patino on 6/29/16. + * + * COST : Frequently the V type, and the K type will often be passed as primitives (float / int / double) + * This will incur an auto-boxing penalty, and an instantiation on each call. + * + * BENEFIT : Formatting of Strings is one of the costliest operations remaining, and it is larger than the boxing penalty. + * Eliminating redundant formats helps more than boxing hurts. + * + * Possibly want to make some explicit primitive enabled caches, though they can be ugly. + * + */ +public class FormattedStringCache { + + private Format mFormat; + private HashMap mCachedStringsHashMap = new HashMap<>(); + private HashMap mCachedValuesHashMap = new HashMap<>(); + + public Format getFormat(){ + return mFormat; + } + + public FormattedStringCache(Format format){ + this.mFormat = format; + } + + public String getFormattedString(V value, K key){ + + // If we can't find the value at all, create an entry for it, and format the string. + if(!mCachedValuesHashMap.containsKey(key)){ + mCachedStringsHashMap.put(key, mFormat.format(value)); + mCachedValuesHashMap.put(key, value); + } + + // If the old value and the new one don't match, format the string and store it, because the string's value will be different now. + if(!value.equals(mCachedValuesHashMap.get(key))){ + mCachedStringsHashMap.put(key, mFormat.format(value)); + mCachedValuesHashMap.put(key, value); + } + + String result = mCachedStringsHashMap.get(key); + + return result; + } + +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index ef8dc4077a..5679c9a2aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -23,11 +23,16 @@ public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { "", "k", "m", "b", "t" }; private static final int MAX_LENGTH = 5; - private DecimalFormat mFormat; private String mText = ""; + + /** + * FormattedStringCache for formatting and caching. + */ + protected FormattedStringCache mFormattedStringCache; + public LargeValueFormatter() { - mFormat = new DecimalFormat("###E00"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###E00")); } /** @@ -77,7 +82,8 @@ public void setSuffix(String[] suff) { */ private String makePretty(double number) { - String r = mFormat.format(number); + // TODO : Should be better way to do this. Double isn't the best key... + String r = mFormattedStringCache.getFormattedString(number,number); int numericValue1 = Character.getNumericValue(r.charAt(r.length() - 1)); int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 209da1fa83..890eb681cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -15,10 +15,12 @@ */ public class PercentFormatter implements ValueFormatter, AxisValueFormatter { - protected DecimalFormat mFormat; + protected FormattedStringCache mFormattedStringCache; + protected FormattedStringCache mFormattedStringCacheAxis; public PercentFormatter() { - mFormat = new DecimalFormat("###,###,##0.0"); + mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,##0.0")); + mFormattedStringCacheAxis = new FormattedStringCache<>(new DecimalFormat("###,###,##0.0")); } /** @@ -27,19 +29,21 @@ public PercentFormatter() { * @param format */ public PercentFormatter(DecimalFormat format) { - this.mFormat = format; + mFormattedStringCache = new FormattedStringCache<>(format); + mFormattedStringCacheAxis = new FormattedStringCache<>(format); } // ValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(value) + " %"; + return mFormattedStringCache.getFormattedString(value, dataSetIndex) + " %"; } // AxisValueFormatter @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(value) + " %"; + // TODO: Find a better way to do this. Float isn't the best key... + return mFormattedStringCacheAxis.getFormattedString(value, value) + " %"; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index b13dd8d907..97cc589528 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -18,6 +18,9 @@ public class StackedValueFormatter implements ValueFormatter { * if true, all stack values of the stacked bar entry are drawn, else only top */ private boolean mDrawWholeStack; + private FormattedStringCache mFormattedStringCacheWholeStack; + private FormattedStringCache mFormattedStringCache; + /** * a string that should be appended behind the value @@ -44,12 +47,16 @@ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decima b.append("0"); } - this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + this.mFormattedStringCache = new FormattedStringCache(new DecimalFormat("###,###,###,##0" + b.toString())); + this.mFormattedStringCacheWholeStack = new FormattedStringCache(new DecimalFormat("###,###,###,##0" + b.toString())); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + FormattedStringCache chosenCache = mFormattedStringCache; + int chosenIndex = dataSetIndex; + float chosenValue = value; if (!mDrawWholeStack && entry instanceof BarEntry) { BarEntry barEntry = (BarEntry) entry; @@ -59,16 +66,19 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View // find out if we are on top of the stack if (vals[vals.length - 1] == value) { - - // return the "sum" across all stack values - return mFormat.format(barEntry.getY()) + mAppendix; + chosenCache = mFormattedStringCacheWholeStack; + chosenValue = barEntry.getY(); } else { - return ""; // return empty + chosenCache = null; } } } + if(chosenCache == null){ + return ""; + } + // return the "proposed" value - return mFormat.format(value) + mAppendix; + return chosenCache.getFormattedString(chosenValue, chosenIndex) + mAppendix; } } From d372fd305c600286709e90e49eb7b13881afdd6a Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 17:05:07 -0700 Subject: [PATCH 1056/1390] Eliminate allocs - Rect and RectF buffers (#1892) Buffering temporary Rect and RectF instances. Created methods to modify RectF instances as performance alternatives to methods that create disposable RectF instances. --- .../mpchartexample/BarChartActivity.java | 5 ++- .../HorizontalBarChartActivity.java | 6 +++- .../mikephil/charting/charts/BarChart.java | 31 +++++++++++++++---- .../charting/charts/HorizontalBarChart.java | 12 ++++--- .../charting/renderer/PieChartRenderer.java | 4 ++- .../github/mikephil/charting/utils/Utils.java | 8 +++-- 6 files changed, 50 insertions(+), 16 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 36dce1166e..775c925bbf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.graphics.PointF; +import android.graphics.Rect; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; @@ -257,6 +258,7 @@ private void setData(int count, float range) { } } + protected RectF mOnValueSelectedRectF = new RectF(); @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { @@ -264,7 +266,8 @@ public void onValueSelected(Entry e, Highlight h) { if (e == null) return; - RectF bounds = mChart.getBarBounds((BarEntry) e); + RectF bounds = mOnValueSelectedRectF; + mChart.getBarBounds((BarEntry) e, bounds); MPPointF position = mChart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index a3ad974eff..bab2e085a0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -3,6 +3,7 @@ import android.annotation.SuppressLint; import android.graphics.PointF; +import android.graphics.Rect; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; @@ -246,6 +247,7 @@ private void setData(int count, float range) { } } + protected RectF mOnValueSelectedRectF = new RectF(); @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { @@ -253,7 +255,9 @@ public void onValueSelected(Entry e, Highlight h) { if (e == null) return; - RectF bounds = mChart.getBarBounds((BarEntry) e); + RectF bounds = mOnValueSelectedRectF; + mChart.getBarBounds((BarEntry) e, bounds); + MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 9b437c9028..05a0e1a1eb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -98,17 +98,37 @@ public Highlight getHighlightByTouchPoint(float x, float y) { /** * Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be - * found in the charts data. + * found in the charts data. Performance-intensive code should use void getBarBounds(BarEntry, RectF) instead. * * @param e * @return */ public RectF getBarBounds(BarEntry e) { + + RectF bounds = new RectF(); + getBarBounds(e, bounds); + + return bounds; + } + + /** + * The passed outputRect will be assigned the values of the bounding box of the specified Entry in the specified DataSet. + * The rect will be assigned Float.MIN_VALUE in all locations if the Entry could not be found in the charts data. + * + * @param e + * @return + */ + public void getBarBounds(BarEntry e, RectF outputRect){ + + RectF bounds = outputRect; + IBarDataSet set = mData.getDataSetForEntry(e); - if (set == null) - return null; + if (set == null) { + bounds.set(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE); + return; + } float y = e.getY(); float x = e.getX(); @@ -120,11 +140,10 @@ public RectF getBarBounds(BarEntry e) { float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; - RectF bounds = new RectF(left, top, right, bottom); + bounds.set(left, top, right, bottom); - getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); + getTransformer(set.getAxisDependency()).rectValueToPixel(outputRect); - return bounds; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index adba11e527..0c14db733a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -141,12 +141,15 @@ protected float[] getMarkerPosition(Highlight high) { } @Override - public RectF getBarBounds(BarEntry e) { + public void getBarBounds(BarEntry e, RectF outputRect) { + RectF bounds = outputRect; IBarDataSet set = mData.getDataSetForEntry(e); - if (set == null) - return null; + if (set == null){ + outputRect.set(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE); + return; + } float y = e.getY(); float x = e.getX(); @@ -158,11 +161,10 @@ public RectF getBarBounds(BarEntry e) { float left = y >= 0 ? y : 0; float right = y <= 0 ? y : 0; - RectF bounds = new RectF(left, top, right, bottom); + bounds.set(left, top, right, bottom); getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - return bounds; } protected float[] mGetPositionBuffer = new float[2]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 354ea5d4ec..d479737c04 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -725,6 +725,7 @@ protected void drawCenterText(Canvas c) { } } + protected RectF mDrawHighlightedRectF = new RectF(); @Override public void drawHighlighted(Canvas c, Highlight[] indices) { @@ -743,7 +744,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; - final RectF highlightedCircleBox = new RectF(); + final RectF highlightedCircleBox = mDrawHighlightedRectF; + highlightedCircleBox.set(0,0,0,0); for (int i = 0; i < indices.length; i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 5ba70d1d1e..eab4b881ff 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -147,6 +147,7 @@ public static int calcTextWidth(Paint paint, String demoText) { return (int) paint.measureText(demoText); } + private static Rect mCalcTextHeightRect = new Rect(); /** * calculates the approximate height of a text, depending on a demo text * avoid repeated calls (e.g. inside drawing methods) @@ -157,7 +158,8 @@ public static int calcTextWidth(Paint paint, String demoText) { */ public static int calcTextHeight(Paint paint, String demoText) { - Rect r = new Rect(); + Rect r = mCalcTextHeightRect; + r.set(0,0,0,0); paint.getTextBounds(demoText, 0, demoText.length(), r); return r.height(); } @@ -188,6 +190,7 @@ public static FSize calcTextSize(Paint paint, String demoText) { return result; } + private static Rect mCalcTextSizeRect = new Rect(); /** * calculates the approximate size of a text, depending on a demo text * avoid repeated calls (e.g. inside drawing methods) @@ -198,7 +201,8 @@ public static FSize calcTextSize(Paint paint, String demoText) { */ public static void calcTextSize(Paint paint, String demoText, FSize outputFSize) { - Rect r = new Rect(); + Rect r = mCalcTextSizeRect; + r.set(0,0,0,0); paint.getTextBounds(demoText, 0, demoText.length(), r); outputFSize.width = r.width(); outputFSize.height = r.height(); From a04ad28cec0b21f95dbaefe5532dbe0b8c7b5c20 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 17:12:47 -0700 Subject: [PATCH 1057/1390] Eliminate allocs - Cache XBounds in Renderer (#1892) getXBounds creates a disposable XBounds instance on every call. Cache it and update the values with a set method. This means XBounds values are now mutable. --- .../BarLineScatterCandleBubbleRenderer.java | 15 ++++++++++++--- .../charting/renderer/LineChartRenderer.java | 8 +++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 60697eac7a..9028e94704 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -58,17 +58,17 @@ protected class XBounds { /** * minimum visible entry index */ - public final int min; + public int min; /** * maximum visible entry index */ - public final int max; + public int max; /** * range of visible entry indices */ - public final int range; + public int range; /** * Calculates the minimum and maximum x values as well as the range between them. @@ -77,7 +77,16 @@ protected class XBounds { * @param dataSet */ public XBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { + this.set(chart, dataSet); + } + /** + * Calculates the minimum and maximum x values as well as the range between them. + * + * @param chart + * @param dataSet + */ + public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet){ float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float low = chart.getLowestVisibleX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index e099af1b88..9c92b9db52 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -302,6 +302,7 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf } private float[] mLineBuffer = new float[4]; + private XBounds xBoundsBuffer; /** * Draws a normal line. @@ -331,7 +332,12 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { canvas = c; } - XBounds bounds = getXBounds(mChart, dataSet); + if(xBoundsBuffer == null){ + xBoundsBuffer = getXBounds(mChart, dataSet); + }else{ + xBoundsBuffer.set(mChart, dataSet); + } + final XBounds bounds = xBoundsBuffer; // more than 1 color if (dataSet.getColors().size() > 1) { From 424ee02ce2088619dc1c792d1f162d33071de15e Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 17:36:15 -0700 Subject: [PATCH 1058/1390] Eliminate allocs - String Caches now have Prim subtypes (#1892) By creating versions of the FormattedStringCache that don't require auto boxing, allocations are cut tremendously in this commit. --- .../BarChartPositiveNegative.java | 6 +- .../formatter/DefaultAxisValueFormatter.java | 6 +- .../formatter/FormattedStringCache.java | 80 ++++++++++++++++++- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index a080de8af6..efe51d2ffd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -165,15 +165,15 @@ public Data(float xValue, float yValue, String xAxisValue) { private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter { - private FormattedStringCache mFormattedStringCache; + private FormattedStringCache.PrimIntFloat mFormattedStringCache; public ValueFormatter() { - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("######.0")); + mFormattedStringCache = new FormattedStringCache.PrimIntFloat(new DecimalFormat("######.0")); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedString(value, dataSetIndex); + return mFormattedStringCache.getFormattedValue(value, dataSetIndex); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index 3369e00693..f55fc8175e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -12,7 +12,7 @@ public class DefaultAxisValueFormatter implements AxisValueFormatter { /** * FormattedStringFormat for formatting and caching */ - protected FormattedStringCache mFormattedStringCache; + protected FormattedStringCache.PrimFloat mFormattedStringCache; /** * the number of decimal digits this formatter uses @@ -35,14 +35,14 @@ public DefaultAxisValueFormatter(int digits) { b.append("0"); } - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0" + b.toString())); + mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0" + b.toString())); } @Override public String getFormattedValue(float value, AxisBase axis) { // TODO: There should be a better way to do this. Floats are not the best keys... - return mFormattedStringCache.getFormattedString(value, value); + return mFormattedStringCache.getFormattedValue(value); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java index 047af77571..cb0508b86e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.formatter; import java.text.Format; +import java.util.ArrayList; import java.util.HashMap; /** @@ -17,7 +18,7 @@ */ public class FormattedStringCache { - private Format mFormat; + protected Format mFormat; private HashMap mCachedStringsHashMap = new HashMap<>(); private HashMap mCachedValuesHashMap = new HashMap<>(); @@ -48,4 +49,81 @@ public String getFormattedString(V value, K key){ return result; } + public static class PrimIntFloat extends FormattedStringCache{ + + public PrimIntFloat(Format format){ + super(format); + } + + private ArrayList cachedValues = new ArrayList<>(); + private ArrayList cachedStrings = new ArrayList<>(); + + public String getFormattedValue(float value, int key) { + + boolean hasValueAtdataSetIndex = true; + if(cachedValues.size() <= key){ + int p = key; + while(p >= 0){ + if(p == 0){ + cachedValues.add(value); + cachedStrings.add(""); + }else{ + cachedValues.add(Float.NaN); + cachedStrings.add(""); + } + p--; + } + hasValueAtdataSetIndex = false; + } + + if(hasValueAtdataSetIndex) { + Float cachedValue = cachedValues.get(key); + hasValueAtdataSetIndex = !(cachedValue == null || cachedValue != value); + } + + if(!hasValueAtdataSetIndex){ + cachedValues.set(key, value); + cachedStrings.set(key, mFormat.format(value)); + } + + return cachedStrings.get(key); + } + + } + + public static class PrimFloat extends FormattedStringCache{ + + public PrimFloat(Format format){ + super(format); + } + + + private ArrayList cachedValues = new ArrayList<>(); + private ArrayList cachedStrings = new ArrayList<>(); + + public String getFormattedValue(float value) { + + boolean alreadyHasValue = false; + int vCount = cachedValues.size(); + int sIndex = -1; + for(int i = 0 ; i < vCount ; i++){ + if(cachedValues.get(i) == value){ + sIndex = i; + alreadyHasValue = true; + break; + } + } + if(!alreadyHasValue) { + cachedValues.add(value); + cachedStrings.add(mFormat.format(value)); + sIndex = cachedValues.size() - 1; + } + + return cachedStrings.get(sIndex); + } + + } + + + } From 7fd18d2177477d2d61d271bfe2ba87f90860d36b Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 17:48:31 -0700 Subject: [PATCH 1059/1390] Eliminate allocs - Buffer Paint.FontMetrics (#1892) paint.getFontMetrics() has a hidden allocation. paint.getFontMetrics(fontMetrics) is used internally inside of Paint, so caching and holding onto a metrics buffer helps reduce allocations. --- .../mikephil/charting/components/Legend.java | 9 +++++---- .../charting/renderer/LegendRenderer.java | 5 +++-- .../github/mikephil/charting/utils/Utils.java | 18 ++++++++++++++---- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index b66d93042e..d1b69e2b16 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -808,6 +808,8 @@ public FSize[] getCalculatedLineSizes() { return mCalculatedLineSizes; } + protected Paint.FontMetrics fontMetricsForCalculateDimensions = new Paint.FontMetrics(); + ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); /** * Calculates the dimensions of the Legend. This includes the maximum width * and height of a single entry, as well as the total width and height of @@ -815,7 +817,6 @@ public FSize[] getCalculatedLineSizes() { * * @param labelpaint */ - ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { mTextWidthMax = getMaximumEntryWidth(labelpaint); @@ -825,7 +826,7 @@ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandle case VERTICAL: { float maxWidth = 0f, maxHeight = 0f, width = 0f; - float labelLineHeight = Utils.getLineHeight(labelpaint); + float labelLineHeight = Utils.getLineHeight(labelpaint, fontMetricsForCalculateDimensions); final int count = mLabels.length; boolean wasStacked = false; @@ -878,8 +879,8 @@ else if (wasStacked) { case HORIZONTAL: { int labelCount = mLabels.length; - float labelLineHeight = Utils.getLineHeight(labelpaint); - float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace; + float labelLineHeight = Utils.getLineHeight(labelpaint, fontMetricsForCalculateDimensions); + float labelLineSpacing = Utils.getLineSpacing(labelpaint, fontMetricsForCalculateDimensions) + mYEntrySpace; float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent; // Prepare arrays for calculated layout diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 0add1004e0..4586d68e22 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -177,6 +177,7 @@ public void computeLegend(ChartData data) { mLegend.calculateDimensions(mLegendLabelPaint, mViewPortHandler); } + protected Paint.FontMetrics fontMetricsForRenderLegent = new Paint.FontMetrics(); public void renderLegend(Canvas c) { if (!mLegend.isEnabled()) @@ -190,8 +191,8 @@ public void renderLegend(Canvas c) { mLegendLabelPaint.setTextSize(mLegend.getTextSize()); mLegendLabelPaint.setColor(mLegend.getTextColor()); - float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint); - float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint) + mLegend.getYEntrySpace(); + float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint, fontMetricsForRenderLegent); + float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, fontMetricsForRenderLegent) + mLegend.getYEntrySpace(); float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f; String[] labels = mLegend.getLabels(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index eab4b881ff..8cf77e2de1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -165,13 +165,23 @@ public static int calcTextHeight(Paint paint, String demoText) { } public static float getLineHeight(Paint paint) { - Paint.FontMetrics metrics = paint.getFontMetrics(); - return metrics.descent - metrics.ascent; + Paint.FontMetrics metrics = new Paint.FontMetrics(); + return getLineHeight(paint, metrics); + } + + public static float getLineHeight(Paint paint, Paint.FontMetrics fontMetrics){ + paint.getFontMetrics(fontMetrics); + return fontMetrics.descent - fontMetrics.ascent; } public static float getLineSpacing(Paint paint) { - Paint.FontMetrics metrics = paint.getFontMetrics(); - return metrics.ascent - metrics.top + metrics.bottom; + Paint.FontMetrics metrics = new Paint.FontMetrics(); + return getLineSpacing(paint, metrics); + } + + public static float getLineSpacing(Paint paint, Paint.FontMetrics fontMetrics){ + paint.getFontMetrics(fontMetrics); + return fontMetrics.ascent - fontMetrics.top + fontMetrics.bottom; } /** From 69f17b2a79de4f06321d154b6050e2a6fc3d2d14 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Wed, 29 Jun 2016 18:30:21 -0700 Subject: [PATCH 1060/1390] Eliminate allocs - Buffer ArrayLists (#1892) Many short-lived ArrayLists were created in various methods, which could easily have been extracted to field level variable. This has been done, and the arrays cleared before use. --- .../RealtimeLineChartActivity.java | 17 ++++++++++------- .../github/mikephil/charting/charts/Chart.java | 18 ++++++++++++++++++ .../mikephil/charting/components/Legend.java | 2 +- .../mikephil/charting/data/BarDataSet.java | 4 +++- .../mikephil/charting/data/BaseDataSet.java | 11 +++++++++-- .../mikephil/charting/data/BubbleDataSet.java | 4 +++- .../mikephil/charting/data/CandleDataSet.java | 4 +++- .../mikephil/charting/data/CombinedData.java | 5 ++++- .../github/mikephil/charting/data/DataSet.java | 4 +++- .../mikephil/charting/data/LineDataSet.java | 18 ++++++++++++++---- .../charting/highlight/ChartHighlighter.java | 5 ++++- .../highlight/CombinedHighlighter.java | 5 ++++- .../charting/highlight/RadarHighlighter.java | 4 +++- .../renderer/CombinedChartRenderer.java | 12 +++++++++--- .../charting/renderer/LegendRenderer.java | 9 +++++++-- .../charting/renderer/LineChartRenderer.java | 10 ++++++++-- 16 files changed, 103 insertions(+), 29 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 5b8d3f6f3e..75675d1ac1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -176,19 +176,22 @@ private void feedMultiple() { if (thread != null) thread.interrupt(); + final Runnable runnable = new Runnable() { + + @Override + public void run() { + addEntry(); + } + }; + thread = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 1000; i++) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - addEntry(); - } - }); + // Don't generate garbage runnables inside the loop. + runOnUiThread(runnable); try { Thread.sleep(25); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 6807a57c08..69bdbd0a13 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -1442,6 +1442,24 @@ public List getEntriesAtIndex(int xIndex) { return vals; } + public void getEntriesAtIndex(int xIndex, List entriesOutput){ + + List vals = entriesOutput; + vals.clear(); + + for (int i = 0; i < mData.getDataSetCount(); i++) { + + IDataSet set = mData.getDataSetByIndex(i); + + Entry e = set.getEntryForXPos(xIndex); + + if (e != null) { + vals.add(e); + } + } + + } + /** * Returns the ChartData object that has been set for the chart. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index d1b69e2b16..b0b82bdc3e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -809,7 +809,7 @@ public FSize[] getCalculatedLineSizes() { } protected Paint.FontMetrics fontMetricsForCalculateDimensions = new Paint.FontMetrics(); - ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); + protected ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); /** * Calculates the dimensions of the Legend. This includes the maximum width * and height of a single entry, as well as the total width and height of diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 2802ebc4c2..8e78de3397 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -51,10 +51,12 @@ public BarDataSet(List yVals, String label) { calcEntryCountIncludingStacks(yVals); } + protected List barEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = new ArrayList(); + List yVals = barEntriesForCopy; + yVals.clear(); for (int i = 0; i < mValues.size(); i++) { yVals.add(mValues.get(i).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 19b06f9ce1..4f64c368f2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -166,7 +166,11 @@ public void setColors(int[] colors) { */ public void setColors(int[] colors, Context c) { - List clrs = new ArrayList(); + if(mColors == null){ + mColors = new ArrayList<>(); + } + List clrs = mColors; + clrs.clear(); for (int color : colors) { clrs.add(c.getResources().getColor(color)); @@ -224,7 +228,10 @@ public void setColors(int[] colors, int alpha) { * Resets all colors of this DataSet and recreates the colors array. */ public void resetColors() { - mColors = new ArrayList(); + if(mColors == null) { + mColors = new ArrayList(); + } + mColors.clear(); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index ec288123e2..3c2858fbf7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -51,10 +51,12 @@ public void calcMinMax() { } } + protected ArrayList bubbleEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = new ArrayList(); + List yVals = bubbleEntriesForCopy; + yVals.clear(); for (int i = 0; i < mValues.size(); i++) { yVals.add(mValues.get(i).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 5288d7e3a6..8af41c7a80 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -77,10 +77,12 @@ public CandleDataSet(List yVals, String label) { super(yVals, label); } + protected ArrayList candleEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = new ArrayList(); + List yVals = candleEntriesForCopy; + yVals.clear(); for (int i = 0; i < mValues.size(); i++) { yVals.add(((CandleEntry) mValues.get(i)).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 37ab1e4bdb..2c650269b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -57,7 +57,10 @@ public void setData(BubbleData data) { @Override public void calcMinMax() { - mDataSets = new ArrayList<>(); + if(mDataSets == null){ + mDataSets = new ArrayList<>(); + } + mDataSets.clear(); mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 42571e95de..84cf7c8bcb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -295,6 +295,7 @@ public int getEntryIndex(float xPos, Rounding rounding) { return high; } + protected ArrayList entriesForGetEntriesForXPos = new ArrayList<>(2); /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical @@ -306,7 +307,8 @@ public int getEntryIndex(float xPos, Rounding rounding) { @Override public List getEntriesForXPos(float xVal) { - List entries = new ArrayList(); + List entries = entriesForGetEntriesForXPos; + entries.clear(); int low = 0; int high = mValues.size() - 1; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 2b802d9c28..0110ecd234 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -52,8 +52,11 @@ public LineDataSet(List yVals, String label) { // mCircleRadius = Utils.convertDpToPixel(4f); // mLineWidth = Utils.convertDpToPixel(1f); - mCircleColors = new ArrayList(); - + if(mCircleColors == null) { + mCircleColors = new ArrayList(); + } + mCircleColors.clear(); + // default colors // mColors.add(Color.rgb(192, 255, 140)); // mColors.add(Color.rgb(255, 247, 140)); @@ -294,7 +297,11 @@ public void setCircleColors(int[] colors) { */ public void setCircleColors(int[] colors, Context c) { - List clrs = new ArrayList(); + List clrs = mCircleColors; + if(clrs == null){ + clrs = new ArrayList<>(); + } + clrs.clear(); for (int color : colors) { clrs.add(c.getResources().getColor(color)); @@ -318,7 +325,10 @@ public void setCircleColor(int color) { * resets the circle-colors array and creates a new one */ public void resetCircleColors() { - mCircleColors = new ArrayList(); + if(mCircleColors == null) { + mCircleColors = new ArrayList(); + } + mCircleColors.clear(); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 90d74b26e9..4f96edfce4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -110,6 +110,8 @@ protected float getHighlightPos(Highlight h) { return h.getYPx(); } + + protected ArrayList highlightsForGetHighlightsAtXPos = new ArrayList<>(2); /** * Returns a list of Highlight objects representing the entries closest to the given xVal. * The returned list contains two objects per DataSet (closest rounding up, closest rounding down). @@ -121,7 +123,8 @@ protected float getHighlightPos(Highlight h) { */ protected List getHighlightsAtXPos(float xVal, float x, float y) { - List vals = new ArrayList(); + List vals = highlightsForGetHighlightsAtXPos; + vals.clear(); BarLineScatterCandleBubbleData data = getData(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index c9ba0b4e6d..d948cedf7c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -28,10 +28,13 @@ public CombinedHighlighter(CombinedDataProvider chart, BarDataProvider barChart) barHighlighter = barChart.getBarData() == null ? null : new BarHighlighter(barChart); } + + protected ArrayList highlightsForGetHighlightsAtXPos = new ArrayList<>(2); @Override protected List getHighlightsAtXPos(float xVal, float x, float y) { - List vals = new ArrayList(); + List vals = highlightsForGetHighlightsAtXPos; + vals.clear(); List dataObjects = mChart.getCombinedData().getAllData(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java index c322980b89..cb0048c477 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -44,6 +44,7 @@ protected Highlight getClosestHighlight(int index, float x, float y) { return closest; } + protected ArrayList highlightsForGetHighlightsAtIndex = new ArrayList<>(2); /** * Returns an array of Highlight objects for the given index. The Highlight * objects give information about the value at the selected index and the @@ -55,7 +56,8 @@ protected Highlight getClosestHighlight(int index, float x, float y) { */ protected List getHighlightsAtIndex(int index) { - List vals = new ArrayList(); + List vals = highlightsForGetHighlightsAtIndex; + vals.clear(); float phaseX = mChart.getAnimator().getPhaseX(); float phaseY = mChart.getAnimator().getPhaseY(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 1f79868185..f6c671d1cf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -33,6 +33,7 @@ public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPo createRenderers(chart, animator, viewPortHandler); } + protected ArrayList renderersForCreateRenderers = new ArrayList<>(4); /** * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into * consideration. @@ -43,7 +44,8 @@ public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPo */ protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { - mRenderers = new ArrayList(); + mRenderers = renderersForCreateRenderers; + mRenderers.clear(); DrawOrder[] orders = chart.getDrawOrder(); @@ -102,6 +104,7 @@ public void drawExtras(Canvas c) { renderer.drawExtras(c); } + protected ArrayList highlightsforDrawHighlighted = new ArrayList<>(); @Override public void drawHighlighted(Canvas c, Highlight[] indices) { @@ -125,8 +128,11 @@ else if (renderer instanceof BubbleChartRenderer) int dataIndex = data == null ? -1 : ((CombinedData)chart.getData()).getAllData().indexOf(data); - ArrayList dataIndices = new ArrayList<>(); - for (Highlight h : indices) { + ArrayList dataIndices = highlightsforDrawHighlighted; + dataIndices.clear(); + Highlight h; + for(int i = 0 ; i < dataIndices.size() ; i++){ + h = dataIndices.get(i); if (h.getDataIndex() == dataIndex || h.getDataIndex() == -1) dataIndices.add(h); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 4586d68e22..fb8937a303 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -70,6 +70,8 @@ public Paint getFormPaint() { return mLegendFormPaint; } + protected ArrayList labelsForComputeLegend = new ArrayList<>(16); + protected ArrayList colorsForComputeLegend = new ArrayList<>(16); /** * Prepares the legend and calculates all needed forms, labels and colors. * @@ -79,8 +81,11 @@ public void computeLegend(ChartData data) { if (!mLegend.isLegendCustom()) { - List labels = new ArrayList(); - List colors = new ArrayList(); + ArrayList labels = labelsForComputeLegend; + ArrayList colors = colorsForComputeLegend; + + labels.clear(); + colors.clear(); // loop for building up the colors and labels used in the legend for (int i = 0; i < data.getDataSetCount(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9c92b9db52..f44739dc8c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -573,6 +573,7 @@ public void drawExtras(Canvas c) { private Path mCirclePathBuffer = new Path(); private float[] mCirclesBuffer = new float[2]; private HashMap mImageCaches = new HashMap<>(); + private XBounds mXBoundsBuffer; protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); @@ -607,8 +608,13 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(mChart, dataSet); - int entryCount = dataSet.getEntryCount(); + if(mXBoundsBuffer == null) { + mXBoundsBuffer = getXBounds(mChart, dataSet); + }else{ + mXBoundsBuffer.set(mChart,dataSet); + } + + XBounds bounds = mXBoundsBuffer; float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); From afdbd2c5f0fad23d255f8811ae756748717ff35a Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 11:30:39 -0700 Subject: [PATCH 1061/1390] Eliminate allocs - Tests for StringCache (#1892) Created unit tests for the FormattedStringCache classes. Also, took this opportunity to create a FormattedStringCache.Generic static class to take over what was previously simply FormattedStringCache. Verified that all unit tests still pass. --- .../mpchartexample/LineChartTime.java | 4 +- .../StackedBarActivityNegative.java | 17 +- .../custom/MyAxisValueFormatter.java | 6 +- .../custom/MyCustomXAxisValueFormatter.java | 6 +- .../custom/MyValueFormatter.java | 6 +- .../custom/RadarMarkerView.java | 4 +- .../formatter/DefaultValueFormatter.java | 6 +- .../formatter/FormattedStringCache.java | 105 ++++- .../formatter/LargeValueFormatter.java | 6 +- .../charting/formatter/PercentFormatter.java | 16 +- .../formatter/StackedValueFormatter.java | 12 +- .../test/FormattedStringCacheTest.java | 433 ++++++++++++++++++ 12 files changed, 559 insertions(+), 62 deletions(-) create mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index c7893188a3..77f9ecb834 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -92,12 +92,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(60000L); // one minute in millis xAxis.setValueFormatter(new AxisValueFormatter() { - private FormattedStringCache mFormattedStringCache = new FormattedStringCache(new SimpleDateFormat("dd MMM HH:mm")); + private FormattedStringCache.Generic mFormattedStringCache = new FormattedStringCache.Generic<>(new SimpleDateFormat("dd MMM HH:mm")); @Override public String getFormattedValue(float value, AxisBase axis) { Long v = (long) value; - return mFormattedStringCache.getFormattedString(new Date(v), v); + return mFormattedStringCache.getFormattedValue(new Date(v), v); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index b1a54cbef1..4f0e16f5fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -80,12 +80,11 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(10f); xAxis.setValueFormatter(new AxisValueFormatter() { - private FormattedStringCache format = new FormattedStringCache(new DecimalFormat("###")); + private FormattedStringCache.PrimFloat format = new FormattedStringCache.PrimFloat(new DecimalFormat("###")); @Override public String getFormattedValue(float value, AxisBase axis) { - Float key = value + 10; - return format.getFormattedString(value, value) + "-" + format.getFormattedString(value, key); + return format.getFormattedValue(value) + "-" + format.getFormattedValue(value+10); } @Override @@ -224,25 +223,25 @@ public void onNothingSelected() { private class CustomFormatter implements ValueFormatter, AxisValueFormatter { - private FormattedStringCache mFormatValue; - private FormattedStringCache mFormatAxis; + private FormattedStringCache.Generic mFormatValue; + private FormattedStringCache.PrimFloat mFormatAxis; public CustomFormatter() { - mFormatValue = new FormattedStringCache<>(new DecimalFormat("###")); - mFormatAxis = new FormattedStringCache<>(new DecimalFormat("###")); + mFormatValue = new FormattedStringCache.Generic<>(new DecimalFormat("###")); + mFormatAxis = new FormattedStringCache.PrimFloat(new DecimalFormat("###")); } // data @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormatValue.getFormattedString(value, dataSetIndex) + "m"; + return mFormatValue.getFormattedValue(value, dataSetIndex) + "m"; } // YAxis @Override public String getFormattedValue(float value, AxisBase axis) { Float v = Math.abs(value); - return mFormatAxis.getFormattedString(v,v) + "m"; + return mFormatAxis.getFormattedValue(v) + "m"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index 06197d7508..2eeff56971 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -9,15 +9,15 @@ public class MyAxisValueFormatter implements AxisValueFormatter { private DecimalFormat mFormat; - private FormattedStringCache mFormattedStringCache; + private FormattedStringCache.PrimFloat mFormattedStringCache; public MyAxisValueFormatter() { - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); + mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0.0")); } @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormattedStringCache.getFormattedString(value, value) + " $"; + return mFormattedStringCache.getFormattedValue(value) + " $"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index f2018bcdd4..9b5f4c921c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -12,13 +12,13 @@ */ public class MyCustomXAxisValueFormatter implements AxisValueFormatter { - private FormattedStringCache mFormattedStringCache; + private FormattedStringCache.PrimFloat mFormattedStringCache; private ViewPortHandler mViewPortHandler; public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { mViewPortHandler = viewPortHandler; // maybe do something here or provide parameters in constructor - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); + mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0.0")); } @Override @@ -35,7 +35,7 @@ else if (xScale > 3) else if (xScale > 1) return "2"; else - return mFormattedStringCache.getFormattedString(value, value); + return mFormattedStringCache.getFormattedValue(value); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index 87cf28f4c3..5ca05d92de 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -9,14 +9,14 @@ public class MyValueFormatter implements ValueFormatter { - private FormattedStringCache mFormattedStringCache; + private FormattedStringCache.Generic mFormattedStringCache; public MyValueFormatter() { - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0.0")); + mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0.0")); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedString(value, dataSetIndex) + " $"; + return mFormattedStringCache.getFormattedValue(value, dataSetIndex) + " $"; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index b02212d89a..61f7209e44 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -23,7 +23,7 @@ public class RadarMarkerView extends MarkerView { private TextView tvContent; - private FormattedStringCache mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("##0")); + private FormattedStringCache.PrimFloat mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("##0")); public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); @@ -37,7 +37,7 @@ public RadarMarkerView(Context context, int layoutResource) { @Override public void refreshContent(Entry e, Highlight highlight) { float value = e.getY(); - tvContent.setText(mFormattedStringCache.getFormattedString(value, value) + " %"); + tvContent.setText(mFormattedStringCache.getFormattedValue(value) + " %"); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 039787113c..b6965435aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -17,7 +17,7 @@ public class DefaultValueFormatter implements ValueFormatter { /** * FormattedStringCache for formatting and caching. */ - protected FormattedStringCache mFormattedStringCache; + protected FormattedStringCache.Generic mFormattedStringCache; protected int mDecimalDigits; @@ -47,14 +47,14 @@ public void setup(int digits) { b.append("0"); } - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,###,##0" + b.toString())); + mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedString(value, dataSetIndex); + return mFormattedStringCache.getFormattedValue(value, dataSetIndex); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java index cb0508b86e..c6b4ef3e6f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java @@ -16,11 +16,9 @@ * Possibly want to make some explicit primitive enabled caches, though they can be ugly. * */ -public class FormattedStringCache { +public class FormattedStringCache { protected Format mFormat; - private HashMap mCachedStringsHashMap = new HashMap<>(); - private HashMap mCachedValuesHashMap = new HashMap<>(); public Format getFormat(){ return mFormat; @@ -30,25 +28,53 @@ public FormattedStringCache(Format format){ this.mFormat = format; } - public String getFormattedString(V value, K key){ - // If we can't find the value at all, create an entry for it, and format the string. - if(!mCachedValuesHashMap.containsKey(key)){ - mCachedStringsHashMap.put(key, mFormat.format(value)); - mCachedValuesHashMap.put(key, value); - } + /** + * Cache a Formatted String, derived from formatting value V in the Format passed to the constructor. + * Use the object K as a way to quickly look up the string in the cache. + * If value of V has changed since the last time the cache was accessed, re-format the string. + * + * NOTE: This version relies on auto-boxing of primitive values. As a result, it has worse memory performance + * than the Prim versions. + * + * @param + * @param + */ + public static class Generic extends FormattedStringCache{ + + private HashMap mCachedStringsHashMap = new HashMap<>(); + private HashMap mCachedValuesHashMap = new HashMap<>(); - // If the old value and the new one don't match, format the string and store it, because the string's value will be different now. - if(!value.equals(mCachedValuesHashMap.get(key))){ - mCachedStringsHashMap.put(key, mFormat.format(value)); - mCachedValuesHashMap.put(key, value); + public Generic(Format format){ + super(format); } - String result = mCachedStringsHashMap.get(key); + public String getFormattedValue(V value, K key){ + + // If we can't find the value at all, create an entry for it, and format the string. + if(!mCachedValuesHashMap.containsKey(key)){ + mCachedStringsHashMap.put(key, mFormat.format(value)); + mCachedValuesHashMap.put(key, value); + } - return result; + // If the old value and the new one don't match, format the string and store it, because the string's value will be different now. + if(!value.equals(mCachedValuesHashMap.get(key))){ + mCachedStringsHashMap.put(key, mFormat.format(value)); + mCachedValuesHashMap.put(key, value); + } + + String result = mCachedStringsHashMap.get(key); + + return result; + } } + /** + * Cache a Formatted String, derived from formatting float value in the Format passed to the constructor. + * Use the integer as a way to quickly look up the string in the cache. + * If value of V has changed since the last time the cache was accessed, re-format the string. + * + */ public static class PrimIntFloat extends FormattedStringCache{ public PrimIntFloat(Format format){ @@ -91,6 +117,9 @@ public String getFormattedValue(float value, int key) { } + /** + * Cache a Formatted String, derived from formatting float value in the Format passed to the constructor. + */ public static class PrimFloat extends FormattedStringCache{ public PrimFloat(Format format){ @@ -113,11 +142,47 @@ public String getFormattedValue(float value) { break; } } - if(!alreadyHasValue) { - cachedValues.add(value); - cachedStrings.add(mFormat.format(value)); - sIndex = cachedValues.size() - 1; - } + if(!alreadyHasValue) { + cachedValues.add(value); + cachedStrings.add(mFormat.format(value)); + sIndex = cachedValues.size() - 1; + } + + return cachedStrings.get(sIndex); + } + + } + + /** + * Cache a Formatted String, derived from formatting double value in the Format passed to the constructor. + */ + public static class PrimDouble extends FormattedStringCache{ + + public PrimDouble(Format format){ + super(format); + } + + + private ArrayList cachedValues = new ArrayList<>(); + private ArrayList cachedStrings = new ArrayList<>(); + + public String getFormattedValue(double value) { + + boolean alreadyHasValue = false; + int vCount = cachedValues.size(); + int sIndex = -1; + for(int i = 0 ; i < vCount ; i++){ + if(cachedValues.get(i) == value){ + sIndex = i; + alreadyHasValue = true; + break; + } + } + if(!alreadyHasValue) { + cachedValues.add(value); + cachedStrings.add(mFormat.format(value)); + sIndex = cachedValues.size() - 1; + } return cachedStrings.get(sIndex); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 5679c9a2aa..4e6e77a6bf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -29,10 +29,10 @@ public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { /** * FormattedStringCache for formatting and caching. */ - protected FormattedStringCache mFormattedStringCache; + protected FormattedStringCache.PrimDouble mFormattedStringCache; public LargeValueFormatter() { - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###E00")); + mFormattedStringCache = new FormattedStringCache.PrimDouble(new DecimalFormat("###E00")); } /** @@ -83,7 +83,7 @@ public void setSuffix(String[] suff) { private String makePretty(double number) { // TODO : Should be better way to do this. Double isn't the best key... - String r = mFormattedStringCache.getFormattedString(number,number); + String r = mFormattedStringCache.getFormattedValue(number); int numericValue1 = Character.getNumericValue(r.charAt(r.length() - 1)); int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 890eb681cc..1ad1ba1c0d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -15,12 +15,12 @@ */ public class PercentFormatter implements ValueFormatter, AxisValueFormatter { - protected FormattedStringCache mFormattedStringCache; - protected FormattedStringCache mFormattedStringCacheAxis; + protected FormattedStringCache.Generic mFormattedStringCache; + protected FormattedStringCache.PrimFloat mFormattedStringCacheAxis; public PercentFormatter() { - mFormattedStringCache = new FormattedStringCache<>(new DecimalFormat("###,###,##0.0")); - mFormattedStringCacheAxis = new FormattedStringCache<>(new DecimalFormat("###,###,##0.0")); + mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,##0.0")); + mFormattedStringCacheAxis = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,##0.0")); } /** @@ -29,21 +29,21 @@ public PercentFormatter() { * @param format */ public PercentFormatter(DecimalFormat format) { - mFormattedStringCache = new FormattedStringCache<>(format); - mFormattedStringCacheAxis = new FormattedStringCache<>(format); + mFormattedStringCache = new FormattedStringCache.Generic<>(format); + mFormattedStringCacheAxis = new FormattedStringCache.PrimFloat(format); } // ValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedString(value, dataSetIndex) + " %"; + return mFormattedStringCache.getFormattedValue(value, dataSetIndex) + " %"; } // AxisValueFormatter @Override public String getFormattedValue(float value, AxisBase axis) { // TODO: Find a better way to do this. Float isn't the best key... - return mFormattedStringCacheAxis.getFormattedString(value, value) + " %"; + return mFormattedStringCacheAxis.getFormattedValue(value) + " %"; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 97cc589528..618b1b1fe4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -18,8 +18,8 @@ public class StackedValueFormatter implements ValueFormatter { * if true, all stack values of the stacked bar entry are drawn, else only top */ private boolean mDrawWholeStack; - private FormattedStringCache mFormattedStringCacheWholeStack; - private FormattedStringCache mFormattedStringCache; + private FormattedStringCache.Generic mFormattedStringCacheWholeStack; + private FormattedStringCache.Generic mFormattedStringCache; /** @@ -47,14 +47,14 @@ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decima b.append("0"); } - this.mFormattedStringCache = new FormattedStringCache(new DecimalFormat("###,###,###,##0" + b.toString())); - this.mFormattedStringCacheWholeStack = new FormattedStringCache(new DecimalFormat("###,###,###,##0" + b.toString())); + this.mFormattedStringCache = new FormattedStringCache.Generic(new DecimalFormat("###,###,###,##0" + b.toString())); + this.mFormattedStringCacheWholeStack = new FormattedStringCache.Generic(new DecimalFormat("###,###,###,##0" + b.toString())); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - FormattedStringCache chosenCache = mFormattedStringCache; + FormattedStringCache.Generic chosenCache = mFormattedStringCache; int chosenIndex = dataSetIndex; float chosenValue = value; if (!mDrawWholeStack && entry instanceof BarEntry) { @@ -79,6 +79,6 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View } // return the "proposed" value - return chosenCache.getFormattedString(chosenValue, chosenIndex) + mAppendix; + return chosenCache.getFormattedValue(chosenValue, chosenIndex) + mAppendix; } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java new file mode 100644 index 0000000000..bd33008ea6 --- /dev/null +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java @@ -0,0 +1,433 @@ +package com.github.mikephil.charting.test; + +import com.github.mikephil.charting.formatter.FormattedStringCache; + +import junit.framework.Assert; + +import org.junit.Test; + +import java.text.DecimalFormat; + +/** + * Created by Tony Patino on 6/30/16. + */ +public class FormattedStringCacheTest { + + @Test + public void testPrimFloat(){ + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.PrimFloat cache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + s = cache.getFormattedValue(1.0f); + + Assert.assertEquals("1.00", s); + + s = cache.getFormattedValue(1.0f); + + Assert.assertEquals("1.00", s); + + + s = cache.getFormattedValue(1.3f); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.0f); + + Assert.assertEquals("1.00", s); + + for(int i = 0 ; i < 100 ; i++){ + float f = 0.75f + i; + s = cache.getFormattedValue(f); + Assert.assertEquals(i+".75", s); + } + + + s = cache.getFormattedValue(1.5323234f); + Assert.assertEquals("1.53", s); + + + s = cache.getFormattedValue(1.31f); + Assert.assertEquals("1.31", s); + + s = cache.getFormattedValue(1.3111111f); + Assert.assertEquals("1.31", s); + + } + + @Test + public void testPrimDouble(){ + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.PrimDouble cache = new FormattedStringCache.PrimDouble(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + s = cache.getFormattedValue(1.0d); + + Assert.assertEquals("1.00", s); + + s = cache.getFormattedValue(1.0d); + + Assert.assertEquals("1.00", s); + + + s = cache.getFormattedValue(1.3d); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3d); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.0d); + + Assert.assertEquals("1.00", s); + + for(int i = 0 ; i < 100 ; i++){ + double f = 0.75f + i; + s = cache.getFormattedValue(f); + Assert.assertEquals(i+".75", s); + } + + + s = cache.getFormattedValue(1.5323234d); + Assert.assertEquals("1.53", s); + + + s = cache.getFormattedValue(1.31d); + Assert.assertEquals("1.31", s); + + s = cache.getFormattedValue(1.3111111d); + Assert.assertEquals("1.31", s); + + } + + @Test + public void testPrimIntFloat(){ + + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.PrimIntFloat cache = new FormattedStringCache.PrimIntFloat(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + s = cache.getFormattedValue(1.0f, 0); + + Assert.assertEquals("1.00", s); + + s = cache.getFormattedValue(1.0f, 0); + + Assert.assertEquals("1.00", s); + + + s = cache.getFormattedValue(1.3f ,1); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 1); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 0); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.0f, 1); + + Assert.assertEquals("1.00", s); + + for(int i = 0 ; i < 100 ; i++){ + float f = 0.75f + i; + s = cache.getFormattedValue(f, i); + Assert.assertEquals(i+".75", s); + } + + + s = cache.getFormattedValue(1.5323234f, 200); + Assert.assertEquals("1.53", s); + + + s = cache.getFormattedValue(1.31f, 300); + Assert.assertEquals("1.31", s); + + s = cache.getFormattedValue(1.3111111f, 300); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 400); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 500); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 5000); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 0); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 1); + Assert.assertEquals("1.31", s); + } + + @Test + public void testGenericKV(){ + + this.genericIntFloat(); + this.genericDoubleFloat(); + this.genericObjectFloat(); + } + + private void genericObjectFloat() { + + + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + + Object obj0 = new Object(); + Object obj1 = new Object(); + Object obj2 = new Object(); + + s = cache.getFormattedValue(10f, obj0); + + Assert.assertEquals("10.00", s); + + + s = cache.getFormattedValue(10f, obj0); + + Assert.assertEquals("10.00", s); + + + s = cache.getFormattedValue(11f, obj1); + + Assert.assertEquals("11.00", s); + + s = cache.getFormattedValue(10f, obj2); + + Assert.assertEquals("10.00", s); + + + s = cache.getFormattedValue(11f, obj0); + + Assert.assertEquals("11.00", s); + + + } + + private void genericDoubleFloat() { + + + + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + s = cache.getFormattedValue(1.0f, 0d); + + Assert.assertEquals("1.00", s); + + s = cache.getFormattedValue(1.0f, 0d); + + Assert.assertEquals("1.00", s); + + + s = cache.getFormattedValue(1.3f ,1d); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 1d); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 0d); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.0f, 1d); + + Assert.assertEquals("1.00", s); + + for(int i = 0 ; i < 100 ; i++){ + float f = 0.75f + i; + s = cache.getFormattedValue(f, (double)i); + Assert.assertEquals(i+".75", s); + } + + + s = cache.getFormattedValue(1.5323234f, 200d); + Assert.assertEquals("1.53", s); + + + s = cache.getFormattedValue(1.31f, 300d); + Assert.assertEquals("1.31", s); + + s = cache.getFormattedValue(1.3111111f, 300d); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 400d); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 500d); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 5000d); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 0d); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 1d); + Assert.assertEquals("1.31", s); + + } + + private void genericIntFloat() { + + + int digits = 2; + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); + + String s = null; + + s = cache.getFormattedValue(1.0f, 0); + + Assert.assertEquals("1.00", s); + + s = cache.getFormattedValue(1.0f, 0); + + Assert.assertEquals("1.00", s); + + + s = cache.getFormattedValue(1.3f ,1); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 1); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.3f, 0); + + Assert.assertEquals("1.30", s); + + + s = cache.getFormattedValue(1.0f, 1); + + Assert.assertEquals("1.00", s); + + for(int i = 0 ; i < 100 ; i++){ + float f = 0.75f + i; + s = cache.getFormattedValue(f, i); + Assert.assertEquals(i+".75", s); + } + + + s = cache.getFormattedValue(1.5323234f, 200); + Assert.assertEquals("1.53", s); + + + s = cache.getFormattedValue(1.31f, 300); + Assert.assertEquals("1.31", s); + + s = cache.getFormattedValue(1.3111111f, 300); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 400); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 500); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.3111111f, 5000); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 0); + Assert.assertEquals("1.31", s); + + + s = cache.getFormattedValue(1.31f, 1); + Assert.assertEquals("1.31", s); + } + +} From b037f55d732e37d2a5c466ce72b4ff36777f6cd5 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 15:29:40 -0700 Subject: [PATCH 1062/1390] Eliminate allocs - XAxisRender array (#1892) Found an array that was instantiated frequently without need. Placed bounds on its instantiation. --- .../github/mikephil/charting/renderer/XAxisRenderer.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 805bdadf8c..ef37a3a069 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -180,12 +180,12 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - if(mDrawLabelsBuffer.length != mAxis.mEntryCount * 2){ + if(mDrawLabelsBuffer.length < mAxis.mEntryCount * 2){ mDrawLabelsBuffer = new float[mXAxis.mEntryCount * 2]; } float[] positions = mDrawLabelsBuffer; - for (int i = 0; i < positions.length; i += 2) { + for (int i = 0; i < positions.length && i < mXAxis.mEntries.length / 2 && i < mXAxis.mCenteredEntries.length / 2 ; i += 2) { // only fill x values if (centeringEnabled) { @@ -199,7 +199,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { mTrans.pointValuesToPixel(positions); - for (int i = 0; i < positions.length; i += 2) { + for (int i = 0; i < positions.length && i < mXAxis.mEntries.length / 2 && i < mXAxis.mCenteredEntries.length / 2 ; i += 2) { float x = positions[i]; From 5a18d0ef225ccf07acbc36cef259ffbdf31ed0ca Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 15:30:45 -0700 Subject: [PATCH 1063/1390] Eliminate allocs - Adjust pool replenishing (#1892) Replenish fewer objects in utils pools when empty, in case the pool size grows large. --- .../src/main/java/com/github/mikephil/charting/utils/FSize.java | 1 + .../main/java/com/github/mikephil/charting/utils/MPPointF.java | 1 + .../src/main/java/com/github/mikephil/charting/utils/PointD.java | 1 + 3 files changed, 3 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index 89bf6a9a80..ecb8c2e312 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -18,6 +18,7 @@ public final class FSize extends ObjectPool.Poolable{ static { pool = ObjectPool.create(256, new FSize(0,0)); + pool.setReplenishPercentage(0.5f); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java index 84f5850862..f2e6c71fea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java @@ -16,6 +16,7 @@ public class MPPointF extends ObjectPool.Poolable { static { pool = ObjectPool.create(32, new MPPointF(0,0)); + pool.setReplenishPercentage(0.5f); } private MPPointF(float x, float y){ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java index ed5ae61e72..c69c4da7d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java @@ -14,6 +14,7 @@ public class PointD extends ObjectPool.Poolable { static { pool = ObjectPool.create(64, new PointD(0,0)); + pool.setReplenishPercentage(0.5f); } public static PointD getInstance(double x, double y){ From 38fbefe66b5f91f6723818073d0acfc8b461aa2f Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 15:33:02 -0700 Subject: [PATCH 1064/1390] Eliminate allocs - Move and Zoom Job Pools (#1892) Create object pools for the Zoom, move, and animation jobs. Their constructors remain public, to make this easier to roll back from if needed. --- .../charting/charts/BarLineChartBase.java | 18 +++---- .../charting/jobs/AnimatedMoveViewJob.java | 37 +++++++++++++++ .../charting/jobs/AnimatedViewPortJob.java | 47 ++++++++++++++++++- .../charting/jobs/AnimatedZoomJob.java | 31 ++++++++++++ .../mikephil/charting/jobs/MoveViewJob.java | 29 ++++++++++++ .../mikephil/charting/jobs/ViewPortJob.java | 4 +- .../mikephil/charting/jobs/ZoomJob.java | 32 +++++++++++++ 7 files changed, 187 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 642c61e7c9..f734a59e71 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -9,7 +9,6 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; -import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; @@ -664,7 +663,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { */ public void zoomAndCenter(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { - Runnable job = new ZoomJob(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); + Runnable job = ZoomJob.getInstance(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); addViewportJob(job); } @@ -686,7 +685,7 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - Runnable job = new AnimatedZoomJob(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis + Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); @@ -800,6 +799,7 @@ public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency ax mViewPortHandler.setMinMaxScaleY(minScale, maxScale); } + /** * Moves the left side of the current viewport to the specified x-position. * This also refreshes the chart by calling invalidate(). @@ -808,7 +808,7 @@ public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency ax */ public void moveViewToX(float xValue) { - Runnable job = new MoveViewJob(mViewPortHandler, xValue, 0f, + Runnable job = MoveViewJob.getInstance(mViewPortHandler, xValue, 0f, getTransformer(AxisDependency.LEFT), this); addViewportJob(job); @@ -827,7 +827,7 @@ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new MoveViewJob(mViewPortHandler, xValue, yValue + yInView / 2f, + Runnable job = MoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this); addViewportJob(job); @@ -852,7 +852,7 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, xValue, yValue + yInView / 2f, + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); addViewportJob(job); @@ -874,7 +874,7 @@ public void centerViewToY(float yValue, AxisDependency axis) { float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); - Runnable job = new MoveViewJob(mViewPortHandler, 0f, yValue + valsInView / 2f, + Runnable job = MoveViewJob.getInstance(mViewPortHandler, 0f, yValue + valsInView / 2f, getTransformer(axis), this); addViewportJob(job); @@ -894,7 +894,7 @@ public void centerViewTo(float xValue, float yValue, AxisDependency axis) { float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); - Runnable job = new MoveViewJob(mViewPortHandler, + Runnable job = MoveViewJob.getInstance(mViewPortHandler, xValue - xInView / 2f, yValue + yInView / 2f, getTransformer(axis), this); @@ -920,7 +920,7 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); - Runnable job = new AnimatedMoveViewJob(mViewPortHandler, + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue - xInView / 2f, yValue + yInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java index 128fdea36f..00bddc2427 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java @@ -5,14 +5,42 @@ import android.annotation.SuppressLint; import android.view.View; +import com.github.mikephil.charting.utils.ObjectPool; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; /** * Created by Philipp Jahoda on 19/02/16. */ +@SuppressLint("NewApi") public class AnimatedMoveViewJob extends AnimatedViewPortJob { + private static ObjectPool pool; + + static { + pool = ObjectPool.create(4, new AnimatedMoveViewJob(null,0,0,null,null,0,0,0)); + pool.setReplenishPercentage(0.5f); + } + + public static AnimatedMoveViewJob getInstance(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration){ + AnimatedMoveViewJob result = pool.get(); + result.mViewPortHandler = viewPortHandler; + result.xValue = xValue; + result.yValue = yValue; + result.mTrans = trans; + result.view = v; + result.xOrigin = xOrigin; + result.yOrigin = yOrigin; + result.resetAnimator(); + result.animator.setDuration(duration); + return result; + } + + public static void recycleInstance(AnimatedMoveViewJob instance){ + pool.recycle(instance); + } + + public AnimatedMoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v, float xOrigin, float yOrigin, long duration) { super(viewPortHandler, xValue, yValue, trans, v, xOrigin, yOrigin, duration); } @@ -26,4 +54,13 @@ public void onAnimationUpdate(ValueAnimator animation) { mTrans.pointValuesToPixel(pts); mViewPortHandler.centerViewPort(pts, view); } + + public void recycleSelf(){ + recycleInstance(this); + } + + @Override + protected ObjectPool.Poolable instantiate() { + return new AnimatedMoveViewJob(null,0,0,null,null,0,0,0); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java index ea17745ee8..f8b520a419 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedViewPortJob.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.jobs; +import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; @@ -12,7 +13,7 @@ * Created by Philipp Jahoda on 19/02/16. */ @SuppressLint("NewApi") -public abstract class AnimatedViewPortJob extends ViewPortJob implements ValueAnimator.AnimatorUpdateListener { +public abstract class AnimatedViewPortJob extends ViewPortJob implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener { protected ObjectAnimator animator; @@ -28,6 +29,7 @@ public AnimatedViewPortJob(ViewPortHandler viewPortHandler, float xValue, float animator = ObjectAnimator.ofFloat(this, "phase", 0f, 1f); animator.setDuration(duration); animator.addUpdateListener(this); + animator.addListener(this); } @SuppressLint("NewApi") @@ -51,4 +53,47 @@ public float getXOrigin() { public float getYOrigin() { return yOrigin; } + + public abstract void recycleSelf(); + + protected void resetAnimator(){ + animator.removeAllListeners(); + animator.removeAllUpdateListeners(); + animator.reverse(); + animator.addUpdateListener(this); + animator.addListener(this); + } + + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + try{ + recycleSelf(); + }catch (IllegalArgumentException e){ + // don't worry about it. + } + } + + @Override + public void onAnimationCancel(Animator animation) { + try{ + recycleSelf(); + }catch (IllegalArgumentException e){ + // don't worry about it. + } + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index be61ce09f3..0157e8fa76 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.utils.ObjectPool; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,6 +18,26 @@ @SuppressLint("NewApi") public class AnimatedZoomJob extends AnimatedViewPortJob implements Animator.AnimatorListener { + private static ObjectPool pool; + + static { + pool = ObjectPool.create(8, new AnimatedZoomJob(null,null,null,null,0,0,0,0,0,0,0,0,0,0)); + } + + public static AnimatedZoomJob getInstance(ViewPortHandler viewPortHandler, View v, Transformer trans, YAxis axis, float xAxisRange, float scaleX, float scaleY, float xOrigin, float yOrigin, float zoomCenterX, float zoomCenterY, float zoomOriginX, float zoomOriginY, long duration) { + AnimatedZoomJob result = pool.get(); + result.mViewPortHandler = viewPortHandler; + result.xValue = scaleX; + result.yValue = scaleY; + result.mTrans = trans; + result.view = v; + result.xOrigin = xOrigin; + result.yOrigin = yOrigin; + result.resetAnimator(); + result.animator.setDuration(duration); + return result; + } + protected float zoomOriginX; protected float zoomOriginY; @@ -79,8 +100,18 @@ public void onAnimationRepeat(Animator animation) { } + @Override + public void recycleSelf() { + + } + @Override public void onAnimationStart(Animator animation) { } + + @Override + protected ObjectPool.Poolable instantiate() { + return new AnimatedZoomJob(null,null,null,null,0,0,0,0,0,0,0,0,0,0); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java index e96aba8052..46b56b1347 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/MoveViewJob.java @@ -3,6 +3,7 @@ import android.view.View; +import com.github.mikephil.charting.utils.ObjectPool; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -11,6 +12,27 @@ */ public class MoveViewJob extends ViewPortJob { + private static ObjectPool pool; + + static { + pool = ObjectPool.create(2, new MoveViewJob(null,0,0,null,null)); + pool.setReplenishPercentage(0.5f); + } + + public static MoveViewJob getInstance(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v){ + MoveViewJob result = pool.get(); + result.mViewPortHandler = viewPortHandler; + result.xValue = xValue; + result.yValue = yValue; + result.mTrans = trans; + result.view = v; + return result; + } + + public static void recycleInstance(MoveViewJob instance){ + pool.recycle(instance); + } + public MoveViewJob(ViewPortHandler viewPortHandler, float xValue, float yValue, Transformer trans, View v) { super(viewPortHandler, xValue, yValue, trans, v); } @@ -23,5 +45,12 @@ public void run() { mTrans.pointValuesToPixel(pts); mViewPortHandler.centerViewPort(pts, view); + + this.recycleInstance(this); + } + + @Override + protected ObjectPool.Poolable instantiate() { + return new MoveViewJob(mViewPortHandler, xValue, yValue, mTrans, view); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java index 912ab38431..c424e4b87a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ViewPortJob.java @@ -3,6 +3,7 @@ import android.view.View; +import com.github.mikephil.charting.utils.ObjectPool; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -15,7 +16,7 @@ * * @author Philipp Jahoda */ -public abstract class ViewPortJob implements Runnable { +public abstract class ViewPortJob extends ObjectPool.Poolable implements Runnable { protected float[] pts = new float[2]; @@ -33,6 +34,7 @@ public ViewPortJob(ViewPortHandler viewPortHandler, float xValue, float yValue, this.yValue = yValue; this.mTrans = trans; this.view = v; + } public float getXValue() { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java index 94a8ea1e7b..00b67df0fc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java @@ -6,6 +6,7 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.utils.ObjectPool; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -14,6 +15,30 @@ */ public class ZoomJob extends ViewPortJob { + private static ObjectPool pool; + + static { + pool = ObjectPool.create(1, new ZoomJob(null,0,0,0,0,null,null,null)); + pool.setReplenishPercentage(0.5f); + } + + public static ZoomJob getInstance(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, Transformer trans, YAxis.AxisDependency axis, View v) { + ZoomJob result = pool.get(); + result.xValue = xValue; + result.yValue = yValue; + result.scaleX = scaleX; + result.scaleY = scaleY; + result.mViewPortHandler = viewPortHandler; + result.mTrans = trans; + result.axisDependency = axis; + result.view = v; + return result; + } + + public static void recycleInstance(ZoomJob instance){ + pool.recycle(instance); + } + protected float scaleX; protected float scaleY; @@ -48,5 +73,12 @@ public void run() { ((BarLineChartBase) view).calculateOffsets(); view.postInvalidate(); + + recycleInstance(this); + } + + @Override + protected ObjectPool.Poolable instantiate() { + return new ZoomJob(null,0,0,0,0,null,null,null); } } From 37f24984879210651a6299021964049e4282d25b Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 16:26:53 -0700 Subject: [PATCH 1065/1390] Eliminate allocs - MFPoint recycle (#1892) Noticed a couple of stray un-recycled MFPoint and FSize instances. These accounted for a bit of the remaining generated garbage. --- .../com/github/mikephil/charting/renderer/XAxisRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index ef37a3a069..8a73bced5c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,7 +6,6 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; -import android.graphics.PointF; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; @@ -98,6 +97,7 @@ protected void computeSize() { mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); FSize.recycleInstance(labelRotatedSize); + FSize.recycleInstance(labelSize); } @Override @@ -141,6 +141,7 @@ public void renderAxisLabels(Canvas c) { pointF.y = 0.0f; drawLabels(c, mViewPortHandler.contentBottom() + yoffset, pointF); } + MPPointF.recycleInstance(pointF); } @Override From 66094db76409e15546921d353d1c4454a8468feb Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 16:28:15 -0700 Subject: [PATCH 1066/1390] Eliminate allocs - Copy arrays without new[] (#1892) Make sure we copy List<> into [] if the size is identical to the length, instead of instantiating a new []. --- .../mikephil/charting/components/Legend.java | 51 +++++++++++++++---- .../github/mikephil/charting/utils/Utils.java | 18 +++++-- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index b0b82bdc3e..65824ac978 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -171,8 +171,8 @@ public Legend(List colors, List labels) { "colors array and labels array need to be of same size"); } - this.mColors = Utils.convertIntegers(colors); - this.mLabels = Utils.convertStrings(labels); + this.setComputedColors(colors); + this.setComputedLabels(labels); } /** @@ -180,7 +180,11 @@ public Legend(List colors, List labels) { * @param colors */ public void setComputedColors(List colors) { - mColors = Utils.convertIntegers(colors); + if(mColors != null && colors.size() == mColors.length){ + Utils.copyIntegers(colors, mColors); + }else { + mColors = Utils.convertIntegers(colors); + } } /** @@ -188,7 +192,11 @@ public void setComputedColors(List colors) { * @param labels */ public void setComputedLabels(List labels) { - mLabels = Utils.convertStrings(labels); + if(mLabels != null && mLabels.length == labels.size()){ + Utils.copyStrings(labels, mLabels); + }else { + mLabels = Utils.convertStrings(labels); + } } /** @@ -291,8 +299,17 @@ public String[] getExtraLabels() { * let the changes take effect) */ public void setExtra(List colors, List labels) { - this.mExtraColors = Utils.convertIntegers(colors); - this.mExtraLabels = Utils.convertStrings(labels); + if(mExtraColors != null && mExtraColors.length == colors.size()){ + Utils.copyIntegers(colors, mExtraColors); + }else { + this.mExtraColors = Utils.convertIntegers(colors); + } + + if(mExtraLabels != null && mExtraLabels.length == labels.size()){ + Utils.copyStrings(labels, mExtraLabels); + }else { + this.mExtraLabels = Utils.convertStrings(labels); + } } /** @@ -343,8 +360,8 @@ public void setCustom(List colors, List labels) { "colors array and labels array need to be of same size"); } - mColors = Utils.convertIntegers(colors); - mLabels = Utils.convertStrings(labels); + this.setComputedColors(colors); + this.setComputedLabels(labels); mIsLegendCustom = true; } @@ -791,6 +808,7 @@ public float getMaxSizePercent() { public void setMaxSizePercent(float maxSize) { mMaxSizePercent = maxSize; } + private boolean isCalculatedLineSizesArrayListResized = true; private FSize[] mCalculatedLabelSizes = new FSize[] {}; private Boolean[] mCalculatedLabelBreakPoints = new Boolean[] {}; @@ -805,6 +823,14 @@ public Boolean[] getCalculatedLabelBreakPoints() { } public FSize[] getCalculatedLineSizes() { + if(mCalculatedLineSizes == null || isCalculatedLineSizesArrayListResized){ + + mCalculatedLineSizes = calculatedLineSizesForCalculateDimensions + .toArray(new FSize[calculatedLineSizesForCalculateDimensions.size()]); + + isCalculatedLineSizesArrayListResized = false; + + } return mCalculatedLineSizes; } @@ -998,8 +1024,13 @@ else if (wasStacked) { stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; } - mCalculatedLineSizes = calculatedLineSizes - .toArray(new FSize[calculatedLineSizes.size()]); + if(calculatedLineSizes.size() != mCalculatedLineSizes.length) { + isCalculatedLineSizesArrayListResized = true; + }else{ + for(int i = 0 ; i < mCalculatedLineSizes.length ; i++){ + mCalculatedLineSizes[i] = calculatedLineSizes.get(i); + } + } mNeededWidth = maxLineWidth; mNeededHeight = labelLineHeight diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 8cf77e2de1..e599fc1db7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -369,13 +369,18 @@ public static int[] convertIntegers(List integers) { int[] ret = new int[integers.size()]; - for (int i = 0; i < ret.length; i++) { - ret[i] = integers.get(i).intValue(); - } + copyIntegers(integers, ret); return ret; } + public static void copyIntegers(List from, int[] to){ + int count = to.length < from.size() ? to.length : from.size(); + for(int i = 0 ; i < count ; i++){ + to[i] = from.get(i); + } + } + /** * Converts the provided String List to a String array. * @@ -393,6 +398,13 @@ public static String[] convertStrings(List strings) { return ret; } + public static void copyStrings(List from, String[] to){ + int count = to.length < from.size() ? to.length : from.size(); + for(int i = 0 ; i < count ; i++){ + to[i] = from.get(i); + } + } + /** * Replacement for the Math.nextUp(...) method that is only available in * HONEYCOMB and higher. Dat's some seeeeek sheeet. From 523c7e5b216e062af5564afadfdf1fa662c3fd5f Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Thu, 30 Jun 2016 17:24:32 -0700 Subject: [PATCH 1067/1390] Render bug fix - circle bitmap sizes (#1892) Zooming in on the circle bitmaps, they were slightly small. Allocate a little more space in the circle's bitmap to correct this. --- .../charting/renderer/LineChartRenderer.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index f44739dc8c..20ffdd9db3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -665,7 +665,7 @@ protected void drawCircles(Canvas c) { if(circleBitmap == null){ Bitmap.Config conf = Bitmap.Config.ARGB_8888; - circleBitmap = Bitmap.createBitmap((int)circleRadius * 2, (int)circleRadius * 2, conf); + circleBitmap = Bitmap.createBitmap((int)(circleRadius * 2.1), (int)(circleRadius * 2.1), conf); Canvas canvas = new Canvas(circleBitmap); imageCache.circleBitmaps[colorIndex] = circleBitmap; imageCache.circleColors[colorIndex] = circleColor; @@ -674,12 +674,16 @@ protected void drawCircles(Canvas c) { // Begin path for circle with hole mCirclePathBuffer.reset(); - mCirclePathBuffer.addCircle(circleRadius, circleRadius, + mCirclePathBuffer.addCircle( + circleRadius, + circleRadius, circleRadius, Path.Direction.CW); // Cut hole in path - mCirclePathBuffer.addCircle(circleHoleRadius, circleHoleRadius, + mCirclePathBuffer.addCircle( + circleRadius, + circleRadius, circleHoleRadius, Path.Direction.CCW); @@ -687,12 +691,16 @@ protected void drawCircles(Canvas c) { canvas.drawPath(mCirclePathBuffer, mRenderPaint); }else{ - canvas.drawCircle(circleRadius, circleRadius, + canvas.drawCircle( + circleRadius, + circleRadius, circleRadius, mRenderPaint); if (drawCircleHole) { - canvas.drawCircle(circleRadius, circleRadius, + canvas.drawCircle( + circleRadius, + circleRadius, circleHoleRadius, mCirclePaintInner); } From 12eee703a7e1e58a343356f742f6e26724f47aa6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Jul 2016 09:13:58 +0200 Subject: [PATCH 1068/1390] Fix issue related to highlight callbacks #745 --- .../mikephil/charting/charts/Chart.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ce5d42ea65..2ff5459c41 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -543,6 +543,20 @@ public boolean valuesToHighlight() { : true; } + /** + * Sets the last highlighted value for the touchlistener. + * + * @param highs + */ + protected void setLastHighlighted(Highlight[] highs) { + + if (highs == null || highs.length <= 0 || highs[0] == null) { + mChartTouchListener.setLastHighlighted(null); + } else { + mChartTouchListener.setLastHighlighted(highs[0]); + } + } + /** * Highlights the values at the given indices in the given DataSets. Provide * null or an empty array to undo all highlighting. This should be used to @@ -556,11 +570,7 @@ public void highlightValues(Highlight[] highs) { // set the indices to highlight mIndicesToHighlight = highs; - if (highs == null || highs.length <= 0 || highs[0] == null) { - mChartTouchListener.setLastHighlighted(null); - } else { - mChartTouchListener.setLastHighlighted(highs[0]); - } + setLastHighlighted(highs); // redraw the chart invalidate(); @@ -635,6 +645,8 @@ public void highlightValue(Highlight high, boolean callListener) { } } + setLastHighlighted(mIndicesToHighlight); + if (callListener && mSelectionListener != null) { if (!valuesToHighlight()) @@ -644,6 +656,7 @@ public void highlightValue(Highlight high, boolean callListener) { mSelectionListener.onValueSelected(e, high); } } + // redraw the chart invalidate(); } From efbea0a7ef24437f49559d738b4a1cf07a043a90 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Jul 2016 17:30:12 +0200 Subject: [PATCH 1069/1390] Documentation --- MPChartExample/build.gradle | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 0cebfdf441..8a6a75823d 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -55,7 +55,10 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':MPChartLib-Realm') + compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: + //compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.0' + + //compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:23.1.1' //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' From 0597663392f9deac0e43f30e6badfece657674e7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Jul 2016 17:49:12 +0200 Subject: [PATCH 1070/1390] changes to build.gradle --- MPChartLib/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index f8f8455805..1d82f5f729 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.library' apply plugin: 'maven' -//apply plugin: 'com.github.dcendents.android-maven' +apply plugin: 'com.github.dcendents.android-maven' //apply plugin: 'realm-android' android { From 6a2e6e55288c81af3a98e903a7d48369960933d7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Jul 2016 18:12:42 +0200 Subject: [PATCH 1071/1390] Temporary remove of realm from example --- MPChartExample/build.gradle | 6 +- .../notimportant/MainActivity.java | 5 +- .../realm/RealmBaseActivity.java | 203 ------------------ .../realm/RealmDatabaseActivityBar.java | 69 ------ .../realm/RealmDatabaseActivityBubble.java | 71 ------ .../realm/RealmDatabaseActivityCandle.java | 77 ------- .../RealmDatabaseActivityHorizontalBar.java | 74 ------- .../realm/RealmDatabaseActivityLine.java | 77 ------- .../realm/RealmDatabaseActivityPie.java | 83 ------- .../realm/RealmDatabaseActivityRadar.java | 78 ------- .../realm/RealmDatabaseActivityScatter.java | 73 ------- .../realm/RealmMainActivity.java | 131 ----------- .../realm/RealmWikiExample.java | 137 ------------ .../mpchartexample/realm/Score.java | 51 ----- settings.gradle | 4 +- 15 files changed, 7 insertions(+), 1132 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8a6a75823d..4a17e8dfc5 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -55,10 +55,10 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) - compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - //compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.0' + //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: + //compile 'com.github.PhilJay:MPAndroidChart-Realm:v0.9.9' - //compile project(':MPChartLib') + compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:23.1.1' //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 617e43c021..df7c6e07c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -46,7 +46,6 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; -import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; @@ -275,8 +274,8 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 28: - i = new Intent(this, RealmMainActivity.class); - startActivity(i); + //i = new Intent(this, RealmMainActivity.class); + //startActivity(i); break; case 29: i = new Intent(this, LineChartTime.class); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java deleted file mode 100644 index d4fef69576..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; - -import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.PercentFormatter; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 05/11/15. - */ -public abstract class RealmBaseActivity extends DemoBase { - - protected Realm mRealm; - - protected Typeface mTf; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("Realm.io Examples"); - } - - protected void setup(Chart chart) { - - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - // no description text - chart.setDescription(""); - chart.setNoDataTextDescription("You need to provide data for the chart."); - - // enable touch gestures - chart.setTouchEnabled(true); - - if (chart instanceof BarLineChartBase) { - - BarLineChartBase mChart = (BarLineChartBase) chart; - - mChart.setDrawGridBackground(false); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setTypeface(mTf); - leftAxis.setTextSize(8f); - leftAxis.setTextColor(Color.DKGRAY); - leftAxis.setValueFormatter(new PercentFormatter()); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTf); - xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); - xAxis.setTextSize(8f); - xAxis.setTextColor(Color.DKGRAY); - - mChart.getAxisRight().setEnabled(false); - } - } - - protected void styleData(ChartData data) { - data.setValueTypeface(mTf); - data.setValueTextSize(8f); - data.setValueTextColor(Color.DKGRAY); - data.setValueFormatter(new PercentFormatter()); - } - - @Override - protected void onResume() { - super.onResume(); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); - Realm.setDefaultConfiguration(realmConfig); - - mRealm = Realm.getDefaultInstance(); - } - - @Override - protected void onPause() { - super.onPause(); - mRealm.close(); - } - - protected void writeToDB(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 40f + (float) (Math.random() * 60f); - - RealmDemoData d = new RealmDemoData(i, value); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBStack(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float val1 = 34f + (float) (Math.random() * 12.0f); - float val2 = 34f + (float) (Math.random() * 12.0f); - float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - - RealmDemoData d = new RealmDemoData(i, stack); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBCandle(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float mult = 50; - float val = (float) (Math.random() * 40) + mult; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close); - - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBBubble(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 30f + (float) (Math.random() * 100.0); - float size = 15f + (float) (Math.random() * 20.0); - - RealmDemoData d = new RealmDemoData(i, value, size); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBPie() { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - float value1 = 15f + (float) (Math.random() * 8f); - float value2 = 15f + (float) (Math.random() * 8f); - float value3 = 15f + (float) (Math.random() * 8f); - float value4 = 15f + (float) (Math.random() * 8f); - float value5 = 100f - value1 - value2 - value3 - value4; - - float[] values = new float[] { value1, value2, value3, value4, value5 }; - String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; - - for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], labels[i]); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java deleted file mode 100644 index c87290050d..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBar extends RealmBaseActivity { - - private BarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart_noseekbar); - - mChart = (BarChart) findViewById(R.id.chart1); - setup(mChart); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(20); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries - set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - set.setLabel("Realm BarDataSet"); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.setFitBars(true); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java deleted file mode 100644 index d0aa25b864..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BubbleChart; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBubble extends RealmBaseActivity { - - private BubbleChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_bubblechart_noseekbar); - - mChart = (BubbleChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getXAxis().setDrawGridLines(false); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBBubble(10); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); - set.setLabel("Realm BubbleDataSet"); - set.setColors(ColorTemplate.COLORFUL_COLORS, 110); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BubbleData data = new BubbleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java deleted file mode 100644 index a388df3741..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Paint; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.CandleStickChart; -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityCandle extends RealmBaseActivity { - - private CandleStickChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_candlechart_noseekbar); - - mChart = (CandleStickChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBCandle(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); - set.setLabel("Realm CandleDataSet"); - set.setShadowColor(Color.DKGRAY); - set.setShadowWidth(0.7f); - set.setDecreasingColor(Color.RED); - set.setDecreasingPaintStyle(Paint.Style.FILL); - set.setIncreasingColor(Color.rgb(122, 242, 84)); - set.setIncreasingPaintStyle(Paint.Style.STROKE); - set.setNeutralColor(Color.BLUE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - CandleData data = new CandleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java deleted file mode 100644 index 32d1234fe2..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { - - private HorizontalBarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_horizontalbarchart_noseekbar); - - mChart = (HorizontalBarChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMinValue(0f); - mChart.setDrawValueAboveBar(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBStack(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries - set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); - set.setLabel("Mobile OS distribution"); - set.setStackLabels(new String[]{"iOS", "Android", "Other"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - data.setValueTextColor(Color.WHITE); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java deleted file mode 100644 index 6d2396c22b..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityLine extends RealmBaseActivity { - - private LineChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart_noseekbar); - - mChart = (LineChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMaxValue(150f); - mChart.getAxisLeft().setAxisMinValue(0f); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(40); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); - set.setDrawCubic(false); - set.setLabel("Realm LineDataSet"); - set.setDrawCircleHole(false); - set.setColor(ColorTemplate.rgb("#FF5722")); - set.setCircleColor(ColorTemplate.rgb("#FF5722")); - set.setLineWidth(1.8f); - set.setCircleSize(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - LineData data = new LineData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java deleted file mode 100644 index 7b1eb675d9..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityPie extends RealmBaseActivity { - - private PieChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_piechart_noseekbar); - - mChart = (PieChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.setCenterText(generateCenterSpannableText()); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBPie(); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries - set.setColors(ColorTemplate.VORDIPLOM_COLORS); - set.setLabel("Example market share"); - set.setSliceSpace(2); - - // create a data object with the dataset list - PieData data = new PieData(set); - styleData(data); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(12f); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } - - private SpannableString generateCenterSpannableText() { - - SpannableString s = new SpannableString("Realm.io\nmobile database"); - s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); - s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); - s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); - s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); - s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); - return s; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java deleted file mode 100644 index 411f4b6ac9..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityRadar extends RealmBaseActivity { - - private RadarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); - - mChart = (RadarChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getYAxis().setEnabled(false); - mChart.getXAxis().setEnabled(false); - mChart.setWebAlpha(180); - mChart.setWebColorInner(Color.DKGRAY); - mChart.setWebColor(Color.GRAY); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(7); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries - set.setLabel("Realm RadarDataSet"); - set.setDrawFilled(true); - set.setColor(ColorTemplate.rgb("#009688")); - set.setFillColor(ColorTemplate.rgb("#009688")); - set.setFillAlpha(130); - set.setLineWidth(2f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - RadarData data = new RadarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java deleted file mode 100644 index 14175ac73a..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityScatter extends RealmBaseActivity { - - private ScatterChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_scatterchart_noseekbar); - - mChart = (ScatterChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(45); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); - set.setLabel("Realm ScatterDataSet"); - set.setScatterShapeSize(9f); - set.setColor(ColorTemplate.rgb("#CDDC39")); - set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - ScatterData data = new ScatterData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java deleted file mode 100644 index 3198320272..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ListView; - -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; - -import java.util.ArrayList; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_main); - - setTitle("Realm.io Examples"); - - ArrayList objects = new ArrayList(); - - objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); - objects.add(new ContentItem("Bar Chart", - "Creating a BarChart with Realm.io database")); - objects.add(new ContentItem("Horizontal Bar Chart", - "Creating a HorizontalBarChart with Realm.io database")); - objects.add(new ContentItem("Scatter Chart", - "Creating a ScatterChart with Realm.io database")); - objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); - objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); - objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); - objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); - objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); - - MyAdapter adapter = new MyAdapter(this, objects); - - ListView lv = (ListView) findViewById(R.id.listView1); - lv.setAdapter(adapter); - - lv.setOnItemClickListener(this); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); - Realm.setDefaultConfiguration(realmConfig); - - Realm realm = Realm.getDefaultInstance(); - realm.beginTransaction(); - realm.deleteAll(); - realm.commitTransaction(); - } - - @Override - public void onItemClick(AdapterView av, View v, int pos, long arg3) { - - Intent i; - - switch (pos) { - case 0: - i = new Intent(this, RealmDatabaseActivityLine.class); - startActivity(i); - break; - case 1: - i = new Intent(this, RealmDatabaseActivityBar.class); - startActivity(i); - break; - case 2: - i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); - startActivity(i); - break; - case 3: - i = new Intent(this, RealmDatabaseActivityScatter.class); - startActivity(i); - break; - case 4: - i = new Intent(this, RealmDatabaseActivityCandle.class); - startActivity(i); - break; - case 5: - i = new Intent(this, RealmDatabaseActivityBubble.class); - startActivity(i); - break; - case 6: - i = new Intent(this, RealmDatabaseActivityPie.class); - startActivity(i); - break; - case 7: - i = new Intent(this, RealmDatabaseActivityRadar.class); - startActivity(i); - break; - case 8: - i = new Intent(this, RealmWikiExample.class); - startActivity(i); - break; - } - - overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realm, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://realm.io")); - startActivity(i); - - return super.onOptionsItemSelected(item); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java deleted file mode 100644 index 7682bca957..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 18/12/15. - */ -public class RealmWikiExample extends RealmBaseActivity { - - private LineChart lineChart; - private BarChart barChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_realm_wiki); - - lineChart = (LineChart) findViewById(R.id.lineChart); - barChart = (BarChart) findViewById(R.id.barChart); - setup(lineChart); - setup(barChart); - - lineChart.setExtraBottomOffset(5f); - barChart.setExtraBottomOffset(5f); - - lineChart.getAxisLeft().setDrawGridLines(false); - lineChart.getXAxis().setDrawGridLines(false); - lineChart.getXAxis().setLabelCount(5); - lineChart.getXAxis().setGranularity(1f); - barChart.getAxisLeft().setDrawGridLines(false); - barChart.getXAxis().setDrawGridLines(false); - barChart.getXAxis().setLabelCount(5); - barChart.getXAxis().setGranularity(1f); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - mRealm.beginTransaction(); - - // write some demo-data into the realm.io database - Score score1 = new Score(100f, 0f, "Peter"); - mRealm.copyToRealm(score1); - Score score2 = new Score(110f, 1f, "Lisa"); - mRealm.copyToRealm(score2); - Score score3 = new Score(130f, 2f, "Dennis"); - mRealm.copyToRealm(score3); - Score score4 = new Score(70f, 3f, "Luke"); - mRealm.copyToRealm(score4); - Score score5 = new Score(80f, 4f, "Sarah"); - mRealm.copyToRealm(score5); - - mRealm.commitTransaction(); - - // add data to the chart - setData(); - } - - private void setData() { - - // LINE-CHART - final RealmResults results = mRealm.where(Score.class).findAll(); - - - AxisValueFormatter formatter = new AxisValueFormatter() { - @Override - public String getFormattedValue(float value, AxisBase axis) { - return results.get((int) value).getPlayerName(); - } - - @Override - public int getDecimalDigits() { - return 0; - } - }; - - lineChart.getXAxis().setValueFormatter(formatter); - barChart.getXAxis().setValueFormatter(formatter); - - RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); - lineDataSet.setDrawCubic(false); - lineDataSet.setLabel("Result Scores"); - lineDataSet.setDrawCircleHole(false); - lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setLineWidth(1.8f); - lineDataSet.setCircleSize(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(lineDataSet); - - LineData lineData = new LineData(dataSets); - styleData(lineData); - - // set data - lineChart.setData(lineData); - lineChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - - - // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); - barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - barDataSet.setLabel("Realm BarDataSet"); - - ArrayList barDataSets = new ArrayList(); - barDataSets.add(barDataSet); - - BarData barData = new BarData(barDataSets); - styleData(barData); - - barChart.setData(barData); - barChart.setFitBars(true); - barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java deleted file mode 100644 index 870e371491..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - - -import io.realm.RealmObject; - -/** - * our data object - */ -public class Score extends RealmObject { - - private float totalScore; - - private float scoreNr; - - private String playerName; - - public Score() { - } - - public Score(float totalScore, float scoreNr, String playerName) { - this.scoreNr = scoreNr; - this.playerName = playerName; - this.totalScore = totalScore; - } - - // all getters and setters... - - public float getTotalScore() { - return totalScore; - } - - public void setTotalScore(float totalScore) { - this.totalScore = totalScore; - } - - public float getScoreNr() { - return scoreNr; - } - - public void setScoreNr(float scoreNr) { - this.scoreNr = scoreNr; - } - - public String getPlayerName() { - return playerName; - } - - public void setPlayerName(String playerName) { - this.playerName = playerName; - } -} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 484b8b3ecd..32efe09de1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ include 'MPChartLib' //include 'MPAndroidChart-Realm' include 'MPChartExample' -include ':MPChartLib-Realm' -project(':MPChartLib-Realm').projectDir = new File('../MPAndroidChart-Realm/MPChartLib-Realm') +//include ':MPChartLib-Realm' +//project(':MPChartLib-Realm').projectDir = new File('../MPAndroidChart-Realm/MPChartLib-Realm') From 0789628197d9b05756a83d179889d37bba2d8abc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 1 Jul 2016 18:54:59 +0200 Subject: [PATCH 1072/1390] Add realm related example code --- MPChartExample/build.gradle | 2 +- .../notimportant/MainActivity.java | 5 +- .../realm/RealmBaseActivity.java | 203 ++++++++++++++++++ .../realm/RealmDatabaseActivityBar.java | 69 ++++++ .../realm/RealmDatabaseActivityBubble.java | 71 ++++++ .../realm/RealmDatabaseActivityCandle.java | 77 +++++++ .../RealmDatabaseActivityHorizontalBar.java | 74 +++++++ .../realm/RealmDatabaseActivityLine.java | 77 +++++++ .../realm/RealmDatabaseActivityPie.java | 83 +++++++ .../realm/RealmDatabaseActivityRadar.java | 78 +++++++ .../realm/RealmDatabaseActivityScatter.java | 73 +++++++ .../realm/RealmMainActivity.java | 131 +++++++++++ .../realm/RealmWikiExample.java | 137 ++++++++++++ .../mpchartexample/realm/Score.java | 51 +++++ MPChartLib/build.gradle | 2 +- 15 files changed, 1129 insertions(+), 4 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 4a17e8dfc5..b9dff17945 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -56,7 +56,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - //compile 'com.github.PhilJay:MPAndroidChart-Realm:v0.9.9' + compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.0@aar' compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:23.1.1' diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index df7c6e07c6..617e43c021 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -46,6 +46,7 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; +import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; @@ -274,8 +275,8 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 28: - //i = new Intent(this, RealmMainActivity.class); - //startActivity(i); + i = new Intent(this, RealmMainActivity.class); + startActivity(i); break; case 29: i = new Intent(this, LineChartTime.class); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java new file mode 100644 index 0000000000..d4fef69576 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -0,0 +1,203 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.formatter.PercentFormatter; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import io.realm.Realm; +import io.realm.RealmConfiguration; + +/** + * Created by Philipp Jahoda on 05/11/15. + */ +public abstract class RealmBaseActivity extends DemoBase { + + protected Realm mRealm; + + protected Typeface mTf; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitle("Realm.io Examples"); + } + + protected void setup(Chart chart) { + + mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + // no description text + chart.setDescription(""); + chart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable touch gestures + chart.setTouchEnabled(true); + + if (chart instanceof BarLineChartBase) { + + BarLineChartBase mChart = (BarLineChartBase) chart; + + mChart.setDrawGridBackground(false); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines + leftAxis.setTypeface(mTf); + leftAxis.setTextSize(8f); + leftAxis.setTextColor(Color.DKGRAY); + leftAxis.setValueFormatter(new PercentFormatter()); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(mTf); + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); + xAxis.setTextSize(8f); + xAxis.setTextColor(Color.DKGRAY); + + mChart.getAxisRight().setEnabled(false); + } + } + + protected void styleData(ChartData data) { + data.setValueTypeface(mTf); + data.setValueTextSize(8f); + data.setValueTextColor(Color.DKGRAY); + data.setValueFormatter(new PercentFormatter()); + } + + @Override + protected void onResume() { + super.onResume(); + + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); + + mRealm = Realm.getDefaultInstance(); + } + + @Override + protected void onPause() { + super.onPause(); + mRealm.close(); + } + + protected void writeToDB(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float value = 40f + (float) (Math.random() * 60f); + + RealmDemoData d = new RealmDemoData(i, value); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBStack(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float val1 = 34f + (float) (Math.random() * 12.0f); + float val2 = 34f + (float) (Math.random() * 12.0f); + float[] stack = new float[]{val1, val2, 100 - val1 - val2}; + + RealmDemoData d = new RealmDemoData(i, stack); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBCandle(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float mult = 50; + float val = (float) (Math.random() * 40) + mult; + + float high = (float) (Math.random() * 9) + 8f; + float low = (float) (Math.random() * 9) + 8f; + + float open = (float) (Math.random() * 6) + 1f; + float close = (float) (Math.random() * 6) + 1f; + + boolean even = i % 2 == 0; + + RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, + even ? val - close : val + close); + + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBBubble(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float value = 30f + (float) (Math.random() * 100.0); + float size = 15f + (float) (Math.random() * 20.0); + + RealmDemoData d = new RealmDemoData(i, value, size); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBPie() { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + float value1 = 15f + (float) (Math.random() * 8f); + float value2 = 15f + (float) (Math.random() * 8f); + float value3 = 15f + (float) (Math.random() * 8f); + float value4 = 15f + (float) (Math.random() * 8f); + float value5 = 100f - value1 - value2 - value3 - value4; + + float[] values = new float[] { value1, value2, value3, value4, value5 }; + String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; + + for (int i = 0; i < values.length; i++) { + RealmDemoData d = new RealmDemoData(values[i], labels[i]); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java new file mode 100644 index 0000000000..c87290050d --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -0,0 +1,69 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityBar extends RealmBaseActivity { + + private BarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart_noseekbar); + + mChart = (BarChart) findViewById(R.id.chart1); + setup(mChart); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(20); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries + set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + set.setLabel("Realm BarDataSet"); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BarData data = new BarData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.setFitBars(true); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java new file mode 100644 index 0000000000..d0aa25b864 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -0,0 +1,71 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BubbleChart; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityBubble extends RealmBaseActivity { + + private BubbleChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_bubblechart_noseekbar); + + mChart = (BubbleChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getXAxis().setDrawGridLines(false); + mChart.getAxisLeft().setDrawGridLines(false); + mChart.setPinchZoom(true); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBBubble(10); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); + set.setLabel("Realm BubbleDataSet"); + set.setColors(ColorTemplate.COLORFUL_COLORS, 110); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BubbleData data = new BubbleData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java new file mode 100644 index 0000000000..a388df3741 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -0,0 +1,77 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.CandleStickChart; +import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityCandle extends RealmBaseActivity { + + private CandleStickChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_candlechart_noseekbar); + + mChart = (CandleStickChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBCandle(50); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); + set.setLabel("Realm CandleDataSet"); + set.setShadowColor(Color.DKGRAY); + set.setShadowWidth(0.7f); + set.setDecreasingColor(Color.RED); + set.setDecreasingPaintStyle(Paint.Style.FILL); + set.setIncreasingColor(Color.rgb(122, 242, 84)); + set.setIncreasingPaintStyle(Paint.Style.STROKE); + set.setNeutralColor(Color.BLUE); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + CandleData data = new CandleData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java new file mode 100644 index 0000000000..32d1234fe2 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -0,0 +1,74 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { + + private HorizontalBarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart_noseekbar); + + mChart = (HorizontalBarChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setAxisMinValue(0f); + mChart.setDrawValueAboveBar(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBStack(50); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries + set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); + set.setLabel("Mobile OS distribution"); + set.setStackLabels(new String[]{"iOS", "Android", "Other"}); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BarData data = new BarData(dataSets); + styleData(data); + data.setValueTextColor(Color.WHITE); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java new file mode 100644 index 0000000000..6d2396c22b --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -0,0 +1,77 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityLine extends RealmBaseActivity { + + private LineChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart_noseekbar); + + mChart = (LineChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setAxisMaxValue(150f); + mChart.getAxisLeft().setAxisMinValue(0f); + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(40); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); + set.setDrawCubic(false); + set.setLabel("Realm LineDataSet"); + set.setDrawCircleHole(false); + set.setColor(ColorTemplate.rgb("#FF5722")); + set.setCircleColor(ColorTemplate.rgb("#FF5722")); + set.setLineWidth(1.8f); + set.setCircleSize(3.6f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + LineData data = new LineData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java new file mode 100644 index 0000000000..7b1eb675d9 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -0,0 +1,83 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityPie extends RealmBaseActivity { + + private PieChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_piechart_noseekbar); + + mChart = (PieChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.setCenterText(generateCenterSpannableText()); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBPie(); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries + set.setColors(ColorTemplate.VORDIPLOM_COLORS); + set.setLabel("Example market share"); + set.setSliceSpace(2); + + // create a data object with the dataset list + PieData data = new PieData(set); + styleData(data); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(12f); + + // set data + mChart.setData(data); + mChart.animateY(1400); + } + + private SpannableString generateCenterSpannableText() { + + SpannableString s = new SpannableString("Realm.io\nmobile database"); + s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); + s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); + s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); + s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); + return s; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java new file mode 100644 index 0000000000..411f4b6ac9 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -0,0 +1,78 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.data.RadarData; +import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityRadar extends RealmBaseActivity { + + private RadarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_radarchart_noseekbar); + + mChart = (RadarChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getYAxis().setEnabled(false); + mChart.getXAxis().setEnabled(false); + mChart.setWebAlpha(180); + mChart.setWebColorInner(Color.DKGRAY); + mChart.setWebColor(Color.GRAY); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(7); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries + set.setLabel("Realm RadarDataSet"); + set.setDrawFilled(true); + set.setColor(ColorTemplate.rgb("#009688")); + set.setFillColor(ColorTemplate.rgb("#009688")); + set.setFillAlpha(130); + set.setLineWidth(2f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + RadarData data = new RadarData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java new file mode 100644 index 0000000000..14175ac73a --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -0,0 +1,73 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityScatter extends RealmBaseActivity { + + private ScatterChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_scatterchart_noseekbar); + + mChart = (ScatterChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + mChart.setPinchZoom(true); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(45); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); + set.setLabel("Realm ScatterDataSet"); + set.setScatterShapeSize(9f); + set.setColor(ColorTemplate.rgb("#CDDC39")); + set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + ScatterData data = new ScatterData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java new file mode 100644 index 0000000000..3198320272 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -0,0 +1,131 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ListView; + +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; + +import java.util.ArrayList; + +import io.realm.Realm; +import io.realm.RealmConfiguration; + +/** + * Created by Philipp Jahoda on 07/12/15. + */ +public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_main); + + setTitle("Realm.io Examples"); + + ArrayList objects = new ArrayList(); + + objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); + objects.add(new ContentItem("Bar Chart", + "Creating a BarChart with Realm.io database")); + objects.add(new ContentItem("Horizontal Bar Chart", + "Creating a HorizontalBarChart with Realm.io database")); + objects.add(new ContentItem("Scatter Chart", + "Creating a ScatterChart with Realm.io database")); + objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); + objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); + objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); + objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); + objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); + + MyAdapter adapter = new MyAdapter(this, objects); + + ListView lv = (ListView) findViewById(R.id.listView1); + lv.setAdapter(adapter); + + lv.setOnItemClickListener(this); + + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); + + Realm realm = Realm.getDefaultInstance(); + realm.beginTransaction(); + realm.deleteAll(); + realm.commitTransaction(); + } + + @Override + public void onItemClick(AdapterView av, View v, int pos, long arg3) { + + Intent i; + + switch (pos) { + case 0: + i = new Intent(this, RealmDatabaseActivityLine.class); + startActivity(i); + break; + case 1: + i = new Intent(this, RealmDatabaseActivityBar.class); + startActivity(i); + break; + case 2: + i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); + startActivity(i); + break; + case 3: + i = new Intent(this, RealmDatabaseActivityScatter.class); + startActivity(i); + break; + case 4: + i = new Intent(this, RealmDatabaseActivityCandle.class); + startActivity(i); + break; + case 5: + i = new Intent(this, RealmDatabaseActivityBubble.class); + startActivity(i); + break; + case 6: + i = new Intent(this, RealmDatabaseActivityPie.class); + startActivity(i); + break; + case 7: + i = new Intent(this, RealmDatabaseActivityRadar.class); + startActivity(i); + break; + case 8: + i = new Intent(this, RealmWikiExample.class); + startActivity(i); + break; + } + + overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.realm, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://realm.io")); + startActivity(i); + + return super.onOptionsItemSelected(item); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java new file mode 100644 index 0000000000..7682bca957 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -0,0 +1,137 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 18/12/15. + */ +public class RealmWikiExample extends RealmBaseActivity { + + private LineChart lineChart; + private BarChart barChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_realm_wiki); + + lineChart = (LineChart) findViewById(R.id.lineChart); + barChart = (BarChart) findViewById(R.id.barChart); + setup(lineChart); + setup(barChart); + + lineChart.setExtraBottomOffset(5f); + barChart.setExtraBottomOffset(5f); + + lineChart.getAxisLeft().setDrawGridLines(false); + lineChart.getXAxis().setDrawGridLines(false); + lineChart.getXAxis().setLabelCount(5); + lineChart.getXAxis().setGranularity(1f); + barChart.getAxisLeft().setDrawGridLines(false); + barChart.getXAxis().setDrawGridLines(false); + barChart.getXAxis().setLabelCount(5); + barChart.getXAxis().setGranularity(1f); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + mRealm.beginTransaction(); + + // write some demo-data into the realm.io database + Score score1 = new Score(100f, 0f, "Peter"); + mRealm.copyToRealm(score1); + Score score2 = new Score(110f, 1f, "Lisa"); + mRealm.copyToRealm(score2); + Score score3 = new Score(130f, 2f, "Dennis"); + mRealm.copyToRealm(score3); + Score score4 = new Score(70f, 3f, "Luke"); + mRealm.copyToRealm(score4); + Score score5 = new Score(80f, 4f, "Sarah"); + mRealm.copyToRealm(score5); + + mRealm.commitTransaction(); + + // add data to the chart + setData(); + } + + private void setData() { + + // LINE-CHART + final RealmResults results = mRealm.where(Score.class).findAll(); + + + AxisValueFormatter formatter = new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return results.get((int) value).getPlayerName(); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }; + + lineChart.getXAxis().setValueFormatter(formatter); + barChart.getXAxis().setValueFormatter(formatter); + + RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); + lineDataSet.setDrawCubic(false); + lineDataSet.setLabel("Result Scores"); + lineDataSet.setDrawCircleHole(false); + lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); + lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); + lineDataSet.setLineWidth(1.8f); + lineDataSet.setCircleSize(3.6f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(lineDataSet); + + LineData lineData = new LineData(dataSets); + styleData(lineData); + + // set data + lineChart.setData(lineData); + lineChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + + + // BAR-CHART + RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); + barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + barDataSet.setLabel("Realm BarDataSet"); + + ArrayList barDataSets = new ArrayList(); + barDataSets.add(barDataSet); + + BarData barData = new BarData(barDataSets); + styleData(barData); + + barChart.setData(barData); + barChart.setFitBars(true); + barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java new file mode 100644 index 0000000000..870e371491 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java @@ -0,0 +1,51 @@ +package com.xxmassdeveloper.mpchartexample.realm; + + +import io.realm.RealmObject; + +/** + * our data object + */ +public class Score extends RealmObject { + + private float totalScore; + + private float scoreNr; + + private String playerName; + + public Score() { + } + + public Score(float totalScore, float scoreNr, String playerName) { + this.scoreNr = scoreNr; + this.playerName = playerName; + this.totalScore = totalScore; + } + + // all getters and setters... + + public float getTotalScore() { + return totalScore; + } + + public void setTotalScore(float totalScore) { + this.totalScore = totalScore; + } + + public float getScoreNr() { + return scoreNr; + } + + public void setScoreNr(float scoreNr) { + this.scoreNr = scoreNr; + } + + public String getPlayerName() { + return playerName; + } + + public void setPlayerName(String playerName) { + this.playerName = playerName; + } +} \ No newline at end of file diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 1d82f5f729..f8f8455805 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'com.android.library' apply plugin: 'maven' -apply plugin: 'com.github.dcendents.android-maven' +//apply plugin: 'com.github.dcendents.android-maven' //apply plugin: 'realm-android' android { From d5df3ad795cb1fa45a24deb32e4f8bdc038c8414 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Fri, 1 Jul 2016 13:16:22 -0700 Subject: [PATCH 1073/1390] Crash fix - Create small clip paths (#1895) With large data sets, the Path object created was sufficiently large as to cause an OutOfMemory error. This is resolved by only pathing a limited number of points on the chart at a time, then clearing the path and resuming. Stress testing with 1500 entries. --- .../res/layout/activity_linechart.xml | 4 +- .../mpchartexample/LineChartActivity1.java | 4 +- .../RealtimeLineChartActivity.java | 2 +- .../charting/renderer/LineChartRenderer.java | 86 +++++++++++++------ 4 files changed, 65 insertions(+), 31 deletions(-) diff --git a/MPChartExample/res/layout/activity_linechart.xml b/MPChartExample/res/layout/activity_linechart.xml index 0389e9e298..7cadd8dd65 100644 --- a/MPChartExample/res/layout/activity_linechart.xml +++ b/MPChartExample/res/layout/activity_linechart.xml @@ -18,7 +18,7 @@ android:layout_margin="8dp" android:layout_toLeftOf="@+id/tvYMax" android:layout_marginRight="5dp" - android:max="200" + android:max="150" android:paddingBottom="12dp" /> endingIndex ? endingIndex : currentEndIndex; + + if(currentStartIndex <= currentEndIndex) { + generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); + + + + trans.pathValueToPixel(filled); + + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { + + drawFilledPath(c, filled, drawable); + } else { + + drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); + } + } + + iterations++; + + }while(currentStartIndex <= currentEndIndex); - drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); - } } - protected Path mGenerateFilledPathBuffer = new Path(); /** - * Generates the path that is used for filled drawing. + * Generates a path that is used for filled drawing. + * + * @param dataSet The dataset from which to read the entries. + * @param startIndex The index from which to start reading the dataset + * @param endIndex The index from which to stop reading the dataset + * @param outputPath The path object that will be assigned the chart data. * - * @param dataSet * @return */ - private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) { + private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) { - float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); - float phaseY = mAnimator.getPhaseY(); + final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); + final float phaseY = mAnimator.getPhaseY(); final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; - Path filled = mGenerateFilledPathBuffer; + final Path filled = outputPath; filled.reset(); - Entry entry = dataSet.getEntryForIndex(bounds.min); + + final Entry entry = dataSet.getEntryForIndex(startIndex); filled.moveTo(entry.getX(), fillMin); filled.lineTo(entry.getX(), entry.getY() * phaseY); // create a new path - for (int x = bounds.min + 1; x <= bounds.range + bounds.min; x++) { - - Entry e = dataSet.getEntryForIndex(x); + Entry currentEntry = null; + Entry previousEntry = null; + for (int x = startIndex + 1 ; x <= endIndex ; x++) { - if (isDrawSteppedEnabled) { - final Entry ePrev = dataSet.getEntryForIndex(x - 1); - if (ePrev == null) continue; + currentEntry = dataSet.getEntryForIndex(x); - filled.lineTo(e.getX(), ePrev.getY() * phaseY); + if (isDrawSteppedEnabled && previousEntry != null) { + filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY); } - filled.lineTo(e.getX(), e.getY() * phaseY); + filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY); + + previousEntry = currentEntry; } // close up - filled.lineTo(dataSet.getEntryForIndex(bounds.range + bounds.min).getX(), fillMin); + if(currentEntry != null) { + filled.lineTo(currentEntry.getX(), fillMin); + } + filled.close(); - return filled; } @Override From 87758604d31270d19bbd55c4b34438ca0ed594da Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Fri, 1 Jul 2016 13:17:49 -0700 Subject: [PATCH 1074/1390] Revert "Crash fix - Create small clip paths (#1895)" This reverts commit d5df3ad795cb1fa45a24deb32e4f8bdc038c8414. --- .../res/layout/activity_linechart.xml | 4 +- .../mpchartexample/LineChartActivity1.java | 4 +- .../RealtimeLineChartActivity.java | 2 +- .../charting/renderer/LineChartRenderer.java | 86 ++++++------------- 4 files changed, 31 insertions(+), 65 deletions(-) diff --git a/MPChartExample/res/layout/activity_linechart.xml b/MPChartExample/res/layout/activity_linechart.xml index 7cadd8dd65..0389e9e298 100644 --- a/MPChartExample/res/layout/activity_linechart.xml +++ b/MPChartExample/res/layout/activity_linechart.xml @@ -18,7 +18,7 @@ android:layout_margin="8dp" android:layout_toLeftOf="@+id/tvYMax" android:layout_marginRight="5dp" - android:max="150" + android:max="200" android:paddingBottom="12dp" /> endingIndex ? endingIndex : currentEndIndex; - - if(currentStartIndex <= currentEndIndex) { - generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); - + Path filled = generateFilledPath(dataSet, bounds); + trans.pathValueToPixel(filled); - trans.pathValueToPixel(filled); - - final Drawable drawable = dataSet.getFillDrawable(); - if (drawable != null) { - - drawFilledPath(c, filled, drawable); - } else { - - drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); - } - } - - iterations++; + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { - }while(currentStartIndex <= currentEndIndex); + drawFilledPath(c, filled, drawable); + } else { + drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); + } } + protected Path mGenerateFilledPathBuffer = new Path(); /** - * Generates a path that is used for filled drawing. - * - * @param dataSet The dataset from which to read the entries. - * @param startIndex The index from which to start reading the dataset - * @param endIndex The index from which to stop reading the dataset - * @param outputPath The path object that will be assigned the chart data. + * Generates the path that is used for filled drawing. * + * @param dataSet * @return */ - private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) { + private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) { - final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); - final float phaseY = mAnimator.getPhaseY(); + float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); + float phaseY = mAnimator.getPhaseY(); final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; - final Path filled = outputPath; + Path filled = mGenerateFilledPathBuffer; filled.reset(); - - final Entry entry = dataSet.getEntryForIndex(startIndex); + Entry entry = dataSet.getEntryForIndex(bounds.min); filled.moveTo(entry.getX(), fillMin); filled.lineTo(entry.getX(), entry.getY() * phaseY); // create a new path - Entry currentEntry = null; - Entry previousEntry = null; - for (int x = startIndex + 1 ; x <= endIndex ; x++) { + for (int x = bounds.min + 1; x <= bounds.range + bounds.min; x++) { - currentEntry = dataSet.getEntryForIndex(x); + Entry e = dataSet.getEntryForIndex(x); - if (isDrawSteppedEnabled && previousEntry != null) { - filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY); - } + if (isDrawSteppedEnabled) { + final Entry ePrev = dataSet.getEntryForIndex(x - 1); + if (ePrev == null) continue; - filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY); + filled.lineTo(e.getX(), ePrev.getY() * phaseY); + } - previousEntry = currentEntry; + filled.lineTo(e.getX(), e.getY() * phaseY); } // close up - if(currentEntry != null) { - filled.lineTo(currentEntry.getX(), fillMin); - } - + filled.lineTo(dataSet.getEntryForIndex(bounds.range + bounds.min).getX(), fillMin); filled.close(); + return filled; } @Override From b5da8dcdb585ad94fefd837d07da638ca40aaa24 Mon Sep 17 00:00:00 2001 From: Tony Patino Date: Fri, 1 Jul 2016 13:19:37 -0700 Subject: [PATCH 1075/1390] Crash fix - Create small clip paths (#1895) With large data sets, the Path object created was sufficiently large as to cause an OutOfMemory error. This is resolved by only pathing a limited number of points on the chart at a time, then clearing the path and resuming. Stress testing with 1500 entries. --- .../res/layout/activity_linechart.xml | 4 +- .../mpchartexample/LineChartActivity1.java | 4 +- .../charting/renderer/LineChartRenderer.java | 86 +++++++++++++------ 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/MPChartExample/res/layout/activity_linechart.xml b/MPChartExample/res/layout/activity_linechart.xml index 0389e9e298..7cadd8dd65 100644 --- a/MPChartExample/res/layout/activity_linechart.xml +++ b/MPChartExample/res/layout/activity_linechart.xml @@ -18,7 +18,7 @@ android:layout_margin="8dp" android:layout_toLeftOf="@+id/tvYMax" android:layout_marginRight="5dp" - android:max="200" + android:max="150" android:paddingBottom="12dp" /> endingIndex ? endingIndex : currentEndIndex; + + if(currentStartIndex <= currentEndIndex) { + generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); + + + + trans.pathValueToPixel(filled); + + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { + + drawFilledPath(c, filled, drawable); + } else { + + drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); + } + } + + iterations++; + + }while(currentStartIndex <= currentEndIndex); - drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); - } } - protected Path mGenerateFilledPathBuffer = new Path(); /** - * Generates the path that is used for filled drawing. + * Generates a path that is used for filled drawing. + * + * @param dataSet The dataset from which to read the entries. + * @param startIndex The index from which to start reading the dataset + * @param endIndex The index from which to stop reading the dataset + * @param outputPath The path object that will be assigned the chart data. * - * @param dataSet * @return */ - private Path generateFilledPath(ILineDataSet dataSet, XBounds bounds) { + private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) { - float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); - float phaseY = mAnimator.getPhaseY(); + final float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); + final float phaseY = mAnimator.getPhaseY(); final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; - Path filled = mGenerateFilledPathBuffer; + final Path filled = outputPath; filled.reset(); - Entry entry = dataSet.getEntryForIndex(bounds.min); + + final Entry entry = dataSet.getEntryForIndex(startIndex); filled.moveTo(entry.getX(), fillMin); filled.lineTo(entry.getX(), entry.getY() * phaseY); // create a new path - for (int x = bounds.min + 1; x <= bounds.range + bounds.min; x++) { - - Entry e = dataSet.getEntryForIndex(x); + Entry currentEntry = null; + Entry previousEntry = null; + for (int x = startIndex + 1 ; x <= endIndex ; x++) { - if (isDrawSteppedEnabled) { - final Entry ePrev = dataSet.getEntryForIndex(x - 1); - if (ePrev == null) continue; + currentEntry = dataSet.getEntryForIndex(x); - filled.lineTo(e.getX(), ePrev.getY() * phaseY); + if (isDrawSteppedEnabled && previousEntry != null) { + filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY); } - filled.lineTo(e.getX(), e.getY() * phaseY); + filled.lineTo(currentEntry.getX(), currentEntry.getY() * phaseY); + + previousEntry = currentEntry; } // close up - filled.lineTo(dataSet.getEntryForIndex(bounds.range + bounds.min).getX(), fillMin); + if(currentEntry != null) { + filled.lineTo(currentEntry.getX(), fillMin); + } + filled.close(); - return filled; } @Override From 43fa1e6cecf9b194be7dc56e4a01df9f6ea3f22b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 2 Jul 2016 12:29:50 +0200 Subject: [PATCH 1076/1390] Merge #1947 --- .../mpchartexample/LineChartActivity2.java | 1 + .../mikephil/charting/charts/BarChart.java | 2 - .../charting/charts/BarLineChartBase.java | 4 + .../mikephil/charting/charts/Chart.java | 45 ------ .../charting/charts/HorizontalBarChart.java | 4 - .../mikephil/charting/data/BarDataSet.java | 3 +- .../mikephil/charting/data/BaseDataSet.java | 8 +- .../mikephil/charting/data/BubbleData.java | 8 +- .../mikephil/charting/data/BubbleDataSet.java | 4 +- .../mikephil/charting/data/CandleDataSet.java | 5 +- .../mikephil/charting/data/ChartData.java | 123 ++++++--------- .../mikephil/charting/data/CombinedData.java | 8 +- .../mikephil/charting/data/DataSet.java | 4 +- .../mikephil/charting/data/LineDataSet.java | 1 + .../mikephil/charting/data/ScatterData.java | 10 +- .../charting/highlight/ChartHighlighter.java | 16 +- .../highlight/CombinedHighlighter.java | 12 +- .../highlight/PieRadarHighlighter.java | 11 +- .../charting/highlight/RadarHighlighter.java | 12 +- .../BarLineScatterCandleBubbleRenderer.java | 24 +-- .../renderer/BubbleChartRenderer.java | 15 +- .../renderer/CandleStickChartRenderer.java | 12 +- .../renderer/CombinedChartRenderer.java | 19 +-- .../charting/renderer/LineChartRenderer.java | 147 ++++++++---------- .../renderer/ScatterChartRenderer.java | 8 +- .../charting/renderer/XAxisRenderer.java | 12 +- .../XAxisRendererHorizontalBarChart.java | 6 +- 27 files changed, 191 insertions(+), 333 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index afdf3eadd7..1508aea66b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -58,6 +58,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); + mChart.setLogEnabled(true); // no description text mChart.setDescription(""); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 05a0e1a1eb..f3d39b97f5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -105,7 +105,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { */ public RectF getBarBounds(BarEntry e) { - RectF bounds = new RectF(); getBarBounds(e, bounds); @@ -143,7 +142,6 @@ public void getBarBounds(BarEntry e, RectF outputRect){ bounds.set(left, top, right, bottom); getTransformer(set.getAxisDependency()).rectValueToPixel(outputRect); - } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index f734a59e71..33de770eb3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1280,7 +1280,9 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float return null; } + /** buffer for storing lowest visible x point */ protected PointD posForGetLowestVisibleX = PointD.getInstance(0,0); + /** * Returns the lowest x-index (value on the x-axis) that is still visible on * the chart. @@ -1295,7 +1297,9 @@ public float getLowestVisibleX() { return result; } + /** buffer for storing highest visible x point */ protected PointD posForGetHighestVisibleX = PointD.getInstance(0,0); + /** * Returns the highest x-index (value on the x-axis) that is still visible * on the chart. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 9709488bc1..c7ae8a57ff 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -12,7 +12,6 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; -import android.graphics.PointF; import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; @@ -1429,50 +1428,6 @@ public void setDrawMarkerViews(boolean enabled) { mDrawMarkerViews = enabled; } - /** - * Get all Entry objects at the given index across all DataSets. - * INFORMATION: This method does calculations at runtime. Do not over-use in - * performance critical situations. - * - * @param xIndex - * @return - */ - public List getEntriesAtIndex(int xIndex) { - - List vals = new ArrayList(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - IDataSet set = mData.getDataSetByIndex(i); - - Entry e = set.getEntryForXPos(xIndex); - - if (e != null) { - vals.add(e); - } - } - - return vals; - } - - public void getEntriesAtIndex(int xIndex, List entriesOutput){ - - List vals = entriesOutput; - vals.clear(); - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - IDataSet set = mData.getDataSetByIndex(i); - - Entry e = set.getEntryForXPos(xIndex); - - if (e != null) { - vals.add(e); - } - } - - } - /** * Returns the ChartData object that has been set for the chart. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 0c14db733a..806717a620 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.charts; import android.content.Context; -import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; @@ -18,7 +17,6 @@ import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; import com.github.mikephil.charting.utils.HorizontalViewPortHandler; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.TransformerHorizontalBarChart; import com.github.mikephil.charting.utils.Utils; @@ -209,7 +207,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { return getHighlighter().getHighlight(y, x); // switch x and y } - protected PointD posForGetLowestVisibleX = PointD.getInstance(0,0); @Override public float getLowestVisibleX() { getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), @@ -218,7 +215,6 @@ public float getLowestVisibleX() { return result; } - protected PointD posForGetHighestVisibleX = PointD.getInstance(0,0); @Override public float getHighestVisibleX() { getTransformer(AxisDependency.LEFT).getValuesByTouchPoint(mViewPortHandler.contentLeft(), diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 8e78de3397..63b5222198 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -51,11 +51,10 @@ public BarDataSet(List yVals, String label) { calcEntryCountIncludingStacks(yVals); } - protected List barEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = barEntriesForCopy; + List yVals = new ArrayList(); yVals.clear(); for (int i = 0; i < mValues.size(); i++) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 4f64c368f2..4c9f8e13e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -169,14 +169,12 @@ public void setColors(int[] colors, Context c) { if(mColors == null){ mColors = new ArrayList<>(); } - List clrs = mColors; - clrs.clear(); + + mColors.clear(); for (int color : colors) { - clrs.add(c.getResources().getColor(color)); + mColors.add(c.getResources().getColor(color)); } - - mColors = clrs; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java index c7522599a9..bf1be94a86 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import java.util.ArrayList; import java.util.List; public class BubbleData extends BarLineScatterCandleBubbleData { @@ -28,11 +27,8 @@ public BubbleData(List dataSets) { * @param width */ public void setHighlightCircleWidth(float width) { - IBubbleDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); - set.setHighlightCircleWidth(width); + for(int i = 0 ; i < mDataSets.size() ; i++){ + mDataSets.get(i).setHighlightCircleWidth(width); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 3c2858fbf7..ec288123e2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -51,12 +51,10 @@ public void calcMinMax() { } } - protected ArrayList bubbleEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = bubbleEntriesForCopy; - yVals.clear(); + List yVals = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { yVals.add(mValues.get(i).copy()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 8af41c7a80..139a1bad42 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -77,15 +77,14 @@ public CandleDataSet(List yVals, String label) { super(yVals, label); } - protected ArrayList candleEntriesForCopy = new ArrayList<>(); @Override public DataSet copy() { - List yVals = candleEntriesForCopy; + List yVals = new ArrayList(); yVals.clear(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(((CandleEntry) mValues.get(i)).copy()); + yVals.add(mValues.get(i).copy()); } CandleDataSet copied = new CandleDataSet(yVals, getLabel()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0d243c6a1c..a8496b3bfb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -80,12 +79,10 @@ public ChartData(T... dataSets) { */ private List arrayToList(T[] array) { - int setsCount = array.length; - List list = new ArrayList<>(setsCount); + List list = new ArrayList(); - T set = null; - for(int i = 0 ; i < setsCount ; i++){ - set = array[i]; + for (int i = 0; i < array.length; i++) { + T set = array[i]; list.add(set); } @@ -132,10 +129,8 @@ public void calcMinMax() { mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - T set; - int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); calcMinMax(set); } @@ -152,10 +147,9 @@ public void calcMinMax() { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - IDataSet dataSet; - int dataSetsCount = mDataSets.size(); - for(int i = 0 ; i < dataSetsCount ; i++){ - dataSet = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + + T dataSet = mDataSets.get(i); if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -174,10 +168,9 @@ public void calcMinMax() { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - IDataSet dataSet; - int dataSetsCount = mDataSets.size(); - for(int i = 0 ; i < dataSetsCount ; i++){ - dataSet = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + + T dataSet = mDataSets.get(i); if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -321,7 +314,7 @@ protected int getDataSetIndexByLabel(List dataSets, String label, * * @return */ - protected String[] getDataSetLabels() { + public String[] getDataSetLabels() { String[] types = new String[mDataSets.size()]; @@ -626,10 +619,9 @@ public int getIndexOfDataSet(T dataSet) { * @return */ protected T getFirstLeft(List sets) { - T dataSet; - int setCount = sets.size(); - for(int i = 0 ; i < setCount ; i++){ - dataSet = sets.get(i); + + for (int i = 0; i < sets.size(); i++) { + T dataSet = sets.get(i); if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; } @@ -643,10 +635,9 @@ protected T getFirstLeft(List sets) { * @return */ public T getFirstRight(List sets) { - T dataSet; - int setCount = sets.size(); - for(int i = 0 ; i < setCount ; i++){ - dataSet = sets.get(i); + + for (int i = 0; i < sets.size(); i++) { + T dataSet = sets.get(i); if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; } @@ -662,10 +653,9 @@ public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setValueFormatter(f); } } @@ -678,10 +668,9 @@ public void setValueFormatter(ValueFormatter f) { * @param color */ public void setValueTextColor(int color) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setValueTextColor(color); } } @@ -693,10 +682,9 @@ public void setValueTextColor(int color) { * @param colors */ public void setValueTextColors(List colors) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setValueTextColors(colors); } } @@ -708,10 +696,9 @@ public void setValueTextColors(List colors) { * @param tf */ public void setValueTypeface(Typeface tf) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setValueTypeface(tf); } } @@ -723,10 +710,9 @@ public void setValueTypeface(Typeface tf) { * @param size */ public void setValueTextSize(float size) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setValueTextSize(size); } } @@ -738,10 +724,9 @@ public void setValueTextSize(float size) { * @param enabled */ public void setDrawValues(boolean enabled) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setDrawValues(enabled); } } @@ -752,10 +737,9 @@ public void setDrawValues(boolean enabled) { * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); set.setHighlightEnabled(enabled); } } @@ -767,10 +751,9 @@ public void setHighlightEnabled(boolean enabled) { * @return */ public boolean isHighlightEnabled() { - IDataSet set; - final int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); if (!set.isHighlightEnabled()) return false; } @@ -782,7 +765,9 @@ public boolean isHighlightEnabled() { * forget to invalidate the chart after this. */ public void clearValues() { - mDataSets.clear(); + if (mDataSets != null) { + mDataSets.clear(); + } notifyDataChanged(); } @@ -795,10 +780,8 @@ public void clearValues() { */ public boolean contains(T dataSet) { - T set; - int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); if (set.equals(dataSet)) return true; } @@ -815,10 +798,8 @@ public int getEntryCount() { int count = 0; - T set; - int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); count += set.getEntryCount(); } @@ -837,10 +818,8 @@ public T getMaxEntryCountSet() { T max = mDataSets.get(0); - T set; - int setCount = mDataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + T set = mDataSets.get(i); if (set.getEntryCount() > max.getEntryCount()) max = set; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 2c650269b6..0b6b94437a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -193,12 +193,12 @@ public Entry getEntryForHighlight(Highlight highlight) { // The value of the highlighted entry could be NaN - // if we are not interested in highlighting a specific value. - List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) + List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) .getEntriesForXPos(highlight.getX()); - for (Object entry : entries) - if (((Entry) entry).getY() == highlight.getY() || + for (Entry entry : entries) + if (entry.getY() == highlight.getY() || Float.isNaN(highlight.getY())) - return (Entry) entry; + return entry; return null; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 84cf7c8bcb..42571e95de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -295,7 +295,6 @@ public int getEntryIndex(float xPos, Rounding rounding) { return high; } - protected ArrayList entriesForGetEntriesForXPos = new ArrayList<>(2); /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical @@ -307,8 +306,7 @@ public int getEntryIndex(float xPos, Rounding rounding) { @Override public List getEntriesForXPos(float xVal) { - List entries = entriesForGetEntriesForXPos; - entries.clear(); + List entries = new ArrayList(); int low = 0; int high = mValues.size() - 1; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 0110ecd234..c568ab0671 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -255,6 +255,7 @@ public int getCircleColor(int index) { return mCircleColors.get(index % mCircleColors.size()); } + @Override public int getCircleColorCount(){ return mCircleColors.size(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java index f34c5ae3a3..930eb04198 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java @@ -3,7 +3,6 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import java.util.ArrayList; import java.util.List; public class ScatterData extends BarLineScatterCandleBubbleData { @@ -22,18 +21,15 @@ public ScatterData(IScatterDataSet... dataSets) { /** * Returns the maximum shape-size across all DataSets. - * + * * @return */ public float getGreatestShapeSize() { float max = 0f; - - IScatterDataSet set; - final int count = mDataSets.size(); - for(int i = 0 ; i < count ; i++){ - set = mDataSets.get(i); + for (int i = 0; i < mDataSets.size(); i++) { + IScatterDataSet set = mDataSets.get(i); float size = set.getScatterShapeSize(); if (size > max) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 4f96edfce4..529ba8894a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -21,6 +21,11 @@ public class ChartHighlighter */ protected T mChart; + /** + * buffer for storing previously highlighted values + */ + protected List mHighlightBuffer = new ArrayList(); + public ChartHighlighter(T chart) { this.mChart = chart; } @@ -110,8 +115,6 @@ protected float getHighlightPos(Highlight h) { return h.getYPx(); } - - protected ArrayList highlightsForGetHighlightsAtXPos = new ArrayList<>(2); /** * Returns a list of Highlight objects representing the entries closest to the given xVal. * The returned list contains two objects per DataSet (closest rounding up, closest rounding down). @@ -123,13 +126,12 @@ protected float getHighlightPos(Highlight h) { */ protected List getHighlightsAtXPos(float xVal, float x, float y) { - List vals = highlightsForGetHighlightsAtXPos; - vals.clear(); + mHighlightBuffer.clear(); BarLineScatterCandleBubbleData data = getData(); if (data == null) - return vals; + return mHighlightBuffer; for (int i = 0, dataSetCount = data.getDataSetCount(); i < dataSetCount; i++) { @@ -142,11 +144,11 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { Highlight high = buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST); if(high != null) - vals.add(high); + mHighlightBuffer.add(high); //vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); } - return vals; + return mHighlightBuffer; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index d948cedf7c..eaff38c27c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import java.util.ArrayList; import java.util.List; /** @@ -28,13 +27,10 @@ public CombinedHighlighter(CombinedDataProvider chart, BarDataProvider barChart) barHighlighter = barChart.getBarData() == null ? null : new BarHighlighter(barChart); } - - protected ArrayList highlightsForGetHighlightsAtXPos = new ArrayList<>(2); @Override protected List getHighlightsAtXPos(float xVal, float x, float y) { - List vals = highlightsForGetHighlightsAtXPos; - vals.clear(); + mHighlightBuffer.clear(); List dataObjects = mChart.getCombinedData().getAllData(); @@ -48,7 +44,7 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { if (high != null) { high.setDataIndex(i); - vals.add(high); + mHighlightBuffer.add(high); } } else { @@ -62,7 +58,7 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.CLOSEST); s1.setDataIndex(i); - vals.add(s1); + mHighlightBuffer.add(s1); // Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); // s2.setDataIndex(i); @@ -71,7 +67,7 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { } } - return vals; + return mHighlightBuffer; } // protected Highlight getClosest(float x, float y, Highlight... highs) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java index 029212c84e..9c067de808 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java @@ -1,13 +1,7 @@ package com.github.mikephil.charting.highlight; -import android.graphics.PointF; - import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieRadarChartBase; -import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; @@ -19,6 +13,11 @@ public abstract class PieRadarHighlighter implement protected T mChart; + /** + * buffer for storing previously highlighted values + */ + protected List mHighlightBuffer = new ArrayList(); + public PieRadarHighlighter(T chart) { this.mChart = chart; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java index cb0048c477..3c4f6d03ac 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/RadarHighlighter.java @@ -1,14 +1,11 @@ package com.github.mikephil.charting.highlight; -import android.graphics.PointF; - import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; import java.util.List; /** @@ -43,8 +40,6 @@ protected Highlight getClosestHighlight(int index, float x, float y) { return closest; } - - protected ArrayList highlightsForGetHighlightsAtIndex = new ArrayList<>(2); /** * Returns an array of Highlight objects for the given index. The Highlight * objects give information about the value at the selected index and the @@ -56,8 +51,7 @@ protected Highlight getClosestHighlight(int index, float x, float y) { */ protected List getHighlightsAtIndex(int index) { - List vals = highlightsForGetHighlightsAtIndex; - vals.clear(); + mHighlightBuffer.clear(); float phaseX = mChart.getAnimator().getPhaseX(); float phaseY = mChart.getAnimator().getPhaseY(); @@ -77,9 +71,9 @@ protected List getHighlightsAtIndex(int index) { mChart.getCenterOffsets(), y * factor * phaseY, sliceangle * index * phaseX + mChart.getRotationAngle(), pOut); - vals.add(new Highlight(index, entry.getY(), pOut.x, pOut.y, i, dataSet.getAxisDependency())); + mHighlightBuffer.add(new Highlight(index, entry.getY(), pOut.x, pOut.y, i, dataSet.getAxisDependency())); } - return vals; + return mHighlightBuffer; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 9028e94704..aa400caa61 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.renderer; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; @@ -13,6 +12,8 @@ */ public abstract class BarLineScatterCandleBubbleRenderer extends DataRenderer { + /** buffer for storing the current minimum and maximum visible x */ + protected XBounds mXBounds = new XBounds(); public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); @@ -39,17 +40,6 @@ protected boolean isInBoundsX(Entry e, IBarLineScatterCandleBubbleDataSet set) { } } - /** - * Calculates and returns the x-bounds for the given DataSet in terms of index in their values array. This - * includes minimum and maximum visible x, as well as range. - * - * @param dataSet - * @return - */ - protected XBounds getXBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { - return new XBounds(chart, dataSet); - } - /** * Class representing the bounds of the current viewport in terms of indices in the values array of a DataSet. */ @@ -70,16 +60,6 @@ protected class XBounds { */ public int range; - /** - * Calculates the minimum and maximum x values as well as the range between them. - * - * @param chart - * @param dataSet - */ - public XBounds(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { - this.set(chart, dataSet); - } - /** * Calculates the minimum and maximum x values as well as the range between them. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 0712c0f84a..6ff540cc7c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -50,7 +49,7 @@ public void drawData(Canvas c) { IBubbleDataSet set; List dataSets = bubbleData.getDataSets(); int setCount = dataSets.size(); - for(int i = 0 ; i < setCount ; i++){ + for (int i = 0; i < setCount; i++) { set = dataSets.get(i); if (set.isVisible() && set.getEntryCount() > 0) @@ -74,7 +73,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { float phaseY = mAnimator.getPhaseY(); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); sizeBuffer[0] = 0f; sizeBuffer[2] = 1f; @@ -88,7 +87,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { + for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { final BubbleEntry entry = dataSet.getEntryForIndex(j); @@ -143,16 +142,16 @@ public void drawValues(Canvas c) { final float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); final float phaseY = mAnimator.getPhaseY(); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) - .generateTransformedValuesBubble(dataSet, phaseY, bounds.min, bounds.max); + .generateTransformedValuesBubble(dataSet, phaseY, mXBounds.min, mXBounds.max); final float alpha = phaseX == 1 ? phaseY : phaseX; for (int j = 0; j < positions.length; j += 2) { - int valueTextColor = dataSet.getValueTextColor(j / 2 + bounds.min); + int valueTextColor = dataSet.getValueTextColor(j / 2 + mXBounds.min); valueTextColor = Color.argb(Math.round(255.f * alpha), Color.red(valueTextColor), Color.green(valueTextColor), Color.blue(valueTextColor)); @@ -165,7 +164,7 @@ public void drawValues(Canvas c) { if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; - BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); + BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, y + (0.5f * lineHeight), valueTextColor); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 9a1842221e..3b99a074f5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -47,7 +47,7 @@ public void drawData(Canvas c) { ICandleDataSet set; List dataSets = candleData.getDataSets(); int setCount = dataSets.size(); - for(int i = 0 ; i < setCount ; i++){ + for (int i = 0; i < setCount; i++) { set = dataSets.get(i); if (set.isVisible() && set.getEntryCount() > 0) @@ -64,12 +64,12 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { float barSpace = dataSet.getBarSpace(); boolean showCandleBar = dataSet.getShowCandleBar(); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); // draw the body - for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { + for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { // get the entry CandleEntry e = dataSet.getEntryForIndex(j); @@ -274,10 +274,10 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); float[] positions = trans.generateTransformedValuesCandle( - dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), bounds.min, bounds.max); + dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), mXBounds.min, mXBounds.max); float yOffset = Utils.convertDpToPixel(5f); @@ -292,7 +292,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - CandleEntry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); + CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet .getValueTextColor(j / 2)); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index f6c671d1cf..142dff4346 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -23,7 +23,7 @@ public class CombinedChartRenderer extends DataRenderer { /** * all rederers for the different kinds of data this combined-renderer can draw */ - protected List mRenderers; + protected List mRenderers = new ArrayList(5); protected WeakReference mChart; @@ -33,7 +33,6 @@ public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPo createRenderers(chart, animator, viewPortHandler); } - protected ArrayList renderersForCreateRenderers = new ArrayList<>(4); /** * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into * consideration. @@ -44,7 +43,6 @@ public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPo */ protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { - mRenderers = renderersForCreateRenderers; mRenderers.clear(); DrawOrder[] orders = chart.getDrawOrder(); @@ -104,7 +102,8 @@ public void drawExtras(Canvas c) { renderer.drawExtras(c); } - protected ArrayList highlightsforDrawHighlighted = new ArrayList<>(); + protected List mHighlightBuffer = new ArrayList(); + @Override public void drawHighlighted(Canvas c, Highlight[] indices) { @@ -128,16 +127,14 @@ else if (renderer instanceof BubbleChartRenderer) int dataIndex = data == null ? -1 : ((CombinedData)chart.getData()).getAllData().indexOf(data); - ArrayList dataIndices = highlightsforDrawHighlighted; - dataIndices.clear(); - Highlight h; - for(int i = 0 ; i < dataIndices.size() ; i++){ - h = dataIndices.get(i); + mHighlightBuffer.clear(); + + for (Highlight h : indices) { if (h.getDataIndex() == dataIndex || h.getDataIndex() == -1) - dataIndices.add(h); + mHighlightBuffer.add(h); } - renderer.drawHighlighted(c, dataIndices.toArray(new Highlight[dataIndices.size()])); + renderer.drawHighlighted(c, mHighlightBuffer.toArray(new Highlight[mHighlightBuffer.size()])); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index f6cbccfefd..87f273ff0a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -29,26 +29,25 @@ public class LineChartRenderer extends LineRadarRenderer { private class DataSetImageCache { - private Bitmap[] circleBitmaps; private int[] circleColors; - private void ensureCircleCache(int size){ - if(circleBitmaps == null){ + private void ensureCircleCache(int size) { + if (circleBitmaps == null) { circleBitmaps = new Bitmap[size]; - }else if(circleBitmaps.length < size){ + } else if (circleBitmaps.length < size) { Bitmap[] tmp = new Bitmap[size]; - for(int i = 0 ; i < circleBitmaps.length ; i++){ + for (int i = 0; i < circleBitmaps.length; i++) { tmp[i] = circleBitmaps[size]; } circleBitmaps = tmp; } - if(circleColors == null){ + if (circleColors == null) { circleColors = new int[size]; - }else if(circleColors.length < size){ + } else if (circleColors.length < size) { int[] tmp = new int[size]; - for(int i = 0 ; i < circleColors.length ; i++){ + for (int i = 0; i < circleColors.length; i++) { tmp[i] = circleColors[size]; } circleColors = tmp; @@ -124,7 +123,7 @@ public void drawData(Canvas c) { ILineDataSet set; int setCount = lineData.getDataSets().size(); - for(int i = 0 ; i < setCount ; i++){ + for (int i = 0; i < setCount; i++) { set = lineData.getDataSets().get(i); if (set.isVisible() && set.getEntryCount() > 0) @@ -167,19 +166,19 @@ protected void drawHorizontalBezier(ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); cubicPath.reset(); - if (bounds.range >= 1) { + if (mXBounds.range >= 1) { - Entry prev = dataSet.getEntryForIndex(bounds.min); + Entry prev = dataSet.getEntryForIndex(mXBounds.min); Entry cur = prev; // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); - for (int j = bounds.min + 1; j <= bounds.range + bounds.min; j++) { + for (int j = mXBounds.min + 1; j <= mXBounds.range + mXBounds.min; j++) { prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); @@ -200,7 +199,7 @@ protected void drawHorizontalBezier(ILineDataSet dataSet) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, bounds); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, mXBounds); } mRenderPaint.setColor(dataSet.getColor()); @@ -221,33 +220,33 @@ protected void drawCubicBezier(ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); float intensity = dataSet.getCubicIntensity(); cubicPath.reset(); - if (bounds.range >= 1) { + if (mXBounds.range >= 1) { float prevDx = 0f; float prevDy = 0f; float curDx = 0f; float curDy = 0f; - Entry prevPrev = dataSet.getEntryForIndex(bounds.min); + Entry prevPrev = dataSet.getEntryForIndex(mXBounds.min); Entry prev = prevPrev; Entry cur = prev; - Entry next = dataSet.getEntryForIndex(bounds.min + 1); + Entry next = dataSet.getEntryForIndex(mXBounds.min + 1); // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); - for (int j = bounds.min + 1; j <= bounds.range + bounds.min; j++) { + for (int j = mXBounds.min + 1; j <= mXBounds.range + mXBounds.min; j++) { prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); prev = dataSet.getEntryForIndex(j - 1); cur = dataSet.getEntryForIndex(j); - next = bounds.max > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; + next = mXBounds.max > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; prevDx = (cur.getX() - prevPrev.getX()) * intensity; prevDy = (cur.getY() - prevPrev.getY()) * intensity; @@ -266,7 +265,7 @@ protected void drawCubicBezier(ILineDataSet dataSet) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, bounds); + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, mXBounds); } mRenderPaint.setColor(dataSet.getColor()); @@ -302,7 +301,6 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf } private float[] mLineBuffer = new float[4]; - private XBounds xBoundsBuffer; /** * Draws a normal line. @@ -332,12 +330,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { canvas = c; } - if(xBoundsBuffer == null){ - xBoundsBuffer = getXBounds(mChart, dataSet); - }else{ - xBoundsBuffer.set(mChart, dataSet); - } - final XBounds bounds = xBoundsBuffer; + mXBounds.set(mChart, dataSet); // more than 1 color if (dataSet.getColors().size() > 1) { @@ -345,7 +338,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (mLineBuffer.length <= pointsPerEntryPair * 2) mLineBuffer = new float[pointsPerEntryPair * 4]; - for (int j = bounds.min; j <= bounds.range + bounds.min; j++) { + for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; @@ -353,7 +346,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[0] = e.getX(); mLineBuffer[1] = e.getY() * phaseY; - if (j < bounds.max) { + if (j < mXBounds.max) { e = dataSet.getEntryForIndex(j + 1); @@ -403,12 +396,12 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { Entry e1, e2; - e1 = dataSet.getEntryForIndex(bounds.min); + e1 = dataSet.getEntryForIndex(mXBounds.min); if (e1 != null) { int j = 0; - for (int x = bounds.min; x <= bounds.range + bounds.min; x++) { + for (int x = mXBounds.min; x <= mXBounds.range + mXBounds.min; x++) { e1 = dataSet.getEntryForIndex(x == 0 ? 0 : (x - 1)); e2 = dataSet.getEntryForIndex(x); @@ -432,7 +425,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (j > 0) { trans.pointValuesToPixel(mLineBuffer); - final int size = Math.max((bounds.range + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; + final int size = Math.max((mXBounds.range + 1) * pointsPerEntryPair, pointsPerEntryPair) * 2; mRenderPaint.setColor(dataSet.getColor()); @@ -445,7 +438,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // if drawing filled is enabled if (dataSet.isDrawFilledEnabled() && entryCount > 0) { - drawLinearFill(c, dataSet, trans, bounds); + drawLinearFill(c, dataSet, trans, mXBounds); } } @@ -472,16 +465,15 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, int iterations = 0; // Doing this iteratively in order to avoid OutOfMemory errors that can happen on large bounds sets. - do{ + do { currentStartIndex = startingIndex + (iterations * indexInterval); currentEndIndex = currentStartIndex + indexInterval; currentEndIndex = currentEndIndex > endingIndex ? endingIndex : currentEndIndex; - if(currentStartIndex <= currentEndIndex) { + if (currentStartIndex <= currentEndIndex) { generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); - trans.pathValueToPixel(filled); final Drawable drawable = dataSet.getFillDrawable(); @@ -496,18 +488,17 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, iterations++; - }while(currentStartIndex <= currentEndIndex); + } while (currentStartIndex <= currentEndIndex); } /** * Generates a path that is used for filled drawing. * - * @param dataSet The dataset from which to read the entries. + * @param dataSet The dataset from which to read the entries. * @param startIndex The index from which to start reading the dataset - * @param endIndex The index from which to stop reading the dataset + * @param endIndex The index from which to stop reading the dataset * @param outputPath The path object that will be assigned the chart data. - * * @return */ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex, final int endIndex, final Path outputPath) { @@ -527,7 +518,7 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex // create a new path Entry currentEntry = null; Entry previousEntry = null; - for (int x = startIndex + 1 ; x <= endIndex ; x++) { + for (int x = startIndex + 1; x <= endIndex; x++) { currentEntry = dataSet.getEntryForIndex(x); @@ -541,7 +532,7 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex } // close up - if(currentEntry != null) { + if (currentEntry != null) { filled.lineTo(currentEntry.getX(), fillMin); } @@ -574,10 +565,10 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator - .getPhaseY(), bounds.min, bounds.max); + .getPhaseY(), mXBounds.min, mXBounds.max); for (int j = 0; j < positions.length; j += 2) { @@ -590,7 +581,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - Entry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); + Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, y - valOffset, dataSet.getValueTextColor(j / 2)); @@ -607,28 +598,27 @@ public void drawExtras(Canvas c) { private Path mCirclePathBuffer = new Path(); private float[] mCirclesBuffer = new float[2]; private HashMap mImageCaches = new HashMap<>(); - private XBounds mXBoundsBuffer; + protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); float phaseY = mAnimator.getPhaseY(); - float[] circlesBuffer = mCirclesBuffer; - circlesBuffer[0] = 0; - circlesBuffer[1] = 0; + mCirclesBuffer[0] = 0; + mCirclesBuffer[1] = 0; List dataSets = mChart.getLineData().getDataSets(); - final int dataSetCount = dataSets.size(); - for (int i = 0; i < dataSetCount ; i++) { + + for (int i = 0; i < dataSets.size(); i++) { ILineDataSet dataSet = dataSets.get(i); DataSetImageCache imageCache; - if(mImageCaches.containsKey(dataSet)){ + if (mImageCaches.containsKey(dataSet)) { imageCache = mImageCaches.get(dataSet); - }else{ + } else { imageCache = new DataSetImageCache(); mImageCaches.put(dataSet, imageCache); } @@ -642,13 +632,7 @@ protected void drawCircles(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - if(mXBoundsBuffer == null) { - mXBoundsBuffer = getXBounds(mChart, dataSet); - }else{ - mXBoundsBuffer.set(mChart,dataSet); - } - - XBounds bounds = mXBoundsBuffer; + mXBounds.set(mChart, dataSet); float circleRadius = dataSet.getCircleRadius(); float circleHoleRadius = dataSet.getCircleHoleRadius(); @@ -658,24 +642,26 @@ protected void drawCircles(Canvas c) { boolean drawTransparentCircleHole = drawCircleHole && dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; - int boundsRangeCount = bounds.range + bounds.min; - for (int j = bounds.min; j <= boundsRangeCount; j++) { + int boundsRangeCount = mXBounds.range + mXBounds.min; + + for (int j = mXBounds.min; j <= boundsRangeCount; j++) { + Entry e = dataSet.getEntryForIndex(j); if (e == null) break; - circlesBuffer[0] = e.getX(); - circlesBuffer[1] = e.getY() * phaseY; + mCirclesBuffer[0] = e.getX(); + mCirclesBuffer[1] = e.getY() * phaseY; - trans.pointValuesToPixel(circlesBuffer); + trans.pointValuesToPixel(mCirclesBuffer); - if (!mViewPortHandler.isInBoundsRight(circlesBuffer[0])) + if (!mViewPortHandler.isInBoundsRight(mCirclesBuffer[0])) break; // make sure the circles don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(circlesBuffer[0]) || - !mViewPortHandler.isInBoundsY(circlesBuffer[1])) + if (!mViewPortHandler.isInBoundsLeft(mCirclesBuffer[0]) || + !mViewPortHandler.isInBoundsY(mCirclesBuffer[1])) continue; final int circleColor = dataSet.getCircleColor(j); @@ -683,28 +669,27 @@ protected void drawCircles(Canvas c) { Bitmap circleBitmap = null; - final int dataSetColorCount = imageCache.circleColors.length; int colorIndex; - for(colorIndex = 0 ; colorIndex < dataSetColorCount ; colorIndex++) { + + for (colorIndex = 0; colorIndex < imageCache.circleColors.length; colorIndex++) { int tempColor = imageCache.circleColors[colorIndex]; Bitmap tempBitmap = imageCache.circleBitmaps[colorIndex]; - if(tempColor == circleColor) { + if (tempColor == circleColor) { circleBitmap = tempBitmap; break; - }else if(tempBitmap == null){ + } else if (tempBitmap == null) { break; } } - - if(circleBitmap == null){ + if (circleBitmap == null) { Bitmap.Config conf = Bitmap.Config.ARGB_8888; - circleBitmap = Bitmap.createBitmap((int)(circleRadius * 2.1), (int)(circleRadius * 2.1), conf); + circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1), (int) (circleRadius * 2.1), conf); Canvas canvas = new Canvas(circleBitmap); imageCache.circleBitmaps[colorIndex] = circleBitmap; imageCache.circleColors[colorIndex] = circleColor; - if(drawTransparentCircleHole){ + if (drawTransparentCircleHole) { // Begin path for circle with hole mCirclePathBuffer.reset(); @@ -723,7 +708,7 @@ protected void drawCircles(Canvas c) { // Fill in-between canvas.drawPath(mCirclePathBuffer, mRenderPaint); - }else{ + } else { canvas.drawCircle( circleRadius, @@ -741,10 +726,8 @@ protected void drawCircles(Canvas c) { } } - if(circleBitmap != null){ - - c.drawBitmap(circleBitmap, circlesBuffer[0] - circleRadius, circlesBuffer[1] - circleRadius, mRenderPaint); - + if (circleBitmap != null) { + c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, mRenderPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 026f975b57..9439cbfd6f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -100,11 +100,11 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - XBounds bounds = getXBounds(mChart, dataSet); + mXBounds.set(mChart, dataSet); float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesScatter(dataSet, - mAnimator.getPhaseX(), mAnimator.getPhaseY(), bounds.min, bounds.max); + mAnimator.getPhaseX(), mAnimator.getPhaseY(), mXBounds.min, mXBounds.max); float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); @@ -118,10 +118,10 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; - Entry entry = dataSet.getEntryForIndex(j / 2 + bounds.min); + Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, positions[j], - positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + bounds.min)); + positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min)); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 8a73bced5c..d112cf92de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -170,7 +170,6 @@ public void renderAxisLine(Canvas c) { } } - protected float[] mDrawLabelsBuffer = new float[2]; /** * draws the x-labels on the specified y-position * @@ -181,12 +180,9 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - if(mDrawLabelsBuffer.length < mAxis.mEntryCount * 2){ - mDrawLabelsBuffer = new float[mXAxis.mEntryCount * 2]; - } - float[] positions = mDrawLabelsBuffer; + float[] positions = new float[mXAxis.mEntryCount * 2]; - for (int i = 0; i < positions.length && i < mXAxis.mEntries.length / 2 && i < mXAxis.mCenteredEntries.length / 2 ; i += 2) { + for (int i = 0; i < positions.length; i += 2) { // only fill x values if (centeringEnabled) { @@ -194,13 +190,11 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { } else { positions[i] = mXAxis.mEntries[i / 2]; } - // init to 0 - positions[i+1] = 0; } mTrans.pointValuesToPixel(positions); - for (int i = 0; i < positions.length && i < mXAxis.mEntries.length / 2 && i < mXAxis.mCenteredEntries.length / 2 ; i += 2) { + for (int i = 0; i < positions.length; i += 2) { float x = positions[i]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index e050af3c13..68b280df2d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -129,17 +129,13 @@ public void renderAxisLabels(Canvas c) { MPPointF.recycleInstance(pointF); } - protected float[] mDrawLabelsBuffer = new float[2]; @Override protected void drawLabels(Canvas c, float pos, MPPointF anchor) { final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); boolean centeringEnabled = mXAxis.isCenterAxisLabelsEnabled(); - if(mDrawLabelsBuffer.length != mAxis.mEntryCount * 2){ - mDrawLabelsBuffer = new float[mXAxis.mEntryCount * 2]; - } - float[] positions = mDrawLabelsBuffer; + float[] positions = new float[mXAxis.mEntryCount * 2]; for (int i = 0; i < positions.length; i += 2) { From 6d21817c8aed43dae6deb1bf7bb835518ecbe2f6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 2 Jul 2016 12:36:16 +0200 Subject: [PATCH 1077/1390] Rename PointD to MPPointD --- .../charting/charts/BarLineChartBase.java | 34 +++++++++---------- .../charting/highlight/BarHighlighter.java | 10 +++--- .../charting/highlight/ChartHighlighter.java | 14 ++++---- .../highlight/HorizontalBarHighlighter.java | 8 ++--- .../charting/renderer/AxisRenderer.java | 10 +++--- .../renderer/CandleStickChartRenderer.java | 4 +-- .../charting/renderer/LineChartRenderer.java | 4 +-- .../renderer/ScatterChartRenderer.java | 4 +-- .../charting/renderer/XAxisRenderer.java | 10 +++--- .../XAxisRendererHorizontalBarChart.java | 10 +++--- .../charting/renderer/YAxisRenderer.java | 4 +-- .../YAxisRendererHorizontalBarChart.java | 12 +++---- .../utils/{PointD.java => MPPointD.java} | 20 +++++------ .../mikephil/charting/utils/MPPointF.java | 1 + .../mikephil/charting/utils/Transformer.java | 16 ++++----- 15 files changed, 81 insertions(+), 80 deletions(-) rename MPChartLib/src/main/java/com/github/mikephil/charting/utils/{PointD.java => MPPointD.java} (55%) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 33de770eb3..a794c6a5ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -31,8 +31,8 @@ import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -683,14 +683,14 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa if (android.os.Build.VERSION.SDK_INT >= 11) { - PointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); - PointD.recycleInstance(origin); + MPPointD.recycleInstance(origin); } else { Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); @@ -848,7 +848,7 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, if (android.os.Build.VERSION.SDK_INT >= 11) { - PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); @@ -857,7 +857,7 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, addViewportJob(job); - PointD.recycleInstance(bounds); + MPPointD.recycleInstance(bounds); } else { Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); } @@ -915,7 +915,7 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis if (android.os.Build.VERSION.SDK_INT >= 11) { - PointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); @@ -926,7 +926,7 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis addViewportJob(job); - PointD.recycleInstance(bounds); + MPPointD.recycleInstance(bounds); } else { Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); } @@ -1202,9 +1202,9 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { } /** - * Returns a recyclable PointD instance + * Returns a recyclable MPPointD instance * Returns the x and y values in the chart at the given touch point - * (encapsulated in a PointD). This method transforms pixel coordinates to + * (encapsulated in a MPPointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). * @@ -1212,18 +1212,18 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { * @param y * @return */ - public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { - PointD result = PointD.getInstance(0,0); + public MPPointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { + MPPointD result = MPPointD.getInstance(0,0); getValuesByTouchPoint(x,y,axis,result); return result; } - public void getValuesByTouchPoint(float x, float y, AxisDependency axis, PointD outputPoint){ + public void getValuesByTouchPoint(float x, float y, AxisDependency axis, MPPointD outputPoint){ getTransformer(axis).getValuesByTouchPoint(x, y, outputPoint); } /** - * Returns a recyclable PointD instance + * Returns a recyclable MPPointD instance * Transforms the given chart values into pixels. This is the opposite * method to getValuesByTouchPoint(...). * @@ -1231,11 +1231,11 @@ public void getValuesByTouchPoint(float x, float y, AxisDependency axis, PointD * @param y * @return */ - public PointD getPixelsForValues(float x, float y, AxisDependency axis) { + public MPPointD getPixelsForValues(float x, float y, AxisDependency axis) { return getTransformer(axis).getPixelsForValues(x, y); } - PointD pointForGetYValueByTouchPoint = PointD.getInstance(0,0); + MPPointD pointForGetYValueByTouchPoint = MPPointD.getInstance(0,0); /** * Returns y value at the given touch position (must not necessarily be * a value contained in one of the datasets) @@ -1281,7 +1281,7 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float } /** buffer for storing lowest visible x point */ - protected PointD posForGetLowestVisibleX = PointD.getInstance(0,0); + protected MPPointD posForGetLowestVisibleX = MPPointD.getInstance(0,0); /** * Returns the lowest x-index (value on the x-axis) that is still visible on @@ -1298,7 +1298,7 @@ public float getLowestVisibleX() { } /** buffer for storing highest visible x point */ - protected PointD posForGetHighestVisibleX = PointD.getInstance(0,0); + protected MPPointD posForGetHighestVisibleX = MPPointD.getInstance(0,0); /** * Returns the highest x-index (value on the x-axis) that is still visible diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index c0b58947e1..1adad89de1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; /** * Created by Philipp Jahoda on 22/07/15. @@ -24,7 +24,7 @@ public Highlight getHighlight(float x, float y) { return null; } - PointD pos = getValsForTouch(x, y); + MPPointD pos = getValsForTouch(x, y); BarData barData = mChart.getBarData(); @@ -37,7 +37,7 @@ public Highlight getHighlight(float x, float y) { (float) pos.y); } - PointD.recycleInstance(pos); + MPPointD.recycleInstance(pos); return high; } @@ -68,7 +68,7 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal if (ranges.length > 0) { int stackIndex = getClosestStackIndex(ranges, yVal); - PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), ranges[stackIndex].to); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), ranges[stackIndex].to); Highlight stackedHigh = new Highlight( entry.getX(), @@ -80,7 +80,7 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal high.getAxis() ); - PointD.recycleInstance(pixels); + MPPointD.recycleInstance(pixels); return stackedHigh; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 529ba8894a..c3aa4560d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import java.util.ArrayList; import java.util.List; @@ -33,26 +33,26 @@ public ChartHighlighter(T chart) { @Override public Highlight getHighlight(float x, float y) { - PointD pos = getValsForTouch(x, y); + MPPointD pos = getValsForTouch(x, y); float xVal = (float) pos.x; - PointD.recycleInstance(pos); + MPPointD.recycleInstance(pos); Highlight high = getHighlightForX(xVal, x, y); return high; } /** - * Returns a recyclable PointD instance. + * Returns a recyclable MPPointD instance. * Returns the corresponding xPos for a given touch-position in pixels. * * @param x * @param y * @return */ - protected PointD getValsForTouch(float x, float y) { + protected MPPointD getValsForTouch(float x, float y) { // take any transformer to determine the x-axis value - PointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, y); + MPPointD pos = mChart.getTransformer(YAxis.AxisDependency.LEFT).getValuesByTouchPoint(x, y); return pos; } @@ -167,7 +167,7 @@ protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, D if (e == null) return null; - PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index ce1220027e..626868c3de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; /** * Created by Philipp Jahoda on 22/07/15. @@ -22,7 +22,7 @@ public Highlight getHighlight(float x, float y) { BarData barData = mChart.getBarData(); - PointD pos = getValsForTouch(y, x); + MPPointD pos = getValsForTouch(y, x); Highlight high = getHighlightForX((float) pos.y, y, x); if (high == null) @@ -37,7 +37,7 @@ public Highlight getHighlight(float x, float y) { (float) pos.x); } - PointD.recycleInstance(pos); + MPPointD.recycleInstance(pos); return high; } @@ -47,7 +47,7 @@ protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, D final Entry e = set.getEntryForXPos(xVal, rounding); - PointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX()); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX()); return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index f1d4ff0981..1b9c82364a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -7,7 +7,7 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -121,8 +121,8 @@ public void computeAxis(float min, float max, boolean inverted) { // zoom / contentrect bounds) if (mViewPortHandler != null && mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); if (!inverted) { @@ -134,8 +134,8 @@ public void computeAxis(float min, float max, boolean inverted) { max = (float) p2.y; } - PointD.recycleInstance(p1); - PointD.recycleInstance(p2); + MPPointD.recycleInstance(p1); + MPPointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 3b99a074f5..2aa11482f0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -326,7 +326,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float highValue = e.getHigh() * mAnimator.getPhaseY(); float y = (lowValue + highValue) / 2f; - PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), y); + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), y); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 87f273ff0a..d478024808 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -17,7 +17,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -750,7 +750,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!isInBoundsX(e, set)) continue; - PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator .getPhaseY()); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 9439cbfd6f..1d45c4974d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -148,7 +148,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!isInBoundsX(e, set)) continue; - PointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator .getPhaseY()); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index d112cf92de..1973aa3a47 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -46,8 +46,8 @@ public void computeAxis(float min, float max, boolean inverted) { // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); + MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); if (inverted) { @@ -59,8 +59,8 @@ public void computeAxis(float min, float max, boolean inverted) { max = (float) p2.x; } - PointD.recycleInstance(p1); - PointD.recycleInstance(p2); + MPPointD.recycleInstance(p1); + MPPointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 68b280df2d..02192f5a47 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -37,8 +37,8 @@ public void computeAxis(float min, float max, boolean inverted) { // zoom / contentrect bounds) if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); if (inverted) { @@ -50,8 +50,8 @@ public void computeAxis(float min, float max, boolean inverted) { max = (float) p2.y; } - PointD.recycleInstance(p1); - PointD.recycleInstance(p2); + MPPointD.recycleInstance(p1); + MPPointD.recycleInstance(p2); } computeAxisValues(min, max); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index b550579d29..71cfbf324e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -203,7 +203,7 @@ protected float[] getTransformedPositions() { protected void drawZeroLine(Canvas c) { // draw zero line - PointD pos = mTrans.getPixelsForValues(0f, 0f); + MPPointD pos = mTrans.getPixelsForValues(0f, 0f); mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 21e16ba325..3f9f36a965 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; -import com.github.mikephil.charting.utils.PointD; +import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -39,9 +39,9 @@ public void computeAxis(float yMin, float yMax, boolean inverted) { // zoom / contentrect bounds) if (mViewPortHandler.contentHeight() > 10 && !mViewPortHandler.isFullyZoomedOutX()) { - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), + MPPointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), + MPPointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentRight(), mViewPortHandler.contentTop()); if (!inverted) { @@ -52,8 +52,8 @@ public void computeAxis(float yMin, float yMax, boolean inverted) { yMax = (float) p1.x; } - PointD.recycleInstance(p1); - PointD.recycleInstance(p2); + MPPointD.recycleInstance(p1); + MPPointD.recycleInstance(p2); } computeAxisValues(yMin, yMax); @@ -179,7 +179,7 @@ protected Path linePath(Path p, int i, float[] positions) { protected void drawZeroLine(Canvas c) { // draw zero line - PointD pos = mTrans.getPixelsForValues(0f, 0f); + MPPointD pos = mTrans.getPixelsForValues(0f, 0f); mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointD.java similarity index 55% rename from MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointD.java index c69c4da7d3..f6220a72e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/PointD.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointD.java @@ -8,27 +8,27 @@ * * @author Philipp Jahoda */ -public class PointD extends ObjectPool.Poolable { +public class MPPointD extends ObjectPool.Poolable { - private static ObjectPool pool; + private static ObjectPool pool; static { - pool = ObjectPool.create(64, new PointD(0,0)); + pool = ObjectPool.create(64, new MPPointD(0,0)); pool.setReplenishPercentage(0.5f); } - public static PointD getInstance(double x, double y){ - PointD result = pool.get(); + public static MPPointD getInstance(double x, double y){ + MPPointD result = pool.get(); result.x = x; result.y = y; return result; } - public static void recycleInstance(PointD instance){ + public static void recycleInstance(MPPointD instance){ pool.recycle(instance); } - public static void recycleInstances(List instances){ + public static void recycleInstances(List instances){ pool.recycle(instances); } @@ -36,10 +36,10 @@ public static void recycleInstances(List instances){ public double y; protected ObjectPool.Poolable instantiate(){ - return new PointD(0,0); + return new MPPointD(0,0); } - private PointD(double x, double y) { + private MPPointD(double x, double y) { this.x = x; this.y = y; } @@ -48,6 +48,6 @@ private PointD(double x, double y) { * returns a string representation of the object */ public String toString() { - return "PointD, x: " + x + ", y: " + y; + return "MPPointD, x: " + x + ", y: " + y; } } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java index f2e6c71fea..2e3fc58934 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java @@ -9,6 +9,7 @@ * Created by Tony Patino on 6/24/16. */ public class MPPointF extends ObjectPool.Poolable { + private static ObjectPool pool; public float x; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index e842084936..be6d4cefe8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -385,9 +385,9 @@ public void pixelsToValue(float[] pixels) { float[] ptsBuffer = new float[2]; /** - * Returns a recyclable PointD instance. + * Returns a recyclable MPPointD instance. * returns the x and y values in the chart at the given touch point - * (encapsulated in a PointD). This method transforms pixel coordinates to + * (encapsulated in a MPPointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). * @@ -395,14 +395,14 @@ public void pixelsToValue(float[] pixels) { * @param y * @return */ - public PointD getValuesByTouchPoint(float x, float y) { + public MPPointD getValuesByTouchPoint(float x, float y) { - PointD result = PointD.getInstance(0,0); + MPPointD result = MPPointD.getInstance(0,0); getValuesByTouchPoint(x,y,result); return result; } - public void getValuesByTouchPoint(float x, float y, PointD outputPoint){ + public void getValuesByTouchPoint(float x, float y, MPPointD outputPoint){ ptsBuffer[0] = x; ptsBuffer[1] = y; @@ -414,14 +414,14 @@ public void getValuesByTouchPoint(float x, float y, PointD outputPoint){ } /** - * Returns a recyclable PointD instance. + * Returns a recyclable MPPointD instance. * Returns the x and y coordinates (pixels) for a given x and y value in the chart. * * @param x * @param y * @return */ - public PointD getPixelsForValues(float x, float y) { + public MPPointD getPixelsForValues(float x, float y) { ptsBuffer[0] = x; ptsBuffer[1] = y; @@ -431,7 +431,7 @@ public PointD getPixelsForValues(float x, float y) { double xPx = ptsBuffer[0]; double yPx = ptsBuffer[1]; - return PointD.getInstance(xPx, yPx); + return MPPointD.getInstance(xPx, yPx); } public Matrix getValueMatrix() { From 94a67ccea00bebd7e82ad73e2e52aa68a12c999e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 2 Jul 2016 21:05:00 +0200 Subject: [PATCH 1078/1390] Fixes & improvements related to circle cache --- MPChartExample/build.gradle | 2 +- .../mpchartexample/LineChartActivity2.java | 19 +- .../mikephil/charting/data/LineDataSet.java | 82 +++--- .../charting/renderer/LineChartRenderer.java | 233 ++++++++++-------- 4 files changed, 186 insertions(+), 150 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index b9dff17945..f0ed2a5a33 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -56,7 +56,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.0@aar' + compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.2@aar' compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:23.1.1' diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 1508aea66b..738e08814a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -193,7 +193,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.CUBIC_BEZIER); + : LineDataSet.Mode.CUBIC_BEZIER); } mChart.invalidate(); break; @@ -207,7 +207,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.STEPPED ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.STEPPED); + : LineDataSet.Mode.STEPPED); } mChart.invalidate(); break; @@ -221,7 +221,7 @@ public boolean onOptionsItemSelected(MenuItem item) { LineDataSet set = (LineDataSet) iSet; set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER ? LineDataSet.Mode.LINEAR - : LineDataSet.Mode.HORIZONTAL_BEZIER); + : LineDataSet.Mode.HORIZONTAL_BEZIER); } mChart.invalidate(); break; @@ -306,8 +306,8 @@ private void setData(int count, float range) { if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); + set1 = (LineDataSet) mChart.getData().getDataSetByIndex(0); + set2 = (LineDataSet) mChart.getData().getDataSetByIndex(1); set1.setValues(yVals1); set2.setValues(yVals2); mChart.getData().notifyDataChanged(); @@ -361,9 +361,12 @@ private void setData(int count, float range) { public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); - mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(h.getDataSetIndex()).getAxisDependency(), 500); - //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); - //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex).getAxisDependency(), 1000); + mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + .getAxisDependency(), 500); + //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + // .getAxisDependency(), 1000); + //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + // .getAxisDependency(), 1000); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index c568ab0671..0d7147e5dd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -5,10 +5,10 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -16,31 +16,49 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet { - /** Drawing mode for this line dataset **/ + /** + * Drawing mode for this line dataset + **/ private LineDataSet.Mode mMode = Mode.LINEAR; - /** List representing all colors that are used for the circles */ + /** + * List representing all colors that are used for the circles + */ private List mCircleColors = null; - /** the color of the inner circles */ + /** + * the color of the inner circles + */ private int mCircleColorHole = Color.WHITE; - /** the radius of the circle-shaped value indicators */ + /** + * the radius of the circle-shaped value indicators + */ private float mCircleRadius = 8f; - /** the hole radius of the circle-shaped value indicators */ + /** + * the hole radius of the circle-shaped value indicators + */ private float mCircleHoleRadius = 4f; - /** sets the intensity of the cubic lines */ + /** + * sets the intensity of the cubic lines + */ private float mCubicIntensity = 0.2f; - /** the path effect of this DataSet that makes dashed lines possible */ + /** + * the path effect of this DataSet that makes dashed lines possible + */ private DashPathEffect mDashPathEffect = null; - /** formatter for customizing the position of the fill-line */ + /** + * formatter for customizing the position of the fill-line + */ private FillFormatter mFillFormatter = new DefaultFillFormatter(); - /** if true, drawing circles is enabled */ + /** + * if true, drawing circles is enabled + */ private boolean mDrawCircles = true; private boolean mDrawCircleHole = true; @@ -52,11 +70,11 @@ public LineDataSet(List yVals, String label) { // mCircleRadius = Utils.convertDpToPixel(4f); // mLineWidth = Utils.convertDpToPixel(1f); - if(mCircleColors == null) { + if (mCircleColors == null) { mCircleColors = new ArrayList(); } mCircleColors.clear(); - + // default colors // mColors.add(Color.rgb(192, 255, 140)); // mColors.add(Color.rgb(255, 247, 140)); @@ -108,7 +126,7 @@ public void setMode(LineDataSet.Mode mode) { /** * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, * Min = 0.05f = low cubic effect, Default: 0.2f - * + * * @param intensity */ public void setCubicIntensity(float intensity) { @@ -160,7 +178,7 @@ public float getCircleHoleRadius() { /** * sets the size (radius) of the circle shpaed value indicators, * default size = 4f - * + *

    GI)49?Pm6G++f_nAd=^o^*A2^5HiXQVi&Of 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

    -Bk|AMFAfZh5J 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 Date: Sun, 7 Aug 2016 23:17:11 +0200 Subject: [PATCH 1105/1390] Add linechart wiki --- screenshots/linechart_wiki.png | Bin 0 -> 73507 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/linechart_wiki.png diff --git a/screenshots/linechart_wiki.png b/screenshots/linechart_wiki.png new file mode 100644 index 0000000000000000000000000000000000000000..b81f5baf02127dbb2157018e5c79a2cbf5bc580d GIT binary patch literal 73507 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 C;Z>sm literal 0 HcmV?d00001 From f9108b9ad9023674657affcf73676bae3021be1c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 15:00:31 +0300 Subject: [PATCH 1106/1390] Groundwork for future support of highlight for multiple bubbles per x --- .../renderer/BubbleChartRenderer.java | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 458a46f884..e4fc5cef5a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -193,57 +193,64 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - final BubbleEntry entry = set.getEntryForXPos(high.getX()); + // In bubble charts - it makes sense to have multiple bubbles on the same X value in the same dataset. + final List entries = set.getEntriesForXPos(high.getX()); - if (!isInBoundsX(entry, set)) - continue; + for (BubbleEntry entry : entries) { - Transformer trans = mChart.getTransformer(set.getAxisDependency()); + if (entry.getY() != high.getY()) + continue; - sizeBuffer[0] = 0f; - sizeBuffer[2] = 1f; + if (!isInBoundsX(entry, set)) + continue; - trans.pointValuesToPixel(sizeBuffer); + Transformer trans = mChart.getTransformer(set.getAxisDependency()); - boolean normalizeSize = set.isNormalizeSizeEnabled(); + sizeBuffer[0] = 0f; + sizeBuffer[2] = 1f; - // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs( - mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); - final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); + trans.pointValuesToPixel(sizeBuffer); - pointBuffer[0] = entry.getX(); - pointBuffer[1] = (entry.getY()) * phaseY; - trans.pointValuesToPixel(pointBuffer); + boolean normalizeSize = set.isNormalizeSizeEnabled(); - high.setDraw(pointBuffer[0], pointBuffer[1]); + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); + final float maxBubbleHeight = Math.abs( + mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - float shapeHalf = getShapeSize(entry.getSize(), - set.getMaxSize(), - referenceSize, - normalizeSize) / 2f; + pointBuffer[0] = entry.getX(); + pointBuffer[1] = (entry.getY()) * phaseY; + trans.pointValuesToPixel(pointBuffer); - if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) - || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) - continue; + high.setDraw(pointBuffer[0], pointBuffer[1]); - if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) - continue; + float shapeHalf = getShapeSize(entry.getSize(), + set.getMaxSize(), + referenceSize, + normalizeSize) / 2f; - if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) - break; + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; - final int originalColor = set.getColor((int) entry.getX()); + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) + continue; + + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; - Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), - Color.blue(originalColor), _hsvBuffer); - _hsvBuffer[2] *= 0.5f; - final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + final int originalColor = set.getColor((int) entry.getX()); - mHighlightPaint.setColor(color); - mHighlightPaint.setStrokeWidth(set.getHighlightCircleWidth()); - c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), + Color.blue(originalColor), _hsvBuffer); + _hsvBuffer[2] *= 0.5f; + final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + + mHighlightPaint.setColor(color); + mHighlightPaint.setStrokeWidth(set.getHighlightCircleWidth()); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); + } } } } From 164bfd7fcab94b0a4595d8e0117a9703a14173c2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 16:50:37 +0300 Subject: [PATCH 1107/1390] Fixed legend anchor for TOP --- .../com/github/mikephil/charting/renderer/XAxisRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 1973aa3a47..2a93910d72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -115,7 +115,7 @@ public void renderAxisLabels(Canvas c) { MPPointF pointF = MPPointF.getInstance(0,0); if (mXAxis.getPosition() == XAxisPosition.TOP) { pointF.x = 0.5f; - pointF.y = 0.9f; + pointF.y = 1.0f; drawLabels(c, mViewPortHandler.contentTop() - yoffset, pointF); } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { From b2250e01558080c8af558bdc19a5a2cd1230813a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 17:10:50 +0300 Subject: [PATCH 1108/1390] Use scientific EPSILON --- .../main/java/com/github/mikephil/charting/data/Entry.java | 6 ++++-- .../main/java/com/github/mikephil/charting/utils/Utils.java | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index 6848540aaa..f7a7ca32f0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -5,6 +5,8 @@ import android.os.ParcelFormatException; import android.os.Parcelable; +import com.github.mikephil.charting.utils.Utils; + /** * Class representing one entry in the chart. Might contain multiple values. * Might only contain a single value depending on the used constructor. @@ -87,10 +89,10 @@ public boolean equalTo(Entry e) { if (e.getData() != this.getData()) return false; - if (Math.abs(e.x - this.x) > 0.000001f) + if (Math.abs(e.x - this.x) > Utils.FLOAT_EPSILON) return false; - if (Math.abs(e.getY() - this.getY()) > 0.000001f) + if (Math.abs(e.getY() - this.getY()) > Utils.FLOAT_EPSILON) return false; return true; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index bee377dcf9..11cffc5d1a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -36,6 +36,12 @@ public abstract class Utils { public final static double DEG2RAD = (Math.PI / 180.0); public final static float FDEG2RAD = ((float) Math.PI / 180.f); + @SuppressWarnings("unused") + public final static double DOUBLE_EPSILON = Double.longBitsToDouble(Double.doubleToLongBits(1.0) + 1); + + @SuppressWarnings("unused") + public final static float FLOAT_EPSILON = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1); + /** * initialize method, called inside the Chart.init() method. * From 1eae18b657cea825a6186475a0991526a155d7e6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 17:24:25 +0300 Subject: [PATCH 1109/1390] Keep that in a variable --- .../github/mikephil/charting/renderer/BarChartRenderer.java | 4 +++- .../charting/renderer/HorizontalBarChartRenderer.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 3260d4c470..00ab5e8d1e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -217,6 +217,8 @@ public void drawValues(Canvas c) { // get the buffer BarBuffer buffer = mBarBuffers[i]; + final float phaseY = mAnimator.getPhaseY(); + // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -293,7 +295,7 @@ public void drawValues(Canvas c) { negY -= value; } - transformed[k + 1] = y * mAnimator.getPhaseY(); + transformed[k + 1] = y * phaseY; } trans.pointValuesToPixel(transformed); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 2162a28b06..26101970e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -130,6 +130,8 @@ public void drawValues(Canvas c) { // get the buffer BarBuffer buffer = mBarBuffers[i]; + final float phaseY = mAnimator.getPhaseY(); + // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -230,7 +232,7 @@ public void drawValues(Canvas c) { negY -= value; } - transformed[k] = y * mAnimator.getPhaseY(); + transformed[k] = y * phaseY; } trans.pointValuesToPixel(transformed); From 0c00b09bdb00eb1916e72e042d296bb1867369e9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 17:28:24 +0300 Subject: [PATCH 1110/1390] DRYed that code --- .../charting/renderer/BarChartRenderer.java | 45 +++++++------------ .../renderer/HorizontalBarChartRenderer.java | 15 +++++-- 2 files changed, 27 insertions(+), 33 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 00ab5e8d1e..6cf208a451 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -121,47 +121,32 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { } } - // if multiple colors - if (dataSet.getColors().size() > 1) { + final boolean isSingleColor = dataSet.getColors().size() == 1; - for (int j = 0; j < buffer.size(); j += 4) { + if (isSingleColor) { + mRenderPaint.setColor(dataSet.getColor()); + } - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) - continue; + for (int j = 0; j < buffer.size(); j += 4) { - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) - break; + if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + continue; + + if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + break; + if (!isSingleColor) { // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. mRenderPaint.setColor(dataSet.getColor(j / 4)); - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); - - if (drawBorder) { - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mBarBorderPaint); - } } - } else { - mRenderPaint.setColor(dataSet.getColor()); - - for (int j = 0; j < buffer.size(); j += 4) { - - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) - continue; - - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) - break; + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); + if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); - - if (drawBorder) { - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mBarBorderPaint); - } + buffer.buffer[j + 3], mBarBorderPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 26101970e9..6f369b75b4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -73,6 +73,12 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isSingleColor = dataSet.getColors().size() == 1; + + if (isSingleColor) { + mRenderPaint.setColor(dataSet.getColor()); + } + for (int j = 0; j < buffer.size(); j += 4) { if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) @@ -87,9 +93,12 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.buffer[j + 3], mShadowPaint); } - // Set the color for the currently drawn value. If the index - // is out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j / 4)); + if (!isSingleColor) { + // Set the color for the currently drawn value. If the index + // is out of bounds, reuse colors. + mRenderPaint.setColor(dataSet.getColor(j / 4)); + } + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); From 1096719e8f66f976723f7641f6c0b0b662c108d5 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 18:10:30 +0300 Subject: [PATCH 1111/1390] `drawBarShadowEnabled` is working again --- .../charting/renderer/BarChartRenderer.java | 54 +++++++++++++------ .../renderer/HorizontalBarChartRenderer.java | 45 +++++++++++++--- 2 files changed, 75 insertions(+), 24 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 6cf208a451..7402f3f2a2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -80,11 +80,12 @@ public void drawData(Canvas c) { } } + private RectF mBarShadowRectBuffer = new RectF(); + protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth())); @@ -93,34 +94,53 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - // initialize the buffer - BarBuffer buffer = mBarBuffers[index]; - buffer.setPhases(phaseX, phaseY); - buffer.setDataSet(index); - buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); - buffer.setBarWidth(mChart.getBarData().getBarWidth()); + // draw the bar shadow before the values + if (mChart.isDrawBarShadowEnabled()) { + mShadowPaint.setColor(dataSet.getBarShadowColor()); - buffer.feed(dataSet); + BarData barData = mChart.getBarData(); - trans.pointValuesToPixel(buffer.buffer); + final float barWidth = barData.getBarWidth(); + final float barWidthHalf = barWidth / 2.0f; + float x; - // draw the bar shadow before the values - if (mChart.isDrawBarShadowEnabled()) { + for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount()); + i < count; + i++) { + + BarEntry e = dataSet.getEntryForIndex(i); - for (int j = 0; j < buffer.size(); j += 4) { + x = e.getX(); - if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) + mBarShadowRectBuffer.left = x - barWidthHalf; + mBarShadowRectBuffer.right = x + barWidthHalf; + + trans.rectValueToPixel(mBarShadowRectBuffer); + + if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) continue; - if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j])) + if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left)) break; - c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), - buffer.buffer[j + 2], - mViewPortHandler.contentBottom(), mShadowPaint); + mBarShadowRectBuffer.top = mViewPortHandler.contentTop(); + mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom(); + + c.drawRect(mBarShadowRectBuffer, mShadowPaint); } } + // initialize the buffer + BarBuffer buffer = mBarBuffers[index]; + buffer.setPhases(phaseX, phaseY); + buffer.setDataSet(index); + buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); + buffer.setBarWidth(mChart.getBarData().getBarWidth()); + + buffer.feed(dataSet); + + trans.pointValuesToPixel(buffer.buffer); + final boolean isSingleColor = dataSet.getColors().size() == 1; if (isSingleColor) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 6f369b75b4..1519364a95 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -48,12 +48,13 @@ public void initBuffers() { } } + private RectF mBarShadowRectBuffer = new RectF(); + @Override protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - mShadowPaint.setColor(dataSet.getBarShadowColor()); mBarBorderPaint.setColor(dataSet.getBarBorderColor()); mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth())); @@ -62,6 +63,42 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + // draw the bar shadow before the values + if (mChart.isDrawBarShadowEnabled()) { + mShadowPaint.setColor(dataSet.getBarShadowColor()); + + BarData barData = mChart.getBarData(); + + final float barWidth = barData.getBarWidth(); + final float barWidthHalf = barWidth / 2.0f; + float x; + + for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount()); + i < count; + i++) { + + BarEntry e = dataSet.getEntryForIndex(i); + + x = e.getX(); + + mBarShadowRectBuffer.top = x - barWidthHalf; + mBarShadowRectBuffer.bottom = x + barWidthHalf; + + trans.rectValueToPixel(mBarShadowRectBuffer); + + if (!mViewPortHandler.isInBoundsTop(mBarShadowRectBuffer.bottom)) + continue; + + if (!mViewPortHandler.isInBoundsBottom(mBarShadowRectBuffer.top)) + break; + + mBarShadowRectBuffer.left = mViewPortHandler.contentLeft(); + mBarShadowRectBuffer.right = mViewPortHandler.contentRight(); + + c.drawRect(mBarShadowRectBuffer, mShadowPaint); + } + } + // initialize the buffer BarBuffer buffer = mBarBuffers[index]; buffer.setPhases(phaseX, phaseY); @@ -87,12 +124,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) continue; - if (mChart.isDrawBarShadowEnabled()) { - c.drawRect(mViewPortHandler.contentLeft(), buffer.buffer[j + 1], - mViewPortHandler.contentRight(), - buffer.buffer[j + 3], mShadowPaint); - } - if (!isSingleColor) { // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. From 9c5a46c9f8532bd8f9f6d142431614af45061450 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 7 Aug 2016 18:16:34 +0300 Subject: [PATCH 1112/1390] Gradle required 2048 heap for multidex --- gradle.properties | 1 + 1 file changed, 1 insertion(+) create mode 100644 gradle.properties diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000000..4a9594aeec --- /dev/null +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx2048M \ No newline at end of file From d2e8ee220a75f46517f833be741a52c9b18ed923 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 09:24:33 +0300 Subject: [PATCH 1113/1390] Renamed `zoomCenter` to `zoomToCenter` --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index a208e73837..bf659468aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -657,7 +657,7 @@ public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDep * @param scaleX * @param scaleY */ - public void zoomCenter(float scaleX, float scaleY) { + public void zoomToCenter(float scaleX, float scaleY) { MPPointF center = getCenterOffsets(); From 99379d7bcffd3247bde40fbe06bab8ec58066586 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 09:28:22 +0300 Subject: [PATCH 1114/1390] Renamed `ShapeRenderer` -> `IShapeRenderer` --- .../custom/CustomScatterShapeRenderer.java | 5 +++-- .../mikephil/charting/data/ScatterDataSet.java | 16 +++++++--------- .../dataprovider/ScatterDataProvider.java | 1 - .../interfaces/datasets/IScatterDataSet.java | 6 +++--- .../charting/renderer/ScatterChartRenderer.java | 6 +++--- .../scatter/ChevronDownShapeRenderer.java | 3 ++- .../renderer/scatter/ChevronUpShapeRenderer.java | 3 ++- .../renderer/scatter/CircleShapeRenderer.java | 3 ++- .../renderer/scatter/CrossShapeRenderer.java | 3 ++- .../{ShapeRenderer.java => IShapeRenderer.java} | 3 ++- .../renderer/scatter/SquareShapeRenderer.java | 3 ++- .../renderer/scatter/TriangleShapeRenderer.java | 3 ++- .../renderer/scatter/XShapeRenderer.java | 3 ++- .../charting/utils/ShapeRendererHandler.java | 14 +++++++------- 14 files changed, 39 insertions(+), 33 deletions(-) rename MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/{ShapeRenderer.java => IShapeRenderer.java} (96%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java index 25cd41b1a2..77ffe2759e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java @@ -5,14 +5,15 @@ import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.utils.ViewPortHandler; /** * Custom shape renderer that draws a single line. * Created by philipp on 26/06/16. */ -public class CustomScatterShapeRenderer implements ShapeRenderer { +public class CustomScatterShapeRenderer implements IShapeRenderer +{ @Override public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index 01f2933d3f..446bce3b52 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -1,11 +1,9 @@ package com.github.mikephil.charting.data; -import android.graphics.drawable.shapes.Shape; - import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.ShapeRendererHandler; @@ -23,7 +21,7 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme /** * Renderer responsible for rendering this DataSet, default: square */ - protected ShapeRenderer mShapeRenderer = new SquareShapeRenderer(); + protected IShapeRenderer mShapeRenderer = new SquareShapeRenderer(); /** * The radius of the hole in the shape (applies to Square, Circle and Triangle) @@ -87,7 +85,7 @@ public float getScatterShapeSize() { } /** - * Sets the ScatterShape this DataSet should be drawn with. This will search for an available ShapeRenderer and set this + * Sets the ScatterShape this DataSet should be drawn with. This will search for an available IShapeRenderer and set this * renderer for the DataSet. * * @param shape @@ -99,17 +97,17 @@ public void setScatterShape(ScatterChart.ScatterShape shape) { } /** - * Sets a new ShapeRenderer responsible for drawing this DataSet. - * This can also be used to set a custom ShapeRenderer aside from the default ones. + * Sets a new IShapeRenderer responsible for drawing this DataSet. + * This can also be used to set a custom IShapeRenderer aside from the default ones. * * @param shapeRenderer */ - public void setShapeRenderer(ShapeRenderer shapeRenderer) { + public void setShapeRenderer(IShapeRenderer shapeRenderer) { mShapeRenderer = shapeRenderer; } @Override - public ShapeRenderer getShapeRenderer() { + public IShapeRenderer getShapeRenderer() { return mShapeRenderer; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java index e89110cdb9..b58d5af95d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; public interface ScatterDataProvider extends BarLineScatterCandleBubbleDataProvider { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java index ac838a4d2e..ac6122742a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; /** * Created by philipp on 21/10/15. @@ -30,9 +30,9 @@ public interface IScatterDataSet extends ILineScatterCandleRadarDataSet { int getScatterShapeHoleColor(); /** - * Returns the ShapeRenderer responsible for rendering this DataSet. + * Returns the IShapeRenderer responsible for rendering this DataSet. * * @return */ - ShapeRenderer getShapeRenderer(); + IShapeRenderer getShapeRenderer(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 484bcba551..417e553b65 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.utils.MPPointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -72,12 +72,12 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { trans.pointValuesToPixel(buffer.buffer); - ShapeRenderer renderer = dataSet.getShapeRenderer(); + IShapeRenderer renderer = dataSet.getShapeRenderer(); if (renderer != null) { renderer.renderShape(c, dataSet, mViewPortHandler, buffer, mRenderPaint, shapeSize); } else { - throw new RuntimeException("No ShapeRenderer found for provided identifier. Please make sure to add a ShapeRenderer" + + throw new RuntimeException("No IShapeRenderer found for provided identifier. Please make sure to add a IShapeRenderer" + " capable of rendering the provided shape."); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java index d293b28481..cdc3f2af6d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java @@ -12,7 +12,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class ChevronDownShapeRenderer implements ShapeRenderer { +public class ChevronDownShapeRenderer implements IShapeRenderer +{ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java index 4eb9db7942..f4185bfd8e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java @@ -12,7 +12,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class ChevronUpShapeRenderer implements ShapeRenderer { +public class ChevronUpShapeRenderer implements IShapeRenderer +{ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java index 449bd9fe96..98ed8c1459 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java @@ -13,7 +13,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class CircleShapeRenderer implements ShapeRenderer { +public class CircleShapeRenderer implements IShapeRenderer +{ @Override public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java index 45db656677..3273490a46 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java @@ -12,7 +12,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class CrossShapeRenderer implements ShapeRenderer { +public class CrossShapeRenderer implements IShapeRenderer +{ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java similarity index 96% rename from MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java index 3fb23f7718..f89d6f6b08 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java @@ -12,7 +12,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:07 */ -public interface ShapeRenderer { +public interface IShapeRenderer +{ /** * Renders the provided ScatterDataSet with a shape. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java index 184e77a449..74670473ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java @@ -13,7 +13,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class SquareShapeRenderer implements ShapeRenderer { +public class SquareShapeRenderer implements IShapeRenderer +{ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java index 789297d170..f8e2f30b47 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java @@ -14,7 +14,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class TriangleShapeRenderer implements ShapeRenderer { +public class TriangleShapeRenderer implements IShapeRenderer +{ protected Path mTrianglePathBuffer = new Path(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java index 2dbac6a974..3c37174e2f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java @@ -12,7 +12,8 @@ * Created by wajdic on 15/06/2016. * Created at Time 09:08 */ -public class XShapeRenderer implements ShapeRenderer { +public class XShapeRenderer implements IShapeRenderer +{ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java index 0cef75f151..c2093e6e76 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.renderer.scatter.ChevronUpShapeRenderer; import com.github.mikephil.charting.renderer.scatter.CircleShapeRenderer; import com.github.mikephil.charting.renderer.scatter.CrossShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.ShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; import com.github.mikephil.charting.renderer.scatter.TriangleShapeRenderer; import com.github.mikephil.charting.renderer.scatter.XShapeRenderer; @@ -14,16 +14,16 @@ /** * Created by Philipp Jahoda on 27/06/16. - * Class allowing to determine the corresponding ShapeRenderer for a given ScatterShape. + * Class allowing to determine the corresponding IShapeRenderer for a given ScatterShape. */ public final class ShapeRendererHandler { /** - * Dictionary of ShapeRenderer which are responsible for drawing custom shapes. + * Dictionary of IShapeRenderer which are responsible for drawing custom shapes. * Can add to it your custom shapes. - * CustomShapeRenderer Implements ShapeRenderer{} + * CustomShapeRenderer Implements IShapeRenderer{} */ - protected HashMap shapeRendererList; + protected HashMap shapeRendererList; /** * Constructor @@ -33,12 +33,12 @@ public ShapeRendererHandler() { } /** - * Returns the corresponding ShapeRenderer for a given ScatterShape. + * Returns the corresponding IShapeRenderer for a given ScatterShape. * * @param shape * @return */ - public ShapeRenderer getShapeRenderer(ScatterChart.ScatterShape shape) { + public IShapeRenderer getShapeRenderer(ScatterChart.ScatterShape shape) { return shapeRendererList.get(shape.toString()); } From 79f5ed02004e8a80f1c4ecfc5cefa50d75dc9703 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 09:46:06 +0300 Subject: [PATCH 1115/1390] Simplified scatter shape enum model (Why would anyone try to subclass an enum?) --- .../charting/charts/ScatterChart.java | 7 ++- .../charting/data/ScatterDataSet.java | 31 +++++++--- .../charting/utils/ShapeRendererHandler.java | 59 ------------------- 3 files changed, 28 insertions(+), 69 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index 0f68457b55..decf1e855a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -48,7 +48,12 @@ public ScatterData getScatterData() { */ public enum ScatterShape { - SQUARE("SQUARE"), CIRCLE("CIRCLE"), TRIANGLE("TRIANGLE"), CROSS("CROSS"), X("X"), CHEVRON_UP("CHEVRON_UP"), + SQUARE("SQUARE"), + CIRCLE("CIRCLE"), + TRIANGLE("TRIANGLE"), + CROSS("CROSS"), + X("X"), + CHEVRON_UP("CHEVRON_UP"), CHEVRON_DOWN("CHEVRON_DOWN"); private final String shapeIdentifier; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index 446bce3b52..a9d73885b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -3,10 +3,15 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.renderer.scatter.ChevronDownShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.ChevronUpShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.CircleShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.CrossShapeRenderer; import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.TriangleShapeRenderer; +import com.github.mikephil.charting.renderer.scatter.XShapeRenderer; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.ShapeRendererHandler; import java.util.ArrayList; import java.util.List; @@ -36,11 +41,6 @@ public class ScatterDataSet extends LineScatterCandleRadarDataSet impleme */ private int mScatterShapeHoleColor = ColorTemplate.COLOR_NONE; - /** - * Custom path object the user can provide that is drawn where the values - * are at. This is used when ScatterShape.CUSTOM is set for a DataSet. - */ - //private Path mCustomScatterPath = null; public ScatterDataSet(List yVals, String label) { super(yVals, label); } @@ -91,9 +91,7 @@ public float getScatterShapeSize() { * @param shape */ public void setScatterShape(ScatterChart.ScatterShape shape) { - - ShapeRendererHandler handler = new ShapeRendererHandler(); - mShapeRenderer = handler.getShapeRenderer(shape); + mShapeRenderer = getRendererForShape(shape); } /** @@ -139,4 +137,19 @@ public void setScatterShapeHoleColor(int holeColor) { public int getScatterShapeHoleColor() { return mScatterShapeHoleColor; } + + public static IShapeRenderer getRendererForShape(ScatterChart.ScatterShape shape) { + + switch (shape) { + case SQUARE: return new SquareShapeRenderer(); + case CIRCLE: return new CircleShapeRenderer(); + case TRIANGLE: return new TriangleShapeRenderer(); + case CROSS: return new CrossShapeRenderer(); + case X: return new XShapeRenderer(); + case CHEVRON_UP: return new ChevronUpShapeRenderer(); + case CHEVRON_DOWN: return new ChevronDownShapeRenderer(); + } + + return null; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java deleted file mode 100644 index c2093e6e76..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ShapeRendererHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.github.mikephil.charting.utils; - -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.renderer.scatter.ChevronDownShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.ChevronUpShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.CircleShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.CrossShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.SquareShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.TriangleShapeRenderer; -import com.github.mikephil.charting.renderer.scatter.XShapeRenderer; - -import java.util.HashMap; - -/** - * Created by Philipp Jahoda on 27/06/16. - * Class allowing to determine the corresponding IShapeRenderer for a given ScatterShape. - */ -public final class ShapeRendererHandler { - - /** - * Dictionary of IShapeRenderer which are responsible for drawing custom shapes. - * Can add to it your custom shapes. - * CustomShapeRenderer Implements IShapeRenderer{} - */ - protected HashMap shapeRendererList; - - /** - * Constructor - */ - public ShapeRendererHandler() { - initShapeRenderers(); - } - - /** - * Returns the corresponding IShapeRenderer for a given ScatterShape. - * - * @param shape - * @return - */ - public IShapeRenderer getShapeRenderer(ScatterChart.ScatterShape shape) { - return shapeRendererList.get(shape.toString()); - } - - /** - * Init default ShapeRenderers. - */ - protected void initShapeRenderers() { - shapeRendererList = new HashMap<>(); - - shapeRendererList.put(ScatterChart.ScatterShape.SQUARE.toString(), new SquareShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.CIRCLE.toString(), new CircleShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.TRIANGLE.toString(), new TriangleShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.CROSS.toString(), new CrossShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.X.toString(), new XShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.CHEVRON_UP.toString(), new ChevronUpShapeRenderer()); - shapeRendererList.put(ScatterChart.ScatterShape.CHEVRON_DOWN.toString(), new ChevronDownShapeRenderer()); - } -} From 2d54fd1f3f0aeba4ffd65b8ad8cd1d11d47cadb1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 09:52:26 +0300 Subject: [PATCH 1116/1390] Call createRenderers() instead of recreating the renderer each time --- .../charting/charts/CombinedChart.java | 4 +--- .../renderer/CombinedChartRenderer.java | 23 ++++++++++--------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index 5f578c5d83..ba0cfcb0ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -81,11 +81,9 @@ public CombinedData getCombinedData() { @Override public void setData(CombinedData data) { - mData = null; - mRenderer = null; super.setData(data); setHighlighter(new CombinedHighlighter(this, this)); - mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); + ((CombinedChartRenderer)mRenderer).createRenderers(); mRenderer.initBuffers(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 142dff4346..6d0d4d3da0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; @@ -30,21 +31,21 @@ public class CombinedChartRenderer extends DataRenderer { public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = new WeakReference(chart); - createRenderers(chart, animator, viewPortHandler); + createRenderers(); } /** * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into * consideration. - * - * @param chart - * @param animator - * @param viewPortHandler */ - protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { + public void createRenderers() { mRenderers.clear(); + CombinedChart chart = (CombinedChart)mChart.get(); + if (chart == null) + return; + DrawOrder[] orders = chart.getDrawOrder(); for (DrawOrder order : orders) { @@ -52,23 +53,23 @@ protected void createRenderers(CombinedChart chart, ChartAnimator animator, View switch (order) { case BAR: if (chart.getBarData() != null) - mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); + mRenderers.add(new BarChartRenderer(chart, mAnimator, mViewPortHandler)); break; case BUBBLE: if (chart.getBubbleData() != null) - mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); + mRenderers.add(new BubbleChartRenderer(chart, mAnimator, mViewPortHandler)); break; case LINE: if (chart.getLineData() != null) - mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); + mRenderers.add(new LineChartRenderer(chart, mAnimator, mViewPortHandler)); break; case CANDLE: if (chart.getCandleData() != null) - mRenderers.add(new CandleStickChartRenderer(chart, animator, viewPortHandler)); + mRenderers.add(new CandleStickChartRenderer(chart, mAnimator, mViewPortHandler)); break; case SCATTER: if (chart.getScatterData() != null) - mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); + mRenderers.add(new ScatterChartRenderer(chart, mAnimator, mViewPortHandler)); break; } } From 77c10fc9e56f9d9538773af9e5af06c072f2318c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 10:03:51 +0300 Subject: [PATCH 1117/1390] These return a single pixel (x/y), for values (x value and y value) --- .../github/mikephil/charting/charts/BarLineChartBase.java | 6 +++--- .../mikephil/charting/highlight/BarHighlighter.java | 2 +- .../mikephil/charting/highlight/ChartHighlighter.java | 2 +- .../charting/highlight/HorizontalBarHighlighter.java | 2 +- .../charting/renderer/CandleStickChartRenderer.java | 2 +- .../mikephil/charting/renderer/LineChartRenderer.java | 2 +- .../mikephil/charting/renderer/ScatterChartRenderer.java | 2 +- .../github/mikephil/charting/renderer/YAxisRenderer.java | 2 +- .../renderer/YAxisRendererHorizontalBarChart.java | 2 +- .../com/github/mikephil/charting/utils/Transformer.java | 8 ++++---- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index bf659468aa..fbc20a44b3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1206,7 +1206,7 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { * Returns the x and y values in the chart at the given touch point * (encapsulated in a MPPointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to - * getPixelsForValues(...). + * getPixelForValues(...). * * @param x * @param y @@ -1231,8 +1231,8 @@ public void getValuesByTouchPoint(float x, float y, AxisDependency axis, MPPoint * @param y * @return */ - public MPPointD getPixelsForValues(float x, float y, AxisDependency axis) { - return getTransformer(axis).getPixelsForValues(x, y); + public MPPointD getPixelForValues(float x, float y, AxisDependency axis) { + return getTransformer(axis).getPixelForValues(x, y); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 1adad89de1..0a5fb25023 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -68,7 +68,7 @@ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal if (ranges.length > 0) { int stackIndex = getClosestStackIndex(ranges, yVal); - MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(high.getX(), ranges[stackIndex].to); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(high.getX(), ranges[stackIndex].to); Highlight stackedHigh = new Highlight( entry.getX(), diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index c3aa4560d8..59a38f6132 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -167,7 +167,7 @@ protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, D if (e == null) return null; - MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY()); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY()); return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 626868c3de..97cb11bff9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -47,7 +47,7 @@ protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, D final Entry e = set.getEntryForXPos(xVal, rounding); - MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getY(), e.getX()); + MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getY(), e.getX()); return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 734b4301e5..cdd79f41c3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -326,7 +326,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float highValue = e.getHigh() * mAnimator.getPhaseY(); float y = (lowValue + highValue) / 2f; - MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), y); + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), y); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 48c7a4be3c..85e95a7621 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -668,7 +668,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!isInBoundsX(e, set)) continue; - MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY() * mAnimator .getPhaseY()); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 417e553b65..2341ca5b59 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -148,7 +148,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (!isInBoundsX(e, set)) continue; - MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelsForValues(e.getX(), e.getY() * mAnimator + MPPointD pix = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY() * mAnimator .getPhaseY()); high.setDraw((float) pix.x, (float) pix.y); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 71cfbf324e..09e25d1e1e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -203,7 +203,7 @@ protected float[] getTransformedPositions() { protected void drawZeroLine(Canvas c) { // draw zero line - MPPointD pos = mTrans.getPixelsForValues(0f, 0f); + MPPointD pos = mTrans.getPixelForValues(0f, 0f); mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 3f9f36a965..6cf7985ea2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -179,7 +179,7 @@ protected Path linePath(Path p, int i, float[] positions) { protected void drawZeroLine(Canvas c) { // draw zero line - MPPointD pos = mTrans.getPixelsForValues(0f, 0f); + MPPointD pos = mTrans.getPixelForValues(0f, 0f); mZeroLinePaint.setColor(mYAxis.getZeroLineColor()); mZeroLinePaint.setStrokeWidth(mYAxis.getZeroLineWidth()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index d9a57c3f82..6848bc58d1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -353,7 +353,7 @@ public void rectValuesToPixel(List rects) { m.mapRect(rects.get(i)); } - protected Matrix mPixelsToValueMatrixBuffer = new Matrix(); + protected Matrix mPixelToValueMatrixBuffer = new Matrix(); /** * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) @@ -363,7 +363,7 @@ public void rectValuesToPixel(List rects) { */ public void pixelsToValue(float[] pixels) { - Matrix tmp = mPixelsToValueMatrixBuffer; + Matrix tmp = mPixelToValueMatrixBuffer; tmp.reset(); // invert all matrixes to convert back to the original value @@ -387,7 +387,7 @@ public void pixelsToValue(float[] pixels) { * returns the x and y values in the chart at the given touch point * (encapsulated in a MPPointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to - * getPixelsForValues(...). + * getPixelForValues(...). * * @param x * @param y @@ -419,7 +419,7 @@ public void getValuesByTouchPoint(float x, float y, MPPointD outputPoint) { * @param y * @return */ - public MPPointD getPixelsForValues(float x, float y) { + public MPPointD getPixelForValues(float x, float y) { ptsBuffer[0] = x; ptsBuffer[1] = y; From f63002e196fb2c86393c018061163c84b2d110a9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 10:14:58 +0300 Subject: [PATCH 1118/1390] Renamed x-pos to x-value where appropriate --- .../mikephil/charting/charts/BarChart.java | 6 +-- .../mikephil/charting/charts/Chart.java | 4 +- .../mikephil/charting/charts/PieChart.java | 2 +- .../mikephil/charting/data/BarData.java | 4 +- .../mikephil/charting/data/BaseDataSet.java | 4 +- .../mikephil/charting/data/ChartData.java | 10 ++--- .../mikephil/charting/data/CombinedData.java | 6 +-- .../mikephil/charting/data/DataSet.java | 32 +++++++------- .../charting/highlight/BarHighlighter.java | 2 +- .../charting/highlight/ChartHighlighter.java | 6 +-- .../highlight/CombinedHighlighter.java | 2 +- .../highlight/HorizontalBarHighlighter.java | 2 +- .../interfaces/datasets/IDataSet.java | 44 +++++++++---------- .../charting/renderer/BarChartRenderer.java | 2 +- .../BarLineScatterCandleBubbleRenderer.java | 4 +- .../renderer/BubbleChartRenderer.java | 2 +- .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 2 +- .../renderer/ScatterChartRenderer.java | 2 +- .../mikephil/charting/test/DataSetTest.java | 16 +++---- 20 files changed, 76 insertions(+), 78 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 6f3692c2f3..a149adf909 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -202,7 +202,7 @@ public boolean isHighlightFullBarEnabled() { } /** - * Highlights the value at the given x-position in the given DataSet. Provide + * Highlights the value at the given x-value in the given DataSet. Provide * -1 as the dataSetIndex to undo all highlighting. * * @param x @@ -230,8 +230,8 @@ public void setFitBars(boolean enabled) { } /** - * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. - * Previously set x-positions of entries will be overwritten. Leaves space between bars and groups as specified + * Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries. + * Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified * by the parameters. * Calls notifyDataSetChanged() afterwards. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ec4d38402b..74823825c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -581,7 +581,7 @@ public void highlightValues(Highlight[] highs) { } /** - * Highlights the value at the given x-position in the given DataSet. Provide + * Highlights the value at the given x-value in the given DataSet. Provide * -1 as the dataSetIndex to undo all highlighting. This will trigger a callback to the OnChartValueSelectedListener. * * @param x @@ -592,7 +592,7 @@ public void highlightValue(float x, int dataSetIndex) { } /** - * Highlights the value at the given x position in the given DataSet. Provide + * Highlights the value at the given x-value in the given DataSet. Provide * -1 as the dataSetIndex to undo all highlighting. * * @param x diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index bad10dbbb4..d2acf19b2d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -328,7 +328,7 @@ public int getDataSetIndexForIndex(int xIndex) { List dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - if (dataSets.get(i).getEntryForXPos(xIndex) != null) + if (dataSets.get(i).getEntryForXValue(xIndex) != null) return i; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 609d480d32..601364dbc4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -44,8 +44,8 @@ public float getBarWidth() { } /** - * Groups all BarDataSet objects this data object holds together by modifying the x-position of their entries. - * Previously set x-positions of entries will be overwritten. Leaves space between bars and groups as specified + * Groups all BarDataSet objects this data object holds together by modifying the x-value of their entries. + * Previously set x-values of entries will be overwritten. Leaves space between bars and groups as specified * by the parameters. * Do not forget to call notifyDataSetChanged() on your BarChart object after calling this method. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 28dd77ceb4..55d7309c9a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -387,9 +387,9 @@ public boolean removeLast() { } @Override - public boolean removeEntryByXPos(float xPos) { + public boolean removeEntryByXValue(float xValue) { - T e = getEntryForXPos(xPos); + T e = getEntryForXValue(xValue); return removeEntry(e); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index a8496b3bfb..0d8c52bd37 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -335,7 +335,7 @@ public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= mDataSets.size()) return null; else { - return mDataSets.get(highlight.getDataSetIndex()).getEntryForXPos(highlight.getX()); + return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX()); } } @@ -526,17 +526,17 @@ public boolean removeEntry(Entry e, int dataSetIndex) { * specified index. Returns true if an Entry was removed, false if no Entry * was found that meets the specified requirements. * - * @param xPos + * @param xValue * @param dataSetIndex * @return */ - public boolean removeEntry(float xPos, int dataSetIndex) { + public boolean removeEntry(float xValue, int dataSetIndex) { if (dataSetIndex >= mDataSets.size()) return false; IDataSet dataSet = mDataSets.get(dataSetIndex); - Entry e = dataSet.getEntryForXPos(xPos); + Entry e = dataSet.getEntryForXValue(xValue); if (e == null) return false; @@ -561,7 +561,7 @@ public T getDataSetForEntry(Entry e) { T set = mDataSets.get(i); for (int j = 0; j < set.getEntryCount(); j++) { - if (e.equalTo(set.getEntryForXPos(e.getX()))) + if (e.equalTo(set.getEntryForXValue(e.getX()))) return set; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 0b6b94437a..035ad9e0b3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -3,10 +3,8 @@ import android.util.Log; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; import java.util.List; @@ -194,7 +192,7 @@ public Entry getEntryForHighlight(Highlight highlight) { // if we are not interested in highlighting a specific value. List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) - .getEntriesForXPos(highlight.getX()); + .getEntriesForXValue(highlight.getX()); for (Entry entry : entries) if (entry.getY() == highlight.getY() || Float.isNaN(highlight.getY())) @@ -243,7 +241,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { @Deprecated @Override - public boolean removeEntry(float xPos, int dataSetIndex) { + public boolean removeEntry(float xValue, int dataSetIndex) { Log.e("MPAndroidChart", "removeEntry(...) not supported for CombinedData"); return false; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 42571e95de..d337a0482b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -239,17 +239,17 @@ public int getEntryIndex(Entry e) { } @Override - public T getEntryForXPos(float xPos, Rounding rounding) { + public T getEntryForXValue(float xValue, Rounding rounding) { - int index = getEntryIndex(xPos, rounding); + int index = getEntryIndex(xValue, rounding); if (index > -1) return mValues.get(index); return null; } @Override - public T getEntryForXPos(float xPos) { - return getEntryForXPos(xPos, Rounding.CLOSEST); + public T getEntryForXValue(float xValue) { + return getEntryForXValue(xValue, Rounding.CLOSEST); } @Override @@ -258,7 +258,7 @@ public T getEntryForIndex(int index) { } @Override - public int getEntryIndex(float xPos, Rounding rounding) { + public int getEntryIndex(float xValue, Rounding rounding) { if (mValues == null || mValues.isEmpty()) return -1; @@ -269,8 +269,8 @@ public int getEntryIndex(float xPos, Rounding rounding) { while (low < high) { int m = (low + high) / 2; - float d1 = Math.abs(mValues.get(m).getX() - xPos); - float d2 = Math.abs(mValues.get(m + 1).getX() - xPos); + float d1 = Math.abs(mValues.get(m).getX() - xValue); + float d2 = Math.abs(mValues.get(m + 1).getX() - xValue); if (d2 <= d1) { low = m + 1; @@ -280,13 +280,13 @@ public int getEntryIndex(float xPos, Rounding rounding) { } if (high != -1) { - float closestXPos = mValues.get(high).getX(); + float closestXValue = mValues.get(high).getX(); if (rounding == Rounding.UP) { - if (closestXPos < xPos && high < mValues.size() - 1) { + if (closestXValue < xValue && high < mValues.size() - 1) { ++high; } } else if (rounding == Rounding.DOWN) { - if (closestXPos > xPos && high > 0) { + if (closestXValue > xValue && high > 0) { --high; } } @@ -300,11 +300,11 @@ public int getEntryIndex(float xPos, Rounding rounding) { * does calculations at runtime. Do not over-use in performance critical * situations. * - * @param xVal + * @param xValue * @return */ @Override - public List getEntriesForXPos(float xVal) { + public List getEntriesForXValue(float xValue) { List entries = new ArrayList(); @@ -315,14 +315,14 @@ public List getEntriesForXPos(float xVal) { int m = (high + low) / 2; T entry = mValues.get(m); - if (xVal == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xVal) + if (xValue == entry.getX()) { + while (m > 0 && mValues.get(m - 1).getX() == xValue) m--; high = mValues.size(); for (; m < high; m++) { entry = mValues.get(m); - if (entry.getX() == xVal) { + if (entry.getX() == xValue) { entries.add(entry); } else { break; @@ -331,7 +331,7 @@ public List getEntriesForXPos(float xVal) { break; } else { - if (xVal > entry.getX()) + if (xValue > entry.getX()) low = m + 1; else high = m - 1; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index 0a5fb25023..b60eeabfe9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -54,7 +54,7 @@ public Highlight getHighlight(float x, float y) { */ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) { - BarEntry entry = set.getEntryForXPos(xVal); + BarEntry entry = set.getEntryForXValue(xVal); if (entry == null) return null; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index 59a38f6132..03491877db 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -66,7 +66,7 @@ protected MPPointD getValsForTouch(float x, float y) { */ protected Highlight getHighlightForX(float xVal, float x, float y) { - List closestValues = getHighlightsAtXPos(xVal, x, y); + List closestValues = getHighlightsAtXValue(xVal, x, y); if(closestValues.isEmpty()) { return null; @@ -124,7 +124,7 @@ protected float getHighlightPos(Highlight h) { * @param y touch position * @return */ - protected List getHighlightsAtXPos(float xVal, float x, float y) { + protected List getHighlightsAtXValue(float xVal, float x, float y) { mHighlightBuffer.clear(); @@ -162,7 +162,7 @@ protected List getHighlightsAtXPos(float xVal, float x, float y) { */ protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { - final Entry e = set.getEntryForXPos(xVal, rounding); + final Entry e = set.getEntryForXValue(xVal, rounding); if (e == null) return null; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index eaff38c27c..d2275187e9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -28,7 +28,7 @@ public CombinedHighlighter(CombinedDataProvider chart, BarDataProvider barChart) } @Override - protected List getHighlightsAtXPos(float xVal, float x, float y) { + protected List getHighlightsAtXValue(float xVal, float x, float y) { mHighlightBuffer.clear(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 97cb11bff9..60ec66ba9d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -45,7 +45,7 @@ public Highlight getHighlight(float x, float y) { @Override protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { - final Entry e = set.getEntryForXPos(xVal, rounding); + final Entry e = set.getEntryForXValue(xVal, rounding); MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getY(), e.getX()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index aadd6efcba..f36cee928e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -58,40 +58,40 @@ public interface IDataSet { void calcMinMax(); /** - * Returns the first Entry object found at the given xPos with binary - * search. If the no Entry at the specified xPos is found, this method - * returns the Entry at the xPos according to the rounding. + * Returns the first Entry object found at the given x-value with binary + * search. If the no Entry at the specified x-value is found, this method + * returns the Entry at the x-value according to the rounding. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xPos + * @param xValue * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - T getEntryForXPos(float xPos, DataSet.Rounding rounding); + T getEntryForXValue(float xValue, DataSet.Rounding rounding); /** - * Returns the first Entry object found at the given xPos with binary - * search. If the no Entry at the specified xPos is found, this method - * returns the index at the closest xPos. + * Returns the first Entry object found at the given x-value with binary + * search. If the no Entry at the specified x-value is found, this method + * returns the index at the closest x-value. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xPos + * @param xValue * @return */ - T getEntryForXPos(float xPos); + T getEntryForXValue(float xValue); /** - * Returns all Entry objects found at the given xPos with binary - * search. An empty array if no Entry object at that xPos. + * Returns all Entry objects found at the given x-value with binary + * search. An empty array if no Entry object at that x-value. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xPos + * @param xValue * @return */ - List getEntriesForXPos(float xPos); + List getEntriesForXValue(float xValue); /** * Returns the Entry object found at the given index (NOT xIndex) in the values array. @@ -102,17 +102,17 @@ public interface IDataSet { T getEntryForIndex(int index); /** - * Returns the first Entry index found at the given xPos with binary - * search. If the no Entry at the specified xPos is found, this method - * returns the Entry at the closest xPos. + * Returns the first Entry index found at the given x-value with binary + * search. If the no Entry at the specified x-value is found, this method + * returns the Entry at the closest x-value. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xPos + * @param xValue * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index * @return */ - int getEntryIndex(float xPos, DataSet.Rounding rounding); + int getEntryIndex(float xValue, DataSet.Rounding rounding); /** * Returns the position of the provided entry in the DataSets Entry array. @@ -183,12 +183,12 @@ public interface IDataSet { boolean removeEntry(T e); /** - * Removes the Entry object closest to the given xPos from the DataSet. + * Removes the Entry object closest to the given x-value from the DataSet. * Returns true if an Entry was removed, false if no Entry could be removed. * - * @param xPos + * @param xValue */ - boolean removeEntryByXPos(float xPos); + boolean removeEntryByXValue(float xValue); /** * Removes the Entry object at the given index in the values array from the DataSet. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 7402f3f2a2..cf41858f46 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -341,7 +341,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - BarEntry e = set.getEntryForXPos(high.getX()); + BarEntry e = set.getEntryForXValue(high.getX()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 8f2447d960..5b58a01deb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -85,8 +85,8 @@ public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCan float low = chart.getLowestVisibleX(); float high = chart.getHighestVisibleX(); - Entry entryFrom = dataSet.getEntryForXPos(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXPos(high, DataSet.Rounding.UP); + Entry entryFrom = dataSet.getEntryForXValue(low, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXValue(high, DataSet.Rounding.UP); min = dataSet.getEntryIndex(entryFrom); max = dataSet.getEntryIndex(entryTo); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index e4fc5cef5a..2a0bfcbb76 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -194,7 +194,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; // In bubble charts - it makes sense to have multiple bubbles on the same X value in the same dataset. - final List entries = set.getEntriesForXPos(high.getX()); + final List entries = set.getEntriesForXValue(high.getX()); for (BubbleEntry entry : entries) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index cdd79f41c3..ffc7479c8b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -317,7 +317,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - CandleEntry e = set.getEntryForXPos(high.getX()); + CandleEntry e = set.getEntryForXValue(high.getX()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 85e95a7621..e29686bf63 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -663,7 +663,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - Entry e = set.getEntryForXPos(high.getX()); + Entry e = set.getEntryForXValue(high.getX()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 2341ca5b59..e3da3cce7a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -143,7 +143,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - Entry e = set.getEntryForXPos(high.getX()); + Entry e = set.getEntryForXValue(high.getX()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 4ade7977b1..381c2b23da 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -141,7 +141,7 @@ public void testAddRemoveEntry() { } @Test - public void testGetEntryForXPos() { + public void testGetEntryForXValue() { List entries = new ArrayList(); entries.add(new Entry(10, 10)); @@ -150,31 +150,31 @@ public void testGetEntryForXPos() { ScatterDataSet set = new ScatterDataSet(entries, ""); - Entry closest = set.getEntryForXPos(17, DataSet.Rounding.CLOSEST); + Entry closest = set.getEntryForXValue(17, DataSet.Rounding.CLOSEST); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXPos(17, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(17, DataSet.Rounding.DOWN); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXPos(15, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(15, DataSet.Rounding.DOWN); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXPos(14, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(14, DataSet.Rounding.DOWN); assertEquals(10, closest.getX(), 0.01f); assertEquals(10, closest.getY(), 0.01f); - closest = set.getEntryForXPos(17, DataSet.Rounding.UP); + closest = set.getEntryForXValue(17, DataSet.Rounding.UP); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXPos(21, DataSet.Rounding.UP); + closest = set.getEntryForXValue(21, DataSet.Rounding.UP); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXPos(21, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(21, DataSet.Rounding.CLOSEST); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); } From 51f0e53a7f1de86bd0bc2fc2e3f2087ce54fe1bc Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 18:25:44 +0300 Subject: [PATCH 1119/1390] Reinvented Markers - interface based, enhanced default behaviour Two default implementations exist now: MarkerView, MarkerImage The default behaviour constraints the marker to the view's bounds. --- MPChartExample/AndroidManifest.xml | 10 - MPChartExample/build.gradle | 2 +- .../mpchartexample/BarChartActivity.java | 4 +- .../BarChartActivityMultiDataset.java | 5 +- .../DynamicalAddingActivity.java | 4 +- .../InvertedLineChartActivity.java | 5 +- .../mpchartexample/LineChartActivity1.java | 5 +- .../mpchartexample/RadarChartActivitry.java | 6 +- .../mpchartexample/custom/MyMarkerView.java | 12 +- .../custom/RadarMarkerView.java | 12 +- .../mpchartexample/custom/RealmDemoData.java | 180 ---------------- .../mpchartexample/custom/RealmFloat.java | 27 --- .../custom/StackedBarsMarkerView.java | 12 +- .../mpchartexample/custom/XYMarkerView.java | 12 +- .../fragments/BarChartFrag.java | 4 +- .../fragments/ScatterChartFrag.java | 4 +- .../notimportant/MainActivity.java | 9 - .../realm/RealmBaseActivity.java | 203 ------------------ .../realm/RealmDatabaseActivityBar.java | 69 ------ .../realm/RealmDatabaseActivityBubble.java | 71 ------ .../realm/RealmDatabaseActivityCandle.java | 77 ------- .../RealmDatabaseActivityHorizontalBar.java | 74 ------- .../realm/RealmDatabaseActivityLine.java | 77 ------- .../realm/RealmDatabaseActivityPie.java | 83 ------- .../realm/RealmDatabaseActivityRadar.java | 78 ------- .../realm/RealmDatabaseActivityScatter.java | 73 ------- .../realm/RealmMainActivity.java | 131 ----------- .../realm/RealmWikiExample.java | 137 ------------ .../mpchartexample/realm/Score.java | 51 ----- .../mikephil/charting/charts/Chart.java | 75 ++++--- .../mikephil/charting/components/IMarker.java | 52 +++++ .../charting/components/MarkerImage.java | 167 ++++++++++++++ .../charting/components/MarkerView.java | 118 ++++++---- .../github/mikephil/charting/utils/FSize.java | 5 +- .../mikephil/charting/utils/MPPointF.java | 7 +- build.gradle | 2 +- 36 files changed, 384 insertions(+), 1479 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index ab730cd2bd..4131688a8d 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -47,22 +47,12 @@ - - - - - - - - - - diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index c0d4745dcc..752d3fd321 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,5 +1,5 @@ apply plugin: 'com.android.application' -apply plugin: 'realm-android' +//apply plugin: 'realm-android' android { compileSdkVersion 23 diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index b51735f1e6..36dbd042b6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -119,7 +119,9 @@ protected void onCreate(Bundle savedInstanceState) { // l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", // "def", "ghj", "ikl", "mno" }); - mChart.setMarkerView(new XYMarkerView(this, xAxisFormatter)); + XYMarkerView mv = new XYMarkerView(this, xAxisFormatter); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); // Set the marker to the chart setData(12, 50); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index a75182bce8..f27de86b53 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -70,9 +70,8 @@ protected void onCreate(Bundle savedInstanceState) { // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - - // set the marker to the chart - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); // Set the marker to the chart mSeekBarX.setProgress(10); mSeekBarY.setProgress(100); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 2d1cbcd907..3462a74af8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -87,11 +87,11 @@ private void removeLastEntry() { if (set != null) { - Entry e = set.getEntryForXPos(set.getEntryCount() - 1); + Entry e = set.getEntryForXValue(set.getEntryCount() - 1); data.removeEntry(e, 0); // or remove by index - // mData.removeEntryByXPos(xIndex, dataSetIndex); + // mData.removeEntryByXValue(xIndex, dataSetIndex); data.notifyDataChanged(); mChart.notifyDataSetChanged(); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 1f760f871e..dc41160eb2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -79,9 +79,8 @@ protected void onCreate(Bundle savedInstanceState) { // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - - // set the marker to the chart - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); // Set the marker to the chart XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index d727370ff0..2de91ee64f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -92,9 +92,8 @@ protected void onCreate(Bundle savedInstanceState) { // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - - // set the marker to the chart - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); // Set the marker to the chart // x-axis limit line LimitLine llXAxis = new LimitLine(10f, "Index 10"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 97b871a0da..3326442a87 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.MarkerImage; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -58,9 +59,8 @@ protected void onCreate(Bundle savedInstanceState) { // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MarkerView mv = new RadarMarkerView(this, R.layout.radar_markerview); - - // set the marker to the chart - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); // Set the marker to the chart setData(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 53a3bc47f4..8d97346195 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -40,17 +41,12 @@ public void refreshContent(Entry e, Highlight highlight) { tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); } - } - @Override - public int getXOffset(float xpos) { - // this will center the marker-view horizontally - return -(getWidth() / 2); + super.refreshContent(e, highlight); } @Override - public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value - return -getHeight(); + public MPPointF getOffset() { + return new MPPointF(-(getWidth() / 2), -getHeight()); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 61f7209e44..b5aa1960d1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -38,17 +39,12 @@ public RadarMarkerView(Context context, int layoutResource) { public void refreshContent(Entry e, Highlight highlight) { float value = e.getY(); tvContent.setText(mFormattedStringCache.getFormattedValue(value) + " %"); - } - @Override - public int getXOffset(float xpos) { - // this will center the marker-view horizontally - return -(getWidth() / 2); + super.refreshContent(e, highlight); } @Override - public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value - return -getHeight()-10; + public MPPointF getOffset() { + return new MPPointF(-(getWidth() / 2), -getHeight() - 10); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java deleted file mode 100644 index 7becc88c90..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ /dev/null @@ -1,180 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - - -import io.realm.RealmList; -import io.realm.RealmObject; - -/** - * Demo class that encapsulates data stored in realm.io database. - * This class represents data suitable for all chart-types. - */ -public class RealmDemoData extends RealmObject { - - private float yValue; - private float xValue; - - private float open, close, high, low; - - private float bubbleSize; - - private RealmList stackValues; - - private String someStringField; - - /** - * label for pie entries - */ - private String label; - - // ofc there could me more fields here... - - public RealmDemoData() { - - } - - public RealmDemoData(float yValue) { - this.yValue = yValue; - } - - public RealmDemoData(float xValue, float yValue) { - this.xValue = xValue; - this.yValue = yValue; - } - - /** - * Constructor for stacked bars. - * - * @param xValue - * @param stackValues - */ - public RealmDemoData(float xValue, float[] stackValues) { - this.xValue = xValue; - this.stackValues = new RealmList(); - - for (float val : stackValues) { - this.stackValues.add(new RealmFloat(val)); - } - } - - /** - * Constructor for candles. - * - * @param xValue - * @param high - * @param low - * @param open - * @param close - */ - public RealmDemoData(float xValue, float high, float low, float open, float close) { - this.yValue = (high + low) / 2f; - this.high = high; - this.low = low; - this.open = open; - this.close = close; - this.xValue = xValue; - } - - /** - * Constructor for bubbles. - * - * @param xValue - * @param yValue - * @param bubbleSize - */ - public RealmDemoData(float xValue, float yValue, float bubbleSize) { - this.xValue = xValue; - this.yValue = yValue; - this.bubbleSize = bubbleSize; - } - - /** - * Constructor for pie chart. - * - * @param yValue - * @param label - */ - public RealmDemoData(float yValue, String label) { - this.yValue = yValue; - this.label = label; - } - - public float getyValue() { - return yValue; - } - - public void setyValue(float yValue) { - this.yValue = yValue; - } - - public float getxValue() { - return xValue; - } - - public void setxValue(float xValue) { - this.xValue = xValue; - } - - public RealmList getStackValues() { - return stackValues; - } - - public void setStackValues(RealmList stackValues) { - this.stackValues = stackValues; - } - - public float getOpen() { - return open; - } - - public void setOpen(float open) { - this.open = open; - } - - public float getClose() { - return close; - } - - public void setClose(float close) { - this.close = close; - } - - public float getHigh() { - return high; - } - - public void setHigh(float high) { - this.high = high; - } - - public float getLow() { - return low; - } - - public void setLow(float low) { - this.low = low; - } - - public float getBubbleSize() { - return bubbleSize; - } - - public void setBubbleSize(float bubbleSize) { - this.bubbleSize = bubbleSize; - } - - public String getSomeStringField() { - return someStringField; - } - - public void setSomeStringField(String someStringField) { - this.someStringField = someStringField; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } -} \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java deleted file mode 100644 index 15b027b3ff..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import io.realm.RealmObject; - -/** - * Created by Philipp Jahoda on 09/11/15. - */ -public class RealmFloat extends RealmObject { - - private float floatValue; - - public RealmFloat() { - - } - - public RealmFloat(float floatValue) { - this.floatValue = floatValue; - } - - public float getFloatValue() { - return floatValue; - } - - public void setFloatValue(float value) { - this.floatValue = value; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 0b8938778d..d0781b2ee2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -46,17 +47,12 @@ public void refreshContent(Entry e, Highlight highlight) { tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); } - } - @Override - public int getXOffset(float xpos) { - // this will center the marker-view horizontally - return -(getWidth() / 2); + super.refreshContent(e, highlight); } @Override - public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value - return -getHeight(); + public MPPointF getOffset() { + return new MPPointF(-(getWidth() / 2), -getHeight()); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 6bfa313c77..7a7fe726d5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -40,17 +41,12 @@ public XYMarkerView(Context context, AxisValueFormatter xAxisValueFormatter) { public void refreshContent(Entry e, Highlight highlight) { tvContent.setText("x: " + xAxisValueFormatter.getFormattedValue(e.getX(), null) + ", y: " + format.format(e.getY())); - } - @Override - public int getXOffset(float xpos) { - // this will center the marker-view horizontally - return -(getWidth() / 2); + super.refreshContent(e, highlight); } @Override - public int getYOffset(float ypos) { - // this will cause the marker-view to be above the selected value - return -getHeight(); + public MPPointF getOffset() { + return new MPPointF(-(getWidth() / 2), -getHeight()); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 29b378d44b..b77c0b815f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -37,8 +37,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setOnChartGestureListener(this); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 652a796321..cb1bd1c7e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -34,8 +34,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - - mChart.setMarkerView(mv); + mv.setChartView(mChart); // For bounds control + mChart.setMarker(mv); mChart.setDrawGridBackground(false); mChart.setData(generateScatterData(6, 10000, 200)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 617e43c021..512f4baa14 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -46,7 +46,6 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; -import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; @@ -131,10 +130,6 @@ protected void onCreate(Bundle savedInstanceState) { "BarChart positive / negative", "This demonstrates how to create a BarChart with positive and negative values in different colors.")); - ContentItem realm = new ContentItem( - "Realm.io Database", - "This demonstrates how to use this library with Realm.io mobile database."); - objects.add(realm); ContentItem time = new ContentItem( "Time Chart", @@ -274,10 +269,6 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, BarChartPositiveNegative.class); startActivity(i); break; - case 28: - i = new Intent(this, RealmMainActivity.class); - startActivity(i); - break; case 29: i = new Intent(this, LineChartTime.class); startActivity(i); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java deleted file mode 100644 index d4fef69576..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ /dev/null @@ -1,203 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; - -import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.PercentFormatter; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 05/11/15. - */ -public abstract class RealmBaseActivity extends DemoBase { - - protected Realm mRealm; - - protected Typeface mTf; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("Realm.io Examples"); - } - - protected void setup(Chart chart) { - - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - // no description text - chart.setDescription(""); - chart.setNoDataTextDescription("You need to provide data for the chart."); - - // enable touch gestures - chart.setTouchEnabled(true); - - if (chart instanceof BarLineChartBase) { - - BarLineChartBase mChart = (BarLineChartBase) chart; - - mChart.setDrawGridBackground(false); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setTypeface(mTf); - leftAxis.setTextSize(8f); - leftAxis.setTextColor(Color.DKGRAY); - leftAxis.setValueFormatter(new PercentFormatter()); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTf); - xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); - xAxis.setTextSize(8f); - xAxis.setTextColor(Color.DKGRAY); - - mChart.getAxisRight().setEnabled(false); - } - } - - protected void styleData(ChartData data) { - data.setValueTypeface(mTf); - data.setValueTextSize(8f); - data.setValueTextColor(Color.DKGRAY); - data.setValueFormatter(new PercentFormatter()); - } - - @Override - protected void onResume() { - super.onResume(); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); - Realm.setDefaultConfiguration(realmConfig); - - mRealm = Realm.getDefaultInstance(); - } - - @Override - protected void onPause() { - super.onPause(); - mRealm.close(); - } - - protected void writeToDB(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 40f + (float) (Math.random() * 60f); - - RealmDemoData d = new RealmDemoData(i, value); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBStack(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float val1 = 34f + (float) (Math.random() * 12.0f); - float val2 = 34f + (float) (Math.random() * 12.0f); - float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - - RealmDemoData d = new RealmDemoData(i, stack); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBCandle(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float mult = 50; - float val = (float) (Math.random() * 40) + mult; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close); - - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBBubble(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 30f + (float) (Math.random() * 100.0); - float size = 15f + (float) (Math.random() * 20.0); - - RealmDemoData d = new RealmDemoData(i, value, size); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBPie() { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - float value1 = 15f + (float) (Math.random() * 8f); - float value2 = 15f + (float) (Math.random() * 8f); - float value3 = 15f + (float) (Math.random() * 8f); - float value4 = 15f + (float) (Math.random() * 8f); - float value5 = 100f - value1 - value2 - value3 - value4; - - float[] values = new float[] { value1, value2, value3, value4, value5 }; - String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; - - for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], labels[i]); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java deleted file mode 100644 index c87290050d..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBar extends RealmBaseActivity { - - private BarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart_noseekbar); - - mChart = (BarChart) findViewById(R.id.chart1); - setup(mChart); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(20); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries - set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - set.setLabel("Realm BarDataSet"); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.setFitBars(true); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java deleted file mode 100644 index d0aa25b864..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BubbleChart; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBubble extends RealmBaseActivity { - - private BubbleChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_bubblechart_noseekbar); - - mChart = (BubbleChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getXAxis().setDrawGridLines(false); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBBubble(10); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); - set.setLabel("Realm BubbleDataSet"); - set.setColors(ColorTemplate.COLORFUL_COLORS, 110); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BubbleData data = new BubbleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java deleted file mode 100644 index a388df3741..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Paint; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.CandleStickChart; -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityCandle extends RealmBaseActivity { - - private CandleStickChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_candlechart_noseekbar); - - mChart = (CandleStickChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBCandle(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); - set.setLabel("Realm CandleDataSet"); - set.setShadowColor(Color.DKGRAY); - set.setShadowWidth(0.7f); - set.setDecreasingColor(Color.RED); - set.setDecreasingPaintStyle(Paint.Style.FILL); - set.setIncreasingColor(Color.rgb(122, 242, 84)); - set.setIncreasingPaintStyle(Paint.Style.STROKE); - set.setNeutralColor(Color.BLUE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - CandleData data = new CandleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java deleted file mode 100644 index 32d1234fe2..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { - - private HorizontalBarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_horizontalbarchart_noseekbar); - - mChart = (HorizontalBarChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMinValue(0f); - mChart.setDrawValueAboveBar(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBStack(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries - set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); - set.setLabel("Mobile OS distribution"); - set.setStackLabels(new String[]{"iOS", "Android", "Other"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - data.setValueTextColor(Color.WHITE); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java deleted file mode 100644 index 6d2396c22b..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityLine extends RealmBaseActivity { - - private LineChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart_noseekbar); - - mChart = (LineChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMaxValue(150f); - mChart.getAxisLeft().setAxisMinValue(0f); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(40); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); - set.setDrawCubic(false); - set.setLabel("Realm LineDataSet"); - set.setDrawCircleHole(false); - set.setColor(ColorTemplate.rgb("#FF5722")); - set.setCircleColor(ColorTemplate.rgb("#FF5722")); - set.setLineWidth(1.8f); - set.setCircleSize(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - LineData data = new LineData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java deleted file mode 100644 index 7b1eb675d9..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityPie extends RealmBaseActivity { - - private PieChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_piechart_noseekbar); - - mChart = (PieChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.setCenterText(generateCenterSpannableText()); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBPie(); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries - set.setColors(ColorTemplate.VORDIPLOM_COLORS); - set.setLabel("Example market share"); - set.setSliceSpace(2); - - // create a data object with the dataset list - PieData data = new PieData(set); - styleData(data); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(12f); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } - - private SpannableString generateCenterSpannableText() { - - SpannableString s = new SpannableString("Realm.io\nmobile database"); - s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); - s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); - s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); - s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); - s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); - return s; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java deleted file mode 100644 index 411f4b6ac9..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityRadar extends RealmBaseActivity { - - private RadarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); - - mChart = (RadarChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getYAxis().setEnabled(false); - mChart.getXAxis().setEnabled(false); - mChart.setWebAlpha(180); - mChart.setWebColorInner(Color.DKGRAY); - mChart.setWebColor(Color.GRAY); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(7); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries - set.setLabel("Realm RadarDataSet"); - set.setDrawFilled(true); - set.setColor(ColorTemplate.rgb("#009688")); - set.setFillColor(ColorTemplate.rgb("#009688")); - set.setFillAlpha(130); - set.setLineWidth(2f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - RadarData data = new RadarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java deleted file mode 100644 index 14175ac73a..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityScatter extends RealmBaseActivity { - - private ScatterChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_scatterchart_noseekbar); - - mChart = (ScatterChart) findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(45); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); - set.setLabel("Realm ScatterDataSet"); - set.setScatterShapeSize(9f); - set.setColor(ColorTemplate.rgb("#CDDC39")); - set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - ScatterData data = new ScatterData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java deleted file mode 100644 index 3198320272..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ListView; - -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; - -import java.util.ArrayList; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_main); - - setTitle("Realm.io Examples"); - - ArrayList objects = new ArrayList(); - - objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); - objects.add(new ContentItem("Bar Chart", - "Creating a BarChart with Realm.io database")); - objects.add(new ContentItem("Horizontal Bar Chart", - "Creating a HorizontalBarChart with Realm.io database")); - objects.add(new ContentItem("Scatter Chart", - "Creating a ScatterChart with Realm.io database")); - objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); - objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); - objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); - objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); - objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); - - MyAdapter adapter = new MyAdapter(this, objects); - - ListView lv = (ListView) findViewById(R.id.listView1); - lv.setAdapter(adapter); - - lv.setOnItemClickListener(this); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); - Realm.setDefaultConfiguration(realmConfig); - - Realm realm = Realm.getDefaultInstance(); - realm.beginTransaction(); - realm.deleteAll(); - realm.commitTransaction(); - } - - @Override - public void onItemClick(AdapterView av, View v, int pos, long arg3) { - - Intent i; - - switch (pos) { - case 0: - i = new Intent(this, RealmDatabaseActivityLine.class); - startActivity(i); - break; - case 1: - i = new Intent(this, RealmDatabaseActivityBar.class); - startActivity(i); - break; - case 2: - i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); - startActivity(i); - break; - case 3: - i = new Intent(this, RealmDatabaseActivityScatter.class); - startActivity(i); - break; - case 4: - i = new Intent(this, RealmDatabaseActivityCandle.class); - startActivity(i); - break; - case 5: - i = new Intent(this, RealmDatabaseActivityBubble.class); - startActivity(i); - break; - case 6: - i = new Intent(this, RealmDatabaseActivityPie.class); - startActivity(i); - break; - case 7: - i = new Intent(this, RealmDatabaseActivityRadar.class); - startActivity(i); - break; - case 8: - i = new Intent(this, RealmWikiExample.class); - startActivity(i); - break; - } - - overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realm, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://realm.io")); - startActivity(i); - - return super.onOptionsItemSelected(item); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java deleted file mode 100644 index 7682bca957..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 18/12/15. - */ -public class RealmWikiExample extends RealmBaseActivity { - - private LineChart lineChart; - private BarChart barChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_realm_wiki); - - lineChart = (LineChart) findViewById(R.id.lineChart); - barChart = (BarChart) findViewById(R.id.barChart); - setup(lineChart); - setup(barChart); - - lineChart.setExtraBottomOffset(5f); - barChart.setExtraBottomOffset(5f); - - lineChart.getAxisLeft().setDrawGridLines(false); - lineChart.getXAxis().setDrawGridLines(false); - lineChart.getXAxis().setLabelCount(5); - lineChart.getXAxis().setGranularity(1f); - barChart.getAxisLeft().setDrawGridLines(false); - barChart.getXAxis().setDrawGridLines(false); - barChart.getXAxis().setLabelCount(5); - barChart.getXAxis().setGranularity(1f); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - mRealm.beginTransaction(); - - // write some demo-data into the realm.io database - Score score1 = new Score(100f, 0f, "Peter"); - mRealm.copyToRealm(score1); - Score score2 = new Score(110f, 1f, "Lisa"); - mRealm.copyToRealm(score2); - Score score3 = new Score(130f, 2f, "Dennis"); - mRealm.copyToRealm(score3); - Score score4 = new Score(70f, 3f, "Luke"); - mRealm.copyToRealm(score4); - Score score5 = new Score(80f, 4f, "Sarah"); - mRealm.copyToRealm(score5); - - mRealm.commitTransaction(); - - // add data to the chart - setData(); - } - - private void setData() { - - // LINE-CHART - final RealmResults results = mRealm.where(Score.class).findAll(); - - - AxisValueFormatter formatter = new AxisValueFormatter() { - @Override - public String getFormattedValue(float value, AxisBase axis) { - return results.get((int) value).getPlayerName(); - } - - @Override - public int getDecimalDigits() { - return 0; - } - }; - - lineChart.getXAxis().setValueFormatter(formatter); - barChart.getXAxis().setValueFormatter(formatter); - - RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); - lineDataSet.setDrawCubic(false); - lineDataSet.setLabel("Result Scores"); - lineDataSet.setDrawCircleHole(false); - lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setLineWidth(1.8f); - lineDataSet.setCircleSize(3.6f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(lineDataSet); - - LineData lineData = new LineData(dataSets); - styleData(lineData); - - // set data - lineChart.setData(lineData); - lineChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - - - // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); - barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); - barDataSet.setLabel("Realm BarDataSet"); - - ArrayList barDataSets = new ArrayList(); - barDataSets.add(barDataSet); - - BarData barData = new BarData(barDataSets); - styleData(barData); - - barChart.setData(barData); - barChart.setFitBars(true); - barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java deleted file mode 100644 index 870e371491..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - - -import io.realm.RealmObject; - -/** - * our data object - */ -public class Score extends RealmObject { - - private float totalScore; - - private float scoreNr; - - private String playerName; - - public Score() { - } - - public Score(float totalScore, float scoreNr, String playerName) { - this.scoreNr = scoreNr; - this.playerName = playerName; - this.totalScore = totalScore; - } - - // all getters and setters... - - public float getTotalScore() { - return totalScore; - } - - public void setTotalScore(float totalScore) { - this.totalScore = totalScore; - } - - public float getScoreNr() { - return scoreNr; - } - - public void setScoreNr(float scoreNr) { - this.scoreNr = scoreNr; - } - - public String getPlayerName() { - return playerName; - } - - public void setPlayerName(String playerName) { - this.playerName = playerName; - } -} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 74823825c8..93d07572ae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -27,8 +27,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.components.IMarker; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; @@ -710,12 +710,12 @@ public ChartTouchListener getOnTouchListener() { /** * if set to true, the marker view is drawn when a value is clicked */ - protected boolean mDrawMarkerViews = true; + protected boolean mDrawMarkers = true; /** * the view that represents the marker */ - protected MarkerView mMarkerView; + protected IMarker mMarker; /** * draws all MarkerViews on the highlighted positions @@ -723,7 +723,7 @@ public ChartTouchListener getOnTouchListener() { protected void drawMarkers(Canvas canvas) { // if there is no marker view or drawing marker is disabled - if (mMarkerView == null || !mDrawMarkerViews || !valuesToHighlight()) + if (mMarker == null || !isDrawMarkersEnabled() || !valuesToHighlight()) return; for (int i = 0; i < mIndicesToHighlight.length; i++) { @@ -746,19 +746,10 @@ protected void drawMarkers(Canvas canvas) { continue; // callbacks to update the content - mMarkerView.refreshContent(e, highlight); + mMarker.refreshContent(e, highlight); - mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - mMarkerView.layout(0, 0, mMarkerView.getMeasuredWidth(), - mMarkerView.getMeasuredHeight()); - - if (pos[1] - mMarkerView.getHeight() <= 0) { - float y = mMarkerView.getHeight() - pos[1]; - mMarkerView.draw(canvas, pos[0], pos[1] + y); - } else { - mMarkerView.draw(canvas, pos[0], pos[1]); - } + // draw the marker + mMarker.draw(canvas, pos[0], pos[1]); } } @@ -1272,21 +1263,31 @@ public void setTouchEnabled(boolean enabled) { } /** - * sets the view that is displayed when a value is clicked on the chart + * sets the marker that is displayed when a value is clicked on the chart * - * @param v + * @param marker */ - public void setMarkerView(MarkerView v) { - mMarkerView = v; + public void setMarker(IMarker marker) { + mMarker = marker; } /** - * returns the view that is set as a marker view for the chart + * returns the marker that is set as a marker view for the chart * * @return */ - public MarkerView getMarkerView() { - return mMarkerView; + public IMarker getMarker() { + return mMarker; + } + + @Deprecated + public void setMarkerView(IMarker v) { + setMarker(v); + } + + @Deprecated + public IMarker getMarkerView() { + return getMarker(); } /** @@ -1407,25 +1408,35 @@ public Paint getPaint(int which) { return null; } + @Deprecated + public boolean isDrawMarkerViewsEnabled() { + return isDrawMarkersEnabled(); + } + + @Deprecated + public void setDrawMarkerViews(boolean enabled) { + setDrawMarkers(enabled); + } + /** - * returns true if drawing the marker-view is enabled when tapping on values - * (use the setMarkerView(View v) method to specify a marker view) + * returns true if drawing the marker is enabled when tapping on values + * (use the setMarker(IMarker marker) method to specify a marker) * * @return */ - public boolean isDrawMarkerViewEnabled() { - return mDrawMarkerViews; + public boolean isDrawMarkersEnabled() { + return mDrawMarkers; } /** - * Set this to true to draw a user specified marker-view when tapping on - * chart values (use the setMarkerView(MarkerView mv) method to specify a - * marker view). Default: true + * Set this to true to draw a user specified marker when tapping on + * chart values (use the setMarker(IMarker marker) method to specify a + * marker). Default: true * * @param enabled */ - public void setDrawMarkerViews(boolean enabled) { - mDrawMarkerViews = enabled; + public void setDrawMarkers(boolean enabled) { + mDrawMarkers = enabled; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java new file mode 100644 index 0000000000..d8ee7452ab --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java @@ -0,0 +1,52 @@ +package com.github.mikephil.charting.components; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointF; + +public interface IMarker { + + /** + * @return The desired offset you wish the IMarker to have on the x-axis. + * By returning x: -(width / 2) you will center the IMarker horizontally. + * By returning y: -(height / 2) you will center the IMarker vertically. + */ + MPPointF getOffset(); + + /** + * @return The offset for drawing at the specific `point` + * If you have no adjustments to make, return getOffset(). + * + * @param posX This is the X position at which the marker wants to be drawn. + * You can adjust the offset conditionally based on this argument. + * @param posY This is the X position at which the marker wants to be drawn. + * You can adjust the offset conditionally based on this argument. + */ + MPPointF getOffsetForDrawingAtPos(float posX, float posY); + + /** + * This method enables a specified custom IMarker to update it's content every time the IMarker is redrawn. + * + * @param e The Entry the IMarker belongs to. This can also be any subclass of Entry, like BarEntry or + * CandleEntry, simply cast it at runtime. + * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the + * selected range or stack-index (only stacked bar entries). + */ + void refreshContent(Entry e, Highlight highlight); + + /** + * Draws the IMarker on the given position on the screen with the given Canvas object. + * + * @param canvas + * @param posX + * @param posY + */ + void draw(Canvas canvas, float posX, float posY); +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java new file mode 100644 index 0000000000..5c952bb056 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java @@ -0,0 +1,167 @@ +package com.github.mikephil.charting.components; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.RelativeLayout; + +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointF; + +import java.lang.ref.WeakReference; + +/** + * View that can be displayed when selecting values in the chart. Extend this class to provide custom layouts for your + * markers. + * + * @author Philipp Jahoda + */ +public class MarkerImage implements IMarker { + + private Context mContext; + private Drawable mDrawable; + + private MPPointF mOffset = new MPPointF(); + private MPPointF mOffset2 = new MPPointF(); + private WeakReference mWeakChart; + + private FSize mSize = new FSize(); + private Rect mDrawableBoundsCache = new Rect(); + + /** + * Constructor. Sets up the MarkerView with a custom layout resource. + * + * @param context + * @param drawableResourceId the drawable resource to render + */ + public MarkerImage(Context context, int drawableResourceId) { + mContext = context; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) + { + mDrawable = mContext.getResources().getDrawable(drawableResourceId, null); + } + else + { + mDrawable = mContext.getResources().getDrawable(drawableResourceId); + } + } + + public void setOffset(MPPointF offset) { + mOffset = offset; + + if (mOffset == null) { + mOffset = new MPPointF(); + } + } + + public void setOffset(float offsetX, float offsetY) { + mOffset.x = offsetX; + mOffset.y = offsetY; + } + + @Override + public MPPointF getOffset() { + return mOffset; + } + + public void setSize(FSize size) { + mSize = size; + + if (mSize == null) { + mSize = new FSize(); + } + } + + public FSize getSize() { + return mSize; + } + + public void setChartView(Chart chart) { + mWeakChart = new WeakReference<>(chart); + } + + public Chart getChartView() { + return mWeakChart == null ? null : mWeakChart.get(); + } + + @Override + public MPPointF getOffsetForDrawingAtPos(float posX, float posY) { + + MPPointF offset = getOffset(); + mOffset2.x = offset.x; + mOffset2.y = offset.y; + + Chart chart = getChartView(); + + float width = mSize.width; + float height = mSize.height; + + if (width == 0.f && mDrawable != null) { + width = mDrawable.getIntrinsicWidth(); + } + if (height == 0.f && mDrawable != null) { + height = mDrawable.getIntrinsicHeight(); + } + + if (posX + mOffset2.x < 0) { + mOffset2.x = - posX; + } else if (chart != null && posX + width + mOffset2.x > chart.getWidth()) { + mOffset2.x = chart.getWidth() - posX - width; + } + + if (posY + mOffset2.y < 0) { + mOffset2.y = - posY; + } else if (chart != null && posY + height + mOffset2.y > chart.getHeight()) { + mOffset2.y = chart.getHeight() - posY - height; + } + + return mOffset2; + } + + @Override + public void refreshContent(Entry e, Highlight highlight) { + + } + + @Override + public void draw(Canvas canvas, float posX, float posY) { + + if (mDrawable == null) return; + + MPPointF offset = getOffsetForDrawingAtPos(posX, posY); + + float width = mSize.width; + float height = mSize.height; + + if (width == 0.f && mDrawable != null) { + width = mDrawable.getIntrinsicWidth(); + } + if (height == 0.f && mDrawable != null) { + height = mDrawable.getIntrinsicHeight(); + } + + mDrawable.copyBounds(mDrawableBoundsCache); + mDrawable.setBounds( + mDrawableBoundsCache.left, + mDrawableBoundsCache.top, + mDrawableBoundsCache.left + (int)width, + mDrawableBoundsCache.top + (int)height); + + int saveId = canvas.save(); + // translate to the correct position and draw + canvas.translate(posX + offset.x, posY + offset.y); + mDrawable.draw(canvas); + canvas.restoreToCount(saveId); + + mDrawable.setBounds(mDrawableBoundsCache); + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java index 523376c786..478527caee 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java @@ -6,8 +6,13 @@ import android.view.View; import android.widget.RelativeLayout; +import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.FSize; +import com.github.mikephil.charting.utils.MPPointF; + +import java.lang.ref.WeakReference; /** * View that can be displayed when selecting values in the chart. Extend this class to provide custom layouts for your @@ -15,7 +20,11 @@ * * @author Philipp Jahoda */ -public abstract class MarkerView extends RelativeLayout { +public class MarkerView extends RelativeLayout implements IMarker { + + private MPPointF mOffset = new MPPointF(); + private MPPointF mOffset2 = new MPPointF(); + private WeakReference mWeakChart; /** * Constructor. Sets up the MarkerView with a custom layout resource. @@ -44,50 +53,77 @@ private void setupLayoutResource(int layoutResource) { inflated.layout(0, 0, inflated.getMeasuredWidth(), inflated.getMeasuredHeight()); } - /** - * Draws the MarkerView on the given position on the screen with the given Canvas object. - * - * @param canvas - * @param posx - * @param posy - */ - public void draw(Canvas canvas, float posx, float posy) { + public void setOffset(MPPointF offset) { + mOffset = offset; - // take offsets into consideration - posx += getXOffset(posx); - posy += getYOffset(posy); + if (mOffset == null) { + mOffset = new MPPointF(); + } + } - // translate to the correct position and draw - canvas.translate(posx, posy); - draw(canvas); - canvas.translate(-posx, -posy); + public void setOffset(float offsetX, float offsetY) { + mOffset.x = offsetX; + mOffset.y = offsetY; } - /** - * This method enables a specified custom MarkerView to update it's content everytime the MarkerView is redrawn. - * - * @param e The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or - * CandleEntry, simply cast it at runtime. - * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the - * selected range or stack-index (only stacked bar entries). - */ - public abstract void refreshContent(Entry e, Highlight highlight); + @Override + public MPPointF getOffset() { + return mOffset; + } - /** - * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / - * 2) you will center the MarkerView horizontally. - * - * @param xpos the position on the x-axis in pixels where the marker is drawn - * @return - */ - public abstract int getXOffset(float xpos); + public void setChartView(Chart chart) { + mWeakChart = new WeakReference<>(chart); + } - /** - * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning - * -getHeight() you will cause the MarkerView to be above the selected value. - * - * @param ypos the position on the y-axis in pixels where the marker is drawn - * @return - */ - public abstract int getYOffset(float ypos); + public Chart getChartView() { + return mWeakChart == null ? null : mWeakChart.get(); + } + + @Override + public MPPointF getOffsetForDrawingAtPos(float posX, float posY) { + + MPPointF offset = getOffset(); + mOffset2.x = offset.x; + mOffset2.y = offset.y; + + Chart chart = getChartView(); + + float width = getWidth(); + float height = getHeight(); + + if (posX + mOffset2.x < 0) { + mOffset2.x = - posX; + } else if (chart != null && posX + width + mOffset2.x > chart.getWidth()) { + mOffset2.x = chart.getWidth() - posX - width; + } + + if (posY + mOffset2.y < 0) { + mOffset2.y = - posY; + } else if (chart != null && posY + height + mOffset2.y > chart.getHeight()) { + mOffset2.y = chart.getHeight() - posY - height; + } + + return mOffset2; + } + + @Override + public void refreshContent(Entry e, Highlight highlight) { + + measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), + MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + layout(0, 0, getMeasuredWidth(), getMeasuredHeight()); + + } + + @Override + public void draw(Canvas canvas, float posX, float posY) { + + MPPointF offset = getOffsetForDrawingAtPos(posX, posY); + + int saveId = canvas.save(); + // translate to the correct position and draw + canvas.translate(posX + offset.x, posY + offset.y); + draw(canvas); + canvas.restoreToCount(saveId); + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index d4ff8974d4..a12bc45918 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -41,7 +41,10 @@ public static void recycleInstances(List instances){ pool.recycle(instances); } - private FSize(final float width, final float height) { + public FSize() { + } + + public FSize(final float width, final float height) { this.width = width; this.height = height; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java index 2e3fc58934..36dd6d33ea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java @@ -20,12 +20,15 @@ public class MPPointF extends ObjectPool.Poolable { pool.setReplenishPercentage(0.5f); } - private MPPointF(float x, float y){ + public MPPointF() { + } + + public MPPointF(float x, float y) { this.x = x; this.y = y; } - public static MPPointF getInstance(float x, float y){ + public static MPPointF getInstance(float x, float y) { MPPointF result = pool.get(); result.x = x; result.y = y; diff --git a/build.gradle b/build.gradle index 3dfff3b287..339dc2007c 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath "io.realm:realm-gradle-plugin:1.1.0" + //classpath "io.realm:realm-gradle-plugin:1.1.0" classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } From aaec1f5d2cbd8546eb2b5df73b512f75fd21004e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 22:15:57 +0300 Subject: [PATCH 1120/1390] DRYed scatter code, simplified IShapeRenderer implementations --- .../custom/CustomScatterShapeRenderer.java | 31 +++----- .../charting/buffer/ScatterBuffer.java | 31 -------- .../renderer/ScatterChartRenderer.java | 56 ++++++++------ .../scatter/ChevronDownShapeRenderer.java | 46 ++++-------- .../scatter/ChevronUpShapeRenderer.java | 45 ++++------- .../renderer/scatter/CircleShapeRenderer.java | 60 ++++++--------- .../renderer/scatter/CrossShapeRenderer.java | 44 ++++------- .../renderer/scatter/IShapeRenderer.java | 14 ++-- .../renderer/scatter/SquareShapeRenderer.java | 64 +++++++--------- .../scatter/TriangleShapeRenderer.java | 74 ++++++++----------- .../renderer/scatter/XShapeRenderer.java | 43 ++++------- 11 files changed, 190 insertions(+), 318 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java index 77ffe2759e..6279e395f6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -16,28 +15,16 @@ public class CustomScatterShapeRenderer implements IShapeRenderer { @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { - final float shapeHalf = shapeSize / 2f; + final float shapeHalf = dataSet.getScatterShapeSize() / 2f; - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - renderPaint); - } + c.drawLine( + posX - shapeHalf, + posY - shapeHalf, + posX + shapeHalf, + posY + shapeHalf, + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java deleted file mode 100644 index 14b75fb1f7..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/ScatterBuffer.java +++ /dev/null @@ -1,31 +0,0 @@ - -package com.github.mikephil.charting.buffer; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; - -public class ScatterBuffer extends AbstractBuffer { - - public ScatterBuffer(int size) { - super(size); - } - - protected void addForm(float x, float y) { - buffer[index++] = x; - buffer[index++] = y; - } - - @Override - public void feed(IScatterDataSet data) { - - float size = data.getEntryCount() * phaseX; - - for (int i = 0; i < size; i++) { - - Entry e = data.getEntryForIndex(i); - addForm(e.getX(), e.getY() * phaseY); - } - - reset(); - } -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index e3da3cce7a..faf2395626 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -2,9 +2,9 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.Highlight; @@ -22,8 +22,6 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer { protected ScatterDataProvider mChart; - protected ScatterBuffer[] mScatterBuffers; - public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -31,15 +29,6 @@ public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, V @Override public void initBuffers() { - - ScatterData scatterData = mChart.getScatterData(); - - mScatterBuffers = new ScatterBuffer[scatterData.getDataSetCount()]; - - for (int i = 0; i < mScatterBuffers.length; i++) { - IScatterDataSet set = scatterData.getDataSetByIndex(i); - mScatterBuffers[i] = new ScatterBuffer(set.getEntryCount() * 2); - } } @Override @@ -57,28 +46,47 @@ public void drawData(Canvas c) { } } + float[] mPixelBuffer = new float[2]; + protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { + ViewPortHandler viewPortHandler = mViewPortHandler; + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); - final float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); + IShapeRenderer renderer = dataSet.getShapeRenderer(); + if (renderer == null) { + Log.i("MISSING", "There's no IShapeRenderer specified for ScatterDataSet"); + return; + } - ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet(dataSet)]; - buffer.setPhases(phaseX, phaseY); - buffer.feed(dataSet); + int max = (int)(Math.min( + Math.ceil((float)dataSet.getEntryCount() * mAnimator.getPhaseX()), + (float)dataSet.getEntryCount())); - trans.pointValuesToPixel(buffer.buffer); + for (int i = 0; i < max; i++) { - IShapeRenderer renderer = dataSet.getShapeRenderer(); + Entry e = dataSet.getEntryForIndex(i); + + mPixelBuffer[0] = e.getX(); + mPixelBuffer[1] = e.getY() * phaseY; + + trans.pointValuesToPixel(mPixelBuffer); + + if (!viewPortHandler.isInBoundsRight(mPixelBuffer[0])) + break; + + if (!viewPortHandler.isInBoundsLeft(mPixelBuffer[0]) + || !viewPortHandler.isInBoundsY(mPixelBuffer[1])) + continue; - if (renderer != null) { - renderer.renderShape(c, dataSet, mViewPortHandler, buffer, mRenderPaint, shapeSize); - } else { - throw new RuntimeException("No IShapeRenderer found for provided identifier. Please make sure to add a IShapeRenderer" + - " capable of rendering the provided shape."); + mRenderPaint.setColor(dataSet.getColor(i / 2)); + renderer.renderShape( + c, dataSet, mViewPortHandler, + mPixelBuffer[0], mPixelBuffer[1], + mRenderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java index cdc3f2af6d..9328b276c4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronDownShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,39 +16,26 @@ public class ChevronDownShapeRenderer implements IShapeRenderer @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { - final float shapeHalf = shapeSize / 2f; + final float shapeHalf = dataSet.getScatterShapeSize() / 2f; renderPaint.setStyle(Paint.Style.STROKE); renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] + (2 * shapeHalf), - buffer.buffer[i] + (2 * shapeHalf), - buffer.buffer[i + 1], - renderPaint); - - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] + (2 * shapeHalf), - buffer.buffer[i] - (2 * shapeHalf), - buffer.buffer[i + 1], - renderPaint); - } - + c.drawLine( + posX, + posY + (2 * shapeHalf), + posX + (2 * shapeHalf), + posY, + renderPaint); + + c.drawLine( + posX, + posY + (2 * shapeHalf), + posX - (2 * shapeHalf), + posY, + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java index f4185bfd8e..6dea0abf7b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/ChevronUpShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,39 +16,27 @@ public class ChevronUpShapeRenderer implements IShapeRenderer @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { - final float shapeHalf = shapeSize / 2f; + final float shapeHalf = dataSet.getScatterShapeSize() / 2f; renderPaint.setStyle(Paint.Style.STROKE); renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] - (2 * shapeHalf), - buffer.buffer[i] + (2 * shapeHalf), - buffer.buffer[i + 1], - renderPaint); - - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] - (2 * shapeHalf), - buffer.buffer[i] - (2 * shapeHalf), - buffer.buffer[i + 1], - renderPaint); - } + c.drawLine( + posX, + posY - (2 * shapeHalf), + posX + (2 * shapeHalf), + posY, + renderPaint); + + c.drawLine( + posX, + posY - (2 * shapeHalf), + posX - (2 * shapeHalf), + posY, + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java index 98ed8c1459..ac7abb92de 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CircleShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -17,9 +16,10 @@ public class CircleShapeRenderer implements IShapeRenderer { @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { + final float shapeSize = dataSet.getScatterShapeSize(); final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); final float shapeHoleSize = shapeHoleSizeHalf * 2.f; @@ -28,46 +28,34 @@ public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewP final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); - for (int i = 0; i < buffer.size(); i += 2) { + if (shapeSize > 0.0) { + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(shapeStrokeSize); - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; + c.drawCircle( + posX, + posY, + shapeHoleSizeHalf + shapeStrokeSizeHalf, + renderPaint); - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - if (shapeSize > 0.0) { - renderPaint.setStyle(Paint.Style.STROKE); - renderPaint.setStrokeWidth(shapeStrokeSize); - - c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHoleSizeHalf + shapeStrokeSizeHalf, - renderPaint); - - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - renderPaint.setStyle(Paint.Style.FILL); - - renderPaint.setColor(shapeHoleColor); - c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHoleSizeHalf, - renderPaint); - } - } else { + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { renderPaint.setStyle(Paint.Style.FILL); + renderPaint.setColor(shapeHoleColor); c.drawCircle( - buffer.buffer[i], - buffer.buffer[i + 1], - shapeHalf, + posX, + posY, + shapeHoleSizeHalf, renderPaint); } + } else { + renderPaint.setStyle(Paint.Style.FILL); + + c.drawCircle( + posX, + posY, + shapeHalf, + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java index 3273490a46..202670d6ba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/CrossShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,39 +16,26 @@ public class CrossShapeRenderer implements IShapeRenderer @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { - - final float shapeHalf = shapeSize / 2f; + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { + final float shapeHalf = dataSet.getScatterShapeSize() / 2f; renderPaint.setStyle(Paint.Style.STROKE); renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1], - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1], - renderPaint); - c.drawLine( - buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i], - buffer.buffer[i + 1] + shapeHalf, - renderPaint); - } + c.drawLine( + posX - shapeHalf, + posY, + posX + shapeHalf, + posY, + renderPaint); + c.drawLine( + posX, + posY - shapeHalf, + posX, + posY + shapeHalf, + renderPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java index f89d6f6b08..20b57a900d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/IShapeRenderer.java @@ -3,8 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; -import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -19,12 +17,12 @@ public interface IShapeRenderer * Renders the provided ScatterDataSet with a shape. * * @param c Canvas object for drawing the shape - * @param dataSet the DataSet to be drawn - * @param viewPortHandler contains information about the current state of the view - * @param buffer buffer containing the transformed values of all entries in the DataSet + * @param dataSet The DataSet to be drawn + * @param viewPortHandler Contains information about the current state of the view + * @param posX Position to draw the shape at + * @param posY Position to draw the shape at * @param renderPaint Paint object used for styling and drawing - * @param shapeSize */ - void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize); + void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java index 74670473ef..ac98679233 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/SquareShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -18,9 +17,10 @@ public class SquareShapeRenderer implements IShapeRenderer @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { + final float shapeSize = dataSet.getScatterShapeSize(); final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); final float shapeHoleSize = shapeHoleSizeHalf * 2.f; @@ -29,47 +29,35 @@ public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewP final int shapeHoleColor = dataSet.getScatterShapeHoleColor(); - for (int i = 0; i < buffer.size(); i += 2) { + if (shapeSize > 0.0) { + renderPaint.setStyle(Paint.Style.STROKE); + renderPaint.setStrokeWidth(shapeStrokeSize); - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; + c.drawRect(posX - shapeHoleSizeHalf - shapeStrokeSizeHalf, + posY - shapeHoleSizeHalf - shapeStrokeSizeHalf, + posX + shapeHoleSizeHalf + shapeStrokeSizeHalf, + posY + shapeHoleSizeHalf + shapeStrokeSizeHalf, + renderPaint); - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - if (shapeSize > 0.0) { - renderPaint.setStyle(Paint.Style.STROKE); - renderPaint.setStrokeWidth(shapeStrokeSize); - - c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf - shapeStrokeSizeHalf, - buffer.buffer[i + 1] - shapeHoleSizeHalf - shapeStrokeSizeHalf, - buffer.buffer[i] + shapeHoleSizeHalf + shapeStrokeSizeHalf, - buffer.buffer[i + 1] + shapeHoleSizeHalf + shapeStrokeSizeHalf, - renderPaint); - - if (shapeHoleColor != ColorTemplate.COLOR_NONE) { - renderPaint.setStyle(Paint.Style.FILL); - - renderPaint.setColor(shapeHoleColor); - c.drawRect(buffer.buffer[i] - shapeHoleSizeHalf, - buffer.buffer[i + 1] - shapeHoleSizeHalf, - buffer.buffer[i] + shapeHoleSizeHalf, - buffer.buffer[i + 1] + shapeHoleSizeHalf, - renderPaint); - } - - } else { + if (shapeHoleColor != ColorTemplate.COLOR_NONE) { renderPaint.setStyle(Paint.Style.FILL); - c.drawRect(buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] + shapeHalf, + renderPaint.setColor(shapeHoleColor); + c.drawRect(posX - shapeHoleSizeHalf, + posY - shapeHoleSizeHalf, + posX + shapeHoleSizeHalf, + posY + shapeHoleSizeHalf, renderPaint); } + + } else { + renderPaint.setStyle(Paint.Style.FILL); + + c.drawRect(posX - shapeHalf, + posY - shapeHalf, + posX + shapeHalf, + posY + shapeHalf, + renderPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java index f8e2f30b47..5343454bbb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/TriangleShapeRenderer.java @@ -4,7 +4,6 @@ import android.graphics.Paint; import android.graphics.Path; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -20,9 +19,10 @@ public class TriangleShapeRenderer implements IShapeRenderer protected Path mTrianglePathBuffer = new Path(); @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { + final float shapeSize = dataSet.getScatterShapeSize(); final float shapeHalf = shapeSize / 2f; final float shapeHoleSizeHalf = Utils.convertDpToPixel(dataSet.getScatterShapeHoleRadius()); final float shapeHoleSize = shapeHoleSizeHalf * 2.f; @@ -36,55 +36,43 @@ public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewP Path tri = mTrianglePathBuffer; tri.reset(); - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; + tri.moveTo(posX, posY - shapeHalf); + tri.lineTo(posX + shapeHalf, posY + shapeHalf); + tri.lineTo(posX - shapeHalf, posY + shapeHalf); + + if (shapeSize > 0.0) { + tri.lineTo(posX, posY - shapeHalf); + + tri.moveTo(posX - shapeHalf + shapeStrokeSize, + posY + shapeHalf - shapeStrokeSize); + tri.lineTo(posX + shapeHalf - shapeStrokeSize, + posY + shapeHalf - shapeStrokeSize); + tri.lineTo(posX, + posY - shapeHalf + shapeStrokeSize); + tri.lineTo(posX - shapeHalf + shapeStrokeSize, + posY + shapeHalf - shapeStrokeSize); + } - renderPaint.setColor(dataSet.getColor(i / 2)); + tri.close(); - tri.moveTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); - tri.lineTo(buffer.buffer[i] + shapeHalf, buffer.buffer[i + 1] + shapeHalf); - tri.lineTo(buffer.buffer[i] - shapeHalf, buffer.buffer[i + 1] + shapeHalf); + c.drawPath(tri, renderPaint); + tri.reset(); - if (shapeSize > 0.0) { - tri.lineTo(buffer.buffer[i], buffer.buffer[i + 1] - shapeHalf); + if (shapeSize > 0.0 && + shapeHoleColor != ColorTemplate.COLOR_NONE) { - tri.moveTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); - tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - } + renderPaint.setColor(shapeHoleColor); + tri.moveTo(posX, + posY - shapeHalf + shapeStrokeSize); + tri.lineTo(posX + shapeHalf - shapeStrokeSize, + posY + shapeHalf - shapeStrokeSize); + tri.lineTo(posX - shapeHalf + shapeStrokeSize, + posY + shapeHalf - shapeStrokeSize); tri.close(); c.drawPath(tri, renderPaint); tri.reset(); - - if (shapeSize > 0.0 && - shapeHoleColor != ColorTemplate.COLOR_NONE) { - - renderPaint.setColor(shapeHoleColor); - - tri.moveTo(buffer.buffer[i], - buffer.buffer[i + 1] - shapeHalf + shapeStrokeSize); - tri.lineTo(buffer.buffer[i] + shapeHalf - shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.lineTo(buffer.buffer[i] - shapeHalf + shapeStrokeSize, - buffer.buffer[i + 1] + shapeHalf - shapeStrokeSize); - tri.close(); - - c.drawPath(tri, renderPaint); - tri.reset(); - } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java index 3c37174e2f..225640ec8e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/scatter/XShapeRenderer.java @@ -3,7 +3,6 @@ import android.graphics.Canvas; import android.graphics.Paint; -import com.github.mikephil.charting.buffer.ScatterBuffer; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -17,38 +16,26 @@ public class XShapeRenderer implements IShapeRenderer @Override - public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, ScatterBuffer buffer, Paint - renderPaint, final float shapeSize) { + public void renderShape(Canvas c, IScatterDataSet dataSet, ViewPortHandler viewPortHandler, + float posX, float posY, Paint renderPaint) { - final float shapeHalf = shapeSize / 2f; + final float shapeHalf = dataSet.getScatterShapeSize() / 2f; renderPaint.setStyle(Paint.Style.STROKE); renderPaint.setStrokeWidth(Utils.convertDpToPixel(1f)); - for (int i = 0; i < buffer.size(); i += 2) { - - if (!viewPortHandler.isInBoundsRight(buffer.buffer[i])) - break; - - if (!viewPortHandler.isInBoundsLeft(buffer.buffer[i]) - || !viewPortHandler.isInBoundsY(buffer.buffer[i + 1])) - continue; - - renderPaint.setColor(dataSet.getColor(i / 2)); - - c.drawLine( - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - renderPaint); - c.drawLine( - buffer.buffer[i] + shapeHalf, - buffer.buffer[i + 1] - shapeHalf, - buffer.buffer[i] - shapeHalf, - buffer.buffer[i + 1] + shapeHalf, - renderPaint); - } + c.drawLine( + posX - shapeHalf, + posY - shapeHalf, + posX + shapeHalf, + posY + shapeHalf, + renderPaint); + c.drawLine( + posX + shapeHalf, + posY - shapeHalf, + posX - shapeHalf, + posY + shapeHalf, + renderPaint); } From 339fa16324fa59e092eeaa78bebd5218eeaa036b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 22:19:25 +0300 Subject: [PATCH 1121/1390] Added back missing `new CombinedChartRenderer` --- .../mikephil/charting/charts/CombinedChart.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index ba0cfcb0ae..65ce85ceb8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -40,9 +40,7 @@ public class CombinedChart extends BarLineChartBase implements Com */ private boolean mDrawBarShadow = false; - protected DrawOrder[] mDrawOrder = new DrawOrder[]{ - DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER - }; + protected DrawOrder[] mDrawOrder; /** * enum that allows to specify the order in which the different data objects @@ -68,10 +66,17 @@ public CombinedChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + // Default values are not ready here yet + mDrawOrder = new DrawOrder[]{ + DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER + }; + setHighlighter(new CombinedHighlighter(this, this)); // Old default behaviour setHighlightFullBarEnabled(true); + + mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); } @Override From 4d9dc0aa06a1684e26a6e76b72b838dcf7f5e4e5 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 8 Aug 2016 23:32:11 +0300 Subject: [PATCH 1122/1390] Safeguard for cubic bezier drawing --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index e29686bf63..75516be93e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -206,6 +206,8 @@ protected void drawCubicBezier(ILineDataSet dataSet) { Entry cur = prev; Entry next = dataSet.getEntryForIndex(mXBounds.min + 1); + if (cur == null || next == null) return; + // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); From 713f467ba839b9811b631c67db6c8c4bf65e3c71 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 11:16:58 +0300 Subject: [PATCH 1123/1390] Renamed Highlighter -> IHighlighter --- .../java/com/github/mikephil/charting/charts/Chart.java | 6 +++--- .../mikephil/charting/highlight/ChartHighlighter.java | 3 ++- .../mikephil/charting/highlight/CombinedHighlighter.java | 3 ++- .../highlight/{Highlighter.java => IHighlighter.java} | 3 ++- .../mikephil/charting/highlight/PieRadarHighlighter.java | 3 ++- 5 files changed, 11 insertions(+), 7 deletions(-) rename MPChartLib/src/main/java/com/github/mikephil/charting/highlight/{Highlighter.java => IHighlighter.java} (90%) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 93d07572ae..e6ef4c6598 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -36,7 +36,7 @@ import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.highlight.Highlighter; +import com.github.mikephil.charting.highlight.IHighlighter; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; @@ -163,7 +163,7 @@ public abstract class Chart implements Highlighter { +public class ChartHighlighter implements IHighlighter +{ /** * instance of the data-provider diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index d2275187e9..f75b0e925d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -13,7 +13,8 @@ /** * Created by Philipp Jahoda on 12/09/15. */ -public class CombinedHighlighter extends ChartHighlighter implements Highlighter { +public class CombinedHighlighter extends ChartHighlighter implements IHighlighter +{ /** * bar highlighter for supporting stacked highlighting diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/IHighlighter.java similarity index 90% rename from MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/highlight/IHighlighter.java index cee50a9e57..d0ca0cfe57 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/IHighlighter.java @@ -3,7 +3,8 @@ /** * Created by philipp on 10/06/16. */ -public interface Highlighter { +public interface IHighlighter +{ /** * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java index 9c067de808..a19906d75c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/PieRadarHighlighter.java @@ -9,7 +9,8 @@ /** * Created by philipp on 12/06/16. */ -public abstract class PieRadarHighlighter implements Highlighter { +public abstract class PieRadarHighlighter implements IHighlighter +{ protected T mChart; From 8cf2a6c3d027356c1ef251452183936dbe508a41 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 11:33:09 +0300 Subject: [PATCH 1124/1390] Removed the extra offset that messed up legend location --- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index f621afcf35..e4b0b81ffc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -273,7 +273,7 @@ public void renderLegend(Canvas c) { List calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); List calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints(); - float posX = originPosX + xoffset; + float posX = originPosX; float posY = 0.f; switch (verticalAlignment) { @@ -372,7 +372,7 @@ public void renderLegend(Canvas c) { for (int i = 0; i < labels.length; i++) { Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP; - float posX = originPosX + xoffset; + float posX = originPosX; if (drawingForm) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) From e841b697be0de4179fb23a4ed7e0e05e580ced9a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 14:26:52 +0300 Subject: [PATCH 1125/1390] Reversed "array access optimization" A `for-each` loop allocates only one iterator for the whole loop, not for each iteration. So this "optimization" is not needed, and just introduces additional clutter. http://stackoverflow.com/questions/14640184/does-the-java-foreach-loop-create-a-new-object --- .../mikephil/charting/charts/Chart.java | 6 +- .../mikephil/charting/data/BarData.java | 5 +- .../mikephil/charting/data/BubbleData.java | 4 +- .../mikephil/charting/data/ChartData.java | 65 +++++-------------- .../mikephil/charting/data/ScatterData.java | 3 +- .../renderer/BubbleChartRenderer.java | 6 +- .../renderer/CandleStickChartRenderer.java | 6 +- .../charting/renderer/LineChartRenderer.java | 5 +- .../charting/renderer/PieChartRenderer.java | 7 +- .../charting/renderer/RadarChartRenderer.java | 6 +- .../renderer/ScatterChartRenderer.java | 5 +- 11 files changed, 30 insertions(+), 88 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index e6ef4c6598..12ce891a98 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -305,11 +305,7 @@ public void setData(T data) { // calculate how many digits are needed setupDefaultFormatter(data.getYMin(), data.getYMax()); - IDataSet set; - final List sets = mData.getDataSets(); - final int count = sets.size(); - for (int i = 0; i < count; i++) { - set = (IDataSet) sets.get(i); + for (IDataSet set : mData.getDataSets()) { if (set.needsFormatter() || set.getValueFormatter() == mDefaultFormatter) set.setValueFormatter(mDefaultFormatter); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 601364dbc4..20a27a5fec 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -74,10 +74,7 @@ public void groupBars(float fromX, float groupSpace, float barSpace) { float start = fromX; fromX += groupSpaceWidthHalf; - IBarDataSet set; - final int setCountJ = mDataSets.size(); - for(int j = 0 ; j < setCountJ ; j++){ - set = mDataSets.get(j); + for (IBarDataSet set : mDataSets) { fromX += barSpaceHalf; fromX += barWidthHalf; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java index bf1be94a86..8fb72f17c5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleData.java @@ -27,8 +27,8 @@ public BubbleData(List dataSets) { * @param width */ public void setHighlightCircleWidth(float width) { - for(int i = 0 ; i < mDataSets.size() ; i++){ - mDataSets.get(i).setHighlightCircleWidth(width); + for (IBubbleDataSet set : mDataSets) { + set.setHighlightCircleWidth(width); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 0d8c52bd37..8c63b3130a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -79,10 +79,9 @@ public ChartData(T... dataSets) { */ private List arrayToList(T[] array) { - List list = new ArrayList(); + List list = new ArrayList<>(); - for (int i = 0; i < array.length; i++) { - T set = array[i]; + for (T set : array) { list.add(set); } @@ -129,8 +128,7 @@ public void calcMinMax() { mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (T set : mDataSets) { calcMinMax(set); } @@ -147,9 +145,7 @@ public void calcMinMax() { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - for (int i = 0; i < mDataSets.size(); i++) { - - T dataSet = mDataSets.get(i); + for (IDataSet dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -168,9 +164,7 @@ public void calcMinMax() { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - for (int i = 0; i < mDataSets.size(); i++) { - - T dataSet = mDataSets.get(i); + for (IDataSet dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -619,9 +613,7 @@ public int getIndexOfDataSet(T dataSet) { * @return */ protected T getFirstLeft(List sets) { - - for (int i = 0; i < sets.size(); i++) { - T dataSet = sets.get(i); + for (T dataSet : sets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) return dataSet; } @@ -635,9 +627,7 @@ protected T getFirstLeft(List sets) { * @return */ public T getFirstRight(List sets) { - - for (int i = 0; i < sets.size(); i++) { - T dataSet = sets.get(i); + for (T dataSet : sets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) return dataSet; } @@ -653,9 +643,7 @@ public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setValueFormatter(f); } } @@ -668,9 +656,7 @@ public void setValueFormatter(ValueFormatter f) { * @param color */ public void setValueTextColor(int color) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setValueTextColor(color); } } @@ -682,9 +668,7 @@ public void setValueTextColor(int color) { * @param colors */ public void setValueTextColors(List colors) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setValueTextColors(colors); } } @@ -696,9 +680,7 @@ public void setValueTextColors(List colors) { * @param tf */ public void setValueTypeface(Typeface tf) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setValueTypeface(tf); } } @@ -710,9 +692,7 @@ public void setValueTypeface(Typeface tf) { * @param size */ public void setValueTextSize(float size) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setValueTextSize(size); } } @@ -724,9 +704,7 @@ public void setValueTextSize(float size) { * @param enabled */ public void setDrawValues(boolean enabled) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setDrawValues(enabled); } } @@ -737,9 +715,7 @@ public void setDrawValues(boolean enabled) { * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { set.setHighlightEnabled(enabled); } } @@ -751,9 +727,7 @@ public void setHighlightEnabled(boolean enabled) { * @return */ public boolean isHighlightEnabled() { - - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (IDataSet set : mDataSets) { if (!set.isHighlightEnabled()) return false; } @@ -780,8 +754,7 @@ public void clearValues() { */ public boolean contains(T dataSet) { - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (T set : mDataSets) { if (set.equals(dataSet)) return true; } @@ -798,8 +771,7 @@ public int getEntryCount() { int count = 0; - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (T set : mDataSets) { count += set.getEntryCount(); } @@ -818,8 +790,7 @@ public T getMaxEntryCountSet() { T max = mDataSets.get(0); - for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + for (T set : mDataSets) { if (set.getEntryCount() > max.getEntryCount()) max = set; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java index 930eb04198..ba142360f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterData.java @@ -28,8 +28,7 @@ public float getGreatestShapeSize() { float max = 0f; - for (int i = 0; i < mDataSets.size(); i++) { - IScatterDataSet set = mDataSets.get(i); + for (IScatterDataSet set : mDataSets) { float size = set.getScatterShapeSize(); if (size > max) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 2a0bfcbb76..f21f03d3e3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -46,11 +46,7 @@ public void drawData(Canvas c) { BubbleData bubbleData = mChart.getBubbleData(); - IBubbleDataSet set; - List dataSets = bubbleData.getDataSets(); - int setCount = dataSets.size(); - for (int i = 0; i < setCount; i++) { - set = dataSets.get(i); + for (IBubbleDataSet set : bubbleData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index ffc7479c8b..8809c0f44b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -44,11 +44,7 @@ public void drawData(Canvas c) { CandleData candleData = mChart.getCandleData(); - ICandleDataSet set; - List dataSets = candleData.getDataSets(); - int setCount = dataSets.size(); - for (int i = 0; i < setCount; i++) { - set = dataSets.get(i); + for (ICandleDataSet set : candleData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 75516be93e..bf55c32cf0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -89,10 +89,7 @@ public void drawData(Canvas c) { LineData lineData = mChart.getLineData(); - ILineDataSet set; - int setCount = lineData.getDataSets().size(); - for (int i = 0; i < setCount; i++) { - set = lineData.getDataSets().get(i); + for (ILineDataSet set : lineData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index d479737c04..a489a18c32 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -142,11 +142,8 @@ public void drawData(Canvas c) { PieData pieData = mChart.getData(); - IPieDataSet set; - int setCount = pieData.getDataSets().size(); - List dataSet = pieData.getDataSets(); - for(int i = 0 ; i < setCount ; i++){ - set = dataSet.get(i); + for (IPieDataSet set : pieData.getDataSets()) { + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 4d0a8d9b0f..dd0918d559 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -63,11 +63,7 @@ public void drawData(Canvas c) { int mostEntries = radarData.getMaxEntryCountSet().getEntryCount(); - IRadarDataSet set; - List dataSets = radarData.getDataSets(); - int setCount = dataSets.size(); - for(int i = 0 ; i < setCount ; i++){ - set = dataSets.get(i); + for (IRadarDataSet set : radarData.getDataSets()) { if (set.isVisible()) { drawDataSet(c, set, mostEntries); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index faf2395626..91dc40fc38 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -36,10 +36,7 @@ public void drawData(Canvas c) { ScatterData scatterData = mChart.getScatterData(); - IScatterDataSet set; - int setCount = scatterData.getDataSets().size(); - for(int i = 0 ; i < setCount ; i++){ - set = scatterData.getDataSets().get(i); + for (IScatterDataSet set : scatterData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); From 02bf21df50f2d31f3f9c7276b24aba9a3dae163e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 15:33:26 +0300 Subject: [PATCH 1126/1390] Reverse string formatter caches These *will* cause trouble. We know of users who format the strings based on the entry's location, view port scroll/scale, etc. The cache will repeat irrelevant values, and gain no benefit for us. --- .../BarChartPositiveNegative.java | 7 +- .../mpchartexample/LineChartTime.java | 6 +- .../StackedBarActivityNegative.java | 16 +- .../custom/MyAxisValueFormatter.java | 6 +- .../custom/MyCustomXAxisValueFormatter.java | 7 +- .../custom/MyValueFormatter.java | 7 +- .../custom/RadarMarkerView.java | 6 +- .../formatter/DefaultAxisValueFormatter.java | 12 +- .../formatter/DefaultValueFormatter.java | 13 +- .../formatter/FormattedStringCache.java | 194 -------- .../formatter/LargeValueFormatter.java | 12 +- .../charting/formatter/PercentFormatter.java | 14 +- .../formatter/StackedValueFormatter.java | 22 +- .../test/FormattedStringCacheTest.java | 433 ------------------ 14 files changed, 48 insertions(+), 707 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java delete mode 100644 MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index efe51d2ffd..1c22ae41c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -16,7 +16,6 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -165,15 +164,15 @@ public Data(float xValue, float yValue, String xAxisValue) { private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter { - private FormattedStringCache.PrimIntFloat mFormattedStringCache; + private DecimalFormat mFormat; public ValueFormatter() { - mFormattedStringCache = new FormattedStringCache.PrimIntFloat(new DecimalFormat("######.0")); + mFormat = new DecimalFormat("######.0"); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedValue(value, dataSetIndex); + return mFormat.format(value); } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 77f9ecb834..7d833625aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -92,12 +91,11 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(60000L); // one minute in millis xAxis.setValueFormatter(new AxisValueFormatter() { - private FormattedStringCache.Generic mFormattedStringCache = new FormattedStringCache.Generic<>(new SimpleDateFormat("dd MMM HH:mm")); + private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); @Override public String getFormattedValue(float value, AxisBase axis) { - Long v = (long) value; - return mFormattedStringCache.getFormattedValue(new Date(v), v); + return mFormat.format(new Date((long) value)); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 4f0e16f5fa..200c012771 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -20,7 +20,6 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.formatter.AxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; @@ -80,11 +79,11 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(10f); xAxis.setValueFormatter(new AxisValueFormatter() { - private FormattedStringCache.PrimFloat format = new FormattedStringCache.PrimFloat(new DecimalFormat("###")); + private DecimalFormat format = new DecimalFormat("###"); @Override public String getFormattedValue(float value, AxisBase axis) { - return format.getFormattedValue(value) + "-" + format.getFormattedValue(value+10); + return format.format(value) + "-" + format.format(value + 10); } @Override @@ -223,25 +222,22 @@ public void onNothingSelected() { private class CustomFormatter implements ValueFormatter, AxisValueFormatter { - private FormattedStringCache.Generic mFormatValue; - private FormattedStringCache.PrimFloat mFormatAxis; + private DecimalFormat mFormat; public CustomFormatter() { - mFormatValue = new FormattedStringCache.Generic<>(new DecimalFormat("###")); - mFormatAxis = new FormattedStringCache.PrimFloat(new DecimalFormat("###")); + mFormat = new DecimalFormat("###"); } // data @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormatValue.getFormattedValue(value, dataSetIndex) + "m"; + return mFormat.format(Math.abs(value)) + "m"; } // YAxis @Override public String getFormattedValue(float value, AxisBase axis) { - Float v = Math.abs(value); - return mFormatAxis.getFormattedValue(v) + "m"; + return mFormat.format(Math.abs(value)) + "m"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index 2eeff56971..ea50fd8fad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -2,22 +2,20 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.formatter.FormattedStringCache; import java.text.DecimalFormat; public class MyAxisValueFormatter implements AxisValueFormatter { private DecimalFormat mFormat; - private FormattedStringCache.PrimFloat mFormattedStringCache; public MyAxisValueFormatter() { - mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0.0")); + mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormattedStringCache.getFormattedValue(value) + " $"; + return mFormat.format(value) + " $"; } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 9b5f4c921c..7d698ef0e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -2,7 +2,6 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -12,13 +11,13 @@ */ public class MyCustomXAxisValueFormatter implements AxisValueFormatter { - private FormattedStringCache.PrimFloat mFormattedStringCache; + private DecimalFormat mFormat; private ViewPortHandler mViewPortHandler; public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { mViewPortHandler = viewPortHandler; // maybe do something here or provide parameters in constructor - mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0.0")); + mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override @@ -35,7 +34,7 @@ else if (xScale > 3) else if (xScale > 1) return "2"; else - return mFormattedStringCache.getFormattedValue(value); + return mFormat.format(value); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index 5ca05d92de..a374b60e7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -9,14 +8,14 @@ public class MyValueFormatter implements ValueFormatter { - private FormattedStringCache.Generic mFormattedStringCache; + private DecimalFormat mFormat; public MyValueFormatter() { - mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0.0")); + mFormat = new DecimalFormat("###,###,###,##0.0"); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedValue(value, dataSetIndex) + " $"; + return mFormat.format(value) + " $"; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index b5aa1960d1..1a350f45ac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -8,7 +8,6 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.FormattedStringCache; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; @@ -24,7 +23,7 @@ public class RadarMarkerView extends MarkerView { private TextView tvContent; - private FormattedStringCache.PrimFloat mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("##0")); + private DecimalFormat format = new DecimalFormat("##0"); public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); @@ -37,8 +36,7 @@ public RadarMarkerView(Context context, int layoutResource) { // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - float value = e.getY(); - tvContent.setText(mFormattedStringCache.getFormattedValue(value) + " %"); + tvContent.setText(format.format(e.getY()) + " %"); super.refreshContent(e, highlight); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index f55fc8175e..ad3bb783ee 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -10,9 +10,9 @@ public class DefaultAxisValueFormatter implements AxisValueFormatter { /** - * FormattedStringFormat for formatting and caching + * decimalformat for formatting */ - protected FormattedStringCache.PrimFloat mFormattedStringCache; + protected DecimalFormat mFormat; /** * the number of decimal digits this formatter uses @@ -35,15 +35,13 @@ public DefaultAxisValueFormatter(int digits) { b.append("0"); } - mFormattedStringCache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0" + b.toString())); + mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } @Override public String getFormattedValue(float value, AxisBase axis) { - - // TODO: There should be a better way to do this. Floats are not the best keys... - return mFormattedStringCache.getFormattedValue(value); - + // avoid memory allocations here (for performance) + return mFormat.format(value); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 8d169b1405..5d23d25f7e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -15,9 +15,9 @@ public class DefaultValueFormatter implements ValueFormatter { /** - * FormattedStringCache for formatting and caching. + * DecimalFormat for formatting */ - protected FormattedStringCache.Generic mFormattedStringCache; + protected DecimalFormat mFormat; protected int mDecimalDigits; @@ -47,13 +47,16 @@ public void setup(int digits) { b.append("0"); } - mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); - + mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedValue(value, dataSetIndex); + + // put more logic here ... + // avoid memory allocations here (for performance reasons) + + return mFormat.format(value); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java deleted file mode 100644 index c6b4ef3e6f..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FormattedStringCache.java +++ /dev/null @@ -1,194 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import java.text.Format; -import java.util.ArrayList; -import java.util.HashMap; - -/** - * Created by Tony Patino on 6/29/16. - * - * COST : Frequently the V type, and the K type will often be passed as primitives (float / int / double) - * This will incur an auto-boxing penalty, and an instantiation on each call. - * - * BENEFIT : Formatting of Strings is one of the costliest operations remaining, and it is larger than the boxing penalty. - * Eliminating redundant formats helps more than boxing hurts. - * - * Possibly want to make some explicit primitive enabled caches, though they can be ugly. - * - */ -public class FormattedStringCache { - - protected Format mFormat; - - public Format getFormat(){ - return mFormat; - } - - public FormattedStringCache(Format format){ - this.mFormat = format; - } - - - /** - * Cache a Formatted String, derived from formatting value V in the Format passed to the constructor. - * Use the object K as a way to quickly look up the string in the cache. - * If value of V has changed since the last time the cache was accessed, re-format the string. - * - * NOTE: This version relies on auto-boxing of primitive values. As a result, it has worse memory performance - * than the Prim versions. - * - * @param - * @param - */ - public static class Generic extends FormattedStringCache{ - - private HashMap mCachedStringsHashMap = new HashMap<>(); - private HashMap mCachedValuesHashMap = new HashMap<>(); - - public Generic(Format format){ - super(format); - } - - public String getFormattedValue(V value, K key){ - - // If we can't find the value at all, create an entry for it, and format the string. - if(!mCachedValuesHashMap.containsKey(key)){ - mCachedStringsHashMap.put(key, mFormat.format(value)); - mCachedValuesHashMap.put(key, value); - } - - // If the old value and the new one don't match, format the string and store it, because the string's value will be different now. - if(!value.equals(mCachedValuesHashMap.get(key))){ - mCachedStringsHashMap.put(key, mFormat.format(value)); - mCachedValuesHashMap.put(key, value); - } - - String result = mCachedStringsHashMap.get(key); - - return result; - } - } - - /** - * Cache a Formatted String, derived from formatting float value in the Format passed to the constructor. - * Use the integer as a way to quickly look up the string in the cache. - * If value of V has changed since the last time the cache was accessed, re-format the string. - * - */ - public static class PrimIntFloat extends FormattedStringCache{ - - public PrimIntFloat(Format format){ - super(format); - } - - private ArrayList cachedValues = new ArrayList<>(); - private ArrayList cachedStrings = new ArrayList<>(); - - public String getFormattedValue(float value, int key) { - - boolean hasValueAtdataSetIndex = true; - if(cachedValues.size() <= key){ - int p = key; - while(p >= 0){ - if(p == 0){ - cachedValues.add(value); - cachedStrings.add(""); - }else{ - cachedValues.add(Float.NaN); - cachedStrings.add(""); - } - p--; - } - hasValueAtdataSetIndex = false; - } - - if(hasValueAtdataSetIndex) { - Float cachedValue = cachedValues.get(key); - hasValueAtdataSetIndex = !(cachedValue == null || cachedValue != value); - } - - if(!hasValueAtdataSetIndex){ - cachedValues.set(key, value); - cachedStrings.set(key, mFormat.format(value)); - } - - return cachedStrings.get(key); - } - - } - - /** - * Cache a Formatted String, derived from formatting float value in the Format passed to the constructor. - */ - public static class PrimFloat extends FormattedStringCache{ - - public PrimFloat(Format format){ - super(format); - } - - - private ArrayList cachedValues = new ArrayList<>(); - private ArrayList cachedStrings = new ArrayList<>(); - - public String getFormattedValue(float value) { - - boolean alreadyHasValue = false; - int vCount = cachedValues.size(); - int sIndex = -1; - for(int i = 0 ; i < vCount ; i++){ - if(cachedValues.get(i) == value){ - sIndex = i; - alreadyHasValue = true; - break; - } - } - if(!alreadyHasValue) { - cachedValues.add(value); - cachedStrings.add(mFormat.format(value)); - sIndex = cachedValues.size() - 1; - } - - return cachedStrings.get(sIndex); - } - - } - - /** - * Cache a Formatted String, derived from formatting double value in the Format passed to the constructor. - */ - public static class PrimDouble extends FormattedStringCache{ - - public PrimDouble(Format format){ - super(format); - } - - - private ArrayList cachedValues = new ArrayList<>(); - private ArrayList cachedStrings = new ArrayList<>(); - - public String getFormattedValue(double value) { - - boolean alreadyHasValue = false; - int vCount = cachedValues.size(); - int sIndex = -1; - for(int i = 0 ; i < vCount ; i++){ - if(cachedValues.get(i) == value){ - sIndex = i; - alreadyHasValue = true; - break; - } - } - if(!alreadyHasValue) { - cachedValues.add(value); - cachedStrings.add(mFormat.format(value)); - sIndex = cachedValues.size() - 1; - } - - return cachedStrings.get(sIndex); - } - - } - - - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 4e6e77a6bf..ef8dc4077a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -23,16 +23,11 @@ public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { "", "k", "m", "b", "t" }; private static final int MAX_LENGTH = 5; + private DecimalFormat mFormat; private String mText = ""; - - /** - * FormattedStringCache for formatting and caching. - */ - protected FormattedStringCache.PrimDouble mFormattedStringCache; - public LargeValueFormatter() { - mFormattedStringCache = new FormattedStringCache.PrimDouble(new DecimalFormat("###E00")); + mFormat = new DecimalFormat("###E00"); } /** @@ -82,8 +77,7 @@ public void setSuffix(String[] suff) { */ private String makePretty(double number) { - // TODO : Should be better way to do this. Double isn't the best key... - String r = mFormattedStringCache.getFormattedValue(number); + String r = mFormat.format(number); int numericValue1 = Character.getNumericValue(r.charAt(r.length() - 1)); int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 1ad1ba1c0d..209da1fa83 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -15,12 +15,10 @@ */ public class PercentFormatter implements ValueFormatter, AxisValueFormatter { - protected FormattedStringCache.Generic mFormattedStringCache; - protected FormattedStringCache.PrimFloat mFormattedStringCacheAxis; + protected DecimalFormat mFormat; public PercentFormatter() { - mFormattedStringCache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,##0.0")); - mFormattedStringCacheAxis = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,##0.0")); + mFormat = new DecimalFormat("###,###,##0.0"); } /** @@ -29,21 +27,19 @@ public PercentFormatter() { * @param format */ public PercentFormatter(DecimalFormat format) { - mFormattedStringCache = new FormattedStringCache.Generic<>(format); - mFormattedStringCacheAxis = new FormattedStringCache.PrimFloat(format); + this.mFormat = format; } // ValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedValue(value, dataSetIndex) + " %"; + return mFormat.format(value) + " %"; } // AxisValueFormatter @Override public String getFormattedValue(float value, AxisBase axis) { - // TODO: Find a better way to do this. Float isn't the best key... - return mFormattedStringCacheAxis.getFormattedValue(value) + " %"; + return mFormat.format(value) + " %"; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index bc020d5637..b13dd8d907 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -18,8 +18,6 @@ public class StackedValueFormatter implements ValueFormatter { * if true, all stack values of the stacked bar entry are drawn, else only top */ private boolean mDrawWholeStack; - private FormattedStringCache.Generic mFormattedStringCacheWholeStack; - private FormattedStringCache.Generic mFormattedStringCache; /** * a string that should be appended behind the value @@ -46,17 +44,12 @@ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decima b.append("0"); } - this.mFormattedStringCache = new FormattedStringCache.Generic(new DecimalFormat("###,###,###,##0" + b.toString())); - this.mFormattedStringCacheWholeStack = new FormattedStringCache.Generic(new DecimalFormat("###,###,###,##0" + b.toString())); + this.mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); } @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - FormattedStringCache.Generic chosenCache = mFormattedStringCache; - int chosenIndex = dataSetIndex; - float chosenValue = value; - if (!mDrawWholeStack && entry instanceof BarEntry) { BarEntry barEntry = (BarEntry) entry; @@ -66,19 +59,16 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View // find out if we are on top of the stack if (vals[vals.length - 1] == value) { - chosenCache = mFormattedStringCacheWholeStack; - chosenValue = barEntry.getY(); + + // return the "sum" across all stack values + return mFormat.format(barEntry.getY()) + mAppendix; } else { - chosenCache = null; + return ""; // return empty } } } - if(chosenCache == null){ - return ""; - } - // return the "proposed" value - return chosenCache.getFormattedValue(chosenValue, chosenIndex) + mAppendix; + return mFormat.format(value) + mAppendix; } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java deleted file mode 100644 index bd33008ea6..0000000000 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/FormattedStringCacheTest.java +++ /dev/null @@ -1,433 +0,0 @@ -package com.github.mikephil.charting.test; - -import com.github.mikephil.charting.formatter.FormattedStringCache; - -import junit.framework.Assert; - -import org.junit.Test; - -import java.text.DecimalFormat; - -/** - * Created by Tony Patino on 6/30/16. - */ -public class FormattedStringCacheTest { - - @Test - public void testPrimFloat(){ - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.PrimFloat cache = new FormattedStringCache.PrimFloat(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - s = cache.getFormattedValue(1.0f); - - Assert.assertEquals("1.00", s); - - s = cache.getFormattedValue(1.0f); - - Assert.assertEquals("1.00", s); - - - s = cache.getFormattedValue(1.3f); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.0f); - - Assert.assertEquals("1.00", s); - - for(int i = 0 ; i < 100 ; i++){ - float f = 0.75f + i; - s = cache.getFormattedValue(f); - Assert.assertEquals(i+".75", s); - } - - - s = cache.getFormattedValue(1.5323234f); - Assert.assertEquals("1.53", s); - - - s = cache.getFormattedValue(1.31f); - Assert.assertEquals("1.31", s); - - s = cache.getFormattedValue(1.3111111f); - Assert.assertEquals("1.31", s); - - } - - @Test - public void testPrimDouble(){ - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.PrimDouble cache = new FormattedStringCache.PrimDouble(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - s = cache.getFormattedValue(1.0d); - - Assert.assertEquals("1.00", s); - - s = cache.getFormattedValue(1.0d); - - Assert.assertEquals("1.00", s); - - - s = cache.getFormattedValue(1.3d); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3d); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.0d); - - Assert.assertEquals("1.00", s); - - for(int i = 0 ; i < 100 ; i++){ - double f = 0.75f + i; - s = cache.getFormattedValue(f); - Assert.assertEquals(i+".75", s); - } - - - s = cache.getFormattedValue(1.5323234d); - Assert.assertEquals("1.53", s); - - - s = cache.getFormattedValue(1.31d); - Assert.assertEquals("1.31", s); - - s = cache.getFormattedValue(1.3111111d); - Assert.assertEquals("1.31", s); - - } - - @Test - public void testPrimIntFloat(){ - - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.PrimIntFloat cache = new FormattedStringCache.PrimIntFloat(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - s = cache.getFormattedValue(1.0f, 0); - - Assert.assertEquals("1.00", s); - - s = cache.getFormattedValue(1.0f, 0); - - Assert.assertEquals("1.00", s); - - - s = cache.getFormattedValue(1.3f ,1); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 1); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 0); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.0f, 1); - - Assert.assertEquals("1.00", s); - - for(int i = 0 ; i < 100 ; i++){ - float f = 0.75f + i; - s = cache.getFormattedValue(f, i); - Assert.assertEquals(i+".75", s); - } - - - s = cache.getFormattedValue(1.5323234f, 200); - Assert.assertEquals("1.53", s); - - - s = cache.getFormattedValue(1.31f, 300); - Assert.assertEquals("1.31", s); - - s = cache.getFormattedValue(1.3111111f, 300); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 400); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 500); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 5000); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 0); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 1); - Assert.assertEquals("1.31", s); - } - - @Test - public void testGenericKV(){ - - this.genericIntFloat(); - this.genericDoubleFloat(); - this.genericObjectFloat(); - } - - private void genericObjectFloat() { - - - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - - Object obj0 = new Object(); - Object obj1 = new Object(); - Object obj2 = new Object(); - - s = cache.getFormattedValue(10f, obj0); - - Assert.assertEquals("10.00", s); - - - s = cache.getFormattedValue(10f, obj0); - - Assert.assertEquals("10.00", s); - - - s = cache.getFormattedValue(11f, obj1); - - Assert.assertEquals("11.00", s); - - s = cache.getFormattedValue(10f, obj2); - - Assert.assertEquals("10.00", s); - - - s = cache.getFormattedValue(11f, obj0); - - Assert.assertEquals("11.00", s); - - - } - - private void genericDoubleFloat() { - - - - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - s = cache.getFormattedValue(1.0f, 0d); - - Assert.assertEquals("1.00", s); - - s = cache.getFormattedValue(1.0f, 0d); - - Assert.assertEquals("1.00", s); - - - s = cache.getFormattedValue(1.3f ,1d); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 1d); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 0d); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.0f, 1d); - - Assert.assertEquals("1.00", s); - - for(int i = 0 ; i < 100 ; i++){ - float f = 0.75f + i; - s = cache.getFormattedValue(f, (double)i); - Assert.assertEquals(i+".75", s); - } - - - s = cache.getFormattedValue(1.5323234f, 200d); - Assert.assertEquals("1.53", s); - - - s = cache.getFormattedValue(1.31f, 300d); - Assert.assertEquals("1.31", s); - - s = cache.getFormattedValue(1.3111111f, 300d); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 400d); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 500d); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 5000d); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 0d); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 1d); - Assert.assertEquals("1.31", s); - - } - - private void genericIntFloat() { - - - int digits = 2; - - StringBuffer b = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - b.append("."); - b.append("0"); - } - - FormattedStringCache.Generic cache = new FormattedStringCache.Generic<>(new DecimalFormat("###,###,###,##0" + b.toString())); - - String s = null; - - s = cache.getFormattedValue(1.0f, 0); - - Assert.assertEquals("1.00", s); - - s = cache.getFormattedValue(1.0f, 0); - - Assert.assertEquals("1.00", s); - - - s = cache.getFormattedValue(1.3f ,1); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 1); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.3f, 0); - - Assert.assertEquals("1.30", s); - - - s = cache.getFormattedValue(1.0f, 1); - - Assert.assertEquals("1.00", s); - - for(int i = 0 ; i < 100 ; i++){ - float f = 0.75f + i; - s = cache.getFormattedValue(f, i); - Assert.assertEquals(i+".75", s); - } - - - s = cache.getFormattedValue(1.5323234f, 200); - Assert.assertEquals("1.53", s); - - - s = cache.getFormattedValue(1.31f, 300); - Assert.assertEquals("1.31", s); - - s = cache.getFormattedValue(1.3111111f, 300); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 400); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 500); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.3111111f, 5000); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 0); - Assert.assertEquals("1.31", s); - - - s = cache.getFormattedValue(1.31f, 1); - Assert.assertEquals("1.31", s); - } - -} From 18eec8f0e6bf2571732ad319e9beb0a7ddcfc6c7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 15:44:03 +0300 Subject: [PATCH 1127/1390] If we are at it - rename those interfaces too FillFormatter -> IFillFormatter ValueFormatter -> IValueFormatter AxisValueFormatter -> IAxisValueFormatter --- .../mpchartexample/BarChartActivity.java | 8 +++----- .../mpchartexample/BarChartActivityMultiDataset.java | 4 ++-- .../mpchartexample/BarChartPositiveNegative.java | 8 +++++--- .../mpchartexample/CombinedChartActivity.java | 6 ++---- .../mpchartexample/CubicLineChartActivity.java | 4 ++-- .../mpchartexample/FilledLineActivity.java | 6 +++--- .../xxmassdeveloper/mpchartexample/LineChartTime.java | 4 ++-- .../mpchartexample/RadarChartActivitry.java | 5 ++--- .../mpchartexample/StackedBarActivityNegative.java | 9 +++++---- .../mpchartexample/custom/DayAxisValueFormatter.java | 7 +++---- .../mpchartexample/custom/MyAxisValueFormatter.java | 5 +++-- .../custom/MyCustomXAxisValueFormatter.java | 5 +++-- .../mpchartexample/custom/MyFillFormatter.java | 5 +++-- .../mpchartexample/custom/MyValueFormatter.java | 5 +++-- .../mpchartexample/custom/XYMarkerView.java | 8 +++----- .../mpchartexample/custom/YearXAxisFormatter.java | 5 +++-- .../com/github/mikephil/charting/charts/Chart.java | 7 +++---- .../com/github/mikephil/charting/charts/PieChart.java | 2 +- .../github/mikephil/charting/components/AxisBase.java | 8 ++++---- .../com/github/mikephil/charting/data/BaseDataSet.java | 8 ++++---- .../com/github/mikephil/charting/data/ChartData.java | 6 +++--- .../com/github/mikephil/charting/data/LineDataSet.java | 10 +++++----- .../charting/formatter/DefaultAxisValueFormatter.java | 3 ++- .../charting/formatter/DefaultFillFormatter.java | 3 ++- .../charting/formatter/DefaultValueFormatter.java | 3 ++- ...xisValueFormatter.java => IAxisValueFormatter.java} | 3 ++- .../{FillFormatter.java => IFillFormatter.java} | 3 ++- .../{ValueFormatter.java => IValueFormatter.java} | 5 +++-- .../charting/formatter/LargeValueFormatter.java | 7 ++++--- .../mikephil/charting/formatter/PercentFormatter.java | 9 +++++---- .../charting/formatter/StackedValueFormatter.java | 3 ++- .../interfaces/dataprovider/ChartInterface.java | 6 ++---- .../charting/interfaces/datasets/IDataSet.java | 6 +++--- .../charting/interfaces/datasets/ILineDataSet.java | 7 +++---- .../mikephil/charting/renderer/DataRenderer.java | 6 +++--- .../charting/renderer/HorizontalBarChartRenderer.java | 4 ++-- .../mikephil/charting/renderer/PieChartRenderer.java | 5 ++--- 37 files changed, 106 insertions(+), 102 deletions(-) rename MPChartLib/src/main/java/com/github/mikephil/charting/formatter/{AxisValueFormatter.java => IAxisValueFormatter.java} (95%) rename MPChartLib/src/main/java/com/github/mikephil/charting/formatter/{FillFormatter.java => IFillFormatter.java} (95%) rename MPChartLib/src/main/java/com/github/mikephil/charting/formatter/{ValueFormatter.java => IValueFormatter.java} (90%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 36dbd042b6..7718cd12ea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -2,8 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.annotation.SuppressLint; -import android.graphics.PointF; -import android.graphics.Rect; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; @@ -28,7 +26,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -80,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); - AxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart); + IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart); XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); @@ -90,7 +88,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setLabelCount(7); xAxis.setValueFormatter(xAxisFormatter); - AxisValueFormatter custom = new MyAxisValueFormatter(); + IAxisValueFormatter custom = new MyAxisValueFormatter(); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTfLight); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index f27de86b53..fe63f075d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -21,7 +21,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; @@ -87,7 +87,7 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(mTfLight); xl.setGranularity(1f); xl.setCenterAxisLabels(true); - xl.setValueFormatter(new AxisValueFormatter() { + xl.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return String.valueOf((int) value); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 1c22ae41c6..424873e72a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -15,7 +15,8 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -86,7 +87,7 @@ protected void onCreate(Bundle savedInstanceState) { data.add(new Data(3.5f, -442.3f, "01-01")); data.add(new Data(4.5f, -2280.1f, "01-02")); - xAxis.setValueFormatter(new AxisValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; @@ -162,7 +163,8 @@ public Data(float xValue, float yValue, String xAxisValue) { } } - private class ValueFormatter implements com.github.mikephil.charting.formatter.ValueFormatter { + private class ValueFormatter implements IValueFormatter + { private DecimalFormat mFormat; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 519a15d219..599143e38b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Paint; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -30,13 +29,12 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; -import java.util.Arrays; public class CombinedChartActivity extends DemoBase { @@ -78,7 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinValue(0f); xAxis.setGranularity(1f); - xAxis.setValueFormatter(new AxisValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return mMonths[(int) value % mMonths.length]; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 2fc7d2b210..2752af37f9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -17,7 +17,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; @@ -294,7 +294,7 @@ private void setData(int count, float range) { set1.setFillColor(Color.WHITE); set1.setFillAlpha(100); set1.setDrawHorizontalHighlightIndicator(false); - set1.setFillFormatter(new FillFormatter() { + set1.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { return -10; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index ece33d8964..a9d7210d62 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -109,7 +109,7 @@ private void setData(int count, float range) { set1.setFillColor(Color.WHITE); set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setDrawCircleHole(false); - set1.setFillFormatter(new FillFormatter() { + set1.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { return mChart.getAxisLeft().getAxisMinimum(); @@ -128,7 +128,7 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv set2.setFillColor(Color.WHITE); set2.setDrawCircleHole(false); set2.setHighLightColor(Color.rgb(244, 117, 117)); - set2.setFillFormatter(new FillFormatter() { + set2.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { return mChart.getAxisLeft().getAxisMaximum(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 7d833625aa..afe8fa2ef0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -20,7 +20,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -89,7 +89,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.rgb(255, 192, 56)); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(60000L); // one minute in millis - xAxis.setValueFormatter(new AxisValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 3326442a87..fcc1b2f55c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -14,14 +14,13 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.components.MarkerImage; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; @@ -74,7 +73,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); - xAxis.setValueFormatter(new AxisValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 200c012771..1569f574ee 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -20,8 +20,8 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -77,7 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setLabelCount(12); xAxis.setGranularity(10f); - xAxis.setValueFormatter(new AxisValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private DecimalFormat format = new DecimalFormat("###"); @@ -220,7 +220,8 @@ public void onNothingSelected() { Log.i("NOTING SELECTED", ""); } - private class CustomFormatter implements ValueFormatter, AxisValueFormatter { + private class CustomFormatter implements IValueFormatter, IAxisValueFormatter + { private DecimalFormat mFormat; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index d989104e48..f6b2908f72 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -1,15 +1,14 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.AxisValueFormatter; -import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by philipp on 02/06/16. */ -public class DayAxisValueFormatter implements AxisValueFormatter { +public class DayAxisValueFormatter implements IAxisValueFormatter +{ protected String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index ea50fd8fad..137097b84e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -1,11 +1,12 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import java.text.DecimalFormat; -public class MyAxisValueFormatter implements AxisValueFormatter { +public class MyAxisValueFormatter implements IAxisValueFormatter +{ private DecimalFormat mFormat; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 7d698ef0e7..23f5785c11 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,7 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -9,7 +9,8 @@ /** * Created by Philipp Jahoda on 14/09/15. */ -public class MyCustomXAxisValueFormatter implements AxisValueFormatter { +public class MyCustomXAxisValueFormatter implements IAxisValueFormatter +{ private DecimalFormat mFormat; private ViewPortHandler mViewPortHandler; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index 1c4d450167..e4b94c331f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -1,13 +1,14 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; /** * Created by Philipp Jahoda on 12/09/15. */ -public class MyFillFormatter implements FillFormatter { +public class MyFillFormatter implements IFillFormatter +{ private float mFillPos = 0f; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index a374b60e7f..cbf5fd56c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,12 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; -public class MyValueFormatter implements ValueFormatter { +public class MyValueFormatter implements IValueFormatter +{ private DecimalFormat mFormat; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 7a7fe726d5..177527b3bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -5,12 +5,10 @@ import android.widget.TextView; import com.github.mikephil.charting.components.MarkerView; -import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; import java.text.DecimalFormat; @@ -23,11 +21,11 @@ public class XYMarkerView extends MarkerView { private TextView tvContent; - private AxisValueFormatter xAxisValueFormatter; + private IAxisValueFormatter xAxisValueFormatter; private DecimalFormat format; - public XYMarkerView(Context context, AxisValueFormatter xAxisValueFormatter) { + public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); this.xAxisValueFormatter = xAxisValueFormatter; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index e9b31bb6c0..0b1245cd77 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -1,12 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ -public class YearXAxisFormatter implements AxisValueFormatter { +public class YearXAxisFormatter implements IAxisValueFormatter +{ protected String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 12ce891a98..c34a8a013b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -33,7 +33,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.IHighlighter; @@ -53,7 +53,6 @@ import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; -import java.util.List; /** * Baseclass of all Chart-Views. @@ -976,12 +975,12 @@ public XAxis getXAxis() { } /** - * Returns the default ValueFormatter that has been determined by the chart + * Returns the default IValueFormatter that has been determined by the chart * considering the provided minimum and maximum values. * * @return */ - public ValueFormatter getDefaultValueFormatter() { + public IValueFormatter getDefaultValueFormatter() { return mDefaultFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index d2acf19b2d..db327fa8b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -662,7 +662,7 @@ public boolean isDrawRoundedSlicesEnabled() { /** * If this is enabled, values inside the PieChart are drawn in percent and - * not with their original value. Values provided for the ValueFormatter to + * not with their original value. Values provided for the IValueFormatter to * format are then provided in percent. * * @param enabled diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 378a3eb49e..bc729f1148 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -5,7 +5,7 @@ import android.graphics.DashPathEffect; import android.util.Log; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -22,7 +22,7 @@ public abstract class AxisBase extends ComponentBase { /** * custom formatter that is used instead of the auto-formatter if set */ - protected AxisValueFormatter mAxisValueFormatter; + protected IAxisValueFormatter mAxisValueFormatter; private int mGridColor = Color.GRAY; @@ -460,7 +460,7 @@ public String getFormattedLabel(int index) { * * @param f */ - public void setValueFormatter(AxisValueFormatter f) { + public void setValueFormatter(IAxisValueFormatter f) { if (f == null) mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); @@ -473,7 +473,7 @@ public void setValueFormatter(AxisValueFormatter f) { * * @return */ - public AxisValueFormatter getValueFormatter() { + public IAxisValueFormatter getValueFormatter() { if (mAxisValueFormatter == null) { mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 55d7309c9a..662f831d9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -49,7 +49,7 @@ public abstract class BaseDataSet implements IDataSet { /** * custom formatter that is used instead of the auto-formatter if set */ - protected transient ValueFormatter mValueFormatter; + protected transient IValueFormatter mValueFormatter; /** * the typeface used for the value text @@ -257,7 +257,7 @@ public boolean isHighlightEnabled() { } @Override - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; @@ -266,7 +266,7 @@ public void setValueFormatter(ValueFormatter f) { } @Override - public ValueFormatter getValueFormatter() { + public IValueFormatter getValueFormatter() { if (needsFormatter()) return new DefaultValueFormatter(1); return mValueFormatter; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 8c63b3130a..23bd58759b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -5,7 +5,7 @@ import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -635,11 +635,11 @@ public T getFirstRight(List sets) { } /** - * Sets a custom ValueFormatter for all DataSets this data object contains. + * Sets a custom IValueFormatter for all DataSets this data object contains. * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 2f1af59d1d..e987707cef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -6,7 +6,7 @@ import android.graphics.DashPathEffect; import com.github.mikephil.charting.formatter.DefaultFillFormatter; -import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -54,7 +54,7 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** * formatter for customizing the position of the fill-line */ - private FillFormatter mFillFormatter = new DefaultFillFormatter(); + private IFillFormatter mFillFormatter = new DefaultFillFormatter(); /** * if true, drawing circles is enabled @@ -377,12 +377,12 @@ public boolean isDrawCircleHoleEnabled() { } /** - * Sets a custom FillFormatter to the chart that handles the position of the + * Sets a custom IFillFormatter to the chart that handles the position of the * filled-line for each DataSet. Set this to null to use the default logic. * * @param formatter */ - public void setFillFormatter(FillFormatter formatter) { + public void setFillFormatter(IFillFormatter formatter) { if (formatter == null) mFillFormatter = new DefaultFillFormatter(); @@ -391,7 +391,7 @@ public void setFillFormatter(FillFormatter formatter) { } @Override - public FillFormatter getFillFormatter() { + public IFillFormatter getFillFormatter() { return mFillFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index ad3bb783ee..f29c554059 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -7,7 +7,8 @@ /** * Created by philipp on 02/06/16. */ -public class DefaultAxisValueFormatter implements AxisValueFormatter { +public class DefaultAxisValueFormatter implements IAxisValueFormatter +{ /** * decimalformat for formatting diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index 54e9cca8b3..851faeb333 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -10,7 +10,8 @@ * * @author Philipp Jahoda */ -public class DefaultFillFormatter implements FillFormatter { +public class DefaultFillFormatter implements IFillFormatter +{ @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 5d23d25f7e..e2fea4b079 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -12,7 +12,8 @@ * * @author Philipp Jahoda */ -public class DefaultValueFormatter implements ValueFormatter { +public class DefaultValueFormatter implements IValueFormatter +{ /** * DecimalFormat for formatting diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java similarity index 95% rename from MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java index ec248cace6..5be1d28752 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/AxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java @@ -7,7 +7,8 @@ * Custom formatter interface that allows formatting of * axis labels before they are being drawn. */ -public interface AxisValueFormatter { +public interface IAxisValueFormatter +{ /** * Called when a value from an axis is to be formatted diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IFillFormatter.java similarity index 95% rename from MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IFillFormatter.java index 66895d77e7..e096cc6528 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IFillFormatter.java @@ -9,7 +9,8 @@ * * @author Philipp Jahoda */ -public interface FillFormatter { +public interface IFillFormatter +{ /** * Returns the vertical (y-axis) position where the filled-line of the diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java similarity index 90% rename from MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java rename to MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java index 1f056bf786..75d2363f26 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java @@ -6,12 +6,13 @@ /** * Interface that allows custom formatting of all values inside the chart before they are * being drawn to the screen. Simply create your own formatting class and let - * it implement ValueFormatter. Then override the getFormattedValue(...) method + * it implement IValueFormatter. Then override the getFormattedValue(...) method * and return whatever you want. * * @author Philipp Jahoda */ -public interface ValueFormatter { +public interface IValueFormatter +{ /** * Called when a value (from labels inside the chart) is formatted diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index ef8dc4077a..0b4e8306c1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -17,7 +17,8 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter implements ValueFormatter, AxisValueFormatter { +public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter +{ private static String[] SUFFIX = new String[]{ "", "k", "m", "b", "t" @@ -40,13 +41,13 @@ public LargeValueFormatter(String appendix) { mText = appendix; } - // ValueFormatter + // IValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return makePretty(value) + mText; } - // AxisValueFormatter + // IAxisValueFormatter @Override public String getFormattedValue(float value, AxisBase axis) { return makePretty(value) + mText; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 209da1fa83..d321b5f03e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -8,12 +8,13 @@ import java.text.DecimalFormat; /** - * This ValueFormatter is just for convenience and simply puts a "%" sign after + * This IValueFormatter is just for convenience and simply puts a "%" sign after * each value. (Recommeded for PieChart) * * @author Philipp Jahoda */ -public class PercentFormatter implements ValueFormatter, AxisValueFormatter { +public class PercentFormatter implements IValueFormatter, IAxisValueFormatter +{ protected DecimalFormat mFormat; @@ -30,13 +31,13 @@ public PercentFormatter(DecimalFormat format) { this.mFormat = format; } - // ValueFormatter + // IValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value) + " %"; } - // AxisValueFormatter + // IAxisValueFormatter @Override public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + " %"; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index b13dd8d907..0e8351634f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -12,7 +12,8 @@ * A formatter specifically for stacked BarChart that allows to specify whether the all stack values * or just the top value should be drawn. */ -public class StackedValueFormatter implements ValueFormatter { +public class StackedValueFormatter implements IValueFormatter +{ /** * if true, all stack values of the stacked bar entry are drawn, else only top diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index a4618554bb..219b46bd82 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -1,12 +1,10 @@ package com.github.mikephil.charting.interfaces.dataprovider; -import android.graphics.PointF; import android.graphics.RectF; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.Utils; /** * Interface that provides everything there is to know about the dimensions, @@ -63,7 +61,7 @@ public interface ChartInterface { RectF getContentRect(); - ValueFormatter getDefaultValueFormatter(); + IValueFormatter getDefaultValueFormatter(); ChartData getData(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index f36cee928e..f2f2eac203 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import java.util.List; @@ -294,14 +294,14 @@ public interface IDataSet { * * @param f */ - void setValueFormatter(ValueFormatter f); + void setValueFormatter(IValueFormatter f); /** * Returns the formatter used for drawing the values inside the chart. * * @return */ - ValueFormatter getValueFormatter(); + IValueFormatter getValueFormatter(); /** * Returns true if the valueFormatter object of this DataSet is null. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index bccf6984d5..3f534fe848 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -1,11 +1,10 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; -import android.graphics.drawable.Drawable; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.formatter.IFillFormatter; /** * Created by Philpp Jahoda on 21/10/15. @@ -96,9 +95,9 @@ public interface ILineDataSet extends ILineRadarDataSet { boolean isDashedLineEnabled(); /** - * Returns the FillFormatter that is set for this DataSet. + * Returns the IFillFormatter that is set for this DataSet. * * @return */ - FillFormatter getFillFormatter(); + IFillFormatter getFillFormatter(); } \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index 39afe9389a..905c6449cb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -134,7 +134,7 @@ protected void applyValueTextStyle(IDataSet set) { public abstract void drawValues(Canvas c); /** - * Draws the value of the given entry by using the provided ValueFormatter. + * Draws the value of the given entry by using the provided IValueFormatter. * * @param c canvas * @param formatter formatter for custom value-formatting @@ -145,7 +145,7 @@ protected void applyValueTextStyle(IDataSet set) { * @param y position * @param color */ - public void drawValue(Canvas c, ValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { + public void drawValue(Canvas c, IValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { mValuePaint.setColor(color); c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 1519364a95..00cce881f2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.buffer.HorizontalBarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; @@ -165,7 +165,7 @@ public void drawValues(Canvas c) { applyValueTextStyle(dataSet); final float halfTextHeight = Utils.calcTextHeight(mValuePaint, "10") / 2f; - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); // get the buffer BarBuffer buffer = mBarBuffers[i]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index a489a18c32..36d18e055f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -8,7 +8,6 @@ import android.graphics.Paint.Align; import android.graphics.Paint.Style; import android.graphics.Path; -import android.graphics.PointF; import android.graphics.RectF; import android.os.Build; import android.text.Layout; @@ -22,7 +21,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -433,7 +432,7 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); int entryCount = dataSet.getEntryCount(); From 2176873271fd6a54511acb80e84d38f681096006 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 16:02:07 +0300 Subject: [PATCH 1128/1390] Avoid creating a new formatter if null This can improve performance in certain cases, and has the advantage of controlling the "global" default formatter that is used for null cases. --- .../github/mikephil/charting/charts/Chart.java | 10 +++++----- .../mikephil/charting/data/BaseDataSet.java | 2 +- .../github/mikephil/charting/utils/Utils.java | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index c34a8a013b..9b409baa00 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -98,7 +98,7 @@ public abstract class Chart Date: Tue, 9 Aug 2016 16:17:19 +0300 Subject: [PATCH 1129/1390] Pie's x is deprecated - log it out, and avoid in calcMinMax --- .../github/mikephil/charting/data/PieDataSet.java | 13 +++++++++++++ .../com/github/mikephil/charting/data/PieEntry.java | 3 +++ 2 files changed, 16 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 4d8b33b964..316aab4773 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -45,6 +45,19 @@ public DataSet copy() { return copied; } + @Override + protected void calcMinMax(PieEntry e) { + + if (e == null) + return; + + if (e.getY() < mYMin) + mYMin = e.getY(); + + if (e.getY() > mYMax) + mYMax = e.getY(); + } + /** * Sets the space that is left out between the piechart-slices in dp. * Default: 0 --> no space, maximum 20f diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java index 6ab31f140c..f5c40804c1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; import android.annotation.SuppressLint; +import android.util.Log; /** * Created by Philipp Jahoda on 31/05/16. @@ -49,11 +50,13 @@ public void setLabel(String label) { @Override public void setX(float x) { super.setX(x); + Log.i("DEPRECATED", "Pie entries do not have x values"); } @Deprecated @Override public float getX() { + Log.i("DEPRECATED", "Pie entries do not have x values"); return super.getX(); } From 86d05e989ad0601e98ac31d0b1fa29eb81a582f9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 9 Aug 2016 20:46:04 +0300 Subject: [PATCH 1130/1390] Corrected formula for 29-feb :-) --- .../custom/DayAxisValueFormatter.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index f6b2908f72..6d58892398 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -70,12 +70,17 @@ public String getFormattedValue(float value, AxisBase axis) { private int getDaysForMonth(int month, int year) { + // month is 0-based + if (month == 1) { + int x400 = month % 400; + if (x400 < 0) + { + x400 = -x400; + } + boolean is29 = (month % 4) == 0 && x400 != 100 && x400 != 200 && x400 != 300; - if (year == 2016 || year == 2020) - return 29; - else - return 28; + return is29 ? 29 : 28; } if (month == 3 || month == 5 || month == 8 || month == 10) From 30cb069974a482a4f9a27d243079b286f99faabb Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Aug 2016 00:15:34 +0300 Subject: [PATCH 1131/1390] Brought back the Realm demos, were removed by mistake --- MPChartExample/AndroidManifest.xml | 10 + MPChartExample/build.gradle | 2 +- .../mpchartexample/custom/RealmDemoData.java | 180 ++++++++++++++++ .../mpchartexample/custom/RealmFloat.java | 27 +++ .../notimportant/MainActivity.java | 9 + .../realm/RealmBaseActivity.java | 203 ++++++++++++++++++ .../realm/RealmDatabaseActivityBar.java | 69 ++++++ .../realm/RealmDatabaseActivityBubble.java | 71 ++++++ .../realm/RealmDatabaseActivityCandle.java | 77 +++++++ .../RealmDatabaseActivityHorizontalBar.java | 74 +++++++ .../realm/RealmDatabaseActivityLine.java | 77 +++++++ .../realm/RealmDatabaseActivityPie.java | 83 +++++++ .../realm/RealmDatabaseActivityRadar.java | 78 +++++++ .../realm/RealmDatabaseActivityScatter.java | 73 +++++++ .../realm/RealmMainActivity.java | 131 +++++++++++ .../realm/RealmWikiExample.java | 137 ++++++++++++ .../mpchartexample/realm/Score.java | 51 +++++ build.gradle | 2 +- 18 files changed, 1352 insertions(+), 2 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 4131688a8d..ab730cd2bd 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -47,12 +47,22 @@ + + + + + + + + + + diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 752d3fd321..c0d4745dcc 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,5 +1,5 @@ apply plugin: 'com.android.application' -//apply plugin: 'realm-android' +apply plugin: 'realm-android' android { compileSdkVersion 23 diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java new file mode 100644 index 0000000000..7becc88c90 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -0,0 +1,180 @@ +package com.xxmassdeveloper.mpchartexample.custom; + + +import io.realm.RealmList; +import io.realm.RealmObject; + +/** + * Demo class that encapsulates data stored in realm.io database. + * This class represents data suitable for all chart-types. + */ +public class RealmDemoData extends RealmObject { + + private float yValue; + private float xValue; + + private float open, close, high, low; + + private float bubbleSize; + + private RealmList stackValues; + + private String someStringField; + + /** + * label for pie entries + */ + private String label; + + // ofc there could me more fields here... + + public RealmDemoData() { + + } + + public RealmDemoData(float yValue) { + this.yValue = yValue; + } + + public RealmDemoData(float xValue, float yValue) { + this.xValue = xValue; + this.yValue = yValue; + } + + /** + * Constructor for stacked bars. + * + * @param xValue + * @param stackValues + */ + public RealmDemoData(float xValue, float[] stackValues) { + this.xValue = xValue; + this.stackValues = new RealmList(); + + for (float val : stackValues) { + this.stackValues.add(new RealmFloat(val)); + } + } + + /** + * Constructor for candles. + * + * @param xValue + * @param high + * @param low + * @param open + * @param close + */ + public RealmDemoData(float xValue, float high, float low, float open, float close) { + this.yValue = (high + low) / 2f; + this.high = high; + this.low = low; + this.open = open; + this.close = close; + this.xValue = xValue; + } + + /** + * Constructor for bubbles. + * + * @param xValue + * @param yValue + * @param bubbleSize + */ + public RealmDemoData(float xValue, float yValue, float bubbleSize) { + this.xValue = xValue; + this.yValue = yValue; + this.bubbleSize = bubbleSize; + } + + /** + * Constructor for pie chart. + * + * @param yValue + * @param label + */ + public RealmDemoData(float yValue, String label) { + this.yValue = yValue; + this.label = label; + } + + public float getyValue() { + return yValue; + } + + public void setyValue(float yValue) { + this.yValue = yValue; + } + + public float getxValue() { + return xValue; + } + + public void setxValue(float xValue) { + this.xValue = xValue; + } + + public RealmList getStackValues() { + return stackValues; + } + + public void setStackValues(RealmList stackValues) { + this.stackValues = stackValues; + } + + public float getOpen() { + return open; + } + + public void setOpen(float open) { + this.open = open; + } + + public float getClose() { + return close; + } + + public void setClose(float close) { + this.close = close; + } + + public float getHigh() { + return high; + } + + public void setHigh(float high) { + this.high = high; + } + + public float getLow() { + return low; + } + + public void setLow(float low) { + this.low = low; + } + + public float getBubbleSize() { + return bubbleSize; + } + + public void setBubbleSize(float bubbleSize) { + this.bubbleSize = bubbleSize; + } + + public String getSomeStringField() { + return someStringField; + } + + public void setSomeStringField(String someStringField) { + this.someStringField = someStringField; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } +} \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java new file mode 100644 index 0000000000..15b027b3ff --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -0,0 +1,27 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import io.realm.RealmObject; + +/** + * Created by Philipp Jahoda on 09/11/15. + */ +public class RealmFloat extends RealmObject { + + private float floatValue; + + public RealmFloat() { + + } + + public RealmFloat(float floatValue) { + this.floatValue = floatValue; + } + + public float getFloatValue() { + return floatValue; + } + + public void setFloatValue(float value) { + this.floatValue = value; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 512f4baa14..617e43c021 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -46,6 +46,7 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; +import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; @@ -130,6 +131,10 @@ protected void onCreate(Bundle savedInstanceState) { "BarChart positive / negative", "This demonstrates how to create a BarChart with positive and negative values in different colors.")); + ContentItem realm = new ContentItem( + "Realm.io Database", + "This demonstrates how to use this library with Realm.io mobile database."); + objects.add(realm); ContentItem time = new ContentItem( "Time Chart", @@ -269,6 +274,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, BarChartPositiveNegative.class); startActivity(i); break; + case 28: + i = new Intent(this, RealmMainActivity.class); + startActivity(i); + break; case 29: i = new Intent(this, LineChartTime.class); startActivity(i); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java new file mode 100644 index 0000000000..d4fef69576 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -0,0 +1,203 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.formatter.PercentFormatter; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import io.realm.Realm; +import io.realm.RealmConfiguration; + +/** + * Created by Philipp Jahoda on 05/11/15. + */ +public abstract class RealmBaseActivity extends DemoBase { + + protected Realm mRealm; + + protected Typeface mTf; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTitle("Realm.io Examples"); + } + + protected void setup(Chart chart) { + + mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + // no description text + chart.setDescription(""); + chart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable touch gestures + chart.setTouchEnabled(true); + + if (chart instanceof BarLineChartBase) { + + BarLineChartBase mChart = (BarLineChartBase) chart; + + mChart.setDrawGridBackground(false); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(false); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines + leftAxis.setTypeface(mTf); + leftAxis.setTextSize(8f); + leftAxis.setTextColor(Color.DKGRAY); + leftAxis.setValueFormatter(new PercentFormatter()); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(mTf); + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); + xAxis.setTextSize(8f); + xAxis.setTextColor(Color.DKGRAY); + + mChart.getAxisRight().setEnabled(false); + } + } + + protected void styleData(ChartData data) { + data.setValueTypeface(mTf); + data.setValueTextSize(8f); + data.setValueTextColor(Color.DKGRAY); + data.setValueFormatter(new PercentFormatter()); + } + + @Override + protected void onResume() { + super.onResume(); + + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); + + mRealm = Realm.getDefaultInstance(); + } + + @Override + protected void onPause() { + super.onPause(); + mRealm.close(); + } + + protected void writeToDB(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float value = 40f + (float) (Math.random() * 60f); + + RealmDemoData d = new RealmDemoData(i, value); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBStack(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float val1 = 34f + (float) (Math.random() * 12.0f); + float val2 = 34f + (float) (Math.random() * 12.0f); + float[] stack = new float[]{val1, val2, 100 - val1 - val2}; + + RealmDemoData d = new RealmDemoData(i, stack); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBCandle(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float mult = 50; + float val = (float) (Math.random() * 40) + mult; + + float high = (float) (Math.random() * 9) + 8f; + float low = (float) (Math.random() * 9) + 8f; + + float open = (float) (Math.random() * 6) + 1f; + float close = (float) (Math.random() * 6) + 1f; + + boolean even = i % 2 == 0; + + RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, + even ? val - close : val + close); + + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBBubble(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + for (int i = 0; i < objectCount; i++) { + + float value = 30f + (float) (Math.random() * 100.0); + float size = 15f + (float) (Math.random() * 20.0); + + RealmDemoData d = new RealmDemoData(i, value, size); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } + + protected void writeToDBPie() { + + mRealm.beginTransaction(); + + mRealm.delete(RealmDemoData.class); + + float value1 = 15f + (float) (Math.random() * 8f); + float value2 = 15f + (float) (Math.random() * 8f); + float value3 = 15f + (float) (Math.random() * 8f); + float value4 = 15f + (float) (Math.random() * 8f); + float value5 = 100f - value1 - value2 - value3 - value4; + + float[] values = new float[] { value1, value2, value3, value4, value5 }; + String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; + + for (int i = 0; i < values.length; i++) { + RealmDemoData d = new RealmDemoData(values[i], labels[i]); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java new file mode 100644 index 0000000000..c87290050d --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -0,0 +1,69 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityBar extends RealmBaseActivity { + + private BarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart_noseekbar); + + mChart = (BarChart) findViewById(R.id.chart1); + setup(mChart); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(20); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries + set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + set.setLabel("Realm BarDataSet"); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BarData data = new BarData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.setFitBars(true); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java new file mode 100644 index 0000000000..d0aa25b864 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -0,0 +1,71 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BubbleChart; +import com.github.mikephil.charting.data.BubbleData; +import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityBubble extends RealmBaseActivity { + + private BubbleChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_bubblechart_noseekbar); + + mChart = (BubbleChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getXAxis().setDrawGridLines(false); + mChart.getAxisLeft().setDrawGridLines(false); + mChart.setPinchZoom(true); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBBubble(10); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); + set.setLabel("Realm BubbleDataSet"); + set.setColors(ColorTemplate.COLORFUL_COLORS, 110); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BubbleData data = new BubbleData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java new file mode 100644 index 0000000000..a388df3741 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -0,0 +1,77 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Paint; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.CandleStickChart; +import com.github.mikephil.charting.data.CandleData; +import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityCandle extends RealmBaseActivity { + + private CandleStickChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_candlechart_noseekbar); + + mChart = (CandleStickChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBCandle(50); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); + set.setLabel("Realm CandleDataSet"); + set.setShadowColor(Color.DKGRAY); + set.setShadowWidth(0.7f); + set.setDecreasingColor(Color.RED); + set.setDecreasingPaintStyle(Paint.Style.FILL); + set.setIncreasingColor(Color.rgb(122, 242, 84)); + set.setIncreasingPaintStyle(Paint.Style.STROKE); + set.setNeutralColor(Color.BLUE); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + CandleData data = new CandleData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java new file mode 100644 index 0000000000..32d1234fe2 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -0,0 +1,74 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { + + private HorizontalBarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart_noseekbar); + + mChart = (HorizontalBarChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setAxisMinValue(0f); + mChart.setDrawValueAboveBar(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBStack(50); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries + set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); + set.setLabel("Mobile OS distribution"); + set.setStackLabels(new String[]{"iOS", "Android", "Other"}); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BarData data = new BarData(dataSets); + styleData(data); + data.setValueTextColor(Color.WHITE); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java new file mode 100644 index 0000000000..6d2396c22b --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -0,0 +1,77 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityLine extends RealmBaseActivity { + + private LineChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart_noseekbar); + + mChart = (LineChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setAxisMaxValue(150f); + mChart.getAxisLeft().setAxisMinValue(0f); + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(40); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); + set.setDrawCubic(false); + set.setLabel("Realm LineDataSet"); + set.setDrawCircleHole(false); + set.setColor(ColorTemplate.rgb("#FF5722")); + set.setCircleColor(ColorTemplate.rgb("#FF5722")); + set.setLineWidth(1.8f); + set.setCircleSize(3.6f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + LineData data = new LineData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java new file mode 100644 index 0000000000..7b1eb675d9 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -0,0 +1,83 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityPie extends RealmBaseActivity { + + private PieChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_piechart_noseekbar); + + mChart = (PieChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.setCenterText(generateCenterSpannableText()); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBPie(); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries + set.setColors(ColorTemplate.VORDIPLOM_COLORS); + set.setLabel("Example market share"); + set.setSliceSpace(2); + + // create a data object with the dataset list + PieData data = new PieData(set); + styleData(data); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(12f); + + // set data + mChart.setData(data); + mChart.animateY(1400); + } + + private SpannableString generateCenterSpannableText() { + + SpannableString s = new SpannableString("Realm.io\nmobile database"); + s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); + s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); + s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); + s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); + return s; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java new file mode 100644 index 0000000000..411f4b6ac9 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -0,0 +1,78 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.graphics.Color; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.data.RadarData; +import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityRadar extends RealmBaseActivity { + + private RadarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_radarchart_noseekbar); + + mChart = (RadarChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getYAxis().setEnabled(false); + mChart.getXAxis().setEnabled(false); + mChart.setWebAlpha(180); + mChart.setWebColorInner(Color.DKGRAY); + mChart.setWebColor(Color.GRAY); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(7); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries + set.setLabel("Realm RadarDataSet"); + set.setDrawFilled(true); + set.setColor(ColorTemplate.rgb("#009688")); + set.setFillColor(ColorTemplate.rgb("#009688")); + set.setFillAlpha(130); + set.setLineWidth(2f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + RadarData data = new RadarData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java new file mode 100644 index 0000000000..14175ac73a --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -0,0 +1,73 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityScatter extends RealmBaseActivity { + + private ScatterChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_scatterchart_noseekbar); + + mChart = (ScatterChart) findViewById(R.id.chart1); + setup(mChart); + + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getXAxis().setDrawGridLines(false); + mChart.setPinchZoom(true); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDB(45); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.where(RealmDemoData.class).findAll(); + + RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); + set.setLabel("Realm ScatterDataSet"); + set.setScatterShapeSize(9f); + set.setColor(ColorTemplate.rgb("#CDDC39")); + set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + ScatterData data = new ScatterData(dataSets); + styleData(data); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java new file mode 100644 index 0000000000..3198320272 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -0,0 +1,131 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.view.WindowManager; +import android.widget.AdapterView; +import android.widget.ListView; + +import com.xxmassdeveloper.mpchartexample.R; +import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; + +import java.util.ArrayList; + +import io.realm.Realm; +import io.realm.RealmConfiguration; + +/** + * Created by Philipp Jahoda on 07/12/15. + */ +public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_main); + + setTitle("Realm.io Examples"); + + ArrayList objects = new ArrayList(); + + objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); + objects.add(new ContentItem("Bar Chart", + "Creating a BarChart with Realm.io database")); + objects.add(new ContentItem("Horizontal Bar Chart", + "Creating a HorizontalBarChart with Realm.io database")); + objects.add(new ContentItem("Scatter Chart", + "Creating a ScatterChart with Realm.io database")); + objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); + objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); + objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); + objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); + objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); + + MyAdapter adapter = new MyAdapter(this, objects); + + ListView lv = (ListView) findViewById(R.id.listView1); + lv.setAdapter(adapter); + + lv.setOnItemClickListener(this); + + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. + RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + Realm.setDefaultConfiguration(realmConfig); + + Realm realm = Realm.getDefaultInstance(); + realm.beginTransaction(); + realm.deleteAll(); + realm.commitTransaction(); + } + + @Override + public void onItemClick(AdapterView av, View v, int pos, long arg3) { + + Intent i; + + switch (pos) { + case 0: + i = new Intent(this, RealmDatabaseActivityLine.class); + startActivity(i); + break; + case 1: + i = new Intent(this, RealmDatabaseActivityBar.class); + startActivity(i); + break; + case 2: + i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); + startActivity(i); + break; + case 3: + i = new Intent(this, RealmDatabaseActivityScatter.class); + startActivity(i); + break; + case 4: + i = new Intent(this, RealmDatabaseActivityCandle.class); + startActivity(i); + break; + case 5: + i = new Intent(this, RealmDatabaseActivityBubble.class); + startActivity(i); + break; + case 6: + i = new Intent(this, RealmDatabaseActivityPie.class); + startActivity(i); + break; + case 7: + i = new Intent(this, RealmDatabaseActivityRadar.class); + startActivity(i); + break; + case 8: + i = new Intent(this, RealmWikiExample.class); + startActivity(i); + break; + } + + overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.realm, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://realm.io")); + startActivity(i); + + return super.onOptionsItemSelected(item); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java new file mode 100644 index 0000000000..7682bca957 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -0,0 +1,137 @@ +package com.xxmassdeveloper.mpchartexample.realm; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.R; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 18/12/15. + */ +public class RealmWikiExample extends RealmBaseActivity { + + private LineChart lineChart; + private BarChart barChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_realm_wiki); + + lineChart = (LineChart) findViewById(R.id.lineChart); + barChart = (BarChart) findViewById(R.id.barChart); + setup(lineChart); + setup(barChart); + + lineChart.setExtraBottomOffset(5f); + barChart.setExtraBottomOffset(5f); + + lineChart.getAxisLeft().setDrawGridLines(false); + lineChart.getXAxis().setDrawGridLines(false); + lineChart.getXAxis().setLabelCount(5); + lineChart.getXAxis().setGranularity(1f); + barChart.getAxisLeft().setDrawGridLines(false); + barChart.getXAxis().setDrawGridLines(false); + barChart.getXAxis().setLabelCount(5); + barChart.getXAxis().setGranularity(1f); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + mRealm.beginTransaction(); + + // write some demo-data into the realm.io database + Score score1 = new Score(100f, 0f, "Peter"); + mRealm.copyToRealm(score1); + Score score2 = new Score(110f, 1f, "Lisa"); + mRealm.copyToRealm(score2); + Score score3 = new Score(130f, 2f, "Dennis"); + mRealm.copyToRealm(score3); + Score score4 = new Score(70f, 3f, "Luke"); + mRealm.copyToRealm(score4); + Score score5 = new Score(80f, 4f, "Sarah"); + mRealm.copyToRealm(score5); + + mRealm.commitTransaction(); + + // add data to the chart + setData(); + } + + private void setData() { + + // LINE-CHART + final RealmResults results = mRealm.where(Score.class).findAll(); + + + AxisValueFormatter formatter = new AxisValueFormatter() { + @Override + public String getFormattedValue(float value, AxisBase axis) { + return results.get((int) value).getPlayerName(); + } + + @Override + public int getDecimalDigits() { + return 0; + } + }; + + lineChart.getXAxis().setValueFormatter(formatter); + barChart.getXAxis().setValueFormatter(formatter); + + RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); + lineDataSet.setDrawCubic(false); + lineDataSet.setLabel("Result Scores"); + lineDataSet.setDrawCircleHole(false); + lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); + lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); + lineDataSet.setLineWidth(1.8f); + lineDataSet.setCircleSize(3.6f); + + ArrayList dataSets = new ArrayList(); + dataSets.add(lineDataSet); + + LineData lineData = new LineData(dataSets); + styleData(lineData); + + // set data + lineChart.setData(lineData); + lineChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + + + // BAR-CHART + RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); + barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + barDataSet.setLabel("Realm BarDataSet"); + + ArrayList barDataSets = new ArrayList(); + barDataSets.add(barDataSet); + + BarData barData = new BarData(barDataSets); + styleData(barData); + + barChart.setData(barData); + barChart.setFitBars(true); + barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java new file mode 100644 index 0000000000..870e371491 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java @@ -0,0 +1,51 @@ +package com.xxmassdeveloper.mpchartexample.realm; + + +import io.realm.RealmObject; + +/** + * our data object + */ +public class Score extends RealmObject { + + private float totalScore; + + private float scoreNr; + + private String playerName; + + public Score() { + } + + public Score(float totalScore, float scoreNr, String playerName) { + this.scoreNr = scoreNr; + this.playerName = playerName; + this.totalScore = totalScore; + } + + // all getters and setters... + + public float getTotalScore() { + return totalScore; + } + + public void setTotalScore(float totalScore) { + this.totalScore = totalScore; + } + + public float getScoreNr() { + return scoreNr; + } + + public void setScoreNr(float scoreNr) { + this.scoreNr = scoreNr; + } + + public String getPlayerName() { + return playerName; + } + + public void setPlayerName(String playerName) { + this.playerName = playerName; + } +} \ No newline at end of file diff --git a/build.gradle b/build.gradle index 339dc2007c..3dfff3b287 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - //classpath "io.realm:realm-gradle-plugin:1.1.0" + classpath "io.realm:realm-gradle-plugin:1.1.0" classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } From 31b0fd9ff94765e68022232099fe02b06113b182 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Aug 2016 00:24:41 +0300 Subject: [PATCH 1132/1390] Updated Realm sample --- .../mpchartexample/realm/RealmWikiExample.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 7682bca957..a2b9e05880 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -84,7 +84,7 @@ private void setData() { final RealmResults results = mRealm.where(Score.class).findAll(); - AxisValueFormatter formatter = new AxisValueFormatter() { + IAxisValueFormatter formatter = new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return results.get((int) value).getPlayerName(); From 788539001ff66550fe895d2868c3a4b1a56df02c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 10 Aug 2016 22:43:54 +0300 Subject: [PATCH 1133/1390] Choose a default that matches the default v2 behavior To avoid hurting existing stylings drastically --- .../main/java/com/github/mikephil/charting/data/BarData.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java index 20a27a5fec..16d60f6f9c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarData.java @@ -15,7 +15,7 @@ public class BarData extends BarLineScatterCandleBubbleData { /** * the width of the bars on the x-axis, in values (not pixels) */ - private float mBarWidth = 1f; + private float mBarWidth = 0.85f; public BarData() { super(); @@ -31,7 +31,7 @@ public BarData(List dataSets) { /** * Sets the width each bar should have on the x-axis (in values, not pixels). - * Default 1f + * Default 0.85f * * @param mBarWidth */ From e158ef15e23bb8f00f4cf064a181bd1a018d604b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Aug 2016 12:46:52 +0200 Subject: [PATCH 1134/1390] Renaming of setAxisMinValue etc to setAxisMinimum for consistency --- .../mpchartexample/BarChartActivity.java | 8 ++--- .../BarChartActivityMultiDataset.java | 6 ++-- .../mpchartexample/BarChartActivitySinus.java | 8 ++--- .../BarChartPositiveNegative.java | 4 +-- .../mpchartexample/CombinedChartActivity.java | 8 ++--- .../mpchartexample/FilledLineActivity.java | 4 +-- .../HorizontalBarChartActivity.java | 6 ++-- .../InvertedLineChartActivity.java | 4 +-- .../mpchartexample/LineChartActivity1.java | 4 +-- .../mpchartexample/LineChartActivity2.java | 8 ++--- .../mpchartexample/LineChartTime.java | 4 +-- .../mpchartexample/RadarChartActivitry.java | 4 +-- .../RealtimeLineChartActivity.java | 5 ++-- .../mpchartexample/ScatterChartActivity.java | 3 +- .../mpchartexample/StackedBarActivity.java | 2 +- .../StackedBarActivityNegative.java | 8 ++--- .../fragments/BarChartFrag.java | 2 +- .../fragments/SineCosineFragment.java | 4 +-- .../listviewitems/BarChartItem.java | 4 +-- .../listviewitems/LineChartItem.java | 4 +-- .../RealmDatabaseActivityHorizontalBar.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 4 +-- .../charting/components/AxisBase.java | 30 +++++++++++++++---- .../mikephil/charting/components/YAxis.java | 6 ++-- 24 files changed, 79 insertions(+), 63 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 7718cd12ea..71aba6f1dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); leftAxis.setSpaceTop(15f); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); @@ -104,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); - rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) Legend l = mChart.getLegend(); l.setPosition(LegendPosition.BELOW_CHART_LEFT); @@ -228,8 +228,8 @@ private void setData(int count, float range) { float start = 0f; - mChart.getXAxis().setAxisMinValue(start); - mChart.getXAxis().setAxisMaxValue(start + count + 2); + mChart.getXAxis().setAxisMinimum(start); + mChart.getXAxis().setAxisMaximum(start + count + 2); ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index fe63f075d0..4024260cc6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -104,7 +104,7 @@ public int getDecimalDigits() { leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); leftAxis.setSpaceTop(30f); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); } @@ -249,8 +249,8 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } mChart.getBarData().setBarWidth(barWidth); - mChart.getXAxis().setAxisMinValue(startYear); - mChart.getXAxis().setAxisMaxValue(mChart.getBarData().getGroupWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); + mChart.getXAxis().setAxisMinimum(startYear); + mChart.getXAxis().setAxisMaximum(mChart.getBarData().getGroupWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); mChart.groupBars(startYear, groupSpace, barSpace); mChart.invalidate(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index a61c357b13..31f9fa1e56 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -76,8 +76,8 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTfLight); leftAxis.setLabelCount(6, false); - leftAxis.setAxisMinValue(-2.5f); - leftAxis.setAxisMaxValue(2.5f); + leftAxis.setAxisMinimum(-2.5f); + leftAxis.setAxisMaximum(2.5f); leftAxis.setGranularityEnabled(true); leftAxis.setGranularity(0.1f); @@ -85,8 +85,8 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setDrawGridLines(false); rightAxis.setTypeface(mTfLight); rightAxis.setLabelCount(6, false); - rightAxis.setAxisMinValue(-2.5f); - rightAxis.setAxisMaxValue(2.5f); + rightAxis.setAxisMinimum(-2.5f); + rightAxis.setAxisMaximum(2.5f); rightAxis.setGranularity(0.1f); mSeekBarX.setOnSeekBarChangeListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 424873e72a..e9b7fc7a50 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -61,8 +61,8 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setTextColor(Color.LTGRAY); xAxis.setTextSize(13f); - xAxis.setAxisMinValue(0f); - xAxis.setAxisMaxValue(5f); + xAxis.setAxisMinimum(0f); + xAxis.setAxisMaximum(5f); xAxis.setLabelCount(5); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 599143e38b..224b1f1fe6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -66,15 +66,15 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setDrawGridLines(false); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); - xAxis.setAxisMinValue(0f); + xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); xAxis.setValueFormatter(new IAxisValueFormatter() { @Override @@ -97,7 +97,7 @@ public int getDecimalDigits() { data.setData(generateCandleData()); data.setValueTypeface(mTfLight); - xAxis.setAxisMaxValue(data.getXMax() + 0.25f); + xAxis.setAxisMaximum(data.getXMax() + 0.25f); mChart.setData(data); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index a9d7210d62..dbc44a34f8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -51,8 +51,8 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setEnabled(false); YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setAxisMaxValue(900f); - leftAxis.setAxisMinValue(-250f); + leftAxis.setAxisMaximum(900f); + leftAxis.setAxisMinimum(-250f); leftAxis.setDrawAxisLine(false); leftAxis.setDrawZeroLine(false); leftAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index bab2e085a0..316ef4ecac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -2,8 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.annotation.SuppressLint; -import android.graphics.PointF; -import android.graphics.Rect; import android.graphics.RectF; import android.os.Bundle; import android.util.Log; @@ -87,14 +85,14 @@ protected void onCreate(Bundle savedInstanceState) { yl.setTypeface(mTfLight); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); - yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) + yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); YAxis yr = mChart.getAxisRight(); yr.setTypeface(mTfLight); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); - yr.setAxisMinValue(0f); // this replaces setStartAtZero(true) + yr.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yr.setInverted(true); setData(12, 50); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index dc41160eb2..9360db623f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -84,11 +84,11 @@ protected void onCreate(Bundle savedInstanceState) { XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); - xl.setAxisMinValue(0f); + xl.setAxisMinimum(0f); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setInverted(true); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 2de91ee64f..44fcfc036f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -128,8 +128,8 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines leftAxis.addLimitLine(ll1); leftAxis.addLimitLine(ll2); - leftAxis.setAxisMaxValue(200f); - leftAxis.setAxisMinValue(-50f); + leftAxis.setAxisMaximum(200f); + leftAxis.setAxisMinimum(-50f); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); leftAxis.setDrawZeroLine(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 81097debea..e46d582e6a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -107,16 +107,16 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); - leftAxis.setAxisMaxValue(200f); - leftAxis.setAxisMinValue(0f); + leftAxis.setAxisMaximum(200f); + leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(mTfLight); rightAxis.setTextColor(Color.RED); - rightAxis.setAxisMaxValue(900); - rightAxis.setAxisMinValue(-200); + rightAxis.setAxisMaximum(900); + rightAxis.setAxisMinimum(-200); rightAxis.setDrawGridLines(false); rightAxis.setDrawZeroLine(false); rightAxis.setGranularityEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index afe8fa2ef0..9380835ed8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -110,8 +110,8 @@ public int getDecimalDigits() { leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); - leftAxis.setAxisMinValue(0f); - leftAxis.setAxisMaxValue(170f); + leftAxis.setAxisMinimum(0f); + leftAxis.setAxisMaximum(170f); leftAxis.setYOffset(-9f); leftAxis.setTextColor(Color.rgb(255, 192, 56)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index fcc1b2f55c..51bd19dfad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -93,8 +93,8 @@ public int getDecimalDigits() { yAxis.setTypeface(mTfLight); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); - yAxis.setAxisMinValue(0f); - yAxis.setAxisMaxValue(80f); + yAxis.setAxisMinimum(0f); + yAxis.setAxisMaximum(80f); yAxis.setDrawLabels(false); Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 75675d1ac1..97410b0ca8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -83,8 +82,8 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTfLight); leftAxis.setTextColor(Color.WHITE); - leftAxis.setAxisMaxValue(100f); - leftAxis.setAxisMinValue(0f); + leftAxis.setAxisMaximum(100f); + leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); YAxis rightAxis = mChart.getAxisRight(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index fbcea85d2f..c6b457eb1a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample; -import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -78,7 +77,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(mTfLight); - yl.setAxisMinValue(0f); // this replaces setStartAtZero(true) + yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 5c562190bc..ff4fde35d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -74,7 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setValueFormatter(new MyAxisValueFormatter()); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); XAxis xLabels = mChart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 1569f574ee..af04d3ae26 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -59,8 +59,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setHighlightFullBarEnabled(false); mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setAxisMaxValue(25f); - mChart.getAxisRight().setAxisMinValue(-25f); + mChart.getAxisRight().setAxisMaximum(25f); + mChart.getAxisRight().setAxisMinimum(-25f); mChart.getAxisRight().setDrawGridLines(false); mChart.getAxisRight().setDrawZeroLine(true); mChart.getAxisRight().setLabelCount(7, false); @@ -72,8 +72,8 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); xAxis.setTextSize(9f); - xAxis.setAxisMinValue(0f); - xAxis.setAxisMaxValue(110f); + xAxis.setAxisMinimum(0f); + xAxis.setAxisMaximum(110f); xAxis.setCenterAxisLabels(true); xAxis.setLabelCount(12); xAxis.setGranularity(10f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index b77c0b815f..286f0d58e4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -52,7 +52,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 418a856f5f..648a0f01d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -41,8 +41,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); - leftAxis.setAxisMaxValue(1.2f); - leftAxis.setAxisMinValue(-1.2f); + leftAxis.setAxisMaximum(1.2f); + leftAxis.setAxisMinimum(-1.2f); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index 008c849786..ab3c99b7c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -62,13 +62,13 @@ public View getView(int position, View convertView, Context c) { leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(20f); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(20f); - rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChartData.setValueTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index e43b64d1bd..c1796258f4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -62,13 +62,13 @@ public View getView(int position, View convertView, Context c) { YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); - leftAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); rightAxis.setDrawGridLines(false); - rightAxis.setAxisMinValue(0f); // this replaces setStartAtZero(true) + rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) // set data holder.chart.setData((LineData) mChartData); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 32d1234fe2..5fcfa76bff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -34,7 +34,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (HorizontalBarChart) findViewById(R.id.chart1); setup(mChart); - mChart.getAxisLeft().setAxisMinValue(0f); + mChart.getAxisLeft().setAxisMinimum(0f); mChart.setDrawValueAboveBar(false); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 6d2396c22b..13513fd50e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -33,8 +33,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); setup(mChart); - mChart.getAxisLeft().setAxisMaxValue(150f); - mChart.getAxisLeft().setAxisMinValue(0f); + mChart.getAxisLeft().setAxisMaximum(150f); + mChart.getAxisLeft().setAxisMinimum(0f); mChart.getAxisLeft().setDrawGridLines(false); mChart.getXAxis().setDrawGridLines(false); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index bc729f1148..a579549f37 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -5,8 +5,8 @@ import android.graphics.DashPathEffect; import android.util.Log; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -542,7 +542,7 @@ public float getAxisMinimum() { * and the calculation is * done automatically. */ - public void resetAxisMaxValue() { + public void resetAxisMaximum() { mCustomAxisMax = false; } @@ -560,7 +560,7 @@ public boolean isAxisMaxCustom() { * and the calculation is * done automatically. */ - public void resetAxisMinValue() { + public void resetAxisMinimum() { mCustomAxisMin = false; } @@ -582,12 +582,22 @@ public boolean isAxisMinCustom() { * * @param min */ - public void setAxisMinValue(float min) { + public void setAxisMinimum(float min) { mCustomAxisMin = true; mAxisMinimum = min; this.mAxisRange = Math.abs(mAxisMaximum - min); } + /** + * Use setAxisMinimum(...) instead. + * + * @param min + */ + @Deprecated + public void setAxisMinValue(float min) { + setAxisMinimum(min); + } + /** * Set a custom maximum value for this axis. If set, this value will not be calculated * automatically depending on @@ -595,12 +605,22 @@ public void setAxisMinValue(float min) { * * @param max */ - public void setAxisMaxValue(float max) { + public void setAxisMaximum(float max) { mCustomAxisMax = true; mAxisMaximum = max; this.mAxisRange = Math.abs(max - mAxisMinimum); } + /** + * Use setAxisMaximum(...) instead. + * + * @param max + */ + @Deprecated + public void setAxisMaxValue(float max) { + setAxisMaximum(max); + } + /** * Calculates the minimum / maximum and range values of the axis with the given * minimum and maximum values from the chart data. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 21dc5f7367..82d77c4c8f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -201,16 +201,16 @@ public boolean isInverted() { /** * This method is deprecated. - * Use setAxisMinValue(...) / setAxisMaxValue(...) instead. + * Use setAxisMinimum(...) / setAxisMaximum(...) instead. * * @param startAtZero */ @Deprecated public void setStartAtZero(boolean startAtZero) { if (startAtZero) - setAxisMinValue(0f); + setAxisMinimum(0f); else - resetAxisMinValue(); + resetAxisMinimum(); } /** From 077365c9af2004cbe99116a7183735ae206b6de9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Aug 2016 18:25:29 +0200 Subject: [PATCH 1135/1390] Add barchart wiki image --- screenshots/normal_barchart_wiki.png | Bin 0 -> 40671 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/normal_barchart_wiki.png diff --git a/screenshots/normal_barchart_wiki.png b/screenshots/normal_barchart_wiki.png new file mode 100644 index 0000000000000000000000000000000000000000..aa5676f9d3058b393c27a23c919f2658d0d1d048 GIT binary patch literal 40671 zcmeEO_aoKq`;RCciHbatmC6d0l`S$#_R1F7dvk1skd+WJkG=OeW>iQ<_BwXfu{kz< z?{`o2Nj-nU_xZs?r@Zg?J+A9@yV_MdF{wfR`yUS%IE_7P3V|OKP?CBfc z@Uw{u0*2bR!z=Zd-NsaHHa>HYg%{e+w!0!|JWpWbQ6K+uEmufP?Bn$36n^-*D_A&0 zLMM)Yp{5Tdk$`&(uKw}o-+!du#d*C#w0^LHJVPs(5N6u4%{lYp{GY!<2>Ur77LE@u zIj31cSE{6XrhKZC;UB|*etbYDn-asPs;YWvo~ch&d?@X4p>82(UJLHk={axROKSJx%gYT%f~0lkpY01_s#5sQ3^!<92W z+{FfMMGOjQ14w)H$nD-d&Ea6)<-6HhHSn;luQk5Gg^!}|C@0@P<7fsS#SgNvwY}W% z_1+rAUqic~Moml9exLb1;+A25p61qiE93G)c&crGg8%U8Zn+=t;;Bo|!aTN7yd!UHBo?FbCQ|)Q)cUkj& zJJ{Ho4wo6acbeiU0U5hhQg8#}Qv}m6Z3v$(1&`f}N>-|NUfy&uG9X>InSFrlrHyM&{?fDo?f!@lbP6g+w_Fh2nlZ}}+ho#c~q4lq=n)$IdUq9iB z&@8QNk9m|AcL)sURj)rJ9hu`^`3Du~b0FTjiRn|f9PCxmUV_sz@GW$whiKY;5$(%V zpz9|$Iy%_RGYo;Baek-NY~l3cKaT24A!_uSE4B{Iz1?z8bbY8yCMF*Ez(^L6=)7V- zD)#}OTMKcBEp&bzGF||t)lD;Kf?0tJmja|y))WP`>OfHwzJavVD2?F6D?54N?GxyuM`OH)J8(V5%Wok z{Br)Wzs~pxulpBeN6&+?`S6{la<#g(iN}A2m3Yn9m|3;xTE%0LctyV^d`WM7Y{HT_ zU!zQ&^$x*rizeIm@txVPn6*YS_a%$smy@s9W1dlF%ND_eI^uZy`|`C{`uw-3Nc{Vv z%DT70wA4HNYNbmK3(x*_xWKu`)!mx@g5~Q=5r%!f?M>=rOO`DnO}H%vSF+g1nN3M_ zh=o^H&~SfiDNRTMV|6tb(XZ?^`!Iqrx<8Pv3r?o2RPAKVb@B~->%LkOg~qrb?9EWQ z<%+Lk&_A~u+Ii47RR#uQ`}l{-Mg?|)|6_4p34M;|i!nE8i{VHk<8YVaH|iM{E4A%m zuQtUj^jfIdvQGP#nD=HWX?m8}&38!zqHJLyilh?Vxlt^dLyr7y6{(q>N}k-x3NLKi zxo0cXgtA&~Tdqe9yydnvTN)}YD|%ChhGO3qiFa5UQuV)ZU85$plahaQ@KGF3 zuas$?7N-{BKLkGVC~_Z`QQOhIq_I+sHZ&G7^0P}$sCZIXFpZkdG;>H9t7XETR_a3% z6?(PO=VcbCg#a#7&VtjFPW5SzqAwsBL;hp6pOZER*gr2d=`Hd&n4+@yw1LlB-ASU8 zr;r{Tt0c+xRO;>BFVc4>aMa5!;xf5{V!SCxSc8dSKDF`Xd}>4~`g`kr1So;c!g9W$ zTH*eFy@V3&Oi?Xe(Sspl~+9V^pfuy8H&&;-$QF(bmX;L1`m9rXm*C+g_kh6B)SwRRbo&}{TAJ#DG5w!hO?~s2< zu$FeK(kvbLuZwY+n<6~Y_#o_>cIbmaA3-T&BasM>bdXDl?>N zLKID3WcCL#HtqctB#H8cK8H39Tci7Omr#yl%tS*@H3kBQn+l|JAlt;i$W0mT30&k? zlN&yV4S~pv>K-jYhxL6SVkVIvEqL+_UmEPnSw%vL#=N4FAKnHI5r3SMoJC-FK;cg6 z&8>H%E-U;XH%NuKY-F%>ic`5wn_M8lJbp~|_j!0Bp4dqfQf|vSu;#9u9}z|?t_E_T zlt@(%yQC6AEXb@UL(U@0#uBx_WzYBullDf-Q71Q%8F0WijnG}GfyNbmV0RlwFsZOuWD}nvR;_(f#qtsgxA719yY^m*I`n9DnuEfo*+bBne zuMsLB*2f&SqJu7u+-*3CE0M)&*Y$vIkbCy+RN1$$QQC{|PE(bDM-CEe5m53CC_awy z{g2@FOeo1@J)=L!pf5|S28n)xNEG*y8ZI-}^qf*Toeq+nMROm7RT4aoD)DvM5q(Aa zt&0^?!L}2j4T+tchV57O54XoOJumK6`|27qZeyK1Rgv^0>l>m#Ea?kaXA45URnJ(g zn|9=NO^oe)c5|}(V1YC(DSbp^Y9#qX+V4)CRgn}Id2jUBq4E?e!h4G2%kZ^{X8YAc7Z2U3Hs9|Z|CH6Wc*kQGB)?l%r zdb)HRtcHN;>YrQf1ol4ltx8#b=bmS?AmW7V+nWF|H>bs!Rfk}$OBze1J5bGL_b-iow3V=59zr%(*oQ7z$-#9;;hwmFTN97 zL4PkCb-@Y%*ZUUDlz##D6JCOvo)c;wd)LQL5J?DPwH0waZ6+dTGk6)BDZ}zWf7ro4)Vp;A*)Yw|ier9jE1TVNBb zS2^TnW>g!DRxK8_=IAvAM@D=Q3~_hh3;BI?{tWfnxBZvH4ua1}j!R6K1&BZZgC-0DIB(WO>0*ZUOf>M4Y6vC&Beq2d3dXP-Pf{|`BUc;n z%?Ape^d*V-VGr*dCWg*~z2o>q4g`7#t3`%~>y5c>$6@BXoA$O>EFDLz{YaRUKU z9~0iSw?av2vN9D2>D80EFbqze(3R1I8=$bJj699_ogR51e*8dsP^Tmmv^Q= z3u%pDG6cE0)(znOG7!zjH~5a%e-|`8L+QTc6E*n>!OqZ+&x0W7c8KX`xqn8G!-qS+ zb}uW=c_tbvZp!Zp3XaXR$C>(3!ZR2={d?}*xuX#je_b+i0F-i9b1%4Bj8;3d+{yxz zxmvk;8U$?)A1Nl~96as!9mnE^Py>u;{n}#cL_LuNKbFsJ##cF7?EMtvH0Acm2y6SHdZ?YQnd1G~OzvZd~DOMNGKyu;bqIqfS5 z*<~Q=ok}3|kS){|Wzs~J90H6y5x8^tSoW28jAhXOa6q!rizYM%8}|5Ux5HzoIgC~c zV;S!>c_tgAQGn)JDP33Zp?fmJBN&w!oz}Ag5kwNW5h8w8xGFniCzn*DiXC@3NUXH# z+-oT8I`83X(Ym_f3i0^%W~=zIP8uGI6Vy*|=UT!GqI^$^P}}3O2lnxn;%FOAj=7ZnvHpAuWRog!r1 z6ine>HF>;rqMpFPbH1?r%1Q_?CC^j%lFwa6vz$?Oy^k*o4HMk@d2F4kLY zDAV69USrWiTt+`GcNejA7!#T8{6r=NLwvzld#JpDwr+-*a7k{uoTcM<9{0a0)ErK) z;yooqO@PC$-fLctG5}98{>;G?*{@b&^u0_Ot#KLF3*k4wCuOkMM-)`mKG6oAMmu{_s zqQsRKr?7v$Qv3LLnz$ANPFS+$`QX!D#Fu1=5Kq(?lNbBh-#%p1XI3x!OwiFqlzobT z>`hsaGOc)bzNy;gGeUs@%l_qEIA)=8>p zY)}yAot7%`)CX|0%xO)RbkWHtG8V*4ler9EnUply8Bh}zC`fZ(@0!H!V5pGmNDL7? zs;J)>B?OoTM3oXyNh5_mxx^nY_l1)2!Qt5>ncN|gpz(@iR#yWh%@T;gDb6F3a4cb0r|{I?cfJ+41|?I{5S!3a8A|C)5FSD5eqdtVr5Cip1pvklfI%8(VGt)WT(*~S%jSEt zquf^Coo2Z!UogdiD^fmU6F6LE+Mkyf9O6xhIYq_~FVVDVxz1@dF2r>)s+{0>IqZc) z`sPuy?TI`hnhq=>{V0a(x9k@bxvC=JU+JynKHAB%MJ>LLD# zVMe|#m6ZBsb(NaH>de7XtrGhh^FONFYl-#KIXHau=gwf^blp!ZNRqxQ{-j)CXNvTM z^ZvDgwQI-!ehW*%w$qEJg0#W^QItrCfaAwrJ@@v`u|x4zUoR!AFc823o2IL8$g)>C!DWe=;UmiPM z&~vE?aErQD-*W5YywafVxM^wlD&eG`M?LNxNn9=OE8jeMH+~=ZwNNl-Y|XRhaJ?Gv zrY+(ucu7ahFMrq+=Ogg4@^WqM=qQo5Un$o88sp14eJo~6JOL9yTwC#0%>*_*n^Vk> zKBAaQk>lf#2`wJt@;a!WiN1cb&Y{k2m{9%q@e6fe<+kx;F7{L7ck_|BJppFw$LPj3PS7h~?*$8rWVT@rL)5O&C+w@kmk)c0+a0zrgN zT58gNGc8>Yz-q+han1%D0~OFeV_*WSQ4|$<@vnl&%kBbLjr8oc%D(`$&?k_qQx;Rd zzW;kQ;&6((=AUw_92+_{3I{N_dLSv^mf@wPZ3IW!AUfJ*8@IWw&3?bRqk}6q-M++v zPpT>Ta4E#?!^WQ3Ga*J0(^A%ZzmEL=5b9i9hvgAth!A6bTu|SCFDa-NB*O0uFd~>I zs~!n}QR##58-vNBfo1^aE0>w6wzjvIfgqy_SZr7hIofY&xO^DYB<6s=OFN9bsoJ&B zlc~q7R#E^8{Hm!JrG%hd^{hKV6H-SY`TN69c%@t#sBtNmisu{r7(%r&ydj3w0shTW z`ItKtJ8?uPF(q;ZwktK;L+|}B<^sN1IaB_+dJVi(y$--S2T=bF1FBb%9sxl65Jd7) zxow6i8JV?WMUyg$o*hV+y#n9CEe1+013vzr!pKv zvE%RPe;NSD^rH0(6)SPC(+hH&i^Uy70Eg%SE;l_6e6dik*wTtW`dTQ71LT z2h64MiJkDe3St#8R-n@H0X@AS%SwTJ+g*yLW2Dk{X`@519G|749@K6#%1Ui-za4GY zZGpmkP}32mPpakg#EKLajC5F9fFD%@mX)QzxGUv>mGjQYd~q;75F`if`!!W`B0xU; zfVqU+TgXP4IxG$p*4wxXo$zYFU(}S#UL7vFar`I-1L zB7j3CNvWs($AX!Uzh}xNS+_WV;)nd{;*Buqe!}>`1}a=Ou%_p>md~)9<&z~$0?LD$ zL*j{IlcS9CU~PqFHp@{ym1lID9K!wij|-DIEJsJ&4>2kV^?-`-+5u2)(pHb@_@T+f zC7yl>iaX3C_x6Y_>X8Z$4K63+t7`W{IO*h0TuPc;|L4byLpiKbfDt3(BV)5x;ZqY!#XjNlJ_b zi@kH;9h?(K`8Z5^tk8L?#W$X|eBB9#X(LjEw42u@VN|5If{%uRgZPldNnrCdE}L2&wYXQP zc6Tj%U}Rq}r+cp1V3CD(jDH~DJk~(ud_Vh9`FNqw13#ut4p1#t?Lv}u_q#9Q5v}Ut((!k3qr#-r?4yaeH)*3qEftvtOeu`qH zDs>2n?9WnajbzofVBETr$>1cfNkyRmpek){gDqG&Jn#fz>O$D@m4ji!3@$ONJ*5?U zc?&a{352Nk-SR7xKFk1NZ&Dbfs_}xI?|>x@IBeQwahXf3S|jIp7jLP^s$wamq=ky_ zccJ^TRamdBu$;DGXu`A<2{*40FY7QSh2+r#p8V+|RiJ%^7sLd=%78?hFiU6}Y{{Ex_XqXUHMGi#LFD#c@O+c{~o$+U6euNLX;PK-sOX3^sPvLRR)-?f!Bx zV0(LrXN-m%q-ydqN2ojwtVtP5P5W6YSSbOd`GSk*9ANSB(jU9~OvZK_7|j!a;EMra z(ZuK8Rsd8VL9WKgG<7O&n-r#^oF^(!u7Jo5DK3=#MO+5g9Q*@%dFoB6Q`VqpYh3S)dOLqsQxK@op|si!5{nNqHLng-h4XgZas&cB+biO zT@Df(0T8-eRk}A9K@4`(u4O6&W1GB`xN0+EXZBxWTrdbxlN$KJILBhtckbhbI*1e& zJe>Fc1f^Iw7sSCw)_J(%-p3C5_XG2u86;*d3i7`o(g|#TT7azX_IuOb`}x9zucUYgE!S?VxLDNCy`C0P!b1P(n zKaD#X$IYueFvCBb`;SL6-S!7QA@Ky`=)M#U3a0pX34^C!yg^+O_H@+#Ggf!0>!@f2 z6KHJ4A3AnFVhU5eT66pE{tImVfQX`w*u%Cgl6)d-ZkemA;vn}Qoc~mP>i5HRt;Q2> z^!oG7%R7@D87XydPLJa}#2qC)+sAXFV6jL7n^=qG0x8q)xcJ9p`ZIuOdeiTN_^TYi z!U?!0)U0rgMOp0c8N8qX7Ugz6zPQidi$V`&f!8mKjYz-FVB{1Mc>iS0Y#)sF4dC%!GUWz)sjqp zt{cQ))|A!$ViUX+zeCTe{4Ph7UM8TRJ~1li%q<5tbnw&BHG#~etERmzhcxWwe^YBm zrSv+@g>@xfdRX7U;MB@Iz}w2NHLrg~KIePjJb2d#!Wmvh*n1z20H-jZZds#mJM-C^ zi$JYT*azk?6~r~PJDZ@bV~aZb2tZwkHHZ~(Lsq?$EdbG%0u7372p{^KgWJ(UfyV{Z zzNp*u>|F$+Am^amS*llsvlTPtz4~WQ|AaKuBsg|dCAuGA5S{I|GvQa}u%tFzY8r*F z1`$Po&b8UrOPWPGZy4+YN5mpPV@06OuLu>VYL2sNIO71wO7%ux0(^>1GZeD7c4rdb z1r*k1Uy?^1$6$#;Z&cb7w0HuN@mVkRf&@Pa*)(AkHQbdTr5KHZj zu4zw37``#ksx1K{gWE1w<8b5A8y&6@t7jChtMB^CEwxR7!c@foc)%k)kNx4Xks#4> z3zY6C@mx3^N_Nio>D0%dcl~{BZ57s2i)&3(j;#RmYi+kEdYzp3-z)p$60brE2Bp(D z)^?IAL|;Ho6@c|CwYp$B4KD2HXO)m@>ektpDoM(__Wq(~$1Ido-5#eCj+Gn~G@c7& zK)BUxkGeq2#WoTY8ddu`<`WG*TVRFM0ehm++ykKIoBf9~BzVrRb{DJ{zi&ib9OAUO zs4C%j$Yg+YT%jyJ9W3yqtL+7R=q#1M2;gJMM$*f^?T>x4fa%9@nwvo2l_hXfsK$Yq z1r#nrqi)-pbx;Gf1)qOk<6xtN70Y`ASWQ%8psPcI0TUzYZxRzO9H{ z@$cKbH|+6kU)u%PQx;=P^9uJ@>I5tHq7CDX_qzP-3HdietI7k}M@EN*YKlnk=4++4 zHHKyqpPjP_v^Rq<18anB{@P5er5ZRjHBt)8ygpG1%dc#N!HWsOVRPLG)nbG13Pit_ zOD<+{kj zqQ!H*OjmnuF7O!YARNU4nYt1squt~{7RH`vrZ;kJ@xYE!HOetTKA)BdYSm@2uT?9x zwtDXy``6t2YS|S{!DK)z*~&cj7=|Z39-amC`rD7`GU{OmznIKxNuIu$*?GafMijQ6 zZ~O3^L{&*e-}%7qy3i>?h%zO26LJ_bPLJ-}pHENNQls2^4!8XV2yu(YQE+X)a=Gg!Yd2f9?>#c= z<{?YZ#WXg(a6xC1h6p_9BDzViv~D`I?Tw4C5kgVd@Cg=V(w8$IESX^Ud$_GR%Kv7$$*zNBs3aK1p50lbT|?b%qJ1>}jBq4fAg1u1fgQ&j3~J)C#OEXnxJ{DkPEV zf^1EsuRqCFcpf(IZwK28XY*c^Ky{XUY5+N$L+|6+{hg^0O-o~f7Wu>2sbJoA#m9r$ z;Rqdx;;<~peYS08N0=Tej&W!IfP{{KO82nW4Y1YGJ^IAI1K-+!}sTW zMX(-0*q)16O?x6tTj8CcTR=+e`MP?EVR$Rat>0(8lmFFnot=H!<)`iow!M$Y z3W`5A`)6KRQ1^UwoNf+V4o`mf>~t)=XKqF)VKoCk--6}T*?)9^TII+^IV8<>mTV(e z`yebPejA&*E*9T>)<+D^Z+R%OzY&Qxc>YW6zEmt$$)#0)JKlq{z=Gu6cn+Qv7BIF=gA!U+n~E`>XZ8EWayZt%=m)a@~0| z<{rMb+f1c?V=CI}^Y<8O%$zu(ws&8G-;v$T5SX$?SZ!8Fk;uJKKs#96I4#wmnMTRA zpo-9KL*Dc6*{nvAnF=xvf#3TT=3Px5B!ON?6K*~9wG$oko&B||?~|-9M{IfxQ#g)H zqzUvNMqrbosOAezZfwncY3xC$l{#%!_iu0yoz~W(Mp%haecI)))J7U^nDR*1L<%E} zw(Z=9=~_3Q^R?Kd-j)6yl(ex>^cjH#$bFMbrwF=XmdG!%o!wbVOyq*@)%a>9@g~zb zfZOMK^M$}mAg;^w3P@oSRRl*lu|5mE*;R=x`EL@oQkUPsBG@hBj?Hb@=0t?A0hC?O z%ZSso0XAa}Mky1+-hxt@uYIsBw&1_izc~@T+_*UrM>_pHKih?mpu4N)&GP&~jKI_G zf;*^h#vYkNc+T>ePc~ZLx9pj@8DTaxhB^PfK(T~t40!S(RG5q}tj;95%4_^}GVYsa zUI|#Q_hIyU(}fpAQ({jCk%#oy(IUPgpBRr+Sf?mC{W6G3Fk-DdyM@BvC3x1wgFM~s zh@vyrL_K4u@aLS$fR92&w3K&}OQD1mO~~>|%)7Wgj4AS4myM6)mjM2K^Mson7uT<~ zMoixQjm2(MrA#_8?#k3suSq>XPi>-Bo}t6VoLKl zm7TJdEjAjNBF)>uq!2RIVa0M|Op&pa=9$0tUH>;wsQWAuD^R0apyO2)W(3Tp`(N{7 zFJLm{1~#BmVgD>CHjvwP=DSx0I7jhNap)k#6BRXasr^rY{sd|)(paQXu%&CwXs-j* z#Z^-;Im7RJkxu>(u6W_vQS}1jVLua;{?5CIXNw1$TwQpU2grts;xDK5(%;$y#CB;E zTl;VkczlDRD`(dH#i30ajk%gg_-=`5e>)%>7Ja|EY#WYplCgYC_;%1lK+1cxGgXtW zu+B>(^H57!8iL-y+~9KqNH~>D%jv2VJrpW5FD3626( zTSM`rZ7RT{A~lwoHHO&HDst!Y|g{30Q7DFZ>TB&hL5N^Gv`IvFdx6T z4ZEz=%=Yzez?>DMG*?|^H-8`s@$kgZ60|=iUMf7*|a?M ztln{z&kPMW_`Vl2p+eX&GsTPI3Mr-z%qaE}%dt@(o`rh|nUGC?NEe%n-#DlFZ3|G~ zZ5IFZ0#0J3jC--5aU{rBn9BaVJA}m_TUnB$097lJfS1{tucacDATj^(9vAJ&)938C z*cTX5$X|klGK#@N0_u3_jb8AY!w1Lju?9+{^SGOiB?9l|<3vy=-PS&kvdDfpjE3Jg zg<*mzc-6*g-JZ>6SxGd`kgOUh=K*y$7CvZ%cU0}XF(NQjW^M{;Z&giQzA)#KM>HWO zdv*&w3_D!aCQC+whx^;*ruj8}()<|3Y>mpIs;1bx*2&~~9v%GKDF>&`KP(fLB-+qW zWuU`h>I;$~m{k0fdhATIXewWyQ@ZQN1#Ikwoi>y&i+T&3TKn zWfo+_t40pFt7$T!cC?A)#BS?|CFOiAbC9XZ>kgMJUD}9~#zeD~b8XP*8R4mxnzY*! zG5o^(zIF--w@h@wM}PFkDFEVZ8XK!IyWc&gp;xe7)@_%%G2!MddG?VJ=f}qGv{VP&aiFB`R;3UYE{cr$y!228^>eWa1ZnYtTmzv4RB@yZKd&x@%(L zSjNgM7~~Ov`lwF0KHh?;8&D9cl0PL4XZV#ZLw2f}vTi>!lc6Y+lk@*XTe#q#V8P7GO%=Lw=J6$)H4F7RY zTD`=+(t;CkLLp=D;kHKFqp_(O`>#WgE9j32zV%0!28yk7%=a;ht@O$k9xE}2sV{!9 zNiX<(^aI}BNcZ|)zt>YS7SLLjYYNU@k1g1BWV*bg7w;=nAr!59-CQx8H`ipXCoZ1% z;O#E=1kMf8J#9K%zK2t%2r11V7ZG|ZW$=Mwgqq$+2_N6IoZ}WZ&=;zbpNl;_QFpXw3W?hqTyVE8 zz%?Zx8G3snv^1A{gA#t_&HwQ&*N{R7#N8sn7KZg;0h~ zXD}~|RNr>|$S(Krz z$iVSEj|(GNr+*`tPu^zwZEM)FYTiIZ=0+ELL6*`jU?<~x`oJsLSIBt@Sm7KAm7;)U zmZhM$ou^fuc&!Tltr`?H7G?>I`lc}&`NnS|y_54atA<{jr(H~owOG$3m^MeO#58Pu zAl0@jPP1DXMdek_kg3q!YfA2Xs4$b|j(yy{@h^RH%Ilk?R`Qjlln3D&6$tN$nCmIG zq6gV#4IR_6xqEbTS$$$_q8?3k;7MU#qYn?=NYi}iq|+PDu^q@`n1#KPdwgRH)Sl# ziQ#u=dt_|%+M80TqtEodDdSMJe(NPu&^PeDR}mpzoR+a2l!grI1(M~I!CaSY@#B07 zQ|+6-ir$}C4^V^ms12Hn-S!<6_^tbNq2QDo z-x;oKm9i>^8+RD9m2KRi*g@A-aLcj^QXKo`D~Pj=O}L~i_kpi&05HrWcC(C&8n2Vv z3bmen{fRmLM|9OwF%T8s2!Rn>4ivm2VejMHSm;H_it+0Z2V{s#gAyGWy(}!087ZoT zDSM~oWa5pwV_X`O6!}z(%|%UM+U$#xG%_X8dBi7-D-D(ddhJHCY7o&Sil0@nBFof) zRTe*v82baS8$74q;6DuPR@6AUzI+R*h)yv!T{jS&`l_96xf&y|$$SKXyRh`$vs0Bx z@*vlg0P|IhuLuK<{M?0HN09#XN4Oaz)=gt>XtpXb(W&KATUHu0F+KwEHHK**N44Z= zBjMYdg`w1erkDNG(Nnd_L^(8cQfi~`)E%fMsDkE%_^1+AfPu#zmG>H_T zm4GOv3Ts4m96~h*q#|{lbYNZ9{meDyT5Lbx^#P!%6rJ;Wxa?nIxZX1XPrH3G^Y+%t z5|ezGp=I3a3dr@2#nu22wC2_Bne?OQz;cv81b-UC81NuFDCEaG#RQAbu287(?dy=^ zY+Y(DI2f7xRyX8A9{+&XtG-Tf*Ll}#NDrRB(=Q!3ll+#xmKm`Wq5tm^UdyllR#(n7 zRs4Fo#`pA5Glna1`JK&_JHx29b$99q-@@gNh`9G>ol9OBAi6?xRy~^(_@-X6Jz~?y z6n`m9iK+Oq$^h``rOgb=kQiUrT@HfnE;E${sn_A*Q{^#e?v$w>q^LQMGKR4$v>0#* zgMjWb0YuE0W(Z}Rj9l#J9)tuYpeNhkx85B{0Gmd`r9+HQPc_6JmMJ*AHo^At@HYFp z&|7BMy)Gm_^=)NFYnEa_mg|ygm80rfoR^yE(0Kx{TV5~g1qFCpDW5ufjdgg*+-Znh zrv-yvab7oY^nihToQ1i}JhLkTi)wFUcac?jpbE1or zQ{Q9_BjUM0_thGz++?aJTcrbYL*8h*pWPnmYd>!f-1qnA?~>3{*fi5PpmWQIo}amB z2Fg*EfdI}&H@i%Y1pz918xzkL_S}g@%WLF7SNXPWgwm%^B^pO%0a3Rx<@h76d0LfS zoWsKS)e11TTDT41eL^cmi`?B)3QS&rXH zsu^j5>h1t>tuVvx$JApE>Llus8*i3we+y;?6QQ{J_+H0CeR_j?8~y|00s0=<=A_P9 zu%=D7|Q=~gYalS&=K#_R`HEGnEBWvYko?^cZ zXIWk8-wMh$@6KS3lnWLd-(H{a7b*z1WIkz+E{b6nKMCP@CNB!-s-@h@I@P1J`Y}q6ALWq%ZB>j^3%IEnvlVcD1Qxb)7FXr=D)XKVTi5IXbkVl3x&XeL}QFiML4{ zxVg_Zx=lU|g_@RY_5AL4G;;-KA8&tkOcBVKs-<15edh87d*w_o>SZrTyBe-*A2^-Y zpY8+tQX_<{#u`KTwl>=@2s;uOJCJ0YS`&J04XMUo{LWsUY@ozt8s&^}mfY{+gsg5> zFJZpKMfA_tVtjQnGd6(q`KUYBZ&}hFZf6Fx!@}Vx_^A&ju+&kHZ*H;tE@iRtnqJ{s zhKD@ zimrXChL!WZH78Z#;>j&4-Yr*5opS;HX4DqhUg~5sz?B8!l+N#^K8)77xmaG@c3T~P zXYr;VNC;*_=`rwb4bT|J3H;_z_an+_D#!vaS~x9LGHM9)8Cb?Jpbs`W968)a#N>_; zp~g@z3k(COYviaP%$1mh;k7*EQW;@ikaK9f`m+}K4c0t?k`9l2Z${<*a+RiK6vX+E zJnXZLp)dtoJ&j00A;V9G%N=;Y2Z6VB5s0^iYg0|?pzTtF@G|D3@lZ)7!Iit6z0+rU zAD0+~;ae!a<}S%(3Gq$>Wa_6q40_hrl41JG9@(c<-4-8aWX^>4PzPw(Tq^4~H3xPI zfKQAd+7+@s-$vv3P?G;wla-))qAX3wIpEEY$(wBjPD?Z3%eVMs{)(Zyk?I!KHSR!Uzg)}IUpza92q~NIPCp%ZOC?*m zZAtP&QeYSH<|gpWn&=Q{$(c6K>PbDEllG+~Q!))!k z+WG8TQv42^U;BH=CA9a8jR&HIuhu1+c+_6n{|^D~+;gEY;rNr*C;SUKfQz9LDXgk$ zb*%w2{?Gp~(2wsD=de@Au!>*S+Z9Y;o(D*`9M`q~MfnN9`?oPWxbZ_QqYizF9dlhV z{GrjhpM;c19nh&44Nehg=b3X_jxHLI^-k%22&hb2jR`Bs5c#MiBYRQD=ws)|h{m>; z64dTcBhvQp;Sb}Q*Cu2h>_E4x{ty|3&f^lNLGl%}jY&Uc&{;VF|57#o?sT}t$M#Nr zm>#?H2f(qL0xrQ};^mD*qppo#qFW=)1sEikv+g!W(hT3K-&^1Gh|5B_e~2}DXL=o zpi=_o2vI_$M7h9;^Ifw7(1suAMrr-@CM$_ASewItz{OBS&}H(#zVhzlA7=@4SrgA0 ziM2!OQ)oKyT;C=X9li;qn^Whm7;%{Pm4L3=8w0K4tv%W4G6@1(&9or{lB_jPf$k89 z>;NiSC6OUey*NP$VG3Fztqy?+cE}U!| zg=!2xy=G9D)4IdW&CO}jL$6-+)E@q!XWV)$Z+(7%PfhY$#LfOU=gU@fC zfF~9M(w_u4Yo9>c;)ZEoP9e}9=@x1q|CIPMAqhFAKce`@4)!{{nHbLn{LHo=f|S@R zZ%K)i5|2Lx4iW1nit_#&pj+Kxy@gI4M2#h2BN{Swp1Vkvl^QR|m@@)QU7e!Kg~GHo z(%{LcTDxlYAJZqn3MAl7gFWKbPK4TVZE6OP3*KPDQTS< zPa1vmMneqNlYeX^A@~{DaJrg2F2led1%NdS;J<}YdcMp2a62nTJ4}w8%oQIdAS>GN zyKP=rc!2P3&PqV&e9ULK#WNi$qA@WInmkkw_b{}1SxLH(4S#<<_J-zumS$C1Hbsh- zASf4tD_G-yES6UfbduW8pHzSC z;-5B_yST)Oin(gNZ7)*iJDC(S#%tN{qal&DiOORHY9>y5(62aa0@EmoYlt_J@_Om3 z76A;SjvPL`YI$y=pk0oj#;OV5#ntg6_RpR20PK|4)j4m8|9v;SgD`BE(m8=09rQ?L zF;j33b{kw;q=NW!21|&x!Y#yCwS0|AoAWB&wGUs@KY=P*v`MUlR7bW!C^jv@@NXLd z_+k4oGiE;`{rHJ9^e^PhDG1tt11tjHd9!$7&B&J-^ow&#M&7ipd7eyS)Ms^@M8B{0 zz}Mb+U!L$PiFexnw$-1%4VH1M2;QBc5)uQSg`hPsx6i86ihqbE1)hBDEBWm*DI$ta zDQ?beuA*w{%SC5yOoa%78w~7ReC|M%BXHjh0tGUvQmOcy=cWoW*U%KZ!4cI-D{n0 zTmTgzrl;bTXm@-zbnH!fGM+$vp>ft9FT1pbrkZoOngA4-MtK+1$7SR;sagVzDXzc^ zfn*pEA(Zk7FMX60ytTsNBL;&?x~C$(XA8kC0wW|(lm}8WN9@ne#yQ5LF;nJ^Kbb5E zDk#oY_Pu5Jae5Y?dBQGlqx(Bp>JDram?_*c8A88o&J+gR$mWy*QmvFvq>_p_O$hee z?*^9jb1oZ>acoNu8F_hX3IPki*hiqqlU1B0Cni*h3=`(pC2))m*w>4sCF|dX2@PEtFGpQ=zmZTv@bD%J}pos>VqZ_ zs4ptk{U>z%-}CFgk-j*H;^8r7Dgf6HL160;_@KVS7*H;ogJ%D>~j$paQSP<4h2(Qt0-~9k7c(J^WdBai4 zO3mF!dsFmiO%sLel@BJG!8-c$nwh!=?os68t;k&n)7?rFmM&I82^`D!c?Z z!UkVnW?KaGX%W;NHvaBeE~shWxqY3T9VQe!(1Gr2!S`S|9%w>HRuhZ zVvAUa1Z2?z66|3sS45%Bs{=hWDj(EsOP}#JQiAbB!lo8lXi2zN~l%QY06c{nA z)R!dhg?ZCp8jJz7O%*z?Y76F6jR^r)qm`RMdiXz4+tu#zK#@n;bxYx5Q!@7x zWkZ)tVWz*VW*)@dp6~P`u8?^L#9T` zLElUOWA=-p{y_06V6`iY0M{o0C8J~*y4Hh706>3&OE$qJ@$ucVH*xu)i_aiQ+$sKax6BM%fM=`IxAyWb*RtnGmIB`TSNi(#osO6k zOeG9{`NpMYyI zG9S=FmMVW-q5xBeMGkXhaZQDdg7 ze1C4)OnR_o6|1vO&%FgE*6NM+V#q#HyE{Y9g&(Q)Q1lfcD63W8aI1Z9U8@I|2XTzi zDz3xqwMNOEflTspK!0!~VFw0H{{V0M{AYS8jK-fLpYNFr$N@Od3vt zj~dPOHPrXa!n6*+T?nKyz<7SBY~5G@IW88~GdM%E)r$>+TylY}YA?58&iBA>IK|z4%8r;BA7GJ z&|FBm{uUIlNiwm%novjwvERFc3iPJ;rAd*K-`0JO{&G=c6$Ca?)-pMSn5y47iX6a1 zOa$)!*#hBJLagJETT;DvM0W_t{3;rytXRY-JJ=RdG%tN+f~W++4Qt~kRbs_UZL1^W z;>=N1j^&UK3$pf;*`zL&#+j^D1GlC!Xdft#D-Wvm07e#0{ZGWaptDixUKnKcUIJIL zl<_WCG=9G_Ypk{g-IU)4#&Nzu?%59o({TM#G5U zTeP4@Ep%ZdP!V6>h!R*gW_verx0e8*Pi@;4@jP={&n_?p2CFpEZ^Q5Vr}r0%YNTt5RM2qQkY{z%U9 zCB*sy2?Awx8JBbKnfgQk+`z~vSo<~#C~{STJ5e`PCmSwHh2_qdaioYR-ID`9Wanzp zFgByxCR6&&N2@D&&q;mN>`6PEJ5UDx4|r^bQ$a&E=td@<%ardqyn)`!Du&W-zl%7( z(`ITK`gQc>s^{UpY7F%9L>cCK=KY{OV;deedK&Jb3A{%R5a;qt6wpxi;k~g_fA$LL zc$@)}I=j>sxX(osMU2Z2Gv4$oQ$dIdIxh6I^yDYKgHkJGpkR%hXgGcA`EgHg9qZ+V6Kk)rKOG*;Mt5emN&<_Cb4IR zMSyQ_hMylc38tVE_*CyQdhgetB&>L%un;i;UA_aFAZvCe16e+U>%weD79|&O!Ids& z6;P3oGzTb_X_E=3VbQ%jN}7u|9u@4b)QyoW_oDx=y{`(Wvfa9+q(iz}N8qzl&^mnXp(itEooj-x&&{HxWot`kzh& zd|CciPnrM8#s2EVRg@NTN_|xCjF4nG{0ysRsphDP-cCIM9#h5%7!MeLgB&mjgL%Kc zu7A2UtTm>0T8YqNYI{r@&*Po5NTE~XmDm$X z!K|##AQ}s~I?6CTj7^yiP{A5h(^N+`jFy6;UCG+y)75`=2LAS>(~!cNl(i}n?)F4a zz;;CTlyfArxFnYwCa(fMe%Fi|pvRTX`n8g?pS6&}Mp(GXxC24c3-|>lWlFpQxc&1Y zAHarD4GO`VPp5`i(JOy^H#>OW9{shJRvPKxQa)YKVd2T?fLer$GP)>`L%prfJ1N$>o_S-d~oUoTWjsg5>7cD zs~n&0@^hfJnuPKCwViZ-R-`v{KC0H%sPwP>gU7KPQm{mX5R8`@+z*VO7KUGwu-&5gGIGy)atXt#oU71ea-V08Lu0hPbJM@ z<;jPNG-gY84`M$0{^f6o@;u1*3~_L16ype)6*OLTEBC)%I}k52cdMrtHVdxxC3qTX z>pO?pWV$`zLicEK>bs`edgawsgkG=mZcj4rTB8vh}*ho5+Bs%jJAs$6?u1KR@3fiFXXEvdv2M$$coH zJp1j7#gA5R_vUdA4hBw7R%7oW!8zXiX>Z?-8O%`2=7v_MQ2+Mj@AFvSWxlH2+;chL z2#_brd1BBwZvS?OtwllTN_yb*`2R7TPfR0Rtz&&6uY{o^!lsIn-bDw-~U`|s`5Fr77P>K?%)CL6CnKO zv!2d_PHEeSU)~sNl1aTsb&W<$3DR8x*>B01aIwfB2R)oY4hya0A!I7TJ)Cz!tPaJl zX}WQyq-n%;s#J6jALj>I&ejz-(%aTrWJ+{&HqFN>u{L?crH%|gUj0&kSly91@FdZ3 zDD6qTK`~Czka{^U1$hPsDw6A z4#7J(u*>5Yk_?Uc@uJeZoi}oQZ>UMa>WuFsex~S_Krb#YKfiG8<7Fi+%N%m-mujwv za%J;Hpsr)r`_z8SomwOn@V0DH5j@dtnvT)YJ;C^ifD)mpGM|!G5&vxGf*NlMozeTEP6pVmKzX6t|E(!zwd!YR( zbmD_py^-8TQ&&~6x}oEbT$}sFx|xVYN5x!Kl;E68{_h1dxZefqKkf}MzkFUa7Jq8! z?#Q;!@oi-fZ;8L6Nh+VuBzMo*C~P6>S_}7gPa^rJs1ekb0lNEb=G{dd4vPl}fnJ-x zHeN2~wqL)Oqg4%{al2V+GkLNuuS=_9XM}{%_Ve`XT)iyq*w@`id)%2Zgy0LaWg`&` zw{^6q4xQ)q4uiWYjtMPd3Dv^EI9D+)OvQWL2($@z-2JFGV!b)sj#0P1bisV#gR{_E zcQHvS%8##pltF9x2%BGLfL(bOg!l#5%qPMvHf3qieD8@9B(klmoY#6CL}4<3-QC^D z_Z7x<=jA`*n$VQ0Kyl;AI}KFADyBC}JL|~bevB|67|ik%dKMl3%-z(~Gqzn+VfAZgrj7pJ~iTJ;tUB9<)nCG`0jwbYZJ!bvITz3!+Y0(IaOeZwFG7IrO{eehX3GKrti5a@X@sPS&E%tp;4FpV^RZC|+n)ZircZ?>-mPx4{T(fq5_&h^RN=*4|aHrn1!t$T)UWG*ymr zu>+PsnsW;*8G(g!OgfKld1=D-rV_KE4ID?Uc>(Or58qBeZ4_zHaIDt zO~(rQ3I&AFy#QOy>>Aayj-rbfuudfC07Ao)VIJjaPYkxv6@YI`XNgMAs}K|% zk28N@TtnvBzt&3huU2Azq5fb|2^vdfDy+{M8g9T%;uAuDg&y!#U5PHy1P1IE28S-7 z_|NKnuF7%#|n=vuv6+kJ5-O$882xT%Iw*J z5yp9pU{*(j?uMXF^YZ{GsLyyt@VUE#T-`v@@XNwl4D>jS9<#}H1Dca|aul@R0 z`^~@5GB6+jP#I=A4~+R5GI*?-O|;QHr=GGY@YveCJR3K8xq?!)mjyC)392xbZM1hQ z+8{6DdGKtd3RK!0Zb1zuoWn&p@cBEK%+(V%q1`r+7i&qw zSS#H}lojZAgGIxLZxEICWd*IRP>dGK%Q5vc3W5KQw6qK%D}f6l>}6 z@YGH~q87AB zP04Hj#p~f8oxMX?ODr%7BK99WDlwWyQ2(%_|Nb{<{LhnzX9!AND;&5e|77p{4bXPO zY%%P+$^Q1Mf7Il}I$;KfHw>$A|5o<}Unh75ETlG02gXMQKi&UW^lmrc&BpQix?piO z?W-#lvxsJjYw%D#1j_J;R=v}RSUlyS6dL%A)WI{nR($`eCq7M$cLzL|BLcqJzGJt8 zw_i^#b1!c_4sQ1|Tt~C50Ehw4PzF6bnw%H{USbf^BN}+L=ea>Dxr5qC4^sZ;=fAxK z{=0$XcAUb)9r4#&|MexjG9maJq10+R4Ca41;6L6qhz4C}u`0r2cNzbD39Kjue|$i5w4dUiEBxC_a{0$#LC?QNv*rJ3Ma)e3$)(vz{IKu!_rHRD zTd@tWpmIM#U9tao34C!i6)`4NetOq`|0~!z2_A$k=<;!0&>vTn4bGp7%&&i(&VM~X zDr`Z=TITQ!e_9bgIDZ?l!?gdo*dV0Gs$fAI@B0xH{_myw-(v^6fb%yts{j9rq2*klng1M2un_D7 z{7em%;XebN*GSDh13Z4e4-df*i*Vor%GUx+tXBZ}^nf!O%v1>neJSP^pnf@80+|z8 zZ!GEL%8v6Ym=e$h+9gzmK*6J8(3kv2;Gv33GQLgT25jh8fK~$yIN`sFO}DYN#n4oK zrlsTDL)fLE$WC~5X1h2R8Uh79eJmhs*C*jJm0ErY*a$W{fGEAzCeN7hZXw|W%uxsf zeolgz7cJ3Ukpxm-U4q~HUU zWeXYkpJ_pW%TgEcfG5HhI&7~22M%K?Nv9L=c6yf$lGqin0<4o^9@TRC2Ueq?ph@-Q z6KI(OHBSUEF%XrRJG=&B2z<~sh;;(*rl+Hr zJi`x5fO-9=%GffhwDhfY8}!nQKVVm=2?D$8@v_wC)o9jE#w04Y2LC>`W*?lnw?qcNt_U{XLhWyn|NY3U*v^ceqy z+{ejL8@dN1-(i9~i2^+31*cXmTinmnZ4lJs|z&r`&!&e^J!vBx8qcxbT z=B{)_M1TjGLy2#}tzaUnz9hpklSH_Sb$F+^;WIZjRbk*ZgJJRL5lsJUnC9HJHmqw? zoVuDT=DFam?S{ER;R71HT|oa%Vwqu)_Q}n59xWgVmbv_UVnN6>j>m)(Pg>|bvsR++ zrsT75No?e&PK;m8(`O?krA8m2E^r5SkMFH7&f&02KqZG~-gQiP1q|}R1eOe5pTN)- zMDiybpgHD@_zPU8XTAz2OSbUhMYdcTW>=qY-g{g7Gi_R@JviU-n$l^zyOp?aoWIZa)S}gFS&hYyp4$e=fu?a>Ohi(?;Nq^ zw>(n z?w_tEAMRRhC}PCq`s^Nhc12$NdVfY^)K>d}Ij`+Z9l<$eibDx0WMqISX-vo3(~Y zaJSQ-hVI)kC<>&A(inLaYVI`r~iplgOkl=oXP35`quXN$gnHIKFUMEvD{SBf`b3- zd}C!#?;Vi4PqRN#AzyTnZotXn_@O9u_)z%i^mEPWA&m>qwA5N$*k~EbG+oOKCm@!O zfQ@&k1Y`)4E-XGflDOw?6B$=n=z^*Z8tEW)#myDD|CwHE)|o$%+^gIsh+wu06*n0s zxc;u<9yEm;;J=!k>Dsbnl^oH?LGJjknv!Ap}_>85pT?LGo-f`VV;TPNy1 zfM)U2WoU-&htJyv75fKL@JBeCQ+D+uM6h9pzh7Paboj#lH8UqJ^Jj8Nmf!Z_TJewP zmrW=ysfPqhc;(2RH3qENMHYScZurQ)#2JHf4GEr;^RX-A@3D3HzCZPX=kcrixyYK` z_N~3Ic}%AY2xhWzyNP}#b&b<$0+`F-o{&a*8?CCD$PiQc@^k_U4=~b(l&O4&= zj#AjGI=b8yzbeaZY74s<+NRelmgt^seH$=9s5qdCzcm{{wxuzG1();;(BncJ%JuRk zQs=%5)ePfv!Y%HS>5Ka&bTW*eBW?Ffe=O<*nC$gg7@fuQH3taDWXPpNS-fm9ZKbc) zIuOkdOt%{xn6$Ws)se;#kr=mveSH-FWyj8ELTeaS?$@i(sp#qLm5$1!!Bm^Pr5j0(!03 z$x0d`zPCU(7y&j(zG1+bIGSt8y#){rXFh8T#66B-00NxLU%1@FYRldK5d#s@k8?AP zy-QXhgE_-Ff#@9uv_vA6b%T$O_Ox2CZ-F`n8_W+x|@x*VPT*6imPnICRj@v-kuo>}?&_ za+vq4LP9`oQX2;V9@lo#6lJ@q;YG-0tJAM+*U=hKY}@(h?3+b4}PJ+yQ1$2;gX64gEtlj;L%zZN<$hm$TF02}9O>cZDb ze|-B}-0=a)Fx=r&5G%WtvviRy-~1^8x5k2Mq2UV?BJDrH4FX)RnVhhgn%`M}2;O*5 z3sCz!twXQ>^v4xMf+N#CzGM9NpbvYq4=E@$wpMnsefZOXndv~4GBUbN{!cf6p$yo~ zIo@-|u)?GHDK7&(IvS8{>v{ns*LFAIhzETX43tnp`mQ6-R=~Zwzn&`8T8%5_0WNOi zA#lJA2eXsUKlWXC>&Y2|@ntK(g%=I5xNJ#)>J#H&z4-bu{F$~<)#bjo!^V4GNa+_$ zIis6hawJYn(Bx_51e)LofW8Z5seOP0#tPs)qbDo#>awXO5cOv9DZ@#gfV&+FhT18* zl{h<)YO$Fz%-@t$PiT=+`|j2{jfCCacy!e6Jz&XHAoE$Ec;K@Ilph`+`#>p68ix zqZvSgCYt69aGrg0Wp)I`4ba|U1Ff-}j&(s;rbv^z%*K1%oNX$Yt7aDfTDb1o>MRq) zdr8#*K62{=(wDP_S#j!%=&KrN^WG&^#x3~pRhF4hdwcsm{)HAox*%ncOyx=cjJB@L-T!G&po?1F(#NfPrr{K#>}5bhAoqQuXos zAl0$&12oQYFYxJITG|GL^b{n1MGf*xm!qDYfH+9-3ru5lVCNsC>>>^+$#4ViRbfkD zEXE3Ou}cW4u^i=6y})n(9D;bzOYVpXMRUV+AAt)E?gu8iq`Wi6A!%;V{-^hetP~R? zkAThC-bZa6i&U*nVDhvy%<`+88Qu-eXaD~0;J(n0t8BEyyo@_P(J-XPN=JA{q=!s`TlYMG?h%f+y%=~;4>U0TK(^XkN`qEmp;O%&V zL8_AkjGi-*^c5u1f|nCo#$S#Epq2MGo1zoEFnd1JrLfjsbC_{2ITNdf^OR9kXx zxF>F$4@gR+Th+#nV%Q2q(^0!VSROZg*@(Gr1-^4DV2U9c5McYjc9b3A7kM`ZOsdr7 z9t8K)cZU&&;7iFSY=Q>oyoKuMN03L)AAVW7eL}`FVn|}P0Wzh8B0J7D9@jx##&{gNYQ0f$ir=} z00KQ3*2)?Qw_Q#>sT3r{!$}oE_7;HHO#mY_a)PJI3lG_3q@PFzIZ1|XFB8}S zyi_Nso>fLF8-fYZ2Z`ee3k^@AIwpavlyVV7n;MV|_Rb#rQCaeRdCX#DAYJEM9g-~s z^2ehR;I-|(a$Et@Y3~*ZXKbH!U=St?Ic!J7*kdt&Pulu)F^v4CL)iJ<8swEn-Mfwr zp{WrhCq_e%v8(_-JSq%Vfpg*)i%qW(8-V7^o;78pOBTRE7ql0`UJnZsS^7hpMMj{QNaOTutsrKMbPlpsQ*;ICzKmE2o)}!t;&e-c-u~_r z#Rl=;Gl$jvU~Ic?e`6u~3)gs0N55Fs1}8}C4)`1-^R9qth^#CZ_pE{Z<@S?r2Cme| z;%p(N1B<{?LC4y4!=5pljRVjMy}-yD^dhh367!{&=(;my#?}>LH{6KFyGIDM zMd^(7jb5dprggP3BKi)8-~1z^`?d9X}xAo_|wh*<=UC~-lvFIh;-=%z0FyuHziA`H*T}F=iaywkjgCa2wZ&R(* zjb=*p@-tP)?FWT^-8tLH>+y*rJ873;=fc;pqD^{2qr~N#N;=z-O7;DUy1=Xtl7g`L zJJi%HZH_uGU2j9EZ)maszlcjpcxSzUDzU1(B=hn22R`r_l7Y|oTZgJfsDLgC!-}zaTYp)5~XEe(a zGkhsiA1Lbr={nCmKxOJoM>zr5q!OMR*RGS&h-2+a{1>YkpEv}{pc%{< z{xts7d63WJ-VN+-k2h(qOFq!HhoY!g9l{jdRD0Jl@m6QrKb#IQv#8TTTe4rH z88S-AX{B(u5&57|hEs-#6dy?AZ0vEkF^@@8?edJu3$SmAjCQH)vX}43$hB@nUF-1U z%B4+kJ~SPp5U@kWj>Dro2IHIX-Wub+QDKUsRSfAHH(po+7I|cxK^e+@%f%)&Ob;%t zF)6Gjzr{cL;10lE1OR(HWN1&7@OmHkUf9(QFi!N#{V2h$>l*}{2JwX)sD@#50-#Kk zmnx%}L8NP*bXcEv%SNTTc{wYB5Esj{9WIVDL{f()c>v;Fyv$%TbU&F7NB2bah z>f|B56Wko5ve-Zt9J_!U}SDISyi3EYpSlvGab@XjF` z>$v_A^J)oMj$gf}%%<2~ye6cHdpM2OW4rxzqx%;Hyb)=P!Y%K5^cI|H@C{PO<-3yI^>$&kf8^v7HBO2bYpSMtEiiKLV96+$fg3SUbyfGW2y~vhLLAyQY z9%93H*BAIPc8;GPFtZ=DvB|bazm3p)_U7t66=|R&2fR5>R=9t@*Abe)hv?(577?IpT!7y3|KE!-5PTd~>9q9->#N8C@Pfw-Dn4(4kbv3%-a;z-i z#@;*|^zTGt>PF5UJ*(eAefTUb&t8gXMsNcl6;F!i^_UTn)X0;V;~7!Sx92~*K=y_| zT5gY;yHpg!{FFkHBn*fk0#c;6$%~S2gO4u-uby_j^2KWbwIwMg|LSw8BHCqh3FwwqY!{#aV2i8b7hx%76#R+yo(ot58-elJsxFzKj0lk)e~gg znA zTxdO91f8@H>n+3FJpu;XLljCVCEdH)(!^(T{@-&uJ0$abfTN)_e~)ggoy8eqNWgBv zC=|tmZlqg|o;pANI*Ry;^)5e8}>I5!67l4{iCm z8Qjo1*^ouqy^Q?rbYy(roFrT+N-{BoXj0L&g3$ZuXToAoAG%ie%(m#w! z@toKmeUty3_FVW1|2BG|*L&tIAe^aE3~{E}$uu=Z*s>mPuiHGBMmNCk$)gaOHJ#ph z_|RoBS89gR@oQnoFF!KO9Fe%JVAMEMr;&b(M1Oz=dV8g0le2}SFNPP}COj$NTgq9m z8YgdU>>#ez*)5c@O{(vta)G*r1-oq4AV(%+Flc4;W4eLq2sim;Mspfm2o>_vP={am z;g8kvN!$Si+jrhEY)Ou!gQNzt(xLV2yY&p?tT|D3@NQyeAEmDOLuuL9HzrcY7mnaT z)L3IQ$}Mb*Vl>4!`XJw}(u`9l!JnRbvw{-{F^m+je?3x`09lQ!=_Rw3lFT}RVmhI7 zMM}PCntSygn#kN--Ij_k*NhT@n)Cwl;Bp@1Ont7$w0xLBPRL8TF?SN*zvXA!=Hra( zVdh7QNpU>f=#RxbmZJ(-qY!XH)|j%g!jtI%uyYbZvgZ5E0&|p0ERtvig4mMsi76a; z!VH$#+i`3O4Mv<~iQ|n$CJTRj>-IHok3LAG12;mygRm5{jTUD%bhoAr9h+twD<_Fk zpCL!a-|30EIRtN(@3G#+X@PzSvl!iHCu7g2EJlBIR5Y*Q-*%;R_uqKa60a!ZvIEF ziBO$p8XK?RaEPk2a-t=Jikq!VUJ^8CJM;#>yz*tyG~|0f^=lXOO4Mg zf>=55`0;r+E`__#ZWf&pAl96_PK6uzISB4@pZF1(*Q0$_sF!9r69YrT*UXioloy=X z@ES#cfJR1F3|s9xNu!-*6mAA}Z1Ks@6M5ONdbF_7GZqeR(NDknrIPTq#7h%Z`&q&{ zsRGSYkDaMD%;5U?x3E|*U2nf|!J7wfD1=^2?(0&CO<_meID5dJ)` z)uq_E5^6@54zZl->yyP@>iZ-Omj#A?S$ai0*JSZF$NKUC99k*Th+>hd}^0SXCCM2SH z)e~8+<>oa!p86!qGh0>KdMLtG+ly_K^{g^$I_dEw=#yM{$^mkmEmmqUQsDW`Z~0kk zjDEhc+*6KC7py{-jNJlNC6(%h7_ zN@lPp@N1`Qz7wmpsh^ zot51@9c$VI_>?mk)-D_$zzd)ttHK&}^LcQkXgPk|ekV8?&qC{$PA=z8_`)CFN8{Dw zkx&o6Fvrg!LCo`68F>0K7SD21*+3CaGQq+Pvp4E>KNEmZPq1?fLs#S;AtvcCE5{OH zl1TKFJFZtV7x=velf_9EwA@;R+oqHGJ_Oe)eCGUq5+z41kWkp|Erfx~Tms^}3duvB zq1O%_mr8B~wDrSClO?2_<~#9z*&+Hg+LxjFTo@{w@s*}2>-cT737Bfl5~T&z$5Gro zzx%i%Cm&~#Fi#kAaz^9z652;)G)x&rA7AS6!<$FL^TmtP?Q^0JX}pO#%^1rIC>1p= zq{}PwH7CB@MqkMH+d#XxS(-u<2yLP|qGUqhCAf;1HBLjmKS~IUO)B#%`N}nbt(th7 z>tFbeIugpNU{FpSZ64#h`g9X3i%m-<>X974AYKl^D5B*;R5;DlTX-x=a;%uZ+0Ye9B-M%hI6ooc zxFp;3=6JXrgUOOWsh7sXzwq4$^26cnTf2jV^!TQDR`%H}^7pqHEV;itc2>0{i6St& zXUP`mCslzT42s>*6h%!9+W%6`T&pWQ5mW86|Fm9haRZ&dt#Ql7_5 z=u>_OBhHU}*Iw~RB_f6oQMp~-5xX9|w0xn{_2Q3_A7C?@=ZIsEZnx+k@mX}GGb^Ov z%nmlbE%dwlo(^}T6Mi`^iPKZu5;y0v#!5)t6IuC#n#=2#j`mc+vDR=~X<*N+hNG(r zohJX?d!yUOPqttd1zArVJhxHy!?1eo__w7wbK$vue;f()`kq{y;|G9|SPzzO|Js13meQlfD@jAm;+uCxtKT^89qsJhlXigm?OAm8 z%dPah9H#al+5-ynpzd$Vi|OsZ0wKlqXkA5yt!fF77iB+WkkPppbSWd)aNdvj)ZXKa zs^K-q))m{*Z(fFCcj-7z8EOd1=Uv+V_B2E2hj(`YP4`|AEYd;jM6x`CfD{3#-j}n~ zEJhn=YSR=@I7ZIMc4O`saTI~lj46YwU}nnm6tn8bc2Ba=`rW?8K}e!carVk)t!#dI zk7z2McA|`!mv2=Uij7V#?5CHi$jh55x(%E3P&vJRji6QvKN>y(eq2~B zjGz>h5I@A=Md@86t|5ytkPqc+yHuul4otMpx#orWy+2Xc%d_opow335GMb&^N-Ine zPY^Np`9zt;#cz(8JscLL5RTKBJ(AgU!K6ynR{$ikb{ zH~W*SPwxF0VzLcehh?77d1_~rm^r;gcT~u}d5Eu@xrn=r)vxM}r5+^X;dK=E*Z%rr z;&HLKsnH>&)?#{oXZx30x6{JeU$&n>d=4u2db-{*aeNfpugHW}&t`@+E#bL?%g!R5 zVS^9l%AUEreK>jYG}Bno+h?d$C3jInQ&>%f4AI0E(}z@zYp2`Rat!pXKE)RDI6f%9 zfUx13(GLS!4cFJ^_+GgX#c)I(L+Nno)}2e=ANVv%Sskq5TRgV89NhXp4PAEzf4an_bMTgyt*bZTQY_RkfzJ%I0-Ge?LIwge_prx#aj z@}iB~NTC^&8ClM*G6p||Z)16Rpb?+$wiFFfB!o+8{=ym4|`720Hf-;xm?$mXc*L2^7+G63=Msl$36 zrmdQac%ALPP}4V#a%z9seE?}7o#%E=RTkFu+^)7$K8-(++OKWNU?`j6u_$NSh^a+8 zC&m?0lBu6YwWpaiN{I{XH&IQik2TSzxG#ADjehSF=ST=I;GWHHciN}tfEq}@ip+!) z7d{#y6NXq)--}-Vl7ygzw6tGyc+NETq2|~_<0zt#7u%Vti&7~BR@!N(Az_JXi{ZVC zLek`~G{XgLc`$P1A&!as-%;>wk^+gc#iVK&`c$pSA|`1I%_d2ox3~4Vp?*kfHZ$u4HMGG_V*kUJ{bs0=f=bA)b6Zn9T#L;Va`kDj}Jj7W$h1*9Q zH9D`#i%r*YnsIbB11;n)TVvryAEw!V+jj=zW;k0PABXLCUq)4)@K)Xosi(J_NuypL z`~BRjcKmu?RM{weSH&1qk9@$CcNw~(DA_loOulcDQgg|!h)3e(&Re^L%rkF;WzkGU zNhEUtwuS|I8TZGsMtA1pK0r3q?VqHh5fQ>fT3WT-`LkKAH#E-5vwhRBA8}L$b7Yj+ zCYI8ie`L-o4^c9!Nwel%_^r266;mQI2`5K%!wO`jlcbTYcx5kePrjd3J&H|S7?6Vs zLpXdz5J`{?A?I?GsqCk8ii43vCj7>{Tw+$#*ymr`y|$skbw5shuTeRJ#mpb8NTd}K z+?r(|0+(toM*cGGH14%W5-QPG1Lvvl%s!`9$2;$QsJC8IQsX2|Qyu7VT~CtjjjB}U zoi*1_o1(@oh)ynM!n=xu+FuFL;nuV8dwCh~O~gx2(9hlkI8p|$uZyb!A&~P#_`qTu zn9w^WA~>f8tlJkMddjz{#p@TAsN-W?cc$Jf@jWuUiiGPJtx~!fk@DBHC7b3HLsZ#P z(DMh^Lvp##PyC_y985BD>ZZm$m`prrnBh9Sk|8VhlEXq1#-K#~~RK*h>VZRx;>z^n_d&+HK79u7~naM3%UO34}V*yy`OoEiXLRsAjucv-tJH!qJ(s$I)Hc`{$TpZ$4R2HBe$QgUUvZrhVjG#GU6-p@ zy!NYYM!JrX)8FMNob|fq=6z%)e>!skbZ^#Ko9;TSr?&KlRU#$HrPHCT9{vJOX{_($ zvi**99Ku|~0JVZ%l#)A#s}}{E`kcMsWbDb1sjDR>9&gz@b(5ev8&_SX(U0;eEDXGT zuza=))e-3W# zmysb?rWsl;$B#mi1O~sm-kHbh#ID#;ZRc21nWtW__{-9+1-&aWNmTWY?Cc0~U_FLuYZ&1RR50!Ox!(x$wd)}{<@9o<$ro^E_xR!!%Xn+73aXS2e*KS5ZGJGOLu8+9u{y z5_K#|Kwn3MYo;7EoqghvC0_W$y1aE_Qd473;PKqM!#T6YpJ?Dl>d0(PO1u}%7gpTO zQ^!HzTTpCUY_^qbdy);U_wm*+6cv<#>uu08XU{96Pm|egm{h4vFddJlpkvLJrJSUG z_UdAa{EY8YiCL!npf*oRMRLSlJSt_H`6@)^x+LEWD(IA02{wP{C{Az9RfvBtsNqt7 z0Ci~4lpGrOgc8Slehd(69Iw_jkZ5ZJ?V>(m$hclhG4f|wQB!K}phCZ!G`vkSBNH6U zJQm8$Lh)BV7qJgq%fqm z4fS=|Tc)hG(zd2)f%q#;;20rru(W|>T|+{F>MI<9vO^FxPxCrlMoglH)R>EAK)_1_ zejvv4>E7}fO_;a}eOM5DXux6%Ije>k$*o&lQYs`bZ4V$8Y=s6UGgU*9SS<0Kxz&H@ zded-(up#S6`$9JI-jH(e;xIkOXHr&}4_Ww~WHzWI+avOr*){$MvtOB8$(w3DDp)_D zE!9m~#2XP!#y-F(#Ez;hFd1&xJDKVX-gX;lHdu5>+C)Kbl<{~uRx;iR^H+k^$uZ?Z zr*Qw+E*2W4L}>yh{abgOpOsmi5^=w*rdGL3t(GeE^#7(!N8O<5Mq)3p#d(E!s?^%37)tE}C*03JqbaWf zEp1j1rRjq*G4dq3QY;OKC!13kNM5p_aL4Tz-n3-I3-t>}9Vo#S?2IdJ30%JH`mm;d zb;V7YBl@E)293s+Gfa3XiSgY2RTxFN3NurO1be z!q*!npxLMg?|;7k6hii>{;bkKHC!U^!D>iTHeCD=d*cip*(h64hZC=Sem&B-1<)fJ z>Nkhz*H(@{3jRQs@8?b^U!Ba+FvAgDQ(@IX_Y2MQ_|IEvUU-QrB9c)gZ-W*cLvDWNZeF@3jD?xI#yt#_q+|CVare z;#n2YkJVi)k(%Lm9FkWzZoR!^3%tNLCdx_t4ddyJO5saK7G;jGqpduX&*wpcm6}fG zWsuSfN^s0=aMYuv`WJP5B^h|Wv7zz6zQ7c~XVA+y)O7$(ANlUr41ZF7HJ8B0M+C~Ezt0?$eyp*K>@#1QJkxlx(cP#wIqsE~+})|gIC-`OJF zd8$Y4ySU*GT*B^5KeJq;;?g<35wk*L{_9huk(`cekYaCHbUNEL5b1Dc>4&Yi=}hmw z$<6Om7D}Pq&SQBmD(8sS>A7>PEgFnVs!uO8no8WbHQ6V#; zHAKT*^VO>4bd%|u$KSqC!h>SMpQqBiX5z2Zy^65Y^7HqwqMCL6k`#129anQbQ#GUb zI`UPvu$0y$b>WwJ>e2)>2@GoO+i8hUh64LPGIu#niPrjMe6!C?%=ZT-BUqPY-~J~7 vYWb(+@=EoR!R?+mbDq?nC{U;T2=_R|?v%)6`x~2Z;Gev-iqr=Q Date: Thu, 11 Aug 2016 18:28:34 +0200 Subject: [PATCH 1136/1390] Update image --- screenshots/normal_barchart_wiki.png | Bin 40671 -> 36513 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshots/normal_barchart_wiki.png b/screenshots/normal_barchart_wiki.png index aa5676f9d3058b393c27a23c919f2658d0d1d048..93479eb37d4d810e1a6dbd986b991311a19c6907 100644 GIT binary patch literal 36513 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³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 literal 40671 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 Date: Fri, 12 Aug 2016 20:50:57 +0200 Subject: [PATCH 1137/1390] Fix crash related to circle size (#2115) --- .../mikephil/charting/data/LineDataSet.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index e987707cef..5eced95e43 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -4,6 +4,7 @@ import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; +import android.util.Log; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.IFillFormatter; @@ -146,13 +147,18 @@ public float getCubicIntensity() { /** - * sets the radius of the drawn circles. - * Default radius = 4f + * Sets the radius of the drawn circles. + * Default radius = 4f, Min = 1f * * @param radius */ public void setCircleRadius(float radius) { - mCircleRadius = Utils.convertDpToPixel(radius); + + if (radius >= 1f) { + mCircleRadius = Utils.convertDpToPixel(radius); + } else { + Log.e("LineDataSet", "Circle radius cannot be < 1"); + } } @Override @@ -161,13 +167,18 @@ public float getCircleRadius() { } /** - * sets the hole radius of the drawn circles. - * Default radius = 2f + * Sets the hole radius of the drawn circles. + * Default radius = 2f, Min = 0.5f * * @param holeRadius */ public void setCircleHoleRadius(float holeRadius) { - mCircleHoleRadius = Utils.convertDpToPixel(holeRadius); + + if (holeRadius >= 0.5f) { + mCircleHoleRadius = Utils.convertDpToPixel(holeRadius); + } else { + Log.e("LineDataSet", "Circle radius cannot be < 0.5"); + } } @Override From 0f04e9c6f5e19f3003c5114383f480345067a905 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Aug 2016 20:55:59 +0200 Subject: [PATCH 1138/1390] Documentation update --- .../github/mikephil/charting/components/IMarker.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java index d8ee7452ab..c15dae3a0c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java @@ -1,27 +1,22 @@ package com.github.mikephil.charting.components; -import android.content.Context; import android.graphics.Canvas; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.RelativeLayout; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.MPPointF; public interface IMarker { /** - * @return The desired offset you wish the IMarker to have on the x-axis. + * @return The desired (general) offset you wish the IMarker to have on the x- and y-axis. * By returning x: -(width / 2) you will center the IMarker horizontally. * By returning y: -(height / 2) you will center the IMarker vertically. */ MPPointF getOffset(); /** - * @return The offset for drawing at the specific `point` + * @return The offset for drawing at the specific `point`. This allows conditional adjusting of the Marker position. * If you have no adjustments to make, return getOffset(). * * @param posX This is the X position at which the marker wants to be drawn. @@ -36,7 +31,7 @@ public interface IMarker { * * @param e The Entry the IMarker belongs to. This can also be any subclass of Entry, like BarEntry or * CandleEntry, simply cast it at runtime. - * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the + * @param highlight The highlight object contains information about the highlighted value such as it's dataset-index, the * selected range or stack-index (only stacked bar entries). */ void refreshContent(Entry e, Highlight highlight); From 7462c083f9c71c908589ec358543cb9fbe58e0a1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Aug 2016 21:02:25 +0200 Subject: [PATCH 1139/1390] Fix #2119 --- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 36d18e055f..1e94b5540c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -265,7 +265,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float arcStartPointX = 0.f, arcStartPointY = 0.f; - if (sweepAngleOuter % 360f == 0.f) { + if (sweepAngleOuter % 360f < 0.00001f) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { From d912964dd31d92f88327c6772655184aa66a7c0f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 13 Aug 2016 15:27:40 +0200 Subject: [PATCH 1140/1390] Cleanup --- .../mikephil/charting/renderer/LineChartRenderer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index bf55c32cf0..516b3b7391 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -65,7 +65,8 @@ public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, } @Override - public void initBuffers() { } + public void initBuffers() { + } @Override public void drawData(Canvas c) { @@ -231,7 +232,7 @@ protected void drawCubicBezier(ILineDataSet dataSet) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); - // create a new path, this is bad for performance + drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, mXBounds); } @@ -440,7 +441,6 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, Transformer trans, if (currentStartIndex <= currentEndIndex) { generateFilledPath(dataSet, currentStartIndex, currentEndIndex, filled); - trans.pathValueToPixel(filled); final Drawable drawable = dataSet.getFillDrawable(); @@ -504,7 +504,6 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex } filled.close(); - } @Override From d342760357eec29154c4f0ca6917398a79036621 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 13 Aug 2016 15:38:40 +0200 Subject: [PATCH 1141/1390] Fix issue #2102 --- .../mpchartexample/PiePolylineChartActivity.java | 2 +- .../charting/renderer/PieChartRenderer.java | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 6db7f80e29..d84301632f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -223,7 +223,7 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); - // dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); + //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); PieData data = new PieData(dataSet); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 1e94b5540c..9535cc1fb9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -414,6 +414,8 @@ public void drawValues(Canvas c) { c.save(); + float offset = Utils.convertDpToPixel(5.f); + for (int i = 0; i < dataSets.size(); i++) { IPieDataSet dataSet = dataSets.get(i); @@ -439,8 +441,6 @@ public void drawValues(Canvas c) { mValueLinePaint.setColor(dataSet.getValueLineColor()); mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); - float offset = Utils.convertDpToPixel(5.f); - final float sliceSpace = getSliceSpace(dataSet); for (int j = 0; j < entryCount; j++) { @@ -509,13 +509,22 @@ public void drawValues(Canvas c) { if (transformedAngle % 360.0 >= 90.0 && transformedAngle % 360.0 <= 270.0) { pt2x = pt1x - polyline2Width; pt2y = pt1y; + mValuePaint.setTextAlign(Align.RIGHT); + + if(drawXOutside) + mEntryLabelsPaint.setTextAlign(Align.RIGHT); + labelPtx = pt2x - offset; labelPty = pt2y; } else { pt2x = pt1x + polyline2Width; pt2y = pt1y; mValuePaint.setTextAlign(Align.LEFT); + + if(drawXOutside) + mEntryLabelsPaint.setTextAlign(Align.LEFT); + labelPtx = pt2x + offset; labelPty = pt2y; } From 3c8bf8cb94a796406e3dc17340f430009b3ea246 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 08:54:20 +0300 Subject: [PATCH 1142/1390] Use an actual Epsilon here --- .../mikephil/charting/renderer/PieChartRenderer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 9535cc1fb9..a37fb0c390 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -229,7 +229,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { // draw only if the value is greater than zero - if ((Math.abs(dataSet.getEntryForIndex(j).getY()) > 0.000001)) { + if ((Math.abs(dataSet.getEntryForIndex(j).getY()) > Utils.FLOAT_EPSILON)) { visibleAngleCount++; } } @@ -244,7 +244,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero - if ((Math.abs(e.getY()) > 0.000001)) { + if ((Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { if (!mChart.needsHighlight(j)) { @@ -265,7 +265,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float arcStartPointX = 0.f, arcStartPointY = 0.f; - if (sweepAngleOuter % 360f < 0.00001f) { + if (sweepAngleOuter % 360f < Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { @@ -771,7 +771,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { // draw only if the value is greater than zero - if ((Math.abs(set.getEntryForIndex(j).getY()) > 0.000001)) { + if ((Math.abs(set.getEntryForIndex(j).getY()) > Utils.FLOAT_EPSILON)) { visibleAngleCount++; } } @@ -958,7 +958,7 @@ protected void drawRoundedSlices(Canvas c) { Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero - if ((Math.abs(e.getY()) > 0.000001)) { + if ((Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { float x = (float) ((r - circleRadius) * Math.cos(Math.toRadians((angle + sliceAngle) From bab5b9dd6cb93c86ffb620252170448141372ca9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 09:37:45 +0300 Subject: [PATCH 1143/1390] Refined scaleXEnabled/scaleYEnabled conditioning --- .../charting/listener/BarLineChartTouchListener.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index f1a8241dc4..e041e5ad97 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -149,10 +149,11 @@ public boolean onTouch(View v, MotionEvent event) { if (mChart.isPinchZoomEnabled()) { mTouchMode = PINCH_ZOOM; } else { - if (mSavedXDist > mSavedYDist) - mTouchMode = X_ZOOM; - else - mTouchMode = Y_ZOOM; + if (mChart.isScaleXEnabled() != mChart.isScaleYEnabled()) { + mTouchMode = mChart.isScaleXEnabled() ? X_ZOOM : Y_ZOOM; + } else { + mTouchMode = mSavedXDist > mSavedYDist ? X_ZOOM : Y_ZOOM; + } } } From be12f155baeb147222dcfe6c37bd8b0bc77dff70 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 10:10:53 +0300 Subject: [PATCH 1144/1390] We need an "equals or less" here --- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index a37fb0c390..530e282a26 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -265,7 +265,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float arcStartPointX = 0.f, arcStartPointY = 0.f; - if (sweepAngleOuter % 360f < Utils.FLOAT_EPSILON) { + if (sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { From 092e8a80f7514d25ec28919fbe38539b334b4064 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Aug 2016 09:51:47 +0200 Subject: [PATCH 1145/1390] Changes related to #2119 --- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 9535cc1fb9..8f1b41a7dd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -265,7 +265,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float arcStartPointX = 0.f, arcStartPointY = 0.f; - if (sweepAngleOuter % 360f < 0.00001f) { + if (sweepAngleOuter % 360f < Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { From 7747c345523f355e807451601a7fbb4d4d5910b1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 11:07:14 +0300 Subject: [PATCH 1146/1390] Add half line width to clipping rect of grid/limit lines (Closes #2081) https://github.com/danielgindi/Charts/issues/1204 --- .../charting/charts/BarLineChartBase.java | 16 ++++--------- .../charting/renderer/XAxisRenderer.java | 23 +++++++++++++++++++ .../XAxisRendererHorizontalBarChart.java | 15 ++++++++++++ .../charting/renderer/YAxisRenderer.java | 22 ++++++++++++++++++ .../YAxisRendererHorizontalBarChart.java | 15 ++++++++++++ 5 files changed, 80 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index fbc20a44b3..494c8bcedb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -222,11 +222,6 @@ protected void onDraw(Canvas canvas) { } } - // make sure the graph values and grid cannot be drawn outside the - // content-rect - int clipRestoreCount = canvas.save(); - canvas.clipRect(mViewPortHandler.getContentRect()); - mXAxisRenderer.renderGridLines(canvas); mAxisRendererLeft.renderGridLines(canvas); mAxisRendererRight.renderGridLines(canvas); @@ -240,6 +235,10 @@ protected void onDraw(Canvas canvas) { if (mAxisRight.isDrawLimitLinesBehindDataEnabled()) mAxisRendererRight.renderLimitLines(canvas); + // make sure the data cannot be drawn outside the content-rect + int clipRestoreCount = canvas.save(); + canvas.clipRect(mViewPortHandler.getContentRect()); + mRenderer.drawData(canvas); // if highlighting is enabled @@ -251,9 +250,6 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(canvas); - clipRestoreCount = canvas.save(); - canvas.clipRect(mViewPortHandler.getContentRect()); - if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); @@ -262,9 +258,7 @@ protected void onDraw(Canvas canvas) { if (!mAxisRight.isDrawLimitLinesBehindDataEnabled()) mAxisRendererRight.renderLimitLines(canvas); - - canvas.restoreToCount(clipRestoreCount); - + mXAxisRenderer.renderAxisLabels(canvas); mAxisRendererLeft.renderAxisLabels(canvas); mAxisRendererRight.renderAxisLabels(canvas); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 2a93910d72..43ce279e8e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.RectF; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; @@ -236,6 +237,9 @@ public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; + int clipRestoreCount = c.save(); + c.clipRect(getGridClippingRect()); + if(mRenderGridLinesBuffer.length != mAxis.mEntryCount * 2){ mRenderGridLinesBuffer = new float[mXAxis.mEntryCount * 2]; } @@ -257,6 +261,16 @@ public void renderGridLines(Canvas c) { drawGridLine(c, positions[i], positions[i + 1], gridLinePath); } + + c.restoreToCount(clipRestoreCount); + } + + protected RectF mGridClippingRect = new RectF(); + + public RectF getGridClippingRect() { + mGridClippingRect.set(mViewPortHandler.getContentRect()); + mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f); + return mGridClippingRect; } /** @@ -279,6 +293,8 @@ protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { } protected float[] mRenderLimitLinesBuffer = new float[2]; + protected RectF mLimitLineClippingRect = new RectF(); + /** * Draws the LimitLines associated with this axis to the screen. * @@ -303,6 +319,11 @@ public void renderLimitLines(Canvas c) { if (!l.isEnabled()) continue; + int clipRestoreCount = c.save(); + mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); + mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f); + c.clipRect(mLimitLineClippingRect); + position[0] = l.getLimit(); position[1] = 0.f; @@ -310,6 +331,8 @@ public void renderLimitLines(Canvas c) { renderLimitLineLine(c, l, position); renderLimitLineLabel(c, l, position, 2.f + l.getYOffset()); + + c.restoreToCount(clipRestoreCount); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 02192f5a47..48e1ece8b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -5,6 +5,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.RectF; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.LimitLine; @@ -161,6 +162,13 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { } } + @Override + public RectF getGridClippingRect() { + mGridClippingRect.set(mViewPortHandler.getContentRect()); + mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f); + return mGridClippingRect; + } + @Override protected void drawGridLine(Canvas c, float x, float y, Path gridLinePath) { @@ -228,6 +236,11 @@ public void renderLimitLines(Canvas c) { if(!l.isEnabled()) continue; + int clipRestoreCount = c.save(); + mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); + mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f); + c.clipRect(mLimitLineClippingRect); + mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); @@ -290,6 +303,8 @@ public void renderLimitLines(Canvas c) { pts[1] + yOffset, mLimitLinePaint); } } + + c.restoreToCount(clipRestoreCount); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 09e25d1e1e..092714788a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.RectF; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; @@ -134,6 +135,9 @@ public void renderGridLines(Canvas c) { if (mYAxis.isDrawGridLinesEnabled()) { + int clipRestoreCount = c.save(); + c.clipRect(getGridClippingRect()); + float[] positions = getTransformedPositions(); mGridPaint.setColor(mYAxis.getGridColor()); @@ -150,6 +154,8 @@ public void renderGridLines(Canvas c) { c.drawPath(linePath(gridLinePath, i, positions), mGridPaint); gridLinePath.reset(); } + + c.restoreToCount(clipRestoreCount); } if (mYAxis.isDrawZeroLineEnabled()) { @@ -157,6 +163,14 @@ public void renderGridLines(Canvas c) { } } + protected RectF mGridClippingRect = new RectF(); + + public RectF getGridClippingRect() { + mGridClippingRect.set(mViewPortHandler.getContentRect()); + mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f); + return mGridClippingRect; + } + /** * Calculates the path for a grid line. * @@ -220,6 +234,7 @@ protected void drawZeroLine(Canvas c) { protected Path mRenderLimitLines = new Path(); protected float[] mRenderLimitLinesBuffer = new float[2]; + protected RectF mLimitLineClippingRect = new RectF(); /** * Draws the LimitLines associated with this axis to the screen. * @@ -246,6 +261,11 @@ public void renderLimitLines(Canvas c) { if (!l.isEnabled()) continue; + int clipRestoreCount = c.save(); + mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); + mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f); + c.clipRect(mLimitLineClippingRect); + mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); @@ -309,6 +329,8 @@ public void renderLimitLines(Canvas c) { pts[1] + yOffset, mLimitLinePaint); } } + + c.restoreToCount(clipRestoreCount); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 6cf7985ea2..f867cf5f3a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -5,6 +5,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.RectF; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.YAxis; @@ -164,6 +165,13 @@ protected float[] getTransformedPositions() { return positions; } + @Override + public RectF getGridClippingRect() { + mGridClippingRect.set(mViewPortHandler.getContentRect()); + mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f); + return mGridClippingRect; + } + @Override protected Path linePath(Path p, int i, float[] positions) { @@ -225,6 +233,11 @@ public void renderLimitLines(Canvas c) { if (!l.isEnabled()) continue; + int clipRestoreCount = c.save(); + mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); + mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f); + c.clipRect(mLimitLineClippingRect); + pts[0] = l.getLimit(); pts[2] = l.getLimit(); @@ -281,6 +294,8 @@ public void renderLimitLines(Canvas c) { c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); } } + + c.restoreToCount(clipRestoreCount); } } } From ea6b0e8e1c3f2567ad5724807a31493b7b88e629 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 16:09:06 +0300 Subject: [PATCH 1147/1390] Simplified legend entries configuration. Option to style dataset form... --- .../mikephil/charting/components/Legend.java | 428 ++++++++++-------- .../charting/components/LegendEntry.java | 66 +++ .../mikephil/charting/data/BaseDataSet.java | 32 ++ .../interfaces/datasets/IDataSet.java | 22 + .../charting/renderer/LegendRenderer.java | 180 +++++--- 5 files changed, 484 insertions(+), 244 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index b12a39b394..8e521f5adc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -3,6 +3,7 @@ import android.graphics.Paint; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; @@ -33,7 +34,35 @@ public enum LegendPosition { } public enum LegendForm { - SQUARE, CIRCLE, LINE + /** + * Avoid drawing a form + */ + NONE, + + /** + * Do not draw the a form, but leave space for it + */ + EMPTY, + + /** + * Use default (default dataset's form to the legend's form) + */ + DEFAULT, + + /** + * Draw a square + */ + SQUARE, + + /** + * Draw a circle + */ + CIRCLE, + + /** + * Draw a horizontal line + */ + LINE } public enum LegendHorizontalAlignment { @@ -53,27 +82,15 @@ public enum LegendDirection { } /** - * the legend colors array, each color is for the form drawn at the same - * index - */ - private int[] mColors; - - /** - * the legend text array. a null label will start a group. - */ - private String[] mLabels; - - /** - * colors that will be appended to the end of the colors array after - * calculating the legend. + * The legend entries array */ - private int[] mExtraColors; + private LegendEntry[] mEntries = new LegendEntry[]{}; /** - * labels that will be appended to the end of the labels array after - * calculating the legend. a null label will start a group. + * Entries that will be appended to the end of the auto calculated entries after calculating the legend. + * (if the legend has already been calculated, you will need to call notifyDataSetChanged() to let the changes take effect) */ - private String[] mExtraLabels; + private LegendEntry[] mExtraEntries; /** * Are the legend labels/colors a custom value or auto calculated? If false, @@ -101,6 +118,11 @@ public enum LegendDirection { */ private float mFormSize = 8f; + /** + * the size of the legend forms/shapes + */ + private float mFormLineWidth = 3f; + /** * the space between the legend entries on a horizontal axis, default 6f */ @@ -134,6 +156,7 @@ public enum LegendDirection { public Legend() { mFormSize = Utils.convertDpToPixel(8f); + mFormLineWidth = Utils.convertDpToPixel(3f); mXEntrySpace = Utils.convertDpToPixel(6f); mYEntrySpace = Utils.convertDpToPixel(0f); mFormToTextSpace = Utils.convertDpToPixel(5f); @@ -144,11 +167,21 @@ public Legend() { } /** - * Constructor. Provide colors and labels for the legend. + * Constructor. Provide entries for the legend. * - * @param colors - * @param labels + * @param entries */ + public Legend(LegendEntry[] entries) { + this(); + + if (entries == null) { + throw new IllegalArgumentException("entries array is NULL"); + } + + this.mEntries = entries; + } + + @Deprecated public Legend(int[] colors, String[] labels) { this(); @@ -161,56 +194,41 @@ public Legend(int[] colors, String[] labels) { "colors array and labels array need to be of same size"); } - this.mColors = colors; - this.mLabels = labels; - } + List entries = new ArrayList<>(); - /** - * Constructor. Provide colors and labels for the legend. - * - * @param colors - * @param labels - */ - public Legend(List colors, List labels) { - this(); + for (int i = 0; i < Math.min(colors.length, labels.length); i++) { + final LegendEntry entry = new LegendEntry(); + entry.formColor = colors[i]; + entry.label = labels[i]; - if (colors == null || labels == null) { - throw new IllegalArgumentException("colors array or labels array is NULL"); - } + if (entry.formColor == ColorTemplate.COLOR_SKIP) + entry.form = LegendForm.NONE; + else if (entry.formColor == ColorTemplate.COLOR_NONE || + entry.formColor == 0) + entry.form = LegendForm.EMPTY; - if (colors.size() != labels.size()) { - throw new IllegalArgumentException( - "colors array and labels array need to be of same size"); + entries.add(entry); } - this.mColors = Utils.convertIntegers(colors); - this.mLabels = Utils.convertStrings(labels); + mEntries = entries.toArray(new LegendEntry[entries.size()]); + } + + @Deprecated + public Legend(List colors, List labels) { + this(Utils.convertIntegers(colors), Utils.convertStrings(labels)); } /** * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. * - * @param colors + * @param entries */ - public void setComputedColors(List colors) { - if (mColors != null && colors.size() == mColors.length) { - Utils.copyIntegers(colors, mColors); - } else { - mColors = Utils.convertIntegers(colors); - } + public void setEntries(List entries) { + mEntries = entries.toArray(new LegendEntry[entries.size()]); } - /** - * This method sets the automatically computed labels for the legend. Use setCustom(...) to set custom labels. - * - * @param labels - */ - public void setComputedLabels(List labels) { - if (mLabels != null && mLabels.length == labels.size()) { - Utils.copyStrings(labels, mLabels); - } else { - mLabels = Utils.convertStrings(labels); - } + public LegendEntry[] getEntries() { + return mEntries; } /** @@ -223,19 +241,24 @@ public void setComputedLabels(List labels) { public float getMaximumEntryWidth(Paint p) { float max = 0f; + float maxFormSize = 0f; - for (int i = 0; i < mLabels.length; i++) { + for (LegendEntry entry : mEntries) { + final float formSize = Float.isNaN(entry.formSize) + ? mFormSize : entry.formSize; + if (formSize > maxFormSize) + maxFormSize = formSize; - if (mLabels[i] != null) { + String label = entry.label; + if (label == null) continue; - float length = (float) Utils.calcTextWidth(p, mLabels[i]); + float length = (float) Utils.calcTextWidth(p, label); - if (length > max) - max = length; - } + if (length > max) + max = length; } - return max + mFormSize + mFormToTextSpace; + return max + maxFormSize + mFormToTextSpace; } /** @@ -248,140 +271,141 @@ public float getMaximumEntryHeight(Paint p) { float max = 0f; - for (int i = 0; i < mLabels.length; i++) { - - if (mLabels[i] != null) { + for (LegendEntry entry : mEntries) { + String label = entry.label; + if (label == null) continue; - float length = (float) Utils.calcTextHeight(p, mLabels[i]); + float length = (float) Utils.calcTextHeight(p, label); - if (length > max) - max = length; - } + if (length > max) + max = length; } return max; } - /** - * returns all the colors the legend uses - * - * @return - */ + @Deprecated public int[] getColors() { - return mColors; + + int[] old = new int[mEntries.length]; + for (int i = 0; i < mEntries.length; i++) { + old[i] = mEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : + (mEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : + mEntries[i].formColor); + } + return old; } - /** - * returns all the labels the legend uses - * - * @return - */ + @Deprecated public String[] getLabels() { - return mLabels; - } - /** - * Returns the legend-label at the given index. - * - * @param index - * @return - */ - public String getLabel(int index) { - return mLabels[index]; + String[] old = new String[mEntries.length]; + for (int i = 0; i < mEntries.length; i++) { + old[i] = mEntries[i].label; + } + return old; } - /** - * colors that will be appended to the end of the colors array after - * calculating the legend. - */ + @Deprecated public int[] getExtraColors() { - return mExtraColors; + + int[] old = new int[mExtraEntries.length]; + for (int i = 0; i < mExtraEntries.length; i++) { + old[i] = mExtraEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : + (mExtraEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : + mExtraEntries[i].formColor); + } + return old; } - /** - * labels that will be appended to the end of the labels array after - * calculating the legend. a null label will start a group. - */ + @Deprecated public String[] getExtraLabels() { - return mExtraLabels; - } - /** - * Colors and labels that will be appended to the end of the auto calculated - * colors and labels arrays after calculating the legend. (if the legend has - * already been calculated, you will need to call notifyDataSetChanged() to - * let the changes take effect) - */ - public void setExtra(List colors, List labels) { - if (mExtraColors != null && mExtraColors.length == colors.size()) { - Utils.copyIntegers(colors, mExtraColors); - } else { - this.mExtraColors = Utils.convertIntegers(colors); + String[] old = new String[mExtraEntries.length]; + for (int i = 0; i < mExtraEntries.length; i++) { + old[i] = mExtraEntries[i].label; } + return old; + } - if (mExtraLabels != null && mExtraLabels.length == labels.size()) { - Utils.copyStrings(labels, mExtraLabels); - } else { - this.mExtraLabels = Utils.convertStrings(labels); - } + public LegendEntry[] getExtraEntries() { + + return mExtraEntries; + } + + public void setExtra(List entries) { + mExtraEntries = entries.toArray(new LegendEntry[entries.size()]); + } + + public void setExtra(LegendEntry[] entries) { + if (entries == null) + entries = new LegendEntry[]{}; + mExtraEntries = entries; + } + + @Deprecated + public void setExtra(List colors, List labels) { + setExtra(Utils.convertIntegers(colors), Utils.convertStrings(labels)); } /** - * Colors and labels that will be appended to the end of the auto calculated - * colors and labels arrays after calculating the legend. (if the legend has - * already been calculated, you will need to call notifyDataSetChanged() to - * let the changes take effect) + * Entries that will be appended to the end of the auto calculated + * entries after calculating the legend. + * (if the legend has already been calculated, you will need to call notifyDataSetChanged() + * to let the changes take effect) */ public void setExtra(int[] colors, String[] labels) { - this.mExtraColors = colors; - this.mExtraLabels = labels; + + List entries = new ArrayList<>(); + + for (int i = 0; i < Math.min(colors.length, labels.length); i++) { + final LegendEntry entry = new LegendEntry(); + entry.formColor = colors[i]; + entry.label = labels[i]; + + if (entry.formColor == ColorTemplate.COLOR_SKIP || + entry.formColor == 0) + entry.form = LegendForm.NONE; + else if (entry.formColor == ColorTemplate.COLOR_NONE) + entry.form = LegendForm.EMPTY; + + entries.add(entry); + } + + mExtraEntries = entries.toArray(new LegendEntry[entries.size()]); } /** - * Sets a custom legend's labels and colors arrays. The colors count should - * match the labels count. * Each color is for the form drawn at the same - * index. * A null label will start a group. * A ColorTemplate.COLOR_SKIP - * color will avoid drawing a form This will disable the feature that - * automatically calculates the legend labels and colors from the datasets. + * Sets a custom legend's entries array. + * * A null label will start a group. + * This will disable the feature that automatically calculates the legend + * entries from the datasets. * Call resetCustom() to re-enable automatic calculation (and then - * notifyDataSetChanged() is needed to auto-calculate the legend again) + * notifyDataSetChanged() is needed to auto-calculate the legend again) */ - public void setCustom(int[] colors, String[] labels) { - - if (colors.length != labels.length) { - throw new IllegalArgumentException( - "colors array and labels array need to be of same size"); - } + public void setCustom(LegendEntry[] entries) { - mLabels = labels; - mColors = colors; + mEntries = entries; mIsLegendCustom = true; } /** - * Sets a custom legend's labels and colors arrays. The colors count should - * match the labels count. * Each color is for the form drawn at the same - * index. * A null label will start a group. * A ColorTemplate.COLOR_SKIP - * color will avoid drawing a form This will disable the feature that - * automatically calculates the legend labels and colors from the datasets. + * Sets a custom legend's entries array. + * * A null label will start a group. + * This will disable the feature that automatically calculates the legend + * entries from the datasets. * Call resetCustom() to re-enable automatic calculation (and then - * notifyDataSetChanged() is needed to auto-calculate the legend again) + * notifyDataSetChanged() is needed to auto-calculate the legend again) */ - public void setCustom(List colors, List labels) { - - if (colors.size() != labels.size()) { - throw new IllegalArgumentException( - "colors array and labels array need to be of same size"); - } + public void setCustom(List entries) { - mColors = Utils.convertIntegers(colors); - mLabels = Utils.convertStrings(labels); + mEntries = entries.toArray(new LegendEntry[entries.size()]); mIsLegendCustom = true; } /** - * Calling this will disable the custom legend labels (set by - * setCustom(...)). Instead, the labels will again be calculated + * Calling this will disable the custom legend entries (set by + * setCustom(...)). Instead, the entries will again be calculated * automatically (after notifyDataSetChanged() is called). */ public void resetCustom() { @@ -389,7 +413,7 @@ public void resetCustom() { } /** - * @return true if a custom legend labels and colors has been set default + * @return true if a custom legend entries has been set default * false (automatic legend) */ public boolean isLegendCustom() { @@ -608,8 +632,7 @@ public void setForm(LegendForm shape) { } /** - * sets the size in pixels of the legend forms, this is internally converted - * in dp, default 8f + * sets the size in dp of the legend forms, default 8f * * @param size */ @@ -626,6 +649,24 @@ public float getFormSize() { return mFormSize; } + /** + * sets the line width in dp for forms that consist of lines, default 3f + * + * @param size + */ + public void setFormLineWidth(float size) { + mFormLineWidth = Utils.convertDpToPixel(size); + } + + /** + * returns the line width in dp for drawing forms that consist of lines + * + * @return + */ + public float getFormLineWidth() { + return mFormLineWidth; + } + /** * returns the space between the legend entries on a horizontal axis in * pixels @@ -795,6 +836,15 @@ public List getCalculatedLineSizes() { */ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { + float defaultFormSize = mFormSize; + float stackSpace = mStackSpace; + float formToTextSpace = mFormToTextSpace; + float xEntrySpace = mXEntrySpace; + float yEntrySpace = mYEntrySpace; + boolean wordWrapEnabled = mWordWrapEnabled; + LegendEntry[] entries = mEntries; + int entryCount = entries.length; + mTextWidthMax = getMaximumEntryWidth(labelpaint); mTextHeightMax = getMaximumEntryHeight(labelpaint); @@ -803,44 +853,46 @@ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandle float maxWidth = 0f, maxHeight = 0f, width = 0f; float labelLineHeight = Utils.getLineHeight(labelpaint); - final int count = mLabels.length; boolean wasStacked = false; - for (int i = 0; i < count; i++) { + for (int i = 0; i < entryCount; i++) { - boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; + LegendEntry e = entries[i]; + boolean drawingForm = e.form != LegendForm.NONE; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + String label = e.label; if (!wasStacked) width = 0.f; if (drawingForm) { if (wasStacked) - width += mStackSpace; - width += mFormSize; + width += stackSpace; + width += formSize; } // grouped forms have null labels - if (mLabels[i] != null) { + if (label != null) { // make a step to the left if (drawingForm && !wasStacked) - width += mFormToTextSpace; + width += formToTextSpace; else if (wasStacked) { maxWidth = Math.max(maxWidth, width); - maxHeight += labelLineHeight + mYEntrySpace; + maxHeight += labelLineHeight + yEntrySpace; width = 0.f; wasStacked = false; } - width += Utils.calcTextWidth(labelpaint, mLabels[i]); + width += Utils.calcTextWidth(labelpaint, label); - if (i < count - 1) - maxHeight += labelLineHeight + mYEntrySpace; + if (i < entryCount - 1) + maxHeight += labelLineHeight + yEntrySpace; } else { wasStacked = true; - width += mFormSize; - if (i < count - 1) - width += mStackSpace; + width += formSize; + if (i < entryCount - 1) + width += stackSpace; } maxWidth = Math.max(maxWidth, width); @@ -853,9 +905,8 @@ else if (wasStacked) { } case HORIZONTAL: { - int labelCount = mLabels.length; float labelLineHeight = Utils.getLineHeight(labelpaint); - float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace; + float labelLineSpacing = Utils.getLineSpacing(labelpaint) + yEntrySpace; float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent; // Start calculating layout @@ -868,9 +919,12 @@ else if (wasStacked) { mCalculatedLabelSizes.clear(); mCalculatedLineSizes.clear(); - for (int i = 0; i < labelCount; i++) { + for (int i = 0; i < entryCount; i++) { - boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; + LegendEntry e = entries[i]; + boolean drawingForm = e.form != LegendForm.NONE; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + String label = e.label; mCalculatedLabelBreakPoints.add(false); @@ -880,19 +934,19 @@ else if (wasStacked) { requiredWidth = 0.f; } else { // add the spacing appropriate for stacked labels/forms - requiredWidth += mStackSpace; + requiredWidth += stackSpace; } // grouped forms have null labels - if (mLabels[i] != null) { + if (label != null) { - mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i])); - requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f; + mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, label)); + requiredWidth += drawingForm ? mFormToTextSpace + formSize : 0.f; requiredWidth += mCalculatedLabelSizes.get(i).width; } else { mCalculatedLabelSizes.add(FSize.getInstance(0.f, 0.f)); - requiredWidth += drawingForm ? mFormSize : 0.f; + requiredWidth += drawingForm ? formSize : 0.f; if (stackedStartIndex == -1) { // mark this index as we might want to break here later @@ -900,11 +954,11 @@ else if (wasStacked) { } } - if (mLabels[i] != null || i == labelCount - 1) { + if (label != null || i == entryCount - 1) { - float requiredSpacing = currentLineWidth == 0.f ? 0.f : mXEntrySpace; + float requiredSpacing = currentLineWidth == 0.f ? 0.f : xEntrySpace; - if (!mWordWrapEnabled // No word wrapping, it must fit. + if (!wordWrapEnabled // No word wrapping, it must fit. // The line is empty, it must fit || currentLineWidth == 0.f // It simply fits @@ -925,14 +979,14 @@ else if (wasStacked) { currentLineWidth = requiredWidth; } - if (i == labelCount - 1) { + if (i == entryCount - 1) { // Add last line size to array mCalculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); maxLineWidth = Math.max(maxLineWidth, currentLineWidth); } } - stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; + stackedStartIndex = label != null ? -1 : stackedStartIndex; } mNeededWidth = maxLineWidth; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java new file mode 100644 index 0000000000..50300b6d7f --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java @@ -0,0 +1,66 @@ +package com.github.mikephil.charting.components; + + +import com.github.mikephil.charting.utils.ColorTemplate; + +public class LegendEntry { + public LegendEntry() { + + } + + /** + * + * @param label The legend entry text. A `null` label will start a group. + * @param form The form to draw for this entry. + * @param formSize Set as NaN to use the legend's default + * @param formLineWidth Set as NaN to use the legend's default + * @param formColor The color for drawing the form + */ + public LegendEntry(String label, + Legend.LegendForm form, + float formSize, + float formLineWidth, + int formColor) + { + this.label = label; + this.form = form; + this.formSize = formSize; + this.formLineWidth = formLineWidth; + this.formColor = formColor; + } + + /** + * The legend entry text. + * A `null` label will start a group. + */ + public String label; + + /** + * The form to draw for this entry. + * + * `NONE` will avoid drawing a form, and any related space. + * `EMPTY` will avoid drawing a form, but keep its space. + * `DEFAULT` will use the Legend's default. + */ + public Legend.LegendForm form = Legend.LegendForm.DEFAULT; + + /** + * Form size will be considered except for when .None is used + * + * Set as NaN to use the legend's default + */ + public float formSize = Float.NaN; + + /** + * Line width used for shapes that consist of lines. + * + * Set as NaN to use the legend's default + */ + public float formLineWidth = Float.NaN; + + /** + * The color for drawing the form + */ + public int formColor = ColorTemplate.COLOR_NONE; + +} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index fe19c80ff9..42212f4423 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -4,6 +4,7 @@ import android.graphics.Color; import android.graphics.Typeface; +import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.IValueFormatter; @@ -56,6 +57,10 @@ public abstract class BaseDataSet implements IDataSet { */ protected Typeface mValueTypeface; + private Legend.LegendForm mForm = Legend.LegendForm.DEFAULT; + private float mFormSize = Float.NaN; + private float mFormLineWidth = Float.NaN; + /** * if true, y-values are drawn on the chart */ @@ -318,6 +323,33 @@ public float getValueTextSize() { return mValueTextSize; } + public void setForm(Legend.LegendForm form) { + mForm = form; + } + + @Override + public Legend.LegendForm getForm() { + return mForm; + } + + public void setFormSize(float formSize) { + mFormSize = formSize; + } + + @Override + public float getFormSize() { + return mFormSize; + } + + public void setFormLineWidth(float formLineWidth) { + mFormLineWidth = formLineWidth; + } + + @Override + public float getFormLineWidth() { + return mFormLineWidth; + } + @Override public void setDrawValues(boolean enabled) { this.mDrawValues = enabled; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index f2f2eac203..ad43237730 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -2,6 +2,7 @@ import android.graphics.Typeface; +import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -368,6 +369,27 @@ public interface IDataSet { */ float getValueTextSize(); + /** + * The form to draw for this dataset in the legend. + * + * Return `DEFAULT` to use the default legend form. + */ + Legend.LegendForm getForm(); + + /** + * The form size to draw for this dataset in the legend. + * + * Return `Float.NaN` to use the default legend form size. + */ + float getFormSize(); + + /** + * The line width for drawing the form of this dataset in the legend + * + * Return `Float.NaN` to use the default legend form line width. + */ + float getFormLineWidth(); + /** * set this to true to draw y-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index e4b0b81ffc..14cf91ecd1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -7,6 +7,7 @@ import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.LegendEntry; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -71,8 +72,7 @@ public Paint getFormPaint() { } - protected List computedLabels = new ArrayList<>(16); - protected List computedColors = new ArrayList<>(16); + protected List computedEntries = new ArrayList<>(16); /** * Prepares the legend and calculates all needed forms, labels and colors. @@ -83,8 +83,7 @@ public void computeLegend(ChartData data) { if (!mLegend.isLegendCustom()) { - computedLabels.clear(); - computedColors.clear(); + computedEntries.clear(); // loop for building up the colors and labels used in the legend for (int i = 0; i < data.getDataSetCount(); i++) { @@ -102,14 +101,24 @@ public void computeLegend(ChartData data) { for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { - computedLabels.add(sLabels[j % sLabels.length]); - computedColors.add(clrs.get(j)); + computedEntries.add(new LegendEntry( + sLabels[j % sLabels.length], + dataSet.getForm(), + dataSet.getFormSize(), + dataSet.getFormLineWidth(), + clrs.get(j) + )); } if (bds.getLabel() != null) { // add the legend description label - computedColors.add(ColorTemplate.COLOR_SKIP); - computedLabels.add(bds.getLabel()); + computedEntries.add(new LegendEntry( + dataSet.getLabel(), + Legend.LegendForm.NONE, + Float.NaN, + Float.NaN, + ColorTemplate.COLOR_NONE + )); } } else if (dataSet instanceof IPieDataSet) { @@ -118,55 +127,77 @@ public void computeLegend(ChartData data) { for (int j = 0; j < clrs.size() && j < entryCount; j++) { - computedLabels.add(pds.getEntryForIndex(j).getLabel()); - computedColors.add(clrs.get(j)); + computedEntries.add(new LegendEntry( + pds.getEntryForIndex(j).getLabel(), + dataSet.getForm(), + dataSet.getFormSize(), + dataSet.getFormLineWidth(), + clrs.get(j) + )); } if (pds.getLabel() != null) { // add the legend description label - computedColors.add(ColorTemplate.COLOR_SKIP); - computedLabels.add(pds.getLabel()); + computedEntries.add(new LegendEntry( + dataSet.getLabel(), + Legend.LegendForm.NONE, + Float.NaN, + Float.NaN, + ColorTemplate.COLOR_NONE + )); } } else if (dataSet instanceof ICandleDataSet && ((ICandleDataSet) dataSet).getDecreasingColor() != ColorTemplate.COLOR_NONE) { int decreasingColor = ((ICandleDataSet) dataSet).getDecreasingColor(); - computedColors.add(decreasingColor); - int increasingColor = ((ICandleDataSet) dataSet).getIncreasingColor(); - computedColors.add(increasingColor); - computedLabels.add(null); - computedLabels.add(dataSet.getLabel()); + computedEntries.add(new LegendEntry( + null, + dataSet.getForm(), + dataSet.getFormSize(), + dataSet.getFormLineWidth(), + decreasingColor + )); + + computedEntries.add(new LegendEntry( + dataSet.getLabel(), + dataSet.getForm(), + dataSet.getFormSize(), + dataSet.getFormLineWidth(), + increasingColor + )); } else { // all others for (int j = 0; j < clrs.size() && j < entryCount; j++) { + String label; + // if multiple colors are set for a DataSet, group them if (j < clrs.size() - 1 && j < entryCount - 1) { - - computedLabels.add(null); + label = null; } else { // add label to the last entry - - String label = data.getDataSetByIndex(i).getLabel(); - computedLabels.add(label); + label = data.getDataSetByIndex(i).getLabel(); } - computedColors.add(clrs.get(j)); + computedEntries.add(new LegendEntry( + label, + dataSet.getForm(), + dataSet.getFormSize(), + dataSet.getFormLineWidth(), + clrs.get(j) + )); } } } - if (mLegend.getExtraColors() != null && mLegend.getExtraLabels() != null) { - for (int color : mLegend.getExtraColors()) - computedColors.add(color); - Collections.addAll(computedLabels, mLegend.getExtraLabels()); + if (mLegend.getExtraEntries() != null) { + Collections.addAll(computedEntries, mLegend.getExtraEntries()); } - mLegend.setComputedColors(computedColors); - mLegend.setComputedLabels(computedLabels); + mLegend.setEntries(computedEntries); } Typeface tf = mLegend.getTypeface(); @@ -200,8 +231,7 @@ public void renderLegend(Canvas c) { float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics) + mLegend.getYEntrySpace(); float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f; - String[] labels = mLegend.getLabels(); - int[] colors = mLegend.getColors(); + LegendEntry[] entries = mLegend.getEntries(); float formToTextSpace = mLegend.getFormToTextSpace(); float xEntrySpace = mLegend.getXEntrySpace(); @@ -209,7 +239,7 @@ public void renderLegend(Canvas c) { Legend.LegendHorizontalAlignment horizontalAlignment = mLegend.getHorizontalAlignment(); Legend.LegendVerticalAlignment verticalAlignment = mLegend.getVerticalAlignment(); Legend.LegendDirection direction = mLegend.getDirection(); - float formSize = mLegend.getFormSize(); + float defaultFormSize = mLegend.getFormSize(); // space between the entries float stackSpace = mLegend.getStackSpace(); @@ -292,7 +322,12 @@ public void renderLegend(Canvas c) { int lineIndex = 0; - for (int i = 0, count = labels.length; i < count; i++) { + for (int i = 0, count = entries.length; i < count; i++) { + + LegendEntry e = entries[i]; + boolean drawingForm = e.form != Legend.LegendForm.NONE; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + if (i < calculatedLabelBreakPoints.size() && calculatedLabelBreakPoints.get(i)) { posX = originPosX; posY += labelLineHeight + labelLineSpacing; @@ -307,14 +342,13 @@ public void renderLegend(Canvas c) { lineIndex++; } - boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP; - boolean isStacked = labels[i] == null; // grouped forms have null labels + boolean isStacked = e.label == null; // grouped forms have null labels if (drawingForm) { if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) posX -= formSize; - drawForm(c, posX, posY + formYOffset, i, mLegend); + drawForm(c, posX, posY + formYOffset, e, mLegend); if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) posX += formSize; @@ -328,7 +362,7 @@ public void renderLegend(Canvas c) { if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) posX -= calculatedLabelSizes.get(i).width; - drawLabel(c, posX, posY + labelLineHeight, labels[i]); + drawLabel(c, posX, posY + labelLineHeight, e.label); if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) posX += calculatedLabelSizes.get(i).width; @@ -369,9 +403,12 @@ public void renderLegend(Canvas c) { break; } - for (int i = 0; i < labels.length; i++) { + for (int i = 0; i < entries.length; i++) { + + LegendEntry e = entries[i]; + boolean drawingForm = e.form != Legend.LegendForm.NONE; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; - Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP; float posX = originPosX; if (drawingForm) { @@ -380,13 +417,13 @@ public void renderLegend(Canvas c) { else posX -= formSize - stack; - drawForm(c, posX, posY + formYOffset, i, mLegend); + drawForm(c, posX, posY + formYOffset, e, mLegend); if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) posX += formSize; } - if (labels[i] != null) { + if (e.label != null) { if (drawingForm && !wasStacked) posX += direction == Legend.LegendDirection.LEFT_TO_RIGHT ? formToTextSpace @@ -395,13 +432,13 @@ else if (wasStacked) posX = originPosX; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) - posX -= Utils.calcTextWidth(mLegendLabelPaint, labels[i]); + posX -= Utils.calcTextWidth(mLegendLabelPaint, e.label); if (!wasStacked) { - drawLabel(c, posX, posY + labelLineHeight, labels[i]); + drawLabel(c, posX, posY + labelLineHeight, e.label); } else { posY += labelLineHeight + labelLineSpacing; - drawLabel(c, posX, posY + labelLineHeight, labels[i]); + drawLabel(c, posX, posY + labelLineHeight, e.label); } // make a step down @@ -423,30 +460,59 @@ else if (wasStacked) * Draws the Legend-form at the given position with the color at the given * index. * - * @param c canvas to draw with - * @param x position - * @param y position - * @param index the index of the color to use (in the colors array) + * @param c canvas to draw with + * @param x position + * @param y position + * @param entry the entry to render + * @param legend the legend context */ - protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { - - if (legend.getColors()[index] == ColorTemplate.COLOR_SKIP) + protected void drawForm( + Canvas c, + float x, float y, + LegendEntry entry, + Legend legend) { + + if (entry.formColor == ColorTemplate.COLOR_SKIP || + entry.formColor == ColorTemplate.COLOR_NONE || + entry.formColor == 0) return; - mLegendFormPaint.setColor(legend.getColors()[index]); + Legend.LegendForm form = entry.form; + if (form == Legend.LegendForm.DEFAULT) + form = legend.getForm(); - float formsize = legend.getFormSize(); - float half = formsize / 2f; + mLegendFormPaint.setColor(entry.formColor); - switch (legend.getForm()) { + final float formSize = Float.isNaN(entry.formSize) ? legend.getFormSize() : entry.formSize; + final float half = formSize / 2f; + + switch (form) { + case NONE: + // Do nothing + break; + + case EMPTY: + // Do not draw, but keep space for the form + break; + + case DEFAULT: case CIRCLE: c.drawCircle(x + half, y, half, mLegendFormPaint); break; + case SQUARE: - c.drawRect(x, y - half, x + formsize, y + half, mLegendFormPaint); + c.drawRect(x, y - half, x + formSize, y + half, mLegendFormPaint); break; + case LINE: - c.drawLine(x, y, x + formsize, y, mLegendFormPaint); + { + final float formLineWidth = Float.isNaN(entry.formLineWidth) + ? legend.getFormLineWidth() + : entry.formLineWidth; + mLegendFormPaint.setStrokeWidth(formLineWidth); + + c.drawLine(x, y, x + formSize, y, mLegendFormPaint); + } break; } } From 7a10c05e3a2a1f2d7549b1ff42c565e1ce291937 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 16:40:55 +0300 Subject: [PATCH 1148/1390] Added feature for dashing legend line forms (Closes #1843) --- .../mpchartexample/LineChartActivity1.java | 4 +++ .../mikephil/charting/components/Legend.java | 22 +++++++++++++++ .../charting/components/LegendEntry.java | 18 ++++++++++-- .../mikephil/charting/data/BaseDataSet.java | 11 ++++++++ .../interfaces/datasets/IDataSet.java | 8 ++++++ .../charting/renderer/LegendRenderer.java | 28 +++++++++++++++++-- 6 files changed, 86 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 44fcfc036f..ab2f226efa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -2,6 +2,7 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; +import android.graphics.DashPathEffect; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -368,6 +369,9 @@ private void setData(int count, float range) { set1.setDrawCircleHole(false); set1.setValueTextSize(9f); set1.setDrawFilled(true); + set1.setFormLineWidth(1f); + set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); + set1.setFormSize(15.f); if (Utils.getSDKInt() >= 18) { // fill drawable only supported on api level 18 and above diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 8e521f5adc..bdcc024f6e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.components; +import android.graphics.DashPathEffect; import android.graphics.Paint; import com.github.mikephil.charting.data.Entry; @@ -123,6 +124,11 @@ public enum LegendDirection { */ private float mFormLineWidth = 3f; + /** + * Line dash path effect used for shapes that consist of lines. + */ + private DashPathEffect mFormLineDashEffect = null; + /** * the space between the legend entries on a horizontal axis, default 6f */ @@ -667,6 +673,22 @@ public float getFormLineWidth() { return mFormLineWidth; } + /** + * Sets the line dash path effect used for shapes that consist of lines. + * + * @param dashPathEffect + */ + public void setFormLineDashEffect(DashPathEffect dashPathEffect) { + mFormLineDashEffect = dashPathEffect; + } + + /** + * @return The line dash path effect used for shapes that consist of lines. + */ + public DashPathEffect getFormLineDashEffect() { + return mFormLineDashEffect; + } + /** * returns the space between the legend entries on a horizontal axis in * pixels diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java index 50300b6d7f..3acec0f461 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/LegendEntry.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.components; +import android.graphics.DashPathEffect; + import com.github.mikephil.charting.utils.ColorTemplate; public class LegendEntry { @@ -12,20 +14,23 @@ public LegendEntry() { * * @param label The legend entry text. A `null` label will start a group. * @param form The form to draw for this entry. - * @param formSize Set as NaN to use the legend's default - * @param formLineWidth Set as NaN to use the legend's default - * @param formColor The color for drawing the form + * @param formSize Set to NaN to use the legend's default. + * @param formLineWidth Set to NaN to use the legend's default. + * @param formLineDashEffect Set to nil to use the legend's default. + * @param formColor The color for drawing the form. */ public LegendEntry(String label, Legend.LegendForm form, float formSize, float formLineWidth, + DashPathEffect formLineDashEffect, int formColor) { this.label = label; this.form = form; this.formSize = formSize; this.formLineWidth = formLineWidth; + this.formLineDashEffect = formLineDashEffect; this.formColor = formColor; } @@ -58,6 +63,13 @@ public LegendEntry(String label, */ public float formLineWidth = Float.NaN; + /** + * Line dash path effect used for shapes that consist of lines. + * + * Set to null to use the legend's default + */ + public DashPathEffect formLineDashEffect = null; + /** * The color for drawing the form */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 42212f4423..f3107ebed7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -2,6 +2,7 @@ import android.content.Context; import android.graphics.Color; +import android.graphics.DashPathEffect; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; @@ -60,6 +61,7 @@ public abstract class BaseDataSet implements IDataSet { private Legend.LegendForm mForm = Legend.LegendForm.DEFAULT; private float mFormSize = Float.NaN; private float mFormLineWidth = Float.NaN; + private DashPathEffect mFormLineDashEffect = null; /** * if true, y-values are drawn on the chart @@ -350,6 +352,15 @@ public float getFormLineWidth() { return mFormLineWidth; } + public void setFormLineDashEffect(DashPathEffect dashPathEffect) { + mFormLineDashEffect = dashPathEffect; + } + + @Override + public DashPathEffect getFormLineDashEffect() { + return mFormLineDashEffect; + } + @Override public void setDrawValues(boolean enabled) { this.mDrawValues = enabled; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index ad43237730..62c10b3f32 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.interfaces.datasets; +import android.graphics.DashPathEffect; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; @@ -390,6 +391,13 @@ public interface IDataSet { */ float getFormLineWidth(); + /** + * The line dash path effect used for shapes that consist of lines. + * + * Return `null` to use the default legend form line dash effect. + */ + DashPathEffect getFormLineDashEffect(); + /** * set this to true to draw y-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 14cf91ecd1..06dc0b60d6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -2,8 +2,10 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.graphics.Path; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; @@ -50,7 +52,6 @@ public LegendRenderer(ViewPortHandler viewPortHandler, Legend legend) { mLegendFormPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mLegendFormPaint.setStyle(Paint.Style.FILL); - mLegendFormPaint.setStrokeWidth(3f); } /** @@ -106,6 +107,7 @@ public void computeLegend(ChartData data) { dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), + dataSet.getFormLineDashEffect(), clrs.get(j) )); } @@ -117,6 +119,7 @@ public void computeLegend(ChartData data) { Legend.LegendForm.NONE, Float.NaN, Float.NaN, + null, ColorTemplate.COLOR_NONE )); } @@ -132,6 +135,7 @@ public void computeLegend(ChartData data) { dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), + dataSet.getFormLineDashEffect(), clrs.get(j) )); } @@ -143,6 +147,7 @@ public void computeLegend(ChartData data) { Legend.LegendForm.NONE, Float.NaN, Float.NaN, + null, ColorTemplate.COLOR_NONE )); } @@ -158,6 +163,7 @@ public void computeLegend(ChartData data) { dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), + dataSet.getFormLineDashEffect(), decreasingColor )); @@ -166,6 +172,7 @@ public void computeLegend(ChartData data) { dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), + dataSet.getFormLineDashEffect(), increasingColor )); @@ -187,6 +194,7 @@ public void computeLegend(ChartData data) { dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), + dataSet.getFormLineDashEffect(), clrs.get(j) )); } @@ -456,6 +464,8 @@ else if (wasStacked) } } + private Path mLineFormPath = new Path(); + /** * Draws the Legend-form at the given position with the color at the given * index. @@ -477,6 +487,8 @@ protected void drawForm( entry.formColor == 0) return; + int restoreCount = c.save(); + Legend.LegendForm form = entry.form; if (form == Legend.LegendForm.DEFAULT) form = legend.getForm(); @@ -497,10 +509,12 @@ protected void drawForm( case DEFAULT: case CIRCLE: + mLegendFormPaint.setStyle(Paint.Style.FILL); c.drawCircle(x + half, y, half, mLegendFormPaint); break; case SQUARE: + mLegendFormPaint.setStyle(Paint.Style.FILL); c.drawRect(x, y - half, x + formSize, y + half, mLegendFormPaint); break; @@ -509,12 +523,22 @@ protected void drawForm( final float formLineWidth = Float.isNaN(entry.formLineWidth) ? legend.getFormLineWidth() : entry.formLineWidth; + final DashPathEffect formLineDashEffect = entry.formLineDashEffect == null + ? legend.getFormLineDashEffect() + : entry.formLineDashEffect; + mLegendFormPaint.setStyle(Paint.Style.STROKE); mLegendFormPaint.setStrokeWidth(formLineWidth); + mLegendFormPaint.setPathEffect(formLineDashEffect); - c.drawLine(x, y, x + formSize, y, mLegendFormPaint); + mLineFormPath.reset(); + mLineFormPath.moveTo(x, y); + mLineFormPath.lineTo(x + formSize, y); + c.drawPath(mLineFormPath, mLegendFormPaint); } break; } + + c.restoreToCount(restoreCount); } /** From 38cdf1b206f025bf8f68edfe067ef768cd6677e2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 16:50:26 +0300 Subject: [PATCH 1149/1390] Set those sizes to dps, convert internally. Until now it was set-dps, get-pixels. --- .../mikephil/charting/components/Legend.java | 46 +++++++++---------- .../charting/renderer/LegendRenderer.java | 27 ++++++----- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index bdcc024f6e..aeba757cc2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -161,13 +161,7 @@ public enum LegendDirection { */ public Legend() { - mFormSize = Utils.convertDpToPixel(8f); - mFormLineWidth = Utils.convertDpToPixel(3f); - mXEntrySpace = Utils.convertDpToPixel(6f); - mYEntrySpace = Utils.convertDpToPixel(0f); - mFormToTextSpace = Utils.convertDpToPixel(5f); - mTextSize = Utils.convertDpToPixel(10f); - mStackSpace = Utils.convertDpToPixel(3f); + this.mTextSize = Utils.convertDpToPixel(10f); this.mXOffset = Utils.convertDpToPixel(5f); this.mYOffset = Utils.convertDpToPixel(3f); // 2 } @@ -248,10 +242,12 @@ public float getMaximumEntryWidth(Paint p) { float max = 0f; float maxFormSize = 0f; + float formToTextSpace = Utils.convertDpToPixel(mFormToTextSpace); for (LegendEntry entry : mEntries) { - final float formSize = Float.isNaN(entry.formSize) - ? mFormSize : entry.formSize; + final float formSize = Utils.convertDpToPixel( + Float.isNaN(entry.formSize) + ? mFormSize : entry.formSize); if (formSize > maxFormSize) maxFormSize = formSize; @@ -264,7 +260,7 @@ public float getMaximumEntryWidth(Paint p) { max = length; } - return max + maxFormSize + mFormToTextSpace; + return max + maxFormSize + formToTextSpace; } /** @@ -643,7 +639,7 @@ public void setForm(LegendForm shape) { * @param size */ public void setFormSize(float size) { - mFormSize = Utils.convertDpToPixel(size); + mFormSize = size; } /** @@ -661,7 +657,7 @@ public float getFormSize() { * @param size */ public void setFormLineWidth(float size) { - mFormLineWidth = Utils.convertDpToPixel(size); + mFormLineWidth = size; } /** @@ -706,7 +702,7 @@ public float getXEntrySpace() { * @param space */ public void setXEntrySpace(float space) { - mXEntrySpace = Utils.convertDpToPixel(space); + mXEntrySpace = space; } /** @@ -725,7 +721,7 @@ public float getYEntrySpace() { * @param space */ public void setYEntrySpace(float space) { - mYEntrySpace = Utils.convertDpToPixel(space); + mYEntrySpace = space; } /** @@ -744,7 +740,7 @@ public float getFormToTextSpace() { * @param space */ public void setFormToTextSpace(float space) { - this.mFormToTextSpace = Utils.convertDpToPixel(space); + this.mFormToTextSpace = space; } /** @@ -858,11 +854,11 @@ public List getCalculatedLineSizes() { */ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { - float defaultFormSize = mFormSize; - float stackSpace = mStackSpace; - float formToTextSpace = mFormToTextSpace; - float xEntrySpace = mXEntrySpace; - float yEntrySpace = mYEntrySpace; + float defaultFormSize = Utils.convertDpToPixel(mFormSize); + float stackSpace = Utils.convertDpToPixel(mStackSpace); + float formToTextSpace = Utils.convertDpToPixel(mFormToTextSpace); + float xEntrySpace = Utils.convertDpToPixel(mXEntrySpace); + float yEntrySpace = Utils.convertDpToPixel(mYEntrySpace); boolean wordWrapEnabled = mWordWrapEnabled; LegendEntry[] entries = mEntries; int entryCount = entries.length; @@ -881,7 +877,9 @@ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandle LegendEntry e = entries[i]; boolean drawingForm = e.form != LegendForm.NONE; - float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + float formSize = Float.isNaN(e.formSize) + ? defaultFormSize + : Utils.convertDpToPixel(e.formSize); String label = e.label; if (!wasStacked) @@ -945,7 +943,9 @@ else if (wasStacked) { LegendEntry e = entries[i]; boolean drawingForm = e.form != LegendForm.NONE; - float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + float formSize = Float.isNaN(e.formSize) + ? defaultFormSize + : Utils.convertDpToPixel(e.formSize); String label = e.label; mCalculatedLabelBreakPoints.add(false); @@ -963,7 +963,7 @@ else if (wasStacked) { if (label != null) { mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, label)); - requiredWidth += drawingForm ? mFormToTextSpace + formSize : 0.f; + requiredWidth += drawingForm ? formToTextSpace + formSize : 0.f; requiredWidth += mCalculatedLabelSizes.get(i).width; } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 06dc0b60d6..85597db6a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -236,21 +236,22 @@ public void renderLegend(Canvas c) { mLegendLabelPaint.setColor(mLegend.getTextColor()); float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint, legendFontMetrics); - float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics) + mLegend.getYEntrySpace(); + float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics) + + Utils.convertDpToPixel(mLegend.getYEntrySpace()); float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f; LegendEntry[] entries = mLegend.getEntries(); - float formToTextSpace = mLegend.getFormToTextSpace(); - float xEntrySpace = mLegend.getXEntrySpace(); + float formToTextSpace = Utils.convertDpToPixel(mLegend.getFormToTextSpace()); + float xEntrySpace = Utils.convertDpToPixel(mLegend.getXEntrySpace()); Legend.LegendOrientation orientation = mLegend.getOrientation(); Legend.LegendHorizontalAlignment horizontalAlignment = mLegend.getHorizontalAlignment(); Legend.LegendVerticalAlignment verticalAlignment = mLegend.getVerticalAlignment(); Legend.LegendDirection direction = mLegend.getDirection(); - float defaultFormSize = mLegend.getFormSize(); + float defaultFormSize = Utils.convertDpToPixel(mLegend.getFormSize()); // space between the entries - float stackSpace = mLegend.getStackSpace(); + float stackSpace = Utils.convertDpToPixel(mLegend.getStackSpace()); float yoffset = mLegend.getYOffset(); float xoffset = mLegend.getXOffset(); @@ -334,7 +335,7 @@ public void renderLegend(Canvas c) { LegendEntry e = entries[i]; boolean drawingForm = e.form != Legend.LegendForm.NONE; - float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : Utils.convertDpToPixel(e.formSize); if (i < calculatedLabelBreakPoints.size() && calculatedLabelBreakPoints.get(i)) { posX = originPosX; @@ -415,7 +416,7 @@ public void renderLegend(Canvas c) { LegendEntry e = entries[i]; boolean drawingForm = e.form != Legend.LegendForm.NONE; - float formSize = Float.isNaN(e.formSize) ? defaultFormSize : e.formSize; + float formSize = Float.isNaN(e.formSize) ? defaultFormSize : Utils.convertDpToPixel(e.formSize); float posX = originPosX; @@ -495,7 +496,10 @@ protected void drawForm( mLegendFormPaint.setColor(entry.formColor); - final float formSize = Float.isNaN(entry.formSize) ? legend.getFormSize() : entry.formSize; + final float formSize = Utils.convertDpToPixel( + Float.isNaN(entry.formSize) + ? legend.getFormSize() + : entry.formSize); final float half = formSize / 2f; switch (form) { @@ -520,9 +524,10 @@ protected void drawForm( case LINE: { - final float formLineWidth = Float.isNaN(entry.formLineWidth) - ? legend.getFormLineWidth() - : entry.formLineWidth; + final float formLineWidth = Utils.convertDpToPixel( + Float.isNaN(entry.formLineWidth) + ? legend.getFormLineWidth() + : entry.formLineWidth); final DashPathEffect formLineDashEffect = entry.formLineDashEffect == null ? legend.getFormLineDashEffect() : entry.formLineDashEffect; From dab8db488f66c6958da541f4596acbcf5e7307b5 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 14 Aug 2016 16:52:09 +0300 Subject: [PATCH 1150/1390] neededWidth should be enough here. formSize has no meaning globally. If more offset is needed - use extraOffsets, or adjust the maxSizePercent). --- .../com/github/mikephil/charting/charts/PieRadarChartBase.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 637be47cab..d403a752cc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -115,8 +115,7 @@ public void calculateOffsets() { if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) { float fullLegendWidth = Math.min(mLegend.mNeededWidth, - mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + - mLegend.getFormSize() + mLegend.getFormToTextSpace(); + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()); switch (mLegend.getOrientation()) { case VERTICAL: { From 62bc0de28ac1125597887eaff6046f21b02d5f3b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Aug 2016 21:25:41 +0200 Subject: [PATCH 1151/1390] Cleanup, preparations for autoScaleMinMax fix --- .../mikephil/charting/data/ChartData.java | 31 ++++++++++--------- .../mikephil/charting/data/CombinedData.java | 13 ++++---- .../mikephil/charting/data/PieData.java | 2 +- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 23bd58759b..9bb8dbf107 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -68,7 +68,7 @@ public ChartData() { */ public ChartData(T... dataSets) { mDataSets = arrayToList(dataSets); - init(); + notifyDataChanged(); } /** @@ -95,15 +95,7 @@ private List arrayToList(T[] array) { */ public ChartData(List sets) { this.mDataSets = sets; - init(); - } - - /** - * performs all kinds of initialization calculations, such as min-max and - * value count and sum - */ - protected void init() { - calcMinMax(); + notifyDataChanged(); } /** @@ -112,11 +104,11 @@ protected void init() { * the contained data has changed. */ public void notifyDataChanged() { - init(); + calcMinMax(); } /** - * calc minimum and maximum values (both x and y) over all DataSets + * Calc minimum and maximum values (both x and y) over all DataSets. */ public void calcMinMax() { @@ -145,7 +137,7 @@ public void calcMinMax() { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - for (IDataSet dataSet : mDataSets) { + for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -164,7 +156,7 @@ public void calcMinMax() { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - for (IDataSet dataSet : mDataSets) { + for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -436,6 +428,12 @@ public void addEntry(Entry e, int dataSetIndex) { } } + /** + * Adjusts the current minimum and maximum values based on the provided Entry object. + * + * @param e + * @param axis + */ protected void calcMinMax(Entry e, AxisDependency axis) { if (mYMax < e.getY()) @@ -462,6 +460,11 @@ protected void calcMinMax(Entry e, AxisDependency axis) { } } + /** + * Adjusts the minimum and maximum values based on the given DataSet. + * + * @param d + */ protected void calcMinMax(T d) { if (mYMax < d.getYMax()) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 035ad9e0b3..c81097da90 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -29,27 +29,27 @@ public CombinedData() { public void setData(LineData data) { mLineData = data; - init(); + notifyDataChanged(); } public void setData(BarData data) { mBarData = data; - init(); + notifyDataChanged(); } public void setData(ScatterData data) { mScatterData = data; - init(); + notifyDataChanged(); } public void setData(CandleData data) { mCandleData = data; - init(); + notifyDataChanged(); } public void setData(BubbleData data) { mBubbleData = data; - init(); + notifyDataChanged(); } @Override @@ -104,7 +104,6 @@ public void calcMinMax() { mRightAxisMin = data.mRightAxisMin; } - } public BubbleData getBubbleData() { @@ -166,7 +165,7 @@ public void notifyDataChanged() { if (mBubbleData != null) mBubbleData.notifyDataChanged(); - init(); // recalculate everything + calcMinMax(); // recalculate everything } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index dc920bae50..db7972a3fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -33,7 +33,7 @@ public PieData(IPieDataSet dataSet) { public void setDataSet(IPieDataSet dataSet) { mDataSets.clear(); mDataSets.add(dataSet); - init(); + notifyDataChanged(); } /** From 336dfb93e5c6cb681aa8c660de780617a90480be Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Aug 2016 21:48:05 +0200 Subject: [PATCH 1152/1390] Fix autoScaleMinMax --- .../mikephil/charting/charts/BarChart.java | 2 +- .../charting/charts/BarLineChartBase.java | 21 ++------- .../mikephil/charting/data/BarDataSet.java | 45 +++++++------------ .../mikephil/charting/data/BubbleDataSet.java | 22 +++------ .../mikephil/charting/data/CandleDataSet.java | 31 +++++-------- .../mikephil/charting/data/ChartData.java | 18 +++++++- .../mikephil/charting/data/DataSet.java | 19 ++++++++ .../interfaces/datasets/IDataSet.java | 16 +++++-- 8 files changed, 85 insertions(+), 89 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index a149adf909..8fa91bf5c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -63,7 +63,7 @@ protected void init() { protected void calcMinMax() { if (mAutoScaleMinMaxEnabled) - mData.calcMinMax(); + mData.calcMinMax(getLowestVisibleX(), getHighestVisibleX()); if (mFitBars) { mXAxis.calculate(mData.getXMin() - mData.getBarWidth() / 2f, mData.getXMax() + mData.getBarWidth() / 2f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 494c8bcedb..a80530bdae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -56,8 +56,6 @@ public abstract class BarLineChartBase yVals) { } @Override - public void calcMinMax() { + protected void calcMinMax(BarEntry e) { - if (mValues == null || mValues.isEmpty()) - return; + if (e != null && !Float.isNaN(e.getY())) { - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; + if (e.getYVals() == null) { - for (BarEntry e : mValues) { + if (e.getY() < mYMin) + mYMin = e.getY(); - if (e != null && !Float.isNaN(e.getY())) { + if (e.getY() > mYMax) + mYMax = e.getY(); + } else { - if (e.getYVals() == null) { + if (-e.getNegativeSum() < mYMin) + mYMin = -e.getNegativeSum(); - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); - } else { - - if (-e.getNegativeSum() < mYMin) - mYMin = -e.getNegativeSum(); - - if (e.getPositiveSum() > mYMax) - mYMax = e.getPositiveSum(); - } + if (e.getPositiveSum() > mYMax) + mYMax = e.getPositiveSum(); + } - if (e.getX() < mXMin) - mXMin = e.getX(); + if (e.getX() < mXMin) + mXMin = e.getX(); - if (e.getX() > mXMax) - mXMax = e.getX(); - } + if (e.getX() > mXMax) + mXMax = e.getX(); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index ec288123e2..d8c0c13013 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -29,25 +29,13 @@ public float getHighlightCircleWidth() { } @Override - public void calcMinMax() { + protected void calcMinMax(BubbleEntry e) { + super.calcMinMax(e); - if (mValues == null || mValues.isEmpty()) - return; + final float size = e.getSize(); - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - - for (BubbleEntry e : mValues) { - - calcMinMax(e); - - final float size = e.getSize(); - - if (size > mMaxSize) { - mMaxSize = size; - } + if (size > mMaxSize) { + mMaxSize = size; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 139a1bad42..8d883f0575 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -25,7 +25,7 @@ public class CandleDataSet extends LineScatterCandleRadarDataSet im /** * should the candle bars show? * when false, only "ticks" will show - * + *

    * - default: true */ private boolean mShowCandleBar = true; @@ -101,30 +101,19 @@ public DataSet copy() { } @Override - public void calcMinMax() { - - if (mValues == null || mValues.isEmpty()) - return; - - mYMax = -Float.MAX_VALUE; - mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; + protected void calcMinMax(CandleEntry e) { - for (CandleEntry e : mValues) { + if (e.getLow() < mYMin) + mYMin = e.getLow(); - if (e.getLow() < mYMin) - mYMin = e.getLow(); + if (e.getHigh() > mYMax) + mYMax = e.getHigh(); - if (e.getHigh() > mYMax) - mYMax = e.getHigh(); + if (e.getX() < mXMin) + mXMin = e.getX(); - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); - } + if (e.getX() > mXMax) + mXMax = e.getX(); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 9bb8dbf107..866f258e16 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -107,10 +107,26 @@ public void notifyDataChanged() { calcMinMax(); } + /** + * Calc minimum and maximum values (both x and y) over all DataSets. + * Tell DataSets to recalculate their min and max values, this is needed for autoScaleMinMax. + * + * @param fromX the x-value to start the calculation from + * @param toX the x-value to which the calculation should be performed + */ + public void calcMinMax(float fromX, float toX) { + + for (T set : mDataSets) { + set.calcMinMax(fromX, toX); + } + + calcMinMax(); + } + /** * Calc minimum and maximum values (both x and y) over all DataSets. */ - public void calcMinMax() { + protected void calcMinMax() { if (mDataSets == null) return; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index d337a0482b..6bd5a78c72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -74,6 +74,25 @@ public void calcMinMax() { } } + @Override + public void calcMinMax(float fromX, float toX) { + + if (mValues == null || mValues.isEmpty()) + return; + + mYMax = -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mXMax = -Float.MAX_VALUE; + mXMin = Float.MAX_VALUE; + + int indexFrom = getEntryIndex(fromX, Rounding.CLOSEST); + int indexTo = getEntryIndex(toX, Rounding.CLOSEST); + + for (int i = indexFrom; i <= indexTo; i++) { + calcMinMax(mValues.get(i)); + } + } + /** * Updates the min and max x and y value of this DataSet based on the given Entry. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 62c10b3f32..8130909b95 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -59,6 +59,14 @@ public interface IDataSet { */ void calcMinMax(); + /** + * Calculates the min and max values from the given x-value to the given x-value. + * + * @param fromX + * @param toX + */ + void calcMinMax(float fromX, float toX); + /** * Returns the first Entry object found at the given x-value with binary * search. If the no Entry at the specified x-value is found, this method @@ -372,28 +380,28 @@ public interface IDataSet { /** * The form to draw for this dataset in the legend. - * + *

    * Return `DEFAULT` to use the default legend form. */ Legend.LegendForm getForm(); /** * The form size to draw for this dataset in the legend. - * + *

    * Return `Float.NaN` to use the default legend form size. */ float getFormSize(); /** * The line width for drawing the form of this dataset in the legend - * + *

    * Return `Float.NaN` to use the default legend form line width. */ float getFormLineWidth(); /** * The line dash path effect used for shapes that consist of lines. - * + *

    * Return `null` to use the default legend form line dash effect. */ DashPathEffect getFormLineDashEffect(); From 1bbf4be1eed520a1da075d2e5a5d4cfb686ff4bd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 14 Aug 2016 22:22:48 +0200 Subject: [PATCH 1153/1390] Fixes and finishing up of autoScaleMinMax feature --- .../mikephil/charting/charts/BarChart.java | 3 -- .../charting/charts/BarLineChartBase.java | 27 +++++++++++++---- .../mikephil/charting/data/BarDataSet.java | 6 +--- .../mikephil/charting/data/CandleDataSet.java | 6 +--- .../mikephil/charting/data/ChartData.java | 9 +++--- .../mikephil/charting/data/DataSet.java | 30 ++++++++++++------- .../mikephil/charting/data/PieDataSet.java | 6 +--- .../interfaces/datasets/IDataSet.java | 5 ++-- 8 files changed, 52 insertions(+), 40 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index 8fa91bf5c9..a805815952 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -62,9 +62,6 @@ protected void init() { @Override protected void calcMinMax() { - if (mAutoScaleMinMaxEnabled) - mData.calcMinMax(getLowestVisibleX(), getHighestVisibleX()); - if (mFitBars) { mXAxis.calculate(mData.getXMin() - mData.getBarWidth() / 2f, mData.getXMax() + mData.getBarWidth() / 2f); } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index a80530bdae..817c70b6c9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -204,9 +204,7 @@ protected void onDraw(Canvas canvas) { mAxisRendererRight.renderAxisLine(canvas); if (mAutoScaleMinMaxEnabled) { - - calcMinMax(); - calculateOffsets(); + autoScale(); } mXAxisRenderer.renderGridLines(canvas); @@ -325,12 +323,29 @@ public void notifyDataSetChanged() { calculateOffsets(); } + /** + * Performs auto scaling of the axis by recalculating the minimum and maximum y-values based on the entries currently in view. + */ + protected void autoScale() { + + final float fromX = getLowestVisibleX(); + final float toX = getHighestVisibleX(); + + mData.calcMinMaxY(fromX, toX); + + mXAxis.calculate(mData.getXMin(), mData.getXMax()); + + // calculate axis range (min / max) according to provided data + mAxisLeft.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); + mAxisRight.calculate(mData.getYMin(AxisDependency.RIGHT), mData.getYMax(AxisDependency + .RIGHT)); + + calculateOffsets(); + } + @Override protected void calcMinMax() { - if (mAutoScaleMinMaxEnabled) - mData.calcMinMax(getLowestVisibleX(), getHighestVisibleX()); - mXAxis.calculate(mData.getXMin(), mData.getXMax()); // calculate axis range (min / max) according to provided data diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index c11eb2b9cc..ae11c97b3c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -127,11 +127,7 @@ protected void calcMinMax(BarEntry e) { mYMax = e.getPositiveSum(); } - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); + calcMinMaxX(e); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 8d883f0575..13bf6062d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -109,11 +109,7 @@ protected void calcMinMax(CandleEntry e) { if (e.getHigh() > mYMax) mYMax = e.getHigh(); - if (e.getX() < mXMin) - mXMin = e.getX(); - - if (e.getX() > mXMax) - mXMax = e.getX(); + calcMinMaxX(e); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 866f258e16..1ffc1dbcc4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -108,18 +108,19 @@ public void notifyDataChanged() { } /** - * Calc minimum and maximum values (both x and y) over all DataSets. - * Tell DataSets to recalculate their min and max values, this is needed for autoScaleMinMax. + * Calc minimum and maximum y-values over all DataSets. + * Tell DataSets to recalculate their min and max y-values, this is only needed for autoScaleMinMax. * * @param fromX the x-value to start the calculation from * @param toX the x-value to which the calculation should be performed */ - public void calcMinMax(float fromX, float toX) { + public void calcMinMaxY(float fromX, float toX) { for (T set : mDataSets) { - set.calcMinMax(fromX, toX); + set.calcMinMaxY(fromX, toX); } + // apply the new data calcMinMax(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 6bd5a78c72..4aa8a17409 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -75,21 +75,21 @@ public void calcMinMax() { } @Override - public void calcMinMax(float fromX, float toX) { + public void calcMinMaxY(float fromX, float toX) { if (mValues == null || mValues.isEmpty()) return; mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - mXMax = -Float.MAX_VALUE; - mXMin = Float.MAX_VALUE; - int indexFrom = getEntryIndex(fromX, Rounding.CLOSEST); - int indexTo = getEntryIndex(toX, Rounding.CLOSEST); + int indexFrom = getEntryIndex(fromX, Rounding.DOWN); + int indexTo = getEntryIndex(toX, Rounding.UP); for (int i = indexFrom; i <= indexTo; i++) { - calcMinMax(mValues.get(i)); + + // only recalculate y + calcMinMaxY(mValues.get(i)); } } @@ -103,11 +103,12 @@ protected void calcMinMax(T e) { if (e == null) return; - if (e.getY() < mYMin) - mYMin = e.getY(); + calcMinMaxX(e); - if (e.getY() > mYMax) - mYMax = e.getY(); + calcMinMaxY(e); + } + + protected void calcMinMaxX(T e) { if (e.getX() < mXMin) mXMin = e.getX(); @@ -116,6 +117,15 @@ protected void calcMinMax(T e) { mXMax = e.getX(); } + protected void calcMinMaxY(T e) { + + if (e.getY() < mYMin) + mYMin = e.getY(); + + if (e.getY() > mYMax) + mYMax = e.getY(); + } + @Override public int getEntryCount() { return mValues.size(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 316aab4773..3e864a25d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -51,11 +51,7 @@ protected void calcMinMax(PieEntry e) { if (e == null) return; - if (e.getY() < mYMin) - mYMin = e.getY(); - - if (e.getY() > mYMax) - mYMax = e.getY(); + calcMinMaxY(e); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 8130909b95..337adc35d2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -60,12 +60,13 @@ public interface IDataSet { void calcMinMax(); /** - * Calculates the min and max values from the given x-value to the given x-value. + * Calculates the min and max y-values from the Entry closest to the given fromX to the Entry closest to the given toX value. + * This is only needed for the autoScaleMinMax feature. * * @param fromX * @param toX */ - void calcMinMax(float fromX, float toX); + void calcMinMaxY(float fromX, float toX); /** * Returns the first Entry object found at the given x-value with binary From 6c17ca45de833f1f66493eee36f2190dbe703497 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 15 Aug 2016 15:21:33 +0300 Subject: [PATCH 1154/1390] Take care of edge cases when calculating intervals (labelCount == 0) --- .../com/github/mikephil/charting/renderer/AxisRenderer.java | 4 ++++ .../mikephil/charting/renderer/YAxisRendererRadarChart.java | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 1b9c82364a..33198f7198 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -162,6 +162,10 @@ protected void computeAxisValues(float min, float max) { // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; + if (Double.isInfinite(rawInterval)) + { + rawInterval = range > 0.0 ? range : 1.0; + } double interval = Utils.roundToNextSignificant(rawInterval); // If granularity is enabled, then do not allow the interval to go below specified granularity. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 9a5fd1cd44..fdef622cc8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -40,6 +40,10 @@ protected void computeAxisValues(float min, float max) { // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; + if (Double.isInfinite(rawInterval)) + { + rawInterval = range > 0.0 ? range : 1.0; + } double interval = Utils.roundToNextSignificant(rawInterval); // If granularity is enabled, then do not allow the interval to go below specified granularity. From e556275e292a226c6bd8655c4f5ab1757e45049f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 15 Aug 2016 15:23:44 +0300 Subject: [PATCH 1155/1390] range may also be Infinite when xMin/xMax are MAX --- .../com/github/mikephil/charting/renderer/AxisRenderer.java | 2 +- .../mikephil/charting/renderer/YAxisRendererRadarChart.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 33198f7198..c96a4d45fe 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -164,7 +164,7 @@ protected void computeAxisValues(float min, float max) { double rawInterval = range / labelCount; if (Double.isInfinite(rawInterval)) { - rawInterval = range > 0.0 ? range : 1.0; + rawInterval = range > 0.0 && !Double.isInfinite(range) ? range : 1.0; } double interval = Utils.roundToNextSignificant(rawInterval); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index fdef622cc8..83d835755c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -42,7 +42,7 @@ protected void computeAxisValues(float min, float max) { double rawInterval = range / labelCount; if (Double.isInfinite(rawInterval)) { - rawInterval = range > 0.0 ? range : 1.0; + rawInterval = range > 0.0 && !Double.isInfinite(range) ? range : 1.0; } double interval = Utils.roundToNextSignificant(rawInterval); From 73148a6aa4ad590b02d7307dd31968ec2d4ae918 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 15 Aug 2016 15:50:08 +0300 Subject: [PATCH 1156/1390] Simplified some code --- .../charting/utils/ViewPortHandler.java | 46 ++++++------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index eedd190456..541c726eeb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -576,42 +576,33 @@ public Matrix getMatrixTouch() { */ public boolean isInBoundsX(float x) { - if (isInBoundsLeft(x) && isInBoundsRight(x)) - return true; - else - return false; + return isInBoundsLeft(x) && isInBoundsRight(x); } public boolean isInBoundsY(float y) { - if (isInBoundsTop(y) && isInBoundsBottom(y)) - return true; - else - return false; + return isInBoundsTop(y) && isInBoundsBottom(y); } public boolean isInBounds(float x, float y) { - if (isInBoundsX(x) && isInBoundsY(y)) - return true; - else - return false; + return isInBoundsX(x) && isInBoundsY(y); } public boolean isInBoundsLeft(float x) { - return mContentRect.left <= x + 1 ? true : false; + return mContentRect.left <= x + 1; } public boolean isInBoundsRight(float x) { x = (float) ((int) (x * 100.f)) / 100.f; - return mContentRect.right >= x - 1 ? true : false; + return mContentRect.right >= x - 1; } public boolean isInBoundsTop(float y) { - return mContentRect.top <= y ? true : false; + return mContentRect.top <= y; } public boolean isInBoundsBottom(float y) { y = (float) ((int) (y * 100.f)) / 100.f; - return mContentRect.bottom >= y ? true : false; + return mContentRect.bottom >= y; } /** @@ -669,10 +660,7 @@ public float getTransY() { */ public boolean isFullyZoomedOut() { - if (isFullyZoomedOutX() && isFullyZoomedOutY()) - return true; - else - return false; + return isFullyZoomedOutX() && isFullyZoomedOutY(); } /** @@ -681,10 +669,7 @@ public boolean isFullyZoomedOut() { * @return */ public boolean isFullyZoomedOutY() { - if (mScaleY > mMinScaleY || mMinScaleY > 1f) - return false; - else - return true; + return !(mScaleY > mMinScaleY || mMinScaleY > 1f); } /** @@ -694,10 +679,7 @@ public boolean isFullyZoomedOutY() { * @return */ public boolean isFullyZoomedOutX() { - if (mScaleX > mMinScaleX || mMinScaleX > 1f) - return false; - else - return true; + return !(mScaleX > mMinScaleX || mMinScaleX > 1f); } /** @@ -735,7 +717,7 @@ public boolean hasNoDragOffset() { * @return */ public boolean canZoomOutMoreX() { - return (mScaleX > mMinScaleX); + return mScaleX > mMinScaleX; } /** @@ -744,7 +726,7 @@ public boolean canZoomOutMoreX() { * @return */ public boolean canZoomInMoreX() { - return (mScaleX < mMaxScaleX); + return mScaleX < mMaxScaleX; } /** @@ -753,7 +735,7 @@ public boolean canZoomInMoreX() { * @return */ public boolean canZoomOutMoreY() { - return (mScaleY > mMinScaleY); + return mScaleY > mMinScaleY; } /** @@ -762,6 +744,6 @@ public boolean canZoomOutMoreY() { * @return */ public boolean canZoomInMoreY() { - return (mScaleY < mMaxScaleY); + return mScaleY < mMaxScaleY; } } From 5daa6dc23cf95fe62251a9ddf1197e6b8532e639 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 15 Aug 2016 15:59:33 +0300 Subject: [PATCH 1157/1390] Fill before stroke - because the fill may cover half of a thick stroke --- .../mikephil/charting/renderer/LineChartRenderer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 516b3b7391..ada9c37715 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -300,6 +300,11 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mXBounds.set(mChart, dataSet); + // if drawing filled is enabled + if (dataSet.isDrawFilledEnabled() && entryCount > 0) { + drawLinearFill(c, dataSet, trans, mXBounds); + } + // more than 1 color if (dataSet.getColors().size() > 1) { @@ -403,11 +408,6 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { } mRenderPaint.setPathEffect(null); - - // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entryCount > 0) { - drawLinearFill(c, dataSet, trans, mXBounds); - } } protected Path mGenerateFilledPathBuffer = new Path(); From cc971a7d02210b6ae6b2836d55e5241dad7595bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20K=C3=B6pke?= Date: Wed, 17 Aug 2016 19:44:48 +0200 Subject: [PATCH 1158/1390] fixed LineChartRenderer to get correct x values when using cubicFill --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index ada9c37715..74af4d04ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -252,8 +252,8 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); - spline.lineTo(bounds.min + bounds.range, fillMin); - spline.lineTo(bounds.min, fillMin); + spline.lineTo(dataSet.getEntryForIndex(mXBounds.max).getX(), fillMin); + spline.lineTo(dataSet.getEntryForIndex(mXBounds.min).getX(), fillMin); spline.close(); trans.pathValueToPixel(spline); From 918950b6ad8109a182a96320a50bf13f73a27de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20K=C3=B6pke?= Date: Wed, 17 Aug 2016 19:44:48 +0200 Subject: [PATCH 1159/1390] respect phaseX when drawing cubicFill --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 74af4d04ef..63b0ad5c8b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -252,8 +252,8 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); - spline.lineTo(dataSet.getEntryForIndex(mXBounds.max).getX(), fillMin); - spline.lineTo(dataSet.getEntryForIndex(mXBounds.min).getX(), fillMin); + spline.lineTo(dataSet.getEntryForIndex(bounds.min + bounds.range).getX(), fillMin); + spline.lineTo(dataSet.getEntryForIndex(bounds.min).getX(), fillMin); spline.close(); trans.pathValueToPixel(spline); From 9d0b0fd955ffe0ecff43fa5173c2a20369941a9c Mon Sep 17 00:00:00 2001 From: Benoit Vermont Date: Thu, 18 Aug 2016 16:48:28 +0200 Subject: [PATCH 1160/1390] Update ComponentBase.java Update the documentation for setTextSize, to reflect that the parameter size is in DP, and not in pixel. --- .../github/mikephil/charting/components/ComponentBase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java index 99e9c7a41b..159b6506f4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java @@ -107,10 +107,10 @@ public void setTypeface(Typeface tf) { } /** - * sets the size of the label text in pixels min = 6f, max = 24f, default + * sets the size of the label text in density pixels min = 6f, max = 24f, default * 10f * - * @param size + * @param size the text size, in DP */ public void setTextSize(float size) { @@ -123,7 +123,7 @@ public void setTextSize(float size) { } /** - * returns the text size that is currently set for the labels + * returns the text size that is currently set for the labels, in pixels * * @return */ From e5d03ba6409fde7f796f056345212293b5a0a1ee Mon Sep 17 00:00:00 2001 From: Voicu Date: Mon, 22 Aug 2016 23:30:43 -0700 Subject: [PATCH 1161/1390] Remove nullcheck for known non-null value --- .../com/github/mikephil/charting/components/MarkerImage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java index 5c952bb056..1d65436e72 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java @@ -142,10 +142,10 @@ public void draw(Canvas canvas, float posX, float posY) { float width = mSize.width; float height = mSize.height; - if (width == 0.f && mDrawable != null) { + if (width == 0.f) { width = mDrawable.getIntrinsicWidth(); } - if (height == 0.f && mDrawable != null) { + if (height == 0.f) { height = mDrawable.getIntrinsicHeight(); } From afcb72f50f3fcc886f423c16e76581acb6bd8fc1 Mon Sep 17 00:00:00 2001 From: Marcin Date: Wed, 24 Aug 2016 14:52:42 +0100 Subject: [PATCH 1162/1390] Fix for pie chart, so small values won't appear as "background" (which really is a huge circle) --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 530e282a26..1681d5baae 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -263,16 +263,14 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mPathBuffer.reset(); - float arcStartPointX = 0.f, arcStartPointY = 0.f; + float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); if (sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { - arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); - arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); - mPathBuffer.moveTo(arcStartPointX, arcStartPointY); mPathBuffer.arcTo( From fd3b71f78053fe57c5ff0297c6f4be6722835144 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 29 Aug 2016 22:21:59 +0300 Subject: [PATCH 1163/1390] Reuse index --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 63b0ad5c8b..5a7da70377 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -146,7 +146,7 @@ protected void drawHorizontalBezier(ILineDataSet dataSet) { for (int j = mXBounds.min + 1; j <= mXBounds.range + mXBounds.min; j++) { - prev = dataSet.getEntryForIndex(j - 1); + prev = cur; cur = dataSet.getEntryForIndex(j); final float cpx = (prev.getX()) From 01419f795bf87ecdbc90c1f61f9bffbad6c79952 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Wed, 31 Aug 2016 09:19:05 +0200 Subject: [PATCH 1164/1390] Remove psd --- design/video_thumbnail.psd | Bin 263006 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 design/video_thumbnail.psd diff --git a/design/video_thumbnail.psd b/design/video_thumbnail.psd deleted file mode 100644 index 4695da67291fbfaf3988c045009388e26ae01223..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 263006 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 From 7b33554d5be299ff922a182b06704fa95f950dfa Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 4 Sep 2016 10:44:23 +0200 Subject: [PATCH 1165/1390] Minor changes & documentation --- MPChartExample/build.gradle | 2 +- .../mikephil/charting/components/AxisBase.java | 16 +++++++++++----- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 3 ++- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index c0d4745dcc..a7e8efa03b 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -39,7 +39,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.2' + classpath 'com.android.tools.build:gradle:2.1.3' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 1805db001a..c2e04fc0a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -183,6 +183,12 @@ public boolean isDrawAxisLineEnabled() { return mDrawAxisLine; } + /** + * Centers the axis labels instead of drawing them at their original position. + * This is useful especially for grouped BarChart. + * + * @param enabled + */ public void setCenterAxisLabels(boolean enabled) { mCenterAxisLabels = enabled; } @@ -504,13 +510,13 @@ public void enableGridDashedLine(float lineLength, float spaceLength, float phas lineLength, spaceLength }, phase); } - + /** * Enables the grid line to be drawn in dashed mode, e.g. like this * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. * Keep in mind that hardware acceleration boosts performance. * - * @param effect the DashPathEffect + * @param effect the DashPathEffect */ public void setGridDashedLine(DashPathEffect effect) { mGridDashPathEffect = effect; @@ -540,7 +546,7 @@ public boolean isGridDashedLineEnabled() { public DashPathEffect getGridDashPathEffect() { return mGridDashPathEffect; } - + /** * Enables the axis line to be drawn in dashed mode, e.g. like this @@ -556,13 +562,13 @@ public void enableAxisLineDashedLine(float lineLength, float spaceLength, float lineLength, spaceLength }, phase); } - + /** * Enables the axis line to be drawn in dashed mode, e.g. like this * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. * Keep in mind that hardware acceleration boosts performance. * - * @param effect the DashPathEffect + * @param effect the DashPathEffect */ public void setAxisLineDashedLine(DashPathEffect effect) { mAxisLineDashPathEffect = effect; diff --git a/build.gradle b/build.gradle index 3dfff3b287..588bad10b1 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:1.1.0" - classpath 'com.android.tools.build:gradle:2.1.2' + classpath 'com.android.tools.build:gradle:2.1.3' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9851e51576..aecf1e6c37 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Sat Sep 03 21:01:56 CEST 2016 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip From 8f5a898a95bee7fbb5b24b9ee00084e94e36dd2c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 14 Sep 2016 22:22:32 +0300 Subject: [PATCH 1166/1390] Improved naming --- .../java/com/github/mikephil/charting/data/BarEntry.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index 023a159750..dbf1e945db 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -142,7 +142,15 @@ public boolean isStacked() { return mYVals != null; } + /** + * Use `getSumBelow(stackIndex)` instead. + */ + @Deprecated public float getBelowSum(int stackIndex) { + return getSumBelow(stackIndex); + } + + public float getSumBelow(int stackIndex) { if (mYVals == null) return 0; From a6dd5bb4a127ed72c11b184cf14aa908a8d78e05 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 14 Sep 2016 23:47:55 +0300 Subject: [PATCH 1167/1390] Improved naming before the big release --- .../java/com/github/mikephil/charting/components/IMarker.java | 2 +- .../com/github/mikephil/charting/components/MarkerImage.java | 4 ++-- .../com/github/mikephil/charting/components/MarkerView.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java index c15dae3a0c..3b8ca43c81 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/IMarker.java @@ -24,7 +24,7 @@ public interface IMarker { * @param posY This is the X position at which the marker wants to be drawn. * You can adjust the offset conditionally based on this argument. */ - MPPointF getOffsetForDrawingAtPos(float posX, float posY); + MPPointF getOffsetForDrawingAtPoint(float posX, float posY); /** * This method enables a specified custom IMarker to update it's content every time the IMarker is redrawn. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java index 5c952bb056..f164d8341f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerImage.java @@ -94,7 +94,7 @@ public Chart getChartView() { } @Override - public MPPointF getOffsetForDrawingAtPos(float posX, float posY) { + public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) { MPPointF offset = getOffset(); mOffset2.x = offset.x; @@ -137,7 +137,7 @@ public void draw(Canvas canvas, float posX, float posY) { if (mDrawable == null) return; - MPPointF offset = getOffsetForDrawingAtPos(posX, posY); + MPPointF offset = getOffsetForDrawingAtPoint(posX, posY); float width = mSize.width; float height = mSize.height; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java index 478527caee..162e88e33c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/MarkerView.java @@ -80,7 +80,7 @@ public Chart getChartView() { } @Override - public MPPointF getOffsetForDrawingAtPos(float posX, float posY) { + public MPPointF getOffsetForDrawingAtPoint(float posX, float posY) { MPPointF offset = getOffset(); mOffset2.x = offset.x; @@ -118,7 +118,7 @@ public void refreshContent(Entry e, Highlight highlight) { @Override public void draw(Canvas canvas, float posX, float posY) { - MPPointF offset = getOffsetForDrawingAtPos(posX, posY); + MPPointF offset = getOffsetForDrawingAtPoint(posX, posY); int saveId = canvas.save(); // translate to the correct position and draw From a3c1fe6bbf7d48b79b42b3a447f946af850d86f0 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 15 Sep 2016 09:12:59 +0300 Subject: [PATCH 1168/1390] Added missing clip rect for zero line --- .../github/mikephil/charting/renderer/YAxisRenderer.java | 9 +++++++++ .../renderer/YAxisRendererHorizontalBarChart.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 092714788a..46f581732c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -211,11 +211,18 @@ protected float[] getTransformedPositions() { } protected Path mDrawZeroLinePath = new Path(); + protected RectF mZeroLineClippingRect = new RectF(); + /** * Draws the zero line. */ protected void drawZeroLine(Canvas c) { + int clipRestoreCount = c.save(); + mZeroLineClippingRect.set(mViewPortHandler.getContentRect()); + mZeroLineClippingRect.inset(0.f, -mYAxis.getZeroLineWidth() / 2.f); + c.clipRect(mLimitLineClippingRect); + // draw zero line MPPointD pos = mTrans.getPixelForValues(0f, 0f); @@ -230,6 +237,8 @@ protected void drawZeroLine(Canvas c) { // draw a path because lines don't support dashing on lower android versions c.drawPath(zeroLinePath, mZeroLinePaint); + + c.restoreToCount(clipRestoreCount); } protected Path mRenderLimitLines = new Path(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index f867cf5f3a..8822ca5a23 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -186,6 +186,11 @@ protected Path linePath(Path p, int i, float[] positions) { @Override protected void drawZeroLine(Canvas c) { + int clipRestoreCount = c.save(); + mZeroLineClippingRect.set(mViewPortHandler.getContentRect()); + mZeroLineClippingRect.inset(-mYAxis.getZeroLineWidth() / 2.f, 0.f); + c.clipRect(mLimitLineClippingRect); + // draw zero line MPPointD pos = mTrans.getPixelForValues(0f, 0f); @@ -200,6 +205,10 @@ protected void drawZeroLine(Canvas c) { // draw a path because lines don't support dashing on lower android versions c.drawPath(zeroLinePath, mZeroLinePaint); + + c.restoreToCount(clipRestoreCount); + + c.restoreToCount(clipRestoreCount); } protected Path mRenderLimitLinesPathBuffer = new Path(); From 643f901b157625ebfc5120207e794939e5570872 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sat, 17 Sep 2016 21:36:59 +0200 Subject: [PATCH 1169/1390] Make chart description a Component which allows to treat description similar to Legend or Axis (issue #2249) --- .../mpchartexample/AnotherBarActivity.java | 2 +- .../mpchartexample/BarChartActivity.java | 2 +- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 2 +- .../mpchartexample/BubbleChartActivity.java | 2 +- .../CandleStickChartActivity.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 2 +- .../mpchartexample/FilledLineActivity.java | 2 +- .../mpchartexample/HalfPieChartActivity.java | 2 +- .../HorizontalBarChartActivity.java | 2 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 3 +- .../LineChartActivityColored.java | 2 +- .../mpchartexample/LineChartTime.java | 2 +- .../ListViewBarChartActivity.java | 2 +- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PerformanceLineChart.java | 2 +- .../mpchartexample/PieChartActivity.java | 2 +- .../PiePolylineChartActivity.java | 2 +- .../mpchartexample/RadarChartActivitry.java | 2 +- .../RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 3 +- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 2 +- .../StackedBarActivityNegative.java | 2 +- .../fragments/BarChartFrag.java | 2 +- .../fragments/ComplexityFragment.java | 4 +- .../fragments/PieChartFrag.java | 2 +- .../fragments/ScatterChartFrag.java | 2 +- .../fragments/SineCosineFragment.java | 4 +- .../listviewitems/BarChartItem.java | 2 +- .../listviewitems/LineChartItem.java | 2 +- .../listviewitems/PieChartItem.java | 2 +- .../realm/RealmBaseActivity.java | 2 +- .../mikephil/charting/charts/Chart.java | 123 ++++++------------ .../charting/components/ComponentBase.java | 4 +- .../charting/components/Description.java | 95 ++++++++++++++ 41 files changed, 180 insertions(+), 124 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/components/Description.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 7e867af488..ba01acd794 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -47,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 71aba6f1dd..53e33c969b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -66,7 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 4024260cc6..3d3efa7076 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // mChart.setDrawBorders(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 31f9fa1e56..a7177ff054 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index e9b7fc7a50..6fe6bc8e8c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -47,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index aabd600026..22f4afe3c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mChart = (BubbleChart) findViewById(R.id.chart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setOnChartValueSelectedListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 1a9d899624..3921215be6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -50,7 +50,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (CandleStickChart) findViewById(R.id.chart1); mChart.setBackgroundColor(Color.WHITE); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 224b1f1fe6..ad3d7e01ea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -49,7 +49,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_combined); mChart = (CombinedChart) findViewById(R.id.chart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setBackgroundColor(Color.WHITE); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 2752af37f9..cb979e80e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setBackgroundColor(Color.rgb(104, 241, 175)); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 3462a74af8..7d3e5f431f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -35,7 +35,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // add an empty data object mChart.setData(new LineData()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index dbc44a34f8..d824167d6b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -39,7 +39,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawBorders(true); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 487da96b7e..0b2f44e04f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -43,7 +43,7 @@ protected void onCreate(Bundle savedInstanceState) { moveOffScreen(); mChart.setUsePercentValues(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setCenterTextTypeface(mTfLight); mChart.setCenterText(generateCenterSpannableText()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 316ef4ecac..71c278fb77 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -60,7 +60,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValueAboveBar(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 9360db623f..a1be487e05 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -61,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index ab2f226efa..72d8638a59 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -72,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index e46d582e6a..eb9c754e1d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -2,6 +2,7 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; +import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -60,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index b66b166320..e3c35c75a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -56,7 +56,7 @@ private void setupChart(LineChart chart, LineData data, int color) { ((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color); // no description text - chart.setDescription(""); + chart.getDescription().setEnabled(false); chart.setNoDataTextDescription("You need to provide data for the chart."); // mChart.setDrawHorizontalGrid(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 9380835ed8..84140938e1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index c3eb7fbf5e..7ee212ff60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -84,7 +84,7 @@ public View getView(int position, View convertView, ViewGroup parent) { // apply styling data.setValueTypeface(mTfLight); data.setValueTextColor(Color.BLACK); - holder.chart.setDescription(""); + holder.chart.getDescription().setEnabled(false); holder.chart.setDrawGridBackground(false); XAxis xAxis = holder.chart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 8d9060a2b6..e8f6182da2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -52,7 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setDrawBorders(false); mChart.getAxisLeft().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 8d2fc7f170..681d241c47 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -42,7 +42,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index f514110d59..a33f8e4a01 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -57,7 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setExtraOffsets(5, 10, 5, 5); mChart.setDragDecelerationFrictionCoef(0.95f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index d84301632f..6583129505 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -62,7 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setExtraOffsets(5, 10, 5, 5); mChart.setDragDecelerationFrictionCoef(0.95f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 51bd19dfad..804df1ec2a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -47,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (RadarChart) findViewById(R.id.chart1); mChart.setBackgroundColor(Color.rgb(60, 65, 82)); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setWebLineWidth(1f); mChart.setWebColor(Color.LTGRAY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 97410b0ca8..4ca946530e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -40,7 +40,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); // no description text - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index c6b457eb1a..ebf43a831d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -52,8 +52,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mChart = (ScatterChart) findViewById(R.id.chart1); - mChart.setDescription(""); - + mChart.getDescription().setEnabled(false); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 617a25b2e0..ff098c32e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -28,7 +28,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index ff4fde35d0..b6c10d700e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (BarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index af04d3ae26..4758490a77 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -49,7 +49,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (HorizontalBarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 286f0d58e4..1cdba2735f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -33,7 +33,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa // create a new chart object mChart = new BarChart(getActivity()); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); mChart.setOnChartGestureListener(this); MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index 98b904b2b7..caf9e3e295 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -26,8 +26,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View v = inflater.inflate(R.layout.frag_simple_line, container, false); mChart = (LineChart) v.findViewById(R.id.lineChart1); - - mChart.setDescription(""); + + mChart.getDescription().setEnabled(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index ae7ca9f19c..dc30f303ec 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -29,7 +29,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View v = inflater.inflate(R.layout.frag_simple_pie, container, false); mChart = (PieChart) v.findViewById(R.id.pieChart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index cb1bd1c7e7..90aba051d3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -29,7 +29,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View v = inflater.inflate(R.layout.frag_simple_scatter, container, false); mChart = (ScatterChart) v.findViewById(R.id.scatterChart1); - mChart.setDescription(""); + mChart.getDescription().setEnabled(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 648a0f01d0..60173c368f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -26,8 +26,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa View v = inflater.inflate(R.layout.frag_simple_line, container, false); mChart = (LineChart) v.findViewById(R.id.lineChart1); - - mChart.setDescription(""); + + mChart.getDescription().setEnabled(false); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index ab3c99b7c8..cf9b4b553d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -48,7 +48,7 @@ public View getView(int position, View convertView, Context c) { } // apply styling - holder.chart.setDescription(""); + holder.chart.getDescription().setEnabled(false); holder.chart.setDrawGridBackground(false); holder.chart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index c1796258f4..f988844fce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -50,7 +50,7 @@ public View getView(int position, View convertView, Context c) { // apply styling // holder.chart.setValueTypeface(mTf); - holder.chart.setDescription(""); + holder.chart.getDescription().setEnabled(false); holder.chart.setDrawGridBackground(false); XAxis xAxis = holder.chart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index f803eb8072..8a2ff8bda6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -56,7 +56,7 @@ public View getView(int position, View convertView, Context c) { } // apply styling - holder.chart.setDescription(""); + holder.chart.getDescription().setEnabled(false); holder.chart.setHoleRadius(52f); holder.chart.setTransparentCircleRadius(57f); holder.chart.setCenterText(mCenterText); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index d4fef69576..27bdff9ce3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -36,7 +36,7 @@ protected void setup(Chart chart) { mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); // no description text - chart.setDescription(""); + chart.getDescription().setEnabled(false); chart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 9b409baa00..6a666b38e5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -13,7 +13,6 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.RectF; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Environment; import android.provider.MediaStore.Images; @@ -27,6 +26,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.IMarker; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; @@ -112,11 +112,6 @@ public abstract class Chart 16f) - size = 16f; - if (size < 6f) - size = 6f; - - mDescPaint.setTextSize(Utils.convertDpToPixel(size)); - } - - /** - * Sets the color of the description text. - * - * @param color - */ - public void setDescriptionColor(int color) { - mDescPaint.setColor(color); - } - /** * Sets extra offsets (around the chart view) to be appended to the * auto-calculated offsets. @@ -1285,6 +1228,24 @@ public IMarker getMarkerView() { return getMarker(); } + /** + * Sets a new Description object for the chart. + * + * @param desc + */ + public void setDescription(Description desc) { + this.mDescription = desc; + } + + /** + * Returns the Description object of the chart. + * + * @return + */ + public Description getDescription() { + return mDescription; + } + /** * Returns the Legend object of the chart. This method can be used to get an * instance of the legend in order to customize the automatically generated diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java index 159b6506f4..7d31d0350a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java @@ -19,12 +19,12 @@ public abstract class ComponentBase { protected boolean mEnabled = true; /** - * the offset in pixels this axis labels have on the x-axis + * the offset in pixels this component has on the x-axis */ protected float mXOffset = 5f; /** - * the offset in pixels this axis labels have on the Y-axis + * the offset in pixels this component has on the Y-axis */ protected float mYOffset = 5f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Description.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Description.java new file mode 100644 index 0000000000..18294a3270 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Description.java @@ -0,0 +1,95 @@ +package com.github.mikephil.charting.components; + +import android.graphics.Paint; + +import com.github.mikephil.charting.utils.MPPointF; +import com.github.mikephil.charting.utils.Utils; + +/** + * Created by Philipp Jahoda on 17/09/16. + */ +public class Description extends ComponentBase { + + /** + * the text used in the description + */ + private String text = "Description Label"; + + /** + * the custom position of the description text + */ + private MPPointF mPosition; + + /** + * the alignment of the description text + */ + private Paint.Align mTextAlign = Paint.Align.RIGHT; + + public Description() { + super(); + + // default size + mTextSize = Utils.convertDpToPixel(8f); + } + + /** + * Sets the text to be shown as the description. + * Never set this to null as this will cause nullpointer exception when drawing with Android Canvas. + * + * @param text + */ + public void setText(String text) { + this.text = text; + } + + /** + * Returns the description text. + * + * @return + */ + public String getText() { + return text; + } + + /** + * Sets a custom position for the description text in pixels on the screen. + * + * @param x - xcoordinate + * @param y - ycoordinate + */ + public void setPosition(float x, float y) { + if (mPosition == null) { + mPosition = MPPointF.getInstance(x, y); + } else { + mPosition.x = x; + mPosition.y = y; + } + } + + /** + * Returns the customized position of the description, or null if none set. + * + * @return + */ + public MPPointF getPosition() { + return mPosition; + } + + /** + * Sets the text alignment of the description text. Default RIGHT. + * + * @param align + */ + public void setTextAlign(Paint.Align align) { + this.mTextAlign = align; + } + + /** + * Returns the text alignment of the description. + * + * @return + */ + public Paint.Align getTextAlign() { + return mTextAlign; + } +} From d34670fa620af9353da4fedc78d2c8653fe5c5b1 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sat, 17 Sep 2016 23:23:12 +0200 Subject: [PATCH 1170/1390] Remove noDataTextDescription - this can be done via noDataText as well --- .../mpchartexample/LineChartActivity1.java | 1 - .../mpchartexample/LineChartActivity2.java | 1 - .../LineChartActivityColored.java | 1 - .../mpchartexample/LineChartTime.java | 1 - .../mpchartexample/PerformanceLineChart.java | 1 - .../RealtimeLineChartActivity.java | 5 +-- .../realm/RealmBaseActivity.java | 1 - .../mikephil/charting/charts/Chart.java | 37 ++++--------------- 8 files changed, 9 insertions(+), 39 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 72d8638a59..bfb14090ab 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -73,7 +73,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.getDescription().setEnabled(false); - mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index eb9c754e1d..5cdeacf3a9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -62,7 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.getDescription().setEnabled(false); - mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index e3c35c75a2..68bba4b458 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -57,7 +57,6 @@ private void setupChart(LineChart chart, LineData data, int color) { // no description text chart.getDescription().setEnabled(false); - chart.setNoDataTextDescription("You need to provide data for the chart."); // mChart.setDrawHorizontalGrid(false); // diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 84140938e1..7208f3f0da 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -54,7 +54,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.getDescription().setEnabled(false); - mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 681d241c47..0763f7f88a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -43,7 +43,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.getDescription().setEnabled(false); - mChart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 4ca946530e..30f38126ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -39,9 +39,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - // no description text - mChart.getDescription().setEnabled(false); - mChart.setNoDataTextDescription("You need to provide data for the chart."); + // enable description text + mChart.getDescription().setEnabled(true); // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 27bdff9ce3..f7d7233d88 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -37,7 +37,6 @@ protected void setup(Chart chart) { // no description text chart.getDescription().setEnabled(false); - chart.setNoDataTextDescription("You need to provide data for the chart."); // enable touch gestures chart.setTouchEnabled(true); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 6a666b38e5..48e206a438 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -13,6 +13,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.RectF; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Environment; import android.provider.MediaStore.Images; @@ -149,12 +150,6 @@ public abstract class Chart Date: Sat, 17 Sep 2016 23:23:59 +0200 Subject: [PATCH 1171/1390] Remove unused mDrawPaint instance --- .../java/com/github/mikephil/charting/charts/Chart.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 48e206a438..e0c94a8f6d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -239,8 +239,6 @@ public void onAnimationUpdate(ValueAnimator animation) { mInfoPaint.setTextAlign(Align.CENTER); mInfoPaint.setTextSize(Utils.convertDpToPixel(12f)); - mDrawPaint = new Paint(Paint.DITHER_FLAG); - if (mLogEnabled) Log.i("", "Chart.init()"); } @@ -394,11 +392,6 @@ protected void setupDefaultFormatter(float min, float max) { */ private boolean mOffsetsCalculated = false; - /** - * paint object used for drawing the bitmap - */ - protected Paint mDrawPaint; - @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); From 0aeddb025efdff11e1f061ecb2645707bbb88219 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sat, 17 Sep 2016 23:47:47 +0200 Subject: [PATCH 1172/1390] Fix issue causing ANR for empty charts --- .../github/mikephil/charting/renderer/AxisRenderer.java | 7 ++----- .../charting/renderer/YAxisRendererRadarChart.java | 7 ++----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index c96a4d45fe..7043e4dd63 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -154,18 +154,15 @@ protected void computeAxisValues(float min, float max) { int labelCount = mAxis.getLabelCount(); double range = Math.abs(yMax - yMin); - if (labelCount == 0 || range <= 0) { + if (labelCount == 0 || range <= 0 || Double.isInfinite(range)) { mAxis.mEntries = new float[]{}; + mAxis.mCenteredEntries = new float[]{}; mAxis.mEntryCount = 0; return; } // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; - if (Double.isInfinite(rawInterval)) - { - rawInterval = range > 0.0 && !Double.isInfinite(range) ? range : 1.0; - } double interval = Utils.roundToNextSignificant(rawInterval); // If granularity is enabled, then do not allow the interval to go below specified granularity. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 83d835755c..64bbb1e085 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -32,18 +32,15 @@ protected void computeAxisValues(float min, float max) { int labelCount = mAxis.getLabelCount(); double range = Math.abs(yMax - yMin); - if (labelCount == 0 || range <= 0) { + if (labelCount == 0 || range <= 0 || Double.isInfinite(range)) { mAxis.mEntries = new float[]{}; + mAxis.mCenteredEntries = new float[]{}; mAxis.mEntryCount = 0; return; } // Find out how much spacing (in y value space) between axis values double rawInterval = range / labelCount; - if (Double.isInfinite(rawInterval)) - { - rawInterval = range > 0.0 && !Double.isInfinite(range) ? range : 1.0; - } double interval = Utils.roundToNextSignificant(rawInterval); // If granularity is enabled, then do not allow the interval to go below specified granularity. From 5b9bd6e633f2f084ea8064af64f8f72402964cd4 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 18 Sep 2016 11:13:25 +0200 Subject: [PATCH 1173/1390] Fix time chart example --- .../mpchartexample/LineChartTime.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 7208f3f0da..be1cadc27a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -25,10 +25,12 @@ import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import java.sql.Time; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.TimeUnit; public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { @@ -87,14 +89,16 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawGridLines(true); xAxis.setTextColor(Color.rgb(255, 192, 56)); xAxis.setCenterAxisLabels(true); - xAxis.setGranularity(60000L); // one minute in millis + xAxis.setGranularity(1f); // one hour xAxis.setValueFormatter(new IAxisValueFormatter() { private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); @Override public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(new Date((long) value)); + + long millis = TimeUnit.HOURS.toMillis((long) value); + return mFormat.format(new Date(millis)); } @Override @@ -264,15 +268,18 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { private void setData(int count, float range) { - long now = System.currentTimeMillis(); - long hourMillis = 3600000L; + // now in hours + long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); ArrayList values = new ArrayList(); - float from = now - (count / 2) * hourMillis; - float to = now + (count / 2) * hourMillis; + float from = now; + + // count = hours + float to = now + count; - for (float x = from; x < to; x += hourMillis) { + // increment by 1 hour + for (float x = from; x < to; x++) { float y = getRandom(range, 50); values.add(new Entry(x, y)); // add one entry per hour From 865c3dae1839dc1ba743159484a70086fcfed682 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 18 Sep 2016 17:33:04 +0200 Subject: [PATCH 1174/1390] Extend test cases (for bugfix) --- .../mpchartexample/LineChartTime.java | 2 +- .../mikephil/charting/charts/Chart.java | 3 +- .../mikephil/charting/test/DataSetTest.java | 41 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index be1cadc27a..04070d2c26 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -318,4 +318,4 @@ public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } -} +} \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index e0c94a8f6d..c8b360b1ab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -1208,7 +1208,8 @@ public void setDescription(Description desc) { } /** - * Returns the Description object of the chart. + * Returns the Description object of the chart that is responsible for holding all information related + * to the description text that is displayed in the bottom right corner of the chart (by default). * * @return */ diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 381c2b23da..2311dc7838 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -178,4 +178,45 @@ public void testGetEntryForXValue() { assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); } + + @Test + public void testGetEntryForXValueWithDuplicates() { + + // sorted list of values (by x position) + List values = new ArrayList(); + values.add(new Entry(0, 10)); + values.add(new Entry(1, 20)); + values.add(new Entry(2, 30)); + values.add(new Entry(3, 40)); + values.add(new Entry(3, 50)); // duplicate + values.add(new Entry(4, 60)); + values.add(new Entry(4, 70)); // duplicate + values.add(new Entry(5, 80)); + values.add(new Entry(6, 90)); + values.add(new Entry(7, 100)); + values.add(new Entry(8, 110)); + values.add(new Entry(8, 120)); // duplicate + + ScatterDataSet set = new ScatterDataSet(values, ""); + + Entry closest = set.getEntryForXValue(0, DataSet.Rounding.CLOSEST); + assertEquals(0, closest.getX(), 0.01f); + assertEquals(10, closest.getY(), 0.01f); + + closest = set.getEntryForXValue(5, DataSet.Rounding.CLOSEST); + assertEquals(5, closest.getX(), 0.01f); + assertEquals(80, closest.getY(), 0.01f); + + closest = set.getEntryForXValue(5.4f, DataSet.Rounding.CLOSEST); + assertEquals(5, closest.getX(), 0.01f); + assertEquals(80, closest.getY(), 0.01f); + + closest = set.getEntryForXValue(4.6f, DataSet.Rounding.CLOSEST); + assertEquals(5, closest.getX(), 0.01f); + assertEquals(80, closest.getY(), 0.01f); + + closest = set.getEntryForXValue(7, DataSet.Rounding.CLOSEST); + assertEquals(7, closest.getX(), 0.01f); + assertEquals(100, closest.getY(), 0.01f); + } } From 89f10e928e846080f4c9ee239ecdc04812b884e9 Mon Sep 17 00:00:00 2001 From: Voicu Date: Sun, 18 Sep 2016 09:32:34 -0700 Subject: [PATCH 1175/1390] Remove unused local variable --- .../com/github/mikephil/charting/renderer/LineChartRenderer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5a7da70377..3184031bce 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -181,7 +181,6 @@ protected void drawHorizontalBezier(ILineDataSet dataSet) { protected void drawCubicBezier(ILineDataSet dataSet) { - float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float phaseY = mAnimator.getPhaseY(); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); From b53c8cdbd1f747adea53a5854878353aa595547c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 19 Sep 2016 22:15:26 +0300 Subject: [PATCH 1176/1390] Removed redundancies --- .../com/github/mikephil/charting/charts/Chart.java | 14 ++++++++------ .../renderer/YAxisRendererHorizontalBarChart.java | 2 -- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index e0c94a8f6d..66b349e8e6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -430,16 +430,18 @@ protected void drawDescription(Canvas c) { mDescPaint.setColor(mDescription.getTextColor()); mDescPaint.setTextAlign(mDescription.getTextAlign()); + float x, y; + // if no position specified, draw on default position if (position == null) { - - float x = getWidth() - mViewPortHandler.offsetRight() - mDescription.getXOffset(); - float y = getHeight() - mViewPortHandler.offsetBottom() - mDescription.getYOffset(); - - c.drawText(mDescription.getText(), x, y, mDescPaint); + x = getWidth() - mViewPortHandler.offsetRight() - mDescription.getXOffset(); + y = getHeight() - mViewPortHandler.offsetBottom() - mDescription.getYOffset(); } else { - c.drawText(mDescription.getText(), position.x, position.y, mDescPaint); + x = position.x; + y = position.y; } + + c.drawText(mDescription.getText(), x, y, mDescPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 8822ca5a23..2f96fa71f6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -207,8 +207,6 @@ protected void drawZeroLine(Canvas c) { c.drawPath(zeroLinePath, mZeroLinePaint); c.restoreToCount(clipRestoreCount); - - c.restoreToCount(clipRestoreCount); } protected Path mRenderLimitLinesPathBuffer = new Path(); From 7ffa9caaa103af79207b56d15d2d239cdfddfea3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 21 Sep 2016 07:30:46 +0300 Subject: [PATCH 1177/1390] Fixed entry searching algorithm to handle sequential same values --- .../mikephil/charting/data/DataSet.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 4aa8a17409..7496a50396 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -298,13 +298,28 @@ public int getEntryIndex(float xValue, Rounding rounding) { while (low < high) { int m = (low + high) / 2; - float d1 = Math.abs(mValues.get(m).getX() - xValue); - float d2 = Math.abs(mValues.get(m + 1).getX() - xValue); + final float d1 = mValues.get(m).getX() - xValue, + d2 = mValues.get(m + 1).getX() - xValue, + ad1 = Math.abs(d1), ad2 = Math.abs(d2); - if (d2 <= d1) { + if (ad2 < ad1) { + // [m + 1] is closer to xValue + // Search in an higher place low = m + 1; - } else { + } else if (ad1 < ad2) { + // [m] is closer to xValue + // Search in a lower place high = m; + } else { + // We have multiple sequential x-value with same distance + + if (d1 >= 0.0) { + // Search in a lower place + high = m; + } else if (d1 < 0.0) { + // Search in an higher place + low = m + 1; + } } } From 21e778cb1fae280f53725ce035227a2504c00316 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 21 Sep 2016 07:53:06 +0300 Subject: [PATCH 1178/1390] Move on from the deprecated property in the demos --- .../mpchartexample/BarChartActivity.java | 5 ++++- .../BarChartActivityMultiDataset.java | 5 ++++- .../mpchartexample/BarChartActivitySinus.java | 5 ++++- .../mpchartexample/BubbleChartActivity.java | 5 ++++- .../mpchartexample/CombinedChartActivity.java | 5 ++++- .../mpchartexample/HalfPieChartActivity.java | 5 ++++- .../HorizontalBarChartActivity.java | 5 ++++- .../mpchartexample/InvertedLineChartActivity.java | 1 - .../mpchartexample/LineChartActivity1.java | 1 - .../mpchartexample/LineChartActivity2.java | 6 ++++-- .../mpchartexample/MultiLineChartActivity.java | 5 ++++- .../mpchartexample/PieChartActivity.java | 5 ++++- .../mpchartexample/PiePolylineChartActivity.java | 5 ++++- .../mpchartexample/RadarChartActivitry.java | 5 ++++- .../mpchartexample/RealtimeLineChartActivity.java | 1 - .../mpchartexample/ScatterChartActivity.java | 5 ++++- .../mpchartexample/StackedBarActivity.java | 5 ++++- .../StackedBarActivityNegative.java | 5 ++++- .../mpchartexample/fragments/PieChartFrag.java | 5 ++++- .../listviewitems/PieChartItem.java | 5 ++++- .../mikephil/charting/components/Legend.java | 15 ++++++++------- 21 files changed, 76 insertions(+), 28 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 53e33c969b..5eb67e7c41 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -107,7 +107,10 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setForm(LegendForm.SQUARE); l.setFormSize(9f); l.setTextSize(11f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 3d3efa7076..da2ba2c8bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -77,7 +77,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(100); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(true); l.setTypeface(mTfLight); l.setYOffset(0f); l.setYEntrySpace(0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index a7177ff054..56add4458e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -93,7 +93,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setProgress(150); // set data Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setForm(LegendForm.SQUARE); l.setFormSize(9f); l.setTextSize(11f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 22f4afe3c9..db72f29495 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -72,7 +72,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(50); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); l.setTypeface(mTfLight); YAxis yl = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index ad3d7e01ea..f221dcf3b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -62,7 +62,10 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); l.setWordWrapEnabled(true); - l.setPosition(Legend.LegendPosition.BELOW_CHART_CENTER); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 0b2f44e04f..15da39a8f3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -71,7 +71,10 @@ protected void onCreate(Bundle savedInstanceState) { mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.ABOVE_CHART_CENTER); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setXEntrySpace(7f); l.setYEntrySpace(0f); l.setYOffset(0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 71c278fb77..f5ea95098b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -107,7 +107,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setFormSize(8f); l.setXEntrySpace(4f); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index a1be487e05..f87a9a8098 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -106,7 +106,6 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); // dont forget to refresh the drawing diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index bfb14090ab..f6747bbf6f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -156,7 +156,6 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); // // dont forget to refresh the drawing diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 5cdeacf3a9..72977c26fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -89,12 +89,14 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); l.setTypeface(mTfLight); l.setTextSize(11f); l.setTextColor(Color.WHITE); - l.setPosition(LegendPosition.BELOW_CHART_LEFT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); // l.setYOffset(11f); XAxis xAxis = mChart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index e8f6182da2..19f7bae938 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -75,7 +75,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(100); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index a33f8e4a01..4493da1f97 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -96,7 +96,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); l.setXEntrySpace(7f); l.setYEntrySpace(0f); l.setYOffset(0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 6583129505..49fc4959e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -102,7 +102,10 @@ protected void onCreate(Bundle savedInstanceState) { // mChart.spin(2000, 0, 360); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); l.setEnabled(false); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 804df1ec2a..b787f17e85 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -98,7 +98,10 @@ public int getDecimalDigits() { yAxis.setDrawLabels(false); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.ABOVE_CHART_CENTER); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setTypeface(mTfLight); l.setXEntrySpace(7f); l.setYEntrySpace(5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 30f38126ed..13346bf631 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -66,7 +66,6 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); // modify the legend ... - // l.setPosition(LegendPosition.LEFT_OF_CHART); l.setForm(LegendForm.LINE); l.setTypeface(mTfLight); l.setTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index ebf43a831d..29904a95c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -70,7 +70,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(100); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); l.setTypeface(mTfLight); l.setXOffset(5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index b6c10d700e..31ad84e5ac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -88,7 +88,10 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setProgress(100); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_RIGHT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setFormSize(8f); l.setFormToTextSpace(4f); l.setXEntrySpace(6f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 4758490a77..8b9819092a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -93,7 +93,10 @@ public int getDecimalDigits() { }); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_RIGHT); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); l.setFormSize(8f); l.setFormToTextSpace(4f); l.setXEntrySpace(6f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index dc30f303ec..7888aa632f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -43,7 +43,10 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setTransparentCircleRadius(50f); Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); mChart.setData(generatePieData()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 8a2ff8bda6..db6ba32416 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -73,7 +73,10 @@ public View getView(int position, View convertView, Context c) { holder.chart.setData((PieData) mChartData); Legend l = holder.chart.getLegend(); - l.setPosition(LegendPosition.RIGHT_OF_CHART); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); + l.setOrientation(Legend.LegendOrientation.VERTICAL); + l.setDrawInside(false); l.setYEntrySpace(0f); l.setYOffset(0f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index aeba757cc2..fb1afc8bba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -23,9 +23,10 @@ public class Legend extends ComponentBase { /** - * This property is deprecated - Use `position`, `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, + * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, * `direction`. */ + @Deprecated public enum LegendPosition { RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, @@ -423,10 +424,10 @@ public boolean isLegendCustom() { } /** - * returns the position of the legend relative to the chart - * - * @return + * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, + * `direction`. */ + @Deprecated public LegendPosition getPosition() { if (mOrientation == LegendOrientation.VERTICAL @@ -463,10 +464,10 @@ public LegendPosition getPosition() { } /** - * sets the position of the legend relative to the whole chart - * - * @param newValue + * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, + * `direction`. */ + @Deprecated public void setPosition(LegendPosition newValue) { switch (newValue) { From 63684f02ca686d38b835f39fc86a5263f86034a3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 21 Sep 2016 17:56:00 +0300 Subject: [PATCH 1179/1390] Avoid crash for `centerAxisLabelsEnabled` when entry count == 1 --- .../com/github/mikephil/charting/renderer/AxisRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 7043e4dd63..2cade932c5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -250,7 +250,9 @@ protected void computeAxisValues(float min, float max) { mAxis.mCenteredEntries = new float[n]; } - float offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f; + float offset = 0.f; + if (mAxis.mEntries.length > 1) + offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f; for (int i = 0; i < n; i++) { mAxis.mCenteredEntries[i] = mAxis.mEntries[i] + offset; From b1fe859ce88a6de3777d67c3ad1f120ba4e84e6c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 21 Sep 2016 19:55:58 +0300 Subject: [PATCH 1180/1390] Fixes for cubic bezier edges --- .../charting/renderer/LineChartRenderer.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5a7da70377..8688ab37ea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -199,22 +199,33 @@ protected void drawCubicBezier(ILineDataSet dataSet) { float curDx = 0f; float curDy = 0f; - Entry prevPrev = dataSet.getEntryForIndex(mXBounds.min); - Entry prev = prevPrev; - Entry cur = prev; - Entry next = dataSet.getEntryForIndex(mXBounds.min + 1); + // Take an extra point from the left, and an extra from the right. + // That's because we need 4 points for a cubic bezier (cubic=4), otherwise we get lines moving and doing weird stuff on the edges of the chart. + // So in the starting `prev` and `cur`, go -2, -1 + // And in the `lastIndex`, add +1 + + final int firstIndex = mXBounds.min + 1; + final int lastIndex = mXBounds.min + mXBounds.range; + + Entry prevPrev; + Entry prev = dataSet.getEntryForIndex(Math.max(firstIndex - 2, 0)); + Entry cur = dataSet.getEntryForIndex(Math.max(firstIndex - 1, 0)); + Entry next = cur; + int nextIndex = -1; - if (cur == null || next == null) return; + if (cur == null) return; // let the spline start cubicPath.moveTo(cur.getX(), cur.getY() * phaseY); for (int j = mXBounds.min + 1; j <= mXBounds.range + mXBounds.min; j++) { - prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); - prev = dataSet.getEntryForIndex(j - 1); - cur = dataSet.getEntryForIndex(j); - next = mXBounds.max > j + 1 ? dataSet.getEntryForIndex(j + 1) : cur; + prevPrev = prev; + prev = cur; + cur = nextIndex == j ? next : dataSet.getEntryForIndex(j); + + nextIndex = j + 1 < dataSet.getEntryCount() ? j + 1 : j; + next = dataSet.getEntryForIndex(nextIndex); prevDx = (cur.getX() - prevPrev.getX()) * intensity; prevDy = (cur.getY() - prevPrev.getY()) * intensity; From 6c0b9c1aabc41a0a80e21ff042e4514cea57ce82 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 21 Sep 2016 20:02:56 +0300 Subject: [PATCH 1181/1390] Removed redundant condition --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 8688ab37ea..9cab2208fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -361,8 +361,6 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // make sure the lines don't do shitty things outside // bounds if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2]) - || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler - .isInBoundsBottom(mLineBuffer[3])) || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler .isInBoundsBottom(mLineBuffer[3]))) continue; From 01d8b246869f3d9517b615814d8ecb30cbfebdf0 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sat, 24 Sep 2016 18:21:50 +0200 Subject: [PATCH 1182/1390] Update gradle --- MPChartExample/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index a7e8efa03b..84513580e4 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -39,7 +39,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.3' + classpath 'com.android.tools.build:gradle:2.2.0' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/build.gradle b/build.gradle index 588bad10b1..8e5194d52e 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:1.1.0" - classpath 'com.android.tools.build:gradle:2.1.3' + classpath 'com.android.tools.build:gradle:2.2.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From 028328b98647ac22624680508bd1b9f42ec2433b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 29 Sep 2016 08:12:05 +0300 Subject: [PATCH 1183/1390] Guard `roundToNextSignificant` and `decimal` from invalids --- .../java/com/github/mikephil/charting/utils/Utils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index c7c1884ff6..b555b44917 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -360,6 +360,11 @@ public static String formatNumber(float number, int digitCount, boolean separate * @return */ public static float roundToNextSignificant(double number) { + if (Double.isInfinite(number) || + Double.isNaN(number) || + number == 0.0) + return 0; + final float d = (float) Math.ceil((float) Math.log10(number < 0 ? -number : number)); final int pw = 1 - (int) d; final float magnitude = (float) Math.pow(10, pw); @@ -377,6 +382,10 @@ public static float roundToNextSignificant(double number) { public static int getDecimals(float number) { float i = roundToNextSignificant(number); + + if (Float.isInfinite(i)) + return 0; + return (int) Math.ceil(-Math.log10(i)) + 2; } From aa14ab262b61da575d0591f0851ff7fccb42e81e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 29 Sep 2016 08:59:33 +0300 Subject: [PATCH 1184/1390] Minor fixes for interval in axis labels --- .../mikephil/charting/renderer/AxisRenderer.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 2cade932c5..4c8ce4c8ba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -179,13 +179,12 @@ protected void computeAxisValues(float min, float max) { interval = Math.floor(10 * intervalMagnitude); } - boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); int n = centeringEnabled ? 1 : 0; // force label count if (mAxis.isForceLabelsEnabled()) { - float step = (float) range / (float) (labelCount - 1); + interval = (float) range / (float) (labelCount - 1); mAxis.mEntryCount = labelCount; if (mAxis.mEntries.length < labelCount) { @@ -197,7 +196,7 @@ protected void computeAxisValues(float min, float max) { for (int i = 0; i < labelCount; i++) { mAxis.mEntries[i] = v; - v += step; + v += interval; } n = labelCount; @@ -206,7 +205,7 @@ protected void computeAxisValues(float min, float max) { } else { double first = interval == 0.0 ? 0.0 : Math.ceil(yMin / interval) * interval; - if(centeringEnabled) { + if(mAxis.isCenterAxisLabelsEnabled()) { first -= interval; } @@ -244,15 +243,13 @@ protected void computeAxisValues(float min, float max) { mAxis.mDecimals = 0; } - if (centeringEnabled) { + if (mAxis.isCenterAxisLabelsEnabled()) { if (mAxis.mCenteredEntries.length < n) { mAxis.mCenteredEntries = new float[n]; } - float offset = 0.f; - if (mAxis.mEntries.length > 1) - offset = (mAxis.mEntries[1] - mAxis.mEntries[0]) / 2f; + float offset = (float)interval / 2f; for (int i = 0; i < n; i++) { mAxis.mCenteredEntries[i] = mAxis.mEntries[i] + offset; From 06bed3332d21f4c4e1e2e7ed67d8f5f1a304aac2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 29 Sep 2016 09:00:18 +0300 Subject: [PATCH 1185/1390] Allow label centering for 1 label --- .../java/com/github/mikephil/charting/components/AxisBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index c2e04fc0a6..fc92dc8fb7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -194,7 +194,7 @@ public void setCenterAxisLabels(boolean enabled) { } public boolean isCenterAxisLabelsEnabled() { - return mCenterAxisLabels && mEntryCount > 1; + return mCenterAxisLabels && mEntryCount > 0; } /** From c8553da89cadb9e81c5c500de7f241ff4afd3e5e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 29 Sep 2016 09:09:05 +0300 Subject: [PATCH 1186/1390] Set z-index of markers to be the highest --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 817c70b6c9..6fa3b4d312 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -252,10 +252,10 @@ protected void onDraw(Canvas canvas) { mLegendRenderer.renderLegend(canvas); - drawMarkers(canvas); - drawDescription(canvas); + drawMarkers(canvas); + if (mLogEnabled) { long drawtime = (System.currentTimeMillis() - starttime); totalTime += drawtime; From cf0f1fca3443141e58696b1861b0a32e9c1fd4ad Mon Sep 17 00:00:00 2001 From: Mark Date: Thu, 29 Sep 2016 19:38:48 +0800 Subject: [PATCH 1187/1390] [FIX] not find centeringEnabled --- .../com/github/mikephil/charting/renderer/AxisRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 4c8ce4c8ba..90528a1359 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -179,7 +179,7 @@ protected void computeAxisValues(float min, float max) { interval = Math.floor(10 * intervalMagnitude); } - int n = centeringEnabled ? 1 : 0; + int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0; // force label count if (mAxis.isForceLabelsEnabled()) { From 323329d8a6e66f75cabd9b37f738e9753d26e0fc Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 2 Oct 2016 14:36:55 +0200 Subject: [PATCH 1188/1390] Extend test cases --- .../github/mikephil/charting/data/DataSet.java | 8 -------- .../charting/highlight/ChartHighlighter.java | 2 +- .../mikephil/charting/test/DataSetTest.java | 16 ++++++++++++++++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 7496a50396..45e5917dd9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -339,14 +339,6 @@ public int getEntryIndex(float xValue, Rounding rounding) { return high; } - /** - * Returns all Entry objects at the given xIndex. INFORMATION: This method - * does calculations at runtime. Do not over-use in performance critical - * situations. - * - * @param xValue - * @return - */ @Override public List getEntriesForXValue(float xValue) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index c4a1716596..a7a3ca7eb5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -138,7 +138,7 @@ protected List getHighlightsAtXValue(float xVal, float x, float y) { IDataSet dataSet = data.getDataSetByIndex(i); - // dont include datasets that cannot be highlighted + // don't include DataSets that cannot be highlighted if (!dataSet.isHighlightEnabled()) continue; diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 2311dc7838..8d3843e5ce 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -218,5 +218,21 @@ public void testGetEntryForXValueWithDuplicates() { closest = set.getEntryForXValue(7, DataSet.Rounding.CLOSEST); assertEquals(7, closest.getX(), 0.01f); assertEquals(100, closest.getY(), 0.01f); + + closest = set.getEntryForXValue(4f, DataSet.Rounding.CLOSEST); + assertEquals(4, closest.getX(), 0.01f); + assertEquals(60, closest.getY(), 0.01f); + + List entries = set.getEntriesForXValue(4f); + assertEquals(2, entries.size()); + assertEquals(60, entries.get(0).getY(), 0.01f); + assertEquals(70, entries.get(1).getY(), 0.01f); + + entries = set.getEntriesForXValue(3.5f); + assertEquals(0, entries.size()); + + entries = set.getEntriesForXValue(2f); + assertEquals(1, entries.size()); + assertEquals(30, entries.get(0).getY(), 0.01f); } } From 3398cf4462bc7f49bb1156ef22040e8a0d63369f Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 2 Oct 2016 15:14:09 +0200 Subject: [PATCH 1189/1390] Refactoring, prepare example for testing highlight --- .../mpchartexample/LineChartActivity2.java | 43 +++++++++++++------ .../mikephil/charting/data/DataSet.java | 3 ++ .../charting/renderer/RadarChartRenderer.java | 4 +- .../charting/utils/ColorTemplate.java | 9 +++- 4 files changed, 41 insertions(+), 18 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 72977c26fa..79f40c4e07 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; -import android.graphics.Paint; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -16,7 +15,6 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; @@ -243,6 +241,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.animateX: { mChart.animateX(3000); + //mChart.highlightValue(9.7f, 1, false); break; } case R.id.animateY: { @@ -287,30 +286,39 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = range / 2f; - float val = (float) (Math.random() * mult) + 50;// + (float) - // ((mult * - // 0.1) / 10); + float val = (float) (Math.random() * mult) + 50; yVals1.add(new Entry(i, val)); } ArrayList yVals2 = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < count-1; i++) { float mult = range; - float val = (float) (Math.random() * mult) + 450;// + (float) - // ((mult * - // 0.1) / 10); + float val = (float) (Math.random() * mult) + 450; yVals2.add(new Entry(i, val)); +// if(i == 10) { +// yVals2.add(new Entry(i, val + 50)); +// } + } + + ArrayList yVals3 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float mult = range; + float val = (float) (Math.random() * mult) + 500; + yVals3.add(new Entry(i, val)); } - LineDataSet set1, set2; + LineDataSet set1, set2, set3; if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { set1 = (LineDataSet) mChart.getData().getDataSetByIndex(0); set2 = (LineDataSet) mChart.getData().getDataSetByIndex(1); + set3 = (LineDataSet) mChart.getData().getDataSetByIndex(2); set1.setValues(yVals1); set2.setValues(yVals2); + set3.setValues(yVals3); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); } else { @@ -344,12 +352,19 @@ private void setData(int count, float range) { set2.setHighLightColor(Color.rgb(244, 117, 117)); //set2.setFillFormatter(new MyFillFormatter(900f)); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - dataSets.add(set2); + set3 = new LineDataSet(yVals3, "DataSet 3"); + set3.setAxisDependency(AxisDependency.RIGHT); + set3.setColor(Color.YELLOW); + set3.setCircleColor(Color.WHITE); + set3.setLineWidth(2f); + set3.setCircleRadius(3f); + set3.setFillAlpha(65); + set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); + set3.setDrawCircleHole(false); + set3.setHighLightColor(Color.rgb(244, 117, 117)); // create a data object with the datasets - LineData data = new LineData(dataSets); + LineData data = new LineData(set1, set2, set3); data.setValueTextColor(Color.WHITE); data.setValueTextSize(9f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 45e5917dd9..adc0083ec0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -351,11 +351,14 @@ public List getEntriesForXValue(float xValue) { int m = (high + low) / 2; T entry = mValues.get(m); + // if we have a match if (xValue == entry.getX()) { while (m > 0 && mValues.get(m - 1).getX() == xValue) m--; high = mValues.size(); + + // loop over all "equal" entries for (; m < high; m++) { entry = mValues.get(m); if (entry.getX() == xValue) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index dd0918d559..6c05b08dca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -18,8 +18,6 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.List; - public class RadarChartRenderer extends LineRadarRenderer { protected RadarChart mChart; @@ -306,7 +304,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } if (set.getHighlightCircleStrokeAlpha() < 255) { - strokeColor = ColorTemplate.getColorWithAlphaComponent(strokeColor, set.getHighlightCircleStrokeAlpha()); + strokeColor = ColorTemplate.colorWithAlpha(strokeColor, set.getHighlightCircleStrokeAlpha()); } drawHighlightCircle(c, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java index 106671ad13..4d9c1de790 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ColorTemplate.java @@ -78,7 +78,14 @@ public static int getHoloBlue() { return Color.rgb(51, 181, 229); } - public static int getColorWithAlphaComponent(int color, int alpha) { + /** + * Sets the alpha component of the given color. + * + * @param color + * @param alpha 0 - 255 + * @return + */ + public static int colorWithAlpha(int color, int alpha) { return (color & 0xffffff) | ((alpha & 0xff) << 24); } From 463ef829d7084504e4891ae1ab59cc8a43b5617a Mon Sep 17 00:00:00 2001 From: nielsz Date: Sat, 8 Oct 2016 12:18:13 +0200 Subject: [PATCH 1190/1390] Fix typo --- .../main/java/com/github/mikephil/charting/charts/Chart.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index cd6bb46d39..443c70092b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -355,14 +355,14 @@ public boolean isEmpty() { public abstract void notifyDataSetChanged(); /** - * calculates the offsets of the chart to the border depending on the + * Calculates the offsets of the chart to the border depending on the * position of an eventual legend or depending on the length of the y-axis * and x-axis labels and their position */ protected abstract void calculateOffsets(); /** - * calcualtes the y-min and y-max value and the y-delta and x-delta value + * Calculates the y-min and y-max value and the y-delta and x-delta value */ protected abstract void calcMinMax(); From 815dee86a097bb843447eedb427269b8c8b69bf0 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 8 Oct 2016 21:47:31 +0300 Subject: [PATCH 1191/1390] Corrected calcMinMaxY for autoScaleMinMax --- .../mikephil/charting/data/CandleDataSet.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 13bf6062d4..7574b78b27 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -112,6 +112,22 @@ protected void calcMinMax(CandleEntry e) { calcMinMaxX(e); } + @Override + protected void calcMinMaxY(CandleEntry e) { + + if (e.getHigh() < mYMin) + mYMin = e.getHigh(); + + if (e.getHigh() > mYMax) + mYMax = e.getHigh(); + + if (e.getLow() < mYMin) + mYMin = e.getLow(); + + if (e.getLow() > mYMax) + mYMax = e.getLow(); + } + /** * Sets the space that is left out on the left and right side of each * candle, default 0.1f (10%), max 0.45f, min 0f From b77063d8185f73631b1fda75cc17e1ddd0984678 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 8 Oct 2016 22:24:08 +0300 Subject: [PATCH 1192/1390] Feature: spaceMin/spaceMax for axis --- .../charting/components/AxisBase.java | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index fc92dc8fb7..997612eb53 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -112,6 +112,16 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mDrawLimitLineBehindData = false; + /** + * Extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` + */ + protected float mSpaceMin = 0.f; + + /** + * Extra spacing for `axisMaximum` to be added to automatically calculated `axisMaximum` + */ + protected float mSpaceMax = 0.f; + /** * flag indicating that the axis-min value has been customized */ @@ -705,8 +715,8 @@ public void setAxisMaxValue(float max) { public void calculate(float dataMin, float dataMax) { // if custom, use value as is, else use data value - float min = mCustomAxisMin ? mAxisMinimum : dataMin; - float max = mCustomAxisMax ? mAxisMaximum : dataMax; + float min = mCustomAxisMin ? mAxisMinimum : (dataMin - mSpaceMin); + float max = mCustomAxisMax ? mAxisMaximum : (dataMax + mSpaceMax); // temporary range (before calculations) float range = Math.abs(max - min); @@ -723,4 +733,36 @@ public void calculate(float dataMin, float dataMax) { // actual range this.mAxisRange = Math.abs(max - min); } + + /** + * Gets extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` + */ + public float getSpaceMin() + { + return mSpaceMin; + } + + /** + * Sets extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` + */ + public void setSpaceMin(float mSpaceMin) + { + this.mSpaceMin = mSpaceMin; + } + + /** + * Gets extra spacing for `axisMaximum` to be added to automatically calculated `axisMaximum` + */ + public float getSpaceMax() + { + return mSpaceMax; + } + + /** + * Sets extra spacing for `axisMaximum` to be added to automatically calculated `axisMaximum` + */ + public void setSpaceMax(float mSpaceMax) + { + this.mSpaceMax = mSpaceMax; + } } From 8d655962661f4079d3f49777f14534f298182bf6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 8 Oct 2016 22:25:44 +0300 Subject: [PATCH 1193/1390] Default spaceMin/spaceMax for bar charts This avoids having to set custom axisMinimum/axisMaximum, or offsetting x --- .../mpchartexample/BarChartActivity.java | 5 +---- .../mpchartexample/BarChartPositiveNegative.java | 12 +++++------- .../github/mikephil/charting/charts/BarChart.java | 3 +++ 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 5eb67e7c41..650d6183c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -231,15 +231,12 @@ private void setData(int count, float range) { float start = 0f; - mChart.getXAxis().setAxisMinimum(start); - mChart.getXAxis().setAxisMaximum(start + count + 2); - ArrayList yVals1 = new ArrayList(); for (int i = (int) start; i < start + count + 1; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(i + 1f, val)); + yVals1.add(new BarEntry(i, val)); } BarDataSet set1; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 6fe6bc8e8c..10a7bb9fd9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -61,8 +61,6 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawAxisLine(false); xAxis.setTextColor(Color.LTGRAY); xAxis.setTextSize(13f); - xAxis.setAxisMinimum(0f); - xAxis.setAxisMaximum(5f); xAxis.setLabelCount(5); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); @@ -81,11 +79,11 @@ protected void onCreate(Bundle savedInstanceState) { // THIS IS THE ORIGINAL DATA YOU WANT TO PLOT final List data = new ArrayList<>(); - data.add(new Data(0.5f, -224.1f, "12-29")); - data.add(new Data(1.5f, 238.5f, "12-30")); - data.add(new Data(2.5f, 1280.1f, "12-31")); - data.add(new Data(3.5f, -442.3f, "01-01")); - data.add(new Data(4.5f, -2280.1f, "01-02")); + data.add(new Data(0f, -224.1f, "12-29")); + data.add(new Data(1f, 238.5f, "12-30")); + data.add(new Data(2f, 1280.1f, "12-31")); + data.add(new Data(3f, -442.3f, "01-01")); + data.add(new Data(4f, -2280.1f, "01-02")); xAxis.setValueFormatter(new IAxisValueFormatter() { @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index a805815952..b048a4fffa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -57,6 +57,9 @@ protected void init() { mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); setHighlighter(new BarHighlighter(this)); + + getXAxis().setSpaceMin(0.5f); + getXAxis().setSpaceMax(0.5f); } @Override From e10628958f7ca17ab415e07f220dcaa44c7ad08e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 10 Oct 2016 16:31:53 +0300 Subject: [PATCH 1194/1390] Improved highlight for scatter/bubble, and fixes highlightValueWithX --- .../DynamicalAddingActivity.java | 2 +- .../mikephil/charting/charts/Chart.java | 52 ++++++++---- .../mikephil/charting/charts/PieChart.java | 2 +- .../mikephil/charting/data/BaseDataSet.java | 2 +- .../mikephil/charting/data/ChartData.java | 6 +- .../mikephil/charting/data/DataSet.java | 64 +++++++++++---- .../charting/highlight/BarHighlighter.java | 2 +- .../charting/highlight/ChartHighlighter.java | 40 +++++++--- .../highlight/CombinedHighlighter.java | 13 ++- .../charting/highlight/Highlight.java | 5 +- .../highlight/HorizontalBarHighlighter.java | 34 +++++++- .../interfaces/datasets/IDataSet.java | 39 +++++---- .../charting/renderer/BarChartRenderer.java | 2 +- .../BarLineScatterCandleBubbleRenderer.java | 4 +- .../renderer/BubbleChartRenderer.java | 80 +++++++++---------- .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 2 +- .../renderer/ScatterChartRenderer.java | 2 +- .../mikephil/charting/test/DataSetTest.java | 26 +++--- 19 files changed, 242 insertions(+), 137 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 7d3e5f431f..2875b89d7e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -87,7 +87,7 @@ private void removeLastEntry() { if (set != null) { - Entry e = set.getEntryForXValue(set.getEntryCount() - 1); + Entry e = set.getEntryForXValue(set.getEntryCount() - 1, Float.NaN); data.removeEntry(e, 0); // or remove by index diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index cd6bb46d39..bcf722015e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -535,8 +535,8 @@ protected void setLastHighlighted(Highlight[] highs) { /** * Highlights the values at the given indices in the given DataSets. Provide * null or an empty array to undo all highlighting. This should be used to - * programmatically highlight values. This DOES NOT generate a callback to - * the OnChartValueSelectedListener. + * programmatically highlight values. + * This method *will not* call the listener. * * @param highs */ @@ -552,35 +552,59 @@ public void highlightValues(Highlight[] highs) { } /** - * Highlights the value at the given x-value in the given DataSet. Provide - * -1 as the dataSetIndex to undo all highlighting. This will trigger a callback to the OnChartValueSelectedListener. - * - * @param x - * @param dataSetIndex + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in */ public void highlightValue(float x, int dataSetIndex) { highlightValue(x, dataSetIndex, true); } /** - * Highlights the value at the given x-value in the given DataSet. Provide - * -1 as the dataSetIndex to undo all highlighting. - * - * @param x - * @param dataSetIndex + * Highlights the value at the given x-value and y-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + */ + public void highlightValue(float x, float y, int dataSetIndex) { + highlightValue(x, y, dataSetIndex, true); + } + + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in + * @param callListener Should the listener be called for this change */ public void highlightValue(float x, int dataSetIndex, boolean callListener) { + highlightValue(x, Float.NaN, dataSetIndex, callListener); + } + + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) { highlightValue(null, callListener); } else { - highlightValue(new Highlight(x, dataSetIndex), callListener); + highlightValue(new Highlight(x, y, dataSetIndex), callListener); } } /** * Highlights the values represented by the provided Highlight object - * This DOES NOT generate a callback to the OnChartValueSelectedListener. + * This method *will not* call the listener. * * @param highlight contains information about which entry should be highlighted */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index db327fa8b9..660fd29bdc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -328,7 +328,7 @@ public int getDataSetIndexForIndex(int xIndex) { List dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - if (dataSets.get(i).getEntryForXValue(xIndex) != null) + if (dataSets.get(i).getEntryForXValue(xIndex, Float.NaN) != null) return i; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index f3107ebed7..89ed9b4001 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -432,7 +432,7 @@ public boolean removeLast() { @Override public boolean removeEntryByXValue(float xValue) { - T e = getEntryForXValue(xValue); + T e = getEntryForXValue(xValue, Float.NaN); return removeEntry(e); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 1ffc1dbcc4..60d89f4753 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -338,7 +338,7 @@ public Entry getEntryForHighlight(Highlight highlight) { if (highlight.getDataSetIndex() >= mDataSets.size()) return null; else { - return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX()); + return mDataSets.get(highlight.getDataSetIndex()).getEntryForXValue(highlight.getX(), highlight.getY()); } } @@ -550,7 +550,7 @@ public boolean removeEntry(float xValue, int dataSetIndex) { return false; IDataSet dataSet = mDataSets.get(dataSetIndex); - Entry e = dataSet.getEntryForXValue(xValue); + Entry e = dataSet.getEntryForXValue(xValue, Float.NaN); if (e == null) return false; @@ -575,7 +575,7 @@ public T getDataSetForEntry(Entry e) { T set = mDataSets.get(i); for (int j = 0; j < set.getEntryCount(); j++) { - if (e.equalTo(set.getEntryForXValue(e.getX()))) + if (e.equalTo(set.getEntryForXValue(e.getX(), e.getY()))) return set; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index adc0083ec0..a96cfdcf66 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -83,8 +83,8 @@ public void calcMinMaxY(float fromX, float toX) { mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - int indexFrom = getEntryIndex(fromX, Rounding.DOWN); - int indexTo = getEntryIndex(toX, Rounding.UP); + int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); + int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); for (int i = indexFrom; i <= indexTo; i++) { @@ -213,7 +213,7 @@ public void addEntryOrdered(T e) { calcMinMax(e); if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { - int closestIndex = getEntryIndex(e.getX(), Rounding.UP); + int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP); mValues.add(closestIndex, e); } else { mValues.add(e); @@ -268,17 +268,17 @@ public int getEntryIndex(Entry e) { } @Override - public T getEntryForXValue(float xValue, Rounding rounding) { + public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { - int index = getEntryIndex(xValue, rounding); + int index = getEntryIndex(xValue, closestToY, rounding); if (index > -1) return mValues.get(index); return null; } @Override - public T getEntryForXValue(float xValue) { - return getEntryForXValue(xValue, Rounding.CLOSEST); + public T getEntryForXValue(float xValue, float closestToY) { + return getEntryForXValue(xValue, closestToY, Rounding.CLOSEST); } @Override @@ -287,13 +287,14 @@ public T getEntryForIndex(int index) { } @Override - public int getEntryIndex(float xValue, Rounding rounding) { + public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { if (mValues == null || mValues.isEmpty()) return -1; int low = 0; int high = mValues.size() - 1; + int closest = high; while (low < high) { int m = (low + high) / 2; @@ -321,22 +322,53 @@ public int getEntryIndex(float xValue, Rounding rounding) { low = m + 1; } } + + closest = high; } - if (high != -1) { - float closestXValue = mValues.get(high).getX(); + if (closest != -1) { + float closestXValue = mValues.get(closest).getX(); if (rounding == Rounding.UP) { - if (closestXValue < xValue && high < mValues.size() - 1) { - ++high; + // If rounding up, and found x-value is lower than specified x, and we can go upper... + if (closestXValue < xValue && closest < mValues.size() - 1) { + ++closest; } } else if (rounding == Rounding.DOWN) { - if (closestXValue > xValue && high > 0) { - --high; + // If rounding down, and found x-value is upper than specified x, and we can go lower... + if (closestXValue > xValue && closest > 0) { + --closest; } } + + // Search by closest to y-value + if (!Float.isNaN(closestToY)) { + while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue) + closest -= 1; + + float closestYValue = mValues.get(closest).getY(); + int closestYIndex = closest; + + while (true) { + closest += 1; + if (closest >= mValues.size()) + break; + + final Entry value = mValues.get(closest); + + if (value.getX() != closestXValue) + break; + + if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) { + closestYValue = closestToY; + closestYIndex = closest; + } + } + + closest = closestYIndex; + } } - return high; + return closest; } @Override @@ -382,7 +414,7 @@ public List getEntriesForXValue(float xValue) { /** * Determines how to round DataSet index values for - * {@link DataSet#getEntryIndex(float, Rounding)} DataSet.getEntryIndex()} + * {@link DataSet#getEntryIndex(float, float, Rounding)} DataSet.getEntryIndex()} * when an exact x-index is not found. */ public enum Rounding { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java index b60eeabfe9..af83a4539f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -54,7 +54,7 @@ public Highlight getHighlight(float x, float y) { */ public Highlight getStackedHighlight(Highlight high, IBarDataSet set, float xVal, float yVal) { - BarEntry entry = set.getEntryForXValue(xVal); + BarEntry entry = set.getEntryForXValue(xVal, yVal); if (entry == null) return null; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java index a7a3ca7eb5..f889bf19d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -142,18 +142,14 @@ protected List getHighlightsAtXValue(float xVal, float x, float y) { if (!dataSet.isHighlightEnabled()) continue; - Highlight high = buildHighlight(dataSet, i, xVal, DataSet.Rounding.CLOSEST); - - if(high != null) - mHighlightBuffer.add(high); - //vals.add(buildHighlight(dataSet, i, xVal, DataSet.Rounding.DOWN)); + mHighlightBuffer.addAll(buildHighlights(dataSet, i, xVal, DataSet.Rounding.CLOSEST)); } return mHighlightBuffer; } /** - * Returns the Highlight object corresponding to the selected xValue and dataSetIndex. + * An array of `Highlight` objects corresponding to the selected xValue and dataSetIndex. * * @param set * @param dataSetIndex @@ -161,16 +157,36 @@ protected List getHighlightsAtXValue(float xVal, float x, float y) { * @param rounding * @return */ - protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected List buildHighlights(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + + ArrayList highlights = new ArrayList<>(); + + //noinspection unchecked + List entries = set.getEntriesForXValue(xVal); + if (entries.size() == 0) { + // Try to find closest x-value and take all entries for that x-value + final Entry closest = set.getEntryForXValue(xVal, Float.NaN, rounding); + if (closest != null) + { + //noinspection unchecked + entries = set.getEntriesForXValue(closest.getX()); + } + } - final Entry e = set.getEntryForXValue(xVal, rounding); + if (entries.size() == 0) + return highlights; - if (e == null) - return null; + for (Entry e : entries) { + MPPointD pixels = mChart.getTransformer( + set.getAxisDependency()).getPixelForValues(e.getX(), e.getY()); - MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getX(), e.getY()); + highlights.add(new Highlight( + e.getX(), e.getY(), + (float) pixels.x, (float) pixels.y, + dataSetIndex, set.getAxisDependency())); + } - return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); + return highlights; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java index f75b0e925d..76788af6e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -57,13 +57,12 @@ protected List getHighlightsAtXValue(float xVal, float x, float y) { if (!dataSet.isHighlightEnabled()) continue; - Highlight s1 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.CLOSEST); - s1.setDataIndex(i); - mHighlightBuffer.add(s1); - -// Highlight s2 = buildHighlight(dataSet, j, xVal, DataSet.Rounding.DOWN); -// s2.setDataIndex(i); -// vals.add(s2); + List highs = buildHighlights(dataSet, j, xVal, DataSet.Rounding.CLOSEST); + for (Highlight high : highs) + { + high.setDataIndex(i); + mHighlightBuffer.add(high); + } } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 5599882ce7..f1d542d80b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -60,13 +60,14 @@ public class Highlight { */ private float mDrawY; - public Highlight(float x, int dataSetIndex) { + public Highlight(float x, float y, int dataSetIndex) { this.mX = x; + this.mY = y; this.mDataSetIndex = dataSetIndex; } public Highlight(float x, int dataSetIndex, int stackIndex) { - this(x, dataSetIndex); + this(x, Float.NaN, dataSetIndex); this.mStackIndex = stackIndex; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 60ec66ba9d..d96298e07d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -8,6 +8,9 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.MPPointD; +import java.util.ArrayList; +import java.util.List; + /** * Created by Philipp Jahoda on 22/07/15. */ @@ -43,13 +46,36 @@ public Highlight getHighlight(float x, float y) { } @Override - protected Highlight buildHighlight(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + protected List buildHighlights(IDataSet set, int dataSetIndex, float xVal, DataSet.Rounding rounding) { + + ArrayList highlights = new ArrayList<>(); + + //noinspection unchecked + List entries = set.getEntriesForXValue(xVal); + if (entries.size() == 0) { + // Try to find closest x-value and take all entries for that x-value + final Entry closest = set.getEntryForXValue(xVal, Float.NaN, rounding); + if (closest != null) + { + //noinspection unchecked + entries = set.getEntriesForXValue(closest.getX()); + } + } - final Entry e = set.getEntryForXValue(xVal, rounding); + if (entries.size() == 0) + return highlights; - MPPointD pixels = mChart.getTransformer(set.getAxisDependency()).getPixelForValues(e.getY(), e.getX()); + for (Entry e : entries) { + MPPointD pixels = mChart.getTransformer( + set.getAxisDependency()).getPixelForValues(e.getY(), e.getX()); + + highlights.add(new Highlight( + e.getX(), e.getY(), + (float) pixels.x, (float) pixels.y, + dataSetIndex, set.getAxisDependency())); + } - return new Highlight(e.getX(), e.getY(), (float) pixels.x, (float) pixels.y, dataSetIndex, set.getAxisDependency()); + return highlights; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 337adc35d2..5f922ba569 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -70,28 +70,36 @@ public interface IDataSet { /** * Returns the first Entry object found at the given x-value with binary - * search. If the no Entry at the specified x-value is found, this method - * returns the Entry at the x-value according to the rounding. + * search. + * If the no Entry at the specified x-value is found, this method + * returns the Entry at the closest x-value according to the rounding. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xValue - * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index + * @param xValue the x-value + * @param closestToY If there are multiple y-values for the specified x-value, + * @param rounding determine whether to round up/down/closest + * if there is no Entry matching the provided x-value * @return + * + * */ - T getEntryForXValue(float xValue, DataSet.Rounding rounding); + T getEntryForXValue(float xValue, float closestToY, DataSet.Rounding rounding); /** * Returns the first Entry object found at the given x-value with binary - * search. If the no Entry at the specified x-value is found, this method - * returns the index at the closest x-value. + * search. + * If the no Entry at the specified x-value is found, this method + * returns the Entry at the closest x-value. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xValue + * + * @param xValue the x-value + * @param closestToY If there are multiple y-values for the specified x-value, * @return */ - T getEntryForXValue(float xValue); + T getEntryForXValue(float xValue, float closestToY); /** * Returns all Entry objects found at the given x-value with binary @@ -114,16 +122,19 @@ public interface IDataSet { /** * Returns the first Entry index found at the given x-value with binary - * search. If the no Entry at the specified x-value is found, this method - * returns the Entry at the closest x-value. + * search. + * If the no Entry at the specified x-value is found, this method + * returns the Entry at the closest x-value according to the rounding. * INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xValue - * @param rounding determine to round up/down/closest if there is no Entry matching the provided x-index + * @param xValue the x-value + * @param closestToY If there are multiple y-values for the specified x-value, + * @param rounding determine whether to round up/down/closest + * if there is no Entry matching the provided x-value * @return */ - int getEntryIndex(float xValue, DataSet.Rounding rounding); + int getEntryIndex(float xValue, float closestToY, DataSet.Rounding rounding); /** * Returns the position of the provided entry in the DataSets Entry array. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index cf41858f46..ad12feae45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -341,7 +341,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - BarEntry e = set.getEntryForXValue(high.getX()); + BarEntry e = set.getEntryForXValue(high.getX(), high.getY()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 5b58a01deb..e7a9c77f52 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -85,8 +85,8 @@ public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCan float low = chart.getLowestVisibleX(); float high = chart.getHighestVisibleX(); - Entry entryFrom = dataSet.getEntryForXValue(low, DataSet.Rounding.DOWN); - Entry entryTo = dataSet.getEntryForXValue(high, DataSet.Rounding.UP); + Entry entryFrom = dataSet.getEntryForXValue(low, Float.NaN, DataSet.Rounding.DOWN); + Entry entryTo = dataSet.getEntryForXValue(high, Float.NaN, DataSet.Rounding.UP); min = dataSet.getEntryIndex(entryFrom); max = dataSet.getEntryIndex(entryTo); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index f21f03d3e3..680e7810e8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -189,64 +189,60 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - // In bubble charts - it makes sense to have multiple bubbles on the same X value in the same dataset. - final List entries = set.getEntriesForXValue(high.getX()); + final BubbleEntry entry = set.getEntryForXValue(high.getX(), high.getY()); - for (BubbleEntry entry : entries) { - - if (entry.getY() != high.getY()) - continue; + if (entry.getY() != high.getY()) + continue; - if (!isInBoundsX(entry, set)) - continue; + if (!isInBoundsX(entry, set)) + continue; - Transformer trans = mChart.getTransformer(set.getAxisDependency()); + Transformer trans = mChart.getTransformer(set.getAxisDependency()); - sizeBuffer[0] = 0f; - sizeBuffer[2] = 1f; + sizeBuffer[0] = 0f; + sizeBuffer[2] = 1f; - trans.pointValuesToPixel(sizeBuffer); + trans.pointValuesToPixel(sizeBuffer); - boolean normalizeSize = set.isNormalizeSizeEnabled(); + boolean normalizeSize = set.isNormalizeSizeEnabled(); - // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs( - mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); - final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); + // calcualte the full width of 1 step on the x-axis + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); + final float maxBubbleHeight = Math.abs( + mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); + final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); - pointBuffer[0] = entry.getX(); - pointBuffer[1] = (entry.getY()) * phaseY; - trans.pointValuesToPixel(pointBuffer); + pointBuffer[0] = entry.getX(); + pointBuffer[1] = (entry.getY()) * phaseY; + trans.pointValuesToPixel(pointBuffer); - high.setDraw(pointBuffer[0], pointBuffer[1]); + high.setDraw(pointBuffer[0], pointBuffer[1]); - float shapeHalf = getShapeSize(entry.getSize(), - set.getMaxSize(), - referenceSize, - normalizeSize) / 2f; + float shapeHalf = getShapeSize(entry.getSize(), + set.getMaxSize(), + referenceSize, + normalizeSize) / 2f; - if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) - || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) - continue; + if (!mViewPortHandler.isInBoundsTop(pointBuffer[1] + shapeHalf) + || !mViewPortHandler.isInBoundsBottom(pointBuffer[1] - shapeHalf)) + continue; - if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) - continue; + if (!mViewPortHandler.isInBoundsLeft(pointBuffer[0] + shapeHalf)) + continue; - if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) - break; + if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) + break; - final int originalColor = set.getColor((int) entry.getX()); + final int originalColor = set.getColor((int) entry.getX()); - Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), - Color.blue(originalColor), _hsvBuffer); - _hsvBuffer[2] *= 0.5f; - final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); + Color.RGBToHSV(Color.red(originalColor), Color.green(originalColor), + Color.blue(originalColor), _hsvBuffer); + _hsvBuffer[2] *= 0.5f; + final int color = Color.HSVToColor(Color.alpha(originalColor), _hsvBuffer); - mHighlightPaint.setColor(color); - mHighlightPaint.setStrokeWidth(set.getHighlightCircleWidth()); - c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); - } + mHighlightPaint.setColor(color); + mHighlightPaint.setStrokeWidth(set.getHighlightCircleWidth()); + c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mHighlightPaint); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 8809c0f44b..efa4c5d012 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -313,7 +313,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - CandleEntry e = set.getEntryForXValue(high.getX()); + CandleEntry e = set.getEntryForXValue(high.getX(), high.getY()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9cab2208fb..1f46e5b7ef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -670,7 +670,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - Entry e = set.getEntryForXValue(high.getX()); + Entry e = set.getEntryForXValue(high.getX(), high.getY()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 91dc40fc38..9c4fdac24e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -148,7 +148,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - Entry e = set.getEntryForXValue(high.getX()); + final Entry e = set.getEntryForXValue(high.getX(), high.getY()); if (!isInBoundsX(e, set)) continue; diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java index 8d3843e5ce..3be28d2a57 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/DataSetTest.java @@ -150,31 +150,31 @@ public void testGetEntryForXValue() { ScatterDataSet set = new ScatterDataSet(entries, ""); - Entry closest = set.getEntryForXValue(17, DataSet.Rounding.CLOSEST); + Entry closest = set.getEntryForXValue(17, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXValue(17, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(17, Float.NaN, DataSet.Rounding.DOWN); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXValue(15, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(15, Float.NaN, DataSet.Rounding.DOWN); assertEquals(15, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXValue(14, DataSet.Rounding.DOWN); + closest = set.getEntryForXValue(14, Float.NaN, DataSet.Rounding.DOWN); assertEquals(10, closest.getX(), 0.01f); assertEquals(10, closest.getY(), 0.01f); - closest = set.getEntryForXValue(17, DataSet.Rounding.UP); + closest = set.getEntryForXValue(17, Float.NaN, DataSet.Rounding.UP); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXValue(21, DataSet.Rounding.UP); + closest = set.getEntryForXValue(21, Float.NaN, DataSet.Rounding.UP); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); - closest = set.getEntryForXValue(21, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(21, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(21, closest.getX(), 0.01f); assertEquals(5, closest.getY(), 0.01f); } @@ -199,27 +199,27 @@ public void testGetEntryForXValueWithDuplicates() { ScatterDataSet set = new ScatterDataSet(values, ""); - Entry closest = set.getEntryForXValue(0, DataSet.Rounding.CLOSEST); + Entry closest = set.getEntryForXValue(0, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(0, closest.getX(), 0.01f); assertEquals(10, closest.getY(), 0.01f); - closest = set.getEntryForXValue(5, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(5, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(5, closest.getX(), 0.01f); assertEquals(80, closest.getY(), 0.01f); - closest = set.getEntryForXValue(5.4f, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(5.4f, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(5, closest.getX(), 0.01f); assertEquals(80, closest.getY(), 0.01f); - closest = set.getEntryForXValue(4.6f, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(4.6f, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(5, closest.getX(), 0.01f); assertEquals(80, closest.getY(), 0.01f); - closest = set.getEntryForXValue(7, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(7, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(7, closest.getX(), 0.01f); assertEquals(100, closest.getY(), 0.01f); - closest = set.getEntryForXValue(4f, DataSet.Rounding.CLOSEST); + closest = set.getEntryForXValue(4f, Float.NaN, DataSet.Rounding.CLOSEST); assertEquals(4, closest.getX(), 0.01f); assertEquals(60, closest.getY(), 0.01f); From 555176bcdbaf0e92dafe8218789b57e3a20c060c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 10 Oct 2016 17:20:05 +0300 Subject: [PATCH 1195/1390] Avoid crash when dataset is empty --- .../charting/renderer/BarLineScatterCandleBubbleRenderer.java | 4 ++-- .../java/com/github/mikephil/charting/utils/Transformer.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index e7a9c77f52..7b48244688 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -88,8 +88,8 @@ public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCan Entry entryFrom = dataSet.getEntryForXValue(low, Float.NaN, DataSet.Rounding.DOWN); Entry entryTo = dataSet.getEntryForXValue(high, Float.NaN, DataSet.Rounding.UP); - min = dataSet.getEntryIndex(entryFrom); - max = dataSet.getEntryIndex(entryTo); + min = entryFrom == null ? 0 : dataSet.getEntryIndex(entryFrom); + max = entryTo == null ? 0 : dataSet.getEntryIndex(entryTo); range = (int) ((max - min) * phaseX); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 6848bc58d1..10377398c7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -171,7 +171,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY public float[] generateTransformedValuesLine(ILineDataSet data, float phaseX, float phaseY, int from, int to) { - final int count = (int) ((to - from) * phaseX + 1) * 2; + final int count = (int) ((to - from) * phaseX) * 2; if (valuePointsForGenerateTransformedValuesLine.length != count) { valuePointsForGenerateTransformedValuesLine = new float[count]; From 8ed6dd24bf1f262789e191f4be7f21651bdbb44e Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 16 Oct 2016 19:09:42 +0200 Subject: [PATCH 1196/1390] Update gradle & android sdk --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 10 +++++----- MPChartLib/build.gradle | 4 ++-- build.gradle | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index ab730cd2bd..2a0d4d3cbd 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,12 +1,12 @@ + android:targetSdkVersion="24" /> Date: Tue, 18 Oct 2016 18:17:16 +0300 Subject: [PATCH 1197/1390] Default spaceMin/max for xAxis in candlestick charts --- .../com/github/mikephil/charting/charts/CandleStickChart.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java index 61dff4bb61..fa36e3522f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java @@ -32,6 +32,9 @@ protected void init() { super.init(); mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); + + getXAxis().setSpaceMin(0.5f); + getXAxis().setSpaceMax(0.5f); } @Override From 730e5d3d9b63eb75da3aef8bac1c71cfbdf96222 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 18 Oct 2016 18:27:21 +0300 Subject: [PATCH 1198/1390] Fixed last label of line chart not rendering --- .../com/github/mikephil/charting/utils/Transformer.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index 10377398c7..0496bd0673 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -169,9 +169,10 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY * @return */ public float[] generateTransformedValuesLine(ILineDataSet data, - float phaseX, float phaseY, int from, int to) { + float phaseX, float phaseY, + int min, int max) { - final int count = (int) ((to - from) * phaseX) * 2; + final int count = ((int) ((max - min) * phaseX) + 1) * 2; if (valuePointsForGenerateTransformedValuesLine.length != count) { valuePointsForGenerateTransformedValuesLine = new float[count]; @@ -180,7 +181,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, for (int j = 0; j < count; j += 2) { - Entry e = data.getEntryForIndex(j / 2 + from); + Entry e = data.getEntryForIndex(j / 2 + min); if (e != null) { valuePoints[j] = e.getX(); From d65ffb88712e682e4ecdbee5cb0d706a327a91b6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 18 Oct 2016 18:39:04 +0300 Subject: [PATCH 1199/1390] Fixed bar chart demo first value being empty --- .../mpchartexample/BarChartActivity.java | 2 +- .../mpchartexample/custom/DayAxisValueFormatter.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 650d6183c9..427c46756a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -229,7 +229,7 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - float start = 0f; + float start = 1f; ArrayList yVals1 = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 6d58892398..59f9f8e3fd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -107,19 +107,19 @@ private int determineMonth(int dayOfYear) { return Math.max(month, 0); } - private int determineDayOfMonth(int dayOfYear, int month) { + private int determineDayOfMonth(int days, int month) { int count = 0; - int days = 0; + int daysForMonths = 0; while (count < month) { - int year = determineYear(days); - days += getDaysForMonth(count % 12, year); + int year = determineYear(daysForMonths); + daysForMonths += getDaysForMonth(count % 12, year); count++; } - return dayOfYear - days; + return days - daysForMonths; } private int determineYear(int days) { From 0fec2ef06b25a675880358cbf0978995eea5dc20 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Tue, 18 Oct 2016 22:40:45 +0200 Subject: [PATCH 1200/1390] Clear up grouped bar example --- .../res/layout/activity_barchart.xml | 8 +- .../BarChartActivityMultiDataset.java | 91 +++++++++---------- 2 files changed, 46 insertions(+), 53 deletions(-) diff --git a/MPChartExample/res/layout/activity_barchart.xml b/MPChartExample/res/layout/activity_barchart.xml index 83c812d93e..ccb26bb81c 100644 --- a/MPChartExample/res/layout/activity_barchart.xml +++ b/MPChartExample/res/layout/activity_barchart.xml @@ -35,7 +35,7 @@ + android:textAppearance="?android:attr/textAppearanceSmall" /> + android:textAppearance="?android:attr/textAppearanceSmall" /> diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index da2ba2c8bc..9377e0f1b2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -14,7 +14,6 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; @@ -46,6 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_barchart); tvX = (TextView) findViewById(R.id.tvXMax); + tvX.setTextSize(10); tvY = (TextView) findViewById(R.id.tvYMax); mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); @@ -59,7 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getDescription().setEnabled(false); // mChart.setDrawBorders(true); - + // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); @@ -83,14 +83,15 @@ protected void onCreate(Bundle savedInstanceState) { l.setDrawInside(true); l.setTypeface(mTfLight); l.setYOffset(0f); + l.setXOffset(10f); l.setYEntrySpace(0f); l.setTextSize(8f); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(mTfLight); - xl.setGranularity(1f); - xl.setCenterAxisLabels(true); - xl.setValueFormatter(new IAxisValueFormatter() { + XAxis xAxis = mChart.getXAxis(); + xAxis.setTypeface(mTfLight); + xAxis.setGranularity(1f); + xAxis.setCenterAxisLabels(true); + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { return String.valueOf((int) value); @@ -106,7 +107,7 @@ public int getDecimalDigits() { leftAxis.setTypeface(mTfLight); leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); - leftAxis.setSpaceTop(30f); + leftAxis.setSpaceTop(35f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChart.getAxisRight().setEnabled(false); @@ -145,13 +146,13 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleBarBorders: { for (IBarDataSet set : mChart.getData().getDataSets()) - ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); mChart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { + if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); mChart.invalidate(); } @@ -171,7 +172,6 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); break; } @@ -182,78 +182,73 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - float groupSpace = 0.04f; - float barSpace = 0.02f; // x3 dataset - float barWidth = 0.3f; // x3 dataset - // (0.3 + 0.02) * 3 + 0.04 = 1.00 -> interval per "group" + float groupSpace = 0.08f; + float barSpace = 0.03f; // x4 DataSet + float barWidth = 0.2f; // x4 DataSet + // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" + int groupCount = mSeekBarX.getProgress() + 1; int startYear = 1980; - int endYear = startYear + mSeekBarX.getProgress(); + int endYear = startYear + groupCount; - tvX.setText(startYear + "\n-" + endYear); + tvX.setText(startYear + "-" + endYear); tvY.setText("" + (mSeekBarY.getProgress())); ArrayList yVals1 = new ArrayList(); ArrayList yVals2 = new ArrayList(); ArrayList yVals3 = new ArrayList(); + ArrayList yVals4 = new ArrayList(); - float mult = mSeekBarY.getProgress() * 100000f; + float randomMultiplier = mSeekBarY.getProgress() * 100000f; for (int i = startYear; i < endYear; i++) { - float val = (float) (Math.random() * mult) + 3; - yVals1.add(new BarEntry(i, val)); + yVals1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + yVals2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + yVals3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + yVals4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); } - for (int i = startYear; i < endYear; i++) { - float val = (float) (Math.random() * mult) + 3; - yVals2.add(new BarEntry(i, val)); - } - - for (int i = startYear; i < endYear; i++) { - float val = (float) (Math.random() * mult) + 3; - yVals3.add(new BarEntry(i, val)); - } + BarDataSet set1, set2, set3, set4; - BarDataSet set1, set2, set3; + if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set2 = (BarDataSet)mChart.getData().getDataSetByIndex(1); - set3 = (BarDataSet)mChart.getData().getDataSetByIndex(2); + set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); + set2 = (BarDataSet) mChart.getData().getDataSetByIndex(1); + set3 = (BarDataSet) mChart.getData().getDataSetByIndex(2); + set4 = (BarDataSet) mChart.getData().getDataSetByIndex(3); set1.setValues(yVals1); set2.setValues(yVals2); set3.setValues(yVals3); + set4.setValues(yVals4); mChart.getData().notifyDataChanged(); mChart.notifyDataSetChanged(); + } else { - // create 3 datasets with different types + // create 4 DataSets set1 = new BarDataSet(yVals1, "Company A"); - // set1.setColors(ColorTemplate.createColors(getApplicationContext(), - // ColorTemplate.FRESH_COLORS)); set1.setColor(Color.rgb(104, 241, 175)); set2 = new BarDataSet(yVals2, "Company B"); set2.setColor(Color.rgb(164, 228, 251)); set3 = new BarDataSet(yVals3, "Company C"); set3.setColor(Color.rgb(242, 247, 158)); + set4 = new BarDataSet(yVals4, "Company D"); + set4.setColor(Color.rgb(255, 102, 0)); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - dataSets.add(set2); - dataSets.add(set3); - - BarData data = new BarData(dataSets); + BarData data = new BarData(set1, set2, set3, set4); data.setValueFormatter(new LargeValueFormatter()); - - // add space between the dataset groups in percent of bar-width data.setValueTypeface(mTfLight); mChart.setData(data); } + // specify the width each bar should have mChart.getBarData().setBarWidth(barWidth); + + // restrict the x-axis range mChart.getXAxis().setAxisMinimum(startYear); - mChart.getXAxis().setAxisMaximum(mChart.getBarData().getGroupWidth(groupSpace, barSpace) * mSeekBarX.getProgress() + startYear); + + // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters + mChart.getXAxis().setAxisMaximum(startYear + mChart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); mChart.groupBars(startYear, groupSpace, barSpace); mChart.invalidate(); } @@ -261,13 +256,11 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub - } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub - } @Override From 810c99c579aa99f2b99174b23380272291bd3931 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 19 Oct 2016 10:08:42 +0300 Subject: [PATCH 1201/1390] Make highlightFullBarEnabled feature work again --- .../mikephil/charting/charts/BarChart.java | 11 ++++++-- .../charting/charts/CombinedChart.java | 28 +++++++++++++++++++ .../charting/highlight/Highlight.java | 4 +-- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index b048a4fffa..2ba15c9118 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -92,8 +92,15 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (mData == null) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; - } else - return getHighlighter().getHighlight(x, y); + } else { + Highlight h = getHighlighter().getHighlight(x, y); + if (h == null || !isHighlightFullBarEnabled()) return h; + + // For isHighlightFullBarEnabled, remove stackIndex + return new Highlight(h.getX(), h.getY(), + h.getXPx(), h.getYPx(), + h.getDataSetIndex(), -1, h.getAxis()); + } } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index 65ce85ceb8..b1975b973e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -3,6 +3,7 @@ import android.content.Context; import android.util.AttributeSet; +import android.util.Log; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BubbleData; @@ -11,6 +12,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; import com.github.mikephil.charting.renderer.CombinedChartRenderer; @@ -92,6 +94,32 @@ public void setData(CombinedData data) { mRenderer.initBuffers(); } + /** + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch + * point + * inside the CombinedChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else { + Highlight h = getHighlighter().getHighlight(x, y); + if (h == null || !isHighlightFullBarEnabled()) return h; + + // For isHighlightFullBarEnabled, remove stackIndex + return new Highlight(h.getX(), h.getY(), + h.getXPx(), h.getYPx(), + h.getDataSetIndex(), -1, h.getAxis()); + } + } + @Override public LineData getLineData() { if (mData == null) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index f1d542d80b..032698d5e5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -78,7 +78,7 @@ public Highlight(float x, int dataSetIndex, int stackIndex) { * @param y the y-value of the highlighted value * @param dataSetIndex the index of the DataSet the highlighted value belongs to */ - protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis.AxisDependency axis) { + public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YAxis.AxisDependency axis) { this.mX = x; this.mY = y; this.mXPx = xPx; @@ -96,7 +96,7 @@ protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, YA * @param stackIndex references which value of a stacked-bar entry has been * selected */ - protected Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, YAxis.AxisDependency axis) { + public Highlight(float x, float y, float xPx, float yPx, int dataSetIndex, int stackIndex, YAxis.AxisDependency axis) { this(x, y, xPx, yPx, dataSetIndex, axis); this.mStackIndex = stackIndex; } From b618524a19512eef89af9d6d920857b15958710f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 19 Oct 2016 23:03:54 +0200 Subject: [PATCH 1202/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 518240d305..989fca594d 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0-beta1/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -117,7 +117,7 @@ allprojects { ```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.0' } ``` @@ -132,7 +132,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.0.0-beta1 + v3.0.0 ``` @@ -152,7 +152,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0-beta1/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 3ce2016048601def85ca31dcc680c892852968d4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 19 Oct 2016 23:09:03 +0200 Subject: [PATCH 1203/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 989fca594d..ecbd2241a8 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Features - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) - Dual (separate) Axes - - Customizable Axes (both xPx- and yPx-axis) + - Customizable Axes (both x- and y-axis) - Highlighting values (with customizable popup-views) - Save chart to SD-Card (as image, or as .txt file) - Predefined color templates From 49b61e92a4b45b33f92a9ee77f94bcd36cbcfdf9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 22 Oct 2016 15:54:26 +0200 Subject: [PATCH 1204/1390] Update README.md --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ecbd2241a8..d8fc9856be 100644 --- a/README.md +++ b/README.md @@ -122,17 +122,21 @@ dependencies { ``` **2. Maven** -- Add the following to your `pom.xml`: +- Add the following to the `` section of your `pom.xml`: + ```xml - jitpack.io - https://jitpack.io + jitpack.io + https://jitpack.io +``` +- Add the following to the `` section of your `pom.xml`: + ```xml - com.github.PhilJay - MPAndroidChart - v3.0.0 + com.github.PhilJay + MPAndroidChart + v3.0.0 ``` From 9b7cffa27420431fbcc481cab7bdffe1eb4acdbb Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sat, 22 Oct 2016 23:54:31 +0200 Subject: [PATCH 1205/1390] Move to Realm v2.0.2, update example --- MPChartExample/build.gradle | 2 +- .../mpchartexample/realm/RealmDatabaseActivityLine.java | 5 +++-- .../mpchartexample/realm/RealmWikiExample.java | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index f02c69be7d..b4c1900648 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -56,7 +56,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.1.0@aar' + compile 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:24.2.1' diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 13513fd50e..55f7f6dd4c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -6,6 +6,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -55,13 +56,13 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); - set.setDrawCubic(false); + set.setMode(LineDataSet.Mode.CUBIC_BEZIER); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); set.setColor(ColorTemplate.rgb("#FF5722")); set.setCircleColor(ColorTemplate.rgb("#FF5722")); set.setLineWidth(1.8f); - set.setCircleSize(3.6f); + set.setCircleRadius(3.6f); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index a2b9e05880..01a6ab7092 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.formatter.IAxisValueFormatter; @@ -100,13 +101,13 @@ public int getDecimalDigits() { barChart.getXAxis().setValueFormatter(formatter); RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); - lineDataSet.setDrawCubic(false); + lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); lineDataSet.setLabel("Result Scores"); lineDataSet.setDrawCircleHole(false); lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); lineDataSet.setLineWidth(1.8f); - lineDataSet.setCircleSize(3.6f); + lineDataSet.setCircleRadius(3.6f); ArrayList dataSets = new ArrayList(); dataSets.add(lineDataSet); From 9a19bf6670570f125b2633f99a17586708d82c4f Mon Sep 17 00:00:00 2001 From: PhilJay Date: Sun, 23 Oct 2016 00:02:49 +0200 Subject: [PATCH 1206/1390] Migrate to Realm v2.0.2, fix example --- .../mpchartexample/realm/RealmBaseActivity.java | 6 +++--- .../mpchartexample/realm/RealmDatabaseActivityPie.java | 3 +-- .../mpchartexample/realm/RealmMainActivity.java | 4 +++- build.gradle | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index f7d7233d88..9b98f00f92 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -83,7 +83,7 @@ protected void onResume() { super.onResume(); // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); Realm.setDefaultConfiguration(realmConfig); mRealm = Realm.getDefaultInstance(); @@ -189,8 +189,8 @@ protected void writeToDBPie() { float value4 = 15f + (float) (Math.random() * 8f); float value5 = 100f - value1 - value2 - value3 - value4; - float[] values = new float[] { value1, value2, value3, value4, value5 }; - String[] labels = new String[]{ "iOS", "Android", "WP 10", "BlackBerry", "Other"}; + float[] values = new float[]{value1, value2, value3, value4, value5}; + String[] labels = new String[]{"iOS", "Android", "WP 10", "BlackBerry", "Other"}; for (int i = 0; i < values.length; i++) { RealmDemoData d = new RealmDemoData(values[i], labels[i]); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 7b1eb675d9..2936379d55 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -53,8 +53,7 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); // stacked entries + RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java index 3198320272..07c54ad88c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -56,8 +56,10 @@ protected void onCreate(Bundle savedInstanceState) { lv.setOnItemClickListener(this); + Realm.init(this); + // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder(getApplicationContext()).build(); + RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); Realm.setDefaultConfiguration(realmConfig); Realm realm = Realm.getDefaultInstance(); diff --git a/build.gradle b/build.gradle index 616c6ebc00..76344c5b7e 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath "io.realm:realm-gradle-plugin:1.1.0" + classpath "io.realm:realm-gradle-plugin:2.0.2" classpath 'com.android.tools.build:gradle:2.2.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } From bc13bc2c172bac486d8d09d5b4c4d4f1d8a04fac Mon Sep 17 00:00:00 2001 From: Evgeniy Date: Thu, 27 Oct 2016 08:45:39 +0300 Subject: [PATCH 1207/1390] Update AxisBase.java Mistake fixed --- .../com/github/mikephil/charting/components/AxisBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 997612eb53..1fd98413db 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -306,7 +306,7 @@ public boolean isDrawLabelsEnabled() { * Sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware * that this number is not fixed. * - * @param count the number of y-axis labels that sould be displayed + * @param count the number of y-axis labels that should be displayed */ public void setLabelCount(int count) { @@ -324,7 +324,7 @@ public void setLabelCount(int count) { * that this number is not * fixed (if force == false) and can only be approximated. * - * @param count the number of y-axis labels that sould be displayed + * @param count the number of y-axis labels that should be displayed * @param force if enabled, the set label count will be forced, meaning that the exact * specified count of labels will * be drawn and evenly distributed alongside the axis - this might cause labels From fb8094e9f2fa687a9440f32be2272770ee45b5a6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 11:45:05 +0200 Subject: [PATCH 1208/1390] Make automatically disabling slice-spacing an opt-in feature --- .../mikephil/charting/data/PieDataSet.java | 22 +++++++++++++++++++ .../interfaces/datasets/IPieDataSet.java | 8 +++++++ .../charting/renderer/PieChartRenderer.java | 3 +++ 3 files changed, 33 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 3e864a25d8..229ed5339b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -11,6 +11,7 @@ public class PieDataSet extends DataSet implements IPieDataSet { /** the space in pixels between the chart-slices, default 0f */ private float mSliceSpace = 0f; + private boolean mAutomaticallyDisableSliceSpacing; /** indicates the selection distance of a pie slice */ private float mShift = 18f; @@ -75,6 +76,27 @@ public float getSliceSpace() { return mSliceSpace; } + /** + * When enabled, slice spacing will be 0.0 when the smallest value is going to be + * smaller than the slice spacing itself. + * + * @param autoDisable + */ + public void setAutomaticallyDisableSliceSpacing(boolean autoDisable) { + mAutomaticallyDisableSliceSpacing = autoDisable; + } + + /** + * When enabled, slice spacing will be 0.0 when the smallest value is going to be + * smaller than the slice spacing itself. + * + * @return + */ + @Override + public boolean isAutomaticallyDisableSliceSpacing() { + return mAutomaticallyDisableSliceSpacing; + } + /** * sets the distance the highlighted piechart-slice of this DataSet is * "shifted" away from the center of the chart, default 12f diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 3b10d003ba..aa1c57524a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -17,6 +17,14 @@ public interface IPieDataSet extends IDataSet { */ float getSliceSpace(); + /** + * When enabled, slice spacing will be 0.0 when the smallest value is going to be + * smaller than the slice spacing itself. + * + * @return + */ + boolean isAutomaticallyDisableSliceSpacing(); + /** * Returns the distance a highlighted piechart slice is "shifted" away from * the chart-center in dp. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 1681d5baae..3c52f7ceca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -199,6 +199,9 @@ protected float calculateMinimumRadiusForSpacedSlice( */ protected float getSliceSpace(IPieDataSet dataSet) { + if (!dataSet.isAutomaticallyDisableSliceSpacing()) + return dataSet.getSliceSpace(); + float spaceSizeRatio = dataSet.getSliceSpace() / mViewPortHandler.getSmallestContentExtension(); float minValueRatio = dataSet.getYMin() / mChart.getData().getYValueSum() * 2; From 49b4d1a96b55d255015e366557fe0eb733542e62 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 12:09:49 +0200 Subject: [PATCH 1209/1390] Bugfix: Corrected clipRect on the proper rect variable --- .../com/github/mikephil/charting/renderer/YAxisRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 46f581732c..bd3994a09e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -221,7 +221,7 @@ protected void drawZeroLine(Canvas c) { int clipRestoreCount = c.save(); mZeroLineClippingRect.set(mViewPortHandler.getContentRect()); mZeroLineClippingRect.inset(0.f, -mYAxis.getZeroLineWidth() / 2.f); - c.clipRect(mLimitLineClippingRect); + c.clipRect(mZeroLineClippingRect); // draw zero line MPPointD pos = mTrans.getPixelForValues(0f, 0f); From 70691bea41a43d9df21db1a785ea3cec3f79c8fc Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 13:10:11 +0200 Subject: [PATCH 1210/1390] Fixed glitch in clipping rects. It's the Android's renderer's bug. When specifying exact clipping rects, they are clipping more than they should! So drawing a thin 1px line on the edge of a clipping rect fail. Instead of insetting by half the line width, inset by full line width. --- .../mikephil/charting/renderer/XAxisRenderer.java | 4 ++-- .../renderer/XAxisRendererHorizontalBarChart.java | 4 ++-- .../mikephil/charting/renderer/YAxisRenderer.java | 10 +++++----- .../renderer/YAxisRendererHorizontalBarChart.java | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index e2a9b8215f..2c305796df 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -270,7 +270,7 @@ public void renderGridLines(Canvas c) { public RectF getGridClippingRect() { mGridClippingRect.set(mViewPortHandler.getContentRect()); - mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f); + mGridClippingRect.inset(-mAxis.getGridLineWidth(), 0.f); return mGridClippingRect; } @@ -322,7 +322,7 @@ public void renderLimitLines(Canvas c) { int clipRestoreCount = c.save(); mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); - mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f); + mLimitLineClippingRect.inset(-l.getLineWidth(), 0.f); c.clipRect(mLimitLineClippingRect); position[0] = l.getLimit(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 48e1ece8b5..86047cf1b8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -165,7 +165,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { @Override public RectF getGridClippingRect() { mGridClippingRect.set(mViewPortHandler.getContentRect()); - mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f); + mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth()); return mGridClippingRect; } @@ -238,7 +238,7 @@ public void renderLimitLines(Canvas c) { int clipRestoreCount = c.save(); mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); - mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f); + mLimitLineClippingRect.inset(0.f, -l.getLineWidth()); c.clipRect(mLimitLineClippingRect); mLimitLinePaint.setStyle(Paint.Style.STROKE); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index bd3994a09e..8de852f645 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -167,7 +167,7 @@ public void renderGridLines(Canvas c) { public RectF getGridClippingRect() { mGridClippingRect.set(mViewPortHandler.getContentRect()); - mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth() / 2.f); + mGridClippingRect.inset(0.f, -mAxis.getGridLineWidth()); return mGridClippingRect; } @@ -220,7 +220,7 @@ protected void drawZeroLine(Canvas c) { int clipRestoreCount = c.save(); mZeroLineClippingRect.set(mViewPortHandler.getContentRect()); - mZeroLineClippingRect.inset(0.f, -mYAxis.getZeroLineWidth() / 2.f); + mZeroLineClippingRect.inset(0.f, -mYAxis.getZeroLineWidth()); c.clipRect(mZeroLineClippingRect); // draw zero line @@ -232,8 +232,8 @@ protected void drawZeroLine(Canvas c) { Path zeroLinePath = mDrawZeroLinePath; zeroLinePath.reset(); - zeroLinePath.moveTo(mViewPortHandler.contentLeft(), (float) pos.y - 1); - zeroLinePath.lineTo(mViewPortHandler.contentRight(), (float) pos.y - 1); + zeroLinePath.moveTo(mViewPortHandler.contentLeft(), (float) pos.y); + zeroLinePath.lineTo(mViewPortHandler.contentRight(), (float) pos.y); // draw a path because lines don't support dashing on lower android versions c.drawPath(zeroLinePath, mZeroLinePaint); @@ -272,7 +272,7 @@ public void renderLimitLines(Canvas c) { int clipRestoreCount = c.save(); mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); - mLimitLineClippingRect.inset(0.f, -l.getLineWidth() / 2.f); + mLimitLineClippingRect.inset(0.f, -l.getLineWidth()); c.clipRect(mLimitLineClippingRect); mLimitLinePaint.setStyle(Paint.Style.STROKE); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 2f96fa71f6..2e394af99a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -168,7 +168,7 @@ protected float[] getTransformedPositions() { @Override public RectF getGridClippingRect() { mGridClippingRect.set(mViewPortHandler.getContentRect()); - mGridClippingRect.inset(-mAxis.getGridLineWidth() / 2.f, 0.f); + mGridClippingRect.inset(-mAxis.getGridLineWidth(), 0.f); return mGridClippingRect; } @@ -188,7 +188,7 @@ protected void drawZeroLine(Canvas c) { int clipRestoreCount = c.save(); mZeroLineClippingRect.set(mViewPortHandler.getContentRect()); - mZeroLineClippingRect.inset(-mYAxis.getZeroLineWidth() / 2.f, 0.f); + mZeroLineClippingRect.inset(-mYAxis.getZeroLineWidth(), 0.f); c.clipRect(mLimitLineClippingRect); // draw zero line @@ -242,7 +242,7 @@ public void renderLimitLines(Canvas c) { int clipRestoreCount = c.save(); mLimitLineClippingRect.set(mViewPortHandler.getContentRect()); - mLimitLineClippingRect.inset(-l.getLineWidth() / 2.f, 0.f); + mLimitLineClippingRect.inset(-l.getLineWidth(), 0.f); c.clipRect(mLimitLineClippingRect); pts[0] = l.getLimit(); From 6a5580b101d7d22ec320a994a90c6c07c90d23bf Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 13:26:25 +0200 Subject: [PATCH 1211/1390] Renamed new property getter --- .../main/java/com/github/mikephil/charting/data/PieDataSet.java | 2 +- .../mikephil/charting/interfaces/datasets/IPieDataSet.java | 2 +- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 229ed5339b..010cfbddc5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -93,7 +93,7 @@ public void setAutomaticallyDisableSliceSpacing(boolean autoDisable) { * @return */ @Override - public boolean isAutomaticallyDisableSliceSpacing() { + public boolean isAutomaticallyDisableSliceSpacingEnabled() { return mAutomaticallyDisableSliceSpacing; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index aa1c57524a..a53a9645af 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -23,7 +23,7 @@ public interface IPieDataSet extends IDataSet { * * @return */ - boolean isAutomaticallyDisableSliceSpacing(); + boolean isAutomaticallyDisableSliceSpacingEnabled(); /** * Returns the distance a highlighted piechart slice is "shifted" away from diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 3c52f7ceca..ff22018364 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -199,7 +199,7 @@ protected float calculateMinimumRadiusForSpacedSlice( */ protected float getSliceSpace(IPieDataSet dataSet) { - if (!dataSet.isAutomaticallyDisableSliceSpacing()) + if (!dataSet.isAutomaticallyDisableSliceSpacingEnabled()) return dataSet.getSliceSpace(); float spaceSizeRatio = dataSet.getSliceSpace() / mViewPortHandler.getSmallestContentExtension(); From 8045d64260ebcd9d49cb6b60c02771a7da18ba73 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 13:32:47 +0200 Subject: [PATCH 1212/1390] Added `clipValuesToContent` property for clipping values --- .../charting/charts/BarLineChartBase.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 6fa3b4d312..c4b32c16eb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -97,6 +97,8 @@ public abstract class BarLineChartBase Date: Mon, 31 Oct 2016 13:34:22 +0200 Subject: [PATCH 1213/1390] Added missing isDrawBordersEnabled getter --- .../mikephil/charting/charts/BarLineChartBase.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index c4b32c16eb..b4a2fb7c19 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1153,8 +1153,8 @@ public void setDrawGridBackground(boolean enabled) { } /** - * Sets drawing the borders rectangle to true. If this is enabled, there is - * no point drawing the axis-lines of x- and y-axis. + * When enabled, the borders rectangle will be rendered. + * If this is enabled, there is no point drawing the axis-lines of x- and y-axis. * * @param enabled */ @@ -1162,6 +1162,16 @@ public void setDrawBorders(boolean enabled) { mDrawBorders = enabled; } + /** + * When enabled, the borders rectangle will be rendered. + * If this is enabled, there is no point drawing the axis-lines of x- and y-axis. + * + * @return + */ + public boolean isDrawBordersEnabled() { + return mDrawBorders; + } + /** * When enabled, the values will be clipped to contentRect, * otherwise they can bleed outside the content rect. From 00f36054c79938e2cb6c0276df16ae10b42a6400 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 31 Oct 2016 15:35:16 +0200 Subject: [PATCH 1214/1390] Fixed weird glitch in mixed (pos/neg) stacked bars highlight https://github.com/danielgindi/Charts/pull/1744 https://github.com/danielgindi/Charts/issues/1726 --- .../java/com/github/mikephil/charting/data/BarEntry.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index dbf1e945db..922f151879 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -42,8 +42,8 @@ public BarEntry(float x, float[] vals) { super(x, calcSum(vals)); this.mYVals = vals; - calcRanges(); calcPosNegSum(); + calcRanges(); } /** @@ -67,8 +67,8 @@ public BarEntry(float x, float[] vals, String label) { super(x, calcSum(vals), label); this.mYVals = vals; - calcRanges(); calcPosNegSum(); + calcRanges(); } /** @@ -242,8 +242,8 @@ protected void calcRanges() { float value = values[i]; if (value < 0) { - mRanges[i] = new Range(negRemain, negRemain + value); - negRemain += Math.abs(value); + mRanges[i] = new Range(negRemain, negRemain - value); + negRemain -= value; } else { mRanges[i] = new Range(posRemain, posRemain + value); posRemain += value; From 3928e285ae4e8970b74e3e5104703105477386fc Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 8 Nov 2016 17:25:19 +0200 Subject: [PATCH 1215/1390] Fixed double calculation of xAxis spacing --- .../github/mikephil/charting/charts/BarLineChartBase.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index b4a2fb7c19..8aeb6828d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -397,18 +397,12 @@ protected void calculateLegendOffsets(RectF offsets) { offsets.top += Math.min(mLegend.mNeededHeight, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + mLegend.getYOffset(); - - if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) - offsets.top += getXAxis().mLabelRotatedHeight; break; case BOTTOM: offsets.bottom += Math.min(mLegend.mNeededHeight, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + mLegend.getYOffset(); - - if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) - offsets.bottom += getXAxis().mLabelRotatedHeight; break; default: From 262d877b9ffa4b529724de2b54db840c1395ea38 Mon Sep 17 00:00:00 2001 From: Mahesh Gaya Date: Sat, 12 Nov 2016 12:23:36 -0600 Subject: [PATCH 1216/1390] Fix: typo for October --- .../mpchartexample/custom/DayAxisValueFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 59f9f8e3fd..b03e773781 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -11,7 +11,7 @@ public class DayAxisValueFormatter implements IAxisValueFormatter { protected String[] mMonths = new String[]{ - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; private BarLineChartBase chart; From ee020bba67a60018e8e864af3bbc6aa32113fd27 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 16 Nov 2016 10:53:47 +0200 Subject: [PATCH 1217/1390] Gradle updates --- MPChartExample/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index b4c1900648..662018126f 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -39,7 +39,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.1' + classpath 'com.android.tools.build:gradle:2.2.2' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/build.gradle b/build.gradle index 76344c5b7e..2894c13be0 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:2.0.2" - classpath 'com.android.tools.build:gradle:2.2.1' + classpath 'com.android.tools.build:gradle:2.2.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From 0818d766dbd71a5106df836784c796cc69f7302f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 16 Nov 2016 11:01:17 +0200 Subject: [PATCH 1218/1390] Fixed EPSILON. (Closes #2432) Closes #2424 Closes #2394 Closes #2393 Closes #2385 --- .../main/java/com/github/mikephil/charting/utils/Utils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index b555b44917..b44f9d9ea7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -40,10 +40,10 @@ public abstract class Utils { public final static float FDEG2RAD = ((float) Math.PI / 180.f); @SuppressWarnings("unused") - public final static double DOUBLE_EPSILON = Double.longBitsToDouble(Double.doubleToLongBits(1.0) + 1); + public final static double DOUBLE_EPSILON = Double.longBitsToDouble(1); @SuppressWarnings("unused") - public final static float FLOAT_EPSILON = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1); + public final static float FLOAT_EPSILON = Float.intBitsToFloat(1); /** * initialize method, called inside the Chart.init() method. From 4cb83a7b915628204131485fee156a873a216cde Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 16 Nov 2016 11:13:29 +0200 Subject: [PATCH 1219/1390] Added IndexAxisValueFormatter, to allow for easy x-axis labels like MPAndroidChart 2.0 --- .../BarChartActivityMultiDataset.java | 5 -- .../BarChartPositiveNegative.java | 5 -- .../mpchartexample/CombinedChartActivity.java | 5 -- .../mpchartexample/LineChartTime.java | 5 -- .../mpchartexample/RadarChartActivitry.java | 5 -- .../StackedBarActivityNegative.java | 10 --- .../custom/DayAxisValueFormatter.java | 5 -- .../custom/MyAxisValueFormatter.java | 5 -- .../custom/MyCustomXAxisValueFormatter.java | 5 -- .../custom/YearXAxisFormatter.java | 5 -- .../realm/RealmWikiExample.java | 5 -- .../charting/components/AxisBase.java | 8 +-- .../formatter/DefaultAxisValueFormatter.java | 6 +- .../formatter/IAxisValueFormatter.java | 7 -- .../formatter/IndexAxisValueFormatter.java | 69 +++++++++++++++++++ .../formatter/LargeValueFormatter.java | 1 - .../charting/formatter/PercentFormatter.java | 1 - 17 files changed, 77 insertions(+), 75 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 9377e0f1b2..671ab5abec 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -96,11 +96,6 @@ protected void onCreate(Bundle savedInstanceState) { public String getFormattedValue(float value, AxisBase axis) { return String.valueOf((int) value); } - - @Override - public int getDecimalDigits() { - return 0; - } }); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 10a7bb9fd9..743b7e735d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -90,11 +90,6 @@ protected void onCreate(Bundle savedInstanceState) { public String getFormattedValue(float value, AxisBase axis) { return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; } - - @Override - public int getDecimalDigits() { - return 0; - } }); setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index f221dcf3b7..fadfbf175f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -84,11 +84,6 @@ protected void onCreate(Bundle savedInstanceState) { public String getFormattedValue(float value, AxisBase axis) { return mMonths[(int) value % mMonths.length]; } - - @Override - public int getDecimalDigits() { - return 0; - } }); CombinedData data = new CombinedData(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 04070d2c26..30e5e2a978 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -100,11 +100,6 @@ public String getFormattedValue(float value, AxisBase axis) { long millis = TimeUnit.HOURS.toMillis((long) value); return mFormat.format(new Date(millis)); } - - @Override - public int getDecimalDigits() { - return 0; - } }); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index b787f17e85..937973fe4e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -81,11 +81,6 @@ protected void onCreate(Bundle savedInstanceState) { public String getFormattedValue(float value, AxisBase axis) { return mActivities[(int) value % mActivities.length]; } - - @Override - public int getDecimalDigits() { - return 0; - } }); xAxis.setTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 8b9819092a..01d4f2f89b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -85,11 +85,6 @@ protected void onCreate(Bundle savedInstanceState) { public String getFormattedValue(float value, AxisBase axis) { return format.format(value) + "-" + format.format(value + 10); } - - @Override - public int getDecimalDigits() { - return 0; - } }); Legend l = mChart.getLegend(); @@ -243,10 +238,5 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(Math.abs(value)) + "m"; } - - @Override - public int getDecimalDigits() { - return 0; - } } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 59f9f8e3fd..6edffb9315 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -136,9 +136,4 @@ else if (days <= 1458) return 2020; } - - @Override - public int getDecimalDigits() { - return 0; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index 137097b84e..e8456675a9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -18,9 +18,4 @@ public MyAxisValueFormatter() { public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + " $"; } - - @Override - public int getDecimalDigits() { - return 1; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 23f5785c11..c66e5d4569 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -37,9 +37,4 @@ else if (xScale > 1) else return mFormat.format(value); } - - @Override - public int getDecimalDigits() { - return 1; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index 0b1245cd77..34d76c25eb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -24,9 +24,4 @@ public String getFormattedValue(float value, AxisBase axis) { float percent = value / axis.mAxisRange; return mMonths[(int) (mMonths.length * percent)]; } - - @Override - public int getDecimalDigits() { - return 0; - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 01a6ab7092..6c1d7cde03 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -90,11 +90,6 @@ private void setData() { public String getFormattedValue(float value, AxisBase axis) { return results.get((int) value).getPlayerName(); } - - @Override - public int getDecimalDigits() { - return 0; - } }; lineChart.getXAxis().setValueFormatter(formatter); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 997612eb53..8113d63bca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -496,12 +496,10 @@ public void setValueFormatter(IAxisValueFormatter f) { */ public IAxisValueFormatter getValueFormatter() { - if (mAxisValueFormatter == null) { + if (mAxisValueFormatter == null || + (mAxisValueFormatter instanceof DefaultAxisValueFormatter && + ((DefaultAxisValueFormatter)mAxisValueFormatter).getDecimalDigits() != mDecimals)) mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); - } else if (mAxisValueFormatter.getDecimalDigits() != mDecimals && mAxisValueFormatter instanceof - DefaultAxisValueFormatter) { - mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); - } return mAxisValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index f29c554059..552c150e69 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -45,7 +45,11 @@ public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value); } - @Override + /** + * Returns the number of decimal digits this formatter uses or -1, if unspecified. + * + * @return + */ public int getDecimalDigits() { return digits; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java index 5be1d28752..51939b5432 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java @@ -20,11 +20,4 @@ public interface IAxisValueFormatter * @return */ String getFormattedValue(float value, AxisBase axis); - - /** - * Returns the number of decimal digits this formatter uses or -1, if unspecified. - * - * @return - */ - int getDecimalDigits(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java new file mode 100644 index 0000000000..07349a6a0e --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java @@ -0,0 +1,69 @@ + +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.Collection; + +/** + * This formatter is used for passing an array of x-axis labels, on whole x steps. + */ +public class IndexAxisValueFormatter implements IAxisValueFormatter +{ + private String[] mValues = new String[] {}; + private int mValueCount = 0; + + /** + * An empty constructor. + * Use `setValues` to set the axis labels. + */ + public IndexAxisValueFormatter() { + } + + /** + * Constructor that specifies axis labels. + * + * @param values The values string array + */ + public IndexAxisValueFormatter(String[] values) { + if (values != null) + setValues(values); + } + + /** + * Constructor that specifies axis labels. + * + * @param values The values string array + */ + public IndexAxisValueFormatter(Collection values) { + if (values != null) + setValues(values.toArray(new String[values.size()])); + } + + public String getFormattedValue(float value, AxisBase axis) { + int index = Math.round(value); + + if (index < 0 || index >= mValueCount || index != (int)value) + return ""; + + return mValues[index]; + } + + public String[] getValues() + { + return mValues; + } + + public void setValues(String[] values) + { + if (values == null) + values = new String[] {}; + + this.mValues = values; + this.mValueCount = values.length; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 0b4e8306c1..c950d640b3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -93,7 +93,6 @@ private String makePretty(double number) { return r; } - @Override public int getDecimalDigits() { return 0; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index d321b5f03e..de8a10255a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -43,7 +43,6 @@ public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(value) + " %"; } - @Override public int getDecimalDigits() { return 1; } From 2e80fada31eb1fdec98f847a2b5f039ed8ea9337 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 16 Nov 2016 12:04:57 +0200 Subject: [PATCH 1220/1390] Fixed a bug where the mod-360 bypass draws a full-circle for 0 slices. --- .../mikephil/charting/renderer/PieChartRenderer.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index ff22018364..84fda6e5f2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -269,7 +269,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); - if (sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); } else { @@ -318,7 +318,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } final float endAngleInner = startAngleInner + sweepAngleInner; - if (sweepAngleOuter % 360f == 0.f) { + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); } else { @@ -335,7 +335,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } } else { - if (sweepAngleOuter % 360f != 0.f) { + if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { if (accountForSliceSpacing) { float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; @@ -818,7 +818,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mPathBuffer.reset(); - if (sweepAngleOuter % 360f == 0.f) { + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, highlightedRadius, Path.Direction.CW); } else { @@ -875,7 +875,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } final float endAngleInner = startAngleInner + sweepAngleInner; - if (sweepAngleOuter % 360f == 0.f) { + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { // Android is doing "mod 360" mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); } else { @@ -892,7 +892,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } else { - if (sweepAngleOuter % 360f != 0.f) { + if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { if (accountForSliceSpacing) { final float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; From a7fd778fc862e9165dfc896105593823eb93bd60 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Thu, 17 Nov 2016 19:01:21 +0100 Subject: [PATCH 1221/1390] Upgrade version --- MPChartExample/build.gradle | 4 ++-- MPChartLib/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 662018126f..8ba24587be 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,8 +7,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 24 - versionCode 53 - versionName '3.0.0' + versionCode 54 + versionName '3.0.1' testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" sourceSets { diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 9bbffe9862..6f1e5d3a00 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -11,7 +11,7 @@ android { minSdkVersion 9 targetSdkVersion 24 versionCode 3 - versionName '3.0.0' + versionName '3.0.1' } buildTypes { release { From 08f295eae1279ba69a18184ee4db86f770df0e18 Mon Sep 17 00:00:00 2001 From: PhilJay Date: Thu, 17 Nov 2016 19:01:53 +0100 Subject: [PATCH 1222/1390] Upgrade manifest --- MPChartExample/AndroidManifest.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 2a0d4d3cbd..b1ac584a2e 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="54" + android:versionName="3.0.1" > Date: Sat, 19 Nov 2016 10:01:13 +0100 Subject: [PATCH 1223/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d8fc9856be..a86d8f123d 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.1/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -117,7 +117,7 @@ allprojects { ```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.0' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.1' } ``` @@ -136,7 +136,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.0.0 + v3.0.1 ``` @@ -156,7 +156,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.1/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 9aaa3328f011cc8f52d2ae3449ae3f16b57cf952 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 10 Dec 2016 10:35:28 +0100 Subject: [PATCH 1224/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a86d8f123d..e2e8f853a6 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Donations - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! -If you just want to be nice, you can check out my [**Amazon-Wishlist**]( https://www.amazon.de/registry/wishlist/2DYHJ69VMF8HM/ref=cm_sw_em_r_mt_ws_WVCyxb4KKQ2G6). +If you just want to be nice, you can check out and rate the new [**Telegram Chat Bot**]( https://storebot.me/bot/myalfred_bot) we created for scheduling meetings and other stuff. ## Xamarin From 8abe7e84ad16cbfa320652573d60f945263ce7bb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 10 Dec 2016 10:35:56 +0100 Subject: [PATCH 1225/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e2e8f853a6..8b25078be2 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Donations - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! -If you just want to be nice, you can check out and rate the new [**Telegram Chat Bot**]( https://storebot.me/bot/myalfred_bot) we created for scheduling meetings and other stuff. +If you just want to be nice, you can check out and rate the new [**Telegram Chat Bot**]( https://storebot.me/bot/myalfred_bot) we created for scheduling meetings and other stuff. 😉 ## Xamarin From 34e7f4497962d235d94072d1544e22a7a362ae30 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 19 Dec 2016 21:56:03 +0200 Subject: [PATCH 1226/1390] drawBottomYLabelEntryEnabled --- .../github/mikephil/charting/components/YAxis.java | 14 ++++++++++++++ .../mikephil/charting/renderer/YAxisRenderer.java | 10 ++++++---- .../renderer/YAxisRendererHorizontalBarChart.java | 10 ++++++---- .../charting/renderer/YAxisRendererRadarChart.java | 10 +++++----- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 82d77c4c8f..e84caab76b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -18,6 +18,11 @@ */ public class YAxis extends AxisBase { + /** + * indicates if the bottom y-label entry is drawn or not + */ + private boolean mDrawBottomYLabelEntry = true; + /** * indicates if the top y-label entry is drawn or not */ @@ -168,6 +173,15 @@ public boolean isDrawTopYLabelEntryEnabled() { return mDrawTopYLabelEntry; } + /** + * returns true if drawing the bottom y-axis label entry is enabled + * + * @return + */ + public boolean isDrawBottomYLabelEntryEnabled() { + return mDrawBottomYLabelEntry; + } + /** * set this to true to enable drawing the top y-label entry. Disabling this can be helpful * when the top y-label and diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index 8de852f645..a2bf679777 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -114,14 +114,16 @@ public void renderAxisLine(Canvas c) { */ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { + final int from = mYAxis.isDrawBottomYLabelEntryEnabled() ? 0 : 1; + final int to = mYAxis.isDrawTopYLabelEntryEnabled() + ? mYAxis.mEntryCount + : (mYAxis.mEntryCount - 1); + // draw - for (int i = 0; i < mYAxis.mEntryCount; i++) { + for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) - return; - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 2e394af99a..71275b03c3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -137,12 +137,14 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); mAxisLabelPaint.setColor(mYAxis.getTextColor()); - for (int i = 0; i < mYAxis.mEntryCount; i++) { + final int from = mYAxis.isDrawBottomYLabelEntryEnabled() ? 0 : 1; + final int to = mYAxis.isDrawTopYLabelEntryEnabled() + ? mYAxis.mEntryCount + : (mYAxis.mEntryCount - 1); - String text = mYAxis.getFormattedLabel(i); + for (int i = from; i < to; i++) { - if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) - return; + String text = mYAxis.getFormattedLabel(i); c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisLabelPaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 64bbb1e085..ee7392e928 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -156,12 +156,12 @@ public void renderAxisLabels(Canvas c) { MPPointF pOut = MPPointF.getInstance(0,0); float factor = mChart.getFactor(); - int labelCount = mYAxis.mEntryCount; + final int from = mYAxis.isDrawBottomYLabelEntryEnabled() ? 0 : 1; + final int to = mYAxis.isDrawTopYLabelEntryEnabled() + ? mYAxis.mEntryCount + : (mYAxis.mEntryCount - 1); - for (int j = 0; j < labelCount; j++) { - - if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) - break; + for (int j = from; j < to; j++) { float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; From a934501315226f4fd13bab18083d59c6ffc90e1b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 19 Dec 2016 21:56:16 +0200 Subject: [PATCH 1227/1390] Gradle updates --- MPChartExample/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8ba24587be..96c367bb0b 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -39,7 +39,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:2.2.3' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/build.gradle b/build.gradle index 2894c13be0..5969598ccc 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:2.0.2" - classpath 'com.android.tools.build:gradle:2.2.2' + classpath 'com.android.tools.build:gradle:2.2.3' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } From d5e5ec3a924248a3b1d4b977b3b7658a0f3d0a12 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 19 Dec 2016 22:06:41 +0200 Subject: [PATCH 1228/1390] resetZoom() --- .../charting/charts/BarLineChartBase.java | 37 ++++++++++++------- .../charting/utils/ViewPortHandler.java | 10 +++++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 8aeb6828d8..745d6019e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -571,17 +571,17 @@ public void computeScroll() { * VIEWPORT */ - protected Matrix mZoomInMatrixBuffer = new Matrix(); + protected Matrix mZoomMatrixBuffer = new Matrix(); /** - * Zooms in by 1.4f, into the charts center. center. + * Zooms in by 1.4f, into the charts center. */ public void zoomIn() { MPPointF center = mViewPortHandler.getContentCenter(); - mViewPortHandler.zoomIn(center.x, -center.y, mZoomInMatrixBuffer); - mViewPortHandler.refresh(mZoomInMatrixBuffer, this, false); + mViewPortHandler.zoomIn(center.x, -center.y, mZoomMatrixBuffer); + mViewPortHandler.refresh(mZoomMatrixBuffer, this, false); MPPointF.recycleInstance(center); @@ -592,17 +592,15 @@ public void zoomIn() { postInvalidate(); } - protected Matrix mZoomOutMatrixBuffer = new Matrix(); - /** - * Zooms out by 0.7f, from the charts center. center. + * Zooms out by 0.7f, from the charts center. */ public void zoomOut() { MPPointF center = mViewPortHandler.getContentCenter(); - mViewPortHandler.zoomOut(center.x, -center.y, mZoomOutMatrixBuffer); - mViewPortHandler.refresh(mZoomOutMatrixBuffer, this, false); + mViewPortHandler.zoomOut(center.x, -center.y, mZoomMatrixBuffer); + mViewPortHandler.refresh(mZoomMatrixBuffer, this, false); MPPointF.recycleInstance(center); @@ -613,7 +611,20 @@ public void zoomOut() { postInvalidate(); } - protected Matrix mZoomMatrixBuffer = new Matrix(); + /** + * Zooms out to original size. + */ + public void resetZoom() { + + mViewPortHandler.resetZoom(mZoomMatrixBuffer); + mViewPortHandler.refresh(mZoomMatrixBuffer, this, false); + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + calculateOffsets(); + postInvalidate(); + } /** * Zooms in or out by the given scale factor. x and y are the coordinates @@ -625,9 +636,9 @@ public void zoomOut() { * @param y */ public void zoom(float scaleX, float scaleY, float x, float y) { - Matrix save = mZoomMatrixBuffer; - mViewPortHandler.zoom(scaleX, scaleY, x, -y, save); - mViewPortHandler.refresh(save, this, false); + + mViewPortHandler.zoom(scaleX, scaleY, x, -y, mZoomMatrixBuffer); + mViewPortHandler.refresh(mZoomMatrixBuffer, this, false); // Range might have changed, which means that Y-axis labels // could have changed in size, affecting Y-axis size. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 541c726eeb..71b4b9bf79 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -223,6 +223,16 @@ public void zoomOut(float x, float y, Matrix outputMatrix) { outputMatrix.postScale(0.7f, 0.7f, x, y); } + /** + * Zooms out to original size. + * @param outputMatrix + */ + public void resetZoom(Matrix outputMatrix) { + outputMatrix.reset(); + outputMatrix.set(mMatrixTouch); + outputMatrix.postScale(1.0f, 1.0f, 0.0f, 0.0f); + } + /** * Post-scales by the specified scale factors. * From ccf6b7e3b1054a5a47d2822148cc19c14e9c3da6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 19 Dec 2016 22:50:08 +0200 Subject: [PATCH 1229/1390] Correctly position 0 in stacked bar --- .../github/mikephil/charting/buffer/BarBuffer.java | 6 +++++- .../charting/renderer/BarChartRenderer.java | 11 +++++++++-- .../renderer/HorizontalBarChartRenderer.java | 13 ++++++++++--- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java index 1a6b85bcb3..136a231445 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/buffer/BarBuffer.java @@ -90,7 +90,11 @@ public void feed(IBarDataSet data) { float value = vals[k]; - if (value >= 0f) { + if (value == 0.0f && (posY == 0.0f || negY == 0.0f)) { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value; + yStart = y; + } else if (value >= 0.0f) { y = posY; yStart = posY + value; posY = yStart; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index ad12feae45..d0e644d806 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -292,7 +292,10 @@ public void drawValues(Canvas c) { float value = vals[idx]; float y; - if (value >= 0f) { + if (value == 0.0f && (posY == 0.0f || negY == 0.0f)) { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value; + } else if (value >= 0.0f) { posY += value; y = posY; } else { @@ -307,8 +310,12 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { + final float val = vals[k / 2]; + final boolean drawBelow = + (val == 0.0f && negY == 0.0f && posY > 0.0f) || + val < 0.0f; float y = transformed[k + 1] - + (vals[k / 2] >= 0 ? posOffset : negOffset); + + (drawBelow ? negOffset : posOffset); if (!mViewPortHandler.isInBoundsRight(x)) break; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 00cce881f2..0a910f6f89 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -264,7 +264,10 @@ public void drawValues(Canvas c) { float value = vals[idx]; float y; - if (value >= 0f) { + if (value == 0.0f && (posY == 0.0f || negY == 0.0f)) { + // Take care of the situation of a 0.0 value, which overlaps a non-zero bar + y = value; + } else if (value >= 0.0f) { posY += value; y = posY; } else { @@ -279,7 +282,7 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { - float val = vals[k / 2]; + final float val = vals[k / 2]; String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value @@ -292,8 +295,12 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } + final boolean drawBelow = + (val == 0.0f && negY == 0.0f && posY > 0.0f) || + val < 0.0f; + float x = transformed[k] - + (val >= 0 ? posOffset : negOffset); + + (drawBelow ? negOffset : posOffset); float y = (buffer.buffer[bufferIndex + 1] + buffer.buffer[bufferIndex + 3]) / 2f; if (!mViewPortHandler.isInBoundsTop(y)) From 6966b8117e6b4706e5e068eba96dce21cceafeed Mon Sep 17 00:00:00 2001 From: Patrick Ivarsson Date: Fri, 23 Dec 2016 12:38:42 +0100 Subject: [PATCH 1230/1390] Fix for default text size being set in PX instead of DP The default text size in ComponentBase was defined as 10 pixels instead of 10dp, which causes tiny text and does not reflect the javadoc and the general behavior of setTextSize(...) --- .../com/github/mikephil/charting/components/ComponentBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java index 7d31d0350a..d3a1d4d82a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/ComponentBase.java @@ -36,7 +36,7 @@ public abstract class ComponentBase { /** * the text size of the labels */ - protected float mTextSize = 10f; + protected float mTextSize = Utils.convertDpToPixel(10f); /** * the text color to use for the labels From 30a331781f72f4217153b5d88b21bd191c58db8f Mon Sep 17 00:00:00 2001 From: Patrick Ivarsson Date: Fri, 23 Dec 2016 14:15:53 +0100 Subject: [PATCH 1231/1390] Fix circles inherit alpha (Fixes #2620) ISSUE: When using multiple LineDataSets like the follows: int solidColor = 0xFFFF00FF; dataSet.setColor(solidColor); dataSet.setCircleColor(solidColor); int semiTransparentColor = 0x8A000000; fadedSet.setColor(semiTransparentColor); LineData data = new LineData(dataSet, fadedSet); the circles in 'dataSet' will rendered with the alpha from fadedSet (0x8A). The reason for this is that mRenderPaint is not reset properly before drawing the circles. The first time drawCircles is called the imageCache.fill(...) method is used where the color is set by mRenderPaint.setColor(set.getCircleColor(i)), restoring the alpha to 0xFF. The second time homever, imageCache.fill(...) is not called which means that mRenderPaint will use it's old color/alpha, which in this case is from fadedSet. TEST INFO: To trigger the issue, add the following to LineChartActivity1: final ArrayList fadedEntries = new ArrayList<>(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range) + 3; fadedEntries.add(new Entry(i, val)); } final LineDataSet fadedDateSet = new LineDataSet(fadedEntries, "Faded"); fadedDateSet.setColor(0x42000000); dataSets.add(fadedDateSet); // add the datasets and launch the first item in the example app. SOLUTION: This commit replaces mRenderPaint with null when drawing the circle bitmap. If circleColor has been defined with a semi-transparent color, it will be drawn that way in the cached bitmap, hence the the bitmap itself does not need to be drawn with an alpha. --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1f46e5b7ef..2c32943d4c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -652,7 +652,7 @@ protected void drawCircles(Canvas c) { Bitmap circleBitmap = imageCache.getBitmap(j); if (circleBitmap != null) { - c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, mRenderPaint); + c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, null); } } } From ed618084f9c8a568ec10a0a85e04a5f0af0158ff Mon Sep 17 00:00:00 2001 From: travisfw Date: Mon, 13 Feb 2017 14:02:55 -0800 Subject: [PATCH 1232/1390] fix tests for java executable location. bug #2805 https://github.com/PhilJay/MPAndroidChart/issues/2805 --- gradlew | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradlew b/gradlew index 86ee20772b..f6890acbdf 100755 --- a/gradlew +++ b/gradlew @@ -64,13 +64,13 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then - if [ -xPx "$JAVA_HOME/jre/sh/java" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi - if [ ! -xPx "$JAVACMD" ] ; then + if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the From 749827798b90c4f060caa4aceaa1fcfc7344bdc4 Mon Sep 17 00:00:00 2001 From: travisfw Date: Tue, 14 Feb 2017 11:07:10 -0800 Subject: [PATCH 1233/1390] fix https://github.com/PhilJay/MPAndroidChart/issues/2813 --- MPChartLib/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 6f1e5d3a00..429fc1df45 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -55,6 +55,7 @@ task sourcesJar(type: Jar) { } task javadoc(type: Javadoc) { + options.charSet = 'UTF-8' failOnError false source = android.sourceSets.main.java.sourceFiles classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) From a02e108f467cda0e74b40bc055251486fe075f45 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 20 Feb 2017 13:33:39 +0200 Subject: [PATCH 1234/1390] Implemented icon support --- .../mikephil/charting/data/BarEntry.java | 87 ++++++++++++--- .../mikephil/charting/data/BaseDataSet.java | 35 ++++++ .../mikephil/charting/data/BaseEntry.java | 34 ++++++ .../mikephil/charting/data/BubbleEntry.java | 28 +++++ .../mikephil/charting/data/CandleEntry.java | 64 +++++++++-- .../github/mikephil/charting/data/Entry.java | 26 +++++ .../mikephil/charting/data/PieEntry.java | 21 +++- .../interfaces/datasets/IDataSet.java | 40 ++++++- .../charting/renderer/BarChartRenderer.java | 92 ++++++++++++++-- .../BarLineScatterCandleBubbleRenderer.java | 2 +- .../renderer/BubbleChartRenderer.java | 27 ++++- .../renderer/CandleStickChartRenderer.java | 34 +++++- .../charting/renderer/DataRenderer.java | 2 + .../renderer/HorizontalBarChartRenderer.java | 102 +++++++++++++++--- .../charting/renderer/LineChartRenderer.java | 27 ++++- .../charting/renderer/PieChartRenderer.java | 24 +++++ .../charting/renderer/RadarChartRenderer.java | 43 +++++++- .../renderer/ScatterChartRenderer.java | 33 +++++- .../mikephil/charting/utils/MPPointF.java | 11 ++ .../github/mikephil/charting/utils/Utils.java | 42 +++++--- 20 files changed, 698 insertions(+), 76 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java index 922f151879..365ef51a2d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarEntry.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; import android.annotation.SuppressLint; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.highlight.Range; @@ -33,10 +34,54 @@ public class BarEntry extends Entry { private float mPositiveSum; /** - * Constructor for stacked bar entries. + * Constructor for normal bars (not stacked). + * + * @param x + * @param y + */ + public BarEntry(float x, float y) { + super(x, y); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param x + * @param y + * @param data - Spot for additional data this Entry represents. + */ + public BarEntry(float x, float y, Object data) { + super(x, y, data); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param x + * @param y + * @param icon - icon image + */ + public BarEntry(float x, float y, Drawable icon) { + super(x, y, icon); + } + + /** + * Constructor for normal bars (not stacked). * * @param x - * @param vals - the stack values, use at lest 2 + * @param y + * @param icon - icon image + * @param data - Spot for additional data this Entry represents. + */ + public BarEntry(float x, float y, Drawable icon, Object data) { + super(x, y, icon, data); + } + + /** + * Constructor for stacked bar entries. One data object for whole stack + * + * @param x + * @param vals - the stack values, use at least 2 */ public BarEntry(float x, float[] vals) { super(x, calcSum(vals)); @@ -47,24 +92,29 @@ public BarEntry(float x, float[] vals) { } /** - * Constructor for normal bars (not stacked). + * Constructor for stacked bar entries. One data object for whole stack * * @param x - * @param y + * @param vals - the stack values, use at least 2 + * @param data - Spot for additional data this Entry represents. */ - public BarEntry(float x, float y) { - super(x, y); + public BarEntry(float x, float[] vals, Object data) { + super(x, calcSum(vals), data); + + this.mYVals = vals; + calcPosNegSum(); + calcRanges(); } /** - * Constructor for stacked bar entries. + * Constructor for stacked bar entries. One data object for whole stack * * @param x - * @param vals - the stack values, use at least 2 - * @param label Additional description label. + * @param vals - the stack values, use at least 2 + * @param icon - icon image */ - public BarEntry(float x, float[] vals, String label) { - super(x, calcSum(vals), label); + public BarEntry(float x, float[] vals, Drawable icon) { + super(x, calcSum(vals), icon); this.mYVals = vals; calcPosNegSum(); @@ -72,14 +122,19 @@ public BarEntry(float x, float[] vals, String label) { } /** - * Constructor for normal bars (not stacked). + * Constructor for stacked bar entries. One data object for whole stack * * @param x - * @param y - * @param data Spot for additional data this Entry represents. + * @param vals - the stack values, use at least 2 + * @param icon - icon image + * @param data - Spot for additional data this Entry represents. */ - public BarEntry(float x, float y, Object data) { - super(x, y, data); + public BarEntry(float x, float[] vals, Drawable icon, Object data) { + super(x, calcSum(vals), icon, data); + + this.mYVals = vals; + calcPosNegSum(); + calcRanges(); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 89ed9b4001..3869a00895 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -11,8 +11,11 @@ import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; import java.util.ArrayList; import java.util.List; @@ -68,6 +71,16 @@ public abstract class BaseDataSet implements IDataSet { */ protected boolean mDrawValues = true; + /** + * if true, y-icons are drawn on the chart + */ + protected boolean mDrawIcons = true; + + /** + * the offset for drawing icons (in dp) + */ + protected MPPointF mIconsOffset = new MPPointF(); + /** * the size of the value-text labels */ @@ -371,6 +384,28 @@ public boolean isDrawValuesEnabled() { return mDrawValues; } + @Override + public void setDrawIcons(boolean enabled) { + mDrawIcons = enabled; + } + + @Override + public boolean isDrawIconsEnabled() { + return mDrawIcons; + } + + @Override + public void setIconsOffset(MPPointF offsetDp) { + + mIconsOffset.x = offsetDp.x; + mIconsOffset.y = offsetDp.y; + } + + @Override + public MPPointF getIconsOffset() { + return mIconsOffset; + } + @Override public void setVisible(boolean visible) { mVisible = visible; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java index 099fee86d8..eb1ada84d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseEntry.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.data; +import android.graphics.drawable.Drawable; + /** * Created by Philipp Jahoda on 02/06/16. */ @@ -11,6 +13,9 @@ public abstract class BaseEntry { /** optional spot for additional data this Entry represents */ private Object mData = null; + /** optional icon image */ + private Drawable mIcon = null; + public BaseEntry() { } @@ -24,6 +29,17 @@ public BaseEntry(float y, Object data) { this.mData = data; } + public BaseEntry(float y, Drawable icon) { + this(y); + this.mIcon = icon; + } + + public BaseEntry(float y, Drawable icon, Object data) { + this(y); + this.mIcon = icon; + this.mData = data; + } + /** * Returns the y value of this Entry. * @@ -33,6 +49,24 @@ public float getY() { return y; } + /** + * Sets the icon drawable + * + * @param icon + */ + public void setIcon(Drawable icon) { + this.mIcon = icon; + } + + /** + * Returns the icon of this Entry. + * + * @return + */ + public Drawable getIcon() { + return mIcon; + } + /** * Sets the y-value for the Entry. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java index c6ff908b85..35d8330aaa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleEntry.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import android.annotation.SuppressLint; +import android.graphics.drawable.Drawable; /** * Subclass of Entry that holds a value for one entry in a BubbleChart. Bubble @@ -41,6 +42,33 @@ public BubbleEntry(float x, float y, float size, Object data) { this.mSize = size; } + /** + * Constructor. + * + * @param x The value on the x-axis. + * @param y The value on the y-axis. + * @param size The size of the bubble. + * @param icon Icon image + */ + public BubbleEntry(float x, float y, float size, Drawable icon) { + super(x, y, icon); + this.mSize = size; + } + + /** + * Constructor. + * + * @param x The value on the x-axis. + * @param y The value on the y-axis. + * @param size The size of the bubble. + * @param icon Icon image + * @param data Spot for additional data this Entry represents. + */ + public BubbleEntry(float x, float y, float size, Drawable icon, Object data) { + super(x, y, icon, data); + this.mSize = size; + } + public BubbleEntry copy() { BubbleEntry c = new BubbleEntry(getX(), getY(), mSize, getData()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java index efe87d077a..5a049957a2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleEntry.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import android.annotation.SuppressLint; +import android.graphics.drawable.Drawable; /** * Subclass of Entry that holds all values for one entry in a CandleStickChart. @@ -26,11 +27,11 @@ public class CandleEntry extends Entry { /** * Constructor. * - * @param x The value on the x-axis. - * @param shadowH The (shadow) high value. - * @param shadowL The (shadow) low value. - * @param open The open value. - * @param close The close value. + * @param x The value on the x-axis + * @param shadowH The (shadow) high value + * @param shadowL The (shadow) low value + * @param open The open value + * @param close The close value */ public CandleEntry(float x, float shadowH, float shadowL, float open, float close) { super(x, (shadowH + shadowL) / 2f); @@ -43,16 +44,16 @@ public CandleEntry(float x, float shadowH, float shadowL, float open, float clos /** * Constructor. - * - * @param x The value on the x-axis. - * @param shadowH The (shadow) high value. - * @param shadowL The (shadow) low value. + * + * @param x The value on the x-axis + * @param shadowH The (shadow) high value + * @param shadowL The (shadow) low value * @param open * @param close - * @param data Spot for additional data this Entry represents. + * @param data Spot for additional data this Entry represents */ public CandleEntry(float x, float shadowH, float shadowL, float open, float close, - Object data) { + Object data) { super(x, (shadowH + shadowL) / 2f, data); this.mShadowHigh = shadowH; @@ -61,6 +62,47 @@ public CandleEntry(float x, float shadowH, float shadowL, float open, float clos this.mClose = close; } + /** + * Constructor. + * + * @param x The value on the x-axis + * @param shadowH The (shadow) high value + * @param shadowL The (shadow) low value + * @param open + * @param close + * @param icon Icon image + */ + public CandleEntry(float x, float shadowH, float shadowL, float open, float close, + Drawable icon) { + super(x, (shadowH + shadowL) / 2f, icon); + + this.mShadowHigh = shadowH; + this.mShadowLow = shadowL; + this.mOpen = open; + this.mClose = close; + } + + /** + * Constructor. + * + * @param x The value on the x-axis + * @param shadowH The (shadow) high value + * @param shadowL The (shadow) low value + * @param open + * @param close + * @param icon Icon image + * @param data Spot for additional data this Entry represents + */ + public CandleEntry(float x, float shadowH, float shadowL, float open, float close, + Drawable icon, Object data) { + super(x, (shadowH + shadowL) / 2f, icon, data); + + this.mShadowHigh = shadowH; + this.mShadowLow = shadowL; + this.mOpen = open; + this.mClose = close; + } + /** * Returns the overall range (difference) between shadow-high and * shadow-low. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index f7a7ca32f0..b7a887990d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.ParcelFormatException; import android.os.Parcelable; @@ -45,6 +46,31 @@ public Entry(float x, float y, Object data) { this.x = x; } + /** + * A Entry represents one single entry in the chart. + * + * @param x the x value + * @param y the y value (the actual value of the entry) + * @param icon icon image + */ + public Entry(float x, float y, Drawable icon) { + super(y, icon); + this.x = x; + } + + /** + * A Entry represents one single entry in the chart. + * + * @param x the x value + * @param y the y value (the actual value of the entry) + * @param icon icon image + * @param data Spot for additional data this Entry represents. + */ + public Entry(float x, float y, Drawable icon, Object data) { + super(y, icon, data); + this.x = x; + } + /** * Returns the x-value of this Entry object. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java index f5c40804c1..65741ef1da 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieEntry.java @@ -1,10 +1,11 @@ package com.github.mikephil.charting.data; import android.annotation.SuppressLint; +import android.graphics.drawable.Drawable; import android.util.Log; /** - * Created by Philipp Jahoda on 31/05/16. + * @author Philipp Jahoda */ @SuppressLint("ParcelCreator") public class PieEntry extends Entry { @@ -19,6 +20,14 @@ public PieEntry(float value, Object data) { super(0f, value, data); } + public PieEntry(float value, Drawable icon) { + super(0f, value, icon); + } + + public PieEntry(float value, Drawable icon, Object data) { + super(0f, value, icon, data); + } + public PieEntry(float value, String label) { super(0f, value); this.label = label; @@ -29,6 +38,16 @@ public PieEntry(float value, String label, Object data) { this.label = label; } + public PieEntry(float value, String label, Drawable icon) { + super(0f, value, icon); + this.label = label; + } + + public PieEntry(float value, String label, Drawable icon, Object data) { + super(0f, value, icon, data); + this.label = label; + } + /** * This is the same as getY(). Returns the value of the PieEntry. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 5f922ba569..fd8af7064b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; +import android.graphics.PointF; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; @@ -8,6 +9,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.utils.MPPointF; import java.util.List; @@ -419,10 +421,10 @@ public interface IDataSet { DashPathEffect getFormLineDashEffect(); /** - * set this to true to draw y-values on the chart NOTE (for bar and - * linechart): if "maxvisiblecount" is reached, no values will be drawn even - * if this is enabled + * set this to true to draw y-values on the chart. * + * NOTE (for bar and line charts): if `maxVisibleCount` is reached, no values will be drawn even + * if this is enabled * @param enabled */ void setDrawValues(boolean enabled); @@ -434,6 +436,38 @@ public interface IDataSet { */ boolean isDrawValuesEnabled(); + /** + * Set this to true to draw y-icons on the chart. + * + * NOTE (for bar and line charts): if `maxVisibleCount` is reached, no icons will be drawn even + * if this is enabled + * + * @param enabled + */ + void setDrawIcons(boolean enabled); + + /** + * Returns true if y-icon drawing is enabled, false if not + * + * @return + */ + boolean isDrawIconsEnabled(); + + /** + * Offset of icons drawn on the chart. + * + * For all charts except Pie and Radar it will be ordinary (x offset,y offset). + * + * For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint. + * @param offset + */ + void setIconsOffset(MPPointF offset); + + /** + * Get the offset for drawing icons. + */ + MPPointF getIconsOffset(); + /** * Set the visibility of this DataSet. If not visible, the DataSet will not * be drawn to the chart upon refreshing it. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index d0e644d806..f17761234e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.BarBuffer; @@ -14,6 +15,7 @@ import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -224,6 +226,10 @@ public void drawValues(Canvas c) { final float phaseY = mAnimator.getPhaseY(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -241,9 +247,34 @@ public void drawValues(Canvas c) { BarEntry entry = dataSet.getEntryForIndex(j / 4); float val = entry.getY(); - drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, - val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), - dataSet.getValueTextColor(j / 4)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, + val >= 0 ? + (buffer.buffer[j + 1] + posOffset) : + (buffer.buffer[j + 3] + negOffset), + dataSet.getValueTextColor(j / 4)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + float px = x; + float py = val >= 0 ? + (buffer.buffer[j + 1] + posOffset) : + (buffer.buffer[j + 3] + negOffset); + + px += iconsOffset.x; + py += iconsOffset.y; + + Utils.drawImage( + c, + icon, + (int)px, + (int)py, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } // if we have stacks @@ -275,9 +306,32 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(x)) continue; - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, - buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), - color); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + buffer.buffer[bufferIndex + 1] + + (entry.getY() >= 0 ? posOffset : negOffset), + color); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + float px = x; + float py = buffer.buffer[bufferIndex + 1] + + (entry.getY() >= 0 ? posOffset : negOffset); + + px += iconsOffset.x; + py += iconsOffset.y; + + Utils.drawImage( + c, + icon, + (int)px, + (int)py, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } // draw stack values } else { @@ -324,7 +378,29 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(x)) continue; - drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y, color); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, + dataSet.getValueFormatter(), + vals[k / 2], + entry, + i, + x, + y, + color); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(x + iconsOffset.x), + (int)(y + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } } @@ -332,6 +408,8 @@ public void drawValues(Canvas c) { index++; } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index 7b48244688..06599187d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -29,7 +29,7 @@ public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandle * @return */ protected boolean shouldDrawValues(IDataSet set) { - return set.isVisible() && set.isDrawValuesEnabled(); + return set.isVisible() && (set.isDrawValuesEnabled() || set.isDrawIconsEnabled()); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 680e7810e8..17bba048b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; @@ -11,6 +12,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -145,6 +147,10 @@ public void drawValues(Canvas c) { final float alpha = phaseX == 1 ? phaseY : phaseX; + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < positions.length; j += 2) { int valueTextColor = dataSet.getValueTextColor(j / 2 + mXBounds.min); @@ -162,9 +168,26 @@ public void drawValues(Canvas c) { BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); - drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, - y + (0.5f * lineHeight), valueTextColor); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, + y + (0.5f * lineHeight), valueTextColor); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(x + iconsOffset.x), + (int)(y + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index efa4c5d012..e4c06fe46c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -3,6 +3,7 @@ import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; @@ -12,6 +13,7 @@ import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointD; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -277,6 +279,10 @@ public void drawValues(Canvas c) { float yOffset = Utils.convertDpToPixel(5f); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < positions.length; j += 2) { float x = positions[j]; @@ -290,9 +296,33 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); - drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet - .getValueTextColor(j / 2)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, + dataSet.getValueFormatter(), + entry.getHigh(), + entry, + i, + x, + y - yOffset, + dataSet + .getValueTextColor(j / 2)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(x + iconsOffset.x), + (int)(y + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index 905c6449cb..e8e5446f4d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; @@ -13,6 +14,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 0a910f6f89..a1e1650865 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -4,6 +4,7 @@ import android.graphics.Canvas; import android.graphics.Paint.Align; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.BarBuffer; @@ -15,6 +16,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -172,6 +174,10 @@ public void drawValues(Canvas c) { final float phaseY = mAnimator.getPhaseY(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -188,9 +194,9 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1])) continue; - BarEntry e = dataSet.getEntryForIndex(j / 4); - float val = e.getY(); - String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); + BarEntry entry = dataSet.getEntryForIndex(j / 4); + float val = entry.getY(); + String formattedValue = formatter.getFormattedValue(val, entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -202,8 +208,32 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, formattedValue, buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset), - y + halfTextHeight, dataSet.getValueTextColor(j / 2)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, + formattedValue, + buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset), + y + halfTextHeight, + dataSet.getValueTextColor(j / 2)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + float px = buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset); + float py = y; + + px += iconsOffset.x; + py += iconsOffset.y; + + Utils.drawImage( + c, + icon, + (int)px, + (int)py, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } // if each value of a potential stack should be drawn @@ -216,10 +246,10 @@ public void drawValues(Canvas c) { while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) { - BarEntry e = dataSet.getEntryForIndex(index); + BarEntry entry = dataSet.getEntryForIndex(index); int color = dataSet.getValueTextColor(index); - float[] vals = e.getYVals(); + float[] vals = entry.getYVals(); // we still draw stacked bars, but there is one // non-stacked @@ -235,8 +265,9 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1])) continue; - float val = e.getY(); - String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); + float val = entry.getY(); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -248,16 +279,39 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, formattedValue, buffer.buffer[bufferIndex + 2] - + (e.getY() >= 0 ? posOffset : negOffset), - buffer.buffer[bufferIndex + 1] + halfTextHeight, color); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, formattedValue, + buffer.buffer[bufferIndex + 2] + + (entry.getY() >= 0 ? posOffset : negOffset), + buffer.buffer[bufferIndex + 1] + halfTextHeight, color); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + float px = buffer.buffer[bufferIndex + 2] + + (entry.getY() >= 0 ? posOffset : negOffset); + float py = buffer.buffer[bufferIndex + 1]; + + px += iconsOffset.x; + py += iconsOffset.y; + + Utils.drawImage( + c, + icon, + (int)px, + (int)py, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } else { float[] transformed = new float[vals.length * 2]; float posY = 0f; - float negY = -e.getNegativeSum(); + float negY = -entry.getNegativeSum(); for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { @@ -283,7 +337,8 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { final float val = vals[k / 2]; - String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -312,7 +367,22 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(y)) continue; - drawValue(c, formattedValue, x, y + halfTextHeight, color); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, formattedValue, x, y + halfTextHeight, color); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(x + iconsOffset.x), + (int)(y + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } } @@ -320,6 +390,8 @@ public void drawValues(Canvas c) { index++; } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1f46e5b7ef..67633ac19a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -18,7 +18,9 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointD; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; +import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; @@ -545,6 +547,10 @@ public void drawValues(Canvas c) { float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator .getPhaseY(), mXBounds.min, mXBounds.max); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < positions.length; j += 2) { float x = positions[j]; @@ -558,9 +564,26 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, - y - valOffset, dataSet.getValueTextColor(j / 2)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + y - valOffset, dataSet.getValueTextColor(j / 2)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(x + iconsOffset.x), + (int)(y + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 84fda6e5f2..be72a0834f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -9,6 +9,7 @@ import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; import android.text.StaticLayout; @@ -444,6 +445,10 @@ public void drawValues(Canvas c) { final float sliceSpace = getSliceSpace(dataSet); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < entryCount; j++) { PieEntry entry = dataSet.getEntryForIndex(j); @@ -588,8 +593,27 @@ public void drawValues(Canvas c) { } } + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + float x = (labelRadius + iconsOffset.y) * sliceXBase + center.x; + float y = (labelRadius + iconsOffset.y) * sliceYBase + center.y; + y += iconsOffset.x; + + Utils.drawImage( + c, + icon, + (int)x, + (int)y, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } + xIndex++; } + + MPPointF.recycleInstance(iconsOffset); } MPPointF.recycleInstance(center); c.restore(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 6c05b08dca..dbf0e8f807 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -160,6 +160,7 @@ public void drawValues(Canvas c) { MPPointF center = mChart.getCenterOffsets(); MPPointF pOut = MPPointF.getInstance(0,0); + MPPointF pIcon = MPPointF.getInstance(0,0); float yoffset = Utils.convertDpToPixel(5f); @@ -173,6 +174,10 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < dataSet.getEntryCount(); j++) { RadarEntry entry = dataSet.getEntryForIndex(j); @@ -183,13 +188,47 @@ public void drawValues(Canvas c) { sliceangle * j * phaseX + mChart.getRotationAngle(), pOut); - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, pOut.x, pOut.y - yoffset, dataSet.getValueTextColor - (j)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + pOut.x, + pOut.y - yoffset, + dataSet.getValueTextColor + (j)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.getPosition( + center, + (entry.getY()) * factor * phaseY + iconsOffset.y, + sliceangle * j * phaseX + mChart.getRotationAngle(), + pIcon); + + //noinspection SuspiciousNameCombination + pIcon.y += iconsOffset.x; + + Utils.drawImage( + c, + icon, + (int)pIcon.x, + (int)pIcon.y, + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } + + MPPointF.recycleInstance(iconsOffset); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); + MPPointF.recycleInstance(pIcon); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 9c4fdac24e..36a38a53c5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; @@ -12,6 +13,7 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.renderer.scatter.IShapeRenderer; import com.github.mikephil.charting.utils.MPPointD; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -113,6 +115,10 @@ public void drawValues(Canvas c) { float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); + iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); + iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); + for (int j = 0; j < positions.length; j += 2) { if (!mViewPortHandler.isInBoundsRight(positions[j])) @@ -125,9 +131,32 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, positions[j], - positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min)); + if (dataSet.isDrawValuesEnabled()) { + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + positions[j], + positions[j + 1] - shapeSize, + dataSet.getValueTextColor(j / 2 + mXBounds.min)); + } + + if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { + + Drawable icon = entry.getIcon(); + + Utils.drawImage( + c, + icon, + (int)(positions[j] + iconsOffset.x), + (int)(positions[j + 1] + iconsOffset.y), + icon.getIntrinsicWidth(), + icon.getIntrinsicHeight()); + } } + + MPPointF.recycleInstance(iconsOffset); } } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java index 36dd6d33ea..fb5a00f508 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/MPPointF.java @@ -35,6 +35,17 @@ public static MPPointF getInstance(float x, float y) { return result; } + public static MPPointF getInstance() { + return pool.get(); + } + + public static MPPointF getInstance(MPPointF copy) { + MPPointF result = pool.get(); + result.x = copy.x; + result.y = copy.y; + return result; + } + public static void recycleInstance(MPPointF instance){ pool.recycle(instance); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index b44f9d9ea7..c302673919 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -7,12 +7,15 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; +import android.util.SizeF; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -107,14 +110,9 @@ public static float convertDpToPixel(float dp) { " calling Utils.convertDpToPixel(...). Otherwise conversion does not " + "take place."); return dp; - // throw new IllegalStateException( - // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before - // calling Utils.convertDpToPixel(...)."); } - DisplayMetrics metrics = mMetrics; - float px = dp * (metrics.densityDpi / 160f); - return px; + return dp * mMetrics.density; } /** @@ -133,14 +131,9 @@ public static float convertPixelsToDp(float px) { " calling Utils.convertPixelsToDp(...). Otherwise conversion does not" + " take place."); return px; - // throw new IllegalStateException( - // "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before - // calling Utils.convertPixelsToDp(...)."); } - DisplayMetrics metrics = mMetrics; - float dp = px / (metrics.densityDpi / 160f); - return dp; + return px / mMetrics.density; } /** @@ -532,6 +525,31 @@ public static float getNormalizedAngle(float angle) { return angle % 360.f; } + private static Rect mDrawableBoundsCache = new Rect(); + + public static void drawImage(Canvas canvas, + Drawable drawable, + int x, int y, + int width, int height) { + + MPPointF drawOffset = MPPointF.getInstance(); + drawOffset.x = x - (width / 2); + drawOffset.y = y - (height / 2); + + drawable.copyBounds(mDrawableBoundsCache); + drawable.setBounds( + mDrawableBoundsCache.left, + mDrawableBoundsCache.top, + mDrawableBoundsCache.left + width, + mDrawableBoundsCache.top + width); + + int saveId = canvas.save(); + // translate to the correct position and draw + canvas.translate(drawOffset.x, drawOffset.y); + drawable.draw(canvas); + canvas.restoreToCount(saveId); + } + private static Rect mDrawTextRectBuffer = new Rect(); private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics(); From 144af7b295076d85f6deeb94e0e77796ec7fa5f1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 20 Feb 2017 13:33:53 +0200 Subject: [PATCH 1235/1390] Added examples for icon entries --- MPChartExample/res/drawable-hdpi/star.png | Bin 0 -> 1221 bytes MPChartExample/res/menu/bar.xml | 4 +++ MPChartExample/res/menu/bubble.xml | 4 +++ MPChartExample/res/menu/line.xml | 4 +++ MPChartExample/res/menu/pie.xml | 4 +++ MPChartExample/res/menu/radar.xml | 4 +++ MPChartExample/res/menu/scatter.xml | 4 +++ .../mpchartexample/BarChartActivity.java | 17 +++++++++++- .../mpchartexample/BubbleChartActivity.java | 17 ++++++++++-- .../CandleStickChartActivity.java | 26 ++++++++++++++++-- .../HorizontalBarChartActivity.java | 18 +++++++++++- .../mpchartexample/LineChartActivity1.java | 17 +++++++++++- .../mpchartexample/PieChartActivity.java | 16 ++++++++++- .../mpchartexample/StackedBarActivity.java | 19 ++++++++++++- .../StackedBarActivityNegative.java | 15 ++++++++++ 15 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 MPChartExample/res/drawable-hdpi/star.png diff --git a/MPChartExample/res/drawable-hdpi/star.png b/MPChartExample/res/drawable-hdpi/star.png new file mode 100644 index 0000000000000000000000000000000000000000..c7811ef2b89b0097f0c64f26718cc07e5a5b64b8 GIT binary patch literal 1221 zcmV;$1UmbPP)U=4^(ZyKr5oQs+34wu%k3i zNrRP02!%k}R7xn6hXLd3$C)m$1Abpf`mL-pbLRVIe9oD<1dF&C47!xayF?TakzQhM zS4ugv<`@CXL=;uPlm=Yy8ykyRiA&WSrh~z50)|-R0+<~Z_3i{Nx z4%V9S_?HZP0zk7!T!^%YdaaVv3{NeCoRRJ@> z;G0793j^NgM7|G^)r`oQ{_*j-vI4T1|7wYx2;LKo0D!eS>y||bk^gWdIQL^N6spUX z-BRX_-7d5STF@G3fxF9PO#qRPfFEYgovSGlunT-)`9CMXd+I=^ug?ci)eDtF4>=s4 z=Lwh&2D`JT-4YtQ+^F#$+{jv=1MW^|g&jrsbS4z)d@6u|Ay~a?M0wfgP-?9LY$P%S z05p64ygQ}qPpm#N?pK{?d;jH6YOp~>%_NeWDI~X&5G6&v%v_5^;;fB`0)-jC0S&P30N){L?eO+cHH@{;!IHze|*0P4|J3)aTZEsiHRs$DG&o_ z_7L_>shqtl-rBvKZ zCU0#s0Ad~+n4H|P0RS?YVQAV%0Boh4YYQrnPAV+je2k^v zo&Zef^f%*`lg-d{KD4K{EV)uDB{th-Alrh!zISi^ z%&!;vZ+jS?HYfg$uEG`v8Vq~U^~#7~GnIm>0bV@e!`g!woSVg6P?U7O}^7n + + diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/res/menu/bubble.xml index a25afd9861..b7950291e9 100644 --- a/MPChartExample/res/menu/bubble.xml +++ b/MPChartExample/res/menu/bubble.xml @@ -5,6 +5,10 @@ android:id="@+id/actionToggleValues" android:title="Toggle Values"> + + diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index aea6845249..f9f5be9615 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -5,6 +5,10 @@ android:id="@+id/actionToggleValues" android:title="Toggle Values"> + + diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/res/menu/pie.xml index fd315839a5..0e5323a590 100644 --- a/MPChartExample/res/menu/pie.xml +++ b/MPChartExample/res/menu/pie.xml @@ -5,6 +5,10 @@ android:id="@+id/actionToggleValues" android:title="Toggle Y-Values"> + + diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/res/menu/radar.xml index 3565065baa..14690f446c 100644 --- a/MPChartExample/res/menu/radar.xml +++ b/MPChartExample/res/menu/radar.xml @@ -5,6 +5,10 @@ android:id="@+id/actionToggleValues" android:title="Toggle Values"> + + diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/res/menu/scatter.xml index a25afd9861..b7950291e9 100644 --- a/MPChartExample/res/menu/scatter.xml +++ b/MPChartExample/res/menu/scatter.xml @@ -5,6 +5,10 @@ android:id="@+id/actionToggleValues" android:title="Toggle Values"> + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 427c46756a..5772359773 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -153,6 +153,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawIcons(!set.isDrawIconsEnabled()); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -236,7 +243,12 @@ private void setData(int count, float range) { for (int i = (int) start; i < start + count + 1; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(i, val)); + + if (Math.random() * 100 < 25) { + yVals1.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); + } else { + yVals1.add(new BarEntry(i, val)); + } } BarDataSet set1; @@ -249,6 +261,9 @@ private void setData(int count, float range) { mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "The year 2017"); + + set1.setDrawIcons(false); + set1.setColors(ColorTemplate.MATERIAL_COLORS); ArrayList dataSets = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index db72f29495..0ecc1e9c93 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -25,6 +25,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -108,6 +109,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawIcons(!set.isDrawIconsEnabled()); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -167,14 +175,14 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float val = (float) (Math.random() * range); float size = (float) (Math.random() * range); - yVals1.add(new BubbleEntry(i, val, size)); + yVals1.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); } for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range); float size = (float) (Math.random() * range); - yVals2.add(new BubbleEntry(i, val, size)); + yVals2.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); } for (int i = 0; i < count; i++) { @@ -186,11 +194,16 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { // create a dataset and give it a type BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1"); + set1.setDrawIcons(false); set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); set1.setDrawValues(true); + BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2"); + set2.setDrawIcons(false); + set2.setIconsOffset(new MPPointF(0, 15)); set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); set2.setDrawValues(true); + BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3"); set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); set3.setDrawValues(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 3921215be6..bd8dde108f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -21,6 +21,7 @@ import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -92,6 +93,20 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleIcons: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawIcons(!set.isDrawIconsEnabled()); + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -171,11 +186,18 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { boolean even = i % 2 == 0; - yVals1.add(new CandleEntry(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close)); + yVals1.add(new CandleEntry( + i, val + high, + val - low, + even ? val + open : val - open, + even ? val - close : val + close, + getResources().getDrawable(R.drawable.star) + )); } CandleDataSet set1 = new CandleDataSet(yVals1, "Data Set"); + + set1.setDrawIcons(false); set1.setAxisDependency(AxisDependency.LEFT); // set1.setColor(Color.rgb(80, 80, 80)); set1.setShadowColor(Color.DKGRAY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index f5ea95098b..d68b75cc15 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -138,6 +138,19 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + IBarDataSet set = (BarDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -223,7 +236,8 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range); - yVals1.add(new BarEntry(i * spaceForBar, val)); + yVals1.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); } BarDataSet set1; @@ -237,6 +251,8 @@ private void setData(int count, float range) { } else { set1 = new BarDataSet(yVals1, "DataSet 1"); + set1.setDrawIcons(false); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f6747bbf6f..b18309a26a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -190,6 +190,19 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -342,7 +355,7 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range) + 3; - values.add(new Entry(i, val)); + values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); } LineDataSet set1; @@ -357,6 +370,8 @@ private void setData(int count, float range) { // create a dataset and give it a type set1 = new LineDataSet(values, "DataSet 1"); + set1.setDrawIcons(false); + // set the line to be drawn like this "- - - - - -" set1.enableDashedLine(10f, 5f, 0f); set1.enableDashedHighlightLine(10f, 5f, 0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 4493da1f97..085580a923 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -29,6 +29,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -127,6 +128,13 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + for (IDataSet set : mChart.getData().getDataSets()) + set.setDrawIcons(!set.isDrawIconsEnabled()); + + mChart.invalidate(); + break; + } case R.id.actionToggleHole: { if (mChart.isDrawHoleEnabled()) mChart.setDrawHoleEnabled(false); @@ -197,11 +205,17 @@ private void setData(int count, float range) { // NOTE: The order of the entries when being added to the entries array determines their position around the center of // the chart. for (int i = 0; i < count ; i++) { - entries.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), mParties[i % mParties.length])); + entries.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), + mParties[i % mParties.length], + getResources().getDrawable(R.drawable.star))); } PieDataSet dataSet = new PieDataSet(entries, "Election Results"); + + dataSet.setDrawIcons(false); + dataSet.setSliceSpace(3f); + dataSet.setIconsOffset(new MPPointF(0, 40)); dataSet.setSelectionShift(5f); // add a lot of colors diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 31ad84e5ac..70afd7c4c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -122,6 +122,19 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + BarDataSet set = (BarDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); @@ -188,7 +201,10 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { float val2 = (float) (Math.random() * mult) + mult / 3; float val3 = (float) (Math.random() * mult) + mult / 3; - yVals1.add(new BarEntry(i, new float[]{val1, val2, val3})); + yVals1.add(new BarEntry( + i, + new float[]{val1, val2, val3}, + getResources().getDrawable(R.drawable.star))); } BarDataSet set1; @@ -201,6 +217,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mChart.notifyDataSetChanged(); } else { set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); + set1.setDrawIcons(false); set1.setColors(getColors()); set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 01d4f2f89b..d5e0f8c885 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -103,6 +103,7 @@ public String getFormattedValue(float value, AxisBase axis) { yValues.add(new BarEntry(25, new float[]{ -15, 15 })); yValues.add(new BarEntry(35, new float[]{ -17, 17 })); yValues.add(new BarEntry(45, new float[]{ -19, 20 })); + yValues.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); yValues.add(new BarEntry(55, new float[]{ -19, 19 })); yValues.add(new BarEntry(65, new float[]{ -16, 16 })); yValues.add(new BarEntry(75, new float[]{ -13, 14 })); @@ -111,6 +112,7 @@ public String getFormattedValue(float value, AxisBase axis) { yValues.add(new BarEntry(105, new float[]{ -1, 2 })); BarDataSet set = new BarDataSet(yValues, "Age Distribution"); + set.setDrawIcons(false); set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); @@ -150,6 +152,19 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.actionToggleIcons: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + BarDataSet set = (BarDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + mChart.invalidate(); + break; + } case R.id.actionToggleHighlight: { if(mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); From 94957fad3369a6c495ceea532035b6e1143e55a8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 20 Feb 2017 13:55:16 +0200 Subject: [PATCH 1236/1390] Improved feb29 formula --- .../custom/DayAxisValueFormatter.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 6edffb9315..86a602eb39 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -73,14 +73,14 @@ private int getDaysForMonth(int month, int year) { // month is 0-based if (month == 1) { - int x400 = month % 400; - if (x400 < 0) - { - x400 = -x400; - } - boolean is29 = (month % 4) == 0 && x400 != 100 && x400 != 200 && x400 != 300; + boolean is29Feb = false; + + if (year < 1582) + is29Feb = (year < 1 ? year + 1 : year) % 4 == 0; + else if (year > 1582) + is29Feb = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); - return is29 ? 29 : 28; + return is29Feb ? 29 : 28; } if (month == 3 || month == 5 || month == 8 || month == 10) From a5e0a9b86c60d453c64f009e01bd2596ab4ff31c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 21 Feb 2017 14:24:13 +0200 Subject: [PATCH 1237/1390] Moved auto scale before render of axis lines https://github.com/danielgindi/Charts/pull/2177 --- .../github/mikephil/charting/charts/BarLineChartBase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 745d6019e0..e9b993139f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -201,14 +201,14 @@ protected void onDraw(Canvas canvas) { if (mXAxis.isEnabled()) mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); - mXAxisRenderer.renderAxisLine(canvas); - mAxisRendererLeft.renderAxisLine(canvas); - mAxisRendererRight.renderAxisLine(canvas); - if (mAutoScaleMinMaxEnabled) { autoScale(); } + mXAxisRenderer.renderAxisLine(canvas); + mAxisRendererLeft.renderAxisLine(canvas); + mAxisRendererRight.renderAxisLine(canvas); + mXAxisRenderer.renderGridLines(canvas); mAxisRendererLeft.renderGridLines(canvas); mAxisRendererRight.renderGridLines(canvas); From 0c919ab02d5919ac3ac76c9f0fb0642a19153f20 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Feb 2017 17:29:19 +0200 Subject: [PATCH 1238/1390] Consider isEnabled in more axis rendering cases --- .../charting/charts/BarLineChartBase.java | 33 +++++++++++-------- .../mikephil/charting/charts/RadarChart.java | 6 +++- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index e9b993139f..0dccacc02d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -194,17 +194,19 @@ protected void onDraw(Canvas canvas) { // execute all drawing commands drawGridBackground(canvas); + if (mAutoScaleMinMaxEnabled) { + autoScale(); + } + if (mAxisLeft.isEnabled()) mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum, mAxisLeft.isInverted()); + if (mAxisRight.isEnabled()) mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum, mAxisRight.isInverted()); + if (mXAxis.isEnabled()) mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false); - if (mAutoScaleMinMaxEnabled) { - autoScale(); - } - mXAxisRenderer.renderAxisLine(canvas); mAxisRendererLeft.renderAxisLine(canvas); mAxisRendererRight.renderAxisLine(canvas); @@ -213,13 +215,13 @@ protected void onDraw(Canvas canvas) { mAxisRendererLeft.renderGridLines(canvas); mAxisRendererRight.renderGridLines(canvas); - if (mXAxis.isDrawLimitLinesBehindDataEnabled()) + if (mXAxis.isEnabled() && mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); - if (mAxisLeft.isDrawLimitLinesBehindDataEnabled()) + if (mAxisLeft.isEnabled() && mAxisLeft.isDrawLimitLinesBehindDataEnabled()) mAxisRendererLeft.renderLimitLines(canvas); - if (mAxisRight.isDrawLimitLinesBehindDataEnabled()) + if (mAxisRight.isEnabled() && mAxisRight.isDrawLimitLinesBehindDataEnabled()) mAxisRendererRight.renderLimitLines(canvas); // make sure the data cannot be drawn outside the content-rect @@ -237,13 +239,13 @@ protected void onDraw(Canvas canvas) { mRenderer.drawExtras(canvas); - if (!mXAxis.isDrawLimitLinesBehindDataEnabled()) + if (mXAxis.isEnabled() && !mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); - if (!mAxisLeft.isDrawLimitLinesBehindDataEnabled()) + if (mAxisLeft.isEnabled() && !mAxisLeft.isDrawLimitLinesBehindDataEnabled()) mAxisRendererLeft.renderLimitLines(canvas); - if (!mAxisRight.isDrawLimitLinesBehindDataEnabled()) + if (mAxisRight.isEnabled() && !mAxisRight.isDrawLimitLinesBehindDataEnabled()) mAxisRendererRight.renderLimitLines(canvas); mXAxisRenderer.renderAxisLabels(canvas); @@ -347,9 +349,14 @@ protected void autoScale() { mXAxis.calculate(mData.getXMin(), mData.getXMax()); // calculate axis range (min / max) according to provided data - mAxisLeft.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT)); - mAxisRight.calculate(mData.getYMin(AxisDependency.RIGHT), mData.getYMax(AxisDependency - .RIGHT)); + + if (mAxisLeft.isEnabled()) + mAxisLeft.calculate(mData.getYMin(AxisDependency.LEFT), + mData.getYMax(AxisDependency.LEFT)); + + if (mAxisRight.isEnabled()) + mAxisRight.calculate(mData.getYMin(AxisDependency.RIGHT), + mData.getYMax(AxisDependency.RIGHT)); calculateOffsets(); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 1cc1bd6d60..3c9aec0dde 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -137,13 +137,17 @@ protected void onDraw(Canvas canvas) { if (mDrawWeb) mRenderer.drawExtras(canvas); - mYAxisRenderer.renderLimitLines(canvas); + if (mYAxis.isEnabled() && mYAxis.isDrawLimitLinesBehindDataEnabled()) + mYAxisRenderer.renderLimitLines(canvas); mRenderer.drawData(canvas); if (valuesToHighlight()) mRenderer.drawHighlighted(canvas, mIndicesToHighlight); + if (mYAxis.isEnabled() && !mYAxis.isDrawLimitLinesBehindDataEnabled()) + mYAxisRenderer.renderLimitLines(canvas); + mYAxisRenderer.renderAxisLabels(canvas); mRenderer.drawValues(canvas); From 6c54f0b0a91ca87fe39dd63d9095e4f55d6c59ff Mon Sep 17 00:00:00 2001 From: Stephen McBride Date: Tue, 28 Feb 2017 15:58:42 +1300 Subject: [PATCH 1239/1390] Fix for missing setters in getInstance method The zoomAndCenterAnimated method in BarLineChartBase crashes with a NullPointer exception because the yAxis variable is null when onAnimationUpdate is called. The yAxis is null because of missing setters in the getInstance method of AnimatedZoomJob. --- .../java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java index 0157e8fa76..e5e4c417d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedZoomJob.java @@ -33,6 +33,8 @@ public static AnimatedZoomJob getInstance(ViewPortHandler viewPortHandler, View result.view = v; result.xOrigin = xOrigin; result.yOrigin = yOrigin; + result.yAxis = axis; + result.xAxisRange = xAxisRange; result.resetAnimator(); result.animator.setDuration(duration); return result; From 993d273a5249f615004234d794f69971b05dc37f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 14 Mar 2017 10:39:05 +0100 Subject: [PATCH 1240/1390] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8b25078be2..c4bbb33027 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Remember: *It's all about the looks.* +## An app using this library is featured on Product Hunt, [check it out](https://www.producthunt.com/posts/myalfred)! ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) From 2eb12901a9847fc4d559fc1c0d3b8b275a0cad41 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 14 Mar 2017 10:39:45 +0100 Subject: [PATCH 1241/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4bbb33027..3beea7c468 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Remember: *It's all about the looks.* -## An app using this library is featured on Product Hunt, [check it out](https://www.producthunt.com/posts/myalfred)! +## Our app which uses this library is featured on Product Hunt, [check it out](https://www.producthunt.com/posts/myalfred)! ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) From 6df13dd66e49650c08231030a3c76d95587a436c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 15 Mar 2017 15:55:23 +0100 Subject: [PATCH 1242/1390] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 3beea7c468..30759eb357 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ Remember: *It's all about the looks.* -## Our app which uses this library is featured on Product Hunt, [check it out](https://www.producthunt.com/posts/myalfred)! - ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) [**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. From b564704b8272ab8091b3bbc04271a53993bcf07b Mon Sep 17 00:00:00 2001 From: PhilJay Date: Thu, 23 Mar 2017 16:13:21 +0100 Subject: [PATCH 1243/1390] Updating versions --- MPChartExample/AndroidManifest.xml | 6 +++--- MPChartExample/build.gradle | 12 ++++++------ MPChartLib/build.gradle | 8 ++++---- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index b1ac584a2e..87d8b72402 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,12 +1,12 @@ + android:versionCode="55" + android:versionName="3.0.2" > + android:targetSdkVersion="25" /> Date: Thu, 23 Mar 2017 16:15:16 +0100 Subject: [PATCH 1244/1390] Remove line width minimum constraint --- .../com/github/mikephil/charting/data/LineRadarDataSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index deced96ee9..6971144e14 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -101,8 +101,8 @@ public void setFillAlpha(int alpha) { */ public void setLineWidth(float width) { - if (width < 0.2f) - width = 0.2f; + if (width < 0.0f) + width = 0.0f; if (width > 10.0f) width = 10.0f; mLineWidth = Utils.convertDpToPixel(width); From 208bf181addad9b62427f0532dcb1f426ba38c39 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 23 Mar 2017 16:23:45 +0100 Subject: [PATCH 1245/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 30759eb357..406e9a9f2e 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.1/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.2/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -116,7 +116,7 @@ allprojects { ```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.1' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.2' } ``` @@ -135,7 +135,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.0.1 + v3.0.2 ``` @@ -155,7 +155,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.1/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.2/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From f6a398b6b230e09da081f34bd135dd1793bbef09 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Mar 2017 11:36:12 +0100 Subject: [PATCH 1246/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 406e9a9f2e..11d0d7cc32 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) [![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) -[![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) Remember: *It's all about the looks.* From 0af86819eac5afee7d3b0a05b8a14b7d37757f37 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 4 Apr 2017 10:29:38 +0200 Subject: [PATCH 1247/1390] Update README.md --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 11d0d7cc32..2c23d1da4e 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ Donations **PayPal** - - [**Donate 5 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - - [**Donate 10 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - - [**Donate 15 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! + - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! + - [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! + - [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! + - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! + - [**Donate 50 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! + - [**Donate 100 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! If you just want to be nice, you can check out and rate the new [**Telegram Chat Bot**]( https://storebot.me/bot/myalfred_bot) we created for scheduling meetings and other stuff. 😉 From acf985ff0cd3a6ba894bcad107732b49530d8098 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 26 Apr 2017 20:45:12 +0300 Subject: [PATCH 1248/1390] Clear lastHighlighted when `clear` is called --- .../src/main/java/com/github/mikephil/charting/charts/Chart.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 79f699320b..9e80d9234a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -315,6 +315,7 @@ public void clear() { mData = null; mOffsetsCalculated = false; mIndicesToHighlight = null; + mChartTouchListener.setLastHighlighted(null); invalidate(); } From fcb506c2199e10215ca997aa18085382f5fa0114 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 26 Jun 2017 09:16:23 +0200 Subject: [PATCH 1249/1390] Create LICENSE --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 43ae497ecf7427587687945496c6a70e65f01fcb Mon Sep 17 00:00:00 2001 From: Scott Kennedy Date: Mon, 26 Jun 2017 10:50:20 -0700 Subject: [PATCH 1250/1390] Fix some potential NPEs with WeakReference usage Even if the WeakReference field is not null, the contained value may be null. Additionally, you always need a strong reference to the value to ensure it isn't garbage collected while you're using it. --- .../charting/renderer/LineChartRenderer.java | 23 +++++++++++-------- .../charting/renderer/PieChartRenderer.java | 21 ++++++++++------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9921cb1ba6..a0e1777569 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -76,19 +76,21 @@ public void drawData(Canvas c) { int width = (int) mViewPortHandler.getChartWidth(); int height = (int) mViewPortHandler.getChartHeight(); - if (mDrawBitmap == null - || (mDrawBitmap.get().getWidth() != width) - || (mDrawBitmap.get().getHeight() != height)) { + Bitmap drawBitmap = mDrawBitmap == null ? null : mDrawBitmap.get(); - if (width > 0 && height > 0) { + if (drawBitmap == null + || (drawBitmap.getWidth() != width) + || (drawBitmap.getHeight() != height)) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, mBitmapConfig)); - mBitmapCanvas = new Canvas(mDrawBitmap.get()); + if (width > 0 && height > 0) { + drawBitmap = Bitmap.createBitmap(width, height, mBitmapConfig); + mDrawBitmap = new WeakReference<>(drawBitmap); + mBitmapCanvas = new Canvas(drawBitmap); } else return; } - mDrawBitmap.get().eraseColor(Color.TRANSPARENT); + drawBitmap.eraseColor(Color.TRANSPARENT); LineData lineData = mChart.getLineData(); @@ -98,7 +100,7 @@ public void drawData(Canvas c) { drawDataSet(c, set); } - c.drawBitmap(mDrawBitmap.get(), 0, 0, mRenderPaint); + c.drawBitmap(drawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, ILineDataSet dataSet) { @@ -738,7 +740,10 @@ public void releaseBitmap() { mBitmapCanvas = null; } if (mDrawBitmap != null) { - mDrawBitmap.get().recycle(); + Bitmap drawBitmap = mDrawBitmap.get(); + if (drawBitmap != null) { + drawBitmap.recycle(); + } mDrawBitmap.clear(); mDrawBitmap = null; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index be72a0834f..ef401eff44 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -126,19 +126,21 @@ public void drawData(Canvas c) { int width = (int) mViewPortHandler.getChartWidth(); int height = (int) mViewPortHandler.getChartHeight(); - if (mDrawBitmap == null - || (mDrawBitmap.get().getWidth() != width) - || (mDrawBitmap.get().getHeight() != height)) { + Bitmap drawBitmap = mDrawBitmap == null ? null : mDrawBitmap.get(); - if (width > 0 && height > 0) { + if (drawBitmap == null + || (drawBitmap.getWidth() != width) + || (drawBitmap.getHeight() != height)) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444)); - mBitmapCanvas = new Canvas(mDrawBitmap.get()); + if (width > 0 && height > 0) { + drawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mDrawBitmap = new WeakReference<>(drawBitmap); + mBitmapCanvas = new Canvas(drawBitmap); } else return; } - mDrawBitmap.get().eraseColor(Color.TRANSPARENT); + drawBitmap.eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -1010,7 +1012,10 @@ public void releaseBitmap() { mBitmapCanvas = null; } if (mDrawBitmap != null) { - mDrawBitmap.get().recycle(); + Bitmap drawBitmap = mDrawBitmap.get(); + if (drawBitmap != null) { + drawBitmap.recycle(); + } mDrawBitmap.clear(); mDrawBitmap = null; } From ad3c82f634ed3e53aaa6706b2df7632333318921 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 4 Aug 2017 17:05:42 +0200 Subject: [PATCH 1251/1390] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 2c23d1da4e..9125f75e63 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,6 @@ Donations - [**Donate 100 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! -If you just want to be nice, you can check out and rate the new [**Telegram Chat Bot**]( https://storebot.me/bot/myalfred_bot) we created for scheduling meetings and other stuff. 😉 - ## Xamarin From 4f77a154bf876e43b96de5e82c53a6a77a44c89c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Aug 2017 16:31:29 +0200 Subject: [PATCH 1252/1390] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 9125f75e63..0fd4b1cd69 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,9 @@ Donations - [**Donate 50 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - [**Donate 100 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! + +## Got a question? +[Contact me via 21.co](https://21.co/philjay/) ## Xamarin From 98f97f0df1a98596ee0b76cc9c328e539fd6f9bd Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 25 Aug 2017 12:13:45 +0300 Subject: [PATCH 1253/1390] Run view port jobs after applying changes --- .../mikephil/charting/charts/Chart.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 9e80d9234a..ea26f2cfca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -1676,20 +1676,23 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { Log.i(LOG_TAG, "OnSizeChanged()"); if (w > 0 && h > 0 && w < 10000 && h < 10000) { - - mViewPortHandler.setChartDimens(w, h); - if (mLogEnabled) Log.i(LOG_TAG, "Setting chart dimens, width: " + w + ", height: " + h); + mViewPortHandler.setChartDimens(w, h); + } else { + if (mLogEnabled) + Log.w(LOG_TAG, "*Avoiding* setting chart dimens! width: " + w + ", height: " + h); + } - for (Runnable r : mJobs) { - post(r); - } + // This may cause the chart view to mutate properties affecting the view port -- + // lets do this before we try to run any pending jobs on the view port itself + notifyDataSetChanged(); - mJobs.clear(); + for (Runnable r : mJobs) { + post(r); } - notifyDataSetChanged(); + mJobs.clear(); super.onSizeChanged(w, h, oldw, oldh); } From ed770762fb7ba043f4f1eaeae217fccbbaeec93e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 25 Aug 2017 12:15:42 +0300 Subject: [PATCH 1254/1390] Add default x spacing (half width) for scatter chart as well --- .../java/com/github/mikephil/charting/charts/ScatterChart.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index decf1e855a..37e8395b5e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -35,6 +35,9 @@ protected void init() { super.init(); mRenderer = new ScatterChartRenderer(this, mAnimator, mViewPortHandler); + + getXAxis().setSpaceMin(0.5f); + getXAxis().setSpaceMax(0.5f); } @Override From ea93823f6373caf3acfc02e2b42e4c2a73ae05f6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Sep 2017 10:13:12 +0300 Subject: [PATCH 1255/1390] Fix CombinedChartView not drawing markers --- .../charting/charts/CombinedChart.java | 43 ++++++++++++++++++ .../mikephil/charting/data/CombinedData.java | 44 +++++++++++++------ 2 files changed, 73 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java index b1975b973e..cd01f0ef73 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CombinedChart.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.charts; import android.content.Context; +import android.graphics.Canvas; import android.util.AttributeSet; import android.util.Log; @@ -9,11 +10,13 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CombinedDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.renderer.CombinedChartRenderer; /** @@ -226,4 +229,44 @@ public void setDrawOrder(DrawOrder[] order) { return; mDrawOrder = order; } + + /** + * draws all MarkerViews on the highlighted positions + */ + protected void drawMarkers(Canvas canvas) { + + // if there is no marker view or drawing marker is disabled + if (mMarker == null || !isDrawMarkersEnabled() || !valuesToHighlight()) + return; + + for (int i = 0; i < mIndicesToHighlight.length; i++) { + + Highlight highlight = mIndicesToHighlight[i]; + + IDataSet set = mData.getDataSetByHighlight(highlight); + + Entry e = mData.getEntryForHighlight(highlight); + if (e == null) + continue; + + int entryIndex = set.getEntryIndex(e); + + // make sure entry not null + if (entryIndex > set.getEntryCount() * mAnimator.getPhaseX()) + continue; + + float[] pos = getMarkerPosition(highlight); + + // check bounds + if (!mViewPortHandler.isInBounds(pos[0], pos[1])) + continue; + + // callbacks to update the content + mMarker.refreshContent(e, highlight); + + // draw the marker + mMarker.draw(canvas, pos[0], pos[1]); + } + } + } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index c81097da90..39625b30f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -177,28 +177,44 @@ public void notifyDataChanged() { @Override public Entry getEntryForHighlight(Highlight highlight) { - List dataObjects = getAllData(); - - if (highlight.getDataIndex() >= dataObjects.size()) + if (highlight.getDataIndex() >= getAllData().size()) return null; - ChartData data = dataObjects.get(highlight.getDataIndex()); + ChartData data = getDataByIndex(highlight.getDataIndex()); if (highlight.getDataSetIndex() >= data.getDataSetCount()) return null; - else { - // The value of the highlighted entry could be NaN - - // if we are not interested in highlighting a specific value. - List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) - .getEntriesForXValue(highlight.getX()); - for (Entry entry : entries) - if (entry.getY() == highlight.getY() || - Float.isNaN(highlight.getY())) - return entry; + // The value of the highlighted entry could be NaN - + // if we are not interested in highlighting a specific value. + + List entries = data.getDataSetByIndex(highlight.getDataSetIndex()) + .getEntriesForXValue(highlight.getX()); + for (Entry entry : entries) + if (entry.getY() == highlight.getY() || + Float.isNaN(highlight.getY())) + return entry; + + return null; + } + /** + * Get dataset for highlight + * + * @param highlight current highlight + * @return dataset related to highlight + */ + public IBarLineScatterCandleBubbleDataSet getDataSetByHighlight(Highlight highlight) { + if (highlight.getDataIndex() >= getAllData().size()) return null; - } + + BarLineScatterCandleBubbleData data = getDataByIndex(highlight.getDataIndex()); + + if (highlight.getDataSetIndex() >= data.getDataSetCount()) + return null; + + return (IBarLineScatterCandleBubbleDataSet) + data.getDataSets().get(highlight.getDataSetIndex()); } public int getDataIndex(ChartData data) { From 72031d33cacf9d880261e491a5de6f0c1b2de78d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Sep 2017 11:00:45 +0300 Subject: [PATCH 1256/1390] Allow locking drag on either axes --- .../charting/charts/BarLineChartBase.java | 44 ++++++++++++- .../listener/BarLineChartTouchListener.java | 64 ++++++++++++------- 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 0dccacc02d..bf4c42e241 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -78,7 +78,8 @@ public abstract class BarLineChartBase= 2) { @@ -161,12 +162,17 @@ public boolean onTouch(View v, MotionEvent event) { midPoint(mTouchPointCenter, event); } break; + case MotionEvent.ACTION_MOVE: if (mTouchMode == DRAG) { mChart.disableScroll(); - performDrag(event); + + float x = mChart.isDragXEnabled() ? event.getX() - mTouchStartPoint.x : 0.f; + float y = mChart.isDragYEnabled() ? event.getY() - mTouchStartPoint.y : 0.f; + + performDrag(event, x, y); } else if (mTouchMode == X_ZOOM || mTouchMode == Y_ZOOM || mTouchMode == PINCH_ZOOM) { @@ -179,22 +185,36 @@ public boolean onTouch(View v, MotionEvent event) { && Math.abs(distance(event.getX(), mTouchStartPoint.x, event.getY(), mTouchStartPoint.y)) > mDragTriggerDist) { - if (mChart.hasNoDragOffset()) { + if (mChart.isDragEnabled()) { + + boolean shouldPan = !mChart.isFullyZoomedOut() || + !mChart.hasNoDragOffset(); + + if (shouldPan) { + + float distanceX = Math.abs(event.getX() - mTouchStartPoint.x); + float distanceY = Math.abs(event.getY() - mTouchStartPoint.y); + + // Disable dragging in a direction that's disallowed + if ((mChart.isDragXEnabled() || distanceY >= distanceX) && + (mChart.isDragYEnabled() || distanceY <= distanceX)) { + + mLastGesture = ChartGesture.DRAG; + mTouchMode = DRAG; + } - if (!mChart.isFullyZoomedOut() && mChart.isDragEnabled()) { - mTouchMode = DRAG; } else { - mLastGesture = ChartGesture.DRAG; + if (mChart.isHighlightPerDragEnabled()) { + mLastGesture = ChartGesture.DRAG; - if (mChart.isHighlightPerDragEnabled()) - performHighlightDrag(event); + if (mChart.isHighlightPerDragEnabled()) + performHighlightDrag(event); + } } - } else if (mChart.isDragEnabled()) { - mLastGesture = ChartGesture.DRAG; - mTouchMode = DRAG; } + } break; @@ -292,7 +312,7 @@ private void saveTouchStart(MotionEvent event) { * * @param event */ - private void performDrag(MotionEvent event) { + private void performDrag(MotionEvent event, float distanceX, float distanceY) { mLastGesture = ChartGesture.DRAG; @@ -300,28 +320,21 @@ private void performDrag(MotionEvent event) { OnChartGestureListener l = mChart.getOnChartGestureListener(); - float dX, dY; - // check if axis is inverted if (inverted()) { // if there is an inverted horizontalbarchart if (mChart instanceof HorizontalBarChart) { - dX = -(event.getX() - mTouchStartPoint.x); - dY = event.getY() - mTouchStartPoint.y; + distanceX = -distanceX; } else { - dX = event.getX() - mTouchStartPoint.x; - dY = -(event.getY() - mTouchStartPoint.y); + distanceY = -distanceY; } - } else { - dX = event.getX() - mTouchStartPoint.x; - dY = event.getY() - mTouchStartPoint.y; } - mMatrix.postTranslate(dX, dY); + mMatrix.postTranslate(distanceX, distanceY); if (l != null) - l.onChartTranslate(event, dX, dY); + l.onChartTranslate(event, distanceX, distanceY); } /** @@ -652,7 +665,12 @@ public void computeScroll() { MotionEvent event = MotionEvent.obtain(currentTime, currentTime, MotionEvent.ACTION_MOVE, mDecelerationCurrentPoint.x, mDecelerationCurrentPoint.y, 0); - performDrag(event); + + float dragDistanceX = mChart.isDragXEnabled() ? mDecelerationCurrentPoint.x - mTouchStartPoint.x : 0.f; + float dragDistanceY = mChart.isDragYEnabled() ? mDecelerationCurrentPoint.y - mTouchStartPoint.y : 0.f; + + performDrag(event, dragDistanceX, dragDistanceY); + event.recycle(); mMatrix = mChart.getViewPortHandler().refresh(mMatrix, mChart, false); From c97b8d531d5584b767d0587805c1c95018cf92d6 Mon Sep 17 00:00:00 2001 From: davidgoli Date: Fri, 22 Sep 2017 18:57:07 -0700 Subject: [PATCH 1257/1390] add option to draw limit lines on top of data --- .../charting/charts/BarLineChartBase.java | 20 ++++++++++++++++--- .../charting/components/AxisBase.java | 17 ++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index bf4c42e241..790ca67b78 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -212,9 +212,14 @@ protected void onDraw(Canvas canvas) { mAxisRendererLeft.renderAxisLine(canvas); mAxisRendererRight.renderAxisLine(canvas); - mXAxisRenderer.renderGridLines(canvas); - mAxisRendererLeft.renderGridLines(canvas); - mAxisRendererRight.renderGridLines(canvas); + if (mXAxis.isDrawGridLinesBehindDataEnabled()) + mXAxisRenderer.renderGridLines(canvas); + + if (mAxisLeft.isDrawGridLinesBehindDataEnabled()) + mAxisRendererLeft.renderGridLines(canvas); + + if (mAxisRight.isDrawGridLinesBehindDataEnabled()) + mAxisRendererRight.renderGridLines(canvas); if (mXAxis.isEnabled() && mXAxis.isDrawLimitLinesBehindDataEnabled()) mXAxisRenderer.renderLimitLines(canvas); @@ -231,6 +236,15 @@ protected void onDraw(Canvas canvas) { mRenderer.drawData(canvas); + if (!mXAxis.isDrawGridLinesBehindDataEnabled()) + mXAxisRenderer.renderGridLines(canvas); + + if (!mAxisLeft.isDrawGridLinesBehindDataEnabled()) + mAxisRendererLeft.renderGridLines(canvas); + + if (!mAxisRight.isDrawGridLinesBehindDataEnabled()) + mAxisRendererRight.renderGridLines(canvas); + // if highlighting is enabled if (valuesToHighlight()) mRenderer.drawHighlighted(canvas, mIndicesToHighlight); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 40835f7347..3c8028c24b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -112,6 +112,11 @@ public abstract class AxisBase extends ComponentBase { */ protected boolean mDrawLimitLineBehindData = false; + /** + * flag indicating the grid lines layer depth + */ + protected boolean mDrawGridLinesBehindData = true; + /** * Extra spacing for `axisMinimum` to be added to automatically calculated `axisMinimum` */ @@ -444,6 +449,18 @@ public boolean isDrawLimitLinesBehindDataEnabled() { return mDrawLimitLineBehindData; } + /** + * If this is set to false, the grid lines are draw on top of the actual data, + * otherwise behind. Default: true + * + * @param enabled + */ + public void setDrawGridLinesBehindData(boolean enabled) { mDrawGridLinesBehindData = enabled; } + + public boolean isDrawGridLinesBehindDataEnabled() { + return mDrawGridLinesBehindData; + } + /** * Returns the longest formatted label (in terms of characters), this axis * contains. From d3c339da100f874f7df8d350bc46dd516ad1d577 Mon Sep 17 00:00:00 2001 From: Maxim Pestryakov Date: Fri, 6 Oct 2017 17:12:46 +0300 Subject: [PATCH 1258/1390] Refactored LargeValueFormatter --- .../charting/formatter/LargeValueFormatter.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index c950d640b3..01eae56f51 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -20,10 +20,10 @@ public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter { - private static String[] SUFFIX = new String[]{ + private String[] mSuffix = new String[]{ "", "k", "m", "b", "t" }; - private static final int MAX_LENGTH = 5; + private int mMaxLength = 5; private DecimalFormat mFormat; private String mText = ""; @@ -68,8 +68,12 @@ public void setAppendix(String appendix) { * * @param suff new suffix */ - public void setSuffix(String[] suff) { - SUFFIX = suff; + public void setSuffix(String[] suffix) { + this.mSuffix = suffix; + } + + public void setMaxLength(int maxLength) { + this.mMaxLength = maxLength; } /** @@ -84,9 +88,9 @@ private String makePretty(double number) { int numericValue2 = Character.getNumericValue(r.charAt(r.length() - 2)); int combined = Integer.valueOf(numericValue2 + "" + numericValue1); - r = r.replaceAll("E[0-9][0-9]", SUFFIX[combined / 3]); + r = r.replaceAll("E[0-9][0-9]", mSuffix[combined / 3]); - while (r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")) { + while (r.length() > mMaxLength || r.matches("[0-9]+\\.[a-z]")) { r = r.substring(0, r.length() - 2) + r.substring(r.length() - 1); } From a5a482fbdcc034c1c8d0340b61a5ac072dbcda7c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 28 Nov 2017 10:50:37 +0100 Subject: [PATCH 1259/1390] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 0fd4b1cd69..e257daa0ab 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,7 @@ Donations - [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - - [**Donate 50 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - - [**Donate 100 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! + - Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! ## Got a question? [Contact me via 21.co](https://21.co/philjay/) From f2dedb30de20122ceb0f43d3d8649a2dfc98bd20 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:23:57 +0100 Subject: [PATCH 1260/1390] Update gradle and dependencies --- MPChartExample/build.gradle | 15 +++++++-------- MPChartLib/build.gradle | 8 ++++---- build.gradle | 12 ++++++++++-- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 75aec0ed32..b2e82531c3 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -2,11 +2,11 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 27 + buildToolsVersion '26.0.2' defaultConfig { minSdkVersion 16 - targetSdkVersion 25 + targetSdkVersion 27 versionCode 55 versionName '3.0.2' testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -22,7 +22,6 @@ android { } buildTypes { - release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' @@ -39,7 +38,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.0' + classpath 'com.android.tools.build:gradle:3.0.1' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -56,10 +55,10 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - compile 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' + implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' - compile project(':MPChartLib') - compile 'com.android.support:appcompat-v7:24.2.1' + implementation project(':MPChartLib') + implementation 'com.android.support:appcompat-v7:27.0.2' //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 58d12e2236..125fe6fdc1 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -4,12 +4,12 @@ apply plugin: 'maven' //apply plugin: 'realm-android' android { - compileSdkVersion 25 - buildToolsVersion '25.0.0' + compileSdkVersion 27 + buildToolsVersion '26.0.2' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 9 - targetSdkVersion 25 + targetSdkVersion 27 versionCode 3 versionName '3.0.2' } @@ -38,7 +38,7 @@ dependencies { //compile 'com.android.support:support-v4:19.+' //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API testCompile 'junit:junit:4.12' - testCompile "org.mockito:mockito-core:1.9.5" + testCompile "org.mockito:mockito-core:1.10.19" } android.libraryVariants.all { variant -> diff --git a/build.gradle b/build.gradle index 2a65e34ca0..a338cc40ff 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,14 @@ task wrapper(type: Wrapper) { buildscript { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } dependencies { - classpath "io.realm:realm-gradle-plugin:2.0.2" - classpath 'com.android.tools.build:gradle:2.3.0' + classpath "io.realm:realm-gradle-plugin:4.2.0" + classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } } @@ -16,5 +20,9 @@ buildscript { allprojects { repositories { jcenter() + maven { + url 'https://maven.google.com/' + name 'Google' + } } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 10dbafb60f..845ff30cac 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Thu Mar 23 15:58:00 CET 2017 +#Mon Nov 20 11:59:54 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip From 796dfb21f8d454296e0590b2f8beafa8a1d0d7e9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:28:03 +0100 Subject: [PATCH 1261/1390] Out comment gradle wrapper --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index a338cc40ff..6ac1e616b1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ -task wrapper(type: Wrapper) { - gradleVersion = '2.9' -} +//task wrapper(type: Wrapper) { +// gradleVersion = '2.9' +//} buildscript { repositories { From ed9340ea51891a53e47556ba13bb62a1bb980fbf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:47:10 +0100 Subject: [PATCH 1262/1390] Update maven android plugin --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 6ac1e616b1..1a6e95f12b 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { dependencies { classpath "io.realm:realm-gradle-plugin:4.2.0" classpath 'com.android.tools.build:gradle:3.0.1' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' } } From dfaffa39cca041dc68ad3171bc1348805618e26a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:48:42 +0100 Subject: [PATCH 1263/1390] Add maven plugin to example --- MPChartExample/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index b2e82531c3..5122ce0873 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,5 +1,6 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' +apply plugin: 'maven' android { compileSdkVersion 27 From 23aef1a0ab247b7e9212d0c1d203c3773bfc583e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:55:18 +0100 Subject: [PATCH 1264/1390] Add new google repo --- MPChartExample/build.gradle | 1 - build.gradle | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 5122ce0873..b2e82531c3 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' -apply plugin: 'maven' android { compileSdkVersion 27 diff --git a/build.gradle b/build.gradle index 1a6e95f12b..92f3d64ccd 100644 --- a/build.gradle +++ b/build.gradle @@ -5,10 +5,7 @@ buildscript { repositories { jcenter() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } dependencies { classpath "io.realm:realm-gradle-plugin:4.2.0" From 0868d9bf89ebff78ba8e0108954cc343bc8b711d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 15:57:30 +0100 Subject: [PATCH 1265/1390] Add new google repo --- MPChartExample/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index b2e82531c3..be9289ae07 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -36,6 +36,7 @@ android { buildscript { repositories { jcenter() + google() } dependencies { classpath 'com.android.tools.build:gradle:3.0.1' From 47485f8364e3520b73b4cf60de1e5c2683a84e51 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 16:03:11 +0100 Subject: [PATCH 1266/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e257daa0ab..50b1947b10 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.2/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -115,7 +115,7 @@ allprojects { ```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.2' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.3' } ``` @@ -134,7 +134,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.0.2 + v3.0.3 ``` @@ -154,7 +154,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.2/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 5e97f561f79a487b1a0813fa2a24f720644646f0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Nov 2017 16:06:58 +0100 Subject: [PATCH 1267/1390] Update version --- MPChartExample/build.gradle | 4 ++-- MPChartLib/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index be9289ae07..164f11425a 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,8 +7,8 @@ android { defaultConfig { minSdkVersion 16 targetSdkVersion 27 - versionCode 55 - versionName '3.0.2' + versionCode 56 + versionName '3.0.3' testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" sourceSets { diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 125fe6fdc1..8e19df7541 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -11,7 +11,7 @@ android { minSdkVersion 9 targetSdkVersion 27 versionCode 3 - versionName '3.0.2' + versionName '3.0.3' } buildTypes { release { From 1ac72ea811944ae7409e37dbfe40f6a6f2bb89e8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Nov 2017 09:27:59 +0100 Subject: [PATCH 1268/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 50b1947b10..da7b77f309 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ allprojects { ```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.3' + implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' } ``` From d9000987c7386ccf94d653295f1c1dd8a1c23907 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Nov 2017 13:40:49 +0100 Subject: [PATCH 1269/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index da7b77f309..12c8e0623c 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Features - Animations (build up animations, on both xPx- and yPx-axis) - Limit lines (providing additional information, maximums, ...) - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart + - Smooth zooming and scrolling for up to 10.000 data points in Line- and BarChart - Gradle support - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [**MPAndroidChart-Realm**](https://github.com/PhilJay/MPAndroidChart-Realm) :zap: From e416736ad52e35d4e25ac67af08525a8d64d4aaa Mon Sep 17 00:00:00 2001 From: Pawel Grzybek Date: Sun, 10 Dec 2017 20:19:06 +0100 Subject: [PATCH 1270/1390] Added option to set restrictions for Y axis autoscaling. --- .../mikephil/charting/components/YAxis.java | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index e84caab76b..c572e3043c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -38,6 +38,27 @@ public class YAxis extends AxisBase { */ protected boolean mDrawZeroLine = false; + /** + * flag indicating that auto scale min restriction should be used + */ + + private boolean mUseAutoScaleRestrictionMin = false; + /** + * flag indicating that auto scale max restriction should be used + */ + + private boolean mUseAutoScaleRestrictionMax = false; + /** + * restriction value of autoscale min + */ + + private float mAutoScaleMinRestriction = 0f; + + /** + * restriction value of autoscale max + */ + private float mAutoScaleMaxRestriction = 0f; + /** * Color of the zero line */ @@ -357,12 +378,54 @@ public boolean needsOffset() { return false; } + /** + * Sets min value restriction for autoscale + */ + public void setAutoScaleMinRestriction(float restrictionValue) { + mUseAutoScaleRestrictionMin = true; + mAutoScaleMinRestriction = restrictionValue; + } + + /** + * Sets max value restriction for autoscale + */ + public void setAutoScaleMaxRestriction(float restrictionValue) { + mUseAutoScaleRestrictionMax = true; + mAutoScaleMaxRestriction = restrictionValue; + } + + /** + * Resets min value restriction for autoscale + */ + public void resetAutoScaleMinRestriction() { + mUseAutoScaleRestrictionMin = false; + } + + /** + * Resets max value restriction for autoscale + */ + public void resetAutoScaleMaxRestriction() { + mUseAutoScaleRestrictionMax = false; + } + @Override public void calculate(float dataMin, float dataMax) { + float min = dataMin; + float max = dataMax; + // if custom, use value as is, else use data value - float min = mCustomAxisMin ? mAxisMinimum : dataMin; - float max = mCustomAxisMax ? mAxisMaximum : dataMax; + if( mCustomAxisMin ) { + min = mAxisMinimum; + } else if( mUseAutoScaleRestrictionMin ) { + min = Math.min( min, mAutoScaleMinRestriction ); + } + + if( mCustomAxisMax ) { + max = mAxisMaximum; + } else if( mUseAutoScaleRestrictionMax ) { + max = Math.max( max, mAutoScaleMaxRestriction ); + } // temporary range (before calculations) float range = Math.abs(max - min); From 16a9be8ea09021ea3dfb9f2e61a9acb4bfdb3fcc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 14 Dec 2017 19:37:09 +0100 Subject: [PATCH 1271/1390] Update gitignore, add assets --- MPChartExample/.gitignore | 1 + .../notimportant/MainActivity.java | 11 +++++------ design/other/bottom.png | Bin 0 -> 23219 bytes design/other/left.png | Bin 0 -> 241389 bytes design/other/right.png | Bin 0 -> 4161 bytes 5 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 design/other/bottom.png create mode 100644 design/other/left.png create mode 100644 design/other/right.png diff --git a/MPChartExample/.gitignore b/MPChartExample/.gitignore index 796b96d1c4..67e07b8fea 100644 --- a/MPChartExample/.gitignore +++ b/MPChartExample/.gitignore @@ -1 +1,2 @@ /build +/release diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 617e43c021..7490c3c933 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -90,7 +90,8 @@ protected void onCreate(Bundle savedInstanceState) { "A bar chart with multiple DataSet objects. One multiple colors per DataSet.")); objects.add(new ContentItem( "Charts in ViewPager Fragments", - "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the chart.")); + "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the" + + " chart.")); objects.add(new ContentItem( "BarChart inside ListView", "Demonstrates the usage of a BarChart inside a ListView item.")); @@ -135,12 +136,10 @@ protected void onCreate(Bundle savedInstanceState) { "Realm.io Database", "This demonstrates how to use this library with Realm.io mobile database."); objects.add(realm); - - ContentItem time = new ContentItem( + objects.add(new ContentItem( "Time Chart", - "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in milliseconds."); - time.isNew = true; - objects.add(time); + "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in " + + "milliseconds.")); objects.add(new ContentItem( "Filled LineChart", "This demonstrates how to fill an area between two LineDataSets.")); diff --git a/design/other/bottom.png b/design/other/bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..368f30987b37ae23057c10ddf90b42cb34441a0d GIT binary patch literal 23219 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 %T`KiZG#R^r$WU0u>{}dMbIUs!BhSKu! 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.T4bj&=rv0Wc(JapY+0wrM9nS_Wwg zJaawVK1o`KBVAm6EOas(ArDeR>IdrR|rgOA78(mqWEF4>P{^CylG_;qJ(FJr6S&jhPuTFBmSpD%gHp z4L&p(-+a`)ZfNm?Tln@}X-vB65_@q=xqxXsxXyppsm;LJ_CG!n+w#v`V^zx@)>j{5 z?qANXS#WMnB|i28J9>3(!1Yv;hG{THBCa_2gFh5nmABW-y%sdXKhN*>HsX#mmO$@J|XLxrO=F?DVlU-{% z2kCK$xxkJ=LH1x!T0O8Zf;b9+S?FG*wF4(b zuH(!RQf4efq23>#&LkEM(>GCCvRheJqse2(Al7nZ860Xs0B@s7yKJO|F4F$9Pay*j z$4Bi1$5Z1F=4gZr2B4my-y=6%0AXG^93SpR! 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

  • qx`i9{_&>4qeYQ~kZ6sIdNX2+o*J-3t3UwrT$M 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%0DHQS4)3Q)nfGGjY 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 z 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 f+_wPbM>_2+KkZRqt6BQh00Yd(%& Date: Tue, 19 Dec 2017 14:14:54 +0100 Subject: [PATCH 1272/1390] Update README.md --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 12c8e0623c..46c57a6d53 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,22 @@ Remember: *It's all about the looks.* As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: -Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). +Enterprise Solution Discount +----- + + + + +MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend [SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART). + + + +All MPAndroidChart users are entitled to a special **discount of 5%** off the [SciChart store](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART), using the following discount code: **MPANDROIDCHART** + + + +
    + Donations ----- From 21ad19661b33a05cd605e8ef4e81757516584a72 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Dec 2017 14:19:30 +0100 Subject: [PATCH 1273/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46c57a6d53..d15dcc7ae9 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,7 @@ Chart types License ======= -Copyright 2016 Philipp Jahoda +Copyright 2018 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 4b7eb1fd04a31d8d8400b6c9c0f990326c45bf79 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Dec 2017 14:38:34 +0100 Subject: [PATCH 1274/1390] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d15dcc7ae9..5ab1b95640 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,12 @@ Enterprise Solution Discount -MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend [SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART). +MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend +
    SciChart Android. -All MPAndroidChart users are entitled to a special **discount of 5%** off the [SciChart store](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART), using the following discount code: **MPANDROIDCHART** +All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** From 44125a87dd149298c8877b36ddc6068218d964af Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Dec 2017 10:59:50 +0100 Subject: [PATCH 1275/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5ab1b95640..8a9e264b9b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Remember: *It's all about the looks.* As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: -Enterprise Solution Discount +Enterprise Solution Discount | SciChart ----- From 89544095750cf35c24e3a1c000201e3acbf60419 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Dec 2017 14:03:05 +0100 Subject: [PATCH 1276/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8a9e264b9b..2e7c452679 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Remember: *It's all about the looks.* As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: -Enterprise Solution Discount | SciChart +[Enterprise Solution Discount | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) ----- From 779e0f566580ff66ebbd1e935a95fbe22eaef12e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Dec 2017 19:58:23 +0100 Subject: [PATCH 1277/1390] Update README.md --- README.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/README.md b/README.md index 2e7c452679..6c4266d660 100644 --- a/README.md +++ b/README.md @@ -41,18 +41,7 @@ Donations - [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! - -## Got a question? -[Contact me via 21.co](https://21.co/philjay/) - - -## Xamarin - -Xamarin port (by [Flash3001](https://github.com/Flash3001)): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). - -## Realm.io -[MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) allows to directly plot / draw data from [Realm.io](https://realm.io) mobile database. Spread the word ----- From 2c08b560d66d51b99ab3d0ee6d666c3e56174956 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Dec 2017 20:05:18 +0100 Subject: [PATCH 1278/1390] Update README.md --- README.md | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 6c4266d660..159fb7f3b3 100644 --- a/README.md +++ b/README.md @@ -83,22 +83,7 @@ Features ----- **Core features:** - - 8 different chart types - - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - - Dragging / Panning (with touch-gesture) - - Combined-Charts (line-, bar-, scatter-, candle-data) - - Dual (separate) Axes - - Customizable Axes (both x- and y-axis) - - Highlighting values (with customizable popup-views) - - Save chart to SD-Card (as image, or as .txt file) - - Predefined color templates - - Legends (generated automatically, customizable) - - Animations (build up animations, on both xPx- and yPx-axis) - - Limit lines (providing additional information, maximums, ...) - - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - - Smooth zooming and scrolling for up to 10.000 data points in Line- and BarChart - - Gradle support - - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [**MPAndroidChart-Realm**](https://github.com/PhilJay/MPAndroidChart-Realm) :zap: +You can have a look at the core features of this libary [**here**](https://github.com/PhilJay/MPAndroidChart/wiki/Core-Features). Usage ----- @@ -143,19 +128,9 @@ dependencies { ``` -**3. jar file only** - - Download the [**latest .jar file**](https://github.com/PhilJay/MPAndroidChart/releases) from the releases section - - Copy the **mpandroidchartlibrary-version.jar** file into the `libs` folder of your Android application project - - Start using the library +**3. jar file only** (not recommended) -**4. clone whole repository** - - Open your **commandline-input** and navigate to the desired destination folder on your machine (where you want to place the library) - - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library as well as the folder of the example project) - - Import the library folder (`MPChartLib`) into Android Studio (recommended) or your Eclipse workspace - - Add it as a reference to your project: - - [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) - - [managing projects from Android Studio](https://developer.android.com/sdk/installing/create-project.html) - +**4. clone whole repository** (not recommended) Documentation ----- From c867d7cb3749f43a25d9961c74319718f14b60a6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Dec 2017 20:06:18 +0100 Subject: [PATCH 1279/1390] Update README.md --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 159fb7f3b3..f5e4f11c6f 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,6 @@ Please do not expect answers to your questions if you have not considered all ab Features ----- - -**Core features:** You can have a look at the core features of this libary [**here**](https://github.com/PhilJay/MPAndroidChart/wiki/Core-Features). Usage @@ -127,10 +125,8 @@ dependencies { v3.0.3 ``` - -**3. jar file only** (not recommended) -**4. clone whole repository** (not recommended) +**3. clone whole repository** (not recommended) Documentation ----- From c50f03cf3970bcb76d677014d32f13c9628b2dc7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Dec 2017 20:09:46 +0100 Subject: [PATCH 1280/1390] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index f5e4f11c6f..8bbc199314 100644 --- a/README.md +++ b/README.md @@ -133,9 +133,7 @@ Documentation For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). - -You have a problem that cannot be solved by having a look at the example project and documentation? -No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) +You can also join others in a discussion on [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) Chart types ----- From 6ccaf940d8cde1bf100ba7531d794d1fded8bceb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Dec 2017 16:24:45 +0100 Subject: [PATCH 1281/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bbc199314..3a45288016 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Remember: *It's all about the looks.* As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: -[Enterprise Solution Discount | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) +[Enterprise Solution 5% Discount Coupon | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) ----- From 8fd1a86b0a33e886026e9fe79233f78d40028578 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Dec 2017 16:25:56 +0100 Subject: [PATCH 1282/1390] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 3a45288016..006fc677d1 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,6 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: - []()Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - - Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) From b3e23583343c81a77463c37a51a0c6c24b78c105 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jan 2018 14:06:19 +0100 Subject: [PATCH 1283/1390] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 006fc677d1..4774844aa2 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,10 @@ Donations **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! +**Bitcoin Wallet** + +1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg + **PayPal** - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! From 297ce9f2cc1f48da67937c0a87d6b69bc39b9395 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jan 2018 14:07:02 +0100 Subject: [PATCH 1284/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4774844aa2..11be4d1109 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Donations **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! -**Bitcoin Wallet** +**My Bitcoin Wallet** (Bitcoin only) 1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg From a5250888b96af4d900bba98ff6f8f385d53c6fa3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jan 2018 15:27:40 +0100 Subject: [PATCH 1285/1390] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 11be4d1109..063680ed0d 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,10 @@ Donations 1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg +**My Ethereum Wallet** (Ethereum only) + +0x04ef098bf9f91871391363e3caf791afa3adc39b + **PayPal** - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! From 82668ebc34b7636e74ee2734c8055a6b8510dbcb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 24 Feb 2018 12:50:04 +0100 Subject: [PATCH 1286/1390] Add files via upload --- googlee1205ea43aa2c32a.html | 1 + 1 file changed, 1 insertion(+) create mode 100644 googlee1205ea43aa2c32a.html diff --git a/googlee1205ea43aa2c32a.html b/googlee1205ea43aa2c32a.html new file mode 100644 index 0000000000..ae23863ce1 --- /dev/null +++ b/googlee1205ea43aa2c32a.html @@ -0,0 +1 @@ +google-site-verification: googlee1205ea43aa2c32a.html \ No newline at end of file From 3e1eb1445a753d77b4dd02db205b2e5bbc41ce4b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 24 Feb 2018 12:51:49 +0100 Subject: [PATCH 1287/1390] Delete googlee1205ea43aa2c32a.html --- googlee1205ea43aa2c32a.html | 1 - 1 file changed, 1 deletion(-) delete mode 100644 googlee1205ea43aa2c32a.html diff --git a/googlee1205ea43aa2c32a.html b/googlee1205ea43aa2c32a.html deleted file mode 100644 index ae23863ce1..0000000000 --- a/googlee1205ea43aa2c32a.html +++ /dev/null @@ -1 +0,0 @@ -google-site-verification: googlee1205ea43aa2c32a.html \ No newline at end of file From aee6058dbb74f4eb1aae8e88c7562d28a91e1e1c Mon Sep 17 00:00:00 2001 From: zhanglong Date: Tue, 27 Feb 2018 15:04:47 +0800 Subject: [PATCH 1288/1390] Avoid that the last label entry in the x-labels clip off the edge of the screen #3819 --- .../com/github/mikephil/charting/renderer/XAxisRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 2c305796df..8adb56c73a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -207,7 +207,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mXAxis.isAvoidFirstLastClippingEnabled()) { // avoid clipping of the last - if (i == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) { + if (i / 2 == mXAxis.mEntryCount - 1 && mXAxis.mEntryCount > 1) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); if (width > mViewPortHandler.offsetRight() * 2 From 1e6e58d2c026be332d6756b04d85b33cd3d36c2b Mon Sep 17 00:00:00 2001 From: sembozdemir Date: Wed, 28 Mar 2018 20:23:51 +0300 Subject: [PATCH 1289/1390] Add option for using slice color as value line color Fixes: #3897 --- .../mpchartexample/PiePolylineChartActivity.java | 3 ++- .../mikephil/charting/data/PieDataSet.java | 16 ++++++++++++++-- .../interfaces/datasets/IPieDataSet.java | 6 +++++- .../charting/renderer/PieChartRenderer.java | 5 +++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 49fc4959e9..e0d3063ede 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -19,7 +19,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; @@ -226,6 +225,8 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); + //dataSet.setUsingSliceColorAsValueLineColor(true); + //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 010cfbddc5..98b434d3d7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -18,6 +18,7 @@ public class PieDataSet extends DataSet implements IPieDataSet { private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; + private boolean mUsingSliceColorAsValueLineColor = false; private int mValueLineColor = 0xff000000; private float mValueLineWidth = 1.0f; private float mValueLinePart1OffsetPercentage = 75.f; @@ -134,6 +135,18 @@ public void setYValuePosition(ValuePosition yValuePosition) this.mYValuePosition = yValuePosition; } + /** + * When valuePosition is OutsideSlice, use slice colors as line color if true + * */ + @Override + public boolean isUsingSliceColorAsValueLineColor() { + return mUsingSliceColorAsValueLineColor; + } + + public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLineColor) { + this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor; + } + /** When valuePosition is OutsideSlice, indicates line color */ @Override public int getValueLineColor() @@ -141,8 +154,7 @@ public int getValueLineColor() return mValueLineColor; } - public void setValueLineColor(int valueLineColor) - { + public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index a53a9645af..1698ef786b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,6 +1,5 @@ package com.github.mikephil.charting.interfaces.datasets; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -36,6 +35,11 @@ public interface IPieDataSet extends IDataSet { PieDataSet.ValuePosition getXValuePosition(); PieDataSet.ValuePosition getYValuePosition(); + /** + * When valuePosition is OutsideSlice, use slice colors as line color if true + * */ + boolean isUsingSliceColorAsValueLineColor(); + /** * When valuePosition is OutsideSlice, indicates line color * */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index be72a0834f..495ae72f3b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -536,6 +536,11 @@ public void drawValues(Canvas c) { } if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + + if (dataSet.isUsingSliceColorAsValueLineColor()) { + mValueLinePaint.setColor(dataSet.getColor(j)); + } + c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint); c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint); } From 508cc565a9818d65ee6d295e8a98a4cda14eb9f3 Mon Sep 17 00:00:00 2001 From: Wilder Pereira Date: Sun, 15 Apr 2018 21:51:15 -0300 Subject: [PATCH 1290/1390] Rename RadarChartActivitry to RadarChartActivity --- MPChartExample/AndroidManifest.xml | 2 +- .../{RadarChartActivitry.java => RadarChartActivity.java} | 2 +- .../mpchartexample/notimportant/MainActivity.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/{RadarChartActivitry.java => RadarChartActivity.java} (99%) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 87d8b72402..3fa15cd69c 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -44,7 +44,7 @@ - + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index 937973fe4e..d060449d9c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -28,7 +28,7 @@ import java.util.ArrayList; -public class RadarChartActivitry extends DemoBase { +public class RadarChartActivity extends DemoBase { private RadarChart mChart; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 7490c3c933..45ca879ee3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -39,7 +39,7 @@ import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.PiePolylineChartActivity; import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; +import com.xxmassdeveloper.mpchartexample.RadarChartActivity; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; @@ -242,7 +242,7 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 20: - i = new Intent(this, RadarChartActivitry.class); + i = new Intent(this, RadarChartActivity.class); startActivity(i); break; case 21: From 993a8554c02c82d455c38abbdf6fc12bb5c01b21 Mon Sep 17 00:00:00 2001 From: Wilder Pereira Date: Sun, 15 Apr 2018 21:51:35 -0300 Subject: [PATCH 1291/1390] Remove unused imports --- .../com/xxmassdeveloper/mpchartexample/RadarChartActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index d060449d9c..bcd9fac285 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; From e1411f169e5c4798e85f2ba07bc5b0dc655b5828 Mon Sep 17 00:00:00 2001 From: almic Date: Fri, 27 Apr 2018 00:08:27 -0600 Subject: [PATCH 1292/1390] Remove Custom Check calculate() no longer checks if min and max is custom, it just adds the padding. --- .../mikephil/charting/components/YAxis.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index e84caab76b..571e0f393e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -373,19 +373,11 @@ public void calculate(float dataMin, float dataMax) { min = min - 1f; } - // bottom-space only effects non-custom min - if (!mCustomAxisMin) { - - float bottomSpace = range / 100f * getSpaceBottom(); - this.mAxisMinimum = (min - bottomSpace); - } - - // top-space only effects non-custom max - if (!mCustomAxisMax) { - - float topSpace = range / 100f * getSpaceTop(); - this.mAxisMaximum = (max + topSpace); - } + float bottomSpace = range / 100f * getSpaceBottom(); + this.mAxisMinimum = (min - bottomSpace); + + float topSpace = range / 100f * getSpaceTop(); + this.mAxisMaximum = (max + topSpace); // calc actual range this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); From d8ea67aa216e924268643b078ed5b7a383a3f64b Mon Sep 17 00:00:00 2001 From: Hannes Achleitner Date: Wed, 25 Apr 2018 08:14:09 +0200 Subject: [PATCH 1293/1390] update to Android Studio 3.1.2 --- MPChartExample/build.gradle | 4 ++-- MPChartLib/build.gradle | 8 +++----- build.gradle | 11 ++--------- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 164f11425a..c7bacd5e4d 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'realm-android' android { compileSdkVersion 27 - buildToolsVersion '26.0.2' + buildToolsVersion '27.0.3' defaultConfig { minSdkVersion 16 targetSdkVersion 27 @@ -39,7 +39,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.1.2' //classpath 'io.realm:realm-gradle-plugin:0.88.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 8e19df7541..8575e37e2f 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'maven' android { compileSdkVersion 27 - buildToolsVersion '26.0.2' + buildToolsVersion '27.0.3' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 9 @@ -34,11 +34,9 @@ repositories { } dependencies { - //compile fileTree(dir: 'libs', include: ['*.jar']) - //compile 'com.android.support:support-v4:19.+' //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API - testCompile 'junit:junit:4.12' - testCompile "org.mockito:mockito-core:1.10.19" + testImplementation 'junit:junit:4.12' + testImplementation "org.mockito:mockito-core:1.10.19" } android.libraryVariants.all { variant -> diff --git a/build.gradle b/build.gradle index 92f3d64ccd..65ca5186cf 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,3 @@ -//task wrapper(type: Wrapper) { -// gradleVersion = '2.9' -//} - buildscript { repositories { jcenter() @@ -9,7 +5,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:4.2.0" - classpath 'com.android.tools.build:gradle:3.0.1' + classpath 'com.android.tools.build:gradle:3.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' } } @@ -17,9 +13,6 @@ buildscript { allprojects { repositories { jcenter() - maven { - url 'https://maven.google.com/' - name 'Google' - } + google() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 845ff30cac..02b0428be0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Mon Nov 20 11:59:54 CET 2017 +#Wed Apr 25 08:04:33 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip From 7286f8703f50b8c128a89c543a58f268d9902123 Mon Sep 17 00:00:00 2001 From: Mick A Date: Sun, 29 Apr 2018 09:48:01 -0600 Subject: [PATCH 1294/1390] Create ISSUE_TEMPLATE.md --- ISSUE_TEMPLATE.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 ISSUE_TEMPLATE.md diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..b87cd42091 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,13 @@ +- [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) file before posting this issue. + +### The problem + +What is the problem, what is going wrong? Is this a bug, question, or a feature request? + +### What should happen + +What do you think _should_ happen? + +### Addition information + +You can add addition info here, like code snippets or references. You can also attach files like images or stacktraces. Images that are no taller than 500px can be put inside the issue text, but please post larger images and stacktraces as links to a [Gist](https://help.github.com/articles/creating-gists/) or attach the file by clicking "Attach files" below, so that we don't have to scroll all the way down a page to respond to you. From 6fbd49276168b6270a85cc8ddb2d655b0afaa1f2 Mon Sep 17 00:00:00 2001 From: Mick A Date: Sun, 29 Apr 2018 09:58:33 -0600 Subject: [PATCH 1295/1390] Create PULL_REQUEST_TEMPLATE.md --- PULL_REQUEST_TEMPLATE.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 PULL_REQUEST_TEMPLATE.md diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..fb64ddf8be --- /dev/null +++ b/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +- [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) file before posting submitting this pull request. + +Before describing this pull request, please prefix the title with a topic from the list: +`Feature`, `Fix`, `Style` + +### [Feature / Fix / Style] (choose ONE) + +What will this PR do? Remember that you don't need to explain everything, let the changes speak for itself. + +If a bug fix, reference any issues that this fixes, like so: "fixes #99" + +### Why should this be merged? + +If needed, further explain this PR and why it should be merged. If the changes are too broad, your pull request may be denied for having too much in it. It may also be denied if the commits aren't properly formatted. From 35c9fc937ecda0dd2eb1a7b879aa869a48bfad3d Mon Sep 17 00:00:00 2001 From: almic Date: Mon, 30 Apr 2018 12:24:18 -0600 Subject: [PATCH 1296/1390] refactor(EasingFunction): Simplified EasingFunction EasingFunction has been simplified greatly, and I've added a MUCH needed annotation to relevant methods. Easing.EasingOptions has been deprecated, as well as any methods using them. Converting is as simple as deleting the "EasingOptions" part. A new signature is available for animateXY()! You are now able to pass one EasingFunction to animateXY() if you want both axes to be animated the same way. Quietly included are some gradle build updates, incrementing the appcompat version to 27.1.1, and using the new `javacompiler` to avoid deprecation of `javacompile` --- MPChartExample/build.gradle | 2 +- .../mpchartexample/HalfPieChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/PieChartActivity.java | 5 +- .../PiePolylineChartActivity.java | 4 +- .../mpchartexample/RadarChartActivity.java | 8 +- .../realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityCandle.java | 2 +- .../RealmDatabaseActivityHorizontalBar.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../realm/RealmWikiExample.java | 4 +- MPChartLib/build.gradle | 8 +- .../charting/animation/ChartAnimator.java | 292 +++--- .../mikephil/charting/animation/Easing.java | 942 ++++++------------ .../charting/animation/EasingFunction.java | 15 - .../mikephil/charting/charts/Chart.java | 44 +- .../charting/charts/PieRadarChartBase.java | 5 +- 19 files changed, 524 insertions(+), 821 deletions(-) delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index c7bacd5e4d..8e6fe137b8 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -59,7 +59,7 @@ dependencies { implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' implementation project(':MPChartLib') - implementation 'com.android.support:appcompat-v7:27.0.2' + implementation 'com.android.support:appcompat-v7:27.1.1' //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 15da39a8f3..a524f36a43 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -68,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(4, 100); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); + mChart.animateY(1400, Easing.EaseInOutQuad); Legend l = mChart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index b18309a26a..6cf7150c97 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -302,7 +302,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.animateY: { - mChart.animateY(3000, Easing.EasingOption.EaseInCubic); + mChart.animateY(3000, Easing.EaseInCubic); break; } case R.id.animateXY: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 085580a923..eb60524cb0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -90,7 +90,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(4, 100); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); + mChart.animateY(1400, Easing.EaseInOutQuad); // mChart.spin(2000, 0, 360); mSeekBarX.setOnSeekBarChangeListener(this); @@ -179,8 +179,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleSpin: { - mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption - .EaseInCubic); + mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); break; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index e0d3063ede..44fbf06c89 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -38,7 +38,7 @@ public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChang private PieChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - + private Typeface tf; @Override @@ -97,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(4, 100); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); + mChart.animateY(1400, Easing.EaseInOutQuad); // mChart.spin(2000, 0, 360); Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index bcd9fac285..f1fd4cc891 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -62,10 +62,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(); - mChart.animateXY( - 1400, 1400, - Easing.EasingOption.EaseInOutQuad, - Easing.EasingOption.EaseInOutQuad); + mChart.animateXY(1400, 1400, Easing.EaseInOutQuad); XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(mTfLight); @@ -193,8 +190,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleSpin: { - mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption - .EaseInCubic); + mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); break; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index c87290050d..4f1d42f1db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -64,6 +64,6 @@ private void setData() { // set data mChart.setData(data); mChart.setFitBars(true); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index d0aa25b864..fb28c3f08a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -66,6 +66,6 @@ private void setData() { // set data mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index a388df3741..17c0d8d2f0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -72,6 +72,6 @@ private void setData() { // set data mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 5fcfa76bff..35138d656d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -69,6 +69,6 @@ private void setData() { // set data mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 55f7f6dd4c..24982cf7fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -73,6 +73,6 @@ private void setData() { // set data mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index 14175ac73a..d2e2fd70f5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -68,6 +68,6 @@ private void setData() { // set data mChart.setData(data); - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + mChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 6c1d7cde03..25011b0e2b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -112,7 +112,7 @@ public String getFormattedValue(float value, AxisBase axis) { // set data lineChart.setData(lineData); - lineChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + lineChart.animateY(1400, Easing.EaseInOutQuart); // BAR-CHART @@ -128,6 +128,6 @@ public String getFormattedValue(float value, AxisBase axis) { barChart.setData(barData); barChart.setFitBars(true); - barChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + barChart.animateY(1400, Easing.EaseInOutQuart); } } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 8575e37e2f..19c06befb3 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -8,6 +8,7 @@ android { buildToolsVersion '27.0.3' // resourcePrefix 'mpcht' defaultConfig { + //noinspection MinSdkTooLow minSdkVersion 9 targetSdkVersion 27 versionCode 3 @@ -35,6 +36,7 @@ repositories { dependencies { //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API + implementation 'com.android.support:support-annotations:27.1.1' testImplementation 'junit:junit:4.12' testImplementation "org.mockito:mockito-core:1.10.19" } @@ -42,9 +44,9 @@ dependencies { android.libraryVariants.all { variant -> def name = variant.buildType.name def task = project.tasks.create "jar${name.capitalize()}", Jar - task.dependsOn variant.javaCompile - task.from variant.javaCompile.destinationDir - artifacts.add('archives', task); + task.dependsOn variant.javaCompiler + task.from variant.javaCompiler.destinationDir + artifacts.add('archives', task) } task sourcesJar(type: Jar) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index 639442a4c9..026a1b30d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -3,224 +3,190 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.annotation.SuppressLint; +import android.support.annotation.RequiresApi; + +import com.github.mikephil.charting.animation.Easing.EasingFunction; /** - * Object responsible for all animations in the Chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * + * Object responsible for all animations in the Chart. Animations require API level 11. + * * @author Philipp Jahoda + * @author Mick Ashton */ public class ChartAnimator { /** object that is updated upon animation update */ private AnimatorUpdateListener mListener; - public ChartAnimator() { + /** The phase of drawn values on the y-axis. 0 - 1 */ + @SuppressWarnings("WeakerAccess") + protected float mPhaseY = 1f; - } + /** The phase of drawn values on the x-axis. 0 - 1 */ + @SuppressWarnings("WeakerAccess") + protected float mPhaseX = 1f; + + public ChartAnimator() { } + @RequiresApi(11) public ChartAnimator(AnimatorUpdateListener listener) { mListener = listener; } - /** - * ################ ################ ################ ################ - */ - /** CODE BELOW THIS RELATED TO ANIMATION */ - - /** the phase that is animated and influences the drawn values on the y-axis */ - protected float mPhaseY = 1f; - - /** the phase that is animated and influences the drawn values on the x-axis */ - protected float mPhaseX = 1f; + @RequiresApi(11) + private ObjectAnimator xAnimator(int duration, EasingFunction easing) { - /** - * ################ ################ ################ ################ - */ - /** METHODS FOR CUSTOM EASING */ + ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(easing); + animatorX.setDuration(duration); - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. - * - * @param durationMillisX - * @param durationMillisY - * @param easingX - * @param easingY - */ - public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, - EasingFunction easingY) { + return animatorX; + } - if (android.os.Build.VERSION.SDK_INT < 11) - return; + @RequiresApi(11) + private ObjectAnimator yAnimator(int duration, EasingFunction easing) { ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easingY); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easingX); - animatorX.setDuration( - durationMillisX); + animatorY.setInterpolator(easing); + animatorY.setDuration(duration); - // make sure only one animator produces update-callbacks (which then - // call invalidate()) - if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); - } else { - animatorY.addUpdateListener(mListener); - } + return animatorY; + } - animatorX.start(); - animatorY.start(); + /** + * Animates values along the X axis, in a linear fashion. + * + * @param durationMillis animation duration + */ + @RequiresApi(11) + public void animateX(int durationMillis) { + animateX(durationMillis, Easing.Linear); } /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. + * Animates values along the X axis. * - * @param durationMillis - * @param easing + * @param durationMillis animation duration + * @param easing EasingFunction */ + @RequiresApi(11) public void animateX(int durationMillis, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(easing); - animatorX.setDuration(durationMillis); + ObjectAnimator animatorX = xAnimator(durationMillis, easing); animatorX.addUpdateListener(mListener); animatorX.start(); } /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. + * Animates values along both the X and Y axes, in a linear fashion. * - * @param durationMillis - * @param easing + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis */ - public void animateY(int durationMillis, EasingFunction easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(easing); - animatorY.setDuration(durationMillis); - animatorY.addUpdateListener(mListener); - animatorY.start(); + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY) { + animateXY(durationMillisX, durationMillisY, Easing.Linear, Easing.Linear); } /** - * ################ ################ ################ ################ - */ - /** METHODS FOR PREDEFINED EASING */ - - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. + * Animates values along both the X and Y axes. * - * @param durationMillisX - * @param durationMillisY - * @param easingX - * @param easingY + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easing EasingFunction for both axes */ - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easingY)); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easingX)); - animatorX.setDuration( - durationMillisX); + ObjectAnimator xAnimator = xAnimator(durationMillisX, easing); + ObjectAnimator yAnimator = yAnimator(durationMillisY, easing); - // make sure only one animator produces update-callbacks (which then - // call invalidate()) if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); + xAnimator.addUpdateListener(mListener); } else { - animatorY.addUpdateListener(mListener); + yAnimator.addUpdateListener(mListener); } - animatorX.start(); - animatorY.start(); + xAnimator.start(); + yAnimator.start(); } /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. + * Animates values along both the X and Y axes. * - * @param durationMillis - * @param easing + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easingX EasingFunction for the X axis + * @param easingY EasingFunction for the Y axis */ - public void animateX(int durationMillis, Easing.EasingOption easing) { + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, + EasingFunction easingY) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; + ObjectAnimator xAnimator = xAnimator(durationMillisX, easingX); + ObjectAnimator yAnimator = yAnimator(durationMillisY, easingY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorX.setDuration(durationMillis); - animatorX.addUpdateListener(mListener); - animatorX.start(); + if (durationMillisX > durationMillisY) { + xAnimator.addUpdateListener(mListener); + } else { + yAnimator.addUpdateListener(mListener); + } + + xAnimator.start(); + yAnimator.start(); } /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. + * Animates values along the Y axis, in a linear fashion. * - * @param durationMillis - * @param easing + * @param durationMillis animation duration */ - public void animateY(int durationMillis, Easing.EasingOption easing) { + @RequiresApi(11) + public void animateY(int durationMillis) { + animateY(durationMillis, Easing.Linear); + } - if (android.os.Build.VERSION.SDK_INT < 11) - return; + /** + * Animates values along the Y axis. + * + * @param durationMillis animation duration + * @param easing EasingFunction + */ + @RequiresApi(11) + public void animateY(int durationMillis, EasingFunction easing) { - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorY.setDuration(durationMillis); + ObjectAnimator animatorY = yAnimator(durationMillis, easing); animatorY.addUpdateListener(mListener); animatorY.start(); } - /** - * ################ ################ ################ ################ - */ - /** METHODS FOR ANIMATION WITHOUT EASING */ - /** * Animates the drawing / rendering of the chart on both x- and y-axis with * the specified animation time. If animate(...) is called, no further * calling of invalidate() is necessary to refresh the chart. * - * @param durationMillisX - * @param durationMillisY + * @param durationMillisX animation duration along the X axis + * @param durationMillisY animation duration along the Y axis + * @param easingX EasingFunction for the X axis + * @param easingY EasingFunction for the Y axis + * + * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} + * @see #animateXY(int, int, EasingFunction, EasingFunction) */ - public void animateXY(int durationMillisX, int durationMillisY) { + @SuppressWarnings("deprecation") + @Deprecated + public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, + Easing.EasingOption easingY) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easingY)); animatorY.setDuration( durationMillisY); ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easingX)); animatorX.setDuration( durationMillisX); @@ -241,14 +207,21 @@ public void animateXY(int durationMillisX, int durationMillisY) { * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * - * @param durationMillis + * @param durationMillis animation duration + * @param easing EasingFunction + * + * @deprecated Use {@link #animateX(int, EasingFunction)} + * @see #animateX(int, EasingFunction) */ - public void animateX(int durationMillis) { + @SuppressWarnings("deprecation") + @Deprecated + public void animateX(int durationMillis, Easing.EasingOption easing) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); + animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easing)); animatorX.setDuration(durationMillis); animatorX.addUpdateListener(mListener); animatorX.start(); @@ -259,52 +232,69 @@ public void animateX(int durationMillis) { * animation time. If animate(...) is called, no further calling of * invalidate() is necessary to refresh the chart. * - * @param durationMillis + * @param durationMillis animation duration + * @param easing EasingFunction + * + * @deprecated Use {@link #animateY(int, EasingFunction)} + * @see #animateY(int, EasingFunction) */ - public void animateY(int durationMillis) { + @SuppressWarnings("deprecation") + @Deprecated + public void animateY(int durationMillis, Easing.EasingOption easing) { if (android.os.Build.VERSION.SDK_INT < 11) return; ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); + animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easing)); animatorY.setDuration(durationMillis); animatorY.addUpdateListener(mListener); animatorY.start(); } /** - * This gets the y-phase that is used to animate the values. + * Gets the Y axis phase of the animation. * - * @return + * @return float value of {@link #mPhaseY} */ public float getPhaseY() { return mPhaseY; } /** - * This modifys the y-phase that is used to animate the values. + * Sets the Y axis phase of the animation. * - * @param phase + * @param phase float value between 0 - 1 */ public void setPhaseY(float phase) { + if (phase > 1f) { + phase = 1f; + } else if (phase < 0f) { + phase = 0f; + } mPhaseY = phase; } /** - * This gets the x-phase that is used to animate the values. + * Gets the X axis phase of the animation. * - * @return + * @return float value of {@link #mPhaseX} */ public float getPhaseX() { return mPhaseX; } /** - * This modifys the x-phase that is used to animate the values. + * Sets the X axis phase of the animation. * - * @param phase + * @param phase float value between 0 - 1 */ public void setPhaseX(float phase) { + if (phase > 1f) { + phase = 1f; + } else if (phase < 0f) { + phase = 0f; + } mPhaseX = phase; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java index 1741f6f511..631e313b10 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java @@ -1,17 +1,30 @@ package com.github.mikephil.charting.animation; +import android.animation.TimeInterpolator; +import android.support.annotation.RequiresApi; + /** * Easing options. - * + * * @author Daniel Cohen Gindi + * @author Mick Ashton */ +@SuppressWarnings("WeakerAccess") +@RequiresApi(11) public class Easing { + public interface EasingFunction extends TimeInterpolator { + @Override + float getInterpolation(float input); + } + /** - * Use EasingOption instead of EasingFunction to avoid crashes below Android - * 3.0 + * Enum holding EasingOption constants + * + * @deprecated Use Easing.Linear instead of Easing.EasingOption.Linear */ + @Deprecated public enum EasingOption { Linear, EaseInQuad, @@ -43,679 +56,362 @@ public enum EasingOption { EaseInOutBounce, } + /** + * Returns the EasingFunction of the given EasingOption + * + * @param easing EasingOption to get + * @return EasingFunction + */ + @SuppressWarnings("deprecation") + @Deprecated public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { switch (easing) { default: case Linear: - return Easing.EasingFunctions.Linear; + return Easing.Linear; case EaseInQuad: - return Easing.EasingFunctions.EaseInQuad; + return Easing.EaseInQuad; case EaseOutQuad: - return Easing.EasingFunctions.EaseOutQuad; + return Easing.EaseOutQuad; case EaseInOutQuad: - return Easing.EasingFunctions.EaseInOutQuad; + return Easing.EaseInOutQuad; case EaseInCubic: - return Easing.EasingFunctions.EaseInCubic; + return Easing.EaseInCubic; case EaseOutCubic: - return Easing.EasingFunctions.EaseOutCubic; + return Easing.EaseOutCubic; case EaseInOutCubic: - return Easing.EasingFunctions.EaseInOutCubic; + return Easing.EaseInOutCubic; case EaseInQuart: - return Easing.EasingFunctions.EaseInQuart; + return Easing.EaseInQuart; case EaseOutQuart: - return Easing.EasingFunctions.EaseOutQuart; + return Easing.EaseOutQuart; case EaseInOutQuart: - return Easing.EasingFunctions.EaseInOutQuart; + return Easing.EaseInOutQuart; case EaseInSine: - return Easing.EasingFunctions.EaseInSine; + return Easing.EaseInSine; case EaseOutSine: - return Easing.EasingFunctions.EaseOutSine; + return Easing.EaseOutSine; case EaseInOutSine: - return Easing.EasingFunctions.EaseInOutSine; + return Easing.EaseInOutSine; case EaseInExpo: - return Easing.EasingFunctions.EaseInExpo; + return Easing.EaseInExpo; case EaseOutExpo: - return Easing.EasingFunctions.EaseOutExpo; + return Easing.EaseOutExpo; case EaseInOutExpo: - return Easing.EasingFunctions.EaseInOutExpo; + return Easing.EaseInOutExpo; case EaseInCirc: - return Easing.EasingFunctions.EaseInCirc; + return Easing.EaseInCirc; case EaseOutCirc: - return Easing.EasingFunctions.EaseOutCirc; + return Easing.EaseOutCirc; case EaseInOutCirc: - return Easing.EasingFunctions.EaseInOutCirc; + return Easing.EaseInOutCirc; case EaseInElastic: - return Easing.EasingFunctions.EaseInElastic; + return Easing.EaseInElastic; case EaseOutElastic: - return Easing.EasingFunctions.EaseOutElastic; + return Easing.EaseOutElastic; case EaseInOutElastic: - return Easing.EasingFunctions.EaseInOutElastic; + return Easing.EaseInOutElastic; case EaseInBack: - return Easing.EasingFunctions.EaseInBack; + return Easing.EaseInBack; case EaseOutBack: - return Easing.EasingFunctions.EaseOutBack; + return Easing.EaseOutBack; case EaseInOutBack: - return Easing.EasingFunctions.EaseInOutBack; + return Easing.EaseInOutBack; case EaseInBounce: - return Easing.EasingFunctions.EaseInBounce; + return Easing.EaseInBounce; case EaseOutBounce: - return Easing.EasingFunctions.EaseOutBounce; + return Easing.EaseOutBounce; case EaseInOutBounce: - return Easing.EasingFunctions.EaseInOutBounce; + return Easing.EaseInOutBounce; } } - - private static class EasingFunctions { - - /** - * ########## ########## ########## ########## ########## ########## - * PREDEFINED EASING FUNCTIONS BELOW THIS - */ - - public static final EasingFunction Linear = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return elapsed / (float) duration; - // } - - @Override - public float getInterpolation(float input) { - return input; + + private static final float DOUBLE_PI = 2f * (float) Math.PI; + + @SuppressWarnings("unused") + public static final EasingFunction Linear = new EasingFunction() { + public float getInterpolation(float input) { + return input; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInQuad = new EasingFunction() { + public float getInterpolation(float input) { + return input * input; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutQuad = new EasingFunction() { + public float getInterpolation(float input) { + return -input * (input - 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutQuad = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + + if (input < 1f) { + return 0.5f * input * input; } - }; - - public static final EasingFunction EaseInQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input; + + return -0.5f * ((--input) * (input - 2f) - 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInCubic = new EasingFunction() { + public float getInterpolation(float input) { + return (float) Math.pow(input, 3); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutCubic = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return (float) Math.pow(input, 3) + 1f; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutCubic = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(input, 3); } - }; - - public static final EasingFunction EaseOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -position * (position - 2.f); - // } - - @Override - public float getInterpolation(float input) { - return -input * (input - 2f); + input -= 2f; + return 0.5f * ((float) Math.pow(input, 3) + 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInQuart = new EasingFunction() { + + public float getInterpolation(float input) { + return (float) Math.pow(input, 4); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutQuart = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return -((float) Math.pow(input, 4) - 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutQuart = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(input, 4); } - }; + input -= 2f; + return -0.5f * ((float) Math.pow(input, 4) - 2f); + } + }; - public static final EasingFunction EaseInOutQuad = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position; - // } - // return -0.5f * ((--position) * (position - 2.f) - 1.f); - // } + @SuppressWarnings("unused") + public static final EasingFunction EaseInSine = new EasingFunction() { + public float getInterpolation(float input) { + return -(float) Math.cos(input * (Math.PI / 2f)) + 1f; + } + }; - @Override - public float getInterpolation(float input) { + @SuppressWarnings("unused") + public static final EasingFunction EaseOutSine = new EasingFunction() { + public float getInterpolation(float input) { + return (float) Math.sin(input * (Math.PI / 2f)); + } + }; - float position = input / 0.5f; + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutSine = new EasingFunction() { + public float getInterpolation(float input) { + return -0.5f * ((float) Math.cos(Math.PI * input) - 1f); + } + }; - if (position < 1.f) { - return 0.5f * position * position; - } + @SuppressWarnings("unused") + public static final EasingFunction EaseInExpo = new EasingFunction() { + public float getInterpolation(float input) { + return (input == 0) ? 0f : (float) Math.pow(2f, 10f * (input - 1f)); + } + }; - return -0.5f * ((--position) * (position - 2.f) - 1.f); - } - }; - - public static final EasingFunction EaseInCubic = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return position * position * position; - // } - - @Override - public float getInterpolation(float input) { - return input * input * input; + @SuppressWarnings("unused") + public static final EasingFunction EaseOutExpo = new EasingFunction() { + public float getInterpolation(float input) { + return (input == 1f) ? 1f : (-(float) Math.pow(2f, -10f * (input + 1f))); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutExpo = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1f) { + return 1f; } - }; - - public static final EasingFunction EaseOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (position * position * position + 1.f); - // } - - @Override - public float getInterpolation(float input) { - input--; - return (input * input * input + 1.f); - } - }; - - public static final EasingFunction EaseInOutCubic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * position * position * position; - // } - // position -= 2.f; - // return 0.5f * (position * position * position + 2.f); - // } - - @Override - public float getInterpolation(float input) { - - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position; - } - position -= 2.f; - return 0.5f * (position * position * position + 2.f); - } - }; - - public static final EasingFunction EaseInQuart = new EasingFunction() { - - public float getInterpolation(float input) { - return input * input * input * input; + + input *= 2f; + if (input < 1f) { + return 0.5f * (float) Math.pow(2f, 10f * (input - 1f)); } - }; + return 0.5f * (-(float) Math.pow(2f, -10f * --input) + 2f); + } + }; - public static final EasingFunction EaseOutQuart = new EasingFunction() { + @SuppressWarnings("unused") + public static final EasingFunction EaseInCirc = new EasingFunction() { + public float getInterpolation(float input) { + return -((float) Math.sqrt(1f - input * input) - 1f); + } + }; - public float getInterpolation(float input) { - input--; - return -(input * input * input * input - 1f); - } - }; - - public static final EasingFunction EaseInOutQuart = new - EasingFunction() { - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) { - return 0.5f * position * position * position * position; - } - position -= 2.f; - return -0.5f * (position * position * position * position - 2.f); - } - }; - - public static final EasingFunction EaseInSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -(float) Math.cos(position * (Math.PI / 2.f)) + 1.f; - // } - @Override - public float getInterpolation(float input) { - return -(float) Math.cos(input * (Math.PI / 2.f)) + 1.f; + @SuppressWarnings("unused") + public static final EasingFunction EaseOutCirc = new EasingFunction() { + public float getInterpolation(float input) { + input--; + return (float) Math.sqrt(1f - input * input); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutCirc = new EasingFunction() { + public float getInterpolation(float input) { + input *= 2f; + if (input < 1f) { + return -0.5f * ((float) Math.sqrt(1f - input * input) - 1f); } - }; - - public static final EasingFunction EaseOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return (float) Math.sin(position * (Math.PI / 2.f)); - // } - @Override - public float getInterpolation(float input) { - return (float) Math.sin(input * (Math.PI / 2.f)); + return 0.5f * ((float) Math.sqrt(1f - (input -= 2f) * input) + 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1) { + return 1f; } - }; - - public static final EasingFunction EaseInOutSine = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -0.5f * ((float) Math.cos(Math.PI * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -0.5f * ((float) Math.cos(Math.PI * input) - 1.f); + + float p = 0.3f; + float s = p / DOUBLE_PI * (float) Math.asin(1f); + return -((float) Math.pow(2f, 10f * (input -= 1f)) + *(float) Math.sin((input - s) * DOUBLE_PI / p)); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; + } else if (input == 1) { + return 1f; } - }; - - public static final EasingFunction EaseInExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (elapsed - // / (float) duration - 1.f)); - // } - @Override - public float getInterpolation(float input) { - return (input == 0) ? 0.f : (float) Math.pow(2.f, 10.f * (input - 1.f)); + + float p = 0.3f; + float s = p / DOUBLE_PI * (float) Math.asin(1f); + return 1f + + (float) Math.pow(2f, -10f * input) + * (float) Math.sin((input - s) * DOUBLE_PI / p); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutElastic = new EasingFunction() { + public float getInterpolation(float input) { + if (input == 0) { + return 0f; } - }; - - public static final EasingFunction EaseOutExpo = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return (elapsed == duration) ? 1.f : (-(float) Math.pow(2.f, -10.f * - // elapsed - // / (float) duration) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - return (input == 1f) ? 1.f : (-(float) Math.pow(2.f, -10.f * (input + 1.f))); + + input *= 2f; + if (input == 2) { + return 1f; } - }; - - public static final EasingFunction EaseInOutExpo = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // if (elapsed == duration) - // { - // return 1.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - // } - // return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + - // 2.f); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - if (input == 1f) - { - return 1.f; - } - - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (float) Math.pow(2.f, 10.f * (position - 1.f)); - } - return 0.5f * (-(float) Math.pow(2.f, -10.f * --position) + 2.f); - } - }; - - public static final EasingFunction EaseInCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // return -((float) Math.sqrt(1.f - position * position) - 1.f); - // } - - @Override - public float getInterpolation(float input) { - return -((float) Math.sqrt(1.f - input * input) - 1.f); + + float p = 1f / 0.45f; + float s = 0.45f / DOUBLE_PI * (float) Math.asin(1f); + if (input < 1f) { + return -0.5f + * ((float) Math.pow(2f, 10f * (input -= 1f)) + * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p)); } - }; - - public static final EasingFunction EaseOutCirc = new EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // position--; - // return (float) Math.sqrt(1.f - position * position); - // } - @Override - public float getInterpolation(float input) { - input--; - return (float) Math.sqrt(1.f - input * input); + return 1f + 0.5f + * (float) Math.pow(2f, -10f * (input -= 1f)) + * (float) Math.sin((input * 1f - s) * DOUBLE_PI * p); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInBack = new EasingFunction() { + public float getInterpolation(float input) { + final float s = 1.70158f; + return input * input * ((s + 1f) * input - s); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutBack = new EasingFunction() { + public float getInterpolation(float input) { + final float s = 1.70158f; + input--; + return (input * input * ((s + 1f) * input + s) + 1f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutBack = new EasingFunction() { + public float getInterpolation(float input) { + float s = 1.70158f; + input *= 2f; + if (input < 1f) { + return 0.5f * (input * input * (((s *= (1.525f)) + 1f) * input - s)); } - }; - - public static final EasingFunction EaseInOutCirc = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return -0.5f * ((float) Math.sqrt(1.f - position * position) - // - 1.f); - // } - // return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * - // position) - // + 1.f); - // } - - @Override - public float getInterpolation(float input) { - float position = input / 0.5f; - if (position < 1.f) - { - return -0.5f * ((float) Math.sqrt(1.f - position * position) - 1.f); - } - return 0.5f * ((float) Math.sqrt(1.f - (position -= 2.f) * position) - + 1.f); - } - }; - - public static final EasingFunction EaseInElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * - // (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - return -((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - Math - .sin((position - s) * (2.f * Math.PI) / p)); - } - }; - - public static final EasingFunction EaseOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (float) duration; - // if (position == 1) - // { - // return 1.f; - // } - // - // float p = duration * .3f; - // float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - // return (float) Math.pow(2, -10 * position) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) + - // 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input; - if (position == 1) - { - return 1.f; - } - - float p = .3f; - float s = p / (2 * (float) Math.PI) * (float) Math.asin(1.f); - return (float) Math.pow(2, -10 * position) - * (float) Math.sin((position - s) * (2.f * Math.PI) / p) + - 1.f; - } - }; - - public static final EasingFunction EaseInOutElastic = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed == 0) - // { - // return 0.f; - // } - // - // float position = elapsed / (duration / 2.f); - // if (position == 2) - // { - // return 1.f; - // } - // - // float p = duration * (.3f * 1.5f); - // float s = p / (2.f * (float) Math.PI) * (float) - // Math.asin(1.f); - // if (position < 1.f) - // { - // return -.5f - // * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) - // Math - // .sin((position * duration - s) * (2.f * Math.PI) / p)); - // } - // return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - // * (float) Math.sin((position * duration - s) * (2.f * - // Math.PI) / p) * - // .5f - // + 1.f; - // } - - @Override - public float getInterpolation(float input) { - if (input == 0) - { - return 0.f; - } - - float position = input / 0.5f; - if (position == 2) - { - return 1.f; - } - - float p = (.3f * 1.5f); - float s = p / (2.f * (float) Math.PI) * (float) Math.asin(1.f); - if (position < 1.f) - { - return -.5f - * ((float) Math.pow(2.f, 10.f * (position -= 1.f)) * (float) Math - .sin((position * 1f - s) * (2.f * Math.PI) / p)); - } - return (float) Math.pow(2.f, -10.f * (position -= 1.f)) - * (float) Math.sin((position * 1f - s) * (2.f * Math.PI) / p) * - .5f - + 1.f; - } - }; - - public static final EasingFunction EaseInBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // return position * position * ((s + 1.f) * position - s); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - return position * position * ((s + 1.f) * position - s); + return 0.5f * ((input -= 2f) * input * (((s *= (1.525f)) + 1f) * input + s) + 2f); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInBounce = new EasingFunction() { + public float getInterpolation(float input) { + return 1f - EaseOutBounce.getInterpolation(1f - input); + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseOutBounce = new EasingFunction() { + public float getInterpolation(float input) { + float s = 7.5625f; + if (input < (1f / 2.75f)) { + return s * input * input; + } else if (input < (2f / 2.75f)) { + return s * (input -= (1.5f / 2.75f)) * input + 0.75f; + } else if (input < (2.5f / 2.75f)) { + return s * (input -= (2.25f / 2.75f)) * input + 0.9375f; } - }; - - public static final EasingFunction EaseOutBack = new EasingFunction() - { - // @Override - // public float ease(long elapsed, long duration) { - // final float s = 1.70158f; - // float position = elapsed / (float) duration; - // position--; - // return (position * position * ((s + 1.f) * position + s) + 1.f); - // } - - @Override - public float getInterpolation(float input) { - final float s = 1.70158f; - float position = input; - position--; - return (position * position * ((s + 1.f) * position + s) + 1.f); + return s * (input -= (2.625f / 2.75f)) * input + 0.984375f; + } + }; + + @SuppressWarnings("unused") + public static final EasingFunction EaseInOutBounce = new EasingFunction() { + public float getInterpolation(float input) { + if (input < 0.5f) { + return EaseInBounce.getInterpolation(input * 2f) * 0.5f; } - }; - - public static final EasingFunction EaseInOutBack = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float s = 1.70158f; - // float position = elapsed / (duration / 2.f); - // if (position < 1.f) - // { - // return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) - // * - // position - s)); - // } - // return 0.5f * ((position -= 2.f) * position - // * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - // } - - @Override - public float getInterpolation(float input) { - float s = 1.70158f; - float position = input / 0.5f; - if (position < 1.f) - { - return 0.5f * (position * position * (((s *= (1.525f)) + 1.f) * - position - s)); - } - return 0.5f * ((position -= 2.f) * position - * (((s *= (1.525f)) + 1.f) * position + s) + 2.f); - } - }; - - public static final EasingFunction EaseInBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // return 1.f - EaseOutBounce.ease(duration - elapsed, - // duration); - // } - - @Override - public float getInterpolation(float input) { - return 1.f - EaseOutBounce.getInterpolation(1f - input); - } - }; - - public static final EasingFunction EaseOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // float position = elapsed / (float) duration; - // if (position < (1.f / 2.75f)) - // { - // return (7.5625f * position * position); - // } - // else if (position < (2.f / 2.75f)) - // { - // return (7.5625f * (position -= (1.5f / 2.75f)) * position + - // .75f); - // } - // else if (position < (2.5f / 2.75f)) - // { - // return (7.5625f * (position -= (2.25f / 2.75f)) * position + - // .9375f); - // } - // else - // { - // return (7.5625f * (position -= (2.625f / 2.75f)) * position + - // .984375f); - // } - // } - - @Override - public float getInterpolation(float input) { - float position = input; - if (position < (1.f / 2.75f)) - { - return (7.5625f * position * position); - } - else if (position < (2.f / 2.75f)) - { - return (7.5625f * (position -= (1.5f / 2.75f)) * position + .75f); - } - else if (position < (2.5f / 2.75f)) - { - return (7.5625f * (position -= (2.25f / 2.75f)) * position + .9375f); - } - else - { - return (7.5625f * (position -= (2.625f / 2.75f)) * position + - .984375f); - } - } - }; - - public static final EasingFunction EaseInOutBounce = new - EasingFunction() { - // @Override - // public float ease(long elapsed, long duration) { - // if (elapsed < duration / 2.f) - // { - // return EaseInBounce.ease(elapsed * 2, duration) * .5f; - // } - // return EaseOutBounce.ease(elapsed * 2 - duration, duration) * - // .5f + - // .5f; - // } - - @Override - public float getInterpolation(float input) { - if (input < 0.5f) - { - return EaseInBounce.getInterpolation(input * 2) * .5f; - } - return EaseOutBounce.getInterpolation(input * 2 - 1f) * .5f + - .5f; - } - }; + return EaseOutBounce.getInterpolation(input * 2f - 1f) * 0.5f + 0.5f; + } + }; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java deleted file mode 100644 index 98d934da23..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/EasingFunction.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.mikephil.charting.animation; - -import android.animation.TimeInterpolator; -import android.annotation.SuppressLint; - -/** - * Interface for creating custom made easing functions. Uses the - * TimeInterpolator interface provided by Android. - */ -@SuppressLint("NewApi") -public interface EasingFunction extends TimeInterpolator { - - @Override - float getInterpolation(float input); -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index ea26f2cfca..35ec2ec1e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -3,7 +3,6 @@ import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; import android.graphics.Bitmap; @@ -15,8 +14,10 @@ import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.os.Build; import android.os.Environment; import android.provider.MediaStore.Images; +import android.support.annotation.RequiresApi; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -26,7 +27,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.animation.EasingFunction; +import com.github.mikephil.charting.animation.Easing.EasingFunction; import com.github.mikephil.charting.components.Description; import com.github.mikephil.charting.components.IMarker; import com.github.mikephil.charting.components.Legend; @@ -60,7 +61,6 @@ * * @author Philipp Jahoda */ -@SuppressLint("NewApi") public abstract class Chart>> extends ViewGroup implements ChartInterface { @@ -209,9 +209,9 @@ protected void init() { setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_HARDWARE, null); - if (android.os.Build.VERSION.SDK_INT < 11) + if (Build.VERSION.SDK_INT < 11) { mAnimator = new ChartAnimator(); - else + } else { mAnimator = new ChartAnimator(new AnimatorUpdateListener() { @Override @@ -220,6 +220,7 @@ public void onAnimationUpdate(ValueAnimator animation) { postInvalidate(); } }); + } // initialize the utils Utils.init(getContext()); @@ -836,11 +837,27 @@ public void setDragDecelerationFrictionCoef(float newValue) { * @param easingX a custom easing function to be used on the animation phase * @param easingY a custom easing function to be used on the animation phase */ + @RequiresApi(11) public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easingX, EasingFunction easingY) { mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); } + /** + * Animates the drawing / rendering of the chart on both x- and y-axis with + * the specified animation time. If animate(...) is called, no further + * calling of invalidate() is necessary to refresh the chart. ANIMATIONS + * ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. + * + * @param durationMillisX + * @param durationMillisY + * @param easing a custom easing function to be used on the animation phase + */ + @RequiresApi(11) + public void animateXY(int durationMillisX, int durationMillisY, EasingFunction easing) { + mAnimator.animateXY(durationMillisX, durationMillisY, easing); + } + /** * Animates the rendering of the chart on the x-axis with the specified * animation time. If animate(...) is called, no further calling of @@ -850,6 +867,7 @@ public void animateXY(int durationMillisX, int durationMillisY, EasingFunction e * @param durationMillis * @param easing a custom easing function to be used on the animation phase */ + @RequiresApi(11) public void animateX(int durationMillis, EasingFunction easing) { mAnimator.animateX(durationMillis, easing); } @@ -863,6 +881,7 @@ public void animateX(int durationMillis, EasingFunction easing) { * @param durationMillis * @param easing a custom easing function to be used on the animation phase */ + @RequiresApi(11) public void animateY(int durationMillis, EasingFunction easing) { mAnimator.animateY(durationMillis, easing); } @@ -883,7 +902,11 @@ public void animateY(int durationMillis, EasingFunction easing) { * @param durationMillisY * @param easingX a predefined easing option * @param easingY a predefined easing option + * + * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} + * @see #animateXY(int, int, EasingFunction, EasingFunction) */ + @Deprecated public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, Easing.EasingOption easingY) { mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); @@ -897,7 +920,11 @@ public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOpt * * @param durationMillis * @param easing a predefined easing option + * + * @deprecated Use {@link #animateX(int, EasingFunction)} + * @see #animateX(int, EasingFunction) */ + @Deprecated public void animateX(int durationMillis, Easing.EasingOption easing) { mAnimator.animateX(durationMillis, easing); } @@ -910,7 +937,11 @@ public void animateX(int durationMillis, Easing.EasingOption easing) { * * @param durationMillis * @param easing a predefined easing option + * + * @deprecated Use {@link #animateY(int, EasingFunction)} + * @see #animateY(int, EasingFunction) */ + @Deprecated public void animateY(int durationMillis, Easing.EasingOption easing) { mAnimator.animateY(durationMillis, easing); } @@ -929,6 +960,7 @@ public void animateY(int durationMillis, Easing.EasingOption easing) { * * @param durationMillis */ + @RequiresApi(11) public void animateX(int durationMillis) { mAnimator.animateX(durationMillis); } @@ -941,6 +973,7 @@ public void animateX(int durationMillis) { * * @param durationMillis */ + @RequiresApi(11) public void animateY(int durationMillis) { mAnimator.animateY(durationMillis); } @@ -954,6 +987,7 @@ public void animateY(int durationMillis) { * @param durationMillisX * @param durationMillisY */ + @RequiresApi(11) public void animateXY(int durationMillisX, int durationMillisY) { mAnimator.animateXY(durationMillisX, durationMillisY); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index d403a752cc..618de18a34 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -12,6 +12,7 @@ import android.view.MotionEvent; import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.animation.Easing.EasingFunction; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; @@ -477,7 +478,7 @@ public float getYChartMin() { * @param toangle */ @SuppressLint("NewApi") - public void spin(int durationmillis, float fromangle, float toangle, Easing.EasingOption easing) { + public void spin(int durationmillis, float fromangle, float toangle, EasingFunction easing) { if (android.os.Build.VERSION.SDK_INT < 11) return; @@ -487,7 +488,7 @@ public void spin(int durationmillis, float fromangle, float toangle, Easing.Easi ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, toangle); spinAnimator.setDuration(durationmillis); - spinAnimator.setInterpolator(Easing.getEasingFunctionFromOption(easing)); + spinAnimator.setInterpolator(easing); spinAnimator.addUpdateListener(new AnimatorUpdateListener() { From 5519c5170df03b3dbae893e7d93979809d0d29b0 Mon Sep 17 00:00:00 2001 From: Mick A Date: Mon, 30 Apr 2018 17:42:35 -0600 Subject: [PATCH 1297/1390] fix(docs): Broken Contributing link --- ISSUE_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index b87cd42091..e8699b3aa4 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -- [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) file before posting this issue. +- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. ### The problem From 11bf7aa8128b705a77bcbb821d804217d557d5de Mon Sep 17 00:00:00 2001 From: Mick A Date: Tue, 1 May 2018 22:57:40 -0600 Subject: [PATCH 1298/1390] Update issue templates --- .github/ISSUE_TEMPLATE/Bug_report.md | 31 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/Feature_request.md | 19 ++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/Feature_request.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md new file mode 100644 index 0000000000..72ab35658a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -0,0 +1,31 @@ +--- +name: Bug report +about: Create a report to help us improve + +--- + +- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Device (please complete the following information):** + - Device: [e.g. Google Pixel] + - Android Version [e.g. 7.0] + - Libaray Version (e.g. 3.0.3) + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md new file mode 100644 index 0000000000..85bcdbea3c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project + +--- + +- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From a7eb395b8197e6c211530974a0563bbc7fe91725 Mon Sep 17 00:00:00 2001 From: Mick A Date: Tue, 1 May 2018 22:59:06 -0600 Subject: [PATCH 1299/1390] Downgrade ISSUE_TEMPLATE.md to generic issue --- ISSUE_TEMPLATE.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index e8699b3aa4..65e0e5d643 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1,13 +1 @@ - [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. - -### The problem - -What is the problem, what is going wrong? Is this a bug, question, or a feature request? - -### What should happen - -What do you think _should_ happen? - -### Addition information - -You can add addition info here, like code snippets or references. You can also attach files like images or stacktraces. Images that are no taller than 500px can be put inside the issue text, but please post larger images and stacktraces as links to a [Gist](https://help.github.com/articles/creating-gists/) or attach the file by clicking "Attach files" below, so that we don't have to scroll all the way down a page to respond to you. From 00e284c043617ae3c8bf81ace0544cfe52ce348b Mon Sep 17 00:00:00 2001 From: Mick A Date: Tue, 1 May 2018 23:02:01 -0600 Subject: [PATCH 1300/1390] Update Bug_report.md quick fix --- .github/ISSUE_TEMPLATE/Bug_report.md | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 72ab35658a..a816dd5bed 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -7,20 +7,16 @@ about: Create a report to help us improve - [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. **Describe the bug** + A clear and concise description of what the bug is. -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error +**Screenshots** + +If applicable, add screenshots to help explain your problem. **Expected behavior** -A clear and concise description of what you expected to happen. -**Screenshots** -If applicable, add screenshots to help explain your problem. +A clear and concise description of what you expected to happen. **Device (please complete the following information):** - Device: [e.g. Google Pixel] @@ -28,4 +24,5 @@ If applicable, add screenshots to help explain your problem. - Libaray Version (e.g. 3.0.3) **Additional context** -Add any other context about the problem here. + +Add any other context about the problem here. If you have source code demonstrating this bug, create a [Gist](https://help.github.com/articles/creating-gists/) and link to it. From 1ff676ecaf6dfe96e862f6cd6726d9e323e6c11b Mon Sep 17 00:00:00 2001 From: Mick A Date: Wed, 2 May 2018 00:44:47 -0600 Subject: [PATCH 1301/1390] Update CONTRIBUTING.md Condensed CONTRIBUTING and added helpful reference links. And cake! --- CONTRIBUTING.md | 87 +++++++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2e4d5b866c..98cf0ab89b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,49 +1,66 @@ +> ### Notice +> *Before you continue, this is the* **ANDROID** *library. If you have an* **iOS** *device, please go here instead*: +> +> – https://github.com/danielgindi/Charts +> +> They might tell you to come back here, if they do, listen to them and ignore this notice. + # How to contribute -Bug-fixes and features often come from users of the MPAndroidChart library and improve it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we -need contributors to follow so that we can have a chance of keeping on -top of things. +Bug-fixes and features often come from users of the MPAndroidChart library and improve it greatly. We want to keep it as easy as possible to contribute changes that improve the experience for users all around the world. There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things. + +## Creating Issues + +There are two main issue templates, one for bugs and another for feature requests. Please use them! You're issue will be much easier to understand, and bugs easier to fix, if you follow the templates. If your issue doesn't fit into those, just use the generic template. -## Simple issues and bug reports +Search existing [issues] to see if your bug has already been reported or if a feature request already exists. Don't forget to remove `is:open` so you see all the issues! If you find that one already exists, use reactions to show how much you care! -If you are reporting a bug which can be observed visually, please add to your issue either: +## Making Pull Requests -* Screenshots, if the bug is easily explainable -* A working sample project that we can compile, run, and immediately observe the issue +Careful! If you fail to follow these guidlines, you're pull request may be closed, *even if it's really awesome*. -## Getting Started with Contributions + 0. **Search** open [pull requests] AND existing [issues] to make sure what you want to do isn't already being worked on or already has an open pull request. + 1. **Fork** the repository + 1. **Create** a new branch based on `master`, and name it according to your changes + 1. **Add** your commits, they MUST follow the [Commit Style](#commit-style) below + 1. **Test** your changes by actually running the example app, or create a new example + 1. **Create** a pull request, following the auto-generated template + 1. ??? + 1. Profit :money_with_wings: + +You are encouraged to use [GitHub Desktop] to inspect your code changes before committing them. It can reveal small changes that might have gone unnoticed, and would be requested for removal before merging. -* Make sure you have a [GitHub account](https://github.com/signup/free) -* Submit a ticket for your issue, assuming one does not already exist. - * Clearly describe the issue including steps to reproduce when it is a bug. - * Make sure you fill in the earliest version (or commit number) that you know has the issue. -* Fork the repository on GitHub +Check out [#3975](https://github.com/PhilJay/MPAndroidChart/pull/3975) for an example of a good-made-better pull request. -## Making Changes +## Commit Style -* Create a topic branch from where you want to base your work. This is usually the master branch. -* Make commits of logical units. -* Make sure your code conforms to the code style around it. It's easy, just look around! -* If you have made changes back and forth, or have made merges, your commit history might look messy and hard to understand. A single issue or change should still be in one commit. So please squash those commits together and rebase them however you need to - to make our lives easier when reading it later. -* Check for unnecessary whitespace with `git diff --check` before committing. -* Make sure your commit messages are in the proper format. + * **Make commits of logical units** + Don't load your commits with tons of changes, this makes it hard to follow what is happening. However, if you have done a lot of work, and there are commits and merges all over the place, squash them down into fewer commits. + + * **Conform to the code style** + It's easy, just look around! + + * **Write good commit messages** + You may prefer [Tim Pope's style], you might like the [commitizen-friendly] way. Regardless of the color you pick, you MUST stay within the lines! + ``` +The commit title CANNOT exceed 50 characters -```` - First line must be up to 50 chars (Fixes #1234) +The body of the message comes after an empty new line, and describes the +changes more thoroughly. If the change is obvious and self-explanatory +from the title, you can omit the body. You should describe all changes +if many were made, or maybe some trickery that only code wizards can +understand. - The first line should be a short statement as to what have changed, and should also include an issue number, prefixed with a dash. - The body of the message comes after an empty new line, and describes the changes - more thoroughly, especially if there was a special case handled there, - or maybe some trickery that only code wizards can understand. -```` +Be polite and wrap your lines to 72 characters, but if you prefer going +to 100 characters then I guess we can't stop you. +``` -* Make sure you have tested your changes well. -* If your changes could theoretically affect some other component or case, which you do not necessarily use, you still have to test it. -* Create a Pull Request from your topic branch to the relevant branch in the main repo. If you go to the main repo of the framework, you'll see a big green button which pretty much prepares the PR for you. You just have to hit it. +## Final Notes -## Making Trivial Changes +Thanks for reading the contributing file! Have some cake! :cake: -For changes of a trivial nature to comments and documentation, it is not -always necessary to create a new ticket. In this case, it is -appropriate to start the first line of a commit with '(doc)' instead of -a ticket number. Even the default commit message the GitHub generates is fine with us. +[issues]: https://github.com/PhilJay/MPAndroidChart/issues +[pull requests]: https://github.com/PhilJay/MPAndroidChart/pulls +[GitHub Desktop]: https://desktop.github.com/ +[Tim Pope's style]: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html +[commitizen-friendly]: https://github.com/commitizen/cz-cli From 9b9d2a68cb1024973e77fb4710aa8747d05b618b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 3 May 2018 16:22:32 +0200 Subject: [PATCH 1302/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 063680ed0d..8ffafdc4c4 100644 --- a/README.md +++ b/README.md @@ -209,4 +209,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [tony](https://github.com/tonypatino-monoclesociety) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. +**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [tony](https://github.com/tonypatino-monoclesociety), [almic](https://github.com/almic) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. From 689d484615a5e587988c08dc7ef5579d29ace5a0 Mon Sep 17 00:00:00 2001 From: almic Date: Thu, 3 May 2018 08:37:00 -0600 Subject: [PATCH 1303/1390] Delete lingering MyEasingFunction.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I made the decision to remove this file instead of updating it, as I'm sure most will instead prefer to look at the actual Easing class. If you miss this example class... ¯\_(ツ)_/¯ --- .../custom/MyEasingFunction.java | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java deleted file mode 100644 index e874a57ab6..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyEasingFunction.java +++ /dev/null @@ -1,18 +0,0 @@ - -package com.xxmassdeveloper.mpchartexample.custom; - -import com.github.mikephil.charting.animation.EasingFunction; - -/** - * Example of a custom made animation EasingFunction. - * - * @author Philipp Jahoda - */ -public class MyEasingFunction implements EasingFunction { - - @Override - public float getInterpolation(float input) { - // do awesome stuff here, this is just linear easing - return input; - } -} From e4ba3cdc20555b5f7cd793e614ee13406a7605ec Mon Sep 17 00:00:00 2001 From: Anirut Teerabut Date: Fri, 4 May 2018 04:21:26 +0700 Subject: [PATCH 1304/1390] - multiple gradient color --- .../mpchartexample/BarChartActivity.java | 30 +++++++++++++- .../mikephil/charting/data/BaseDataSet.java | 39 +++++++++++++++++++ .../interfaces/datasets/IDataSet.java | 23 +++++++++++ .../charting/model/GradientColor.java | 28 +++++++++++++ .../charting/renderer/BarChartRenderer.java | 28 +++++++++++++ 5 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 5772359773..2707d0bd51 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.graphics.RectF; import android.os.Bundle; +import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -16,7 +17,6 @@ import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -31,6 +31,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; @@ -39,6 +40,7 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class BarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -264,7 +266,31 @@ private void setData(int count, float range) { set1.setDrawIcons(false); - set1.setColors(ColorTemplate.MATERIAL_COLORS); +// set1.setColors(ColorTemplate.MATERIAL_COLORS); + + /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); + int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); + set1.setGradientColor(startColor, endColor);*/ + + int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); + int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); + int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); + int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); + int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); + int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); + int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); + int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); + + List gradientColors = new ArrayList<>(); + gradientColors.add(new GradientColor(startColor1, endColor1)); + gradientColors.add(new GradientColor(startColor2, endColor2)); + gradientColors.add(new GradientColor(startColor3, endColor3)); + gradientColors.add(new GradientColor(startColor4, endColor4)); + gradientColors.add(new GradientColor(startColor5, endColor5)); + + set1.setGradientColors(gradientColors); ArrayList dataSets = new ArrayList(); dataSets.add(set1); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 3869a00895..1b9d97850a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.model.GradientColor; import java.lang.annotation.Documented; import java.lang.annotation.Inherited; @@ -31,6 +32,10 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; + protected GradientColor gradientColor = null; + + protected List gradientColors = null; + /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -144,6 +149,21 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } + @Override + public GradientColor getGradientColor() { + return gradientColor; + } + + @Override + public List getGradientColors() { + return gradientColors; + } + + @Override + public GradientColor getGradientColor(int index) { + return gradientColors.get(index % gradientColors.size()); + } + /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -219,6 +239,25 @@ public void setColor(int color) { mColors.add(color); } + /** + * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. + * + * @param startColor + * @param endColor + */ + public void setGradientColor(int startColor, int endColor) { + gradientColor = new GradientColor(startColor, endColor); + } + + /** + * Sets the start and end color for gradient colors, ONLY color that should be used for this DataSet. + * + * @param gradientColors + */ + public void setGradientColors(List gradientColors) { + this.gradientColors = gradientColors; + } + /** * Sets a color with a specific alpha value. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index fd8af7064b..f64db706e0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; +import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -285,6 +286,28 @@ public interface IDataSet { */ int getColor(); + /** + * Returns the Gradient color model + * + * @return + */ + GradientColor getGradientColor(); + + /** + * Returns the Gradient colors + * + * @return + */ + List getGradientColors(); + + /** + * Returns the Gradient colors + * + * @param index + * @return + */ + GradientColor getGradientColor(int index); + /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java new file mode 100644 index 0000000000..1162c01198 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java @@ -0,0 +1,28 @@ +package com.github.mikephil.charting.model; + +public class GradientColor { + + private int startColor; + private int endColor; + + public GradientColor(int startColor, int endColor) { + this.startColor = startColor; + this.endColor = endColor; + } + + public int getStartColor() { + return startColor; + } + + public void setStartColor(int startColor) { + this.startColor = startColor; + } + + public int getEndColor() { + return endColor; + } + + public void setEndColor(int endColor) { + this.endColor = endColor; + } +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index f17761234e..d3f71af02c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -19,6 +19,8 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; +import android.graphics.LinearGradient; +import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -163,6 +165,32 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mRenderPaint.setColor(dataSet.getColor(j / 4)); } + if (dataSet.getGradientColor() != null) { + GradientColor gradientColor = dataSet.getGradientColor(); + mRenderPaint.setShader( + new LinearGradient( + buffer.buffer[j], + buffer.buffer[j + 3], + buffer.buffer[j], + buffer.buffer[j + 1], + gradientColor.getStartColor(), + gradientColor.getEndColor(), + android.graphics.Shader.TileMode.MIRROR)); + } + + if (dataSet.getGradientColors() != null) { + mRenderPaint.setShader( + new LinearGradient( + buffer.buffer[j], + buffer.buffer[j + 3], + buffer.buffer[j], + buffer.buffer[j + 1], + dataSet.getGradientColor(j / 4).getStartColor(), + dataSet.getGradientColor(j / 4).getEndColor(), + android.graphics.Shader.TileMode.MIRROR)); + } + + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint); From 03c538fc34a945a27a1a636410b0819e56a7c355 Mon Sep 17 00:00:00 2001 From: almic Date: Sun, 6 May 2018 00:02:06 -0600 Subject: [PATCH 1305/1390] docs(templates): Update Issue & PR templates I've updated the issue and pull request templates, again. This time I looked to the node.js request library for inspiration. It's no secret that this project has been attracting a LOT of very low-quality issues. Almost all are asking questions that can be easily answered if the person looked at the example project or the wiki. Specifically, the new Support_help.md file. This file will hopefully bait these low-quality support questions and reduce the number of opened issues regarding debugging or support significantly. I've updated the default ISSUE_TEMPLATE.md to be a copy of Bug_report.md to force people to read that notice text if they decide to not choose any of the templates. --- .github/ISSUE_TEMPLATE/Bug_report.md | 40 +++++++++++++++-------- .github/ISSUE_TEMPLATE/Feature_request.md | 26 +++++++++++---- .github/ISSUE_TEMPLATE/Support_help.md | 24 ++++++++++++++ ISSUE_TEMPLATE.md | 38 ++++++++++++++++++++- PULL_REQUEST_TEMPLATE.md | 21 ++++++------ 5 files changed, 119 insertions(+), 30 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/Support_help.md diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index a816dd5bed..496d0a0d8d 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -1,28 +1,42 @@ --- -name: Bug report -about: Create a report to help us improve +name: Bugs +about: Create a bug report to help us improve --- -- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. + -**Expected behavior** +**Summary** + -A clear and concise description of what you expected to happen. +**Expected Behavior** + + +**Possible Solution** + + **Device (please complete the following information):** - Device: [e.g. Google Pixel] - Android Version [e.g. 7.0] - - Libaray Version (e.g. 3.0.3) - -**Additional context** + - Library Version (e.g. 3.0.3) -Add any other context about the problem here. If you have source code demonstrating this bug, create a [Gist](https://help.github.com/articles/creating-gists/) and link to it. +**Additional Context** + diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 85bcdbea3c..823b940961 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -1,19 +1,33 @@ --- -name: Feature request +name: Feature Request about: Suggest an idea for this project --- -- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. + **Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + **Describe the solution you'd like** -A clear and concise description of what you want to happen. + **Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. + **Additional context** -Add any other context or screenshots about the feature request here. + diff --git a/.github/ISSUE_TEMPLATE/Support_help.md b/.github/ISSUE_TEMPLATE/Support_help.md new file mode 100644 index 0000000000..64c87763df --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Support_help.md @@ -0,0 +1,24 @@ +--- +name: Support +about: I need help! + +--- + +# *STOP RIGHT THERE!* + +Issues are ***NOT*** for getting help, only for reporting bugs and feature requests. + +Search open and closed issues to see if your question already has an answer. However, **do not create a new issue.** + +Instead, do the following: + +1. Download the [Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) and check out the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample). 90% of the time there is an example that does exactly what you are trying to do. + +1. Look at the [Wiki](https://github.com/PhilJay/MPAndroidChart/wiki) for the official documentation for MPAndroidChart. You can also browse the [javadoc](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for a more detailed tutorial of the API. + +1. Go to [StackOverflow](https://stackoverflow.com/questions/tagged/mpandroidchart) and ask your questions there. The community will be much more helpful and willing to offer guidance. + + +### You have been warned! + +From now on, any issues asking for help will get closed with a link to this file. diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index 65e0e5d643..49ed0dfc1d 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -1 +1,37 @@ -- [ ] I have read the [CONTRIBUTING](https://github.com/PhilJay/MPAndroidChart/blob/master/CONTRIBUTING.md) file before posting this issue. + + +**Summary** + + +**Expected Behavior** + + +**Possible Solution** + + + +**Device (please complete the following information):** + - Device: [e.g. Google Pixel] + - Android Version [e.g. 7.0] + - Library Version (e.g. 3.0.3) + +**Additional Context** + diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index fb64ddf8be..f65a30b178 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,14 +1,15 @@ -- [ ] I have read the [CONTRIBUTING](CONTRIBUTING.md) file before posting submitting this pull request. +## PR Checklist: +- [ ] I have tested this extensively and it does not break any existing behavior. +- [ ] I have added/updated examples and tests for any new behavior. +- [ ] If this is a significant change, an issue has already been created where the problem / solution was discussed: [N/A, or add link to issue here] + -Before describing this pull request, please prefix the title with a topic from the list: -`Feature`, `Fix`, `Style` -### [Feature / Fix / Style] (choose ONE) +## PR Description + -What will this PR do? Remember that you don't need to explain everything, let the changes speak for itself. + -If a bug fix, reference any issues that this fixes, like so: "fixes #99" - -### Why should this be merged? - -If needed, further explain this PR and why it should be merged. If the changes are too broad, your pull request may be denied for having too much in it. It may also be denied if the commits aren't properly formatted. + From 9583a18b84e88289774c9713d65764b1bb7c40d7 Mon Sep 17 00:00:00 2001 From: almic Date: Sun, 6 May 2018 00:29:31 -0600 Subject: [PATCH 1306/1390] chore(template): Move templates to .github folder --- ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md | 0 PULL_REQUEST_TEMPLATE.md => .github/PULL_REQUEST_TEMPLATE.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename ISSUE_TEMPLATE.md => .github/ISSUE_TEMPLATE.md (100%) rename PULL_REQUEST_TEMPLATE.md => .github/PULL_REQUEST_TEMPLATE.md (100%) diff --git a/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md similarity index 100% rename from ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE.md diff --git a/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md similarity index 100% rename from PULL_REQUEST_TEMPLATE.md rename to .github/PULL_REQUEST_TEMPLATE.md From 7abc9cd6696f78c77068ffc278793594b33497fe Mon Sep 17 00:00:00 2001 From: RobertZagorski Date: Tue, 8 May 2018 16:19:09 +0200 Subject: [PATCH 1307/1390] Update and reorganise copy data sets methods (Fix for #1604). Copying class properties is always done in protected copy method. --- .../LineChartActivityColored.java | 2 +- .../mikephil/charting/data/BarDataSet.java | 27 +++-- .../BarLineScatterCandleBubbleDataSet.java | 17 ++- .../mikephil/charting/data/BaseDataSet.java | 43 +++++--- .../mikephil/charting/data/BubbleDataSet.java | 18 ++-- .../mikephil/charting/data/CandleDataSet.java | 35 +++--- .../mikephil/charting/data/DataSet.java | 8 ++ .../mikephil/charting/data/LineDataSet.java | 42 ++++---- .../charting/data/LineRadarDataSet.java | 9 ++ .../data/LineScatterCandleRadarDataSet.java | 8 ++ .../mikephil/charting/data/PieDataSet.java | 102 +++++++++--------- .../mikephil/charting/data/RadarDataSet.java | 67 +++++------- .../charting/data/ScatterDataSet.java | 50 ++++----- 13 files changed, 238 insertions(+), 190 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 68bba4b458..22984b4b6e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -53,7 +53,7 @@ protected void onCreate(Bundle savedInstanceState) { private void setupChart(LineChart chart, LineData data, int color) { - ((LineDataSet) data.getDataSetByIndex(0)).setCircleColorHole(color); + ((LineDataSet) data.getDataSetByIndex(0)).setCircleHoleColor(color); // no description text chart.getDescription().setEnabled(false); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index ae11c97b3c..496f4046f8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -53,25 +53,24 @@ public BarDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - yVals.clear(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - BarDataSet copied = new BarDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mStackSize = mStackSize; - copied.mBarShadowColor = mBarShadowColor; - copied.mStackLabels = mStackLabels; - copied.mHighLightColor = mHighLightColor; - copied.mHighLightAlpha = mHighLightAlpha; - + BarDataSet copied = new BarDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(BarDataSet barDataSet) { + super.copy(barDataSet); + barDataSet.mStackSize = mStackSize; + barDataSet.mBarShadowColor = mBarShadowColor; + barDataSet.mBarBorderWidth = mBarBorderWidth; + barDataSet.mStackLabels = mStackLabels; + barDataSet.mHighLightAlpha = mHighLightAlpha; + } + /** * Calculates the total number of entries this DataSet represents, including * stacks. All values belonging to a stack are calculated separately. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index fba8216c3d..eab6dccc55 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -9,12 +9,16 @@ /** * Baseclass of all DataSets for Bar-, Line-, Scatter- and CandleStickChart. - * + * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleBubbleDataSet extends DataSet implements IBarLineScatterCandleBubbleDataSet { +public abstract class BarLineScatterCandleBubbleDataSet + extends DataSet + implements IBarLineScatterCandleBubbleDataSet { - /** default highlight color */ + /** + * default highlight color + */ protected int mHighLightColor = Color.rgb(255, 187, 115); public BarLineScatterCandleBubbleDataSet(List yVals, String label) { @@ -25,7 +29,7 @@ public BarLineScatterCandleBubbleDataSet(List yVals, String label) { * Sets the color that is used for drawing the highlight indicators. Dont * forget to resolve the color using getResources().getColor(...) or * Color.rgb(...). - * + * * @param color */ public void setHighLightColor(int color) { @@ -36,4 +40,9 @@ public void setHighLightColor(int color) { public int getHighLightColor() { return mHighLightColor; } + + protected void copy(BarLineScatterCandleBubbleDataSet barLineScatterCandleBubbleDataSet) { + super.copy(barLineScatterCandleBubbleDataSet); + barLineScatterCandleBubbleDataSet.mHighLightColor = mHighLightColor; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 1b9d97850a..7800986dcd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -7,16 +7,13 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.model.GradientColor; -import java.lang.annotation.Documented; -import java.lang.annotation.Inherited; import java.util.ArrayList; import java.util.List; @@ -32,9 +29,9 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; - protected GradientColor gradientColor = null; + protected GradientColor mGradientColor = null; - protected List gradientColors = null; + protected List mGradientColors = null; /** * List representing all colors that are used for drawing the actual values for this DataSet @@ -151,17 +148,17 @@ public int getColor(int index) { @Override public GradientColor getGradientColor() { - return gradientColor; + return mGradientColor; } @Override public List getGradientColors() { - return gradientColors; + return mGradientColors; } @Override public GradientColor getGradientColor(int index) { - return gradientColors.get(index % gradientColors.size()); + return mGradientColors.get(index % mGradientColors.size()); } /** @@ -206,7 +203,7 @@ public void setColors(int... colors) { */ public void setColors(int[] colors, Context c) { - if(mColors == null){ + if (mColors == null) { mColors = new ArrayList<>(); } @@ -246,7 +243,7 @@ public void setColor(int color) { * @param endColor */ public void setGradientColor(int startColor, int endColor) { - gradientColor = new GradientColor(startColor, endColor); + mGradientColor = new GradientColor(startColor, endColor); } /** @@ -255,7 +252,7 @@ public void setGradientColor(int startColor, int endColor) { * @param gradientColors */ public void setGradientColors(List gradientColors) { - this.gradientColors = gradientColors; + this.mGradientColors = gradientColors; } /** @@ -285,7 +282,7 @@ public void setColors(int[] colors, int alpha) { * Resets all colors of this DataSet and recreates the colors array. */ public void resetColors() { - if(mColors == null) { + if (mColors == null) { mColors = new ArrayList(); } mColors.clear(); @@ -527,4 +524,24 @@ public boolean contains(T e) { return false; } + + protected void copy(BaseDataSet baseDataSet) { + baseDataSet.mAxisDependency = mAxisDependency; + baseDataSet.mColors = mColors; + baseDataSet.mDrawIcons = mDrawIcons; + baseDataSet.mDrawValues = mDrawValues; + baseDataSet.mForm = mForm; + baseDataSet.mFormLineDashEffect = mFormLineDashEffect; + baseDataSet.mFormLineWidth = mFormLineWidth; + baseDataSet.mFormSize = mFormSize; + baseDataSet.mGradientColor = mGradientColor; + baseDataSet.mGradientColors = mGradientColors; + baseDataSet.mHighlightEnabled = mHighlightEnabled; + baseDataSet.mIconsOffset = mIconsOffset; + baseDataSet.mValueColors = mValueColors; + baseDataSet.mValueFormatter = mValueFormatter; + baseDataSet.mValueColors = mValueColors; + baseDataSet.mValueTextSize = mValueTextSize; + baseDataSet.mVisible = mVisible; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index d8c0c13013..1f88272dd9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -41,20 +41,20 @@ protected void calcMinMax(BubbleEntry e) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - BubbleDataSet copied = new BubbleDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mHighLightColor = mHighLightColor; - + BubbleDataSet copied = new BubbleDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(BubbleDataSet bubbleDataSet) { + bubbleDataSet.mHighlightCircleWidth = mHighlightCircleWidth; + bubbleDataSet.mNormalizeSize = mNormalizeSize; + } + @Override public float getMaxSize() { return mMaxSize; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index 7574b78b27..c7f8362803 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -79,27 +79,30 @@ public CandleDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - yVals.clear(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - CandleDataSet copied = new CandleDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mShadowWidth = mShadowWidth; - copied.mShowCandleBar = mShowCandleBar; - copied.mBarSpace = mBarSpace; - copied.mHighLightColor = mHighLightColor; - copied.mIncreasingPaintStyle = mIncreasingPaintStyle; - copied.mDecreasingPaintStyle = mDecreasingPaintStyle; - copied.mShadowColor = mShadowColor; - + CandleDataSet copied = new CandleDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(CandleDataSet candleDataSet) { + super.copy(candleDataSet); + candleDataSet.mShadowWidth = mShadowWidth; + candleDataSet.mShowCandleBar = mShowCandleBar; + candleDataSet.mBarSpace = mBarSpace; + candleDataSet.mShadowColorSameAsCandle = mShadowColorSameAsCandle; + candleDataSet.mHighLightColor = mHighLightColor; + candleDataSet.mIncreasingPaintStyle = mIncreasingPaintStyle; + candleDataSet.mDecreasingPaintStyle = mDecreasingPaintStyle; + candleDataSet.mNeutralColor = mNeutralColor; + candleDataSet.mIncreasingColor = mIncreasingColor; + candleDataSet.mDecreasingColor = mDecreasingColor; + candleDataSet.mShadowColor = mShadowColor; + } + @Override protected void calcMinMax(CandleEntry e) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index a96cfdcf66..3c69d9c58f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -157,6 +157,14 @@ public void setValues(List values) { */ public abstract DataSet copy(); + /** + * + * @param dataSet + */ + protected void copy(DataSet dataSet) { + super.copy(dataSet); + } + @Override public String toString() { StringBuffer buffer = new StringBuffer(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 5eced95e43..c1018d1fb4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -30,7 +30,7 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet /** * the color of the inner circles */ - private int mCircleColorHole = Color.WHITE; + private int mCircleHoleColor = Color.WHITE; /** * the radius of the circle-shaped value indicators @@ -84,27 +84,29 @@ public LineDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - LineDataSet copied = new LineDataSet(yVals, getLabel()); - copied.mMode = mMode; - copied.mColors = mColors; - copied.mCircleRadius = mCircleRadius; - copied.mCircleHoleRadius = mCircleHoleRadius; - copied.mCircleColors = mCircleColors; - copied.mDashPathEffect = mDashPathEffect; - copied.mDrawCircles = mDrawCircles; - copied.mDrawCircleHole = mDrawCircleHole; - copied.mHighLightColor = mHighLightColor; - + LineDataSet copied = new LineDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(LineDataSet lineDataSet) { + super.copy(lineDataSet); + lineDataSet.mCircleColors = mCircleColors; + lineDataSet.mCircleHoleColor = mCircleHoleColor; + lineDataSet.mCircleHoleRadius = mCircleHoleRadius; + lineDataSet.mCircleRadius = mCircleRadius; + lineDataSet.mCubicIntensity = mCubicIntensity; + lineDataSet.mDashPathEffect = mDashPathEffect; + lineDataSet.mDrawCircleHole = mDrawCircleHole; + lineDataSet.mDrawCircles = mDrawCircleHole; + lineDataSet.mFillFormatter = mFillFormatter; + lineDataSet.mMode = mMode; + } + /** * Returns the drawing mode for this line dataset * @@ -364,13 +366,13 @@ public void resetCircleColors() { * * @param color */ - public void setCircleColorHole(int color) { - mCircleColorHole = color; + public void setCircleHoleColor(int color) { + mCircleHoleColor = color; } @Override public int getCircleHoleColor() { - return mCircleColorHole; + return mCircleHoleColor; } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index 6971144e14..688585cbdd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -122,4 +122,13 @@ public void setDrawFilled(boolean filled) { public boolean isDrawFilledEnabled() { return mDrawFilled; } + + protected void copy(LineRadarDataSet lineRadarDataSet) { + super.copy(lineRadarDataSet); + lineRadarDataSet.mDrawFilled = mDrawFilled; + lineRadarDataSet.mFillAlpha = mFillAlpha; + lineRadarDataSet.mFillColor = mFillColor; + lineRadarDataSet.mFillDrawable = mFillDrawable; + lineRadarDataSet.mLineWidth = mLineWidth; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index 90a0a43fb3..d4618d809e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -109,4 +109,12 @@ public boolean isDashedHighlightLineEnabled() { public DashPathEffect getDashPathEffectHighlight() { return mHighlightDashPathEffect; } + + protected void copy(LineScatterCandleRadarDataSet lineScatterCandleRadarDataSet) { + super.copy(lineScatterCandleRadarDataSet); + lineScatterCandleRadarDataSet.mDrawHorizontalHighlightIndicator = mDrawHorizontalHighlightIndicator; + lineScatterCandleRadarDataSet.mDrawVerticalHighlightIndicator = mDrawVerticalHighlightIndicator; + lineScatterCandleRadarDataSet.mHighlightLineWidth = mHighlightLineWidth; + lineScatterCandleRadarDataSet.mHighlightDashPathEffect = mHighlightDashPathEffect; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 98b434d3d7..e592399513 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -9,11 +9,15 @@ public class PieDataSet extends DataSet implements IPieDataSet { - /** the space in pixels between the chart-slices, default 0f */ + /** + * the space in pixels between the chart-slices, default 0f + */ private float mSliceSpace = 0f; private boolean mAutomaticallyDisableSliceSpacing; - /** indicates the selection distance of a pie slice */ + /** + * indicates the selection distance of a pie slice + */ private float mShift = 18f; private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; @@ -33,20 +37,19 @@ public PieDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList<>(); - + List entries = new ArrayList<>(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - PieDataSet copied = new PieDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mSliceSpace = mSliceSpace; - copied.mShift = mShift; + PieDataSet copied = new PieDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(PieDataSet pieDataSet) { + super.copy(pieDataSet); + } + @Override protected void calcMinMax(PieEntry e) { @@ -79,7 +82,7 @@ public float getSliceSpace() { /** * When enabled, slice spacing will be 0.0 when the smallest value is going to be - * smaller than the slice spacing itself. + * smaller than the slice spacing itself. * * @param autoDisable */ @@ -89,7 +92,7 @@ public void setAutomaticallyDisableSliceSpacing(boolean autoDisable) { /** * When enabled, slice spacing will be 0.0 when the smallest value is going to be - * smaller than the slice spacing itself. + * smaller than the slice spacing itself. * * @return */ @@ -101,7 +104,7 @@ public boolean isAutomaticallyDisableSliceSpacingEnabled() { /** * sets the distance the highlighted piechart-slice of this DataSet is * "shifted" away from the center of the chart, default 12f - * + * * @param shift */ public void setSelectionShift(float shift) { @@ -114,30 +117,26 @@ public float getSelectionShift() { } @Override - public ValuePosition getXValuePosition() - { + public ValuePosition getXValuePosition() { return mXValuePosition; } - public void setXValuePosition(ValuePosition xValuePosition) - { + public void setXValuePosition(ValuePosition xValuePosition) { this.mXValuePosition = xValuePosition; } @Override - public ValuePosition getYValuePosition() - { + public ValuePosition getYValuePosition() { return mYValuePosition; } - public void setYValuePosition(ValuePosition yValuePosition) - { + public void setYValuePosition(ValuePosition yValuePosition) { this.mYValuePosition = yValuePosition; } /** * When valuePosition is OutsideSlice, use slice colors as line color if true - * */ + */ @Override public boolean isUsingSliceColorAsValueLineColor() { return mUsingSliceColorAsValueLineColor; @@ -147,10 +146,11 @@ public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLin this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor; } - /** When valuePosition is OutsideSlice, indicates line color */ + /** + * When valuePosition is OutsideSlice, indicates line color + */ @Override - public int getValueLineColor() - { + public int getValueLineColor() { return mValueLineColor; } @@ -158,63 +158,63 @@ public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } - /** When valuePosition is OutsideSlice, indicates line width */ + /** + * When valuePosition is OutsideSlice, indicates line width + */ @Override - public float getValueLineWidth() - { + public float getValueLineWidth() { return mValueLineWidth; } - public void setValueLineWidth(float valueLineWidth) - { + public void setValueLineWidth(float valueLineWidth) { this.mValueLineWidth = valueLineWidth; } - /** When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size */ + /** + * When valuePosition is OutsideSlice, indicates offset as percentage out of the slice size + */ @Override - public float getValueLinePart1OffsetPercentage() - { + public float getValueLinePart1OffsetPercentage() { return mValueLinePart1OffsetPercentage; } - public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) - { + public void setValueLinePart1OffsetPercentage(float valueLinePart1OffsetPercentage) { this.mValueLinePart1OffsetPercentage = valueLinePart1OffsetPercentage; } - /** When valuePosition is OutsideSlice, indicates length of first half of the line */ + /** + * When valuePosition is OutsideSlice, indicates length of first half of the line + */ @Override - public float getValueLinePart1Length() - { + public float getValueLinePart1Length() { return mValueLinePart1Length; } - public void setValueLinePart1Length(float valueLinePart1Length) - { + public void setValueLinePart1Length(float valueLinePart1Length) { this.mValueLinePart1Length = valueLinePart1Length; } - /** When valuePosition is OutsideSlice, indicates length of second half of the line */ + /** + * When valuePosition is OutsideSlice, indicates length of second half of the line + */ @Override - public float getValueLinePart2Length() - { + public float getValueLinePart2Length() { return mValueLinePart2Length; } - public void setValueLinePart2Length(float valueLinePart2Length) - { + public void setValueLinePart2Length(float valueLinePart2Length) { this.mValueLinePart2Length = valueLinePart2Length; } - /** When valuePosition is OutsideSlice, this allows variable line length */ + /** + * When valuePosition is OutsideSlice, this allows variable line length + */ @Override - public boolean isValueLineVariableLength() - { + public boolean isValueLineVariableLength() { return mValueLineVariableLength; } - public void setValueLineVariableLength(boolean valueLineVariableLength) - { + public void setValueLineVariableLength(boolean valueLineVariableLength) { this.mValueLineVariableLength = valueLineVariableLength; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java index f18aa8c23a..09c94b417d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java @@ -20,7 +20,7 @@ public class RadarDataSet extends LineRadarDataSet implements IRadar /// If Utils.COLOR_NONE, the color of the dataset is taken. protected int mHighlightCircleStrokeColor = ColorTemplate.COLOR_NONE; - protected int mHighlightCircleStrokeAlpha = (int)(0.3 * 255); + protected int mHighlightCircleStrokeAlpha = (int) (0.3 * 255); protected float mHighlightCircleInnerRadius = 3.0f; protected float mHighlightCircleOuterRadius = 4.0f; protected float mHighlightCircleStrokeWidth = 2.0f; @@ -31,101 +31,92 @@ public RadarDataSet(List yVals, String label) { /// Returns true if highlight circle should be drawn, false if not @Override - public boolean isDrawHighlightCircleEnabled() - { + public boolean isDrawHighlightCircleEnabled() { return mDrawHighlightCircleEnabled; } /// Sets whether highlight circle should be drawn or not @Override - public void setDrawHighlightCircleEnabled(boolean enabled) - { + public void setDrawHighlightCircleEnabled(boolean enabled) { mDrawHighlightCircleEnabled = enabled; } @Override - public int getHighlightCircleFillColor() - { + public int getHighlightCircleFillColor() { return mHighlightCircleFillColor; } - public void setHighlightCircleFillColor(int color) - { + public void setHighlightCircleFillColor(int color) { mHighlightCircleFillColor = color; } /// Returns the stroke color for highlight circle. /// If Utils.COLOR_NONE, the color of the dataset is taken. @Override - public int getHighlightCircleStrokeColor() - { + public int getHighlightCircleStrokeColor() { return mHighlightCircleStrokeColor; } /// Sets the stroke color for highlight circle. /// Set to Utils.COLOR_NONE in order to use the color of the dataset; - public void setHighlightCircleStrokeColor(int color) - { + public void setHighlightCircleStrokeColor(int color) { mHighlightCircleStrokeColor = color; } @Override - public int getHighlightCircleStrokeAlpha() - { + public int getHighlightCircleStrokeAlpha() { return mHighlightCircleStrokeAlpha; } - public void setHighlightCircleStrokeAlpha(int alpha) - { + public void setHighlightCircleStrokeAlpha(int alpha) { mHighlightCircleStrokeAlpha = alpha; } @Override - public float getHighlightCircleInnerRadius() - { + public float getHighlightCircleInnerRadius() { return mHighlightCircleInnerRadius; } - public void setHighlightCircleInnerRadius(float radius) - { + public void setHighlightCircleInnerRadius(float radius) { mHighlightCircleInnerRadius = radius; } @Override - public float getHighlightCircleOuterRadius() - { + public float getHighlightCircleOuterRadius() { return mHighlightCircleOuterRadius; } - public void setHighlightCircleOuterRadius(float radius) - { + public void setHighlightCircleOuterRadius(float radius) { mHighlightCircleOuterRadius = radius; } @Override - public float getHighlightCircleStrokeWidth() - { + public float getHighlightCircleStrokeWidth() { return mHighlightCircleStrokeWidth; } - public void setHighlightCircleStrokeWidth(float strokeWidth) - { + public void setHighlightCircleStrokeWidth(float strokeWidth) { mHighlightCircleStrokeWidth = strokeWidth; } @Override public DataSet copy() { - - List yVals = new ArrayList(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - RadarDataSet copied = new RadarDataSet(yVals, getLabel()); - copied.mColors = mColors; - copied.mHighLightColor = mHighLightColor; - + RadarDataSet copied = new RadarDataSet(entries, getLabel()); + copy(copied); return copied; } + + protected void copy(RadarDataSet radarDataSet) { + super.copy(radarDataSet); + radarDataSet.mDrawHighlightCircleEnabled = mDrawHighlightCircleEnabled; + radarDataSet.mHighlightCircleFillColor = mHighlightCircleFillColor; + radarDataSet.mHighlightCircleInnerRadius = mHighlightCircleInnerRadius; + radarDataSet.mHighlightCircleStrokeAlpha = mHighlightCircleStrokeAlpha; + radarDataSet.mHighlightCircleStrokeColor = mHighlightCircleStrokeColor; + radarDataSet.mHighlightCircleStrokeWidth = mHighlightCircleStrokeWidth; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index a9d73885b5..d234c751a0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -47,28 +47,23 @@ public ScatterDataSet(List yVals, String label) { @Override public DataSet copy() { - - List yVals = new ArrayList(); - + List entries = new ArrayList(); for (int i = 0; i < mValues.size(); i++) { - yVals.add(mValues.get(i).copy()); + entries.add(mValues.get(i).copy()); } - - ScatterDataSet copied = new ScatterDataSet(yVals, getLabel()); - copied.mDrawValues = mDrawValues; - copied.mValueColors = mValueColors; - copied.mColors = mColors; - copied.mShapeSize = mShapeSize; - copied.mShapeRenderer = mShapeRenderer; - copied.mScatterShapeHoleRadius = mScatterShapeHoleRadius; - copied.mScatterShapeHoleColor = mScatterShapeHoleColor; - copied.mHighlightLineWidth = mHighlightLineWidth; - copied.mHighLightColor = mHighLightColor; - copied.mHighlightDashPathEffect = mHighlightDashPathEffect; - + ScatterDataSet copied = new ScatterDataSet(entries, getLabel()); + copy(copied); return copied; } + protected void copy(ScatterDataSet scatterDataSet) { + super.copy(scatterDataSet); + scatterDataSet.mShapeSize = mShapeSize; + scatterDataSet.mShapeRenderer = mShapeRenderer; + scatterDataSet.mScatterShapeHoleRadius = mScatterShapeHoleRadius; + scatterDataSet.mScatterShapeHoleColor = mScatterShapeHoleColor; + } + /** * Sets the size in density pixels the drawn scattershape will have. This * only applies for non custom shapes. @@ -141,13 +136,20 @@ public int getScatterShapeHoleColor() { public static IShapeRenderer getRendererForShape(ScatterChart.ScatterShape shape) { switch (shape) { - case SQUARE: return new SquareShapeRenderer(); - case CIRCLE: return new CircleShapeRenderer(); - case TRIANGLE: return new TriangleShapeRenderer(); - case CROSS: return new CrossShapeRenderer(); - case X: return new XShapeRenderer(); - case CHEVRON_UP: return new ChevronUpShapeRenderer(); - case CHEVRON_DOWN: return new ChevronDownShapeRenderer(); + case SQUARE: + return new SquareShapeRenderer(); + case CIRCLE: + return new CircleShapeRenderer(); + case TRIANGLE: + return new TriangleShapeRenderer(); + case CROSS: + return new CrossShapeRenderer(); + case X: + return new XShapeRenderer(); + case CHEVRON_UP: + return new ChevronUpShapeRenderer(); + case CHEVRON_DOWN: + return new ChevronDownShapeRenderer(); } return null; From 92c14db5b4de4efd43c9fd74361886b92111ca9f Mon Sep 17 00:00:00 2001 From: Pawel Grzybek Date: Wed, 9 May 2018 08:09:03 +0200 Subject: [PATCH 1308/1390] Fixed code review comments. --- .../mikephil/charting/components/YAxis.java | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index c572e3043c..2d2782cf85 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -41,23 +41,12 @@ public class YAxis extends AxisBase { /** * flag indicating that auto scale min restriction should be used */ - private boolean mUseAutoScaleRestrictionMin = false; + /** * flag indicating that auto scale max restriction should be used */ - private boolean mUseAutoScaleRestrictionMax = false; - /** - * restriction value of autoscale min - */ - - private float mAutoScaleMinRestriction = 0f; - - /** - * restriction value of autoscale max - */ - private float mAutoScaleMaxRestriction = 0f; /** * Color of the zero line @@ -379,35 +368,34 @@ public boolean needsOffset() { } /** - * Sets min value restriction for autoscale + * Returns true if autoscale restriction for axis min value is enabled */ - public void setAutoScaleMinRestriction(float restrictionValue) { - mUseAutoScaleRestrictionMin = true; - mAutoScaleMinRestriction = restrictionValue; + public boolean isUseAutoScaleMinRestriction( ) { + return mUseAutoScaleRestrictionMin; } /** - * Sets max value restriction for autoscale + * Sets autoscale restriction for axis min value as enabled/disabled */ - public void setAutoScaleMaxRestriction(float restrictionValue) { - mUseAutoScaleRestrictionMax = true; - mAutoScaleMaxRestriction = restrictionValue; + public void setUseAutoScaleMinRestriction( boolean isEnabled ) { + mUseAutoScaleRestrictionMin = isEnabled; } /** - * Resets min value restriction for autoscale + * Returns true if autoscale restriction for axis max value is enabled */ - public void resetAutoScaleMinRestriction() { - mUseAutoScaleRestrictionMin = false; + public boolean isUseAutoScaleMaxRestriction() { + return mUseAutoScaleRestrictionMax; } /** - * Resets max value restriction for autoscale + * Sets autoscale restriction for axis max value as enabled/disabled */ - public void resetAutoScaleMaxRestriction() { - mUseAutoScaleRestrictionMax = false; + public void setUseAutoScaleMaxRestriction( boolean isEnabled ) { + mUseAutoScaleRestrictionMax = isEnabled; } + @Override public void calculate(float dataMin, float dataMax) { @@ -416,15 +404,19 @@ public void calculate(float dataMin, float dataMax) { // if custom, use value as is, else use data value if( mCustomAxisMin ) { - min = mAxisMinimum; - } else if( mUseAutoScaleRestrictionMin ) { - min = Math.min( min, mAutoScaleMinRestriction ); + if( mUseAutoScaleRestrictionMin ) { + min = Math.min( dataMin, mAxisMinimum ); + } else { + min = mAxisMinimum; + } } if( mCustomAxisMax ) { - max = mAxisMaximum; - } else if( mUseAutoScaleRestrictionMax ) { - max = Math.max( max, mAutoScaleMaxRestriction ); + if( mUseAutoScaleRestrictionMax ) { + max = Math.max( max, mAxisMaximum ); + } else { + max = mAxisMaximum; + } } // temporary range (before calculations) From 89436221db3d83991f9ecd830f871d4ce7da47a4 Mon Sep 17 00:00:00 2001 From: RobertZagorski Date: Wed, 9 May 2018 08:44:22 +0200 Subject: [PATCH 1309/1390] Remove mLabelRotatedHeight counted twice, when calculating legend offsets. (Fix for #2369). Removed statements where completely not needed as calculating offsets is alredy done in BarLineCharBase#calculateOffsets(...) --- .../charting/charts/BarLineChartBase.java | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index bf4c42e241..1cca83ddd0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -427,18 +427,12 @@ protected void calculateLegendOffsets(RectF offsets) { offsets.top += Math.min(mLegend.mNeededHeight, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + mLegend.getYOffset(); - - if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) - offsets.top += getXAxis().mLabelRotatedHeight; break; case BOTTOM: offsets.bottom += Math.min(mLegend.mNeededHeight, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + mLegend.getYOffset(); - - if (getXAxis().isEnabled() && getXAxis().isDrawLabelsEnabled()) - offsets.bottom += getXAxis().mLabelRotatedHeight; break; default: @@ -478,21 +472,21 @@ public void calculateOffsets() { if (mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled()) { - float xlabelheight = mXAxis.mLabelRotatedHeight + mXAxis.getYOffset(); + float xLabelHeight = mXAxis.mLabelRotatedHeight + mXAxis.getYOffset(); // offsets for x-labels if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - offsetBottom += xlabelheight; + offsetBottom += xLabelHeight; } else if (mXAxis.getPosition() == XAxisPosition.TOP) { - offsetTop += xlabelheight; + offsetTop += xLabelHeight; } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { - offsetBottom += xlabelheight; - offsetTop += xlabelheight; + offsetBottom += xLabelHeight; + offsetTop += xLabelHeight; } } @@ -1224,7 +1218,7 @@ public boolean isDrawBordersEnabled() { /** * When enabled, the values will be clipped to contentRect, - * otherwise they can bleed outside the content rect. + * otherwise they can bleed outside the content rect. * * @param enabled */ @@ -1234,7 +1228,7 @@ public void setClipValuesToContent(boolean enabled) { /** * When enabled, the values will be clipped to contentRect, - * otherwise they can bleed outside the content rect. + * otherwise they can bleed outside the content rect. * * @return */ From 5869c9de23bf46eb36631a1dcc2785fe6f0e19f0 Mon Sep 17 00:00:00 2001 From: Maxim Pestryakov Date: Wed, 9 May 2018 16:03:48 +0300 Subject: [PATCH 1310/1390] Fixed Javadoc --- .../github/mikephil/charting/formatter/LargeValueFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 01eae56f51..211401ad8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -66,7 +66,7 @@ public void setAppendix(String appendix) { * Set custom suffix to be appended after the values. * Default suffix: ["", "k", "m", "b", "t"] * - * @param suff new suffix + * @param suffix new suffix */ public void setSuffix(String[] suffix) { this.mSuffix = suffix; From 75dd04cc42b519b6221b68061a74ee6b7f222d88 Mon Sep 17 00:00:00 2001 From: RobertZagorski Date: Thu, 10 May 2018 08:01:03 +0200 Subject: [PATCH 1311/1390] Remove redundant findViewById casts, that became obsolete after migration to API 26. --- .../mpchartexample/AnotherBarActivity.java | 10 +++++----- .../mpchartexample/BarChartActivity.java | 10 +++++----- .../mpchartexample/BarChartActivityMultiDataset.java | 10 +++++----- .../mpchartexample/BarChartActivitySinus.java | 6 +++--- .../mpchartexample/BarChartPositiveNegative.java | 2 +- .../mpchartexample/BubbleChartActivity.java | 10 +++++----- .../mpchartexample/CandleStickChartActivity.java | 10 +++++----- .../mpchartexample/CombinedChartActivity.java | 2 +- .../mpchartexample/CubicLineChartActivity.java | 10 +++++----- .../mpchartexample/DrawChartActivity.java | 2 +- .../mpchartexample/DynamicalAddingActivity.java | 2 +- .../mpchartexample/FilledLineActivity.java | 2 +- .../mpchartexample/HalfPieChartActivity.java | 2 +- .../mpchartexample/HorizontalBarChartActivity.java | 10 +++++----- .../mpchartexample/InvertedLineChartActivity.java | 10 +++++----- .../mpchartexample/LineChartActivity1.java | 10 +++++----- .../mpchartexample/LineChartActivity2.java | 10 +++++----- .../mpchartexample/LineChartActivityColored.java | 8 ++++---- .../xxmassdeveloper/mpchartexample/LineChartTime.java | 6 +++--- .../mpchartexample/ListViewBarChartActivity.java | 4 ++-- .../mpchartexample/ListViewMultiChartActivity.java | 2 +- .../mpchartexample/MultiLineChartActivity.java | 10 +++++----- .../mpchartexample/PerformanceLineChart.java | 6 +++--- .../mpchartexample/PieChartActivity.java | 10 +++++----- .../mpchartexample/PiePolylineChartActivity.java | 10 +++++----- .../mpchartexample/RadarChartActivity.java | 4 ++-- .../mpchartexample/RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 10 +++++----- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 10 +++++----- .../mpchartexample/StackedBarActivityNegative.java | 2 +- .../mpchartexample/custom/MyMarkerView.java | 2 +- .../mpchartexample/custom/RadarMarkerView.java | 2 +- .../mpchartexample/custom/StackedBarsMarkerView.java | 2 +- .../mpchartexample/custom/XYMarkerView.java | 2 +- .../mpchartexample/fragments/BarChartFrag.java | 2 +- .../mpchartexample/fragments/ComplexityFragment.java | 2 +- .../mpchartexample/fragments/PieChartFrag.java | 2 +- .../mpchartexample/fragments/ScatterChartFrag.java | 2 +- .../mpchartexample/fragments/SimpleChartDemo.java | 2 +- .../mpchartexample/fragments/SineCosineFragment.java | 2 +- .../mpchartexample/listviewitems/BarChartItem.java | 2 +- .../mpchartexample/listviewitems/LineChartItem.java | 2 +- .../mpchartexample/listviewitems/PieChartItem.java | 2 +- .../mpchartexample/notimportant/MainActivity.java | 2 +- .../mpchartexample/notimportant/MyAdapter.java | 6 +++--- .../mpchartexample/realm/RealmDatabaseActivityBar.java | 2 +- .../realm/RealmDatabaseActivityBubble.java | 2 +- .../realm/RealmDatabaseActivityCandle.java | 2 +- .../realm/RealmDatabaseActivityHorizontalBar.java | 2 +- .../realm/RealmDatabaseActivityLine.java | 2 +- .../mpchartexample/realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 2 +- .../realm/RealmDatabaseActivityScatter.java | 2 +- .../mpchartexample/realm/RealmMainActivity.java | 2 +- .../mpchartexample/realm/RealmWikiExample.java | 4 ++-- 56 files changed, 130 insertions(+), 130 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index ba01acd794..f6cffddcbe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -36,16 +36,16 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 2707d0bd51..c0e3405625 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -56,13 +56,13 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 671ab5abec..204dc1fe64 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -44,17 +44,17 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); - tvX = (TextView) findViewById(R.id.tvXMax); + tvX = findViewById(R.id.tvXMax); tvX.setTextSize(10); - tvY = (TextView) findViewById(R.id.tvYMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 56add4458e..82b039909f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -44,11 +44,11 @@ protected void onCreate(Bundle savedInstanceState) { mSinusData = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); - tvX = (TextView) findViewById(R.id.tvValueCount); + tvX = findViewById(R.id.tvValueCount); - mSeekBarX = (SeekBar) findViewById(R.id.seekbarValues); + mSeekBarX = findViewById(R.id.seekbarValues); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setDrawBarShadow(false); mChart.setDrawValueAboveBar(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 743b7e735d..7d6bd44896 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -37,7 +37,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_barchart_noseekbar); mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setBackgroundColor(Color.WHITE); mChart.setExtraTopOffset(-30f); mChart.setExtraBottomOffset(10f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 0ecc1e9c93..bc1750381e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -44,16 +44,16 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_bubblechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (BubbleChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.getDescription().setEnabled(false); mChart.setOnChartValueSelectedListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index bd8dde108f..54eb768a7b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -39,16 +39,16 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_candlechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (CandleStickChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setBackgroundColor(Color.WHITE); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index fadfbf175f..e4d8fb2e3b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -48,7 +48,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_combined); - mChart = (CombinedChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.getDescription().setEnabled(false); mChart.setBackgroundColor(Color.WHITE); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index cb979e80e9..4a278c398e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -39,11 +39,11 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarX.setProgress(45); mSeekBarY.setProgress(100); @@ -51,7 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setViewPortOffsets(0, 0, 0, 0); mChart.setBackgroundColor(Color.rgb(104, 241, 175)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 970ba12909..d3551068c1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -43,7 +43,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_draw_chart); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); // listener for selecting and drawing mChart.setOnChartValueSelectedListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 2875b89d7e..f8f64c374f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -32,7 +32,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index d824167d6b..9109d5d29c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -31,7 +31,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setBackgroundColor(Color.WHITE); mChart.setGridBackgroundColor(mFillColor); mChart.setDrawGridBackground(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index a524f36a43..38a228b322 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -37,7 +37,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart_half); - mChart = (PieChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setBackgroundColor(Color.WHITE); moveOffScreen(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index d68b75cc15..95e138aade 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -46,13 +46,13 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_horizontalbarchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); - mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); // mChart.setHighlightEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index f87a9a8098..4ad4e691ef 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -44,11 +44,11 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarX.setProgress(45); mSeekBarY.setProgress(100); @@ -56,7 +56,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 6cf7150c97..85d213e351 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -54,11 +54,11 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarX.setProgress(45); mSeekBarY.setProgress(100); @@ -66,7 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartGestureListener(this); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 79f40c4e07..e2a381ff91 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -44,10 +44,10 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarX.setProgress(45); mSeekBarY.setProgress(100); @@ -55,7 +55,7 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarY.setOnSeekBarChangeListener(this); mSeekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); // no description text diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 22984b4b6e..39730d55b1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -27,10 +27,10 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_colored_lines); - mCharts[0] = (LineChart) findViewById(R.id.chart1); - mCharts[1] = (LineChart) findViewById(R.id.chart2); - mCharts[2] = (LineChart) findViewById(R.id.chart3); - mCharts[3] = (LineChart) findViewById(R.id.chart4); + mCharts[0] = findViewById(R.id.chart1); + mCharts[1] = findViewById(R.id.chart2); + mCharts[2] = findViewById(R.id.chart3); + mCharts[3] = findViewById(R.id.chart4); mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 30e5e2a978..6bf96f02a7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -45,14 +45,14 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_time); - tvX = (TextView) findViewById(R.id.tvXMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + tvX = findViewById(R.id.tvXMax); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setProgress(100); tvX.setText("100"); mSeekBarX.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); // no description text mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 7ee212ff60..54218a53da 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -41,7 +41,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - ListView lv = (ListView) findViewById(R.id.listView1); + ListView lv = findViewById(R.id.listView1); ArrayList list = new ArrayList(); @@ -73,7 +73,7 @@ public View getView(int position, View convertView, ViewGroup parent) { convertView = LayoutInflater.from(getContext()).inflate( R.layout.list_item_barchart, null); - holder.chart = (BarChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 0e273596fe..0c9f132f03 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -45,7 +45,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - ListView lv = (ListView) findViewById(R.id.listView1); + ListView lv = findViewById(R.id.listView1); ArrayList list = new ArrayList(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 19f7bae938..e6acf01670 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -39,16 +39,16 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index 0763f7f88a..a2d4becadc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -30,15 +30,15 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_performance_linechart); - mTvCount = (TextView) findViewById(R.id.tvValueCount); - mSeekBarValues = (SeekBar) findViewById(R.id.seekbarValues); + mTvCount = findViewById(R.id.tvValueCount); + mSeekBarValues = findViewById(R.id.seekbarValues); mTvCount.setText("500"); mSeekBarValues.setProgress(500); mSeekBarValues.setOnSeekBarChangeListener(this); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setDrawGridBackground(false); // no description text diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index eb60524cb0..0252ff8ff0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -48,15 +48,15 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarX.setProgress(4); mSeekBarY.setProgress(10); - mChart = (PieChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setUsePercentValues(true); mChart.getDescription().setEnabled(false); mChart.setExtraOffsets(5, 10, 5, 5); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 44fbf06c89..c0199723d9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -48,18 +48,18 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarX = findViewById(R.id.seekBar1); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setProgress(10); mSeekBarX.setOnSeekBarChangeListener(this); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (PieChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setUsePercentValues(true); mChart.getDescription().setEnabled(false); mChart.setExtraOffsets(5, 10, 5, 5); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index f1fd4cc891..d354886f6e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -38,12 +38,12 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_radarchart_noseekbar); - TextView tv = (TextView) findViewById(R.id.textView); + TextView tv = findViewById(R.id.textView); tv.setTypeface(mTfLight); tv.setTextColor(Color.WHITE); tv.setBackgroundColor(Color.rgb(60, 65, 82)); - mChart = (RadarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setBackgroundColor(Color.rgb(60, 65, 82)); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 13346bf631..f3661628d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -36,7 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_realtime_linechart); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); // enable description text diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 29904a95c9..f0f889e194 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -42,16 +42,16 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scatterchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (ScatterChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.getDescription().setEnabled(false); mChart.setOnChartValueSelectedListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index ff098c32e0..1aeb7f0f0c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -26,7 +26,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scrollview); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 70afd7c4c6..9951060177 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -44,16 +44,16 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvX = findViewById(R.id.tvXMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX = findViewById(R.id.seekBar1); mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY = findViewById(R.id.seekBar2); mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index d5e0f8c885..c1d64a106b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -46,7 +46,7 @@ protected void onCreate(Bundle savedInstanceState) { setTitle("Age Distribution Austria"); - mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); mChart.setDrawGridBackground(false); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 8d97346195..ef20bda3b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -24,7 +24,7 @@ public class MyMarkerView extends MarkerView { public MyMarkerView(Context context, int layoutResource) { super(context, layoutResource); - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); } // callbacks everytime the MarkerView is redrawn, can be used to update the diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 1a350f45ac..12b473f7d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -28,7 +28,7 @@ public class RadarMarkerView extends MarkerView { public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); tvContent.setTypeface(Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf")); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index d0781b2ee2..487705bb7d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -24,7 +24,7 @@ public class StackedBarsMarkerView extends MarkerView { public StackedBarsMarkerView(Context context, int layoutResource) { super(context, layoutResource); - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); } // callbacks everytime the MarkerView is redrawn, can be used to update the diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 177527b3bf..0475bdd038 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -29,7 +29,7 @@ public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); this.xAxisValueFormatter = xAxisValueFormatter; - tvContent = (TextView) findViewById(R.id.tvContent); + tvContent = findViewById(R.id.tvContent); format = new DecimalFormat("###.0"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 1cdba2735f..655fc6bb25 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -60,7 +60,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa xAxis.setEnabled(false); // programatically add the chart - FrameLayout parent = (FrameLayout) v.findViewById(R.id.parentLayout); + FrameLayout parent = v.findViewById(R.id.parentLayout); parent.addView(mChart); return v; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index caf9e3e295..b960e9ae0c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -25,7 +25,7 @@ public static Fragment newInstance() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - mChart = (LineChart) v.findViewById(R.id.lineChart1); + mChart = v.findViewById(R.id.lineChart1); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index 7888aa632f..946532ac40 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -28,7 +28,7 @@ public static Fragment newInstance() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_pie, container, false); - mChart = (PieChart) v.findViewById(R.id.pieChart1); + mChart = v.findViewById(R.id.pieChart1); mChart.getDescription().setEnabled(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 90aba051d3..b8a3f0f324 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -28,7 +28,7 @@ public static Fragment newInstance() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_scatter, container, false); - mChart = (ScatterChart) v.findViewById(R.id.scatterChart1); + mChart = v.findViewById(R.id.scatterChart1); mChart.getDescription().setEnabled(false); Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java index 7af599e927..ee64ffdfce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java @@ -29,7 +29,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_awesomedesign); - ViewPager pager = (ViewPager) findViewById(R.id.pager); + ViewPager pager = findViewById(R.id.pager); pager.setOffscreenPageLimit(3); PageAdapter a = new PageAdapter(getSupportFragmentManager()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 60173c368f..7e425172fb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -25,7 +25,7 @@ public static Fragment newInstance() { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - mChart = (LineChart) v.findViewById(R.id.lineChart1); + mChart = v.findViewById(R.id.lineChart1); mChart.getDescription().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index cf9b4b553d..c09297a391 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -39,7 +39,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_barchart, null); - holder.chart = (BarChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index f988844fce..107930af2a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -40,7 +40,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_linechart, null); - holder.chart = (LineChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index db6ba32416..5503018792 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -47,7 +47,7 @@ public View getView(int position, View convertView, Context c) { convertView = LayoutInflater.from(c).inflate( R.layout.list_item_piechart, null); - holder.chart = (PieChart) convertView.findViewById(R.id.chart); + holder.chart = convertView.findViewById(R.id.chart); convertView.setTag(holder); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 45ca879ee3..d994f87c96 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -149,7 +149,7 @@ protected void onCreate(Bundle savedInstanceState) { MyAdapter adapter = new MyAdapter(this, objects); - ListView lv = (ListView) findViewById(R.id.listView1); + ListView lv = findViewById(R.id.listView1); lv.setAdapter(adapter); lv.setOnItemClickListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java index 8395ce2720..5b424e88a5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java @@ -39,9 +39,9 @@ public View getView(int position, View convertView, ViewGroup parent) { holder = new ViewHolder(); convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, null); - holder.tvName = (TextView) convertView.findViewById(R.id.tvName); - holder.tvDesc = (TextView) convertView.findViewById(R.id.tvDesc); - holder.tvNew = (TextView) convertView.findViewById(R.id.tvNew); + holder.tvName = convertView.findViewById(R.id.tvName); + holder.tvDesc = convertView.findViewById(R.id.tvDesc); + holder.tvNew = convertView.findViewById(R.id.tvNew); convertView.setTag(holder); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 4f1d42f1db..1e5d5cb8d5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart_noseekbar); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index fb28c3f08a..ad65a3de18 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_bubblechart_noseekbar); - mChart = (BubbleChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getXAxis().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 17c0d8d2f0..96fbade855 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -31,7 +31,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_candlechart_noseekbar); - mChart = (CandleStickChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index 35138d656d..b5e3345134 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -31,7 +31,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_horizontalbarchart_noseekbar); - mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getAxisLeft().setAxisMinimum(0f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 24982cf7fa..7d2e49fdff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -31,7 +31,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getAxisLeft().setAxisMaximum(150f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 2936379d55..9fad49c617 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -32,7 +32,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart_noseekbar); - mChart = (PieChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.setCenterText(generateCenterSpannableText()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 411f4b6ac9..02f3ac0492 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_radarchart_noseekbar); - mChart = (RadarChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getYAxis().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index d2e2fd70f5..9da64cbf1d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -30,7 +30,7 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scatterchart_noseekbar); - mChart = (ScatterChart) findViewById(R.id.chart1); + mChart = findViewById(R.id.chart1); setup(mChart); mChart.getAxisLeft().setDrawGridLines(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java index 07c54ad88c..1776a8bd7e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -51,7 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { MyAdapter adapter = new MyAdapter(this, objects); - ListView lv = (ListView) findViewById(R.id.listView1); + ListView lv = findViewById(R.id.listView1); lv.setAdapter(adapter); lv.setOnItemClickListener(this); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index 25011b0e2b..f223be6093 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -37,8 +37,8 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_realm_wiki); - lineChart = (LineChart) findViewById(R.id.lineChart); - barChart = (BarChart) findViewById(R.id.barChart); + lineChart = findViewById(R.id.lineChart); + barChart = findViewById(R.id.barChart); setup(lineChart); setup(barChart); From 536a35a6fd045e1279edf72f8afad736de3d93a1 Mon Sep 17 00:00:00 2001 From: almic Date: Thu, 10 May 2018 11:03:03 -0600 Subject: [PATCH 1312/1390] docs(README): Update & simplify README - Re-ordered some of the sections - Simplified some sections - Reformatted here and there - Added a few emojis, how cute! The goal of this change was to hopefully further reduce the amount of issue support/ question spam. By moving the sections around to show the more important parts higher up, like usage and documentation links, I hope this will make it easier for people to find the documentation. --- README.md | 243 +++++++++++++++-------------- design/feature_graphic_smaller.png | Bin 0 -> 22385 bytes 2 files changed, 127 insertions(+), 116 deletions(-) create mode 100644 design/feature_graphic_smaller.png diff --git a/README.md b/README.md index 8ffafdc4c4..b651ea3157 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ -[![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) -[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) -[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) -[![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +**Remember: _It's all about the looks._** -Remember: *It's all about the looks.* +![banner](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic_smaller.png) -![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) +[![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) +[![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) +[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) -[**MPAndroidChart**](https://github.com/PhilJay/MPAndroidChart) :zap: is a powerful & easy to use chart library for Android. It runs on [API level 8](http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels) and upwards. +:zap: A powerful & easy to use chart library for Android :zap: -As an additional feature, this library allows cross-platform development between Android and iOS as an iOS version of this library is also available: [**Charts**](https://github.com/danielgindi/Charts) :zap: +[**Charts**](https://github.com/danielgindi/Charts) is the iOS version of this library -[Enterprise Solution 5% Discount Coupon | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) ------ +## [Enterprise Solution 5% Discount Coupon | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) @@ -24,177 +24,178 @@ MPAndroidChart is free software, as a result **dynamic & realtime data is not of All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** +
    +## Usage :chart_with_upwards_trend: -
    +**Gradle** +- **Project level `build.gradle`** +```gradle +allprojects { + repositories { + maven { url 'https://jitpack.io' } + } +} +``` +- **App level `build.gradle`** +```gradle +dependencies { + implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' +} +``` -Donations ------ +**Maven** -**This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! +```xml + + + jitpack.io + https://jitpack.io + -**My Bitcoin Wallet** (Bitcoin only) -1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg + + + com.github.PhilJay + MPAndroidChart + v3.0.3 + +``` -**My Ethereum Wallet** (Ethereum only) +
    -0x04ef098bf9f91871391363e3caf791afa3adc39b +## Documentation :notebook_with_decorative_cover: -**PayPal** +See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. - - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - - [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! - - [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - - Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! +See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for more advanced documentation. +
    -Spread the word ------ +## Examples :eyes: +Download the [MPAndroidChart Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) or look at the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample). -If you like this library, please tell others about it :two_hearts: :two_hearts: +[![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI) - - - +
    - - []()Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - - Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) +## Questions & Issues :thinking: +This repository's issue tracker is only for bugs and feature requests. The maintainers ask that you refrain from asking questions about how to use MPAndroidChart through the issue tracker. -Demo ------ +Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer. -For a brief overview of the most important features, please download the **PlayStore Demo** [**MPAndroidChart Example.apk**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) and try it out. The corresponding code for the demo-application is also included in this repository inside the **MPChartExample folder**. +
    -[![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI) +## Donations :heart: -Questions & Issues ------ +**This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! -If you are having questions or problems, you should: +**My Bitcoin Wallet** (Bitcoin only) - - **Review your code**. Make absolutely sure that everything is correct on your side. - - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) - - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) - - Check this: ["how not to contribute"](https://github.com/PhilJay/MPAndroidChart/wiki/How-not-to-contribute) - -Please do not expect answers to your questions if you have not considered all above mentioned approaches in advance. +1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg -Features ------ -You can have a look at the core features of this libary [**here**](https://github.com/PhilJay/MPAndroidChart/wiki/Core-Features). - -Usage ------ +**My Ethereum Wallet** (Ethereum only) -In order to use the library, there are 4 different options: +0x04ef098bf9f91871391363e3caf791afa3adc39b -**1. Gradle dependency** (recommended) +**PayPal** - - Add the following to your project level `build.gradle`: - -```gradle -allprojects { - repositories { - maven { url "https://jitpack.io" } - } -} -``` - - Add this to your app `build.gradle`: - -```gradle -dependencies { - implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' -} -``` +- [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! +- [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! +- [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! +- [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! +- Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! -**2. Maven** -- Add the following to the `` section of your `pom.xml`: +
    - ```xml - - jitpack.io - https://jitpack.io - -``` -- Add the following to the `` section of your `pom.xml`: +## Social Media :fire: - ```xml - - com.github.PhilJay - MPAndroidChart - v3.0.3 - -``` - -**3. clone whole repository** (not recommended) +If you like this library, please tell others about it :two_hearts: :two_hearts: + +[![Share on Twitter](https://github.com/PhilJay/MPAndroidChart/blob/master/design/twitter_icon.png)](https://twitter.com/intent/tweet?text=Check%20out%20the%20awesome%20MPAndroidChart%20library%20on%20Github:%20https://github.com/PhilJay/MPAndroidChart) +[![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) +[![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -Documentation ------ -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/). +You can follow the creator on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) -Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). -You can also join others in a discussion on [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) - -Chart types ------ +Philipp is also on [StackOverflow](http://stackoverflow.com/users/1590502/philipp-jahoda) + +
    + +## More Examples :+1: + +
    + +**LineChart (with legend, simple design)** - - **LineChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart4.png) - - **LineChart (with legend, simple design)** +

    + +**LineChart (with legend, simple design)** + ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_linechart3.png) +

    + +**LineChart (cubic lines)** - - **LineChart (cubic lines)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) +

    - - **LineChart (gradient fill)** -![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) +**LineChart (gradient fill)** - - **Combined-Chart (bar- and linechart in this case)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) +

    - - **BarChart (with legend, simple design)** +**BarChart (with legend, simple design)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/simpledesign_barchart3.png) +

    - - **BarChart (grouped DataSets)** +**BarChart (grouped DataSets)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/groupedbarchart.png) +

    - - **Horizontal-BarChart** +**Horizontal-BarChart** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) +

    + +**Combined-Chart (bar- and linechart in this case)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) +

    - - **PieChart (with selection, ...)** +**PieChart (with selection, ...)** ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/simpledesign_piechart1.png) +

    - - **ScatterChart** (with squares, triangles, circles, ... and more) +**ScatterChart** (with squares, triangles, circles, ... and more) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/scatterchart.png) +

    - - **CandleStickChart** (for financial data) +**CandleStickChart** (for financial data) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) +

    - - **BubbleChart** (area covered by bubbles indicates the yValue) +**BubbleChart** (area covered by bubbles indicates the yValue) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) +

    - - **RadarChart** (spider web chart) +**RadarChart** (spider web chart) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) +
    + +# License :page_facing_up: -License -======= Copyright 2018 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); @@ -209,4 +210,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [tony](https://github.com/tonypatino-monoclesociety), [almic](https://github.com/almic) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. +
    + +## Special Thanks :heart: + +These people rock! + +- [danielgindi](https://github.com/danielgindi) - Daniel Gindi +- [mikegr](https://github.com/mikegr) - Michael Greifeneder +- [tony](https://github.com/tonypatino-monoclesociety) - Tony +- [almic](https://github.com/almic) - Mick A. +- [jitpack.io](https://github.com/jitpack-io) - JitPack.io diff --git a/design/feature_graphic_smaller.png b/design/feature_graphic_smaller.png new file mode 100644 index 0000000000000000000000000000000000000000..c1e5db57999c7bf354399d7d8e5d52185f0ab108 GIT binary patch literal 22385 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 E0R<|U(f|Me literal 0 HcmV?d00001 From b65ba083243d74f90a36d154029622c9fc241619 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 15 May 2018 15:57:09 +0200 Subject: [PATCH 1313/1390] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b651ea3157..55eb482f91 100644 --- a/README.md +++ b/README.md @@ -12,20 +12,21 @@ [**Charts**](https://github.com/danielgindi/Charts) is the iOS version of this library -## [Enterprise Solution 5% Discount Coupon | SciChart](http://store.scichart.com?productTab=Android&CouponCode=MPANDROIDCHART) +## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart) -MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend -
    SciChart Android. +MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend +SciChart Android. -All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** +All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART**
    + ## Usage :chart_with_upwards_trend: **Gradle** From c1f6fcebf0c3516e067b34312b283189f909bde5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 6 Jun 2018 09:14:41 +0200 Subject: [PATCH 1314/1390] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 55eb482f91..986e4f8102 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -**Remember: _It's all about the looks._** - ![banner](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic_smaller.png) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) From 073ad3c87713421025ec1dd102283ae46d10fdf6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Aug 2018 20:14:32 +0200 Subject: [PATCH 1315/1390] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 986e4f8102..ed3220eb3a 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,7 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: [![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) [![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -You can follow the creator on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) - -Philipp is also on [StackOverflow](http://stackoverflow.com/users/1590502/philipp-jahoda) +You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**daily coding newsletter**](https://philjay.substack.com).
    From 6f0b7432ac97adbf5a19853670cc65910d25a717 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Aug 2018 20:21:19 +0200 Subject: [PATCH 1316/1390] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index ed3220eb3a..ceb3385962 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,9 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the +## [Daily Coding Newsletter](philjay.substack.com) + +Sign up for my [daily coding newsletter](philjay.substack.com) to get quick updates on Kotlin and Android developent related topics. ## Usage :chart_with_upwards_trend: From 2316f8500f0478fc6ab48cac65e2df65d39657bb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Aug 2018 20:21:49 +0200 Subject: [PATCH 1317/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ceb3385962..270b034cf3 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the Date: Sun, 26 Aug 2018 20:31:00 +0200 Subject: [PATCH 1318/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 270b034cf3..7ad6824cfe 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the From 20bca4a8ca6a6d9e0c508ec6363d387df1aaa999 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Aug 2018 20:31:44 +0200 Subject: [PATCH 1319/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ad6824cfe..96d9ac9039 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the -## [Daily Coding Newsletter](philjay.substack.com) +## [Daily Coding Newsletter](https://philjay.substack.com/subscribe) Sign up for my [daily coding newsletter](https://philjay.substack.com/subscribe) to get quick updates on Kotlin and Android development related topics. From d67ea481af1e8528c617dfd404d0c7827b0134b2 Mon Sep 17 00:00:00 2001 From: almic Date: Fri, 26 Oct 2018 10:30:22 -0600 Subject: [PATCH 1320/1390] Huge Project Refresh Before anyone freaks out, all these changes are under-the-hood, meaning that you probably won't even notice them at all. The biggest difference is raising the minSdkVersion from 9 to 14. Recently android bumped this number interally as there are basically no devices running lower than 14 anymore. Sorry but you are just wasting your time if you are trying to support anything lower than 14 now. The next biggest change is updating the project to the new AndroidX libraries, which changes some imports and nothing else really. The third biggest change is fixing a few bugs in the code that cause values to be drawn even if there are none, which results in your app crashing. Surprisingly, these checks already existed in a few of the newer chart types, but most lacked this simple check. Other than those three changes, nothing else is functionally different. Well, saving to gallery works on all charts in the example app now, and you can quickly see the code for each example in the menus. The only real potential "breaking" change is that charts are now saved as PNGs by default instead of JPGs if you go the route of not specifying as a JPG. You may want to double check your file sizes as PNGs can be larger than low quality JPGs. I still have more plans for simplifying the API and fixing other issues with the project, for the small few that closely pay attention to individual commits: there's going to be more soon. --- MPChartExample/AndroidManifest.xml | 99 ++-- MPChartExample/build.gradle | 38 +- MPChartExample/res/drawable-nodpi/marker.png | Bin 12480 -> 0 bytes .../res/layout/activity_age_distribution.xml | 2 +- .../res/layout/activity_awesomedesign.xml | 6 +- .../res/layout/activity_barchart.xml | 8 +- .../layout/activity_barchart_noseekbar.xml | 4 +- .../res/layout/activity_barchart_sinus.xml | 2 +- .../res/layout/activity_bubblechart.xml | 8 +- .../layout/activity_bubblechart_noseekbar.xml | 4 +- .../res/layout/activity_candlechart.xml | 8 +- .../layout/activity_candlechart_noseekbar.xml | 4 +- .../res/layout/activity_colored_lines.xml | 2 +- .../res/layout/activity_combined.xml | 2 +- .../res/layout/activity_draw_chart.xml | 2 +- .../layout/activity_horizontalbarchart.xml | 8 +- .../activity_horizontalbarchart_noseekbar.xml | 4 +- .../res/layout/activity_linechart.xml | 11 +- .../layout/activity_linechart_noseekbar.xml | 4 +- .../res/layout/activity_linechart_time.xml | 2 +- .../res/layout/activity_listview_chart.xml | 2 +- MPChartExample/res/layout/activity_main.xml | 5 +- .../layout/activity_performance_linechart.xml | 5 +- .../res/layout/activity_piechart.xml | 8 +- .../res/layout/activity_piechart_half.xml | 4 +- .../layout/activity_piechart_noseekbar.xml | 4 +- .../res/layout/activity_radarchart.xml | 2 +- .../layout/activity_radarchart_noseekbar.xml | 22 - .../res/layout/activity_realm_wiki.xml | 3 +- .../layout/activity_realtime_linechart.xml | 2 +- .../res/layout/activity_scatterchart.xml | 8 +- .../activity_scatterchart_noseekbar.xml | 4 +- .../res/layout/activity_scrollview.xml | 14 +- .../res/layout/custom_marker_view.xml | 6 +- MPChartExample/res/layout/frag_simple_bar.xml | 6 +- MPChartExample/res/layout/list_item.xml | 8 +- .../res/layout/list_item_section.xml | 42 ++ .../res/layout/radar_markerview.xml | 9 +- MPChartExample/res/menu/bar.xml | 46 +- MPChartExample/res/menu/bubble.xml | 36 +- MPChartExample/res/menu/candle.xml | 46 +- MPChartExample/res/menu/combined.xml | 13 +- MPChartExample/res/menu/draw.xml | 26 +- MPChartExample/res/menu/dynamical.xml | 30 +- MPChartExample/res/menu/line.xml | 51 +- MPChartExample/res/menu/main.xml | 12 +- MPChartExample/res/menu/only_github.xml | 7 + MPChartExample/res/menu/pie.xml | 44 +- MPChartExample/res/menu/radar.xml | 49 +- MPChartExample/res/menu/realm.xml | 9 +- MPChartExample/res/menu/realtime.xml | 17 +- MPChartExample/res/menu/scatter.xml | 34 +- MPChartExample/res/values-sw600dp/dimens.xml | 8 - .../res/values-sw720dp-land/dimens.xml | 9 - MPChartExample/res/values-v11/styles.xml | 11 - MPChartExample/res/values-v14/styles.xml | 12 - MPChartExample/res/values/dimens.xml | 7 - MPChartExample/res/values/strings.xml | 51 +- MPChartExample/res/values/styles.xml | 14 +- .../mpchartexample/AnotherBarActivity.java | 186 +++---- .../mpchartexample/BarChartActivity.java | 292 +++++------ .../BarChartActivityMultiDataset.java | 256 +++++----- .../mpchartexample/BarChartActivitySinus.java | 182 +++---- .../BarChartPositiveNegative.java | 97 ++-- .../mpchartexample/BubbleChartActivity.java | 238 +++++---- .../CandleStickChartActivity.java | 219 +++++---- .../mpchartexample/CombinedChartActivity.java | 96 ++-- .../CubicLineChartActivity.java | 267 +++++----- .../mpchartexample/DrawChartActivity.java | 84 ++-- .../DynamicalAddingActivity.java | 153 +++--- .../mpchartexample/FilledLineActivity.java | 119 +++-- .../mpchartexample/HalfPieChartActivity.java | 103 ++-- .../HorizontalBarChartActivity.java | 230 ++++----- .../InvertedLineChartActivity.java | 205 ++++---- .../mpchartexample/LineChartActivity1.java | 462 +++++++++--------- .../mpchartexample/LineChartActivity2.java | 344 ++++++------- .../LineChartActivityColored.java | 72 ++- .../mpchartexample/LineChartTime.java | 220 +++++---- .../ListViewBarChartActivity.java | 79 ++- .../ListViewMultiChartActivity.java | 116 +++-- .../MultiLineChartActivity.java | 285 +++++++---- .../mpchartexample/PerformanceLineChart.java | 138 +++--- .../mpchartexample/PieChartActivity.java | 271 +++++----- .../PiePolylineChartActivity.java | 259 +++++----- .../mpchartexample/RadarChartActivity.java | 222 +++++---- .../RealtimeLineChartActivity.java | 129 +++-- .../mpchartexample/ScatterChartActivity.java | 233 ++++----- .../mpchartexample/ScrollViewActivity.java | 69 ++- .../mpchartexample/StackedBarActivity.java | 226 ++++----- .../StackedBarActivityNegative.java | 156 +++--- .../custom/DayAxisValueFormatter.java | 2 +- .../custom/MyCustomXAxisValueFormatter.java | 3 + .../custom/MyFillFormatter.java | 9 +- .../mpchartexample/custom/MyMarkerView.java | 10 +- .../custom/RadarMarkerView.java | 10 +- .../mpchartexample/custom/RealmDemoData.java | 47 +- .../mpchartexample/custom/RealmFloat.java | 1 + .../custom/StackedBarsMarkerView.java | 13 +- .../mpchartexample/custom/XYMarkerView.java | 6 +- .../custom/YearXAxisFormatter.java | 6 +- .../fragments/BarChartFrag.java | 68 +-- .../fragments/ComplexityFragment.java | 51 +- .../fragments/PieChartFrag.java | 48 +- .../fragments/ScatterChartFrag.java | 55 ++- .../fragments/SimpleChartDemo.java | 61 ++- .../fragments/SimpleFragment.java | 144 +++--- .../fragments/SineCosineFragment.java | 51 +- .../listviewitems/BarChartItem.java | 18 +- .../listviewitems/ChartItem.java | 25 +- .../listviewitems/LineChartItem.java | 6 +- .../listviewitems/PieChartItem.java | 5 +- .../notimportant/ContentItem.java | 7 + .../mpchartexample/notimportant/DemoBase.java | 77 ++- .../notimportant/MainActivity.java | 271 ++++------ .../notimportant/MyAdapter.java | 39 +- .../realm/RealmBaseActivity.java | 7 +- .../realm/RealmDatabaseActivityBar.java | 8 +- .../realm/RealmDatabaseActivityBubble.java | 4 +- .../realm/RealmDatabaseActivityCandle.java | 4 +- .../RealmDatabaseActivityHorizontalBar.java | 8 +- .../realm/RealmDatabaseActivityLine.java | 4 +- .../realm/RealmDatabaseActivityPie.java | 2 +- .../realm/RealmDatabaseActivityRadar.java | 28 +- .../realm/RealmDatabaseActivityScatter.java | 4 +- .../realm/RealmMainActivity.java | 6 +- .../realm/RealmWikiExample.java | 13 +- .../mpchartexample/realm/Score.java | 37 +- MPChartLib/build.gradle | 11 +- .../charting/animation/ChartAnimator.java | 2 +- .../mikephil/charting/animation/Easing.java | 3 +- .../mikephil/charting/charts/Chart.java | 17 +- .../mikephil/charting/components/YAxis.java | 36 +- .../listener/PieRadarChartTouchListener.java | 1 + .../renderer/BubbleChartRenderer.java | 5 +- .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 6 +- .../renderer/ScatterChartRenderer.java | 5 +- build.gradle | 2 +- gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 140 files changed, 4397 insertions(+), 3771 deletions(-) delete mode 100644 MPChartExample/res/drawable-nodpi/marker.png delete mode 100644 MPChartExample/res/layout/activity_radarchart_noseekbar.xml create mode 100644 MPChartExample/res/layout/list_item_section.xml create mode 100644 MPChartExample/res/menu/only_github.xml delete mode 100644 MPChartExample/res/values-sw600dp/dimens.xml delete mode 100644 MPChartExample/res/values-sw720dp-land/dimens.xml delete mode 100644 MPChartExample/res/values-v11/styles.xml delete mode 100644 MPChartExample/res/values-v14/styles.xml delete mode 100644 MPChartExample/res/values/dimens.xml diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 3fa15cd69c..292e0933a2 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,71 +1,66 @@ + package="com.xxmassdeveloper.mpchartexample"> - + android:theme="@style/AppTheme"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 8e6fe137b8..2856bc0109 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -2,14 +2,14 @@ apply plugin: 'com.android.application' apply plugin: 'realm-android' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 28 defaultConfig { + applicationId "com.xxmassdeveloper.mpchartexample" minSdkVersion 16 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 56 versionName '3.0.3' - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" sourceSets { main { @@ -33,17 +33,14 @@ android { } } -buildscript { - repositories { - jcenter() - google() - } - dependencies { - classpath 'com.android.tools.build:gradle:3.1.2' - //classpath 'io.realm:realm-gradle-plugin:0.88.2' - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } +dependencies { + implementation "androidx.appcompat:appcompat:1.0.0" + implementation 'com.google.android.material:material:1.0.0' + //implementation "androidx.legacy:legacy-support-v4:1.0.0" + //implementation "androidx.legacy:legacy-support-v13:1.0.0" + //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: + implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' + implementation project(':MPChartLib') } repositories { @@ -52,14 +49,3 @@ repositories { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' } } - -dependencies { - //compile fileTree(dir: 'libs', include: ['*.jar']) - //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' - - implementation project(':MPChartLib') - implementation 'com.android.support:appcompat-v7:27.1.1' - //compile 'io.realm:realm-android:0.87.5' // dependency for realm-database API (http://realm.io) - //compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' -} diff --git a/MPChartExample/res/drawable-nodpi/marker.png b/MPChartExample/res/drawable-nodpi/marker.png deleted file mode 100644 index 616cdd7b31c3b3f511793ee72b9c9f595af4c2b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12480 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 KMNUMnLSTa9_GI<| diff --git a/MPChartExample/res/layout/activity_age_distribution.xml b/MPChartExample/res/layout/activity_age_distribution.xml index b023d3ab2d..574510fa0b 100644 --- a/MPChartExample/res/layout/activity_age_distribution.xml +++ b/MPChartExample/res/layout/activity_age_distribution.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - - + + + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_barchart_sinus.xml b/MPChartExample/res/layout/activity_barchart_sinus.xml index 78b849081f..f39f2c7739 100644 --- a/MPChartExample/res/layout/activity_barchart_sinus.xml +++ b/MPChartExample/res/layout/activity_barchart_sinus.xml @@ -28,7 +28,7 @@ android:layout_height="wrap_content" android:layout_alignBottom="@+id/seekbarValues" android:layout_alignParentRight="true" - android:text="0" + android:text="@string/dash" android:layout_marginBottom="15dp" android:layout_marginRight="10dp" android:gravity="right" diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/res/layout/activity_bubblechart.xml index 1cc55dfb42..d3df042fd0 100644 --- a/MPChartExample/res/layout/activity_bubblechart.xml +++ b/MPChartExample/res/layout/activity_bubblechart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_candlechart.xml b/MPChartExample/res/layout/activity_candlechart.xml index f9384c9158..39df4c8104 100644 --- a/MPChartExample/res/layout/activity_candlechart.xml +++ b/MPChartExample/res/layout/activity_candlechart.xml @@ -1,14 +1,14 @@ + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_colored_lines.xml b/MPChartExample/res/layout/activity_colored_lines.xml index cac3442e54..f6b61cfc54 100644 --- a/MPChartExample/res/layout/activity_colored_lines.xml +++ b/MPChartExample/res/layout/activity_colored_lines.xml @@ -2,7 +2,7 @@ + android:orientation="vertical"> - + diff --git a/MPChartExample/res/layout/activity_draw_chart.xml b/MPChartExample/res/layout/activity_draw_chart.xml index 5b3792395b..5e2f1a21fc 100644 --- a/MPChartExample/res/layout/activity_draw_chart.xml +++ b/MPChartExample/res/layout/activity_draw_chart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_linechart.xml b/MPChartExample/res/layout/activity_linechart.xml index 7cadd8dd65..d7cd3a1e39 100644 --- a/MPChartExample/res/layout/activity_linechart.xml +++ b/MPChartExample/res/layout/activity_linechart.xml @@ -1,5 +1,6 @@ - @@ -8,7 +9,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/seekBar1" /> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_linechart_time.xml b/MPChartExample/res/layout/activity_linechart_time.xml index 27f70f8ba3..c63d3e6f41 100644 --- a/MPChartExample/res/layout/activity_linechart_time.xml +++ b/MPChartExample/res/layout/activity_linechart_time.xml @@ -25,7 +25,7 @@ android:layout_width="50dp" android:layout_height="wrap_content" android:layout_alignParentRight="true" - android:text="500" + android:text="@string/dash" android:layout_marginBottom="15dp" android:layout_marginRight="10dp" android:gravity="right" diff --git a/MPChartExample/res/layout/activity_listview_chart.xml b/MPChartExample/res/layout/activity_listview_chart.xml index b11c3d1ef8..12aa2f8500 100644 --- a/MPChartExample/res/layout/activity_listview_chart.xml +++ b/MPChartExample/res/layout/activity_listview_chart.xml @@ -2,7 +2,7 @@ + android:orientation="vertical"> + android:layout_height="fill_parent" + android:scrollbarFadeDuration="0"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_performance_linechart.xml b/MPChartExample/res/layout/activity_performance_linechart.xml index d7cd5747fe..515321e1de 100644 --- a/MPChartExample/res/layout/activity_performance_linechart.xml +++ b/MPChartExample/res/layout/activity_performance_linechart.xml @@ -1,8 +1,7 @@ + android:layout_height="match_parent"> + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_piechart_noseekbar.xml b/MPChartExample/res/layout/activity_piechart_noseekbar.xml index 52c62806b0..a92eec3c48 100644 --- a/MPChartExample/res/layout/activity_piechart_noseekbar.xml +++ b/MPChartExample/res/layout/activity_piechart_noseekbar.xml @@ -1,11 +1,11 @@ + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_radarchart.xml b/MPChartExample/res/layout/activity_radarchart.xml index a197875bb8..aff98010c8 100644 --- a/MPChartExample/res/layout/activity_radarchart.xml +++ b/MPChartExample/res/layout/activity_radarchart.xml @@ -1,7 +1,7 @@ + android:layout_height="match_parent"> - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/activity_realm_wiki.xml b/MPChartExample/res/layout/activity_realm_wiki.xml index d4e27933cf..a9ba53fa6f 100644 --- a/MPChartExample/res/layout/activity_realm_wiki.xml +++ b/MPChartExample/res/layout/activity_realm_wiki.xml @@ -2,7 +2,6 @@ - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_realtime_linechart.xml b/MPChartExample/res/layout/activity_realtime_linechart.xml index 0f09b88325..9ee392a8f2 100644 --- a/MPChartExample/res/layout/activity_realtime_linechart.xml +++ b/MPChartExample/res/layout/activity_realtime_linechart.xml @@ -7,5 +7,5 @@ android:id="@+id/chart1" android:layout_width="match_parent" android:layout_height="match_parent"/> - + diff --git a/MPChartExample/res/layout/activity_scatterchart.xml b/MPChartExample/res/layout/activity_scatterchart.xml index 947f8ce56d..41df167e5a 100644 --- a/MPChartExample/res/layout/activity_scatterchart.xml +++ b/MPChartExample/res/layout/activity_scatterchart.xml @@ -1,14 +1,14 @@ + android:layout_height="match_parent"> - + + android:layout_height="match_parent"> - \ No newline at end of file + diff --git a/MPChartExample/res/layout/activity_scrollview.xml b/MPChartExample/res/layout/activity_scrollview.xml index 95c78fedeb..f4865426fd 100644 --- a/MPChartExample/res/layout/activity_scrollview.xml +++ b/MPChartExample/res/layout/activity_scrollview.xml @@ -1,18 +1,18 @@ + android:layout_height="wrap_content"> - + + android:text="@string/scrollViewStart" /> @@ -30,13 +30,13 @@ - + - + android:text="@string/scrollViewEnd" /> + - \ No newline at end of file + diff --git a/MPChartExample/res/layout/custom_marker_view.xml b/MPChartExample/res/layout/custom_marker_view.xml index 12cb53c2e2..f8444bf8c4 100644 --- a/MPChartExample/res/layout/custom_marker_view.xml +++ b/MPChartExample/res/layout/custom_marker_view.xml @@ -1,8 +1,10 @@ + android:background="@drawable/marker2" + tools:ignore="Overdraw"> - - + diff --git a/MPChartExample/res/layout/list_item.xml b/MPChartExample/res/layout/list_item.xml index c9c11e93ba..2b6069b4f4 100644 --- a/MPChartExample/res/layout/list_item.xml +++ b/MPChartExample/res/layout/list_item.xml @@ -12,7 +12,7 @@ android:layout_alignParentTop="true" android:layout_marginLeft="4dp" android:text="Medium Text" - android:textSize="16dp"/> + android:textSize="16sp"/> @@ -32,11 +32,11 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" - android:text="NEW" + android:text="@string/textNew" android:background="@drawable/new_background" android:textColor="@android:color/white" android:id="@+id/tvNew" - android:textSize="11dp" + android:textSize="12sp" android:layout_marginRight="5dp" android:layout_centerVertical="true" android:layout_alignParentRight="true" diff --git a/MPChartExample/res/layout/list_item_section.xml b/MPChartExample/res/layout/list_item_section.xml new file mode 100644 index 0000000000..f71901d1fb --- /dev/null +++ b/MPChartExample/res/layout/list_item_section.xml @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/MPChartExample/res/layout/radar_markerview.xml b/MPChartExample/res/layout/radar_markerview.xml index 9ab1b84121..d94768dd67 100644 --- a/MPChartExample/res/layout/radar_markerview.xml +++ b/MPChartExample/res/layout/radar_markerview.xml @@ -1,8 +1,10 @@ + android:background="@drawable/radar_marker" + tools:ignore="Overdraw"> + android:textAppearance="?android:attr/textAppearanceSmall" + tools:ignore="SmallSp" /> diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index 4bbfedd4db..e05fc59797 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -2,48 +2,48 @@ + android:id="@+id/viewGithub" + android:title="@string/viewGithub"> + android:id="@+id/actionToggleBarBorders" + android:title="@string/actionToggleBarBorders"> + android:id="@+id/actionToggleValues" + android:title="@string/actionToggleValues"> + android:id="@+id/actionToggleIcons" + android:title="@string/actionToggleIcons"> + android:id="@+id/actionToggleHighlight" + android:title="@string/actionToggleHighlight"> + android:id="@+id/actionTogglePinch" + android:title="@string/actionTogglePinch"> + android:id="@+id/actionToggleAutoScaleMinMax" + android:title="@string/actionToggleAutoScale"> + android:id="@+id/animateX" + android:title="@string/animateX"> + android:id="@+id/animateY" + android:title="@string/animateY"> + android:id="@+id/animateXY" + android:title="@string/animateXY"> + android:id="@+id/actionSave" + android:title="@string/actionSave"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/res/menu/bubble.xml index b7950291e9..7b9ab5cd11 100644 --- a/MPChartExample/res/menu/bubble.xml +++ b/MPChartExample/res/menu/bubble.xml @@ -1,45 +1,45 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleHighlight"> + + + android:id="@+id/actionToggleAutoScaleMinMax" + android:title="@string/actionToggleAutoScale"> + android:title="@string/animateX"> + android:title="@string/animateY"> + android:title="@string/animateXY"> - - - - + android:title="@string/actionSave"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/candle.xml b/MPChartExample/res/menu/candle.xml index cdf1c4e4dd..42a1a7e050 100644 --- a/MPChartExample/res/menu/candle.xml +++ b/MPChartExample/res/menu/candle.xml @@ -2,40 +2,48 @@ + android:id="@+id/viewGithub" + android:title="@string/viewGithub"> - - + android:id="@+id/actionToggleValues" + android:title="@string/actionToggleValues"> + android:id="@+id/actionToggleIcons" + android:title="@string/actionToggleIcons"> + android:id="@+id/actionToggleHighlight" + android:title="@string/actionToggleHighlight"> + android:id="@+id/actionToggleMakeShadowSameColorAsCandle" + android:title="@string/actionToggleCandleShadow"> + android:title="@string/actionTogglePinch"> + android:title="@string/actionToggleAutoScale"> + android:id="@+id/animateX" + android:title="@string/animateX"> + + + + + + - \ No newline at end of file + diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/res/menu/combined.xml index 7e37ba0d83..c7def2509c 100644 --- a/MPChartExample/res/menu/combined.xml +++ b/MPChartExample/res/menu/combined.xml @@ -1,16 +1,21 @@ + + + android:title="@string/actionToggleLineValues"> + android:title="@string/actionToggleBarValues"> + android:title="@string/actionRemoveDataSet"> - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/draw.xml b/MPChartExample/res/menu/draw.xml index 50f35239e7..36383db54f 100644 --- a/MPChartExample/res/menu/draw.xml +++ b/MPChartExample/res/menu/draw.xml @@ -3,34 +3,30 @@ + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleCircles"> - - - - + android:title="@string/actionToggleHighlight"> + android:title="@string/actionTogglePinch"> + android:title="@string/actionToggleAutoScale"> + + - \ No newline at end of file + diff --git a/MPChartExample/res/menu/dynamical.xml b/MPChartExample/res/menu/dynamical.xml index c43a3a0ae6..68d4fab0c9 100644 --- a/MPChartExample/res/menu/dynamical.xml +++ b/MPChartExample/res/menu/dynamical.xml @@ -1,33 +1,33 @@ + + + android:title="@string/actionAddEntry"> - + android:title="@string/actionRemoveEntry"> - - + android:title="@string/actionAddDataSet"> - + android:title="@string/actionRemoveDataSet"> - + android:id="@+id/actionClear" + android:title="@string/actionClearChart"> - + android:id="@+id/actionSave" + android:title="@string/actionSave"> - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index f9f5be9615..a812b91b5a 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -1,64 +1,65 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleCircles"> + android:title="@string/actionToggleCubic"> + android:title="@string/actionToggleStepped"> + android:title="@string/actionToggleHorizontalCubic"> + + + + + android:title="@string/actionToggleHighlight"> + android:title="@string/animateX"> + android:title="@string/animateY"> - - + android:title="@string/animateXY"> - - + android:title="@string/actionSave"> - - - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/main.xml b/MPChartExample/res/menu/main.xml index b45d3bbb9f..9ac13dbbae 100644 --- a/MPChartExample/res/menu/main.xml +++ b/MPChartExample/res/menu/main.xml @@ -3,19 +3,15 @@ + android:title="@string/viewGithub"> - - + android:title="@string/reportProblem"> + android:title="@string/viewWebsite"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/only_github.xml b/MPChartExample/res/menu/only_github.xml new file mode 100644 index 0000000000..c0a9b66934 --- /dev/null +++ b/MPChartExample/res/menu/only_github.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/res/menu/pie.xml index 0e5323a590..b2de043409 100644 --- a/MPChartExample/res/menu/pie.xml +++ b/MPChartExample/res/menu/pie.xml @@ -1,49 +1,53 @@ + + + android:title="@string/actionToggleYValues"> + android:id="@+id/actionToggleXValues" + android:title="@string/actionToggleXValues"> + android:id="@+id/actionToggleIcons" + android:title="@string/actionToggleIcons"> + android:title="@string/actionTogglePercent"> + android:title="@string/actionToggleHole"> + + + + + android:title="@string/animateX"> + android:title="@string/animateY"> - - + android:title="@string/animateXY"> - - + android:title="@string/actionSave"> - \ No newline at end of file + diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/res/menu/radar.xml index 14690f446c..2a5c19cf81 100644 --- a/MPChartExample/res/menu/radar.xml +++ b/MPChartExample/res/menu/radar.xml @@ -1,57 +1,62 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> + android:title="@string/actionToggleFilled"> + android:title="@string/actionToggleHighlight"> + android:title="@string/actionToggleHighlightCircle"> + android:id="@+id/actionToggleRotate" + android:title="@string/actionToggleRotation"> + android:id="@+id/actionToggleYLabels" + android:title="@string/actionToggleYValues"> + android:id="@+id/actionToggleXLabels" + android:title="@string/actionToggleXValues"> + android:id="@+id/actionToggleSpin" + android:title="@string/actionToggleSpin"> + android:id="@+id/animateX" + android:title="@string/animateX"> + android:id="@+id/animateY" + android:title="@string/animateY"> + android:id="@+id/animateXY" + android:title="@string/animateXY"> + android:id="@+id/actionSave" + android:title="@string/actionSave"> - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/realm.xml b/MPChartExample/res/menu/realm.xml index f954443b30..ce149bef91 100644 --- a/MPChartExample/res/menu/realm.xml +++ b/MPChartExample/res/menu/realm.xml @@ -1,8 +1,13 @@ + + + android:title="@string/realmIOWebsite"> - \ No newline at end of file + + diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/res/menu/realtime.xml index a4b2d22a78..48cc7ccd0a 100644 --- a/MPChartExample/res/menu/realtime.xml +++ b/MPChartExample/res/menu/realtime.xml @@ -1,16 +1,25 @@ + + + android:title="@string/actionAddEntry"> + android:title="@string/actionClearChart"> + android:title="@string/actionFeedMultiple"> - \ No newline at end of file + + + + diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/res/menu/scatter.xml index b7950291e9..eb8e0efa67 100644 --- a/MPChartExample/res/menu/scatter.xml +++ b/MPChartExample/res/menu/scatter.xml @@ -1,45 +1,45 @@ + + + android:title="@string/actionToggleValues"> + android:title="@string/actionToggleIcons"> - - + android:title="@string/actionToggleHighlight"> + android:title="@string/animateX"> + android:title="@string/animateY"> - - + android:title="@string/animateXY"> + android:title="@string/actionTogglePinch"> + android:title="@string/actionToggleAutoScale"> + + - \ No newline at end of file + diff --git a/MPChartExample/res/values-sw600dp/dimens.xml b/MPChartExample/res/values-sw600dp/dimens.xml deleted file mode 100644 index 44f01db75f..0000000000 --- a/MPChartExample/res/values-sw600dp/dimens.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/MPChartExample/res/values-sw720dp-land/dimens.xml b/MPChartExample/res/values-sw720dp-land/dimens.xml deleted file mode 100644 index 61e3fa8fbc..0000000000 --- a/MPChartExample/res/values-sw720dp-land/dimens.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - 128dp - - diff --git a/MPChartExample/res/values-v11/styles.xml b/MPChartExample/res/values-v11/styles.xml deleted file mode 100644 index 3c02242ad0..0000000000 --- a/MPChartExample/res/values-v11/styles.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/values-v14/styles.xml b/MPChartExample/res/values-v14/styles.xml deleted file mode 100644 index a91fd0372b..0000000000 --- a/MPChartExample/res/values-v14/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/values/dimens.xml b/MPChartExample/res/values/dimens.xml deleted file mode 100644 index 55c1e5908c..0000000000 --- a/MPChartExample/res/values/dimens.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - 16dp - 16dp - - diff --git a/MPChartExample/res/values/strings.xml b/MPChartExample/res/values/strings.xml index 7f59af64bb..d81d9b1a0c 100644 --- a/MPChartExample/res/values/strings.xml +++ b/MPChartExample/res/values/strings.xml @@ -2,7 +2,54 @@ MPAndroidChart Example - Settings - Hello world! + + View on GitHub + Problem Report + Developer Website + Save to Gallery + realm.io website + + Animate X + Animate Y + Animate XY + + Toggle Values + Toggle Y-Values + Toggle X-Values + + Toggle Icons + Toggle Highlight + Toggle PinchZoom + Toggle Auto Scale + + Toggle Line Values + Toggle Bar Values + Toggle Bar Borders + Toggle Filled + Toggle Circles + Toggle Shadow Color + + Toggle Cubic + Toggle Stepped + Toggle Horizontal Cubic + + Add Entry + Add Multiple + Remove Entry + Add Data Set + Remove Data Set + Clear chart + + Toggle Percent + Toggle Hole + Draw Center Text + Toggle Highlight Circle + Toggle Rotation + Spin Animation + + - + START OF SCROLLVIEW + END OF SCROLLVIEW + NEW diff --git a/MPChartExample/res/values/styles.xml b/MPChartExample/res/values/styles.xml index 6ce89c7ba4..9d5b53bd6c 100644 --- a/MPChartExample/res/values/styles.xml +++ b/MPChartExample/res/values/styles.xml @@ -1,19 +1,7 @@ - - - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index f6cffddcbe..5916619645 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -1,14 +1,18 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; @@ -25,8 +29,8 @@ public class AnotherBarActivity extends DemoBase implements OnSeekBarChangeListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -36,48 +40,89 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("AnotherBarActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); + chart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); - - mChart.getAxisLeft().setDrawGridLines(false); + + chart.getAxisLeft().setDrawGridLines(false); // setting data - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(100); + seekBarX.setProgress(10); + seekBarY.setProgress(100); // add a nice and smooth animation - mChart.animateY(2500); - - mChart.getLegend().setEnabled(false); + chart.animateY(1500); + + chart.getLegend().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float multi = (seekBarY.getProgress() + 1); + float val = (float) (Math.random() * multi) + multi / 3; + values.add(new BarEntry(i, val)); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "Data Set"); + set1.setColors(ColorTemplate.VORDIPLOM_COLORS); + set1.setDrawValues(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + chart.setData(data); + chart.setFitBars(true); + } + + chart.invalidate(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); + menu.removeItem(R.id.actionToggleIcons); return true; } @@ -85,63 +130,71 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } + /* + case R.id.actionToggleIcons: { break; } + */ case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -149,52 +202,13 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val = (float) (Math.random() * mult) + mult / 3; - yVals1.add(new BarEntry(i, val)); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "Data Set"); - set1.setColors(ColorTemplate.VORDIPLOM_COLORS); - set1.setDrawValues(false); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(dataSets); - mChart.setData(data); - mChart.setFitBars(true); - } - - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "AnotherBarActivity"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index c0e3405625..fcdaae364d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -1,10 +1,13 @@ package com.xxmassdeveloper.mpchartexample; -import android.annotation.SuppressLint; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.RectF; +import android.net.Uri; import android.os.Bundle; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -12,7 +15,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; @@ -32,7 +34,6 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.model.GradientColor; -import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; @@ -45,8 +46,8 @@ public class BarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - protected BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -56,35 +57,40 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("BarChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - // mChart.setDrawYLabels(false); + chart.setDrawGridBackground(false); + // chart.setDrawYLabels(false); - IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart); + IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day xAxis.setLabelCount(7); @@ -92,23 +98,23 @@ protected void onCreate(Bundle savedInstanceState) { IAxisValueFormatter custom = new MyAxisValueFormatter(); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(8, false); leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); leftAxis.setSpaceTop(15f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -117,25 +123,85 @@ protected void onCreate(Bundle savedInstanceState) { l.setFormSize(9f); l.setTextSize(11f); l.setXEntrySpace(4f); - // l.setExtra(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", - // "def", "ghj", "ikl", "mno" }); - // l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", - // "def", "ghj", "ikl", "mno" }); XYMarkerView mv = new XYMarkerView(this, xAxisFormatter); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart + // setting data + seekBarY.setProgress(50); + seekBarX.setProgress(12); setData(12, 50); - // setting data - mSeekBarY.setProgress(50); - mSeekBarX.setProgress(12); + // chart.setDrawLegend(false); + } + + private void setData(int count, float range) { + + float start = 1f; + + ArrayList values = new ArrayList<>(); + + for (int i = (int) start; i < start + count; i++) { + float val = (float) (Math.random() * (range + 1)); + + if (Math.random() * 100 < 25) { + values.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); + } else { + values.add(new BarEntry(i, val)); + } + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + + } else { + set1 = new BarDataSet(values, "The year 2017"); + + set1.setDrawIcons(false); + +// set1.setColors(ColorTemplate.MATERIAL_COLORS); + + /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); + int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); + set1.setGradientColor(startColor, endColor);*/ + + int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); + int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); + int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); + int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); + int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); + int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); + int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); + int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); + int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); + + List gradientColors = new ArrayList<>(); + gradientColors.add(new GradientColor(startColor1, endColor1)); + gradientColors.add(new GradientColor(startColor2, endColor2)); + gradientColors.add(new GradientColor(startColor3, endColor3)); + gradientColors.add(new GradientColor(startColor4, endColor4)); + gradientColors.add(new GradientColor(startColor5, endColor5)); + + set1.setGradientColors(gradientColors); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); - // mChart.setDrawLegend(false); + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(0.9f); + + chart.setData(data); + } } @Override @@ -148,68 +214,72 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -219,110 +289,42 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 2)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1 , mSeekBarY.getProgress()); - mChart.invalidate(); + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + public void saveToGallery() { + saveToGallery(chart, "BarChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } - - private void setData(int count, float range) { - - float start = 1f; - - ArrayList yVals1 = new ArrayList(); - - for (int i = (int) start; i < start + count + 1; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult); - - if (Math.random() * 100 < 25) { - yVals1.add(new BarEntry(i, val, getResources().getDrawable(R.drawable.star))); - } else { - yVals1.add(new BarEntry(i, val)); - } - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "The year 2017"); - - set1.setDrawIcons(false); - -// set1.setColors(ColorTemplate.MATERIAL_COLORS); - - /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); - set1.setGradientColor(startColor, endColor);*/ - - int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); - int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); - int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); - int startColor4 = ContextCompat.getColor(this, android.R.color.holo_green_light); - int startColor5 = ContextCompat.getColor(this, android.R.color.holo_red_light); - int endColor1 = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor2 = ContextCompat.getColor(this, android.R.color.holo_purple); - int endColor3 = ContextCompat.getColor(this, android.R.color.holo_green_dark); - int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); - int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); - - List gradientColors = new ArrayList<>(); - gradientColors.add(new GradientColor(startColor1, endColor1)); - gradientColors.add(new GradientColor(startColor2, endColor2)); - gradientColors.add(new GradientColor(startColor3, endColor3)); - gradientColors.add(new GradientColor(startColor4, endColor4)); - gradientColors.add(new GradientColor(startColor5, endColor5)); - - set1.setGradientColors(gradientColors); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + public void onStartTrackingTouch(SeekBar seekBar) {} - BarData data = new BarData(dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setBarWidth(0.9f); - - mChart.setData(data); - } - } + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - protected RectF mOnValueSelectedRectF = new RectF(); + private RectF onValueSelectedRectF = new RectF(); - @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { if (e == null) return; - RectF bounds = mOnValueSelectedRectF; - mChart.getBarBounds((BarEntry) e, bounds); - MPPointF position = mChart.getPosition(e, AxisDependency.LEFT); + RectF bounds = onValueSelectedRectF; + chart.getBarBounds((BarEntry) e, bounds); + MPPointF position = chart.getPosition(e, AxisDependency.LEFT); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); Log.i("x-index", - "low: " + mChart.getLowestVisibleX() + ", high: " - + mChart.getHighestVisibleX()); + "low: " + chart.getLowestVisibleX() + ", high: " + + chart.getHighestVisibleX()); MPPointF.recycleInstance(position); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 204dc1fe64..d0c0bc453d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -29,12 +34,13 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.Locale; public class BarChartActivityMultiDataset extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,51 +50,53 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("BarChartActivityMultiDataset"); + tvX = findViewById(R.id.tvXMax); tvX.setTextSize(10); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.getDescription().setEnabled(false); -// mChart.setDrawBorders(true); +// chart.setDrawBorders(true); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawBarShadow(false); + chart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(100); + seekBarX.setProgress(10); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(true); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setYOffset(0f); l.setXOffset(10f); l.setYEntrySpace(0f); l.setTextSize(8f); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); xAxis.setValueFormatter(new IAxisValueFormatter() { @@ -98,14 +106,88 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); leftAxis.setSpaceTop(35f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + float groupSpace = 0.08f; + float barSpace = 0.03f; // x4 DataSet + float barWidth = 0.2f; // x4 DataSet + // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" + + int groupCount = seekBarX.getProgress() + 1; + int startYear = 1980; + int endYear = startYear + groupCount; + + tvX.setText(String.format(Locale.ENGLISH, "%d-%d", startYear, endYear)); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + ArrayList values4 = new ArrayList<>(); + + float randomMultiplier = seekBarY.getProgress() * 100000f; + + for (int i = startYear; i < endYear; i++) { + values1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + values4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); + } + + BarDataSet set1, set2, set3, set4; + + if (chart.getData() != null && chart.getData().getDataSetCount() > 0) { + + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set2 = (BarDataSet) chart.getData().getDataSetByIndex(1); + set3 = (BarDataSet) chart.getData().getDataSetByIndex(2); + set4 = (BarDataSet) chart.getData().getDataSetByIndex(3); + set1.setValues(values1); + set2.setValues(values2); + set3.setValues(values3); + set4.setValues(values4); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + + } else { + // create 4 DataSets + set1 = new BarDataSet(values1, "Company A"); + set1.setColor(Color.rgb(104, 241, 175)); + set2 = new BarDataSet(values2, "Company B"); + set2.setColor(Color.rgb(164, 228, 251)); + set3 = new BarDataSet(values3, "Company C"); + set3.setColor(Color.rgb(242, 247, 158)); + set4 = new BarDataSet(values4, "Company D"); + set4.setColor(Color.rgb(255, 102, 0)); + + BarData data = new BarData(set1, set2, set3, set4); + data.setValueFormatter(new LargeValueFormatter()); + data.setValueTypeface(tfLight); + + chart.setData(data); + } + + // specify the width each bar should have + chart.getBarData().setBarWidth(barWidth); + + // restrict the x-axis range + chart.getXAxis().setAxisMinimum(startYear); + + // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters + chart.getXAxis().setAxisMaximum(startYear + chart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); + chart.groupBars(startYear, groupSpace, barSpace); + chart.invalidate(); } @Override @@ -118,56 +200,65 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } } @@ -175,88 +266,15 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - float groupSpace = 0.08f; - float barSpace = 0.03f; // x4 DataSet - float barWidth = 0.2f; // x4 DataSet - // (0.2 + 0.03) * 4 + 0.08 = 1.00 -> interval per "group" - - int groupCount = mSeekBarX.getProgress() + 1; - int startYear = 1980; - int endYear = startYear + groupCount; - - tvX.setText(startYear + "-" + endYear); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - ArrayList yVals4 = new ArrayList(); - - float randomMultiplier = mSeekBarY.getProgress() * 100000f; - - for (int i = startYear; i < endYear; i++) { - yVals1.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals2.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals3.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - yVals4.add(new BarEntry(i, (float) (Math.random() * randomMultiplier))); - } - - BarDataSet set1, set2, set3, set4; - - if (mChart.getData() != null && mChart.getData().getDataSetCount() > 0) { - - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set2 = (BarDataSet) mChart.getData().getDataSetByIndex(1); - set3 = (BarDataSet) mChart.getData().getDataSetByIndex(2); - set4 = (BarDataSet) mChart.getData().getDataSetByIndex(3); - set1.setValues(yVals1); - set2.setValues(yVals2); - set3.setValues(yVals3); - set4.setValues(yVals4); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - - } else { - // create 4 DataSets - set1 = new BarDataSet(yVals1, "Company A"); - set1.setColor(Color.rgb(104, 241, 175)); - set2 = new BarDataSet(yVals2, "Company B"); - set2.setColor(Color.rgb(164, 228, 251)); - set3 = new BarDataSet(yVals3, "Company C"); - set3.setColor(Color.rgb(242, 247, 158)); - set4 = new BarDataSet(yVals4, "Company D"); - set4.setColor(Color.rgb(255, 102, 0)); - - BarData data = new BarData(set1, set2, set3, set4); - data.setValueFormatter(new LargeValueFormatter()); - data.setValueTypeface(mTfLight); - - mChart.setData(data); - } - - // specify the width each bar should have - mChart.getBarData().setBarWidth(barWidth); - - // restrict the x-axis range - mChart.getXAxis().setAxisMinimum(startYear); - - // barData.getGroupWith(...) is a helper that calculates the width each group needs based on the provided parameters - mChart.getXAxis().setAxisMaximum(startYear + mChart.getBarData().getGroupWidth(groupSpace, barSpace) * groupCount); - mChart.groupBars(startYear, groupSpace, barSpace); - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "BarChartActivityMultiDataset"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - } + public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 82b039909f..d7c16df440 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -1,20 +1,23 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendForm; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; @@ -29,11 +32,11 @@ public class BarChartActivitySinus extends DemoBase implements OnSeekBarChangeListener { - protected BarChart mChart; - private SeekBar mSeekBarX; + private BarChart chart; + private SeekBar seekBarX; private TextView tvX; - private List mSinusData; + private List data; @Override protected void onCreate(Bundle savedInstanceState) { @@ -42,57 +45,59 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart_sinus); - mSinusData = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); + setTitle("BarChartActivitySinus"); + + data = FileUtils.loadBarEntriesFromAssets(getAssets(), "othersine.txt"); tvX = findViewById(R.id.tvValueCount); - mSeekBarX = findViewById(R.id.seekbarValues); + seekBarX = findViewById(R.id.seekbarValues); - mChart = findViewById(R.id.chart1); + chart = findViewById(R.id.chart1); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); + // chart.setDrawBarShadow(true); - // mChart.setDrawXLabels(false); + // chart.setDrawXLabels(false); - mChart.setDrawGridBackground(false); - // mChart.setDrawYLabels(false); + chart.setDrawGridBackground(false); + // chart.setDrawYLabels(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(6, false); leftAxis.setAxisMinimum(-2.5f); leftAxis.setAxisMaximum(2.5f); leftAxis.setGranularityEnabled(true); leftAxis.setGranularity(0.1f); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(6, false); rightAxis.setAxisMinimum(-2.5f); rightAxis.setAxisMaximum(2.5f); rightAxis.setGranularity(0.1f); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarX.setProgress(150); // set data + seekBarX.setOnSeekBarChangeListener(this); + seekBarX.setProgress(150); // set data - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -102,7 +107,37 @@ protected void onCreate(Bundle savedInstanceState) { l.setTextSize(11f); l.setXEntrySpace(4f); - mChart.animateXY(2000, 2000); + chart.animateXY(1500, 1500); + } + + private void setData(int count) { + + ArrayList entries = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + entries.add(data.get(i)); + } + + BarDataSet set; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set = (BarDataSet) chart.getData().getDataSetByIndex(0); + set.setValues(entries); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set = new BarDataSet(entries, "Sinus Function"); + set.setColor(Color.rgb(240, 120, 124)); + } + + BarData data = new BarData(set); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setDrawValues(false); + data.setBarWidth(0.8f); + + chart.setData(data); } @Override @@ -115,61 +150,66 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(1500); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(1500); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(2000, 2000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -179,51 +219,21 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); - setData(mSeekBarX.getProgress()); - mChart.invalidate(); + setData(seekBarX.getProgress()); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + public void saveToGallery() { + saveToGallery(chart, "BarChartActivitySinus"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count) { - - ArrayList entries = new ArrayList(); - - for (int i = 0; i < count; i++) { - entries.add(mSinusData.get(i)); - } - - BarDataSet set; + public void onStartTrackingTouch(SeekBar seekBar) {} - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set.setValues(entries); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set = new BarDataSet(entries, "Sinus Function"); - set.setColor(Color.rgb(240, 120, 124)); - } - - BarData data = new BarData(set); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setDrawValues(false); - data.setBarWidth(0.8f); + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - mChart.setData(data); - } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 7d6bd44896..ce73317860 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -1,9 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; @@ -26,8 +29,7 @@ public class BarChartPositiveNegative extends DemoBase { - protected BarChart mChart; - private Typeface mTf; + private BarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,27 +38,28 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart_noseekbar); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); - mChart.setExtraTopOffset(-30f); - mChart.setExtraBottomOffset(10f); - mChart.setExtraLeftOffset(70f); - mChart.setExtraRightOffset(70f); + setTitle("BarChartPositiveNegative"); - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); + chart.setExtraTopOffset(-30f); + chart.setExtraBottomOffset(10f); + chart.setExtraLeftOffset(70f); + chart.setExtraRightOffset(70f); - mChart.getDescription().setEnabled(false); + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); + + chart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTf); + xAxis.setTypeface(tfRegular); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); xAxis.setTextColor(Color.LTGRAY); @@ -65,7 +68,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); - YAxis left = mChart.getAxisLeft(); + YAxis left = chart.getAxisLeft(); left.setDrawLabels(false); left.setSpaceTop(25f); left.setSpaceBottom(25f); @@ -74,8 +77,8 @@ protected void onCreate(Bundle savedInstanceState) { left.setDrawZeroLine(true); // draw a zero line left.setZeroLineColor(Color.GRAY); left.setZeroLineWidth(0.7f); - mChart.getAxisRight().setEnabled(false); - mChart.getLegend().setEnabled(false); + chart.getAxisRight().setEnabled(false); + chart.getLegend().setEnabled(false); // THIS IS THE ORIGINAL DATA YOU WANT TO PLOT final List data = new ArrayList<>(); @@ -97,8 +100,8 @@ public String getFormattedValue(float value, AxisBase axis) { private void setData(List dataList) { - ArrayList values = new ArrayList(); - List colors = new ArrayList(); + ArrayList values = new ArrayList<>(); + List colors = new ArrayList<>(); int green = Color.rgb(110, 190, 102); int red = Color.rgb(211, 74, 88); @@ -118,12 +121,12 @@ private void setData(List dataList) { BarDataSet set; - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set = (BarDataSet)mChart.getData().getDataSetByIndex(0); + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set = (BarDataSet) chart.getData().getDataSetByIndex(0); set.setValues(values); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); } else { set = new BarDataSet(values, "Values"); set.setColors(colors); @@ -131,12 +134,12 @@ private void setData(List dataList) { BarData data = new BarData(set); data.setValueTextSize(13f); - data.setValueTypeface(mTf); + data.setValueTypeface(tfRegular); data.setValueFormatter(new ValueFormatter()); data.setBarWidth(0.8f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } } @@ -145,11 +148,11 @@ private void setData(List dataList) { */ private class Data { - public String xAxisValue; - public float yValue; - public float xValue; + String xAxisValue; + float yValue; + float xValue; - public Data(float xValue, float yValue, String xAxisValue) { + Data(float xValue, float yValue, String xAxisValue) { this.xAxisValue = xAxisValue; this.yValue = yValue; this.xValue = xValue; @@ -161,7 +164,7 @@ private class ValueFormatter implements IValueFormatter private DecimalFormat mFormat; - public ValueFormatter() { + ValueFormatter() { mFormat = new DecimalFormat("######.0"); } @@ -170,4 +173,28 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View return mFormat.format(value); } } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index bc1750381e..098c8f242b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -13,7 +18,6 @@ import com.github.mikephil.charting.charts.BubbleChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BubbleData; @@ -33,10 +37,10 @@ public class BubbleChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BubbleChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BubbleChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -44,52 +48,106 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_bubblechart); + setTitle("BubbleChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); - mChart.setMaxVisibleValueCount(200); - mChart.setPinchZoom(true); + chart.setMaxVisibleValueCount(200); + chart.setPinchZoom(true); - mSeekBarX.setProgress(10); - mSeekBarY.setProgress(50); + seekBarX.setProgress(10); + seekBarY.setProgress(50); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setSpaceTop(30f); yl.setSpaceBottom(30f); yl.setDrawZeroLine(false); - - mChart.getAxisRight().setEnabled(false); - XAxis xl = mChart.getXAxis(); + chart.getAxisRight().setEnabled(false); + + XAxis xl = chart.getXAxis(); xl.setPosition(XAxis.XAxisPosition.BOTTOM); - xl.setTypeface(mTfLight); + xl.setTypeface(tfLight); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + int count = seekBarX.getProgress(); + int range = seekBarY.getProgress(); + + tvX.setText(String.valueOf(count)); + tvY.setText(String.valueOf(range)); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + values1.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range), getResources().getDrawable(R.drawable.star))); + values2.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range), getResources().getDrawable(R.drawable.star))); + values3.add(new BubbleEntry(i, (float) (Math.random() * range), (float) (Math.random() * range))); + } + + // create a dataset and give it a type + BubbleDataSet set1 = new BubbleDataSet(values1, "DS 1"); + set1.setDrawIcons(false); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); + set1.setDrawValues(true); + + BubbleDataSet set2 = new BubbleDataSet(values2, "DS 2"); + set2.setDrawIcons(false); + set2.setIconsOffset(new MPPointF(0, 15)); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); + set2.setDrawValues(true); + + BubbleDataSet set3 = new BubbleDataSet(values3, "DS 3"); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); + set3.setDrawValues(true); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + dataSets.add(set2); + dataSets.add(set3); + + // create a data object with the data sets + BubbleData data = new BubbleData(dataSets); + data.setDrawValues(false); + data.setValueTypeface(tfLight); + data.setValueTextSize(8f); + data.setValueTextColor(Color.WHITE); + data.setHighlightCircleWidth(1.5f); + + chart.setData(data); + chart.invalidate(); } @Override @@ -102,56 +160,65 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } } @@ -159,70 +226,8 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int count = mSeekBarX.getProgress(); - int range = mSeekBarY.getProgress(); - - tvX.setText("" + count); - tvY.setText("" + range); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals1.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); - } - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals2.add(new BubbleEntry(i, val, size, getResources().getDrawable(R.drawable.star))); - } - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - float size = (float) (Math.random() * range); - - yVals3.add(new BubbleEntry(i, val, size)); - } - - // create a dataset and give it a type - BubbleDataSet set1 = new BubbleDataSet(yVals1, "DS 1"); - set1.setDrawIcons(false); - set1.setColor(ColorTemplate.COLORFUL_COLORS[0], 130); - set1.setDrawValues(true); - - BubbleDataSet set2 = new BubbleDataSet(yVals2, "DS 2"); - set2.setDrawIcons(false); - set2.setIconsOffset(new MPPointF(0, 15)); - set2.setColor(ColorTemplate.COLORFUL_COLORS[1], 130); - set2.setDrawValues(true); - - BubbleDataSet set3 = new BubbleDataSet(yVals3, "DS 3"); - set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); - set3.setDrawValues(true); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - dataSets.add(set2); - dataSets.add(set3); - - // create a data object with the datasets - BubbleData data = new BubbleData(dataSets); - data.setDrawValues(false); - data.setValueTypeface(mTfLight); - data.setValueTextSize(8f); - data.setValueTextColor(Color.WHITE); - data.setHighlightCircleWidth(1.5f); - - mChart.setData(data); - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "BubbleChartActivity"); } @Override @@ -233,20 +238,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 54eb768a7b..b0b29dfbe4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -1,16 +1,20 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Paint; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.CandleStickChart; import com.github.mikephil.charting.components.XAxis; @@ -28,8 +32,8 @@ public class CandleStickChartActivity extends DemoBase implements OnSeekBarChangeListener { - private CandleStickChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private CandleStickChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -39,48 +43,103 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_candlechart); + setTitle("CandleStickChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); // leftAxis.setEnabled(false); leftAxis.setLabelCount(7, false); leftAxis.setDrawGridLines(false); leftAxis.setDrawAxisLine(false); - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); // rightAxis.setStartAtZero(false); // setting data - mSeekBarX.setProgress(40); - mSeekBarY.setProgress(100); - - mChart.getLegend().setEnabled(false); + seekBarX.setProgress(40); + seekBarY.setProgress(100); + + chart.getLegend().setEnabled(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + progress = (seekBarX.getProgress()); + + tvX.setText(String.valueOf(progress)); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + chart.resetTracking(); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < progress; i++) { + float multi = (seekBarY.getProgress() + 1); + float val = (float) (Math.random() * 40) + multi; + + float high = (float) (Math.random() * 9) + 8f; + float low = (float) (Math.random() * 9) + 8f; + + float open = (float) (Math.random() * 6) + 1f; + float close = (float) (Math.random() * 6) + 1f; + + boolean even = i % 2 == 0; + + values.add(new CandleEntry( + i, val + high, + val - low, + even ? val + open : val - open, + even ? val - close : val + close, + getResources().getDrawable(R.drawable.star) + )); + } + + CandleDataSet set1 = new CandleDataSet(values, "Data Set"); + + set1.setDrawIcons(false); + set1.setAxisDependency(AxisDependency.LEFT); +// set1.setColor(Color.rgb(80, 80, 80)); + set1.setShadowColor(Color.DKGRAY); + set1.setShadowWidth(0.7f); + set1.setDecreasingColor(Color.RED); + set1.setDecreasingPaintStyle(Paint.Style.FILL); + set1.setIncreasingColor(Color.rgb(122, 242, 84)); + set1.setIncreasingPaintStyle(Paint.Style.STROKE); + set1.setNeutralColor(Color.BLUE); + //set1.setHighlightLineWidth(1f); + + CandleData data = new CandleData(set1); + + chart.setData(data); + chart.invalidate(); } @Override @@ -93,69 +152,73 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleMakeShadowSameColorAsCandle: { - for (ICandleDataSet set : mChart.getData().getDataSets()) { - //TODO: set.setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); + for (ICandleDataSet set : chart.getData().getDataSets()) { + ((CandleDataSet) set).setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -163,67 +226,13 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int prog = (mSeekBarX.getProgress() + 1); - - tvX.setText("" + prog); - tvY.setText("" + (mSeekBarY.getProgress())); - - mChart.resetTracking(); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < prog; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val = (float) (Math.random() * 40) + mult; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - yVals1.add(new CandleEntry( - i, val + high, - val - low, - even ? val + open : val - open, - even ? val - close : val + close, - getResources().getDrawable(R.drawable.star) - )); - } - - CandleDataSet set1 = new CandleDataSet(yVals1, "Data Set"); - - set1.setDrawIcons(false); - set1.setAxisDependency(AxisDependency.LEFT); -// set1.setColor(Color.rgb(80, 80, 80)); - set1.setShadowColor(Color.DKGRAY); - set1.setShadowWidth(0.7f); - set1.setDecreasingColor(Color.RED); - set1.setDecreasingPaintStyle(Paint.Style.FILL); - set1.setIncreasingColor(Color.rgb(122, 242, 84)); - set1.setIncreasingPaintStyle(Paint.Style.STROKE); - set1.setNeutralColor(Color.BLUE); - //set1.setHighlightLineWidth(1f); - - CandleData data = new CandleData(set1); - - mChart.setData(data); - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "CandleStickChartActivity"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index e4d8fb2e3b..7526dc1d59 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -1,7 +1,9 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; @@ -38,8 +40,8 @@ public class CombinedChartActivity extends DemoBase { - private CombinedChart mChart; - private final int itemcount = 12; + private CombinedChart chart; + private final int count = 12; @Override protected void onCreate(Bundle savedInstanceState) { @@ -48,41 +50,43 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_combined); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); - mChart.setBackgroundColor(Color.WHITE); - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - mChart.setHighlightFullBarEnabled(false); + setTitle("CombinedChartActivity"); + + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); + chart.setBackgroundColor(Color.WHITE); + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + chart.setHighlightFullBarEnabled(false); // draw bars behind lines - mChart.setDrawOrder(new DrawOrder[]{ + chart.setDrawOrder(new DrawOrder[]{ DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.CANDLE, DrawOrder.LINE, DrawOrder.SCATTER }); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setWordWrapEnabled(true); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); l.setDrawInside(false); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setDrawGridLines(false); rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setDrawGridLines(false); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); xAxis.setValueFormatter(new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { - return mMonths[(int) value % mMonths.length]; + return months[(int) value % months.length]; } }); @@ -93,21 +97,21 @@ public String getFormattedValue(float value, AxisBase axis) { data.setData(generateBubbleData()); data.setData(generateScatterData()); data.setData(generateCandleData()); - data.setValueTypeface(mTfLight); + data.setValueTypeface(tfLight); xAxis.setAxisMaximum(data.getXMax() + 0.25f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } private LineData generateLineData() { LineData d = new LineData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) + for (int index = 0; index < count; index++) entries.add(new Entry(index + 0.5f, getRandom(15, 5))); LineDataSet set = new LineDataSet(entries, "Line DataSet"); @@ -129,10 +133,10 @@ private LineData generateLineData() { private BarData generateBarData() { - ArrayList entries1 = new ArrayList(); - ArrayList entries2 = new ArrayList(); + ArrayList entries1 = new ArrayList<>(); + ArrayList entries2 = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) { + for (int index = 0; index < count; index++) { entries1.add(new BarEntry(0, getRandom(25, 25))); // stacked @@ -147,7 +151,7 @@ private BarData generateBarData() { BarDataSet set2 = new BarDataSet(entries2, ""); set2.setStackLabels(new String[]{"Stack 1", "Stack 2"}); - set2.setColors(new int[]{Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)}); + set2.setColors(Color.rgb(61, 165, 255), Color.rgb(23, 197, 255)); set2.setValueTextColor(Color.rgb(61, 165, 255)); set2.setValueTextSize(10f); set2.setAxisDependency(YAxis.AxisDependency.LEFT); @@ -166,13 +170,13 @@ private BarData generateBarData() { return d; } - protected ScatterData generateScatterData() { + ScatterData generateScatterData() { ScatterData d = new ScatterData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (float index = 0; index < itemcount; index += 0.5f) + for (float index = 0; index < count; index += 0.5f) entries.add(new Entry(index + 0.25f, getRandom(10, 55))); ScatterDataSet set = new ScatterDataSet(entries, "Scatter DataSet"); @@ -185,13 +189,13 @@ protected ScatterData generateScatterData() { return d; } - protected CandleData generateCandleData() { + CandleData generateCandleData() { CandleData d = new CandleData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index += 2) + for (int index = 0; index < count; index += 2) entries.add(new CandleEntry(index + 1f, 90, 70, 85, 75f)); CandleDataSet set = new CandleDataSet(entries, "Candle DataSet"); @@ -205,13 +209,13 @@ protected CandleData generateCandleData() { return d; } - protected BubbleData generateBubbleData() { + BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); - for (int index = 0; index < itemcount; index++) { + for (int index = 0; index < count; index++) { float y = getRandom(10, 105); float size = getRandom(100, 105); entries.add(new BubbleEntry(index + 0.5f, y, size)); @@ -237,34 +241,42 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleLineValues: { - for (IDataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : chart.getData().getDataSets()) { if (set instanceof LineDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleBarValues: { - for (IDataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : chart.getData().getDataSets()) { if (set instanceof BarDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionRemoveDataSet: { - - int rnd = (int) getRandom(mChart.getData().getDataSetCount(), 0); - mChart.getData().removeDataSet(mChart.getData().getDataSetByIndex(rnd)); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + int rnd = (int) getRandom(chart.getData().getDataSetCount(), 0); + chart.getData().removeDataSet(chart.getData().getDataSetByIndex(rnd)); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + chart.invalidate(); break; } } return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 4a278c398e..25134f71fd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -1,15 +1,19 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.XAxis; @@ -28,8 +32,8 @@ public class CubicLineChartActivity extends DemoBase implements OnSeekBarChangeListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -39,60 +43,115 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("CubicLineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); - - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart = findViewById(R.id.chart1); - mChart.setViewPortOffsets(0, 0, 0, 0); - mChart.setBackgroundColor(Color.rgb(104, 241, 175)); + chart = findViewById(R.id.chart1); + chart.setViewPortOffsets(0, 0, 0, 0); + chart.setBackgroundColor(Color.rgb(104, 241, 175)); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - mChart.setMaxHighlightDistance(300); - - XAxis x = mChart.getXAxis(); + chart.setDrawGridBackground(false); + chart.setMaxHighlightDistance(300); + + XAxis x = chart.getXAxis(); x.setEnabled(false); - - YAxis y = mChart.getAxisLeft(); - y.setTypeface(mTfLight); + + YAxis y = chart.getAxisLeft(); + y.setTypeface(tfLight); y.setLabelCount(6, false); y.setTextColor(Color.WHITE); y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); y.setDrawGridLines(false); y.setAxisLineColor(Color.WHITE); - - mChart.getAxisRight().setEnabled(false); + + chart.getAxisRight().setEnabled(false); // add data + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + + // lower max, as cubic runs significantly slower than linear + seekBarX.setMax(700); + + seekBarX.setProgress(45); + seekBarY.setProgress(100); setData(45, 100); - - mChart.getLegend().setEnabled(false); - - mChart.animateXY(2000, 2000); - // dont forget to refresh the drawing - mChart.invalidate(); + chart.getLegend().setEnabled(false); + + chart.animateXY(2000, 2000); + + // don't forget to refresh the drawing + chart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * (range + 1)) + 20; + values.add(new Entry(i, val)); + } + + LineDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values, "DataSet 1"); + + set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); + set1.setCubicIntensity(0.2f); + set1.setDrawFilled(true); + set1.setDrawCircles(false); + set1.setLineWidth(1.8f); + set1.setCircleRadius(4f); + set1.setCircleColor(Color.WHITE); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setColor(Color.WHITE); + set1.setFillColor(Color.WHITE); + set1.setFillAlpha(100); + set1.setDrawHorizontalHighlightIndicator(false); + set1.setFillFormatter(new IFillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return chart.getAxisLeft().getAxisMinimum(); + } + }); + + // create a data object with the data sets + LineData data = new LineData(set1); + data.setValueTypeface(tfLight); + data.setValueTextSize(9f); + data.setDrawValues(false); + + // set data + chart.setData(data); + } } @Override @@ -105,23 +164,29 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -133,11 +198,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -148,11 +213,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -162,11 +227,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -176,11 +241,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -190,44 +255,41 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.HORIZONTAL_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -237,78 +299,23 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + public void saveToGallery() { + saveToGallery(chart, "CubicLineChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList yVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 20;// + (float) - // ((mult * - // 0.1) / 10); - yVals.add(new Entry(i, val)); - } - - LineDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(yVals, "DataSet 1"); - - set1.setMode(LineDataSet.Mode.CUBIC_BEZIER); - set1.setCubicIntensity(0.2f); - //set1.setDrawFilled(true); - set1.setDrawCircles(false); - set1.setLineWidth(1.8f); - set1.setCircleRadius(4f); - set1.setCircleColor(Color.WHITE); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setColor(Color.WHITE); - set1.setFillColor(Color.WHITE); - set1.setFillAlpha(100); - set1.setDrawHorizontalHighlightIndicator(false); - set1.setFillFormatter(new IFillFormatter() { - @Override - public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return -10; - } - }); + public void onStartTrackingTouch(SeekBar seekBar) {} - // create a data object with the datasets - LineData data = new LineData(set1); - data.setValueTypeface(mTfLight); - data.setValueTextSize(9f); - data.setDrawValues(false); - - // set data - mChart.setData(data); - } - } + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index d3551068c1..348b9ad0fc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -1,8 +1,10 @@ - +// TODO: Finish and add to main activity list package com.xxmassdeveloper.mpchartexample; -import android.graphics.Typeface; +import android.Manifest; +import android.content.pm.PackageManager; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -28,13 +30,13 @@ /** * This Activity demonstrates drawing into the Chart with the finger. Both line, * bar and scatter charts can be used for drawing. - * + * * @author Philipp Jahoda */ public class DrawChartActivity extends DemoBase implements OnChartValueSelectedListener, OnDrawListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -43,49 +45,49 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_draw_chart); - mChart = findViewById(R.id.chart1); + setTitle("DrawChartActivity"); + + chart = findViewById(R.id.chart1); // listener for selecting and drawing - mChart.setOnChartValueSelectedListener(this); - mChart.setOnDrawListener(this); + chart.setOnChartValueSelectedListener(this); + chart.setOnDrawListener(this); - // if disabled, drawn datasets with the finger will not be automatically + // if disabled, drawn data sets with the finger will not be automatically // finished - // mChart.setAutoFinish(true); - mChart.setDrawGridBackground(false); + // chart.setAutoFinish(true); + chart.setDrawGridBackground(false); // add dummy-data to the chart initWithDummyData(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - XAxis xl = mChart.getXAxis(); - xl.setTypeface(tf); + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfRegular); xl.setAvoidFirstLastClipping(true); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(tf); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfRegular); - mChart.getLegend().setEnabled(false); + chart.getLegend().setEnabled(false); - // mChart.setYRange(-40f, 40f, true); + // chart.setYRange(-40f, 40f, true); // call this to reset the changed y-range - // mChart.resetYRange(true); + // chart.resetYRange(true); } private void initWithDummyData() { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); // create a dataset and give it a type (0) - LineDataSet set1 = new LineDataSet(yVals, "DataSet"); + LineDataSet set1 = new LineDataSet(values, "DataSet"); set1.setLineWidth(3f); set1.setCircleRadius(5f); - // create a data object with the datasets + // create a data object with the data sets LineData data = new LineData(set1); - mChart.setData(data); + chart.setData(data); } @Override @@ -99,7 +101,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -108,39 +110,47 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } return true; } + @Override + public void saveToGallery() { + saveToGallery(chart, "DrawChartActivity"); + } + @Override public void onValueSelected(Entry e, Highlight h) { Log.i("VAL SELECTED", @@ -164,7 +174,7 @@ public void onDrawFinished(DataSet dataSet) { Log.i(Chart.LOG_TAG, "DataSet drawn. " + dataSet.toSimpleString()); // prepare the legend again - mChart.getLegendRenderer().computeLegend(mChart.getData()); + chart.getLegendRenderer().computeLegend(chart.getData()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index f8f64c374f..501090af62 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; @@ -23,7 +28,7 @@ public class DynamicalAddingActivity extends DemoBase implements OnChartValueSelectedListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -32,24 +37,30 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); + setTitle("DynamicalAddingActivity"); - // add an empty data object - mChart.setData(new LineData()); -// mChart.getXAxis().setDrawLabels(false); -// mChart.getXAxis().setDrawGridLines(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); + chart.setNoDataText("No chart data available. Use the menu to add entries and data sets!"); - mChart.invalidate(); +// chart.getXAxis().setDrawLabels(false); +// chart.getXAxis().setDrawGridLines(false); + + chart.invalidate(); } - int[] mColors = ColorTemplate.VORDIPLOM_COLORS; + private final int[] colors = ColorTemplate.VORDIPLOM_COLORS; private void addEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); + + if (data == null) { + data = new LineData(); + chart.setData(data); + } ILineDataSet set = data.getDataSetByIndex(0); // set.addEntry(...); // can be called as well @@ -61,25 +72,26 @@ private void addEntry() { // choose a random dataSet int randomDataSetIndex = (int) (Math.random() * data.getDataSetCount()); - float yValue = (float) (Math.random() * 10) + 50f; + ILineDataSet randomSet = data.getDataSetByIndex(randomDataSetIndex); + float value = (float) (Math.random() * 50) + 50f * (randomDataSetIndex + 1); - data.addEntry(new Entry(data.getDataSetByIndex(randomDataSetIndex).getEntryCount(), yValue), randomDataSetIndex); + data.addEntry(new Entry(randomSet.getEntryCount(), value), randomDataSetIndex); data.notifyDataChanged(); // let the chart know it's data has changed - mChart.notifyDataSetChanged(); + chart.notifyDataSetChanged(); - mChart.setVisibleXRangeMaximum(6); - //mChart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); -// + chart.setVisibleXRangeMaximum(6); + //chart.setVisibleYRangeMaximum(15, AxisDependency.LEFT); +// // // this automatically refreshes the chart (calls invalidate()) - mChart.moveViewTo(data.getEntryCount() - 7, 50f, AxisDependency.LEFT); + chart.moveViewTo(data.getEntryCount() - 7, 50f, AxisDependency.LEFT); } private void removeLastEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { @@ -93,31 +105,33 @@ private void removeLastEntry() { // or remove by index // mData.removeEntryByXValue(xIndex, dataSetIndex); data.notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } } private void addDataSet() { - LineData data = mChart.getData(); - - if (data != null) { + LineData data = chart.getData(); + if (data == null) { + chart.setData(new LineData()); + } else { int count = (data.getDataSetCount() + 1); + int amount = data.getDataSetByIndex(0).getEntryCount(); - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); - for (int i = 0; i < data.getEntryCount(); i++) { - yVals.add(new Entry(i, (float) (Math.random() * 50f) + 50f * count)); + for (int i = 0; i < amount; i++) { + values.add(new Entry(i, (float) (Math.random() * 50f) + 50f * count)); } - LineDataSet set = new LineDataSet(yVals, "DataSet " + count); + LineDataSet set = new LineDataSet(values, "DataSet " + count); set.setLineWidth(2.5f); set.setCircleRadius(4.5f); - int color = mColors[count % mColors.length]; + int color = colors[count % colors.length]; set.setColor(color); set.setCircleColor(color); @@ -127,33 +141,45 @@ private void addDataSet() { data.addDataSet(set); data.notifyDataChanged(); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } private void removeDataSet() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { data.removeDataSet(data.getDataSetByIndex(data.getDataSetCount() - 1)); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.notifyDataSetChanged(); + chart.invalidate(); } } + private LineDataSet createSet() { + + LineDataSet set = new LineDataSet(null, "DataSet 1"); + set.setLineWidth(2.5f); + set.setCircleRadius(4.5f); + set.setColor(Color.rgb(240, 99, 99)); + set.setCircleColor(Color.rgb(240, 99, 99)); + set.setHighLightColor(Color.rgb(190, 190, 190)); + set.setAxisDependency(AxisDependency.LEFT); + set.setValueTextSize(10f); + + return set; + } + @Override public void onValueSelected(Entry e, Highlight h) { Toast.makeText(this, e.toString(), Toast.LENGTH_SHORT).show(); } @Override - public void onNothingSelected() { - - } + public void onNothingSelected() {} @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -165,47 +191,52 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.actionAddEntry: + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java")); + startActivity(i); + break; + } + case R.id.actionAddEntry: { addEntry(); Toast.makeText(this, "Entry added!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionRemoveEntry: + } + case R.id.actionRemoveEntry: { removeLastEntry(); Toast.makeText(this, "Entry removed!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionAddDataSet: + } + case R.id.actionAddDataSet: { addDataSet(); Toast.makeText(this, "DataSet added!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionRemoveDataSet: + } + case R.id.actionRemoveDataSet: { removeDataSet(); Toast.makeText(this, "DataSet removed!", Toast.LENGTH_SHORT).show(); break; - case R.id.actionAddEmptyLineData: - mChart.setData(new LineData()); - mChart.invalidate(); - Toast.makeText(this, "Empty data added!", Toast.LENGTH_SHORT).show(); - break; - case R.id.actionClear: - mChart.clear(); + } + case R.id.actionClear: { + chart.clear(); Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } } return true; } - private LineDataSet createSet() { - - LineDataSet set = new LineDataSet(null, "DataSet 1"); - set.setLineWidth(2.5f); - set.setCircleRadius(4.5f); - set.setColor(Color.rgb(240, 99, 99)); - set.setCircleColor(Color.rgb(240, 99, 99)); - set.setHighLightColor(Color.rgb(190, 190, 190)); - set.setAxisDependency(AxisDependency.LEFT); - set.setValueTextSize(10f); - - return set; + @Override + public void saveToGallery() { + saveToGallery(chart, "DynamicalAddingActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java index 9109d5d29c..e821a04969 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java @@ -1,8 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.LineChart; @@ -19,10 +23,19 @@ import java.util.ArrayList; +/** + * This works by inverting the background and desired "fill" color. First, we draw the fill color + * that we want between the lines as the actual background of the chart. Then, we fill the area + * above the highest line and the area under the lowest line with the desired background color. + * + * This method makes it look like we filled the area between the lines, but really we are filling + * the area OUTSIDE the lines! + */ +@SuppressWarnings("SameParameterValue") public class FilledLineActivity extends DemoBase { - private LineChart mChart; - private int mFillColor = Color.argb(150, 51, 181, 229); + private LineChart chart; + private final int fillColor = Color.argb(150, 51, 181, 229); @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,73 +44,71 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_noseekbar); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); - mChart.setGridBackgroundColor(mFillColor); - mChart.setDrawGridBackground(true); + setTitle("FilledLineActivity"); - mChart.setDrawBorders(true); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); + chart.setGridBackgroundColor(fillColor); + chart.setDrawGridBackground(true); + + chart.setDrawBorders(true); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setEnabled(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setAxisMaximum(900f); leftAxis.setAxisMinimum(-250f); leftAxis.setDrawAxisLine(false); leftAxis.setDrawZeroLine(false); leftAxis.setDrawGridLines(false); - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); // add data setData(100, 60); - mChart.invalidate(); + chart.invalidate(); } private void setData(int count, float range) { - ArrayList yVals1 = new ArrayList(); + ArrayList values1 = new ArrayList<>(); for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range) + 50;// + (float) - // ((mult * - // 0.1) / 10); - yVals1.add(new Entry(i, val)); + float val = (float) (Math.random() * range) + 50; + values1.add(new Entry(i, val)); } - ArrayList yVals2 = new ArrayList(); + ArrayList values2 = new ArrayList<>(); for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range) + 450;// + (float) - // ((mult * - // 0.1) / 10); - yVals2.add(new Entry(i, val)); + float val = (float) (Math.random() * range) + 450; + values2.add(new Entry(i, val)); } LineDataSet set1, set2; - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set2 = (LineDataSet)mChart.getData().getDataSetByIndex(1); - set1.setValues(yVals1); - set2.setValues(yVals2); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set2 = (LineDataSet) chart.getData().getDataSetByIndex(1); + set1.setValues(values1); + set2.setValues(values2); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); } else { // create a dataset and give it a type - set1 = new LineDataSet(yVals1, "DataSet 1"); + set1 = new LineDataSet(values1, "DataSet 1"); set1.setAxisDependency(YAxis.AxisDependency.LEFT); set1.setColor(Color.rgb(255, 241, 46)); @@ -112,12 +123,14 @@ private void setData(int count, float range) { set1.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return mChart.getAxisLeft().getAxisMinimum(); + // change the return value here to better understand the effect + // return 0; + return chart.getAxisLeft().getAxisMinimum(); } }); // create a dataset and give it a type - set2 = new LineDataSet(yVals2, "DataSet 2"); + set2 = new LineDataSet(values2, "DataSet 2"); set2.setAxisDependency(YAxis.AxisDependency.LEFT); set2.setColor(Color.rgb(255, 241, 46)); set2.setDrawCircles(false); @@ -131,20 +144,46 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv set2.setFillFormatter(new IFillFormatter() { @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { - return mChart.getAxisLeft().getAxisMaximum(); + // change the return value here to better understand the effect + // return 600; + return chart.getAxisLeft().getAxisMaximum(); } }); - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets dataSets.add(set2); - // create a data object with the datasets + // create a data object with the data sets LineData data = new LineData(dataSets); data.setDrawValues(false); // set data - mChart.setData(data); + chart.setData(data); } } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java index 38a228b322..ed2adcc960 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java @@ -1,22 +1,24 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Point; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.text.style.StyleSpan; -import android.view.Display; +import android.util.DisplayMetrics; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import android.widget.RelativeLayout; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -26,9 +28,10 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class HalfPieChartActivity extends DemoBase { - private PieChart mChart; + private PieChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -37,40 +40,42 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart_half); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.WHITE); + setTitle("HalfPieChartActivity"); + + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.WHITE); moveOffScreen(); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); - mChart.setCenterTextTypeface(mTfLight); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(tfLight); + chart.setCenterText(generateCenterSpannableText()); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationEnabled(false); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(false); + chart.setHighlightPerTapEnabled(true); - mChart.setMaxAngle(180f); // HALF CHART - mChart.setRotationAngle(180f); - mChart.setCenterTextOffset(0, -20); + chart.setMaxAngle(180f); // HALF CHART + chart.setRotationAngle(180f); + chart.setCenterTextOffset(0, -20); setData(4, 100); - mChart.animateY(1400, Easing.EaseInOutQuad); + chart.animateY(1400, Easing.EaseInOutQuad); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -80,17 +85,17 @@ protected void onCreate(Bundle savedInstanceState) { l.setYOffset(0f); // entry label styling - mChart.setEntryLabelColor(Color.WHITE); - mChart.setEntryLabelTypeface(mTfRegular); - mChart.setEntryLabelTextSize(12f); + chart.setEntryLabelColor(Color.WHITE); + chart.setEntryLabelTypeface(tfRegular); + chart.setEntryLabelTextSize(12f); } private void setData(int count, float range) { - ArrayList values = new ArrayList(); + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { - values.add(new PieEntry((float) ((Math.random() * range) + range / 5), mParties[i % mParties.length])); + values.add(new PieEntry((float) ((Math.random() * range) + range / 5), parties[i % parties.length])); } PieDataSet dataSet = new PieDataSet(values, "Election Results"); @@ -104,10 +109,10 @@ private void setData(int count, float range) { data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); - data.setValueTypeface(mTfLight); - mChart.setData(data); + data.setValueTypeface(tfLight); + chart.setData(data); - mChart.invalidate(); + chart.invalidate(); } private SpannableString generateCenterSpannableText() { @@ -124,14 +129,40 @@ private SpannableString generateCenterSpannableText() { private void moveOffScreen() { - Display display = getWindowManager().getDefaultDisplay(); - int height = display.getHeight(); // deprecated + DisplayMetrics displayMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + + int height = displayMetrics.heightPixels; int offset = (int)(height * 0.65); /* percent to move */ RelativeLayout.LayoutParams rlParams = - (RelativeLayout.LayoutParams)mChart.getLayoutParams(); + (RelativeLayout.LayoutParams) chart.getLayoutParams(); rlParams.setMargins(0, 0, 0, -offset); - mChart.setLayoutParams(rlParams); + chart.setLayoutParams(rlParams); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java")); + startActivity(i); + break; + } + } + + return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 95e138aade..6e4e9275bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -1,9 +1,13 @@ package com.xxmassdeveloper.mpchartexample; -import android.annotation.SuppressLint; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.RectF; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -11,11 +15,9 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -35,8 +37,8 @@ public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - protected HorizontalBarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private HorizontalBarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -46,67 +48,69 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_horizontalbarchart); + setTitle("HorizontalBarChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - // mChart.setHighlightEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); - mChart.setDrawBarShadow(false); + chart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawValueAboveBar(true); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); + // chart.setDrawBarShadow(true); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xl = mChart.getXAxis(); + XAxis xl = chart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(mTfLight); + xl.setTypeface(tfLight); xl.setDrawAxisLine(true); xl.setDrawGridLines(false); xl.setGranularity(10f); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yl.setInverted(true); - YAxis yr = mChart.getAxisRight(); - yr.setTypeface(mTfLight); + YAxis yr = chart.getAxisRight(); + yr.setTypeface(tfLight); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); yr.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yr.setInverted(true); setData(12, 50); - mChart.setFitBars(true); - mChart.animateY(2500); + chart.setFitBars(true); + chart.animateY(2500); // setting data - mSeekBarY.setProgress(50); - mSeekBarX.setProgress(12); + seekBarY.setProgress(50); + seekBarX.setProgress(12); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -115,6 +119,42 @@ protected void onCreate(Bundle savedInstanceState) { l.setXEntrySpace(4f); } + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range); + values.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(barWidth); + chart.setData(data); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); @@ -125,80 +165,80 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); + iSet.setDrawValues(!iSet.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawIcons(!set.isDrawIconsEnabled()); + iSet.setDrawIcons(!iSet.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -208,64 +248,27 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - mChart.setFitBars(true); - mChart.invalidate(); + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.setFitBars(true); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + public void saveToGallery() { + saveToGallery(chart, "HorizontalBarChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { + public void onStartTrackingTouch(SeekBar seekBar) {} - float barWidth = 9f; - float spaceForBar = 10f; - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range); - yVals1.add(new BarEntry(i * spaceForBar, val, - getResources().getDrawable(R.drawable.star))); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "DataSet 1"); - - set1.setDrawIcons(false); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - BarData data = new BarData(dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setBarWidth(barWidth); - mChart.setData(data); - } - } + private RectF mOnValueSelectedRectF = new RectF(); - protected RectF mOnValueSelectedRectF = new RectF(); - @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { @@ -273,9 +276,9 @@ public void onValueSelected(Entry e, Highlight h) { return; RectF bounds = mOnValueSelectedRectF; - mChart.getBarBounds((BarEntry) e, bounds); + chart.getBarBounds((BarEntry) e, bounds); - MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); Log.i("bounds", bounds.toString()); @@ -285,6 +288,5 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - }; + public void onNothingSelected() {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 4ad4e691ef..cdc3188854 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -9,7 +14,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -33,8 +37,8 @@ public class InvertedLineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,72 +48,100 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("InvertedLineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarX.setProgress(45); + seekBarY.setProgress(100); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - // mChart.setBackgroundColor(Color.GRAY); + // chart.setBackgroundColor(Color.GRAY); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart - - XAxis xl = mChart.getXAxis(); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart + + XAxis xl = chart.getXAxis(); xl.setAvoidFirstLastClipping(true); xl.setAxisMinimum(0f); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setInverted(true); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); // add data setData(25, 50); // // restrain the maximum scale-out factor - // mChart.setScaleMinima(3f, 3f); + // chart.setScaleMinima(3f, 3f); // // // center the view to a specific position inside the chart - // mChart.centerViewPort(10, 50); + // chart.centerViewPort(10, 50); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - // dont forget to refresh the drawing - mChart.invalidate(); + // don't forget to refresh the drawing + chart.invalidate(); + } + + private void setData(int count, float range) { + + ArrayList entries = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float xVal = (float) (Math.random() * range); + float yVal = (float) (Math.random() * range); + entries.add(new Entry(xVal, yVal)); + } + + // sort by x-value + Collections.sort(entries, new EntryXComparator()); + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(entries, "DataSet 1"); + + set1.setLineWidth(1.5f); + set1.setCircleRadius(4f); + + // create a data object with the data sets + LineData data = new LineData(set1); + + // set data + chart.setData(data); } @Override @@ -122,8 +154,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -132,19 +170,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -155,11 +193,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -170,45 +208,42 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -218,13 +253,18 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); + } + + @Override + public void saveToGallery() { + saveToGallery(chart, "InvertedLineChartActivity"); } @Override @@ -235,46 +275,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList entries = new ArrayList(); - - for (int i = 0; i < count; i++) { - float xVal = (float) (Math.random() * range); - float yVal = (float) (Math.random() * range); - entries.add(new Entry(xVal, yVal)); - } - - // sort by x-value - Collections.sort(entries, new EntryXComparator()); - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(entries, "DataSet 1"); - - set1.setLineWidth(1.5f); - set1.setCircleRadius(4f); - - // create a data object with the datasets - LineData data = new LineData(set1); - - // set data - mChart.setData(data); - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 85d213e351..4a970df995 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -1,21 +1,22 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.DashPathEffect; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; -import android.support.v4.content.ContextCompat; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; -import android.view.MotionEvent; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; @@ -28,10 +29,10 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.IFillFormatter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.listener.ChartTouchListener; -import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; @@ -40,11 +41,17 @@ import java.util.ArrayList; import java.util.List; +/** + * Example of a heavily customized {@link LineChart} with limit lines, custom line shapes, etc. + * + * @since 1.7.4 + * @version 3.0.3 + */ public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, - OnChartGestureListener, OnChartValueSelectedListener { + OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -54,117 +61,200 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("LineChartActivity1"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setMax(180); + seekBarY.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartGestureListener(this); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); + { // // Chart Style // // + chart = findViewById(R.id.chart1); - // no description text - mChart.getDescription().setEnabled(false); + // background color + chart.setBackgroundColor(Color.WHITE); - // enable touch gestures - mChart.setTouchEnabled(true); + // disable description text + chart.getDescription().setEnabled(false); - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - // mChart.setScaleXEnabled(true); - // mChart.setScaleYEnabled(true); + // enable touch gestures + chart.setTouchEnabled(true); - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + // set listeners + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); - // set an alternative background color - // mChart.setBackgroundColor(Color.GRAY); + // create marker to display box when values are selected + MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - // create a custom MarkerView (extend MarkerView) and specify the layout - // to use for it - MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + // Set the marker to the chart + mv.setChartView(chart); + chart.setMarker(mv); - // x-axis limit line - LimitLine llXAxis = new LimitLine(10f, "Index 10"); - llXAxis.setLineWidth(4f); - llXAxis.enableDashedLine(10f, 10f, 0f); - llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); - llXAxis.setTextSize(10f); + // enable scaling and dragging + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + // chart.setScaleXEnabled(true); + // chart.setScaleYEnabled(true); - XAxis xAxis = mChart.getXAxis(); - xAxis.enableGridDashedLine(10f, 10f, 0f); - //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); - //xAxis.addLimitLine(llXAxis); // add x-axis limit line + // force pinch zoom along both axis + chart.setPinchZoom(true); + } + XAxis xAxis; + { // // X-Axis Style // // + xAxis = chart.getXAxis(); - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + // vertical grid lines + xAxis.enableGridDashedLine(10f, 10f, 0f); + } - LimitLine ll1 = new LimitLine(150f, "Upper Limit"); - ll1.setLineWidth(4f); - ll1.enableDashedLine(10f, 10f, 0f); - ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); - ll1.setTextSize(10f); - ll1.setTypeface(tf); + YAxis yAxis; + { // // Y-Axis Style // // + yAxis = chart.getAxisLeft(); - LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); - ll2.setLineWidth(4f); - ll2.enableDashedLine(10f, 10f, 0f); - ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); - ll2.setTextSize(10f); - ll2.setTypeface(tf); + // disable dual axis (only use LEFT axis) + chart.getAxisRight().setEnabled(false); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.addLimitLine(ll1); - leftAxis.addLimitLine(ll2); - leftAxis.setAxisMaximum(200f); - leftAxis.setAxisMinimum(-50f); - //leftAxis.setYOffset(20f); - leftAxis.enableGridDashedLine(10f, 10f, 0f); - leftAxis.setDrawZeroLine(false); + // horizontal grid lines + yAxis.enableGridDashedLine(10f, 10f, 0f); - // limit lines are drawn behind data (and not on top) - leftAxis.setDrawLimitLinesBehindData(true); + // axis range + yAxis.setAxisMaximum(200f); + yAxis.setAxisMinimum(-50f); + } - mChart.getAxisRight().setEnabled(false); - //mChart.getViewPortHandler().setMaximumScaleY(2f); - //mChart.getViewPortHandler().setMaximumScaleX(2f); + { // // Create Limit Lines // // + LimitLine llXAxis = new LimitLine(9f, "Index 10"); + llXAxis.setLineWidth(4f); + llXAxis.enableDashedLine(10f, 10f, 0f); + llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); + llXAxis.setTextSize(10f); + llXAxis.setTypeface(tfRegular); + + LimitLine ll1 = new LimitLine(150f, "Upper Limit"); + ll1.setLineWidth(4f); + ll1.enableDashedLine(10f, 10f, 0f); + ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); + ll1.setTextSize(10f); + ll1.setTypeface(tfRegular); + + LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); + ll2.setLineWidth(4f); + ll2.enableDashedLine(10f, 10f, 0f); + ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); + ll2.setTextSize(10f); + ll2.setTypeface(tfRegular); + + // draw limit lines behind data instead of on top + yAxis.setDrawLimitLinesBehindData(true); + xAxis.setDrawLimitLinesBehindData(true); + + // add limit lines + yAxis.addLimitLine(ll1); + yAxis.addLimitLine(ll2); + //xAxis.addLimitLine(llXAxis); + } // add data - setData(45, 100); + seekBarX.setProgress(45); + seekBarY.setProgress(180); + setData(45, 180); -// mChart.setVisibleXRange(20); -// mChart.setVisibleYRange(20f, AxisDependency.LEFT); -// mChart.centerViewTo(20, 50, AxisDependency.LEFT); - - mChart.animateX(2500); - //mChart.invalidate(); + // draw points over time + chart.animateX(1500); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); - // modify the legend ... + // draw legend entries as lines l.setForm(LegendForm.LINE); - - // // dont forget to refresh the drawing - // mChart.invalidate(); } - @Override - public void onWindowFocusChanged(boolean hasFocus) { - super.onWindowFocusChanged(hasFocus); + private void setData(int count, float range) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + + float val = (float) (Math.random() * range) - 30; + values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); + } + + LineDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + set1.notifyDataSetChanged(); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + // draw dashed line + set1.enableDashedLine(10f, 5f, 0f); + + // black lines and points + set1.setColor(Color.BLACK); + set1.setCircleColor(Color.BLACK); + + // line thickness and point size + set1.setLineWidth(1f); + set1.setCircleRadius(3f); + + // draw points as solid circles + set1.setDrawCircleHole(false); + + // customize legend entry + set1.setFormLineWidth(1f); + set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); + set1.setFormSize(15.f); + + // text size of values + set1.setValueTextSize(9f); + + // draw selection line as dashed + set1.enableDashedHighlightLine(10f, 5f, 0f); + + // set the filled area + set1.setDrawFilled(true); + set1.setFillFormatter(new IFillFormatter() { + @Override + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { + return chart.getAxisLeft().getAxisMinimum(); + } + }); + + // set color of filled area + if (Utils.getSDKInt() >= 18) { + // drawables only supported on api level 18 and above + Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); + set1.setFillDrawable(drawable); + } else { + set1.setFillColor(Color.BLACK); + } + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + + // create a data object with the data sets + LineData data = new LineData(dataSets); + + // set data + chart.setData(data); + } } @Override @@ -177,8 +267,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -187,11 +283,11 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -200,19 +296,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawIcons(!set.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -223,11 +319,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -238,11 +334,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -252,11 +348,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -266,11 +362,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -280,44 +376,41 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.HORIZONTAL_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000, Easing.EaseInCubic); + chart.animateY(2000, Easing.EaseInCubic); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -327,134 +420,31 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - ArrayList values = new ArrayList(); - - for (int i = 0; i < count; i++) { - - float val = (float) (Math.random() * range) + 3; - values.add(new Entry(i, val, getResources().getDrawable(R.drawable.star))); - } - - LineDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(values); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(values, "DataSet 1"); - - set1.setDrawIcons(false); - - // set the line to be drawn like this "- - - - - -" - set1.enableDashedLine(10f, 5f, 0f); - set1.enableDashedHighlightLine(10f, 5f, 0f); - set1.setColor(Color.BLACK); - set1.setCircleColor(Color.BLACK); - set1.setLineWidth(1f); - set1.setCircleRadius(3f); - set1.setDrawCircleHole(false); - set1.setValueTextSize(9f); - set1.setDrawFilled(true); - set1.setFormLineWidth(1f); - set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f)); - set1.setFormSize(15.f); - - if (Utils.getSDKInt() >= 18) { - // fill drawable only supported on api level 18 and above - Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); - set1.setFillDrawable(drawable); - } - else { - set1.setFillColor(Color.BLACK); - } - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - - // create a data object with the datasets - LineData data = new LineData(dataSets); - - // set data - mChart.setData(data); - } - } - - @Override - public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); - } - - @Override - public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { - Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); - - // un-highlight values after the gesture is finished and no single-tap - if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) - mChart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) - } - - @Override - public void onChartLongPressed(MotionEvent me) { - Log.i("LongPress", "Chart longpressed."); + chart.invalidate(); } @Override - public void onChartDoubleTapped(MotionEvent me) { - Log.i("DoubleTap", "Chart double-tapped."); + public void saveToGallery() { + saveToGallery(chart, "LineChartActivity1"); } @Override - public void onChartSingleTapped(MotionEvent me) { - Log.i("SingleTap", "Chart single-tapped."); - } - - @Override - public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY); - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onChartScale(MotionEvent me, float scaleX, float scaleY) { - Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); - } - - @Override - public void onChartTranslate(MotionEvent me, float dX, float dY) { - Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); - } + public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); - Log.i("LOWHIGH", "low: " + mChart.getLowestVisibleX() + ", high: " + mChart.getHighestVisibleX()); - Log.i("MIN MAX", "xmin: " + mChart.getXChartMin() + ", xmax: " + mChart.getXChartMax() + ", ymin: " + mChart.getYChartMin() + ", ymax: " + mChart.getYChartMax()); + Log.i("LOW HIGH", "low: " + chart.getLowestVisibleX() + ", high: " + chart.getHighestVisibleX()); + Log.i("MIN MAX", "xMin: " + chart.getXChartMin() + ", xMax: " + chart.getXChartMax() + ", yMin: " + chart.getYChartMin() + ", yMax: " + chart.getYChartMax()); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index e2a381ff91..c0f72d87fa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -10,7 +15,6 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; @@ -30,11 +34,17 @@ import java.util.ArrayList; import java.util.List; +/** + * Example of a dual axis {@link LineChart} with multiple data sets. + * + * @since 1.7.4 + * @version 3.0.3 + */ public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,51 +54,53 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("LineChartActivity2"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); - mChart.setDragDecelerationFrictionCoef(0.9f); + chart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); - mChart.setHighlightPerDragEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); + chart.setHighlightPerDragEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + chart.setBackgroundColor(Color.LTGRAY); // add data + seekBarX.setProgress(20); + seekBarY.setProgress(30); setData(20, 30); - mChart.animateX(2500); + chart.animateX(1500); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setTextSize(11f); l.setTextColor(Color.WHITE); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); @@ -97,23 +109,23 @@ protected void onCreate(Bundle savedInstanceState) { l.setDrawInside(false); // l.setYOffset(11f); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setTextSize(11f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setAxisMaximum(200f); leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); - YAxis rightAxis = mChart.getAxisRight(); - rightAxis.setTypeface(mTfLight); + YAxis rightAxis = chart.getAxisRight(); + rightAxis.setTypeface(tfLight); rightAxis.setTextColor(Color.RED); rightAxis.setAxisMaximum(900); rightAxis.setAxisMinimum(-200); @@ -122,6 +134,93 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setGranularityEnabled(false); } + private void setData(int count, float range) { + + ArrayList values1 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * (range / 2f)) + 50; + values1.add(new Entry(i, val)); + } + + ArrayList values2 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 450; + values2.add(new Entry(i, val)); + } + + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range) + 500; + values3.add(new Entry(i, val)); + } + + LineDataSet set1, set2, set3; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (LineDataSet) chart.getData().getDataSetByIndex(0); + set2 = (LineDataSet) chart.getData().getDataSetByIndex(1); + set3 = (LineDataSet) chart.getData().getDataSetByIndex(2); + set1.setValues(values1); + set2.setValues(values2); + set3.setValues(values3); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + // create a dataset and give it a type + set1 = new LineDataSet(values1, "DataSet 1"); + + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setCircleColor(Color.WHITE); + set1.setLineWidth(2f); + set1.setCircleRadius(3f); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + //set1.setFillFormatter(new MyFillFormatter(0f)); + //set1.setDrawHorizontalHighlightIndicator(false); + //set1.setVisible(false); + //set1.setCircleHoleColor(Color.WHITE); + + // create a dataset and give it a type + set2 = new LineDataSet(values2, "DataSet 2"); + set2.setAxisDependency(AxisDependency.RIGHT); + set2.setColor(Color.RED); + set2.setCircleColor(Color.WHITE); + set2.setLineWidth(2f); + set2.setCircleRadius(3f); + set2.setFillAlpha(65); + set2.setFillColor(Color.RED); + set2.setDrawCircleHole(false); + set2.setHighLightColor(Color.rgb(244, 117, 117)); + //set2.setFillFormatter(new MyFillFormatter(900f)); + + set3 = new LineDataSet(values3, "DataSet 3"); + set3.setAxisDependency(AxisDependency.RIGHT); + set3.setColor(Color.YELLOW); + set3.setCircleColor(Color.WHITE); + set3.setLineWidth(2f); + set3.setCircleRadius(3f); + set3.setFillAlpha(65); + set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); + set3.setDrawCircleHole(false); + set3.setHighLightColor(Color.rgb(244, 117, 117)); + + // create a data object with the data sets + LineData data = new LineData(set1, set2, set3); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + chart.setData(data); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); @@ -132,8 +231,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -142,19 +247,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -165,11 +270,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -180,11 +285,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -194,11 +299,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -208,11 +313,11 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHorizontalCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -222,46 +327,41 @@ public boolean onOptionsItemSelected(MenuItem item) { ? LineDataSet.Mode.LINEAR : LineDataSet.Mode.HORIZONTAL_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); - //mChart.highlightValue(9.7f, 1, false); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -271,117 +371,29 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); // redraw - mChart.invalidate(); + chart.invalidate(); } - private void setData(int count, float range) { - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = range / 2f; - float val = (float) (Math.random() * mult) + 50; - yVals1.add(new Entry(i, val)); - } - - ArrayList yVals2 = new ArrayList(); - - for (int i = 0; i < count-1; i++) { - float mult = range; - float val = (float) (Math.random() * mult) + 450; - yVals2.add(new Entry(i, val)); -// if(i == 10) { -// yVals2.add(new Entry(i, val + 50)); -// } - } - - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float mult = range; - float val = (float) (Math.random() * mult) + 500; - yVals3.add(new Entry(i, val)); - } - - LineDataSet set1, set2, set3; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (LineDataSet) mChart.getData().getDataSetByIndex(0); - set2 = (LineDataSet) mChart.getData().getDataSetByIndex(1); - set3 = (LineDataSet) mChart.getData().getDataSetByIndex(2); - set1.setValues(yVals1); - set2.setValues(yVals2); - set3.setValues(yVals3); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - // create a dataset and give it a type - set1 = new LineDataSet(yVals1, "DataSet 1"); - - set1.setAxisDependency(AxisDependency.LEFT); - set1.setColor(ColorTemplate.getHoloBlue()); - set1.setCircleColor(Color.WHITE); - set1.setLineWidth(2f); - set1.setCircleRadius(3f); - set1.setFillAlpha(65); - set1.setFillColor(ColorTemplate.getHoloBlue()); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setDrawCircleHole(false); - //set1.setFillFormatter(new MyFillFormatter(0f)); - //set1.setDrawHorizontalHighlightIndicator(false); - //set1.setVisible(false); - //set1.setCircleHoleColor(Color.WHITE); - - // create a dataset and give it a type - set2 = new LineDataSet(yVals2, "DataSet 2"); - set2.setAxisDependency(AxisDependency.RIGHT); - set2.setColor(Color.RED); - set2.setCircleColor(Color.WHITE); - set2.setLineWidth(2f); - set2.setCircleRadius(3f); - set2.setFillAlpha(65); - set2.setFillColor(Color.RED); - set2.setDrawCircleHole(false); - set2.setHighLightColor(Color.rgb(244, 117, 117)); - //set2.setFillFormatter(new MyFillFormatter(900f)); - - set3 = new LineDataSet(yVals3, "DataSet 3"); - set3.setAxisDependency(AxisDependency.RIGHT); - set3.setColor(Color.YELLOW); - set3.setCircleColor(Color.WHITE); - set3.setLineWidth(2f); - set3.setCircleRadius(3f); - set3.setFillAlpha(65); - set3.setFillColor(ColorTemplate.colorWithAlpha(Color.YELLOW, 200)); - set3.setDrawCircleHole(false); - set3.setHighLightColor(Color.rgb(244, 117, 117)); - - // create a data object with the datasets - LineData data = new LineData(set1, set2, set3); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(9f); - - // set data - mChart.setData(data); - } + @Override + public void saveToGallery() { + saveToGallery(chart, "LineChartActivity2"); } @Override public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); - mChart.centerViewToAnimated(e.getX(), e.getY(), mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + chart.centerViewToAnimated(e.getX(), e.getY(), chart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency(), 500); - //mChart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + //chart.zoomAndCenterAnimated(2.5f, 2.5f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) // .getAxisDependency(), 1000); - //mChart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), mChart.getData().getDataSetByIndex(dataSetIndex) + //chart.zoomAndCenterAnimated(1.8f, 1.8f, e.getX(), e.getY(), chart.getData().getDataSetByIndex(dataSetIndex) // .getAxisDependency(), 1000); } @@ -391,14 +403,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 39730d55b1..7bb95b83ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -1,9 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.LineChart; @@ -15,10 +19,10 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class LineChartActivityColored extends DemoBase { - private LineChart[] mCharts = new LineChart[4]; - private Typeface mTf; + private LineChart[] charts = new LineChart[4]; @Override protected void onCreate(Bundle savedInstanceState) { @@ -27,26 +31,28 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_colored_lines); - mCharts[0] = findViewById(R.id.chart1); - mCharts[1] = findViewById(R.id.chart2); - mCharts[2] = findViewById(R.id.chart3); - mCharts[3] = findViewById(R.id.chart4); + setTitle("LineChartActivityColored"); - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); + charts[0] = findViewById(R.id.chart1); + charts[1] = findViewById(R.id.chart2); + charts[2] = findViewById(R.id.chart3); + charts[3] = findViewById(R.id.chart4); - for (int i = 0; i < mCharts.length; i++) { + Typeface mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Bold.ttf"); + + for (int i = 0; i < charts.length; i++) { LineData data = getData(36, 100); data.setValueTypeface(mTf); // add some transparency to the color with "& 0x90FFFFFF" - setupChart(mCharts[i], data, mColors[i % mColors.length]); + setupChart(charts[i], data, colors[i % colors.length]); } } - private int[] mColors = new int[] { - Color.rgb(137, 230, 81), - Color.rgb(240, 240, 30), + private final int[] colors = new int[] { + Color.rgb(137, 230, 81), + Color.rgb(240, 240, 30), Color.rgb(89, 199, 250), Color.rgb(250, 104, 104) }; @@ -57,8 +63,8 @@ private void setupChart(LineChart chart, LineData data, int color) { // no description text chart.getDescription().setEnabled(false); - - // mChart.setDrawHorizontalGrid(false); + + // chart.setDrawHorizontalGrid(false); // // enable / disable grid background chart.setDrawGridBackground(false); @@ -75,7 +81,7 @@ private void setupChart(LineChart chart, LineData data, int color) { chart.setPinchZoom(false); chart.setBackgroundColor(color); - + // set custom chart offsets (automatic offset calculation is hereby disabled) chart.setViewPortOffsets(10, 0, 10, 0); @@ -96,18 +102,18 @@ private void setupChart(LineChart chart, LineData data, int color) { // animate calls invalidate()... chart.animateX(2500); } - + private LineData getData(int count, float range) { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * range) + 3; - yVals.add(new Entry(i, val)); + values.add(new Entry(i, val)); } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); // set1.setFillAlpha(110); // set1.setFillColor(Color.RED); @@ -119,9 +125,31 @@ private LineData getData(int count, float range) { set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); - // create a data object with the datasets - LineData data = new LineData(set1); + // create a data object with the data sets + return new LineData(set1); + } - return data; + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 6bf96f02a7..a88842c5d0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -1,15 +1,19 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.AxisBase; @@ -25,17 +29,17 @@ import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import java.sql.Time; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.concurrent.TimeUnit; public class LineChartTime extends DemoBase implements OnSeekBarChangeListener { - private LineChart mChart; - private SeekBar mSeekBarX; + private LineChart chart; + private SeekBar seekBarX; private TextView tvX; @Override @@ -45,44 +49,44 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart_time); - tvX = findViewById(R.id.tvXMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setProgress(100); - tvX.setText("100"); + setTitle("LineChartTime"); - mSeekBarX.setOnSeekBarChangeListener(this); + tvX = findViewById(R.id.tvXMax); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); + chart = findViewById(R.id.chart1); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); - mChart.setDragDecelerationFrictionCoef(0.9f); + chart.setDragDecelerationFrictionCoef(0.9f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); - mChart.setHighlightPerDragEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); + chart.setHighlightPerDragEnabled(true); // set an alternative background color - mChart.setBackgroundColor(Color.WHITE); - mChart.setViewPortOffsets(0f, 0f, 0f, 0f); + chart.setBackgroundColor(Color.WHITE); + chart.setViewPortOffsets(0f, 0f, 0f, 0f); // add data + seekBarX.setProgress(100); setData(100, 30); - mChart.invalidate(); + chart.invalidate(); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setEnabled(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxis.XAxisPosition.TOP_INSIDE); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setTextSize(10f); xAxis.setTextColor(Color.WHITE); xAxis.setDrawAxisLine(false); @@ -92,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(1f); // one hour xAxis.setValueFormatter(new IAxisValueFormatter() { - private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm"); + private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override public String getFormattedValue(float value, AxisBase axis) { @@ -102,9 +106,9 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); - leftAxis.setTypeface(mTfLight); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setDrawGridLines(true); leftAxis.setGranularityEnabled(true); @@ -113,10 +117,49 @@ public String getFormattedValue(float value, AxisBase axis) { leftAxis.setYOffset(-9f); leftAxis.setTextColor(Color.rgb(255, 192, 56)); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); } + private void setData(int count, float range) { + + // now in hours + long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); + + ArrayList values = new ArrayList<>(); + + // count = hours + float to = now + count; + + // increment by 1 hour + for (float x = now; x < to; x++) { + + float y = getRandom(range, 50); + values.add(new Entry(x, y)); // add one entry per hour + } + + // create a dataset and give it a type + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); + set1.setAxisDependency(AxisDependency.LEFT); + set1.setColor(ColorTemplate.getHoloBlue()); + set1.setValueTextColor(ColorTemplate.getHoloBlue()); + set1.setLineWidth(1.5f); + set1.setDrawCircles(false); + set1.setDrawValues(false); + set1.setFillAlpha(65); + set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setHighLightColor(Color.rgb(244, 117, 117)); + set1.setDrawCircleHole(false); + + // create a data object with the data sets + LineData data = new LineData(set1); + data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); + + // set data + chart.setData(data); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); @@ -127,8 +170,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -137,19 +186,19 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -160,11 +209,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -175,11 +224,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCubic: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -190,11 +239,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setMode(LineDataSet.Mode.CUBIC_BEZIER); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleStepped: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -205,45 +254,42 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setMode(LineDataSet.Mode.STEPPED); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - - // mChart.saveToGallery("title"+System.currentTimeMillis()) + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -253,64 +299,22 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); - setData(mSeekBarX.getProgress(), 50); + setData(seekBarX.getProgress(), 50); // redraw - mChart.invalidate(); - } - - private void setData(int count, float range) { - - // now in hours - long now = TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis()); - - ArrayList values = new ArrayList(); - - float from = now; - - // count = hours - float to = now + count; - - // increment by 1 hour - for (float x = from; x < to; x++) { - - float y = getRandom(range, 50); - values.add(new Entry(x, y)); // add one entry per hour - } - - // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(values, "DataSet 1"); - set1.setAxisDependency(AxisDependency.LEFT); - set1.setColor(ColorTemplate.getHoloBlue()); - set1.setValueTextColor(ColorTemplate.getHoloBlue()); - set1.setLineWidth(1.5f); - set1.setDrawCircles(false); - set1.setDrawValues(false); - set1.setFillAlpha(65); - set1.setFillColor(ColorTemplate.getHoloBlue()); - set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setDrawCircleHole(false); - - // create a data object with the datasets - LineData data = new LineData(set1); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(9f); - - // set data - mChart.setData(data); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + public void saveToGallery() { + saveToGallery(chart, "LineChartTime"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + public void onStartTrackingTouch(SeekBar seekBar) {} - } -} \ No newline at end of file + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 54218a53da..1466e5f9de 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -1,11 +1,16 @@ package com.xxmassdeveloper.mpchartexample; +import android.annotation.SuppressLint; import android.content.Context; +import android.content.Intent; import android.graphics.Color; -import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.annotation.NonNull; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -28,8 +33,8 @@ /** * Demonstrates the use of charts inside a ListView. IMPORTANT: provide a - * specific height attribute for the chart inside your listview-item - * + * specific height attribute for the chart inside your ListView item + * * @author Philipp Jahoda */ public class ListViewBarChartActivity extends DemoBase { @@ -40,10 +45,12 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - + + setTitle("ListViewBarChartActivity"); + ListView lv = findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); // 20 items for (int i = 0; i < 20; i++) { @@ -56,16 +63,18 @@ protected void onCreate(Bundle savedInstanceState) { private class ChartDataAdapter extends ArrayAdapter { - public ChartDataAdapter(Context context, List objects) { + ChartDataAdapter(Context context, List objects) { super(context, 0, objects); } + @SuppressLint("InflateParams") + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { BarData data = getItem(position); - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -82,30 +91,32 @@ public View getView(int position, View convertView, ViewGroup parent) { } // apply styling - data.setValueTypeface(mTfLight); - data.setValueTextColor(Color.BLACK); + if (data != null) { + data.setValueTypeface(tfLight); + data.setValueTextColor(Color.BLACK); + } holder.chart.getDescription().setEnabled(false); holder.chart.setDrawGridBackground(false); XAxis xAxis = holder.chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); - xAxis.setTypeface(mTfLight); + xAxis.setTypeface(tfLight); xAxis.setDrawGridLines(false); - + YAxis leftAxis = holder.chart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + leftAxis.setTypeface(tfLight); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(15f); - + YAxis rightAxis = holder.chart.getAxisRight(); - rightAxis.setTypeface(mTfLight); + rightAxis.setTypeface(tfLight); rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(15f); // set data holder.chart.setData(data); holder.chart.setFitBars(true); - + // do not forget to refresh the chart // holder.chart.invalidate(); holder.chart.animateY(700); @@ -121,12 +132,12 @@ private class ViewHolder { /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Bar data */ private BarData generateData(int cnt) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 12; i++) { entries.add(new BarEntry(i, (float) (Math.random() * 70) + 30)); @@ -135,12 +146,36 @@ private BarData generateData(int cnt) { BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setBarShadowColor(Color.rgb(203, 203, 203)); - - ArrayList sets = new ArrayList(); + + ArrayList sets = new ArrayList<>(); sets.add(d); - + BarData cd = new BarData(sets); cd.setBarWidth(0.9f); return cd; } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 0c9f132f03..1455691620 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -2,8 +2,13 @@ package com.xxmassdeveloper.mpchartexample; import android.content.Context; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.annotation.NonNull; +import android.view.Menu; +import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; @@ -32,8 +37,8 @@ /** * Demonstrates the use of charts inside a ListView. IMPORTANT: provide a - * specific height attribute for the chart inside your listview-item - * + * specific height attribute for the chart inside your ListView item + * * @author Philipp Jahoda */ public class ListViewMultiChartActivity extends DemoBase { @@ -44,20 +49,22 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_listview_chart); - + + setTitle("ListViewMultiChartActivity"); + ListView lv = findViewById(R.id.listView1); - ArrayList list = new ArrayList(); + ArrayList list = new ArrayList<>(); // 30 items for (int i = 0; i < 30; i++) { - + if(i % 3 == 0) { list.add(new LineChartItem(generateDataLine(i + 1), getApplicationContext())); } else if(i % 3 == 1) { list.add(new BarChartItem(generateDataBar(i + 1), getApplicationContext())); } else if(i % 3 == 2) { - list.add(new PieChartItem(generateDataPie(i + 1), getApplicationContext())); + list.add(new PieChartItem(generateDataPie(), getApplicationContext())); } } @@ -67,77 +74,79 @@ protected void onCreate(Bundle savedInstanceState) { /** adapter that supports 3 different item types */ private class ChartDataAdapter extends ArrayAdapter { - - public ChartDataAdapter(Context context, List objects) { + + ChartDataAdapter(Context context, List objects) { super(context, 0, objects); } + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { + //noinspection ConstantConditions return getItem(position).getView(position, convertView, getContext()); } - + @Override - public int getItemViewType(int position) { + public int getItemViewType(int position) { // return the views type - return getItem(position).getItemType(); + ChartItem ci = getItem(position); + return ci != null ? ci.getItemType() : 0; } - + @Override public int getViewTypeCount() { return 3; // we have 3 different item-types } } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Line data */ private LineData generateDataLine(int cnt) { - ArrayList e1 = new ArrayList(); + ArrayList values1 = new ArrayList<>(); for (int i = 0; i < 12; i++) { - e1.add(new Entry(i, (int) (Math.random() * 65) + 40)); + values1.add(new Entry(i, (int) (Math.random() * 65) + 40)); } - LineDataSet d1 = new LineDataSet(e1, "New DataSet " + cnt + ", (1)"); + LineDataSet d1 = new LineDataSet(values1, "New DataSet " + cnt + ", (1)"); d1.setLineWidth(2.5f); d1.setCircleRadius(4.5f); d1.setHighLightColor(Color.rgb(244, 117, 117)); d1.setDrawValues(false); - - ArrayList e2 = new ArrayList(); + + ArrayList values2 = new ArrayList<>(); for (int i = 0; i < 12; i++) { - e2.add(new Entry(i, e1.get(i).getY() - 30)); + values2.add(new Entry(i, values1.get(i).getY() - 30)); } - LineDataSet d2 = new LineDataSet(e2, "New DataSet " + cnt + ", (2)"); + LineDataSet d2 = new LineDataSet(values2, "New DataSet " + cnt + ", (2)"); d2.setLineWidth(2.5f); d2.setCircleRadius(4.5f); d2.setHighLightColor(Color.rgb(244, 117, 117)); d2.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setDrawValues(false); - - ArrayList sets = new ArrayList(); + + ArrayList sets = new ArrayList<>(); sets.add(d1); sets.add(d2); - - LineData cd = new LineData(sets); - return cd; + + return new LineData(sets); } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Bar data */ private BarData generateDataBar(int cnt) { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 12; i++) { entries.add(new BarEntry(i, (int) (Math.random() * 70) + 30)); @@ -146,32 +155,55 @@ private BarData generateDataBar(int cnt) { BarDataSet d = new BarDataSet(entries, "New DataSet " + cnt); d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setHighLightAlpha(255); - + BarData cd = new BarData(d); cd.setBarWidth(0.9f); return cd; } - + /** * generates a random ChartData object with just one DataSet - * - * @return + * + * @return Pie data */ - private PieData generateDataPie(int cnt) { + private PieData generateDataPie() { - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); for (int i = 0; i < 4; i++) { entries.add(new PieEntry((float) ((Math.random() * 70) + 30), "Quarter " + (i+1))); } PieDataSet d = new PieDataSet(entries, ""); - + // space between slices d.setSliceSpace(2f); d.setColors(ColorTemplate.VORDIPLOM_COLORS); - - PieData cd = new PieData(d); - return cd; + + return new PieData(d); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java")); + startActivity(i); + break; + } + } + + return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index e6acf01670..c5cbd570c6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -1,10 +1,16 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; +import android.view.MotionEvent; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -12,12 +18,13 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.listener.ChartTouchListener; +import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -26,10 +33,10 @@ import java.util.List; public class MultiLineChartActivity extends DemoBase implements OnSeekBarChangeListener, - OnChartValueSelectedListener { + OnChartGestureListener, OnChartValueSelectedListener { - private LineChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private LineChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -39,51 +46,101 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_linechart); + setTitle("MultiLineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); + + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); - mChart.setDrawBorders(false); + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); + chart.setDrawBorders(false); - mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setDrawAxisLine(false); - mChart.getAxisRight().setDrawGridLines(false); - mChart.getXAxis().setDrawAxisLine(false); - mChart.getXAxis().setDrawGridLines(false); + chart.getAxisLeft().setEnabled(false); + chart.getAxisRight().setDrawAxisLine(false); + chart.getAxisRight().setDrawGridLines(false); + chart.getXAxis().setDrawAxisLine(false); + chart.getXAxis().setDrawGridLines(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mSeekBarX.setProgress(20); - mSeekBarY.setProgress(100); + seekBarX.setProgress(20); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); } + private final int[] colors = new int[] { + ColorTemplate.VORDIPLOM_COLORS[0], + ColorTemplate.VORDIPLOM_COLORS[1], + ColorTemplate.VORDIPLOM_COLORS[2] + }; + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + chart.resetTracking(); + + progress = seekBarX.getProgress(); + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList dataSets = new ArrayList<>(); + + for (int z = 0; z < 3; z++) { + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < progress; i++) { + double val = (Math.random() * seekBarY.getProgress()) + 3; + values.add(new Entry(i, (float) val)); + } + + LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); + d.setLineWidth(2.5f); + d.setCircleRadius(4f); + + int color = colors[z % colors.length]; + d.setColor(color); + d.setCircleColor(color); + dataSets.add(d); + } + + // make the first DataSet dashed + ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); + ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); + ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); + + LineData data = new LineData(dataSets); + chart.setData(data); + chart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.line, menu); + menu.removeItem(R.id.actionToggleIcons); return true; } @@ -91,8 +148,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -101,32 +164,35 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } + /* + case R.id.actionToggleIcons: { break; } + */ case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleFilled: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -137,11 +203,11 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleCircles: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (ILineDataSet iSet : sets) { @@ -152,74 +218,122 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawCircles(true); } - mChart.invalidate(); + chart.invalidate(); + break; + } + case R.id.actionToggleCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.CUBIC_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.CUBIC_BEZIER); + } + chart.invalidate(); + break; + } + case R.id.actionToggleStepped: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.STEPPED + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.STEPPED); + } + chart.invalidate(); + break; + } + case R.id.actionToggleHorizontalCubic: { + List sets = chart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + set.setMode(set.getMode() == LineDataSet.Mode.HORIZONTAL_BEZIER + ? LineDataSet.Mode.LINEAR + : LineDataSet.Mode.HORIZONTAL_BEZIER); + } + chart.invalidate(); break; } case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } } return true; } - private int[] mColors = new int[] { - ColorTemplate.VORDIPLOM_COLORS[0], - ColorTemplate.VORDIPLOM_COLORS[1], - ColorTemplate.VORDIPLOM_COLORS[2] - }; - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - mChart.resetTracking(); + public void saveToGallery() { + saveToGallery(chart, "MultiLineChartActivity"); + } - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); + @Override + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + Log.i("Gesture", "START, x: " + me.getX() + ", y: " + me.getY()); + } - ArrayList dataSets = new ArrayList(); + @Override + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); - for (int z = 0; z < 3; z++) { + // un-highlight values after the gesture is finished and no single-tap + if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) + chart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) + } - ArrayList values = new ArrayList(); + @Override + public void onChartLongPressed(MotionEvent me) { + Log.i("LongPress", "Chart long pressed."); + } - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - double val = (Math.random() * mSeekBarY.getProgress()) + 3; - values.add(new Entry(i, (float) val)); - } + @Override + public void onChartDoubleTapped(MotionEvent me) { + Log.i("DoubleTap", "Chart double-tapped."); + } - LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); - d.setLineWidth(2.5f); - d.setCircleRadius(4f); + @Override + public void onChartSingleTapped(MotionEvent me) { + Log.i("SingleTap", "Chart single-tapped."); + } - int color = mColors[z % mColors.length]; - d.setColor(color); - d.setCircleColor(color); - dataSets.add(d); - } + @Override + public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { + Log.i("Fling", "Chart fling. VelocityX: " + velocityX + ", VelocityY: " + velocityY); + } - // make the first DataSet dashed - ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); - ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); - ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); + @Override + public void onChartScale(MotionEvent me, float scaleX, float scaleY) { + Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); + } - LineData data = new LineData(dataSets); - mChart.setData(data); - mChart.invalidate(); + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); } @Override @@ -230,16 +344,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index a2d4becadc..c557323451 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -1,8 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; @@ -17,11 +21,12 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class PerformanceLineChart extends DemoBase implements OnSeekBarChangeListener { - private LineChart mChart; - private SeekBar mSeekBarValues; - private TextView mTvCount; + private LineChart chart; + private SeekBar seekBarValues; + private TextView tvCount; @Override protected void onCreate(Bundle savedInstanceState) { @@ -30,80 +35,51 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_performance_linechart); - mTvCount = findViewById(R.id.tvValueCount); - mSeekBarValues = findViewById(R.id.seekbarValues); - mTvCount.setText("500"); + setTitle("PerformanceLineChart"); - mSeekBarValues.setProgress(500); - - mSeekBarValues.setOnSeekBarChangeListener(this); + tvCount = findViewById(R.id.tvValueCount); + seekBarValues = findViewById(R.id.seekbarValues); + seekBarValues.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setDrawGridBackground(false); + chart = findViewById(R.id.chart1); + chart.setDrawGridBackground(false); // no description text - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getAxisRight().setEnabled(false); - mChart.getXAxis().setDrawGridLines(true); - mChart.getXAxis().setDrawAxisLine(false); - - // dont forget to refresh the drawing - mChart.invalidate(); - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - int count = mSeekBarValues.getProgress() + 1000; - mTvCount.setText("" + count); - - mChart.resetTracking(); - - setData(count, 500f); - - // redraw - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + chart.setPinchZoom(false); - } + chart.getAxisLeft().setDrawGridLines(false); + chart.getAxisRight().setEnabled(false); + chart.getXAxis().setDrawGridLines(true); + chart.getXAxis().setDrawAxisLine(false); - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub + seekBarValues.setProgress(9000); + // don't forget to refresh the drawing + chart.invalidate(); } private void setData(int count, float range) { - ArrayList yVals = new ArrayList(); + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10); - yVals.add(new Entry(i * 0.001f, val)); + float val = (float) (Math.random() * (range + 1)) + 3; + values.add(new Entry(i * 0.001f, val)); } // create a dataset and give it a type - LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); - + LineDataSet set1 = new LineDataSet(values, "DataSet 1"); + set1.setColor(Color.BLACK); set1.setLineWidth(0.5f); set1.setDrawValues(false); @@ -111,14 +87,58 @@ private void setData(int count, float range) { set1.setMode(LineDataSet.Mode.LINEAR); set1.setDrawFilled(false); - // create a data object with the datasets + // create a data object with the data sets LineData data = new LineData(set1); // set data - mChart.setData(data); - + chart.setData(data); + // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setEnabled(false); } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + int count = seekBarValues.getProgress() + 1000; + tvCount.setText(String.valueOf(count)); + + chart.resetTracking(); + + setData(count, 500f); + + // redraw + chart.invalidate(); + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) {} + + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 0252ff8ff0..9d77dcc8b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -1,9 +1,14 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -19,7 +24,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; @@ -37,8 +41,8 @@ public class PieChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private PieChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private PieChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -48,55 +52,57 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); + setTitle("PieChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setProgress(4); - mSeekBarY.setProgress(10); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); + + seekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); - mChart.setExtraOffsets(5, 10, 5, 5); + chart = findViewById(R.id.chart1); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); + chart.setExtraOffsets(5, 10, 5, 5); - mChart.setDragDecelerationFrictionCoef(0.95f); + chart.setDragDecelerationFrictionCoef(0.95f); - mChart.setCenterTextTypeface(mTfLight); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(tfLight); + chart.setCenterText(generateCenterSpannableText()); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationAngle(0); + chart.setRotationAngle(0); // enable rotation of the chart by touch - mChart.setRotationEnabled(true); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(true); + chart.setHighlightPerTapEnabled(true); - // mChart.setUnit(" €"); - // mChart.setDrawUnitsInChart(true); + // chart.setUnit(" €"); + // chart.setDrawUnitsInChart(true); // add a selection listener - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); + seekBarX.setProgress(4); + seekBarY.setProgress(10); setData(4, 100); - mChart.animateY(1400, Easing.EaseInOutQuad); - // mChart.spin(2000, 0, 360); + chart.animateY(1400, Easing.EaseInOutQuad); + // chart.spin(2000, 0, 360); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); @@ -106,9 +112,65 @@ protected void onCreate(Bundle savedInstanceState) { l.setYOffset(0f); // entry label styling - mChart.setEntryLabelColor(Color.WHITE); - mChart.setEntryLabelTypeface(mTfRegular); - mChart.setEntryLabelTextSize(12f); + chart.setEntryLabelColor(Color.WHITE); + chart.setEntryLabelTypeface(tfRegular); + chart.setEntryLabelTextSize(12f); + } + + private void setData(int count, float range) { + ArrayList entries = new ArrayList<>(); + + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < count ; i++) { + entries.add(new PieEntry((float) ((Math.random() * range) + range / 5), + parties[i % parties.length], + getResources().getDrawable(R.drawable.star))); + } + + PieDataSet dataSet = new PieDataSet(entries, "Election Results"); + + dataSet.setDrawIcons(false); + + dataSet.setSliceSpace(3f); + dataSet.setIconsOffset(new MPPointF(0, 40)); + dataSet.setSelectionShift(5f); + + // add a lot of colors + + ArrayList colors = new ArrayList<>(); + + for (int c : ColorTemplate.VORDIPLOM_COLORS) + colors.add(c); + + for (int c : ColorTemplate.JOYFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.COLORFUL_COLORS) + colors.add(c); + + for (int c : ColorTemplate.LIBERTY_COLORS) + colors.add(c); + + for (int c : ColorTemplate.PASTEL_COLORS) + colors.add(c); + + colors.add(ColorTemplate.getHoloBlue()); + + dataSet.setColors(colors); + //dataSet.setSelectionShift(0f); + + PieData data = new PieData(dataSet); + data.setValueFormatter(new PercentFormatter()); + data.setValueTextSize(11f); + data.setValueTextColor(Color.WHITE); + data.setValueTypeface(tfLight); + chart.setData(data); + + // undo all highlights + chart.highlightValues(null); + + chart.invalidate(); } @Override @@ -121,65 +183,74 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawIcons(!set.isDrawIconsEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHole: { - if (mChart.isDrawHoleEnabled()) - mChart.setDrawHoleEnabled(false); + if (chart.isDrawHoleEnabled()) + chart.setDrawHoleEnabled(false); else - mChart.setDrawHoleEnabled(true); - mChart.invalidate(); + chart.setDrawHoleEnabled(true); + chart.invalidate(); break; } case R.id.actionDrawCenter: { - if (mChart.isDrawCenterTextEnabled()) - mChart.setDrawCenterText(false); + if (chart.isDrawCenterTextEnabled()) + chart.setDrawCenterText(false); else - mChart.setDrawCenterText(true); - mChart.invalidate(); + chart.setDrawCenterText(true); + chart.invalidate(); break; } - case R.id.actionToggleXVals: { + case R.id.actionToggleXValues: { - mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); - mChart.invalidate(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + chart.setDrawEntryLabels(!chart.isDrawEntryLabelsEnabled()); + chart.invalidate(); break; } case R.id.actionTogglePercent: - mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); - mChart.invalidate(); + chart.setUsePercentValues(!chart.isUsePercentValuesEnabled()); + chart.invalidate(); break; case R.id.animateX: { - mChart.animateX(1400); + chart.animateX(1400); break; } case R.id.animateY: { - mChart.animateY(1400); + chart.animateY(1400); break; } case R.id.animateXY: { - mChart.animateXY(1400, 1400); + chart.animateXY(1400, 1400); break; } case R.id.actionToggleSpin: { - mChart.spin(1000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); + chart.spin(1000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -189,69 +260,15 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); + setData(seekBarX.getProgress(), seekBarY.getProgress()); } - private void setData(int count, float range) { - - float mult = range; - - ArrayList entries = new ArrayList(); - - // NOTE: The order of the entries when being added to the entries array determines their position around the center of - // the chart. - for (int i = 0; i < count ; i++) { - entries.add(new PieEntry((float) ((Math.random() * mult) + mult / 5), - mParties[i % mParties.length], - getResources().getDrawable(R.drawable.star))); - } - - PieDataSet dataSet = new PieDataSet(entries, "Election Results"); - - dataSet.setDrawIcons(false); - - dataSet.setSliceSpace(3f); - dataSet.setIconsOffset(new MPPointF(0, 40)); - dataSet.setSelectionShift(5f); - - // add a lot of colors - - ArrayList colors = new ArrayList(); - - for (int c : ColorTemplate.VORDIPLOM_COLORS) - colors.add(c); - - for (int c : ColorTemplate.JOYFUL_COLORS) - colors.add(c); - - for (int c : ColorTemplate.COLORFUL_COLORS) - colors.add(c); - - for (int c : ColorTemplate.LIBERTY_COLORS) - colors.add(c); - - for (int c : ColorTemplate.PASTEL_COLORS) - colors.add(c); - - colors.add(ColorTemplate.getHoloBlue()); - - dataSet.setColors(colors); - //dataSet.setSelectionShift(0f); - - PieData data = new PieData(dataSet); - data.setValueFormatter(new PercentFormatter()); - data.setValueTextSize(11f); - data.setValueTextColor(Color.WHITE); - data.setValueTypeface(mTfLight); - mChart.setData(data); - - // undo all highlights - mChart.highlightValues(null); - - mChart.invalidate(); + @Override + public void saveToGallery() { + saveToGallery(chart, "PieChartActivity"); } private SpannableString generateCenterSpannableText() { @@ -282,14 +299,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index c0199723d9..80ca82cde9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -1,9 +1,14 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; import android.graphics.Typeface; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -35,8 +40,8 @@ public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private PieChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private PieChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; private Typeface tf; @@ -48,59 +53,61 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_piechart); + setTitle("PiePolylineChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarY = findViewById(R.id.seekBar2); - - mSeekBarY.setProgress(10); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setUsePercentValues(true); - mChart.getDescription().setEnabled(false); - mChart.setExtraOffsets(5, 10, 5, 5); + chart = findViewById(R.id.chart1); + chart.setUsePercentValues(true); + chart.getDescription().setEnabled(false); + chart.setExtraOffsets(5, 10, 5, 5); - mChart.setDragDecelerationFrictionCoef(0.95f); + chart.setDragDecelerationFrictionCoef(0.95f); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); - mChart.setCenterText(generateCenterSpannableText()); + chart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); + chart.setCenterText(generateCenterSpannableText()); - mChart.setExtraOffsets(20.f, 0.f, 20.f, 0.f); + chart.setExtraOffsets(20.f, 0.f, 20.f, 0.f); - mChart.setDrawHoleEnabled(true); - mChart.setHoleColor(Color.WHITE); + chart.setDrawHoleEnabled(true); + chart.setHoleColor(Color.WHITE); - mChart.setTransparentCircleColor(Color.WHITE); - mChart.setTransparentCircleAlpha(110); + chart.setTransparentCircleColor(Color.WHITE); + chart.setTransparentCircleAlpha(110); - mChart.setHoleRadius(58f); - mChart.setTransparentCircleRadius(61f); + chart.setHoleRadius(58f); + chart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + chart.setDrawCenterText(true); - mChart.setRotationAngle(0); + chart.setRotationAngle(0); // enable rotation of the chart by touch - mChart.setRotationEnabled(true); - mChart.setHighlightPerTapEnabled(true); + chart.setRotationEnabled(true); + chart.setHighlightPerTapEnabled(true); - // mChart.setUnit(" €"); - // mChart.setDrawUnitsInChart(true); + // chart.setUnit(" €"); + // chart.setDrawUnitsInChart(true); // add a selection listener - mChart.setOnChartValueSelectedListener(this); + chart.setOnChartValueSelectedListener(this); + seekBarX.setProgress(4); + seekBarY.setProgress(100); setData(4, 100); - mChart.animateY(1400, Easing.EaseInOutQuad); - // mChart.spin(2000, 0, 360); + chart.animateY(1400, Easing.EaseInOutQuad); + // chart.spin(2000, 0, 360); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); @@ -108,89 +115,14 @@ protected void onCreate(Bundle savedInstanceState) { l.setEnabled(false); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.pie, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) - set.setDrawValues(!set.isDrawValuesEnabled()); - - mChart.invalidate(); - break; - } - case R.id.actionToggleHole: { - if (mChart.isDrawHoleEnabled()) - mChart.setDrawHoleEnabled(false); - else - mChart.setDrawHoleEnabled(true); - mChart.invalidate(); - break; - } - case R.id.actionDrawCenter: { - if (mChart.isDrawCenterTextEnabled()) - mChart.setDrawCenterText(false); - else - mChart.setDrawCenterText(true); - mChart.invalidate(); - break; - } - case R.id.actionToggleXVals: { - - mChart.setDrawEntryLabels(!mChart.isDrawEntryLabelsEnabled()); - mChart.invalidate(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); - break; - } - case R.id.actionTogglePercent: - mChart.setUsePercentValues(!mChart.isUsePercentValuesEnabled()); - mChart.invalidate(); - break; - case R.id.animateX: { - mChart.animateX(1400); - break; - } - case R.id.animateY: { - mChart.animateY(1400); - break; - } - case R.id.animateXY: { - mChart.animateXY(1400, 1400); - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress())); - tvY.setText("" + (mSeekBarY.getProgress())); - - setData(mSeekBarX.getProgress(), mSeekBarY.getProgress()); - } - private void setData(int count, float range) { - float mult = range; - - ArrayList entries = new ArrayList(); + ArrayList entries = new ArrayList<>(); // NOTE: The order of the entries when being added to the entries array determines their position around the center of // the chart. for (int i = 0; i < count; i++) { - entries.add(new PieEntry((float) (Math.random() * mult) + mult / 5, mParties[i % mParties.length])); + entries.add(new PieEntry((float) (Math.random() * range) + range / 5, parties[i % parties.length])); } PieDataSet dataSet = new PieDataSet(entries, "Election Results"); @@ -199,7 +131,7 @@ private void setData(int count, float range) { // add a lot of colors - ArrayList colors = new ArrayList(); + ArrayList colors = new ArrayList<>(); for (int c : ColorTemplate.VORDIPLOM_COLORS) colors.add(c); @@ -235,12 +167,103 @@ private void setData(int count, float range) { data.setValueTextSize(11f); data.setValueTextColor(Color.BLACK); data.setValueTypeface(tf); - mChart.setData(data); + chart.setData(data); // undo all highlights - mChart.highlightValues(null); + chart.highlightValues(null); + + chart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.pie, menu); + return true; + } - mChart.invalidate(); + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionToggleValues: { + for (IDataSet set : chart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + chart.invalidate(); + break; + } + case R.id.actionToggleHole: { + if (chart.isDrawHoleEnabled()) + chart.setDrawHoleEnabled(false); + else + chart.setDrawHoleEnabled(true); + chart.invalidate(); + break; + } + case R.id.actionDrawCenter: { + if (chart.isDrawCenterTextEnabled()) + chart.setDrawCenterText(false); + else + chart.setDrawCenterText(true); + chart.invalidate(); + break; + } + case R.id.actionToggleXValues: { + + chart.setDrawEntryLabels(!chart.isDrawEntryLabelsEnabled()); + chart.invalidate(); + break; + } + case R.id.actionTogglePercent: + chart.setUsePercentValues(!chart.isUsePercentValuesEnabled()); + chart.invalidate(); + break; + case R.id.animateX: { + chart.animateX(1400); + break; + } + case R.id.animateY: { + chart.animateY(1400); + break; + } + case R.id.animateXY: { + chart.animateXY(1400, 1400); + break; + } + case R.id.actionToggleSpin: { + chart.spin(1000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + setData(seekBarX.getProgress(), seekBarY.getProgress()); + } + + @Override + public void saveToGallery() { + saveToGallery(chart, "PiePolylineChartActivity"); } private SpannableString generateCenterSpannableText() { @@ -271,14 +294,8 @@ public void onNothingSelected() { } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index d354886f6e..c2a5eb3d0a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,13 +1,16 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; -import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; @@ -29,49 +32,46 @@ public class RadarChartActivity extends DemoBase { - private RadarChart mChart; + private RadarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); + setContentView(R.layout.activity_radarchart); - TextView tv = findViewById(R.id.textView); - tv.setTypeface(mTfLight); - tv.setTextColor(Color.WHITE); - tv.setBackgroundColor(Color.rgb(60, 65, 82)); + setTitle("RadarChartActivity"); - mChart = findViewById(R.id.chart1); - mChart.setBackgroundColor(Color.rgb(60, 65, 82)); + chart = findViewById(R.id.chart1); + chart.setBackgroundColor(Color.rgb(60, 65, 82)); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); - mChart.setWebLineWidth(1f); - mChart.setWebColor(Color.LTGRAY); - mChart.setWebLineWidthInner(1f); - mChart.setWebColorInner(Color.LTGRAY); - mChart.setWebAlpha(100); + chart.setWebLineWidth(1f); + chart.setWebColor(Color.LTGRAY); + chart.setWebLineWidthInner(1f); + chart.setWebColorInner(Color.LTGRAY); + chart.setWebAlpha(100); // create a custom MarkerView (extend MarkerView) and specify the layout // to use for it MarkerView mv = new RadarMarkerView(this, R.layout.radar_markerview); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); // Set the marker to the chart + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); // Set the marker to the chart setData(); - mChart.animateXY(1400, 1400, Easing.EaseInOutQuad); + chart.animateXY(1400, 1400, Easing.EaseInOutQuad); - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTfLight); + XAxis xAxis = chart.getXAxis(); + xAxis.setTypeface(tfLight); xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); xAxis.setValueFormatter(new IAxisValueFormatter() { - private String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; + private final String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override public String getFormattedValue(float value, AxisBase axis) { @@ -80,25 +80,76 @@ public String getFormattedValue(float value, AxisBase axis) { }); xAxis.setTextColor(Color.WHITE); - YAxis yAxis = mChart.getYAxis(); - yAxis.setTypeface(mTfLight); + YAxis yAxis = chart.getYAxis(); + yAxis.setTypeface(tfLight); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setAxisMinimum(0f); yAxis.setAxisMaximum(80f); yAxis.setDrawLabels(false); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setXEntrySpace(7f); l.setYEntrySpace(5f); l.setTextColor(Color.WHITE); } + private void setData() { + + float mul = 80; + float min = 20; + int cnt = 5; + + ArrayList entries1 = new ArrayList<>(); + ArrayList entries2 = new ArrayList<>(); + + // NOTE: The order of the entries when being added to the entries array determines their position around the center of + // the chart. + for (int i = 0; i < cnt; i++) { + float val1 = (float) (Math.random() * mul) + min; + entries1.add(new RadarEntry(val1)); + + float val2 = (float) (Math.random() * mul) + min; + entries2.add(new RadarEntry(val2)); + } + + RadarDataSet set1 = new RadarDataSet(entries1, "Last Week"); + set1.setColor(Color.rgb(103, 110, 129)); + set1.setFillColor(Color.rgb(103, 110, 129)); + set1.setDrawFilled(true); + set1.setFillAlpha(180); + set1.setLineWidth(2f); + set1.setDrawHighlightCircleEnabled(true); + set1.setDrawHighlightIndicators(false); + + RadarDataSet set2 = new RadarDataSet(entries2, "This Week"); + set2.setColor(Color.rgb(121, 162, 175)); + set2.setFillColor(Color.rgb(121, 162, 175)); + set2.setDrawFilled(true); + set2.setFillAlpha(180); + set2.setLineWidth(2f); + set2.setDrawHighlightCircleEnabled(true); + set2.setDrawHighlightIndicators(false); + + ArrayList sets = new ArrayList<>(); + sets.add(set1); + sets.add(set2); + + RadarData data = new RadarData(sets); + data.setValueTypeface(tfLight); + data.setValueTextSize(8f); + data.setDrawValues(false); + data.setValueTextColor(Color.WHITE); + + chart.setData(data); + chart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.radar, menu); @@ -109,31 +160,37 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - for (IDataSet set : mChart.getData().getDataSets()) + for (IDataSet set : chart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionToggleRotate: { - if (mChart.isRotationEnabled()) - mChart.setRotationEnabled(false); + if (chart.isRotationEnabled()) + chart.setRotationEnabled(false); else - mChart.setRotationEnabled(true); - mChart.invalidate(); + chart.setRotationEnabled(true); + chart.invalidate(); break; } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + ArrayList sets = (ArrayList) chart.getData() .getDataSets(); for (IRadarDataSet set : sets) { @@ -142,109 +199,62 @@ public boolean onOptionsItemSelected(MenuItem item) { else set.setDrawFilled(true); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlightCircle: { - ArrayList sets = (ArrayList) mChart.getData() + ArrayList sets = (ArrayList) chart.getData() .getDataSets(); for (IRadarDataSet set : sets) { set.setDrawHighlightCircleEnabled(!set.isDrawHighlightCircleEnabled()); } - mChart.invalidate(); - break; - } - case R.id.actionSave: { - if (mChart.saveToPath("title" + System.currentTimeMillis(), "")) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + chart.invalidate(); break; } case R.id.actionToggleXLabels: { - mChart.getXAxis().setEnabled(!mChart.getXAxis().isEnabled()); - mChart.notifyDataSetChanged(); - mChart.invalidate(); + chart.getXAxis().setEnabled(!chart.getXAxis().isEnabled()); + chart.notifyDataSetChanged(); + chart.invalidate(); break; } case R.id.actionToggleYLabels: { - mChart.getYAxis().setEnabled(!mChart.getYAxis().isEnabled()); - mChart.invalidate(); + chart.getYAxis().setEnabled(!chart.getYAxis().isEnabled()); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(1400); + chart.animateX(1400); break; } case R.id.animateY: { - mChart.animateY(1400); + chart.animateY(1400); break; } case R.id.animateXY: { - mChart.animateXY(1400, 1400); + chart.animateXY(1400, 1400); break; } case R.id.actionToggleSpin: { - mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EaseInCubic); + chart.spin(2000, chart.getRotationAngle(), chart.getRotationAngle() + 360, Easing.EaseInOutCubic); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } return true; } - public void setData() { - - float mult = 80; - float min = 20; - int cnt = 5; - - ArrayList entries1 = new ArrayList(); - ArrayList entries2 = new ArrayList(); - - // NOTE: The order of the entries when being added to the entries array determines their position around the center of - // the chart. - for (int i = 0; i < cnt; i++) { - float val1 = (float) (Math.random() * mult) + min; - entries1.add(new RadarEntry(val1)); - - float val2 = (float) (Math.random() * mult) + min; - entries2.add(new RadarEntry(val2)); - } - - RadarDataSet set1 = new RadarDataSet(entries1, "Last Week"); - set1.setColor(Color.rgb(103, 110, 129)); - set1.setFillColor(Color.rgb(103, 110, 129)); - set1.setDrawFilled(true); - set1.setFillAlpha(180); - set1.setLineWidth(2f); - set1.setDrawHighlightCircleEnabled(true); - set1.setDrawHighlightIndicators(false); - - RadarDataSet set2 = new RadarDataSet(entries2, "This Week"); - set2.setColor(Color.rgb(121, 162, 175)); - set2.setFillColor(Color.rgb(121, 162, 175)); - set2.setDrawFilled(true); - set2.setFillAlpha(180); - set2.setLineWidth(2f); - set2.setDrawHighlightCircleEnabled(true); - set2.setDrawHighlightIndicators(false); - - ArrayList sets = new ArrayList(); - sets.add(set1); - sets.add(set2); - - RadarData data = new RadarData(sets); - data.setValueTypeface(mTfLight); - data.setValueTextSize(8f); - data.setDrawValues(false); - data.setValueTextColor(Color.WHITE); - - mChart.setData(data); - mChart.invalidate(); + @Override + public void saveToGallery() { + saveToGallery(chart, "RadarChartActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index f3661628d0..606d750efe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -1,8 +1,13 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -27,7 +32,7 @@ public class RealtimeLineChartActivity extends DemoBase implements OnChartValueSelectedListener { - private LineChart mChart; + private LineChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -36,89 +41,64 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_realtime_linechart); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + setTitle("RealtimeLineChartActivity"); + + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); // enable description text - mChart.getDescription().setEnabled(true); + chart.getDescription().setEnabled(true); // enable touch gestures - mChart.setTouchEnabled(true); + chart.setTouchEnabled(true); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - mChart.setDrawGridBackground(false); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); + chart.setDrawGridBackground(false); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + chart.setPinchZoom(true); // set an alternative background color - mChart.setBackgroundColor(Color.LTGRAY); + chart.setBackgroundColor(Color.LTGRAY); LineData data = new LineData(); data.setValueTextColor(Color.WHITE); // add empty data - mChart.setData(data); + chart.setData(data); // get the legend (only possible after setting data) - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); // modify the legend ... l.setForm(LegendForm.LINE); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setTextColor(Color.WHITE); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(mTfLight); + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfLight); xl.setTextColor(Color.WHITE); xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); xl.setEnabled(true); - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.setTypeface(mTfLight); + YAxis leftAxis = chart.getAxisLeft(); + leftAxis.setTypeface(tfLight); leftAxis.setTextColor(Color.WHITE); leftAxis.setAxisMaximum(100f); leftAxis.setAxisMinimum(0f); leftAxis.setDrawGridLines(true); - YAxis rightAxis = mChart.getAxisRight(); + YAxis rightAxis = chart.getAxisRight(); rightAxis.setEnabled(false); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realtime, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionAdd: { - addEntry(); - break; - } - case R.id.actionClear: { - mChart.clearValues(); - Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); - break; - } - case R.id.actionFeedMultiple: { - feedMultiple(); - break; - } - } - return true; - } - private void addEntry() { - LineData data = mChart.getData(); + LineData data = chart.getData(); if (data != null) { @@ -134,17 +114,17 @@ private void addEntry() { data.notifyDataChanged(); // let the chart know it's data has changed - mChart.notifyDataSetChanged(); + chart.notifyDataSetChanged(); // limit the number of visible entries - mChart.setVisibleXRangeMaximum(120); - // mChart.setVisibleYRange(30, AxisDependency.LEFT); + chart.setVisibleXRangeMaximum(120); + // chart.setVisibleYRange(30, AxisDependency.LEFT); // move to the latest entry - mChart.moveViewToX(data.getEntryCount()); + chart.moveViewToX(data.getEntryCount()); // this automatically refreshes the chart (calls invalidate()) - // mChart.moveViewTo(data.getXValCount()-7, 55f, + // chart.moveViewTo(data.getXValCount()-7, 55f, // AxisDependency.LEFT); } } @@ -193,7 +173,6 @@ public void run() { try { Thread.sleep(25); } catch (InterruptedException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } @@ -203,6 +182,52 @@ public void run() { thread.start(); } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.realtime, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java")); + startActivity(i); + break; + } + case R.id.actionAdd: { + addEntry(); + break; + } + case R.id.actionClear: { + chart.clearValues(); + Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); + break; + } + case R.id.actionFeedMultiple: { + feedMultiple(); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } + break; + } + } + return true; + } + + @Override + public void saveToGallery() { + saveToGallery(chart, "RealtimeLineChartActivity"); + } + @Override public void onValueSelected(Entry e, Highlight h) { Log.i("Entry selected", e.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index f0f889e194..9b441793f0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -12,7 +17,6 @@ import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; @@ -31,10 +35,10 @@ public class ScatterChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private ScatterChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private ScatterChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; - + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -42,52 +46,109 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scatterchart); + setTitle("ScatterChartActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.getDescription().setEnabled(false); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.getDescription().setEnabled(false); + chart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.setTouchEnabled(true); - mChart.setMaxHighlightDistance(50f); + chart.setDrawGridBackground(false); + chart.setTouchEnabled(true); + chart.setMaxHighlightDistance(50f); // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); + chart.setDragEnabled(true); + chart.setScaleEnabled(true); - mChart.setMaxVisibleValueCount(200); - mChart.setPinchZoom(true); + chart.setMaxVisibleValueCount(200); + chart.setPinchZoom(true); - mSeekBarX.setProgress(45); - mSeekBarY.setProgress(100); + seekBarX.setProgress(45); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - l.setTypeface(mTfLight); + l.setTypeface(tfLight); l.setXOffset(5f); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setAxisMinimum(0f); // this replaces setStartAtZero(true) - - mChart.getAxisRight().setEnabled(false); - XAxis xl = mChart.getXAxis(); - xl.setTypeface(mTfLight); + chart.getAxisRight().setEnabled(false); + + XAxis xl = chart.getXAxis(); + xl.setTypeface(tfLight); xl.setDrawGridLines(false); } + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values1 = new ArrayList<>(); + ArrayList values2 = new ArrayList<>(); + ArrayList values3 = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values1.add(new Entry(i, val)); + } + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values2.add(new Entry(i+0.33f, val)); + } + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float val = (float) (Math.random() * seekBarY.getProgress()) + 3; + values3.add(new Entry(i+0.66f, val)); + } + + // create a dataset and give it a type + ScatterDataSet set1 = new ScatterDataSet(values1, "DS 1"); + set1.setScatterShape(ScatterChart.ScatterShape.SQUARE); + set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); + ScatterDataSet set2 = new ScatterDataSet(values2, "DS 2"); + set2.setScatterShape(ScatterChart.ScatterShape.CIRCLE); + set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); + set2.setScatterShapeHoleRadius(3f); + set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); + ScatterDataSet set3 = new ScatterDataSet(values3, "DS 3"); + set3.setShapeRenderer(new CustomScatterShapeRenderer()); + set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); + + set1.setScatterShapeSize(8f); + set2.setScatterShapeSize(8f); + set3.setScatterShapeSize(8f); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); // add the data sets + dataSets.add(set2); + dataSets.add(set3); + + // create a data object with the data sets + ScatterData data = new ScatterData(dataSets); + data.setValueTypeface(tfLight); + + chart.setData(data); + chart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.scatter, menu); @@ -98,8 +159,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IScatterDataSet iSet : sets) { @@ -108,46 +175,49 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionSave: { - // mChart.saveToGallery("title"+System.currentTimeMillis()); - mChart.saveToPath("title" + System.currentTimeMillis(), ""); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(3000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(3000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(3000, 3000); + break; + } + case R.id.actionSave: { + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -155,58 +225,8 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - ArrayList yVals2 = new ArrayList(); - ArrayList yVals3 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals1.add(new Entry(i, val)); - } - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals2.add(new Entry(i+0.33f, val)); - } - - for (int i = 0; i < mSeekBarX.getProgress(); i++) { - float val = (float) (Math.random() * mSeekBarY.getProgress()) + 3; - yVals3.add(new Entry(i+0.66f, val)); - } - - // create a dataset and give it a type - ScatterDataSet set1 = new ScatterDataSet(yVals1, "DS 1"); - set1.setScatterShape(ScatterChart.ScatterShape.SQUARE); - set1.setColor(ColorTemplate.COLORFUL_COLORS[0]); - ScatterDataSet set2 = new ScatterDataSet(yVals2, "DS 2"); - set2.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - set2.setScatterShapeHoleColor(ColorTemplate.COLORFUL_COLORS[3]); - set2.setScatterShapeHoleRadius(3f); - set2.setColor(ColorTemplate.COLORFUL_COLORS[1]); - ScatterDataSet set3 = new ScatterDataSet(yVals3, "DS 3"); - set3.setShapeRenderer(new CustomScatterShapeRenderer()); - set3.setColor(ColorTemplate.COLORFUL_COLORS[2]); - - set1.setScatterShapeSize(8f); - set2.setScatterShapeSize(8f); - set3.setScatterShapeSize(8f); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - dataSets.add(set2); - dataSets.add(set3); - - // create a data object with the datasets - ScatterData data = new ScatterData(dataSets); - data.setValueTypeface(mTfLight); - - mChart.setData(data); - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "ScatterChartActivity"); } @Override @@ -217,20 +237,11 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 1aeb7f0f0c..37de64d728 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -1,7 +1,11 @@ package com.xxmassdeveloper.mpchartexample; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; @@ -15,9 +19,10 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public class ScrollViewActivity extends DemoBase { - private BarChart mChart; + private BarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -26,45 +31,71 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_scrollview); - mChart = findViewById(R.id.chart1); + setTitle("ScrollViewActivity"); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + + chart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawBarShadow(false); - mChart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setDrawGridLines(false); - mChart.getAxisLeft().setDrawGridLines(false); - - mChart.getLegend().setEnabled(false); + chart.getAxisLeft().setDrawGridLines(false); + + chart.getLegend().setEnabled(false); setData(10); - mChart.setFitBars(true); + chart.setFitBars(true); } - + private void setData(int count) { - - ArrayList yVals = new ArrayList(); + + ArrayList values = new ArrayList<>(); for (int i = 0; i < count; i++) { float val = (float) (Math.random() * count) + 15; - yVals.add(new BarEntry(i, (int) val)); + values.add(new BarEntry(i, (int) val)); } - BarDataSet set = new BarDataSet(yVals, "Data Set"); + BarDataSet set = new BarDataSet(values, "Data Set"); set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setDrawValues(false); BarData data = new BarData(set); - mChart.setData(data); - mChart.invalidate(); - mChart.animateY(800); + chart.setData(data); + chart.invalidate(); + chart.animateY(800); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java")); + startActivity(i); + break; + } + } + + return true; } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 9951060177..c98abb68aa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -1,7 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -9,11 +14,9 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; -import android.widget.Toast; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -34,8 +37,8 @@ public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private BarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -44,50 +47,52 @@ protected void onCreate(Bundle savedInstanceState) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_barchart); + setTitle("StackedBarActivity"); + tvX = findViewById(R.id.tvXMax); tvY = findViewById(R.id.tvYMax); - mSeekBarX = findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarX = findViewById(R.id.seekBar1); + seekBarX.setOnSeekBarChangeListener(this); - mSeekBarY = findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); + seekBarY = findViewById(R.id.seekBar2); + seekBarY.setOnSeekBarChangeListener(this); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); - mChart.getDescription().setEnabled(false); + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(40); + chart.setMaxVisibleValueCount(40); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(false); - mChart.setHighlightFullBarEnabled(false); + chart.setDrawValueAboveBar(false); + chart.setHighlightFullBarEnabled(false); // change the position of the y-labels - YAxis leftAxis = mChart.getAxisLeft(); + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); + chart.getAxisRight().setEnabled(false); - XAxis xLabels = mChart.getXAxis(); + XAxis xLabels = chart.getXAxis(); xLabels.setPosition(XAxisPosition.TOP); - // mChart.setDrawXLabels(false); - // mChart.setDrawYLabels(false); + // chart.setDrawXLabels(false); + // chart.setDrawYLabels(false); // setting data - mSeekBarX.setProgress(12); - mSeekBarY.setProgress(100); + seekBarX.setProgress(12); + seekBarY.setProgress(100); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -96,7 +101,55 @@ protected void onCreate(Bundle savedInstanceState) { l.setFormToTextSpace(4f); l.setXEntrySpace(6f); - // mChart.setDrawLegend(false); + // chart.setDrawLegend(false); + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); + + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < seekBarX.getProgress(); i++) { + float mul = (seekBarY.getProgress() + 1); + float val1 = (float) (Math.random() * mul) + mul / 3; + float val2 = (float) (Math.random() * mul) + mul / 3; + float val3 = (float) (Math.random() * mul) + mul / 3; + + values.add(new BarEntry( + i, + new float[]{val1, val2, val3}, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "Statistics Vienna 2014"); + set1.setDrawIcons(false); + set1.setColors(getColors()); + set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueFormatter(new MyValueFormatter()); + data.setValueTextColor(Color.WHITE); + + chart.setData(data); + } + + chart.setFitBars(true); + chart.invalidate(); } @Override @@ -109,8 +162,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -119,11 +178,11 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -132,55 +191,56 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawIcons(!set.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if (mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if (chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet) set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT).show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -188,64 +248,15 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val1 = (float) (Math.random() * mult) + mult / 3; - float val2 = (float) (Math.random() * mult) + mult / 3; - float val3 = (float) (Math.random() * mult) + mult / 3; - - yVals1.add(new BarEntry( - i, - new float[]{val1, val2, val3}, - getResources().getDrawable(R.drawable.star))); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet) mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setDrawIcons(false); - set1.setColors(getColors()); - set1.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(dataSets); - data.setValueFormatter(new MyValueFormatter()); - data.setValueTextColor(Color.WHITE); - - mChart.setData(data); - } - - mChart.setFitBars(true); - mChart.invalidate(); + public void saveToGallery() { + saveToGallery(chart, "StackedBarActivity"); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStartTrackingTouch(SeekBar seekBar) {} @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } + public void onStopTrackingTouch(SeekBar seekBar) {} @Override public void onValueSelected(Entry e, Highlight h) { @@ -259,21 +270,14 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } + public void onNothingSelected() {} private int[] getColors() { - int stacksize = 3; - // have as many colors as stack-values per entry - int[] colors = new int[stacksize]; + int[] colors = new int[3]; - for (int i = 0; i < colors.length; i++) { - colors[i] = ColorTemplate.MATERIAL_COLORS[i]; - } + System.arraycopy(ColorTemplate.MATERIAL_COLORS, 0, colors, 0, 3); return colors; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index c1d64a106b..b9df66981a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -1,18 +1,21 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.Color; +import android.net.Uri; import android.os.Bundle; +import androidx.core.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; -import android.widget.Toast; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; @@ -35,7 +38,7 @@ public class StackedBarActivityNegative extends DemoBase implements OnChartValueSelectedListener { - private HorizontalBarChart mChart; + private HorizontalBarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { @@ -44,30 +47,30 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_age_distribution); - setTitle("Age Distribution Austria"); + setTitle("StackedBarActivityNegative"); - mChart = findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - mChart.setDrawGridBackground(false); - mChart.getDescription().setEnabled(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + chart.setDrawGridBackground(false); + chart.getDescription().setEnabled(false); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawBarShadow(false); - mChart.setDrawValueAboveBar(true); - mChart.setHighlightFullBarEnabled(false); - - mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setAxisMaximum(25f); - mChart.getAxisRight().setAxisMinimum(-25f); - mChart.getAxisRight().setDrawGridLines(false); - mChart.getAxisRight().setDrawZeroLine(true); - mChart.getAxisRight().setLabelCount(7, false); - mChart.getAxisRight().setValueFormatter(new CustomFormatter()); - mChart.getAxisRight().setTextSize(9f); - - XAxis xAxis = mChart.getXAxis(); + chart.setPinchZoom(false); + + chart.setDrawBarShadow(false); + chart.setDrawValueAboveBar(true); + chart.setHighlightFullBarEnabled(false); + + chart.getAxisLeft().setEnabled(false); + chart.getAxisRight().setAxisMaximum(25f); + chart.getAxisRight().setAxisMinimum(-25f); + chart.getAxisRight().setDrawGridLines(false); + chart.getAxisRight().setDrawZeroLine(true); + chart.getAxisRight().setLabelCount(7, false); + chart.getAxisRight().setValueFormatter(new CustomFormatter()); + chart.getAxisRight().setTextSize(9f); + + XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(false); @@ -87,7 +90,7 @@ public String getFormattedValue(float value, AxisBase axis) { } }); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -97,36 +100,34 @@ public String getFormattedValue(float value, AxisBase axis) { l.setXEntrySpace(6f); // IMPORTANT: When using negative values in stacked bars, always make sure the negative values are in the array first - ArrayList yValues = new ArrayList(); - yValues.add(new BarEntry(5, new float[]{ -10, 10 })); - yValues.add(new BarEntry(15, new float[]{ -12, 13 })); - yValues.add(new BarEntry(25, new float[]{ -15, 15 })); - yValues.add(new BarEntry(35, new float[]{ -17, 17 })); - yValues.add(new BarEntry(45, new float[]{ -19, 20 })); - yValues.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); - yValues.add(new BarEntry(55, new float[]{ -19, 19 })); - yValues.add(new BarEntry(65, new float[]{ -16, 16 })); - yValues.add(new BarEntry(75, new float[]{ -13, 14 })); - yValues.add(new BarEntry(85, new float[]{ -10, 11 })); - yValues.add(new BarEntry(95, new float[]{ -5, 6 })); - yValues.add(new BarEntry(105, new float[]{ -1, 2 })); - - BarDataSet set = new BarDataSet(yValues, "Age Distribution"); + ArrayList values = new ArrayList<>(); + values.add(new BarEntry(5, new float[]{ -10, 10 })); + values.add(new BarEntry(15, new float[]{ -12, 13 })); + values.add(new BarEntry(25, new float[]{ -15, 15 })); + values.add(new BarEntry(35, new float[]{ -17, 17 })); + values.add(new BarEntry(45, new float[]{ -19, 20 })); + values.add(new BarEntry(45, new float[]{ -19, 20 }, getResources().getDrawable(R.drawable.star))); + values.add(new BarEntry(55, new float[]{ -19, 19 })); + values.add(new BarEntry(65, new float[]{ -16, 16 })); + values.add(new BarEntry(75, new float[]{ -13, 14 })); + values.add(new BarEntry(85, new float[]{ -10, 11 })); + values.add(new BarEntry(95, new float[]{ -5, 6 })); + values.add(new BarEntry(105, new float[]{ -1, 2 })); + + BarDataSet set = new BarDataSet(values, "Age Distribution"); set.setDrawIcons(false); set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); - set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); + set.setColors(Color.rgb(67,67,72), Color.rgb(124,181,236)); set.setStackLabels(new String[]{ "Men", "Women" }); - String []xLabels = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; - BarData data = new BarData(set); data.setBarWidth(8.5f); - mChart.setData(data); - mChart.invalidate(); + chart.setData(data); + chart.invalidate(); } @Override @@ -139,8 +140,14 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -149,11 +156,11 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawValues(!set.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { @@ -162,57 +169,56 @@ public boolean onOptionsItemSelected(MenuItem item) { set.setDrawIcons(!set.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(3000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(3000); break; } case R.id.animateXY: { - mChart.animateXY(3000, 3000); + chart.animateXY(3000, 3000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -220,8 +226,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void onValueSelected(Entry e, Highlight h) { + public void saveToGallery() { + saveToGallery(chart, "StackedBarActivityNegative"); + } + @Override + public void onValueSelected(Entry e, Highlight h) { BarEntry entry = (BarEntry) e; Log.i("VAL SELECTED", "Value: " + Math.abs(entry.getYVals()[h.getStackIndex()])); @@ -229,16 +239,14 @@ public void onValueSelected(Entry e, Highlight h) { @Override public void onNothingSelected() { - // TODO Auto-generated method stub Log.i("NOTING SELECTED", ""); } - private class CustomFormatter implements IValueFormatter, IAxisValueFormatter - { + private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { private DecimalFormat mFormat; - public CustomFormatter() { + CustomFormatter() { mFormat = new DecimalFormat("###"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index b8bc1a41c2..a27cff89c9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -10,7 +10,7 @@ public class DayAxisValueFormatter implements IAxisValueFormatter { - protected String[] mMonths = new String[]{ + private final String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index c66e5d4569..e9662aca78 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -8,7 +8,10 @@ /** * Created by Philipp Jahoda on 14/09/15. + * + * @deprecated The {@link MyAxisValueFormatter} does exactly the same thing and is more functional. */ +@Deprecated public class MyCustomXAxisValueFormatter implements IAxisValueFormatter { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index e4b94c331f..2ca87b2f0f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -7,18 +7,19 @@ /** * Created by Philipp Jahoda on 12/09/15. */ +@SuppressWarnings("unused") public class MyFillFormatter implements IFillFormatter { - private float mFillPos = 0f; + private float fillPos; - public MyFillFormatter(float fillpos) { - this.mFillPos = fillpos; + public MyFillFormatter(float fillPos) { + this.fillPos = fillPos; } @Override public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { // your logic could be here - return mFillPos; + return fillPos; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index ef20bda3b7..25d3195cb5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -14,9 +15,10 @@ /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class MyMarkerView extends MarkerView { private TextView tvContent; @@ -27,7 +29,7 @@ public MyMarkerView(Context context, int layoutResource) { tvContent = findViewById(R.id.tvContent); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { @@ -36,10 +38,10 @@ public void refreshContent(Entry e, Highlight highlight) { CandleEntry ce = (CandleEntry) e; - tvContent.setText("" + Utils.formatNumber(ce.getHigh(), 0, true)); + tvContent.setText(Utils.formatNumber(ce.getHigh(), 0, true)); } else { - tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(e.getY(), 0, true)); } super.refreshContent(e, highlight); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 12b473f7d0..6fb2161577 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -1,25 +1,25 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.widget.TextView; import com.github.mikephil.charting.components.MarkerView; -import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; import java.text.DecimalFormat; /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class RadarMarkerView extends MarkerView { private TextView tvContent; @@ -32,11 +32,11 @@ public RadarMarkerView(Context context, int layoutResource) { tvContent.setTypeface(Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf")); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(format.format(e.getY()) + " %"); + tvContent.setText(String.format("%s %%", format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index 7becc88c90..7a8584f8ef 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -8,6 +8,7 @@ * Demo class that encapsulates data stored in realm.io database. * This class represents data suitable for all chart-types. */ +@SuppressWarnings("unused") public class RealmDemoData extends RealmObject { private float yValue; @@ -26,15 +27,7 @@ public class RealmDemoData extends RealmObject { */ private String label; - // ofc there could me more fields here... - - public RealmDemoData() { - - } - - public RealmDemoData(float yValue) { - this.yValue = yValue; - } + public RealmDemoData() {} public RealmDemoData(float xValue, float yValue) { this.xValue = xValue; @@ -44,12 +37,12 @@ public RealmDemoData(float xValue, float yValue) { /** * Constructor for stacked bars. * - * @param xValue - * @param stackValues + * @param xValue x position for bars + * @param stackValues values of bars in the stack */ public RealmDemoData(float xValue, float[] stackValues) { this.xValue = xValue; - this.stackValues = new RealmList(); + this.stackValues = new RealmList<>(); for (float val : stackValues) { this.stackValues.add(new RealmFloat(val)); @@ -59,11 +52,11 @@ public RealmDemoData(float xValue, float[] stackValues) { /** * Constructor for candles. * - * @param xValue - * @param high - * @param low - * @param open - * @param close + * @param xValue x position of candle + * @param high high value for candle + * @param low low value for candle + * @param open open value for candle + * @param close close value for candle */ public RealmDemoData(float xValue, float high, float low, float open, float close) { this.yValue = (high + low) / 2f; @@ -77,9 +70,9 @@ public RealmDemoData(float xValue, float high, float low, float open, float clos /** * Constructor for bubbles. * - * @param xValue - * @param yValue - * @param bubbleSize + * @param xValue x position of bubble + * @param yValue y position of bubble + * @param bubbleSize size of bubble */ public RealmDemoData(float xValue, float yValue, float bubbleSize) { this.xValue = xValue; @@ -90,27 +83,27 @@ public RealmDemoData(float xValue, float yValue, float bubbleSize) { /** * Constructor for pie chart. * - * @param yValue - * @param label + * @param yValue size of pie slice + * @param label label for pie slice */ public RealmDemoData(float yValue, String label) { this.yValue = yValue; this.label = label; } - public float getyValue() { + public float getYValue() { return yValue; } - public void setyValue(float yValue) { + public void setYValue(float yValue) { this.yValue = yValue; } - public float getxValue() { + public float getXValue() { return xValue; } - public void setxValue(float xValue) { + public void setXValue(float xValue) { this.xValue = xValue; } @@ -177,4 +170,4 @@ public String getLabel() { public void setLabel(String label) { this.label = label; } -} \ No newline at end of file +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java index 15b027b3ff..a8310dc9b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -5,6 +5,7 @@ /** * Created by Philipp Jahoda on 09/11/15. */ +@SuppressWarnings("unused") public class RealmFloat extends RealmObject { private float floatValue; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 487705bb7d..554ef2fe27 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -14,9 +15,11 @@ /** * Custom implementation of the MarkerView. - * + * * @author Philipp Jahoda */ +@SuppressWarnings("unused") +@SuppressLint("ViewConstructor") public class StackedBarsMarkerView extends MarkerView { private TextView tvContent; @@ -27,7 +30,7 @@ public StackedBarsMarkerView(Context context, int layoutResource) { tvContent = findViewById(R.id.tvContent); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { @@ -39,13 +42,13 @@ public void refreshContent(Entry e, Highlight highlight) { if(be.getYVals() != null) { // draw the stack value - tvContent.setText("" + Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); + tvContent.setText(Utils.formatNumber(be.getYVals()[highlight.getStackIndex()], 0, true)); } else { - tvContent.setText("" + Utils.formatNumber(be.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(be.getY(), 0, true)); } } else { - tvContent.setText("" + Utils.formatNumber(e.getY(), 0, true)); + tvContent.setText(Utils.formatNumber(e.getY(), 0, true)); } super.refreshContent(e, highlight); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 0475bdd038..f85f538988 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; +import android.annotation.SuppressLint; import android.content.Context; import android.widget.TextView; @@ -18,6 +19,7 @@ * * @author Philipp Jahoda */ +@SuppressLint("ViewConstructor") public class XYMarkerView extends MarkerView { private TextView tvContent; @@ -33,12 +35,12 @@ public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { format = new DecimalFormat("###.0"); } - // callbacks everytime the MarkerView is redrawn, can be used to update the + // runs every time the MarkerView is redrawn, can be used to update the // content (user-interface) @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText("x: " + xAxisValueFormatter.getFormattedValue(e.getX(), null) + ", y: " + format.format(e.getY())); + tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX(), null), format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index 34d76c25eb..7122e0d80c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -6,16 +6,16 @@ /** * Created by Philipp Jahoda on 14/09/15. */ +@SuppressWarnings("unused") public class YearXAxisFormatter implements IAxisValueFormatter { - protected String[] mMonths = new String[]{ + private final String[] mMonths = new String[]{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; public YearXAxisFormatter() { - // maybe do something here or provide parameters in constructor - + // take parameters to change behavior of formatter } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 655fc6bb25..4bcc543722 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; @@ -21,48 +22,49 @@ public class BarChartFrag extends SimpleFragment implements OnChartGestureListener { + @NonNull public static Fragment newInstance() { return new BarChartFrag(); } - private BarChart mChart; - + private BarChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_bar, container, false); - + // create a new chart object - mChart = new BarChart(getActivity()); - mChart.getDescription().setEnabled(false); - mChart.setOnChartGestureListener(this); - + chart = new BarChart(getActivity()); + chart.getDescription().setEnabled(false); + chart.setOnChartGestureListener(this); + MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); - - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - mChart.setData(generateBarData(1, 20000, 12)); - - Legend l = mChart.getLegend(); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); + + chart.setDrawGridBackground(false); + chart.setDrawBarShadow(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + chart.setData(generateBarData(1, 20000, 12)); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - - // programatically add the chart + + // programmatically add the chart FrameLayout parent = v.findViewById(R.id.parentLayout); - parent.addView(mChart); - + parent.addView(chart); + return v; } @@ -74,12 +76,12 @@ public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture @Override public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "END"); - mChart.highlightValues(null); + chart.highlightValues(null); } @Override public void onChartLongPressed(MotionEvent me) { - Log.i("LongPress", "Chart longpressed."); + Log.i("LongPress", "Chart long pressed."); } @Override @@ -94,9 +96,9 @@ public void onChartSingleTapped(MotionEvent me) { @Override public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) { - Log.i("Fling", "Chart flinged. VeloX: " + velocityX + ", VeloY: " + velocityY); + Log.i("Fling", "Chart fling. VelocityX: " + velocityX + ", VelocityY: " + velocityY); } - + @Override public void onChartScale(MotionEvent me, float scaleX, float scaleY) { Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index b960e9ae0c..9edee8bdfb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,38 +16,40 @@ public class ComplexityFragment extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new ComplexityFragment(); } - private LineChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private LineChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - - mChart = v.findViewById(R.id.lineChart1); - - mChart.getDescription().setEnabled(false); - - mChart.setDrawGridBackground(false); - - mChart.setData(getComplexity()); - mChart.animateX(3000); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - Legend l = mChart.getLegend(); + + chart = v.findViewById(R.id.lineChart1); + + chart.getDescription().setEnabled(false); + + chart.setDrawGridBackground(false); + + chart.setData(getComplexity()); + chart.animateX(3000); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); - - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index 946532ac40..5de9a46ea3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -2,7 +2,8 @@ import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; @@ -12,44 +13,45 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.xxmassdeveloper.mpchartexample.R; public class PieChartFrag extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new PieChartFrag(); } - private PieChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private PieChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_pie, container, false); - - mChart = v.findViewById(R.id.pieChart1); - mChart.getDescription().setEnabled(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf"); - - mChart.setCenterTextTypeface(tf); - mChart.setCenterText(generateCenterText()); - mChart.setCenterTextSize(10f); - mChart.setCenterTextTypeface(tf); - + + chart = v.findViewById(R.id.pieChart1); + chart.getDescription().setEnabled(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + chart.setCenterTextTypeface(tf); + chart.setCenterText(generateCenterText()); + chart.setCenterTextSize(10f); + chart.setCenterTextTypeface(tf); + // radius of the center hole in percent of maximum radius - mChart.setHoleRadius(45f); - mChart.setTransparentCircleRadius(50f); - - Legend l = mChart.getLegend(); + chart.setHoleRadius(45f); + chart.setTransparentCircleRadius(50f); + + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT); l.setOrientation(Legend.LegendOrientation.VERTICAL); l.setDrawInside(false); - - mChart.setData(generatePieData()); - + + chart.setData(generatePieData()); + return v; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index b8a3f0f324..d5d292bf0b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -2,7 +2,8 @@ import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -18,49 +19,51 @@ public class ScatterChartFrag extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new ScatterChartFrag(); } - private ScatterChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private ScatterChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_scatter, container, false); - - mChart = v.findViewById(R.id.scatterChart1); - mChart.getDescription().setEnabled(false); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - + + chart = v.findViewById(R.id.scatterChart1); + chart.getDescription().setEnabled(false); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); - mv.setChartView(mChart); // For bounds control - mChart.setMarker(mv); + mv.setChartView(chart); // For bounds control + chart.setMarker(mv); + + chart.setDrawGridBackground(false); + chart.setData(generateScatterData(6, 10000, 200)); - mChart.setDrawGridBackground(false); - mChart.setData(generateScatterData(6, 10000, 200)); - - XAxis xAxis = mChart.getXAxis(); + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(true); xAxis.setPosition(XAxisPosition.BOTTOM); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); - - YAxis rightAxis = mChart.getAxisRight(); + + YAxis rightAxis = chart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setDrawGridLines(false); - - Legend l = mChart.getLegend(); + + Legend l = chart.getLegend(); l.setWordWrapEnabled(true); l.setTypeface(tf); l.setFormSize(14f); l.setTextSize(9f); - + // increase the space between legend & bottom and legend & content - l.setYOffset(13f); - mChart.setExtraBottomOffset(16f); - + l.setYOffset(13f); + chart.setExtraBottomOffset(16f); + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java index ee64ffdfce..32b78142b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java @@ -4,11 +4,15 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; +import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.support.v4.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; +import android.view.Menu; +import android.view.MenuItem; import android.view.WindowManager; import com.xxmassdeveloper.mpchartexample.R; @@ -16,7 +20,7 @@ /** * Demonstrates how to keep your charts straight forward, simple and beautiful with the MPAndroidChart library. - * + * * @author Philipp Jahoda */ public class SimpleChartDemo extends DemoBase { @@ -26,21 +30,22 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_awesomedesign); + setTitle("SimpleChartDemo"); + ViewPager pager = findViewById(R.id.pager); pager.setOffscreenPageLimit(3); - + PageAdapter a = new PageAdapter(getSupportFragmentManager()); pager.setAdapter(a); - - + + AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle("This is a ViewPager."); b.setMessage("Swipe left and right for more awesome design examples!"); b.setPositiveButton("OK", new OnClickListener() { - + @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); @@ -48,17 +53,17 @@ public void onClick(DialogInterface dialog, int which) { }); b.show(); } - + private class PageAdapter extends FragmentPagerAdapter { - public PageAdapter(FragmentManager fm) { - super(fm); + PageAdapter(FragmentManager fm) { + super(fm); } @Override - public Fragment getItem(int pos) { + public Fragment getItem(int pos) { Fragment f = null; - + switch(pos) { case 0: f = SineCosineFragment.newInstance(); @@ -83,6 +88,30 @@ public Fragment getItem(int pos) { @Override public int getCount() { return 5; - } + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.only_github, menu); + return true; } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java")); + startActivity(i); + break; + } + } + + return true; + } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 22b35e4963..5caa290178 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -1,9 +1,11 @@ package com.xxmassdeveloper.mpchartexample.fragments; +import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -28,58 +30,64 @@ import java.util.ArrayList; +@SuppressWarnings("SameParameterValue") public abstract class SimpleFragment extends Fragment { - + private Typeface tf; - + protected Context context; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.context = context; + } + public SimpleFragment() { - + } - + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Regular.ttf"); + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf"); return super.onCreateView(inflater, container, savedInstanceState); } protected BarData generateBarData(int dataSets, float range, int count) { - - ArrayList sets = new ArrayList(); - + + ArrayList sets = new ArrayList<>(); + for(int i = 0; i < dataSets; i++) { - - ArrayList entries = new ArrayList(); - -// entries = FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "stacked_bars.txt"); - - for(int j = 0; j < count; j++) { + + ArrayList entries = new ArrayList<>(); + + for(int j = 0; j < count; j++) { entries.add(new BarEntry(j, (float) (Math.random() * range) + range / 4)); } - + BarDataSet ds = new BarDataSet(entries, getLabel(i)); ds.setColors(ColorTemplate.VORDIPLOM_COLORS); sets.add(ds); } - + BarData d = new BarData(sets); d.setValueTypeface(tf); return d; } - + protected ScatterData generateScatterData(int dataSets, float range, int count) { - - ArrayList sets = new ArrayList(); - + + ArrayList sets = new ArrayList<>(); + ScatterChart.ScatterShape[] shapes = ScatterChart.ScatterShape.getAllDefaultShapes(); - + for(int i = 0; i < dataSets; i++) { - - ArrayList entries = new ArrayList(); - - for(int j = 0; j < count; j++) { + + ArrayList entries = new ArrayList<>(); + + for(int j = 0; j < count; j++) { entries.add(new Entry(j, (float) (Math.random() * range) + range / 4)); } - + ScatterDataSet ds = new ScatterDataSet(entries, getLabel(i)); ds.setScatterShapeSize(12f); ds.setScatterShape(shapes[i % shapes.length]); @@ -87,82 +95,81 @@ protected ScatterData generateScatterData(int dataSets, float range, int count) ds.setScatterShapeSize(9f); sets.add(ds); } - + ScatterData d = new ScatterData(sets); d.setValueTypeface(tf); return d; } - + /** * generates less data (1 DataSet, 4 values) - * @return + * @return PieData */ protected PieData generatePieData() { - + int count = 4; - - ArrayList entries1 = new ArrayList(); - + + ArrayList entries1 = new ArrayList<>(); + for(int i = 0; i < count; i++) { entries1.add(new PieEntry((float) ((Math.random() * 60) + 40), "Quarter " + (i+1))); } - + PieDataSet ds1 = new PieDataSet(entries1, "Quarterly Revenues 2015"); ds1.setColors(ColorTemplate.VORDIPLOM_COLORS); ds1.setSliceSpace(2f); ds1.setValueTextColor(Color.WHITE); ds1.setValueTextSize(12f); - + PieData d = new PieData(ds1); d.setValueTypeface(tf); return d; } - + protected LineData generateLineData() { - - ArrayList sets = new ArrayList(); - - LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "sine.txt"), "Sine function"); - LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "cosine.txt"), "Cosine function"); - + + ArrayList sets = new ArrayList<>(); + LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "sine.txt"), "Sine function"); + LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "cosine.txt"), "Cosine function"); + ds1.setLineWidth(2f); ds2.setLineWidth(2f); - + ds1.setDrawCircles(false); ds2.setDrawCircles(false); - + ds1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setColor(ColorTemplate.VORDIPLOM_COLORS[1]); - - // load DataSets from textfiles in assets folders + + // load DataSets from files in assets folder sets.add(ds1); sets.add(ds2); - + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } - + protected LineData getComplexity() { - - ArrayList sets = new ArrayList(); - - LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "n.txt"), "O(n)"); - LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "nlogn.txt"), "O(nlogn)"); - LineDataSet ds3 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "square.txt"), "O(n\u00B2)"); - LineDataSet ds4 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "three.txt"), "O(n\u00B3)"); - + + ArrayList sets = new ArrayList<>(); + + LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "n.txt"), "O(n)"); + LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "nlogn.txt"), "O(nlogn)"); + LineDataSet ds3 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "square.txt"), "O(n\u00B2)"); + LineDataSet ds4 = new LineDataSet(FileUtils.loadEntriesFromAssets(context.getAssets(), "three.txt"), "O(n\u00B3)"); + ds1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setColor(ColorTemplate.VORDIPLOM_COLORS[1]); ds3.setColor(ColorTemplate.VORDIPLOM_COLORS[2]); ds4.setColor(ColorTemplate.VORDIPLOM_COLORS[3]); - + ds1.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); ds2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[1]); ds3.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[2]); ds4.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[3]); - + ds1.setLineWidth(2.5f); ds1.setCircleRadius(3f); ds2.setLineWidth(2.5f); @@ -171,22 +178,21 @@ protected LineData getComplexity() { ds3.setCircleRadius(3f); ds4.setLineWidth(2.5f); ds4.setCircleRadius(3f); - - - // load DataSets from textfiles in assets folders - sets.add(ds1); + + + // load DataSets from files in assets folder + sets.add(ds1); sets.add(ds2); sets.add(ds3); sets.add(ds4); - + LineData d = new LineData(sets); d.setValueTypeface(tf); return d; } - - private String[] mLabels = new String[] { "Company A", "Company B", "Company C", "Company D", "Company E", "Company F" }; -// private String[] mXVals = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; - + + private final String[] mLabels = new String[] { "Company A", "Company B", "Company C", "Company D", "Company E", "Company F" }; + private String getLabel(int i) { return mLabels[i]; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index 7e425172fb..0581529308 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -1,7 +1,8 @@ package com.xxmassdeveloper.mpchartexample.fragments; import android.graphics.Typeface; import android.os.Bundle; -import android.support.v4.app.Fragment; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -15,40 +16,42 @@ public class SineCosineFragment extends SimpleFragment { + @NonNull public static Fragment newInstance() { return new SineCosineFragment(); } - private LineChart mChart; - + @SuppressWarnings("FieldCanBeLocal") + private LineChart chart; + @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.frag_simple_line, container, false); - - mChart = v.findViewById(R.id.lineChart1); - - mChart.getDescription().setEnabled(false); - - mChart.setDrawGridBackground(false); - - mChart.setData(generateLineData()); - mChart.animateX(3000); - - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); - - Legend l = mChart.getLegend(); + + chart = v.findViewById(R.id.lineChart1); + + chart.getDescription().setEnabled(false); + + chart.setDrawGridBackground(false); + + chart.setData(generateLineData()); + chart.animateX(3000); + + Typeface tf = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); + + Legend l = chart.getLegend(); l.setTypeface(tf); - - YAxis leftAxis = mChart.getAxisLeft(); + + YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tf); leftAxis.setAxisMaximum(1.2f); leftAxis.setAxisMinimum(-1.2f); - - mChart.getAxisRight().setEnabled(false); - - XAxis xAxis = mChart.getXAxis(); + + chart.getAxisRight().setEnabled(false); + + XAxis xAxis = chart.getXAxis(); xAxis.setEnabled(false); - + return v; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index c09297a391..b49daa3be4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -1,5 +1,6 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; @@ -14,9 +15,9 @@ import com.xxmassdeveloper.mpchartexample.R; public class BarChartItem extends ChartItem { - + private Typeface mTf; - + public BarChartItem(ChartData cd, Context c) { super(cd); @@ -28,10 +29,11 @@ public int getItemType() { return TYPE_BARCHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -57,13 +59,13 @@ public View getView(int position, View convertView, Context c) { xAxis.setTypeface(mTf); xAxis.setDrawGridLines(false); xAxis.setDrawAxisLine(true); - + YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(20f); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - + YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); @@ -71,18 +73,18 @@ public View getView(int position, View convertView, Context c) { rightAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) mChartData.setValueTypeface(mTf); - + // set data holder.chart.setData((BarData) mChartData); holder.chart.setFitBars(true); - + // do not forget to refresh the chart // holder.chart.invalidate(); holder.chart.animateY(700); return convertView; } - + private static class ViewHolder { BarChart chart; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java index 0e6182165c..2a8ed0561d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java @@ -6,23 +6,24 @@ import com.github.mikephil.charting.data.ChartData; /** - * baseclass of the chart-listview items + * Base class of the Chart ListView items * @author philipp * */ +@SuppressWarnings("unused") public abstract class ChartItem { - - protected static final int TYPE_BARCHART = 0; - protected static final int TYPE_LINECHART = 1; - protected static final int TYPE_PIECHART = 2; - - protected ChartData mChartData; - - public ChartItem(ChartData cd) { - this.mChartData = cd; + + static final int TYPE_BARCHART = 0; + static final int TYPE_LINECHART = 1; + static final int TYPE_PIECHART = 2; + + ChartData mChartData; + + ChartItem(ChartData cd) { + this.mChartData = cd; } - + public abstract int getItemType(); - + public abstract View getView(int position, View convertView, Context c); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 107930af2a..e4c11869ac 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; import android.view.LayoutInflater; @@ -29,10 +30,11 @@ public int getItemType() { return TYPE_LINECHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { @@ -63,7 +65,7 @@ public View getView(int position, View convertView, Context c) { leftAxis.setTypeface(mTf); leftAxis.setLabelCount(5, false); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) - + YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(5, false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 5503018792..0c5e56bd3b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.listviewitems; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; @@ -12,7 +13,6 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.formatter.PercentFormatter; @@ -36,10 +36,11 @@ public int getItemType() { return TYPE_PIECHART; } + @SuppressLint("InflateParams") @Override public View getView(int position, View convertView, Context c) { - ViewHolder holder = null; + ViewHolder holder; if (convertView == null) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java index 97bb230ec9..41f05afc10 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java @@ -8,6 +8,13 @@ public class ContentItem { String name; String desc; boolean isNew = false; + boolean isSection = false; + + public ContentItem(String n) { + name = n; + desc = ""; + isSection = true; + } public ContentItem(String n, String d) { name = n; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index 59b73b1ad7..ea0d1aa008 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -1,45 +1,55 @@ package com.xxmassdeveloper.mpchartexample.notimportant; +import android.Manifest; +import android.content.pm.PackageManager; import android.graphics.Typeface; import android.os.Bundle; -import android.renderscript.Type; -import android.support.annotation.Nullable; -import android.support.v4.app.FragmentActivity; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import com.google.android.material.snackbar.Snackbar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import android.view.View; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.Chart; import com.xxmassdeveloper.mpchartexample.R; /** - * Baseclass of all Activities of the Demo Application. - * + * Base class of all Activities of the Demo Application. + * * @author Philipp Jahoda */ -public abstract class DemoBase extends FragmentActivity { +public abstract class DemoBase extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback { - protected String[] mMonths = new String[] { + protected final String[] months = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" }; - protected String[] mParties = new String[] { + protected final String[] parties = new String[] { "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H", "Party I", "Party J", "Party K", "Party L", "Party M", "Party N", "Party O", "Party P", "Party Q", "Party R", "Party S", "Party T", "Party U", "Party V", "Party W", "Party X", "Party Y", "Party Z" }; - protected Typeface mTfRegular; - protected Typeface mTfLight; + private static final int PERMISSION_STORAGE = 0; + + protected Typeface tfRegular; + protected Typeface tfLight; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mTfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - mTfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); + tfRegular = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + tfLight = Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf"); } - protected float getRandom(float range, float startsfrom) { - return (float) (Math.random() * range) + startsfrom; + protected float getRandom(float range, float start) { + return (float) (Math.random() * range) + start; } @Override @@ -47,4 +57,43 @@ public void onBackPressed() { super.onBackPressed(); overridePendingTransition(R.anim.move_left_in_activity, R.anim.move_right_out_activity); } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == PERMISSION_STORAGE) { + if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + } + } + } + + protected void requestStoragePermission(View view) { + if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + Snackbar.make(view, "Write permission is required to save image to gallery", Snackbar.LENGTH_INDEFINITE) + .setAction(android.R.string.ok, new View.OnClickListener() { + @Override + public void onClick(View v) { + ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE); + } + }).show(); + } else { + Toast.makeText(getApplicationContext(), "Permission Required!", Toast.LENGTH_SHORT) + .show(); + ActivityCompat.requestPermissions(DemoBase.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSION_STORAGE); + } + } + + protected void saveToGallery(Chart chart, String name) { + if (chart.saveToGallery(name + "_" + System.currentTimeMillis(), 70)) + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + } + + abstract public void saveToGallery(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index d994f87c96..67749e742f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample.notimportant; -import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -46,11 +45,12 @@ import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; -import com.xxmassdeveloper.mpchartexample.realm.RealmMainActivity; import java.util.ArrayList; -public class MainActivity extends Activity implements OnItemClickListener { +import androidx.appcompat.app.AppCompatActivity; + +public class MainActivity extends AppCompatActivity implements OnItemClickListener { @Override protected void onCreate(Bundle savedInstanceState) { @@ -64,88 +64,63 @@ protected void onCreate(Bundle savedInstanceState) { // initialize the utilities Utils.init(this); - ArrayList objects = new ArrayList(); - - objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); - objects.add(new ContentItem("Line Chart (Dual YAxis)", - "Demonstration of the linechart with dual y-axis.")); - objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); - objects.add(new ContentItem("Horizontal Bar Chart", - "A simple demonstration of the horizontal bar chart.")); - objects.add(new ContentItem("Combined Chart", - "Demonstrates how to create a combined chart (bar and line in this case).")); - objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); - objects.add(new ContentItem("Pie Chart with value lines", "A simple demonstration of the pie chart with polyline notes.")); - objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); - objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); - objects.add(new ContentItem("Stacked Bar Chart", - "A simple demonstration of a bar chart with stacked bars.")); - objects.add(new ContentItem("Stacked Bar Chart Negative", - "A simple demonstration of stacked bars with negative and positive values.")); - objects.add(new ContentItem("Another Bar Chart", - "Implementation of a BarChart that only shows values at the bottom.")); - objects.add(new ContentItem("Multiple Lines Chart", - "A line chart with multiple DataSet objects. One color per DataSet.")); - objects.add(new ContentItem("Multiple Bars Chart", - "A bar chart with multiple DataSet objects. One multiple colors per DataSet.")); - objects.add(new ContentItem( - "Charts in ViewPager Fragments", - "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the" + - " chart.")); - objects.add(new ContentItem( - "BarChart inside ListView", - "Demonstrates the usage of a BarChart inside a ListView item.")); - objects.add(new ContentItem( - "Multiple charts inside ListView", - "Demonstrates the usage of different chart types inside a ListView.")); - objects.add(new ContentItem( - "Inverted Line Chart", - "Demonstrates the feature of inverting the y-axis.")); - objects.add(new ContentItem( - "Candle Stick Chart", - "Demonstrates usage of the CandleStickChart.")); - objects.add(new ContentItem( - "Cubic Line Chart", - "Demonstrates cubic lines in a LineChart.")); - objects.add(new ContentItem( - "Radar Chart", - "Demonstrates the use of a spider-web like (net) chart.")); - objects.add(new ContentItem( - "Colored Line Chart", - "Shows a LineChart with different background and line color.")); - objects.add(new ContentItem( - "Realtime Chart", - "This chart is fed with new data in realtime. It also restrains the view on the x-axis.")); - objects.add(new ContentItem( - "Dynamical data adding", - "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); - objects.add(new ContentItem( - "Performance Line Chart", - "Renders up to 30.000 objects smoothly.")); - objects.add(new ContentItem( - "Sinus Bar Chart", - "A Bar Chart plotting the sinus function with 8.000 values.")); - objects.add(new ContentItem( - "Chart in ScrollView", - "This demonstrates how to use a chart inside a ScrollView.")); - objects.add(new ContentItem( - "BarChart positive / negative", - "This demonstrates how to create a BarChart with positive and negative values in different colors.")); - - ContentItem realm = new ContentItem( - "Realm.io Database", - "This demonstrates how to use this library with Realm.io mobile database."); - objects.add(realm); - objects.add(new ContentItem( - "Time Chart", - "Simple demonstration of a time-chart. This chart draws one line entry per hour originating from the current time in " + - "milliseconds.")); - objects.add(new ContentItem( - "Filled LineChart", - "This demonstrates how to fill an area between two LineDataSets.")); - objects.add(new ContentItem( - "Half PieChart", - "This demonstrates how to create a 180 degree PieChart.")); + ArrayList objects = new ArrayList<>(); + + //// + objects.add(0, new ContentItem("Line Charts")); + + objects.add(1, new ContentItem("Basic", "Simple line chart.")); + objects.add(2, new ContentItem("Multiple", "Show multiple data sets.")); + objects.add(3, new ContentItem("Dual Axis", "Line chart with dual y-axes.")); + objects.add(4, new ContentItem("Inverted Axis", "Inverted y-axis.")); + objects.add(5, new ContentItem("Cubic", "Line chart with a cubic line shape.")); + objects.add(6, new ContentItem("Colorful", "Colorful line chart.")); + objects.add(7, new ContentItem("Performance", "Render 30.000 data points smoothly.")); + objects.add(8, new ContentItem("Filled", "Colored area between two lines.")); + + //// + objects.add(9, new ContentItem("Bar Charts")); + + objects.add(10, new ContentItem("Basic", "Simple bar chart.")); + objects.add(11, new ContentItem("Basic 2", "Variation of the simple bar chart.")); + objects.add(12, new ContentItem("Multiple", "Show multiple data sets.")); + objects.add(13, new ContentItem("Horizontal", "Render bar chart horizontally.")); + objects.add(14, new ContentItem("Stacked", "Stacked bar chart.")); + objects.add(15, new ContentItem("Negative", "Positive and negative values with unique colors.")); + objects.add(16, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); + objects.add(17, new ContentItem("Sine", "Sine function in bar chart format.")); + + //// + objects.add(18, new ContentItem("Pie Charts")); + + objects.add(19, new ContentItem("Basic", "Simple pie chart.")); + objects.add(20, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); + objects.add(21, new ContentItem("Half Pie", "180° (half) pie chart.")); + + //// + objects.add(22, new ContentItem("Other Charts")); + + objects.add(23, new ContentItem("Combined Chart", "Bar and line chart together.")); + objects.add(24, new ContentItem("Scatter Plot", "Simple scatter plot.")); + objects.add(25, new ContentItem("Bubble Chart", "Simple bubble chart.")); + objects.add(26, new ContentItem("Candlestick", "Simple financial chart.")); + objects.add(27, new ContentItem("Radar Chart", "Simple web chart.")); + + //// + objects.add(28, new ContentItem("Scrolling Charts")); + + objects.add(29, new ContentItem("Multiple", "Various types of charts as fragments.")); + objects.add(30, new ContentItem("View Pager", "Swipe through different charts.")); + objects.add(31, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); + objects.add(32, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); + + //// + objects.add(33, new ContentItem("Even More Line Charts")); + + objects.add(34, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); + objects.add(35, new ContentItem("Realtime", "Add data points in realtime.")); + objects.add(36, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); + //objects.add(37, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -158,140 +133,109 @@ protected void onCreate(Bundle savedInstanceState) { @Override public void onItemClick(AdapterView av, View v, int pos, long arg3) { - Intent i; + Intent i = null; switch (pos) { - case 0: - i = new Intent(this, LineChartActivity1.class); - startActivity(i); - break; case 1: - i = new Intent(this, LineChartActivity2.class); - startActivity(i); + i = new Intent(this, LineChartActivity1.class); break; case 2: - i = new Intent(this, BarChartActivity.class); - startActivity(i); + i = new Intent(this, MultiLineChartActivity.class); break; case 3: - i = new Intent(this, HorizontalBarChartActivity.class); - startActivity(i); + i = new Intent(this, LineChartActivity2.class); break; case 4: - i = new Intent(this, CombinedChartActivity.class); - startActivity(i); + i = new Intent(this, InvertedLineChartActivity.class); break; case 5: - i = new Intent(this, PieChartActivity.class); - startActivity(i); + i = new Intent(this, CubicLineChartActivity.class); break; case 6: - i = new Intent(this, PiePolylineChartActivity.class); - startActivity(i); + i = new Intent(this, LineChartActivityColored.class); break; case 7: - i = new Intent(this, ScatterChartActivity.class); - startActivity(i); + i = new Intent(this, PerformanceLineChart.class); break; case 8: - i = new Intent(this, BubbleChartActivity.class); - startActivity(i); - break; - case 9: - i = new Intent(this, StackedBarActivity.class); - startActivity(i); + i = new Intent(this, FilledLineActivity.class); break; case 10: - i = new Intent(this, StackedBarActivityNegative.class); - startActivity(i); + i = new Intent(this, BarChartActivity.class); break; case 11: i = new Intent(this, AnotherBarActivity.class); - startActivity(i); break; case 12: - i = new Intent(this, MultiLineChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartActivityMultiDataset.class); break; case 13: - i = new Intent(this, BarChartActivityMultiDataset.class); - startActivity(i); + i = new Intent(this, HorizontalBarChartActivity.class); break; case 14: - i = new Intent(this, SimpleChartDemo.class); - startActivity(i); + i = new Intent(this, StackedBarActivity.class); break; case 15: - i = new Intent(this, ListViewBarChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartPositiveNegative.class); break; case 16: - i = new Intent(this, ListViewMultiChartActivity.class); - startActivity(i); + i = new Intent(this, StackedBarActivityNegative.class); break; case 17: - i = new Intent(this, InvertedLineChartActivity.class); - startActivity(i); - break; - case 18: - i = new Intent(this, CandleStickChartActivity.class); - startActivity(i); + i = new Intent(this, BarChartActivitySinus.class); break; case 19: - i = new Intent(this, CubicLineChartActivity.class); - startActivity(i); + i = new Intent(this, PieChartActivity.class); break; case 20: - i = new Intent(this, RadarChartActivity.class); - startActivity(i); + i = new Intent(this, PiePolylineChartActivity.class); break; case 21: - i = new Intent(this, LineChartActivityColored.class); - startActivity(i); - break; - case 22: - i = new Intent(this, RealtimeLineChartActivity.class); - startActivity(i); + i = new Intent(this, HalfPieChartActivity.class); break; case 23: - i = new Intent(this, DynamicalAddingActivity.class); - startActivity(i); + i = new Intent(this, CombinedChartActivity.class); break; case 24: - i = new Intent(this, PerformanceLineChart.class); - startActivity(i); + i = new Intent(this, ScatterChartActivity.class); break; case 25: - i = new Intent(this, BarChartActivitySinus.class); - startActivity(i); + i = new Intent(this, BubbleChartActivity.class); break; case 26: - i = new Intent(this, ScrollViewActivity.class); - startActivity(i); + i = new Intent(this, CandleStickChartActivity.class); break; case 27: - i = new Intent(this, BarChartPositiveNegative.class); - startActivity(i); - break; - case 28: - i = new Intent(this, RealmMainActivity.class); - startActivity(i); + i = new Intent(this, RadarChartActivity.class); break; case 29: - i = new Intent(this, LineChartTime.class); - startActivity(i); + i = new Intent(this, ListViewMultiChartActivity.class); break; case 30: - i = new Intent(this, FilledLineActivity.class); - startActivity(i); + i = new Intent(this, SimpleChartDemo.class); break; case 31: - i = new Intent(this, HalfPieChartActivity.class); - startActivity(i); + i = new Intent(this, ScrollViewActivity.class); break; - + case 32: + i = new Intent(this, ListViewBarChartActivity.class); + break; + case 34: + i = new Intent(this, DynamicalAddingActivity.class); + break; + case 35: + i = new Intent(this, RealtimeLineChartActivity.class); + break; + case 36: + i = new Intent(this, LineChartTime.class); + break; + /*case 37: + i = new Intent(this, RealmMainActivity.class); + break;*/ } + if (i != null) startActivity(i); + overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); } @@ -304,7 +248,7 @@ public boolean onCreateOptionsMenu(Menu menu) { @Override public boolean onOptionsItemSelected(MenuItem item) { - Intent i = null; + Intent i; switch (item.getItemId()) { case R.id.viewGithub: @@ -319,11 +263,6 @@ public boolean onOptionsItemSelected(MenuItem item) { i.putExtra(Intent.EXTRA_TEXT, "Your error report here..."); startActivity(Intent.createChooser(i, "Report Problem")); break; - case R.id.blog: - i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("http://www.xxmassdeveloper.com")); - startActivity(i); - break; case R.id.website: i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse("http://at.linkedin.com/in/philippjahoda")); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java index 5b424e88a5..d9fc14a609 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java @@ -1,7 +1,10 @@ package com.xxmassdeveloper.mpchartexample.notimportant; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Typeface; +import androidx.annotation.NonNull; + import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -27,36 +30,40 @@ public MyAdapter(Context context, List objects) { mTypeFaceRegular = Typeface.createFromAsset(context.getAssets(), "OpenSans-Regular.ttf"); } + @SuppressLint("InflateParams") + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { ContentItem c = getItem(position); - ViewHolder holder = null; - - if (convertView == null) { + ViewHolder holder; - holder = new ViewHolder(); + holder = new ViewHolder(); + if (c != null && c.isSection) { + convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_section, null); + } else { convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, null); - holder.tvName = convertView.findViewById(R.id.tvName); - holder.tvDesc = convertView.findViewById(R.id.tvDesc); - holder.tvNew = convertView.findViewById(R.id.tvNew); + } - convertView.setTag(holder); + holder.tvName = convertView.findViewById(R.id.tvName); + holder.tvDesc = convertView.findViewById(R.id.tvDesc); + holder.tvNew = convertView.findViewById(R.id.tvNew); - } else { - holder = (ViewHolder) convertView.getTag(); - } + convertView.setTag(holder); holder.tvNew.setTypeface(mTypeFaceRegular); - holder.tvName.setTypeface(mTypeFaceLight); + if (c != null && c.isSection) + holder.tvName.setTypeface(mTypeFaceRegular); + else + holder.tvName.setTypeface(mTypeFaceLight); holder.tvDesc.setTypeface(mTypeFaceLight); - holder.tvName.setText(c.name); - holder.tvDesc.setText(c.desc); + holder.tvName.setText(c != null ? c.name : null); + holder.tvDesc.setText(c != null ? c.desc : null); - if(c.isNew) + if(c != null && c.isNew) holder.tvNew.setVisibility(View.VISIBLE); else holder.tvNew.setVisibility(View.GONE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 9b98f00f92..690eb6cf3a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -19,6 +19,7 @@ /** * Created by Philipp Jahoda on 05/11/15. */ +@SuppressWarnings("SameParameterValue") public abstract class RealmBaseActivity extends DemoBase { protected Realm mRealm; @@ -139,8 +140,7 @@ protected void writeToDBCandle(int objectCount) { for (int i = 0; i < objectCount; i++) { - float mult = 50; - float val = (float) (Math.random() * 40) + mult; + float val = (float) (Math.random() * 40) + 50f; float high = (float) (Math.random() * 9) + 8f; float low = (float) (Math.random() * 9) + 8f; @@ -199,4 +199,7 @@ protected void writeToDBPie() { mRealm.commitTransaction(); } + + @Override + public void saveToGallery() { /* Intentionally left empty */ } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java index 1e5d5cb8d5..f7cba47340 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java @@ -49,12 +49,12 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "yValue"); // stacked entries - set.setColors(new int[] {ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet<>(result, "xValue", "yValue"); // stacked entries + set.setColors(ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")); set.setLabel("Realm BarDataSet"); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java index ad65a3de18..3493ade94f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java @@ -53,11 +53,11 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - RealmBubbleDataSet set = new RealmBubbleDataSet(result, "xValue", "yValue", "bubbleSize"); + RealmBubbleDataSet set = new RealmBubbleDataSet<>(result, "xValue", "yValue", "bubbleSize"); set.setLabel("Realm BubbleDataSet"); set.setColors(ColorTemplate.COLORFUL_COLORS, 110); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java index 96fbade855..49d8903c6e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - RealmCandleDataSet set = new RealmCandleDataSet(result, "xValue", "high", "low", "open", "close"); + RealmCandleDataSet set = new RealmCandleDataSet<>(result, "xValue", "high", "low", "open", "close"); set.setLabel("Realm CandleDataSet"); set.setShadowColor(Color.DKGRAY); set.setShadowWidth(0.7f); @@ -63,7 +63,7 @@ private void setData() { set.setIncreasingPaintStyle(Paint.Style.STROKE); set.setNeutralColor(Color.BLUE); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index b5e3345134..680ee1e83c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -53,13 +53,13 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet(result, "xValue", "stackValues", "floatValue"); // stacked entries - set.setColors(new int[]{ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")}); + //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet<>(result, "xValue", "stackValues", "floatValue"); // stacked entries + set.setColors(ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")); set.setLabel("Mobile OS distribution"); set.setStackLabels(new String[]{"iOS", "Android", "Other"}); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java index 7d2e49fdff..c0bbd3caf6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java @@ -55,7 +55,7 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - RealmLineDataSet set = new RealmLineDataSet(result, "xValue", "yValue"); + RealmLineDataSet set = new RealmLineDataSet<>(result, "xValue", "yValue"); set.setMode(LineDataSet.Mode.CUBIC_BEZIER); set.setLabel("Realm LineDataSet"); set.setDrawCircleHole(false); @@ -64,7 +64,7 @@ private void setData() { set.setLineWidth(1.8f); set.setCircleRadius(3.6f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java index 9fad49c617..46af4cda31 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java @@ -53,7 +53,7 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - RealmPieDataSet set = new RealmPieDataSet(result, "yValue", "label"); + RealmPieDataSet set = new RealmPieDataSet<>(result, "yValue", "label"); set.setColors(ColorTemplate.VORDIPLOM_COLORS); set.setLabel("Example market share"); set.setSliceSpace(2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java index 02f3ac0492..faef4e28bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java @@ -21,23 +21,23 @@ */ public class RealmDatabaseActivityRadar extends RealmBaseActivity { - private RadarChart mChart; + private RadarChart chart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart_noseekbar); + setContentView(R.layout.activity_radarchart); - mChart = findViewById(R.id.chart1); - setup(mChart); + chart = findViewById(R.id.chart1); + setup(chart); - mChart.getYAxis().setEnabled(false); - mChart.getXAxis().setEnabled(false); - mChart.setWebAlpha(180); - mChart.setWebColorInner(Color.DKGRAY); - mChart.setWebColor(Color.GRAY); + chart.getYAxis().setEnabled(false); + chart.getXAxis().setEnabled(false); + chart.setWebAlpha(180); + chart.setWebColorInner(Color.DKGRAY); + chart.setWebColor(Color.GRAY); } @Override @@ -55,8 +55,8 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet(result, "yValue"); // stacked entries + //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries + RealmRadarDataSet set = new RealmRadarDataSet<>(result, "yValue"); // stacked entries set.setLabel("Realm RadarDataSet"); set.setDrawFilled(true); set.setColor(ColorTemplate.rgb("#009688")); @@ -64,7 +64,7 @@ private void setData() { set.setFillAlpha(130); set.setLineWidth(2f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list @@ -72,7 +72,7 @@ private void setData() { styleData(data); // set data - mChart.setData(data); - mChart.animateY(1400); + chart.setData(data); + chart.animateY(1400); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java index 9da64cbf1d..01e0151933 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java @@ -53,13 +53,13 @@ private void setData() { RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - RealmScatterDataSet set = new RealmScatterDataSet(result, "xValue", "yValue"); + RealmScatterDataSet set = new RealmScatterDataSet<>(result, "xValue", "yValue"); set.setLabel("Realm ScatterDataSet"); set.setScatterShapeSize(9f); set.setColor(ColorTemplate.rgb("#CDDC39")); set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(set); // add the dataset // create a data object with the dataset list diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java index 1776a8bd7e..674cef458e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java @@ -1,5 +1,6 @@ package com.xxmassdeveloper.mpchartexample.realm; +import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -12,7 +13,6 @@ import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; import java.util.ArrayList; @@ -23,7 +23,7 @@ /** * Created by Philipp Jahoda on 07/12/15. */ -public class RealmMainActivity extends DemoBase implements AdapterView.OnItemClickListener { +public class RealmMainActivity extends Activity implements AdapterView.OnItemClickListener { @Override protected void onCreate(Bundle savedInstanceState) { @@ -34,7 +34,7 @@ protected void onCreate(Bundle savedInstanceState) { setTitle("Realm.io Examples"); - ArrayList objects = new ArrayList(); + ArrayList objects = new ArrayList<>(); objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); objects.add(new ContentItem("Bar Chart", diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index f223be6093..35212728cd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -88,14 +88,15 @@ private void setData() { IAxisValueFormatter formatter = new IAxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { - return results.get((int) value).getPlayerName(); + Score result = results.get((int) value); + return result != null ? result.playerName : ""; } }; lineChart.getXAxis().setValueFormatter(formatter); barChart.getXAxis().setValueFormatter(formatter); - RealmLineDataSet lineDataSet = new RealmLineDataSet(results, "scoreNr", "totalScore"); + RealmLineDataSet lineDataSet = new RealmLineDataSet<>(results, "scoreNr", "totalScore"); lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); lineDataSet.setLabel("Result Scores"); lineDataSet.setDrawCircleHole(false); @@ -104,7 +105,7 @@ public String getFormattedValue(float value, AxisBase axis) { lineDataSet.setLineWidth(1.8f); lineDataSet.setCircleRadius(3.6f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList<>(); dataSets.add(lineDataSet); LineData lineData = new LineData(dataSets); @@ -116,11 +117,11 @@ public String getFormattedValue(float value, AxisBase axis) { // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet(results, "scoreNr", "totalScore"); - barDataSet.setColors(new int[]{ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")}); + RealmBarDataSet barDataSet = new RealmBarDataSet<>(results, "scoreNr", "totalScore"); + barDataSet.setColors(ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")); barDataSet.setLabel("Realm BarDataSet"); - ArrayList barDataSets = new ArrayList(); + ArrayList barDataSets = new ArrayList<>(); barDataSets.add(barDataSet); BarData barData = new BarData(barDataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java index 870e371491..0d1f806616 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java @@ -6,16 +6,16 @@ /** * our data object */ +@SuppressWarnings({"WeakerAccess", "unused"}) public class Score extends RealmObject { - private float totalScore; + public float totalScore; - private float scoreNr; + public float scoreNr; - private String playerName; + public String playerName; - public Score() { - } + public Score() {} public Score(float totalScore, float scoreNr, String playerName) { this.scoreNr = scoreNr; @@ -23,29 +23,4 @@ public Score(float totalScore, float scoreNr, String playerName) { this.totalScore = totalScore; } - // all getters and setters... - - public float getTotalScore() { - return totalScore; - } - - public void setTotalScore(float totalScore) { - this.totalScore = totalScore; - } - - public float getScoreNr() { - return scoreNr; - } - - public void setScoreNr(float scoreNr) { - this.scoreNr = scoreNr; - } - - public String getPlayerName() { - return playerName; - } - - public void setPlayerName(String playerName) { - this.playerName = playerName; - } -} \ No newline at end of file +} diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 19c06befb3..83fc126bff 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -4,13 +4,12 @@ apply plugin: 'maven' //apply plugin: 'realm-android' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 28 + buildToolsVersion '28.0.3' // resourcePrefix 'mpcht' defaultConfig { - //noinspection MinSdkTooLow - minSdkVersion 9 - targetSdkVersion 27 + minSdkVersion 14 + targetSdkVersion 28 versionCode 3 versionName '3.0.3' } @@ -36,7 +35,7 @@ repositories { dependencies { //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API - implementation 'com.android.support:support-annotations:27.1.1' + implementation 'androidx.annotation:annotation:1.0.0' testImplementation 'junit:junit:4.12' testImplementation "org.mockito:mockito-core:1.10.19" } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index 026a1b30d3..b33b3fb69d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -3,7 +3,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; import com.github.mikephil.charting.animation.Easing.EasingFunction; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java index 631e313b10..2c64777a6a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java @@ -2,7 +2,7 @@ package com.github.mikephil.charting.animation; import android.animation.TimeInterpolator; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; /** * Easing options. @@ -62,7 +62,6 @@ public enum EasingOption { * @param easing EasingOption to get * @return EasingFunction */ - @SuppressWarnings("deprecation") @Deprecated public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { switch (easing) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 35ec2ec1e0..718d7e2acb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -17,7 +17,7 @@ import android.os.Build; import android.os.Environment; import android.provider.MediaStore.Images; -import android.support.annotation.RequiresApi; +import androidx.annotation.RequiresApi; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -1527,6 +1527,8 @@ public Bitmap getChartBitmap() { */ public boolean saveToPath(String title, String pathOnSD) { + + Bitmap b = getChartBitmap(); OutputStream stream = null; @@ -1642,7 +1644,18 @@ public boolean saveToGallery(String fileName, String subFolderPath, String fileD * @return returns true if saving was successful, false if not */ public boolean saveToGallery(String fileName, int quality) { - return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.JPEG, quality); + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.PNG, quality); + } + + /** + * Saves the current state of the chart to the gallery as a PNG image. + * NOTE: Needs permission WRITE_EXTERNAL_STORAGE + * + * @param fileName e.g. "my_image" + * @return returns true if saving was successful, false if not + */ + public boolean saveToGallery(String fileName) { + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.PNG, 40); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 2381dbf868..030603f55a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -370,6 +370,7 @@ public boolean needsOffset() { /** * Returns true if autoscale restriction for axis min value is enabled */ + @Deprecated public boolean isUseAutoScaleMinRestriction( ) { return mUseAutoScaleRestrictionMin; } @@ -377,6 +378,7 @@ public boolean isUseAutoScaleMinRestriction( ) { /** * Sets autoscale restriction for axis min value as enabled/disabled */ + @Deprecated public void setUseAutoScaleMinRestriction( boolean isEnabled ) { mUseAutoScaleRestrictionMin = isEnabled; } @@ -384,6 +386,7 @@ public void setUseAutoScaleMinRestriction( boolean isEnabled ) { /** * Returns true if autoscale restriction for axis max value is enabled */ + @Deprecated public boolean isUseAutoScaleMaxRestriction() { return mUseAutoScaleRestrictionMax; } @@ -391,6 +394,7 @@ public boolean isUseAutoScaleMaxRestriction() { /** * Sets autoscale restriction for axis max value as enabled/disabled */ + @Deprecated public void setUseAutoScaleMaxRestriction( boolean isEnabled ) { mUseAutoScaleRestrictionMax = isEnabled; } @@ -402,24 +406,6 @@ public void calculate(float dataMin, float dataMax) { float min = dataMin; float max = dataMax; - // if custom, use value as is, else use data value - if( mCustomAxisMin ) { - if( mUseAutoScaleRestrictionMin ) { - min = Math.min( dataMin, mAxisMinimum ); - } else { - min = mAxisMinimum; - } - } - - if( mCustomAxisMax ) { - if( mUseAutoScaleRestrictionMax ) { - max = Math.max( max, mAxisMaximum ); - } else { - max = mAxisMaximum; - } - } - - // temporary range (before calculations) float range = Math.abs(max - min); // in case all values are equal @@ -428,13 +414,13 @@ public void calculate(float dataMin, float dataMax) { min = min - 1f; } - float bottomSpace = range / 100f * getSpaceBottom(); - this.mAxisMinimum = (min - bottomSpace); - - float topSpace = range / 100f * getSpaceTop(); - this.mAxisMaximum = (max + topSpace); + // recalculate + range = Math.abs(max - min); + + // calc extra spacing + this.mAxisMinimum = mCustomAxisMin ? this.mAxisMinimum : min - (range / 100f) * getSpaceBottom(); + this.mAxisMaximum = mCustomAxisMax ? this.mAxisMaximum : max + (range / 100f) * getSpaceTop(); - // calc actual range - this.mAxisRange = Math.abs(this.mAxisMaximum - this.mAxisMinimum); + this.mAxisRange = Math.abs(this.mAxisMinimum - this.mAxisMaximum); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 527617472a..d3527f924a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -45,6 +45,7 @@ public boolean onTouch(View v, MotionEvent event) { return true; // if rotation by touch is enabled + // TODO: Also check if the pie itself is being touched, rather than the entire chart area if (mChart.isRotationEnabled()) { float x = event.getX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 17bba048b9..d53dcd4785 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -67,6 +67,9 @@ protected float getShapeSize(float entrySize, float maxSize, float reference, bo protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { + if (dataSet.getEntryCount() < 1) + return; + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); float phaseY = mAnimator.getPhaseY(); @@ -131,7 +134,7 @@ public void drawValues(Canvas c) { IBubbleDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index e4c06fe46c..991b702117 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -264,7 +264,7 @@ public void drawValues(Canvas c) { ICandleDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a0e1777569..744bf654c0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -497,12 +497,12 @@ private void generateFilledPath(final ILineDataSet dataSet, final int startIndex // create a new path Entry currentEntry = null; - Entry previousEntry = null; + Entry previousEntry = entry; for (int x = startIndex + 1; x <= endIndex; x++) { currentEntry = dataSet.getEntryForIndex(x); - if (isDrawSteppedEnabled && previousEntry != null) { + if (isDrawSteppedEnabled) { filled.lineTo(currentEntry.getX(), previousEntry.getY() * phaseY); } @@ -530,7 +530,7 @@ public void drawValues(Canvas c) { ILineDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 36a38a53c5..ccd077e55c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -49,6 +49,9 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { + if (dataSet.getEntryCount() < 1) + return; + ViewPortHandler viewPortHandler = mViewPortHandler; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -101,7 +104,7 @@ public void drawValues(Canvas c) { IScatterDataSet dataSet = dataSets.get(i); - if (!shouldDrawValues(dataSet)) + if (!shouldDrawValues(dataSet) || dataSet.getEntryCount() < 1) continue; // apply the text-styling defined by the DataSet diff --git a/build.gradle b/build.gradle index 65ca5186cf..fb18d8fe7d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { classpath "io.realm:realm-gradle-plugin:4.2.0" - classpath 'com.android.tools.build:gradle:3.1.2' + classpath 'com.android.tools.build:gradle:3.2.1' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' } } diff --git a/gradle.properties b/gradle.properties index 4a9594aeec..0c0632ee2f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1,3 @@ -org.gradle.jvmargs=-Xmx2048M \ No newline at end of file +android.enableJetifier=true +android.useAndroidX=true +org.gradle.jvmargs=-Xmx2048M diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 02b0428be0..f48e20880d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Apr 25 08:04:33 CEST 2018 +#Mon Oct 22 19:51:30 MDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip From db7dda2b7e42060e90b7ac780fd7f60ac30d6ef3 Mon Sep 17 00:00:00 2001 From: almic Date: Sat, 27 Oct 2018 13:40:38 -0600 Subject: [PATCH 1321/1390] More Linting Lots of things in the example app are now marked with the 'final' modifier, and saveToGallery() is protected in classes that implement it. As well, new suppressions are in a few places. NEW text is now removed completely. Looks like this has been unused for a long time and it's just stuck around anyway. --- .../res/drawable/new_background.xml | 9 --------- MPChartExample/res/layout/list_item.xml | 19 +------------------ .../res/layout/list_item_section.xml | 16 ---------------- MPChartExample/res/values/strings.xml | 1 - .../mpchartexample/AnotherBarActivity.java | 2 +- .../mpchartexample/BarChartActivity.java | 4 ++-- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BarChartActivitySinus.java | 2 +- .../BarChartPositiveNegative.java | 8 ++++---- .../mpchartexample/BubbleChartActivity.java | 2 +- .../CandleStickChartActivity.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 6 +++--- .../CubicLineChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 2 +- .../HorizontalBarChartActivity.java | 4 ++-- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 2 +- .../LineChartActivityColored.java | 2 +- .../mpchartexample/LineChartTime.java | 4 ++-- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PieChartActivity.java | 2 +- .../PiePolylineChartActivity.java | 2 +- .../mpchartexample/RadarChartActivity.java | 2 +- .../RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 2 +- .../StackedBarActivityNegative.java | 6 +++--- .../custom/DayAxisValueFormatter.java | 2 +- .../custom/MyAxisValueFormatter.java | 2 +- .../custom/MyCustomXAxisValueFormatter.java | 4 ++-- .../mpchartexample/custom/MyMarkerView.java | 2 +- .../custom/MyValueFormatter.java | 4 ++-- .../custom/RadarMarkerView.java | 4 ++-- .../mpchartexample/custom/XYMarkerView.java | 6 +++--- .../fragments/SimpleFragment.java | 2 +- .../listviewitems/BarChartItem.java | 2 +- .../listviewitems/LineChartItem.java | 2 +- .../listviewitems/PieChartItem.java | 4 ++-- .../notimportant/ContentItem.java | 5 ++--- .../mpchartexample/notimportant/DemoBase.java | 2 +- .../notimportant/MyAdapter.java | 12 ++---------- 43 files changed, 58 insertions(+), 110 deletions(-) delete mode 100644 MPChartExample/res/drawable/new_background.xml diff --git a/MPChartExample/res/drawable/new_background.xml b/MPChartExample/res/drawable/new_background.xml deleted file mode 100644 index c2d3b9cfc5..0000000000 --- a/MPChartExample/res/drawable/new_background.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/MPChartExample/res/layout/list_item.xml b/MPChartExample/res/layout/list_item.xml index 2b6069b4f4..a6e5b5f3eb 100644 --- a/MPChartExample/res/layout/list_item.xml +++ b/MPChartExample/res/layout/list_item.xml @@ -23,23 +23,6 @@ android:layout_marginTop="3dp" android:text="Small Text" android:textSize="12sp" - android:layout_marginRight="10dp" - android:layout_toLeftOf="@+id/tvNew" - android:layout_toStartOf="@+id/tvNew" /> - - + android:layout_marginRight="10dp" /> diff --git a/MPChartExample/res/layout/list_item_section.xml b/MPChartExample/res/layout/list_item_section.xml index f71901d1fb..19707f1777 100644 --- a/MPChartExample/res/layout/list_item_section.xml +++ b/MPChartExample/res/layout/list_item_section.xml @@ -23,20 +23,4 @@ android:textSize="12sp" android:visibility="gone" /> - - diff --git a/MPChartExample/res/values/strings.xml b/MPChartExample/res/values/strings.xml index d81d9b1a0c..2426d92a78 100644 --- a/MPChartExample/res/values/strings.xml +++ b/MPChartExample/res/values/strings.xml @@ -50,6 +50,5 @@ - START OF SCROLLVIEW END OF SCROLLVIEW - NEW diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 5916619645..69b5a96c42 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -202,7 +202,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "AnotherBarActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index fcdaae364d..865bc92ea2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -297,7 +297,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "BarChartActivity"); } @@ -307,7 +307,7 @@ public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} - private RectF onValueSelectedRectF = new RectF(); + private final RectF onValueSelectedRectF = new RectF(); @Override public void onValueSelected(Entry e, Highlight h) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index d0c0bc453d..7f795046e3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -266,7 +266,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "BarChartActivityMultiDataset"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index d7c16df440..95443e8214 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -226,7 +226,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "BarChartActivitySinus"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index ce73317860..4fec7dd6ab 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -148,9 +148,9 @@ private void setData(List dataList) { */ private class Data { - String xAxisValue; - float yValue; - float xValue; + final String xAxisValue; + final float yValue; + final float xValue; Data(float xValue, float yValue, String xAxisValue) { this.xAxisValue = xAxisValue; @@ -162,7 +162,7 @@ private class Data { private class ValueFormatter implements IValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; ValueFormatter() { mFormat = new DecimalFormat("######.0"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 098c8f242b..6288dda2be 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -226,7 +226,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "BubbleChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index b0b29dfbe4..ecf7167a62 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -226,7 +226,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "CandleStickChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 7526dc1d59..0308b9a891 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -170,7 +170,7 @@ private BarData generateBarData() { return d; } - ScatterData generateScatterData() { + private ScatterData generateScatterData() { ScatterData d = new ScatterData(); @@ -189,7 +189,7 @@ ScatterData generateScatterData() { return d; } - CandleData generateCandleData() { + private CandleData generateCandleData() { CandleData d = new CandleData(); @@ -209,7 +209,7 @@ CandleData generateCandleData() { return d; } - BubbleData generateBubbleData() { + private BubbleData generateBubbleData() { BubbleData bd = new BubbleData(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 25134f71fd..f30732e6eb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -309,7 +309,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "CubicLineChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 348b9ad0fc..7a32e5329c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -147,7 +147,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "DrawChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 501090af62..84de449283 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -236,7 +236,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "DynamicalAddingActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 6e4e9275bf..f93baaa376 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -257,7 +257,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "HorizontalBarChartActivity"); } @@ -267,7 +267,7 @@ public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} - private RectF mOnValueSelectedRectF = new RectF(); + private final RectF mOnValueSelectedRectF = new RectF(); @Override public void onValueSelected(Entry e, Highlight h) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index cdc3188854..999d17e7b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -263,7 +263,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "InvertedLineChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 4a970df995..9505838810 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -430,7 +430,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "LineChartActivity1"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index c0f72d87fa..60cab539a9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -381,7 +381,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "LineChartActivity2"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 7bb95b83ed..6a12e8f95d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -22,7 +22,7 @@ @SuppressWarnings("SameParameterValue") public class LineChartActivityColored extends DemoBase { - private LineChart[] charts = new LineChart[4]; + private final LineChart[] charts = new LineChart[4]; @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java index a88842c5d0..47d0a79046 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(1f); // one hour xAxis.setValueFormatter(new IAxisValueFormatter() { - private SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); + private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override public String getFormattedValue(float value, AxisBase axis) { @@ -308,7 +308,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "LineChartTime"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index c5cbd570c6..11d69d8dae 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -288,7 +288,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "MultiLineChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 9d77dcc8b7..e22b828d56 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -267,7 +267,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "PieChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 80ca82cde9..ebeb43e9cf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -262,7 +262,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "PiePolylineChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index c2a5eb3d0a..883eb7dfc1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -254,7 +254,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "RadarChartActivity"); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 606d750efe..e26c460ffa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -224,7 +224,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "RealtimeLineChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 9b441793f0..e51755ad0b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -225,7 +225,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "ScatterChartActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index c98abb68aa..676e0e62b0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -248,7 +248,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "StackedBarActivity"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index b9df66981a..7af58c85ca 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -82,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setGranularity(10f); xAxis.setValueFormatter(new IAxisValueFormatter() { - private DecimalFormat format = new DecimalFormat("###"); + private final DecimalFormat format = new DecimalFormat("###"); @Override public String getFormattedValue(float value, AxisBase axis) { @@ -226,7 +226,7 @@ public boolean onOptionsItemSelected(MenuItem item) { } @Override - public void saveToGallery() { + protected void saveToGallery() { saveToGallery(chart, "StackedBarActivityNegative"); } @@ -244,7 +244,7 @@ public void onNothingSelected() { private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; CustomFormatter() { mFormat = new DecimalFormat("###"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index a27cff89c9..ba4d860d92 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -14,7 +14,7 @@ public class DayAxisValueFormatter implements IAxisValueFormatter "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - private BarLineChartBase chart; + private final BarLineChartBase chart; public DayAxisValueFormatter(BarLineChartBase chart) { this.chart = chart; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java index e8456675a9..e7cdbfcd10 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -8,7 +8,7 @@ public class MyAxisValueFormatter implements IAxisValueFormatter { - private DecimalFormat mFormat; + private final DecimalFormat mFormat; public MyAxisValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index e9662aca78..bea4908ef2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -15,8 +15,8 @@ public class MyCustomXAxisValueFormatter implements IAxisValueFormatter { - private DecimalFormat mFormat; - private ViewPortHandler mViewPortHandler; + private final DecimalFormat mFormat; + private final ViewPortHandler mViewPortHandler; public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { mViewPortHandler = viewPortHandler; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 25d3195cb5..2c1da9b4e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -21,7 +21,7 @@ @SuppressLint("ViewConstructor") public class MyMarkerView extends MarkerView { - private TextView tvContent; + private final TextView tvContent; public MyMarkerView(Context context, int layoutResource) { super(context, layoutResource); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index cbf5fd56c8..ec1c119818 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -9,8 +9,8 @@ public class MyValueFormatter implements IValueFormatter { - private DecimalFormat mFormat; - + private final DecimalFormat mFormat; + public MyValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java index 6fb2161577..ca057a5aa3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java @@ -22,8 +22,8 @@ @SuppressLint("ViewConstructor") public class RadarMarkerView extends MarkerView { - private TextView tvContent; - private DecimalFormat format = new DecimalFormat("##0"); + private final TextView tvContent; + private final DecimalFormat format = new DecimalFormat("##0"); public RadarMarkerView(Context context, int layoutResource) { super(context, layoutResource); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index f85f538988..51e4247d35 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -22,10 +22,10 @@ @SuppressLint("ViewConstructor") public class XYMarkerView extends MarkerView { - private TextView tvContent; - private IAxisValueFormatter xAxisValueFormatter; + private final TextView tvContent; + private final IAxisValueFormatter xAxisValueFormatter; - private DecimalFormat format; + private final DecimalFormat format; public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 5caa290178..ab70041e60 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -30,7 +30,7 @@ import java.util.ArrayList; -@SuppressWarnings("SameParameterValue") +@SuppressWarnings({"SameParameterValue", "WeakerAccess"}) public abstract class SimpleFragment extends Fragment { private Typeface tf; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index b49daa3be4..eeb1791fe1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -16,7 +16,7 @@ public class BarChartItem extends ChartItem { - private Typeface mTf; + private final Typeface mTf; public BarChartItem(ChartData cd, Context c) { super(cd); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index e4c11869ac..d69b010322 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -17,7 +17,7 @@ public class LineChartItem extends ChartItem { - private Typeface mTf; + private final Typeface mTf; public LineChartItem(ChartData cd, Context c) { super(cd); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 0c5e56bd3b..916f8dc5e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -21,8 +21,8 @@ public class PieChartItem extends ChartItem { - private Typeface mTf; - private SpannableString mCenterText; + private final Typeface mTf; + private final SpannableString mCenterText; public PieChartItem(ChartData cd, Context c) { super(cd); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java index 41f05afc10..a6625bae9a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java @@ -5,9 +5,8 @@ */ public class ContentItem { - String name; - String desc; - boolean isNew = false; + final String name; + final String desc; boolean isSection = false; public ContentItem(String n) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java index ea0d1aa008..a963609aff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java @@ -95,5 +95,5 @@ protected void saveToGallery(Chart chart, String name) { .show(); } - abstract public void saveToGallery(); + protected abstract void saveToGallery(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java index d9fc14a609..4ddac475bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java @@ -20,8 +20,8 @@ */ public class MyAdapter extends ArrayAdapter { - private Typeface mTypeFaceLight; - private Typeface mTypeFaceRegular; + private final Typeface mTypeFaceLight; + private final Typeface mTypeFaceRegular; public MyAdapter(Context context, List objects) { super(context, 0, objects); @@ -49,11 +49,9 @@ public View getView(int position, View convertView, @NonNull ViewGroup parent) { holder.tvName = convertView.findViewById(R.id.tvName); holder.tvDesc = convertView.findViewById(R.id.tvDesc); - holder.tvNew = convertView.findViewById(R.id.tvNew); convertView.setTag(holder); - holder.tvNew.setTypeface(mTypeFaceRegular); if (c != null && c.isSection) holder.tvName.setTypeface(mTypeFaceRegular); else @@ -63,17 +61,11 @@ public View getView(int position, View convertView, @NonNull ViewGroup parent) { holder.tvName.setText(c != null ? c.name : null); holder.tvDesc.setText(c != null ? c.desc : null); - if(c != null && c.isNew) - holder.tvNew.setVisibility(View.VISIBLE); - else - holder.tvNew.setVisibility(View.GONE); - return convertView; } private class ViewHolder { TextView tvName, tvDesc; - TextView tvNew; } } From 5030b36c86cfa2d076bb6b86fa8fcb37ce58557f Mon Sep 17 00:00:00 2001 From: almic Date: Sat, 27 Oct 2018 18:00:06 -0600 Subject: [PATCH 1322/1390] More Cleanup I've removed the realm examples, mainly because the library was buggy. In the previous commit, I already removed the examples from the list since they didn't add anything to the overall demonstration. I thought that if anyone wants to use realm.io with the charts, they can see the actual library. The file structure has been updated to match how Android Studio does things. Some files added way back when have been deleted as they don't do anything but cause the linter to freak out about 'unused properties' All 'build.gradle' files have been refreshed as well. Small addition to the README file to add a quick way to reach sections of the page. --- ...springsource.ide.eclipse.gradle.core.prefs | 4 - ...springsource.ide.eclipse.gradle.core.prefs | 3 - MPChartExample/build.gradle | 25 --- MPChartExample/proguard-project.txt | 20 -- MPChartExample/proguard-rules.pro | 21 ++ MPChartExample/project.properties | 15 -- .../layout/activity_bubblechart_noseekbar.xml | 11 - .../layout/activity_candlechart_noseekbar.xml | 11 - .../activity_horizontalbarchart_noseekbar.xml | 11 - .../layout/activity_piechart_noseekbar.xml | 11 - .../res/layout/activity_realm_wiki.xml | 19 -- .../activity_scatterchart_noseekbar.xml | 11 - MPChartExample/res/menu/realm.xml | 13 -- .../mpchartexample/custom/RealmDemoData.java | 173 --------------- .../mpchartexample/custom/RealmFloat.java | 28 --- .../realm/RealmBaseActivity.java | 205 ------------------ .../realm/RealmDatabaseActivityBar.java | 69 ------ .../realm/RealmDatabaseActivityBubble.java | 71 ------ .../realm/RealmDatabaseActivityCandle.java | 77 ------- .../RealmDatabaseActivityHorizontalBar.java | 74 ------- .../realm/RealmDatabaseActivityLine.java | 78 ------- .../realm/RealmDatabaseActivityPie.java | 82 ------- .../realm/RealmDatabaseActivityRadar.java | 78 ------- .../realm/RealmDatabaseActivityScatter.java | 73 ------- .../realm/RealmMainActivity.java | 133 ------------ .../realm/RealmWikiExample.java | 134 ------------ .../mpchartexample/realm/Score.java | 26 --- .../{ => src/main}/AndroidManifest.xml | 22 +- .../{ => src/main}/assets/OpenSans-Bold.ttf | Bin .../main}/assets/OpenSans-BoldItalic.ttf | Bin .../main}/assets/OpenSans-ExtraBold.ttf | Bin .../main}/assets/OpenSans-ExtraBoldItalic.ttf | Bin .../{ => src/main}/assets/OpenSans-Italic.ttf | Bin .../{ => src/main}/assets/OpenSans-Light.ttf | Bin .../main}/assets/OpenSans-LightItalic.ttf | Bin .../main}/assets/OpenSans-Regular.ttf | Bin .../main}/assets/OpenSans-Semibold.ttf | Bin .../main}/assets/OpenSans-SemiboldItalic.ttf | Bin .../{ => src/main}/assets/cosine.txt | 0 .../{ => src/main}/assets/hugecosine.txt | 0 .../{ => src/main}/assets/hugesine.txt | 0 MPChartExample/{ => src/main}/assets/n.txt | 0 .../{ => src/main}/assets/nlogn.txt | 0 .../{ => src/main}/assets/othersine.txt | 0 MPChartExample/{ => src/main}/assets/sine.txt | 0 .../{ => src/main}/assets/square.txt | 0 .../{ => src/main}/assets/stacked_bars.txt | 0 .../{ => src/main}/assets/three.txt | 0 .../{ => src/main}/ic_launcher-web.png | Bin .../mpchartexample/AnotherBarActivity.java | 0 .../mpchartexample/BarChartActivity.java | 1 - .../BarChartActivityMultiDataset.java | 1 + .../mpchartexample/BarChartActivitySinus.java | 0 .../BarChartPositiveNegative.java | 0 .../mpchartexample/BubbleChartActivity.java | 0 .../CandleStickChartActivity.java | 0 .../mpchartexample/CombinedChartActivity.java | 0 .../CubicLineChartActivity.java | 1 - .../mpchartexample/DrawChartActivity.java | 0 .../DynamicalAddingActivity.java | 0 .../mpchartexample/FilledLineActivity.java | 0 .../mpchartexample/HalfPieChartActivity.java | 0 .../HorizontalBarChartActivity.java | 1 - .../InvertedLineChartActivity.java | 6 +- .../mpchartexample/LineChartActivity1.java | 0 .../mpchartexample/LineChartActivity2.java | 1 - .../LineChartActivityColored.java | 0 .../mpchartexample/LineChartTime.java | 2 - .../ListViewBarChartActivity.java | 0 .../ListViewMultiChartActivity.java | 0 .../MultiLineChartActivity.java | 0 .../mpchartexample/PerformanceLineChart.java | 0 .../mpchartexample/PieChartActivity.java | 1 - .../PiePolylineChartActivity.java | 1 - .../mpchartexample/RadarChartActivity.java | 0 .../RealtimeLineChartActivity.java | 0 .../mpchartexample/ScatterChartActivity.java | 0 .../mpchartexample/ScrollViewActivity.java | 0 .../mpchartexample/StackedBarActivity.java | 0 .../StackedBarActivityNegative.java | 0 .../custom/CustomScatterShapeRenderer.java | 0 .../custom/DayAxisValueFormatter.java | 0 .../custom/MyAxisValueFormatter.java | 0 .../custom/MyCustomXAxisValueFormatter.java | 0 .../custom/MyFillFormatter.java | 0 .../mpchartexample/custom/MyMarkerView.java | 0 .../custom/MyValueFormatter.java | 0 .../custom/RadarMarkerView.java | 0 .../custom/StackedBarsMarkerView.java | 0 .../mpchartexample/custom/XYMarkerView.java | 0 .../custom/YearXAxisFormatter.java | 0 .../fragments/BarChartFrag.java | 0 .../fragments/ComplexityFragment.java | 0 .../fragments/PieChartFrag.java | 0 .../fragments/ScatterChartFrag.java | 0 .../fragments/SimpleChartDemo.java | 0 .../fragments/SimpleFragment.java | 0 .../fragments/SineCosineFragment.java | 0 .../listviewitems/BarChartItem.java | 0 .../listviewitems/ChartItem.java | 0 .../listviewitems/LineChartItem.java | 0 .../listviewitems/PieChartItem.java | 0 .../notimportant/ContentItem.java | 6 +- .../mpchartexample/notimportant/DemoBase.java | 0 .../notimportant/MainActivity.java | 0 .../notimportant/MyAdapter.java | 4 +- .../main}/res/anim/move_left_in_activity.xml | 0 .../main}/res/anim/move_left_out_activity.xml | 0 .../main}/res/anim/move_right_in_activity.xml | 0 .../res/anim/move_right_out_activity.xml | 0 .../main}/res/drawable-hdpi/ic_launcher.png | Bin .../{ => src/main}/res/drawable-hdpi/star.png | Bin .../main}/res/drawable-mdpi/ic_launcher.png | Bin .../main}/res/drawable-nodpi/marker2.png | Bin .../main}/res/drawable-nodpi/radar_marker.png | Bin .../main}/res/drawable-xhdpi/ic_launcher.png | Bin .../main}/res/drawable-xxhdpi/ic_launcher.png | Bin .../{ => src/main}/res/drawable/fade_red.xml | 0 .../res/layout/activity_age_distribution.xml | 0 .../res/layout/activity_awesomedesign.xml | 0 .../main}/res/layout/activity_barchart.xml | 0 .../layout/activity_barchart_noseekbar.xml | 0 .../res/layout/activity_barchart_sinus.xml | 0 .../main}/res/layout/activity_bubblechart.xml | 0 .../main}/res/layout/activity_candlechart.xml | 0 .../res/layout/activity_colored_lines.xml | 0 .../main}/res/layout/activity_combined.xml | 0 .../main}/res/layout/activity_draw_chart.xml | 0 .../layout/activity_horizontalbarchart.xml | 0 .../main}/res/layout/activity_linechart.xml | 0 .../layout/activity_linechart_noseekbar.xml | 0 .../res/layout/activity_linechart_time.xml | 0 .../res/layout/activity_listview_chart.xml | 0 .../main}/res/layout/activity_main.xml | 0 .../layout/activity_performance_linechart.xml | 0 .../main}/res/layout/activity_piechart.xml | 0 .../res/layout/activity_piechart_half.xml | 0 .../main}/res/layout/activity_radarchart.xml | 0 .../layout/activity_realtime_linechart.xml | 0 .../res/layout/activity_scatterchart.xml | 0 .../main}/res/layout/activity_scrollview.xml | 0 .../main}/res/layout/custom_marker_view.xml | 0 .../main}/res/layout/frag_simple_bar.xml | 0 .../main}/res/layout/frag_simple_line.xml | 0 .../main}/res/layout/frag_simple_pie.xml | 0 .../main}/res/layout/frag_simple_scatter.xml | 0 .../{ => src/main}/res/layout/list_item.xml | 0 .../main}/res/layout/list_item_barchart.xml | 0 .../main}/res/layout/list_item_linechart.xml | 0 .../main}/res/layout/list_item_piechart.xml | 0 .../main}/res/layout/list_item_section.xml | 0 .../main}/res/layout/radar_markerview.xml | 0 .../{ => src/main}/res/menu/bar.xml | 0 .../{ => src/main}/res/menu/bubble.xml | 0 .../{ => src/main}/res/menu/candle.xml | 0 .../{ => src/main}/res/menu/combined.xml | 0 .../{ => src/main}/res/menu/draw.xml | 0 .../{ => src/main}/res/menu/dynamical.xml | 0 .../{ => src/main}/res/menu/line.xml | 0 .../{ => src/main}/res/menu/main.xml | 0 .../{ => src/main}/res/menu/only_github.xml | 0 .../{ => src/main}/res/menu/pie.xml | 0 .../{ => src/main}/res/menu/radar.xml | 0 .../{ => src/main}/res/menu/realtime.xml | 0 .../{ => src/main}/res/menu/scatter.xml | 0 .../{ => src/main}/res/values/strings.xml | 1 - .../{ => src/main}/res/values/styles.xml | 0 ...springsource.ide.eclipse.gradle.core.prefs | 4 - MPChartLib/build.gradle | 26 +-- MPChartLib/proguard-project.txt | 20 -- MPChartLib/project.properties | 15 -- README.md | 55 +++-- build.gradle | 3 +- 173 files changed, 71 insertions(+), 1576 deletions(-) delete mode 100644 .settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs delete mode 100644 MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs delete mode 100644 MPChartExample/proguard-project.txt create mode 100644 MPChartExample/proguard-rules.pro delete mode 100644 MPChartExample/project.properties delete mode 100644 MPChartExample/res/layout/activity_bubblechart_noseekbar.xml delete mode 100644 MPChartExample/res/layout/activity_candlechart_noseekbar.xml delete mode 100644 MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml delete mode 100644 MPChartExample/res/layout/activity_piechart_noseekbar.xml delete mode 100644 MPChartExample/res/layout/activity_realm_wiki.xml delete mode 100644 MPChartExample/res/layout/activity_scatterchart_noseekbar.xml delete mode 100644 MPChartExample/res/menu/realm.xml delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java delete mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java rename MPChartExample/{ => src/main}/AndroidManifest.xml (68%) rename MPChartExample/{ => src/main}/assets/OpenSans-Bold.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-BoldItalic.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-ExtraBold.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-ExtraBoldItalic.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-Italic.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-Light.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-LightItalic.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-Regular.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-Semibold.ttf (100%) rename MPChartExample/{ => src/main}/assets/OpenSans-SemiboldItalic.ttf (100%) rename MPChartExample/{ => src/main}/assets/cosine.txt (100%) rename MPChartExample/{ => src/main}/assets/hugecosine.txt (100%) rename MPChartExample/{ => src/main}/assets/hugesine.txt (100%) rename MPChartExample/{ => src/main}/assets/n.txt (100%) rename MPChartExample/{ => src/main}/assets/nlogn.txt (100%) rename MPChartExample/{ => src/main}/assets/othersine.txt (100%) rename MPChartExample/{ => src/main}/assets/sine.txt (100%) rename MPChartExample/{ => src/main}/assets/square.txt (100%) rename MPChartExample/{ => src/main}/assets/stacked_bars.txt (100%) rename MPChartExample/{ => src/main}/assets/three.txt (100%) rename MPChartExample/{ => src/main}/ic_launcher-web.png (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/BarChartActivity.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java (98%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/LineChartTime.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/PieChartActivity.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java (99%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java (73%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java (100%) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java (93%) rename MPChartExample/{ => src/main}/res/anim/move_left_in_activity.xml (100%) rename MPChartExample/{ => src/main}/res/anim/move_left_out_activity.xml (100%) rename MPChartExample/{ => src/main}/res/anim/move_right_in_activity.xml (100%) rename MPChartExample/{ => src/main}/res/anim/move_right_out_activity.xml (100%) rename MPChartExample/{ => src/main}/res/drawable-hdpi/ic_launcher.png (100%) rename MPChartExample/{ => src/main}/res/drawable-hdpi/star.png (100%) rename MPChartExample/{ => src/main}/res/drawable-mdpi/ic_launcher.png (100%) rename MPChartExample/{ => src/main}/res/drawable-nodpi/marker2.png (100%) rename MPChartExample/{ => src/main}/res/drawable-nodpi/radar_marker.png (100%) rename MPChartExample/{ => src/main}/res/drawable-xhdpi/ic_launcher.png (100%) rename MPChartExample/{ => src/main}/res/drawable-xxhdpi/ic_launcher.png (100%) rename MPChartExample/{ => src/main}/res/drawable/fade_red.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_age_distribution.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_awesomedesign.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_barchart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_barchart_noseekbar.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_barchart_sinus.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_bubblechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_candlechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_colored_lines.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_combined.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_draw_chart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_horizontalbarchart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_linechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_linechart_noseekbar.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_linechart_time.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_listview_chart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_main.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_performance_linechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_piechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_piechart_half.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_radarchart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_realtime_linechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_scatterchart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/activity_scrollview.xml (100%) rename MPChartExample/{ => src/main}/res/layout/custom_marker_view.xml (100%) rename MPChartExample/{ => src/main}/res/layout/frag_simple_bar.xml (100%) rename MPChartExample/{ => src/main}/res/layout/frag_simple_line.xml (100%) rename MPChartExample/{ => src/main}/res/layout/frag_simple_pie.xml (100%) rename MPChartExample/{ => src/main}/res/layout/frag_simple_scatter.xml (100%) rename MPChartExample/{ => src/main}/res/layout/list_item.xml (100%) rename MPChartExample/{ => src/main}/res/layout/list_item_barchart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/list_item_linechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/list_item_piechart.xml (100%) rename MPChartExample/{ => src/main}/res/layout/list_item_section.xml (100%) rename MPChartExample/{ => src/main}/res/layout/radar_markerview.xml (100%) rename MPChartExample/{ => src/main}/res/menu/bar.xml (100%) rename MPChartExample/{ => src/main}/res/menu/bubble.xml (100%) rename MPChartExample/{ => src/main}/res/menu/candle.xml (100%) rename MPChartExample/{ => src/main}/res/menu/combined.xml (100%) rename MPChartExample/{ => src/main}/res/menu/draw.xml (100%) rename MPChartExample/{ => src/main}/res/menu/dynamical.xml (100%) rename MPChartExample/{ => src/main}/res/menu/line.xml (100%) rename MPChartExample/{ => src/main}/res/menu/main.xml (100%) rename MPChartExample/{ => src/main}/res/menu/only_github.xml (100%) rename MPChartExample/{ => src/main}/res/menu/pie.xml (100%) rename MPChartExample/{ => src/main}/res/menu/radar.xml (100%) rename MPChartExample/{ => src/main}/res/menu/realtime.xml (100%) rename MPChartExample/{ => src/main}/res/menu/scatter.xml (100%) rename MPChartExample/{ => src/main}/res/values/strings.xml (97%) rename MPChartExample/{ => src/main}/res/values/styles.xml (100%) delete mode 100644 MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs delete mode 100644 MPChartLib/proguard-project.txt delete mode 100644 MPChartLib/project.properties diff --git a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index 9383f623c6..0000000000 --- a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -build.family.org.gradle.tooling.model.eclipse.HierarchicalEclipseProject=;MPChartExample;MPChartLib; -org.springsource.ide.eclipse.gradle.rootprojectloc= diff --git a/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index be975eb2db..0000000000 --- a/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 2856bc0109..647aca2b51 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,5 +1,4 @@ apply plugin: 'com.android.application' -apply plugin: 'realm-android' android { compileSdkVersion 28 @@ -10,15 +9,6 @@ android { versionCode 56 versionName '3.0.3' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - - sourceSets { - main { - java.srcDirs = ['src'] - res.srcDirs = ['res'] - assets.srcDirs = ['assets'] - manifest.srcFile 'AndroidManifest.xml' - } - } } buildTypes { @@ -27,25 +17,10 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - - lintOptions { - abortOnError false - } } dependencies { implementation "androidx.appcompat:appcompat:1.0.0" implementation 'com.google.android.material:material:1.0.0' - //implementation "androidx.legacy:legacy-support-v4:1.0.0" - //implementation "androidx.legacy:legacy-support-v13:1.0.0" - //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - implementation 'com.github.PhilJay:MPAndroidChart-Realm:v2.0.2@aar' implementation project(':MPChartLib') } - -repositories { - maven { url "https://jitpack.io" } - maven { // this is for realm-db - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } -} diff --git a/MPChartExample/proguard-project.txt b/MPChartExample/proguard-project.txt deleted file mode 100644 index f2fe1559a2..0000000000 --- a/MPChartExample/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/MPChartExample/proguard-rules.pro b/MPChartExample/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/MPChartExample/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties deleted file mode 100644 index b32d807be6..0000000000 --- a/MPChartExample/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-23 -android.library.reference.1=../MPChartLib diff --git a/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml b/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml deleted file mode 100644 index 6251c70e74..0000000000 --- a/MPChartExample/res/layout/activity_bubblechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/layout/activity_candlechart_noseekbar.xml b/MPChartExample/res/layout/activity_candlechart_noseekbar.xml deleted file mode 100644 index 3f726c6673..0000000000 --- a/MPChartExample/res/layout/activity_candlechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml b/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml deleted file mode 100644 index c571afc967..0000000000 --- a/MPChartExample/res/layout/activity_horizontalbarchart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/layout/activity_piechart_noseekbar.xml b/MPChartExample/res/layout/activity_piechart_noseekbar.xml deleted file mode 100644 index a92eec3c48..0000000000 --- a/MPChartExample/res/layout/activity_piechart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/layout/activity_realm_wiki.xml b/MPChartExample/res/layout/activity_realm_wiki.xml deleted file mode 100644 index a9ba53fa6f..0000000000 --- a/MPChartExample/res/layout/activity_realm_wiki.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - diff --git a/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml b/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml deleted file mode 100644 index c0ea204e93..0000000000 --- a/MPChartExample/res/layout/activity_scatterchart_noseekbar.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/MPChartExample/res/menu/realm.xml b/MPChartExample/res/menu/realm.xml deleted file mode 100644 index ce149bef91..0000000000 --- a/MPChartExample/res/menu/realm.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java deleted file mode 100644 index 7a8584f8ef..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - - -import io.realm.RealmList; -import io.realm.RealmObject; - -/** - * Demo class that encapsulates data stored in realm.io database. - * This class represents data suitable for all chart-types. - */ -@SuppressWarnings("unused") -public class RealmDemoData extends RealmObject { - - private float yValue; - private float xValue; - - private float open, close, high, low; - - private float bubbleSize; - - private RealmList stackValues; - - private String someStringField; - - /** - * label for pie entries - */ - private String label; - - public RealmDemoData() {} - - public RealmDemoData(float xValue, float yValue) { - this.xValue = xValue; - this.yValue = yValue; - } - - /** - * Constructor for stacked bars. - * - * @param xValue x position for bars - * @param stackValues values of bars in the stack - */ - public RealmDemoData(float xValue, float[] stackValues) { - this.xValue = xValue; - this.stackValues = new RealmList<>(); - - for (float val : stackValues) { - this.stackValues.add(new RealmFloat(val)); - } - } - - /** - * Constructor for candles. - * - * @param xValue x position of candle - * @param high high value for candle - * @param low low value for candle - * @param open open value for candle - * @param close close value for candle - */ - public RealmDemoData(float xValue, float high, float low, float open, float close) { - this.yValue = (high + low) / 2f; - this.high = high; - this.low = low; - this.open = open; - this.close = close; - this.xValue = xValue; - } - - /** - * Constructor for bubbles. - * - * @param xValue x position of bubble - * @param yValue y position of bubble - * @param bubbleSize size of bubble - */ - public RealmDemoData(float xValue, float yValue, float bubbleSize) { - this.xValue = xValue; - this.yValue = yValue; - this.bubbleSize = bubbleSize; - } - - /** - * Constructor for pie chart. - * - * @param yValue size of pie slice - * @param label label for pie slice - */ - public RealmDemoData(float yValue, String label) { - this.yValue = yValue; - this.label = label; - } - - public float getYValue() { - return yValue; - } - - public void setYValue(float yValue) { - this.yValue = yValue; - } - - public float getXValue() { - return xValue; - } - - public void setXValue(float xValue) { - this.xValue = xValue; - } - - public RealmList getStackValues() { - return stackValues; - } - - public void setStackValues(RealmList stackValues) { - this.stackValues = stackValues; - } - - public float getOpen() { - return open; - } - - public void setOpen(float open) { - this.open = open; - } - - public float getClose() { - return close; - } - - public void setClose(float close) { - this.close = close; - } - - public float getHigh() { - return high; - } - - public void setHigh(float high) { - this.high = high; - } - - public float getLow() { - return low; - } - - public void setLow(float low) { - this.low = low; - } - - public float getBubbleSize() { - return bubbleSize; - } - - public void setBubbleSize(float bubbleSize) { - this.bubbleSize = bubbleSize; - } - - public String getSomeStringField() { - return someStringField; - } - - public void setSomeStringField(String someStringField) { - this.someStringField = someStringField; - } - - public String getLabel() { - return label; - } - - public void setLabel(String label) { - this.label = label; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java deleted file mode 100644 index a8310dc9b5..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import io.realm.RealmObject; - -/** - * Created by Philipp Jahoda on 09/11/15. - */ -@SuppressWarnings("unused") -public class RealmFloat extends RealmObject { - - private float floatValue; - - public RealmFloat() { - - } - - public RealmFloat(float floatValue) { - this.floatValue = floatValue; - } - - public float getFloatValue() { - return floatValue; - } - - public void setFloatValue(float value) { - this.floatValue = value; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java deleted file mode 100644 index 690eb6cf3a..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; - -import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.charts.Chart; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.PercentFormatter; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 05/11/15. - */ -@SuppressWarnings("SameParameterValue") -public abstract class RealmBaseActivity extends DemoBase { - - protected Realm mRealm; - - protected Typeface mTf; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle("Realm.io Examples"); - } - - protected void setup(Chart chart) { - - mTf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - // no description text - chart.getDescription().setEnabled(false); - - // enable touch gestures - chart.setTouchEnabled(true); - - if (chart instanceof BarLineChartBase) { - - BarLineChartBase mChart = (BarLineChartBase) chart; - - mChart.setDrawGridBackground(false); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setTypeface(mTf); - leftAxis.setTextSize(8f); - leftAxis.setTextColor(Color.DKGRAY); - leftAxis.setValueFormatter(new PercentFormatter()); - - XAxis xAxis = mChart.getXAxis(); - xAxis.setTypeface(mTf); - xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); - xAxis.setTextSize(8f); - xAxis.setTextColor(Color.DKGRAY); - - mChart.getAxisRight().setEnabled(false); - } - } - - protected void styleData(ChartData data) { - data.setValueTypeface(mTf); - data.setValueTextSize(8f); - data.setValueTextColor(Color.DKGRAY); - data.setValueFormatter(new PercentFormatter()); - } - - @Override - protected void onResume() { - super.onResume(); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); - Realm.setDefaultConfiguration(realmConfig); - - mRealm = Realm.getDefaultInstance(); - } - - @Override - protected void onPause() { - super.onPause(); - mRealm.close(); - } - - protected void writeToDB(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 40f + (float) (Math.random() * 60f); - - RealmDemoData d = new RealmDemoData(i, value); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBStack(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float val1 = 34f + (float) (Math.random() * 12.0f); - float val2 = 34f + (float) (Math.random() * 12.0f); - float[] stack = new float[]{val1, val2, 100 - val1 - val2}; - - RealmDemoData d = new RealmDemoData(i, stack); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBCandle(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float val = (float) (Math.random() * 40) + 50f; - - float high = (float) (Math.random() * 9) + 8f; - float low = (float) (Math.random() * 9) + 8f; - - float open = (float) (Math.random() * 6) + 1f; - float close = (float) (Math.random() * 6) + 1f; - - boolean even = i % 2 == 0; - - RealmDemoData d = new RealmDemoData(i, val + high, val - low, even ? val + open : val - open, - even ? val - close : val + close); - - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBBubble(int objectCount) { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - for (int i = 0; i < objectCount; i++) { - - float value = 30f + (float) (Math.random() * 100.0); - float size = 15f + (float) (Math.random() * 20.0); - - RealmDemoData d = new RealmDemoData(i, value, size); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - protected void writeToDBPie() { - - mRealm.beginTransaction(); - - mRealm.delete(RealmDemoData.class); - - float value1 = 15f + (float) (Math.random() * 8f); - float value2 = 15f + (float) (Math.random() * 8f); - float value3 = 15f + (float) (Math.random() * 8f); - float value4 = 15f + (float) (Math.random() * 8f); - float value5 = 100f - value1 - value2 - value3 - value4; - - float[] values = new float[]{value1, value2, value3, value4, value5}; - String[] labels = new String[]{"iOS", "Android", "WP 10", "BlackBerry", "Other"}; - - for (int i = 0; i < values.length; i++) { - RealmDemoData d = new RealmDemoData(values[i], labels[i]); - mRealm.copyToRealm(d); - } - - mRealm.commitTransaction(); - } - - @Override - public void saveToGallery() { /* Intentionally left empty */ } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java deleted file mode 100644 index f7cba47340..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBar.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBar extends RealmBaseActivity { - - private BarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(20); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet<>(result, "xValue", "yValue"); // stacked entries - set.setColors(ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")); - set.setLabel("Realm BarDataSet"); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.setFitBars(true); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java deleted file mode 100644 index 3493ade94f..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityBubble.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BubbleChart; -import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.realm.implementation.RealmBubbleDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityBubble extends RealmBaseActivity { - - private BubbleChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_bubblechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getXAxis().setDrawGridLines(false); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBBubble(10); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmBubbleDataSet set = new RealmBubbleDataSet<>(result, "xValue", "yValue", "bubbleSize"); - set.setLabel("Realm BubbleDataSet"); - set.setColors(ColorTemplate.COLORFUL_COLORS, 110); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BubbleData data = new BubbleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java deleted file mode 100644 index 49d8903c6e..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityCandle.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Paint; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.CandleStickChart; -import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.realm.implementation.RealmCandleDataSet; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityCandle extends RealmBaseActivity { - - private CandleStickChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_candlechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBCandle(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmCandleDataSet set = new RealmCandleDataSet<>(result, "xValue", "high", "low", "open", "close"); - set.setLabel("Realm CandleDataSet"); - set.setShadowColor(Color.DKGRAY); - set.setShadowWidth(0.7f); - set.setDecreasingColor(Color.RED); - set.setDecreasingPaintStyle(Paint.Style.FILL); - set.setIncreasingColor(Color.rgb(122, 242, 84)); - set.setIncreasingPaintStyle(Paint.Style.STROKE); - set.setNeutralColor(Color.BLUE); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - CandleData data = new CandleData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java deleted file mode 100644 index 680ee1e83c..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ /dev/null @@ -1,74 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityHorizontalBar extends RealmBaseActivity { - - private HorizontalBarChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_horizontalbarchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMinimum(0f); - mChart.setDrawValueAboveBar(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBStack(50); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries - RealmBarDataSet set = new RealmBarDataSet<>(result, "xValue", "stackValues", "floatValue"); // stacked entries - set.setColors(ColorTemplate.rgb("#8BC34A"), ColorTemplate.rgb("#FFC107"), ColorTemplate.rgb("#9E9E9E")); - set.setLabel("Mobile OS distribution"); - set.setStackLabels(new String[]{"iOS", "Android", "Other"}); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - BarData data = new BarData(dataSets); - styleData(data); - data.setValueTextColor(Color.WHITE); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java deleted file mode 100644 index c0bbd3caf6..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityLine.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityLine extends RealmBaseActivity { - - private LineChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setAxisMaximum(150f); - mChart.getAxisLeft().setAxisMinimum(0f); - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(40); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmLineDataSet set = new RealmLineDataSet<>(result, "xValue", "yValue"); - set.setMode(LineDataSet.Mode.CUBIC_BEZIER); - set.setLabel("Realm LineDataSet"); - set.setDrawCircleHole(false); - set.setColor(ColorTemplate.rgb("#FF5722")); - set.setCircleColor(ColorTemplate.rgb("#FF5722")); - set.setLineWidth(1.8f); - set.setCircleRadius(3.6f); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - LineData data = new LineData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java deleted file mode 100644 index 46af4cda31..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityPie.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.graphics.Typeface; -import android.os.Bundle; -import android.text.SpannableString; -import android.text.style.ForegroundColorSpan; -import android.text.style.RelativeSizeSpan; -import android.text.style.StyleSpan; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.realm.implementation.RealmPieDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityPie extends RealmBaseActivity { - - private PieChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_piechart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.setCenterText(generateCenterSpannableText()); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDBPie(); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmPieDataSet set = new RealmPieDataSet<>(result, "yValue", "label"); - set.setColors(ColorTemplate.VORDIPLOM_COLORS); - set.setLabel("Example market share"); - set.setSliceSpace(2); - - // create a data object with the dataset list - PieData data = new PieData(set); - styleData(data); - data.setValueTextColor(Color.WHITE); - data.setValueTextSize(12f); - - // set data - mChart.setData(data); - mChart.animateY(1400); - } - - private SpannableString generateCenterSpannableText() { - - SpannableString s = new SpannableString("Realm.io\nmobile database"); - s.setSpan(new ForegroundColorSpan(Color.rgb(240, 115, 126)), 0, 8, 0); - s.setSpan(new RelativeSizeSpan(2.2f), 0, 8, 0); - s.setSpan(new StyleSpan(Typeface.ITALIC), 9, s.length(), 0); - s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 9, s.length(), 0); - s.setSpan(new RelativeSizeSpan(0.85f), 9, s.length(), 0); - return s; - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java deleted file mode 100644 index faef4e28bc..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityRadar.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.graphics.Color; -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.realm.implementation.RealmRadarDataSet; -import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityRadar extends RealmBaseActivity { - - private RadarChart chart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_radarchart); - - chart = findViewById(R.id.chart1); - setup(chart); - - chart.getYAxis().setEnabled(false); - chart.getXAxis().setEnabled(false); - chart.setWebAlpha(180); - chart.setWebColorInner(Color.DKGRAY); - chart.setWebColor(Color.GRAY); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(7); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - //RealmBarDataSet set = new RealmBarDataSet<>(result, "stackValues", "xIndex"); // normal entries - RealmRadarDataSet set = new RealmRadarDataSet<>(result, "yValue"); // stacked entries - set.setLabel("Realm RadarDataSet"); - set.setDrawFilled(true); - set.setColor(ColorTemplate.rgb("#009688")); - set.setFillColor(ColorTemplate.rgb("#009688")); - set.setFillAlpha(130); - set.setLineWidth(2f); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - RadarData data = new RadarData(dataSets); - styleData(data); - - // set data - chart.setData(data); - chart.animateY(1400); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java deleted file mode 100644 index 01e0151933..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityScatter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.ScatterChart; -import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.realm.implementation.RealmScatterDataSet; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmDatabaseActivityScatter extends RealmBaseActivity { - - private ScatterChart mChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_scatterchart_noseekbar); - - mChart = findViewById(R.id.chart1); - setup(mChart); - - mChart.getAxisLeft().setDrawGridLines(false); - mChart.getXAxis().setDrawGridLines(false); - mChart.setPinchZoom(true); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - // write some demo-data into the realm.io database - writeToDB(45); - - // add data to the chart - setData(); - } - - private void setData() { - - RealmResults result = mRealm.where(RealmDemoData.class).findAll(); - - RealmScatterDataSet set = new RealmScatterDataSet<>(result, "xValue", "yValue"); - set.setLabel("Realm ScatterDataSet"); - set.setScatterShapeSize(9f); - set.setColor(ColorTemplate.rgb("#CDDC39")); - set.setScatterShape(ScatterChart.ScatterShape.CIRCLE); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(set); // add the dataset - - // create a data object with the dataset list - ScatterData data = new ScatterData(dataSets); - styleData(data); - - // set data - mChart.setData(data); - mChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java deleted file mode 100644 index 674cef458e..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmMainActivity.java +++ /dev/null @@ -1,133 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.ListView; - -import com.xxmassdeveloper.mpchartexample.R; -import com.xxmassdeveloper.mpchartexample.notimportant.ContentItem; -import com.xxmassdeveloper.mpchartexample.notimportant.MyAdapter; - -import java.util.ArrayList; - -import io.realm.Realm; -import io.realm.RealmConfiguration; - -/** - * Created by Philipp Jahoda on 07/12/15. - */ -public class RealmMainActivity extends Activity implements AdapterView.OnItemClickListener { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_main); - - setTitle("Realm.io Examples"); - - ArrayList objects = new ArrayList<>(); - - objects.add(new ContentItem("Line Chart", "Creating a LineChart with Realm.io database")); - objects.add(new ContentItem("Bar Chart", - "Creating a BarChart with Realm.io database")); - objects.add(new ContentItem("Horizontal Bar Chart", - "Creating a HorizontalBarChart with Realm.io database")); - objects.add(new ContentItem("Scatter Chart", - "Creating a ScatterChart with Realm.io database")); - objects.add(new ContentItem("Candle Stick Chart", "Creating a CandleStickChart with Realm.io database")); - objects.add(new ContentItem("Bubble Chart", "Creating a BubbleChart with Realm.io database")); - objects.add(new ContentItem("Pie Chart", "Creating a PieChart with Realm.io database")); - objects.add(new ContentItem("Radar Chart", "Creating a RadarChart with Realm.io database")); - objects.add(new ContentItem("Realm Wiki", "This is the code related to the wiki entry about realm.io on the MPAndroidChart github page.")); - - MyAdapter adapter = new MyAdapter(this, objects); - - ListView lv = findViewById(R.id.listView1); - lv.setAdapter(adapter); - - lv.setOnItemClickListener(this); - - Realm.init(this); - - // Create a RealmConfiguration that saves the Realm file in the app's "files" directory. - RealmConfiguration realmConfig = new RealmConfiguration.Builder().build(); - Realm.setDefaultConfiguration(realmConfig); - - Realm realm = Realm.getDefaultInstance(); - realm.beginTransaction(); - realm.deleteAll(); - realm.commitTransaction(); - } - - @Override - public void onItemClick(AdapterView av, View v, int pos, long arg3) { - - Intent i; - - switch (pos) { - case 0: - i = new Intent(this, RealmDatabaseActivityLine.class); - startActivity(i); - break; - case 1: - i = new Intent(this, RealmDatabaseActivityBar.class); - startActivity(i); - break; - case 2: - i = new Intent(this, RealmDatabaseActivityHorizontalBar.class); - startActivity(i); - break; - case 3: - i = new Intent(this, RealmDatabaseActivityScatter.class); - startActivity(i); - break; - case 4: - i = new Intent(this, RealmDatabaseActivityCandle.class); - startActivity(i); - break; - case 5: - i = new Intent(this, RealmDatabaseActivityBubble.class); - startActivity(i); - break; - case 6: - i = new Intent(this, RealmDatabaseActivityPie.class); - startActivity(i); - break; - case 7: - i = new Intent(this, RealmDatabaseActivityRadar.class); - startActivity(i); - break; - case 8: - i = new Intent(this, RealmWikiExample.class); - startActivity(i); - break; - } - - overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.realm, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - Intent i = new Intent(Intent.ACTION_VIEW); - i.setData(Uri.parse("https://realm.io")); - startActivity(i); - - return super.onOptionsItemSelected(item); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java deleted file mode 100644 index 35212728cd..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ /dev/null @@ -1,134 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - -import android.os.Bundle; -import android.view.WindowManager; - -import com.github.mikephil.charting.animation.Easing; -import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.R; - -import java.util.ArrayList; - -import io.realm.RealmResults; - -/** - * Created by Philipp Jahoda on 18/12/15. - */ -public class RealmWikiExample extends RealmBaseActivity { - - private LineChart lineChart; - private BarChart barChart; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_realm_wiki); - - lineChart = findViewById(R.id.lineChart); - barChart = findViewById(R.id.barChart); - setup(lineChart); - setup(barChart); - - lineChart.setExtraBottomOffset(5f); - barChart.setExtraBottomOffset(5f); - - lineChart.getAxisLeft().setDrawGridLines(false); - lineChart.getXAxis().setDrawGridLines(false); - lineChart.getXAxis().setLabelCount(5); - lineChart.getXAxis().setGranularity(1f); - barChart.getAxisLeft().setDrawGridLines(false); - barChart.getXAxis().setDrawGridLines(false); - barChart.getXAxis().setLabelCount(5); - barChart.getXAxis().setGranularity(1f); - } - - @Override - protected void onResume() { - super.onResume(); // setup realm - - mRealm.beginTransaction(); - - // write some demo-data into the realm.io database - Score score1 = new Score(100f, 0f, "Peter"); - mRealm.copyToRealm(score1); - Score score2 = new Score(110f, 1f, "Lisa"); - mRealm.copyToRealm(score2); - Score score3 = new Score(130f, 2f, "Dennis"); - mRealm.copyToRealm(score3); - Score score4 = new Score(70f, 3f, "Luke"); - mRealm.copyToRealm(score4); - Score score5 = new Score(80f, 4f, "Sarah"); - mRealm.copyToRealm(score5); - - mRealm.commitTransaction(); - - // add data to the chart - setData(); - } - - private void setData() { - - // LINE-CHART - final RealmResults results = mRealm.where(Score.class).findAll(); - - - IAxisValueFormatter formatter = new IAxisValueFormatter() { - @Override - public String getFormattedValue(float value, AxisBase axis) { - Score result = results.get((int) value); - return result != null ? result.playerName : ""; - } - }; - - lineChart.getXAxis().setValueFormatter(formatter); - barChart.getXAxis().setValueFormatter(formatter); - - RealmLineDataSet lineDataSet = new RealmLineDataSet<>(results, "scoreNr", "totalScore"); - lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); - lineDataSet.setLabel("Result Scores"); - lineDataSet.setDrawCircleHole(false); - lineDataSet.setColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setCircleColor(ColorTemplate.rgb("#FF5722")); - lineDataSet.setLineWidth(1.8f); - lineDataSet.setCircleRadius(3.6f); - - ArrayList dataSets = new ArrayList<>(); - dataSets.add(lineDataSet); - - LineData lineData = new LineData(dataSets); - styleData(lineData); - - // set data - lineChart.setData(lineData); - lineChart.animateY(1400, Easing.EaseInOutQuart); - - - // BAR-CHART - RealmBarDataSet barDataSet = new RealmBarDataSet<>(results, "scoreNr", "totalScore"); - barDataSet.setColors(ColorTemplate.rgb("#FF5722"), ColorTemplate.rgb("#03A9F4")); - barDataSet.setLabel("Realm BarDataSet"); - - ArrayList barDataSets = new ArrayList<>(); - barDataSets.add(barDataSet); - - BarData barData = new BarData(barDataSets); - styleData(barData); - - barChart.setData(barData); - barChart.setFitBars(true); - barChart.animateY(1400, Easing.EaseInOutQuart); - } -} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java deleted file mode 100644 index 0d1f806616..0000000000 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/Score.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.realm; - - -import io.realm.RealmObject; - -/** - * our data object - */ -@SuppressWarnings({"WeakerAccess", "unused"}) -public class Score extends RealmObject { - - public float totalScore; - - public float scoreNr; - - public String playerName; - - public Score() {} - - public Score(float totalScore, float scoreNr, String playerName) { - this.scoreNr = scoreNr; - this.playerName = playerName; - this.totalScore = totalScore; - } - -} diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/src/main/AndroidManifest.xml similarity index 68% rename from MPChartExample/AndroidManifest.xml rename to MPChartExample/src/main/AndroidManifest.xml index 292e0933a2..28c55b89b2 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/src/main/AndroidManifest.xml @@ -19,9 +19,9 @@ - + - + @@ -31,7 +31,7 @@ - + @@ -42,25 +42,15 @@ - - - - - - - - - - - - - + + + diff --git a/MPChartExample/assets/OpenSans-Bold.ttf b/MPChartExample/src/main/assets/OpenSans-Bold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Bold.ttf rename to MPChartExample/src/main/assets/OpenSans-Bold.ttf diff --git a/MPChartExample/assets/OpenSans-BoldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-BoldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-BoldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-BoldItalic.ttf diff --git a/MPChartExample/assets/OpenSans-ExtraBold.ttf b/MPChartExample/src/main/assets/OpenSans-ExtraBold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-ExtraBold.ttf rename to MPChartExample/src/main/assets/OpenSans-ExtraBold.ttf diff --git a/MPChartExample/assets/OpenSans-ExtraBoldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-ExtraBoldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-ExtraBoldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-ExtraBoldItalic.ttf diff --git a/MPChartExample/assets/OpenSans-Italic.ttf b/MPChartExample/src/main/assets/OpenSans-Italic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Italic.ttf rename to MPChartExample/src/main/assets/OpenSans-Italic.ttf diff --git a/MPChartExample/assets/OpenSans-Light.ttf b/MPChartExample/src/main/assets/OpenSans-Light.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Light.ttf rename to MPChartExample/src/main/assets/OpenSans-Light.ttf diff --git a/MPChartExample/assets/OpenSans-LightItalic.ttf b/MPChartExample/src/main/assets/OpenSans-LightItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-LightItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-LightItalic.ttf diff --git a/MPChartExample/assets/OpenSans-Regular.ttf b/MPChartExample/src/main/assets/OpenSans-Regular.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Regular.ttf rename to MPChartExample/src/main/assets/OpenSans-Regular.ttf diff --git a/MPChartExample/assets/OpenSans-Semibold.ttf b/MPChartExample/src/main/assets/OpenSans-Semibold.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-Semibold.ttf rename to MPChartExample/src/main/assets/OpenSans-Semibold.ttf diff --git a/MPChartExample/assets/OpenSans-SemiboldItalic.ttf b/MPChartExample/src/main/assets/OpenSans-SemiboldItalic.ttf similarity index 100% rename from MPChartExample/assets/OpenSans-SemiboldItalic.ttf rename to MPChartExample/src/main/assets/OpenSans-SemiboldItalic.ttf diff --git a/MPChartExample/assets/cosine.txt b/MPChartExample/src/main/assets/cosine.txt similarity index 100% rename from MPChartExample/assets/cosine.txt rename to MPChartExample/src/main/assets/cosine.txt diff --git a/MPChartExample/assets/hugecosine.txt b/MPChartExample/src/main/assets/hugecosine.txt similarity index 100% rename from MPChartExample/assets/hugecosine.txt rename to MPChartExample/src/main/assets/hugecosine.txt diff --git a/MPChartExample/assets/hugesine.txt b/MPChartExample/src/main/assets/hugesine.txt similarity index 100% rename from MPChartExample/assets/hugesine.txt rename to MPChartExample/src/main/assets/hugesine.txt diff --git a/MPChartExample/assets/n.txt b/MPChartExample/src/main/assets/n.txt similarity index 100% rename from MPChartExample/assets/n.txt rename to MPChartExample/src/main/assets/n.txt diff --git a/MPChartExample/assets/nlogn.txt b/MPChartExample/src/main/assets/nlogn.txt similarity index 100% rename from MPChartExample/assets/nlogn.txt rename to MPChartExample/src/main/assets/nlogn.txt diff --git a/MPChartExample/assets/othersine.txt b/MPChartExample/src/main/assets/othersine.txt similarity index 100% rename from MPChartExample/assets/othersine.txt rename to MPChartExample/src/main/assets/othersine.txt diff --git a/MPChartExample/assets/sine.txt b/MPChartExample/src/main/assets/sine.txt similarity index 100% rename from MPChartExample/assets/sine.txt rename to MPChartExample/src/main/assets/sine.txt diff --git a/MPChartExample/assets/square.txt b/MPChartExample/src/main/assets/square.txt similarity index 100% rename from MPChartExample/assets/square.txt rename to MPChartExample/src/main/assets/square.txt diff --git a/MPChartExample/assets/stacked_bars.txt b/MPChartExample/src/main/assets/stacked_bars.txt similarity index 100% rename from MPChartExample/assets/stacked_bars.txt rename to MPChartExample/src/main/assets/stacked_bars.txt diff --git a/MPChartExample/assets/three.txt b/MPChartExample/src/main/assets/three.txt similarity index 100% rename from MPChartExample/assets/three.txt rename to MPChartExample/src/main/assets/three.txt diff --git a/MPChartExample/ic_launcher-web.png b/MPChartExample/src/main/ic_launcher-web.png similarity index 100% rename from MPChartExample/ic_launcher-web.png rename to MPChartExample/src/main/ic_launcher-web.png diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 865bc92ea2..77875972c3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -131,7 +131,6 @@ protected void onCreate(Bundle savedInstanceState) { // setting data seekBarY.setProgress(50); seekBarX.setProgress(12); - setData(12, 50); // chart.setDrawLegend(false); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 7f795046e3..075af0edbc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -57,6 +57,7 @@ protected void onCreate(Bundle savedInstanceState) { tvY = findViewById(R.id.tvYMax); seekBarX = findViewById(R.id.seekBar1); + seekBarX.setMax(50); seekBarX.setOnSeekBarChangeListener(this); seekBarY = findViewById(R.id.seekBar2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index f30732e6eb..996e088f43 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -93,7 +93,6 @@ protected void onCreate(Bundle savedInstanceState) { seekBarX.setProgress(45); seekBarY.setProgress(100); - setData(45, 100); chart.getLegend().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/FilledLineActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HalfPieChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index f93baaa376..27f7f29627 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -102,7 +102,6 @@ protected void onCreate(Bundle savedInstanceState) { yr.setAxisMinimum(0f); // this replaces setStartAtZero(true) // yr.setInverted(true); - setData(12, 50); chart.setFitBars(true); chart.animateY(2500); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java similarity index 98% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 999d17e7b5..08983710f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -56,9 +56,6 @@ protected void onCreate(Bundle savedInstanceState) { seekBarX = findViewById(R.id.seekBar1); seekBarY = findViewById(R.id.seekBar2); - seekBarX.setProgress(45); - seekBarY.setProgress(100); - seekBarY.setOnSeekBarChangeListener(this); seekBarX.setOnSeekBarChangeListener(this); @@ -100,7 +97,8 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setEnabled(false); // add data - setData(25, 50); + seekBarX.setProgress(25); + seekBarY.setProgress(50); // // restrain the maximum scale-out factor // chart.setScaleMinima(3f, 3f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 60cab539a9..9e0c98f89b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -91,7 +91,6 @@ protected void onCreate(Bundle savedInstanceState) { // add data seekBarX.setProgress(20); seekBarY.setProgress(30); - setData(20, 30); chart.animateX(1500); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 47d0a79046..212b90ff87 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -77,8 +77,6 @@ protected void onCreate(Bundle savedInstanceState) { // add data seekBarX.setProgress(100); - setData(100, 30); - chart.invalidate(); // get the legend (only possible after setting data) Legend l = chart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index e22b828d56..3c94e2ad5d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -97,7 +97,6 @@ protected void onCreate(Bundle savedInstanceState) { seekBarX.setProgress(4); seekBarY.setProgress(10); - setData(4, 100); chart.animateY(1400, Easing.EaseInOutQuad); // chart.spin(2000, 0, 360); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java similarity index 99% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index ebeb43e9cf..dc26f48297 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -102,7 +102,6 @@ protected void onCreate(Bundle savedInstanceState) { seekBarX.setProgress(4); seekBarY.setProgress(100); - setData(4, 100); chart.animateY(1400, Easing.EaseInOutQuad); // chart.spin(2000, 0, 360); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/CustomScatterShapeRenderer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/RadarMarkerView.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleChartDemo.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/ChartItem.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java similarity index 73% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java index a6625bae9a..f322090d72 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/ContentItem.java @@ -3,19 +3,19 @@ /** * Created by Philipp Jahoda on 07/12/15. */ -public class ContentItem { +class ContentItem { final String name; final String desc; boolean isSection = false; - public ContentItem(String n) { + ContentItem(String n) { name = n; desc = ""; isSection = true; } - public ContentItem(String n, String d) { + ContentItem(String n, String d) { name = n; desc = d; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/DemoBase.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java similarity index 100% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java similarity index 93% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java index 4ddac475bc..9a22b51c9a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MyAdapter.java @@ -18,12 +18,12 @@ /** * Created by Philipp Jahoda on 07/12/15. */ -public class MyAdapter extends ArrayAdapter { +class MyAdapter extends ArrayAdapter { private final Typeface mTypeFaceLight; private final Typeface mTypeFaceRegular; - public MyAdapter(Context context, List objects) { + MyAdapter(Context context, List objects) { super(context, 0, objects); mTypeFaceLight = Typeface.createFromAsset(context.getAssets(), "OpenSans-Light.ttf"); diff --git a/MPChartExample/res/anim/move_left_in_activity.xml b/MPChartExample/src/main/res/anim/move_left_in_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_left_in_activity.xml rename to MPChartExample/src/main/res/anim/move_left_in_activity.xml diff --git a/MPChartExample/res/anim/move_left_out_activity.xml b/MPChartExample/src/main/res/anim/move_left_out_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_left_out_activity.xml rename to MPChartExample/src/main/res/anim/move_left_out_activity.xml diff --git a/MPChartExample/res/anim/move_right_in_activity.xml b/MPChartExample/src/main/res/anim/move_right_in_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_right_in_activity.xml rename to MPChartExample/src/main/res/anim/move_right_in_activity.xml diff --git a/MPChartExample/res/anim/move_right_out_activity.xml b/MPChartExample/src/main/res/anim/move_right_out_activity.xml similarity index 100% rename from MPChartExample/res/anim/move_right_out_activity.xml rename to MPChartExample/src/main/res/anim/move_right_out_activity.xml diff --git a/MPChartExample/res/drawable-hdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-hdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-hdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-hdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-hdpi/star.png b/MPChartExample/src/main/res/drawable-hdpi/star.png similarity index 100% rename from MPChartExample/res/drawable-hdpi/star.png rename to MPChartExample/src/main/res/drawable-hdpi/star.png diff --git a/MPChartExample/res/drawable-mdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-mdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-mdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-mdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-nodpi/marker2.png b/MPChartExample/src/main/res/drawable-nodpi/marker2.png similarity index 100% rename from MPChartExample/res/drawable-nodpi/marker2.png rename to MPChartExample/src/main/res/drawable-nodpi/marker2.png diff --git a/MPChartExample/res/drawable-nodpi/radar_marker.png b/MPChartExample/src/main/res/drawable-nodpi/radar_marker.png similarity index 100% rename from MPChartExample/res/drawable-nodpi/radar_marker.png rename to MPChartExample/src/main/res/drawable-nodpi/radar_marker.png diff --git a/MPChartExample/res/drawable-xhdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-xhdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-xhdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-xhdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable-xxhdpi/ic_launcher.png b/MPChartExample/src/main/res/drawable-xxhdpi/ic_launcher.png similarity index 100% rename from MPChartExample/res/drawable-xxhdpi/ic_launcher.png rename to MPChartExample/src/main/res/drawable-xxhdpi/ic_launcher.png diff --git a/MPChartExample/res/drawable/fade_red.xml b/MPChartExample/src/main/res/drawable/fade_red.xml similarity index 100% rename from MPChartExample/res/drawable/fade_red.xml rename to MPChartExample/src/main/res/drawable/fade_red.xml diff --git a/MPChartExample/res/layout/activity_age_distribution.xml b/MPChartExample/src/main/res/layout/activity_age_distribution.xml similarity index 100% rename from MPChartExample/res/layout/activity_age_distribution.xml rename to MPChartExample/src/main/res/layout/activity_age_distribution.xml diff --git a/MPChartExample/res/layout/activity_awesomedesign.xml b/MPChartExample/src/main/res/layout/activity_awesomedesign.xml similarity index 100% rename from MPChartExample/res/layout/activity_awesomedesign.xml rename to MPChartExample/src/main/res/layout/activity_awesomedesign.xml diff --git a/MPChartExample/res/layout/activity_barchart.xml b/MPChartExample/src/main/res/layout/activity_barchart.xml similarity index 100% rename from MPChartExample/res/layout/activity_barchart.xml rename to MPChartExample/src/main/res/layout/activity_barchart.xml diff --git a/MPChartExample/res/layout/activity_barchart_noseekbar.xml b/MPChartExample/src/main/res/layout/activity_barchart_noseekbar.xml similarity index 100% rename from MPChartExample/res/layout/activity_barchart_noseekbar.xml rename to MPChartExample/src/main/res/layout/activity_barchart_noseekbar.xml diff --git a/MPChartExample/res/layout/activity_barchart_sinus.xml b/MPChartExample/src/main/res/layout/activity_barchart_sinus.xml similarity index 100% rename from MPChartExample/res/layout/activity_barchart_sinus.xml rename to MPChartExample/src/main/res/layout/activity_barchart_sinus.xml diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/src/main/res/layout/activity_bubblechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_bubblechart.xml rename to MPChartExample/src/main/res/layout/activity_bubblechart.xml diff --git a/MPChartExample/res/layout/activity_candlechart.xml b/MPChartExample/src/main/res/layout/activity_candlechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_candlechart.xml rename to MPChartExample/src/main/res/layout/activity_candlechart.xml diff --git a/MPChartExample/res/layout/activity_colored_lines.xml b/MPChartExample/src/main/res/layout/activity_colored_lines.xml similarity index 100% rename from MPChartExample/res/layout/activity_colored_lines.xml rename to MPChartExample/src/main/res/layout/activity_colored_lines.xml diff --git a/MPChartExample/res/layout/activity_combined.xml b/MPChartExample/src/main/res/layout/activity_combined.xml similarity index 100% rename from MPChartExample/res/layout/activity_combined.xml rename to MPChartExample/src/main/res/layout/activity_combined.xml diff --git a/MPChartExample/res/layout/activity_draw_chart.xml b/MPChartExample/src/main/res/layout/activity_draw_chart.xml similarity index 100% rename from MPChartExample/res/layout/activity_draw_chart.xml rename to MPChartExample/src/main/res/layout/activity_draw_chart.xml diff --git a/MPChartExample/res/layout/activity_horizontalbarchart.xml b/MPChartExample/src/main/res/layout/activity_horizontalbarchart.xml similarity index 100% rename from MPChartExample/res/layout/activity_horizontalbarchart.xml rename to MPChartExample/src/main/res/layout/activity_horizontalbarchart.xml diff --git a/MPChartExample/res/layout/activity_linechart.xml b/MPChartExample/src/main/res/layout/activity_linechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_linechart.xml rename to MPChartExample/src/main/res/layout/activity_linechart.xml diff --git a/MPChartExample/res/layout/activity_linechart_noseekbar.xml b/MPChartExample/src/main/res/layout/activity_linechart_noseekbar.xml similarity index 100% rename from MPChartExample/res/layout/activity_linechart_noseekbar.xml rename to MPChartExample/src/main/res/layout/activity_linechart_noseekbar.xml diff --git a/MPChartExample/res/layout/activity_linechart_time.xml b/MPChartExample/src/main/res/layout/activity_linechart_time.xml similarity index 100% rename from MPChartExample/res/layout/activity_linechart_time.xml rename to MPChartExample/src/main/res/layout/activity_linechart_time.xml diff --git a/MPChartExample/res/layout/activity_listview_chart.xml b/MPChartExample/src/main/res/layout/activity_listview_chart.xml similarity index 100% rename from MPChartExample/res/layout/activity_listview_chart.xml rename to MPChartExample/src/main/res/layout/activity_listview_chart.xml diff --git a/MPChartExample/res/layout/activity_main.xml b/MPChartExample/src/main/res/layout/activity_main.xml similarity index 100% rename from MPChartExample/res/layout/activity_main.xml rename to MPChartExample/src/main/res/layout/activity_main.xml diff --git a/MPChartExample/res/layout/activity_performance_linechart.xml b/MPChartExample/src/main/res/layout/activity_performance_linechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_performance_linechart.xml rename to MPChartExample/src/main/res/layout/activity_performance_linechart.xml diff --git a/MPChartExample/res/layout/activity_piechart.xml b/MPChartExample/src/main/res/layout/activity_piechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_piechart.xml rename to MPChartExample/src/main/res/layout/activity_piechart.xml diff --git a/MPChartExample/res/layout/activity_piechart_half.xml b/MPChartExample/src/main/res/layout/activity_piechart_half.xml similarity index 100% rename from MPChartExample/res/layout/activity_piechart_half.xml rename to MPChartExample/src/main/res/layout/activity_piechart_half.xml diff --git a/MPChartExample/res/layout/activity_radarchart.xml b/MPChartExample/src/main/res/layout/activity_radarchart.xml similarity index 100% rename from MPChartExample/res/layout/activity_radarchart.xml rename to MPChartExample/src/main/res/layout/activity_radarchart.xml diff --git a/MPChartExample/res/layout/activity_realtime_linechart.xml b/MPChartExample/src/main/res/layout/activity_realtime_linechart.xml similarity index 100% rename from MPChartExample/res/layout/activity_realtime_linechart.xml rename to MPChartExample/src/main/res/layout/activity_realtime_linechart.xml diff --git a/MPChartExample/res/layout/activity_scatterchart.xml b/MPChartExample/src/main/res/layout/activity_scatterchart.xml similarity index 100% rename from MPChartExample/res/layout/activity_scatterchart.xml rename to MPChartExample/src/main/res/layout/activity_scatterchart.xml diff --git a/MPChartExample/res/layout/activity_scrollview.xml b/MPChartExample/src/main/res/layout/activity_scrollview.xml similarity index 100% rename from MPChartExample/res/layout/activity_scrollview.xml rename to MPChartExample/src/main/res/layout/activity_scrollview.xml diff --git a/MPChartExample/res/layout/custom_marker_view.xml b/MPChartExample/src/main/res/layout/custom_marker_view.xml similarity index 100% rename from MPChartExample/res/layout/custom_marker_view.xml rename to MPChartExample/src/main/res/layout/custom_marker_view.xml diff --git a/MPChartExample/res/layout/frag_simple_bar.xml b/MPChartExample/src/main/res/layout/frag_simple_bar.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_bar.xml rename to MPChartExample/src/main/res/layout/frag_simple_bar.xml diff --git a/MPChartExample/res/layout/frag_simple_line.xml b/MPChartExample/src/main/res/layout/frag_simple_line.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_line.xml rename to MPChartExample/src/main/res/layout/frag_simple_line.xml diff --git a/MPChartExample/res/layout/frag_simple_pie.xml b/MPChartExample/src/main/res/layout/frag_simple_pie.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_pie.xml rename to MPChartExample/src/main/res/layout/frag_simple_pie.xml diff --git a/MPChartExample/res/layout/frag_simple_scatter.xml b/MPChartExample/src/main/res/layout/frag_simple_scatter.xml similarity index 100% rename from MPChartExample/res/layout/frag_simple_scatter.xml rename to MPChartExample/src/main/res/layout/frag_simple_scatter.xml diff --git a/MPChartExample/res/layout/list_item.xml b/MPChartExample/src/main/res/layout/list_item.xml similarity index 100% rename from MPChartExample/res/layout/list_item.xml rename to MPChartExample/src/main/res/layout/list_item.xml diff --git a/MPChartExample/res/layout/list_item_barchart.xml b/MPChartExample/src/main/res/layout/list_item_barchart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_barchart.xml rename to MPChartExample/src/main/res/layout/list_item_barchart.xml diff --git a/MPChartExample/res/layout/list_item_linechart.xml b/MPChartExample/src/main/res/layout/list_item_linechart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_linechart.xml rename to MPChartExample/src/main/res/layout/list_item_linechart.xml diff --git a/MPChartExample/res/layout/list_item_piechart.xml b/MPChartExample/src/main/res/layout/list_item_piechart.xml similarity index 100% rename from MPChartExample/res/layout/list_item_piechart.xml rename to MPChartExample/src/main/res/layout/list_item_piechart.xml diff --git a/MPChartExample/res/layout/list_item_section.xml b/MPChartExample/src/main/res/layout/list_item_section.xml similarity index 100% rename from MPChartExample/res/layout/list_item_section.xml rename to MPChartExample/src/main/res/layout/list_item_section.xml diff --git a/MPChartExample/res/layout/radar_markerview.xml b/MPChartExample/src/main/res/layout/radar_markerview.xml similarity index 100% rename from MPChartExample/res/layout/radar_markerview.xml rename to MPChartExample/src/main/res/layout/radar_markerview.xml diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/src/main/res/menu/bar.xml similarity index 100% rename from MPChartExample/res/menu/bar.xml rename to MPChartExample/src/main/res/menu/bar.xml diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/src/main/res/menu/bubble.xml similarity index 100% rename from MPChartExample/res/menu/bubble.xml rename to MPChartExample/src/main/res/menu/bubble.xml diff --git a/MPChartExample/res/menu/candle.xml b/MPChartExample/src/main/res/menu/candle.xml similarity index 100% rename from MPChartExample/res/menu/candle.xml rename to MPChartExample/src/main/res/menu/candle.xml diff --git a/MPChartExample/res/menu/combined.xml b/MPChartExample/src/main/res/menu/combined.xml similarity index 100% rename from MPChartExample/res/menu/combined.xml rename to MPChartExample/src/main/res/menu/combined.xml diff --git a/MPChartExample/res/menu/draw.xml b/MPChartExample/src/main/res/menu/draw.xml similarity index 100% rename from MPChartExample/res/menu/draw.xml rename to MPChartExample/src/main/res/menu/draw.xml diff --git a/MPChartExample/res/menu/dynamical.xml b/MPChartExample/src/main/res/menu/dynamical.xml similarity index 100% rename from MPChartExample/res/menu/dynamical.xml rename to MPChartExample/src/main/res/menu/dynamical.xml diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/src/main/res/menu/line.xml similarity index 100% rename from MPChartExample/res/menu/line.xml rename to MPChartExample/src/main/res/menu/line.xml diff --git a/MPChartExample/res/menu/main.xml b/MPChartExample/src/main/res/menu/main.xml similarity index 100% rename from MPChartExample/res/menu/main.xml rename to MPChartExample/src/main/res/menu/main.xml diff --git a/MPChartExample/res/menu/only_github.xml b/MPChartExample/src/main/res/menu/only_github.xml similarity index 100% rename from MPChartExample/res/menu/only_github.xml rename to MPChartExample/src/main/res/menu/only_github.xml diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/src/main/res/menu/pie.xml similarity index 100% rename from MPChartExample/res/menu/pie.xml rename to MPChartExample/src/main/res/menu/pie.xml diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/src/main/res/menu/radar.xml similarity index 100% rename from MPChartExample/res/menu/radar.xml rename to MPChartExample/src/main/res/menu/radar.xml diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/src/main/res/menu/realtime.xml similarity index 100% rename from MPChartExample/res/menu/realtime.xml rename to MPChartExample/src/main/res/menu/realtime.xml diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/src/main/res/menu/scatter.xml similarity index 100% rename from MPChartExample/res/menu/scatter.xml rename to MPChartExample/src/main/res/menu/scatter.xml diff --git a/MPChartExample/res/values/strings.xml b/MPChartExample/src/main/res/values/strings.xml similarity index 97% rename from MPChartExample/res/values/strings.xml rename to MPChartExample/src/main/res/values/strings.xml index 2426d92a78..1e96d8b6b6 100644 --- a/MPChartExample/res/values/strings.xml +++ b/MPChartExample/src/main/res/values/strings.xml @@ -7,7 +7,6 @@ Problem Report Developer Website Save to Gallery - realm.io website Animate X Animate Y diff --git a/MPChartExample/res/values/styles.xml b/MPChartExample/src/main/res/values/styles.xml similarity index 100% rename from MPChartExample/res/values/styles.xml rename to MPChartExample/src/main/res/values/styles.xml diff --git a/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs deleted file mode 100644 index 77dc3a2d85..0000000000 --- a/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences -#Mon Jan 18 23:02:46 CET 2016 -org.springsource.ide.eclipse.gradle.linkedresources= -org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 83fc126bff..881cfd5365 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,12 +1,11 @@ apply plugin: 'com.android.library' -apply plugin: 'maven' -//apply plugin: 'com.github.dcendents.android-maven' -//apply plugin: 'realm-android' +apply plugin: 'com.github.dcendents.android-maven' + +group='com.github.philjay' android { compileSdkVersion 28 buildToolsVersion '28.0.3' - // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 14 targetSdkVersion 28 @@ -19,33 +18,14 @@ android { proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - lintOptions { - abortOnError false - } testOptions { unitTests.returnDefaultValues = true // this prevents "not mocked" error } } -repositories { - maven { - url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' - } -} - dependencies { - //provided 'io.realm:realm-android:0.87.5' // "optional" dependency to realm-database API implementation 'androidx.annotation:annotation:1.0.0' testImplementation 'junit:junit:4.12' - testImplementation "org.mockito:mockito-core:1.10.19" -} - -android.libraryVariants.all { variant -> - def name = variant.buildType.name - def task = project.tasks.create "jar${name.capitalize()}", Jar - task.dependsOn variant.javaCompiler - task.from variant.javaCompiler.destinationDir - artifacts.add('archives', task) } task sourcesJar(type: Jar) { diff --git a/MPChartLib/proguard-project.txt b/MPChartLib/proguard-project.txt deleted file mode 100644 index f2fe1559a2..0000000000 --- a/MPChartLib/proguard-project.txt +++ /dev/null @@ -1,20 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} diff --git a/MPChartLib/project.properties b/MPChartLib/project.properties deleted file mode 100644 index b2ef7dccc5..0000000000 --- a/MPChartLib/project.properties +++ /dev/null @@ -1,15 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt - -# Project target. -target=android-23 -android.library=true diff --git a/README.md b/README.md index 96d9ac9039..d6c9ea60d2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![banner](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic_smaller.png) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?style=flat)](https://jitpack.io/#PhilJay/MPAndroidChart) -[![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![API](https://img.shields.io/badge/API-14%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=14) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/PhilJay/MPAndroidChart?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) @@ -10,6 +10,19 @@ [**Charts**](https://github.com/danielgindi/Charts) is the iOS version of this library +## Table of Contents +1. [Quick Start](#quick-start) + 1. [Gradle](#gradle-setup) + 1. [Maven](#maven-setup) +1. [Documentation](#documentation) +1. [Examples](#examples) +1. [Questions](#report) +1. [Donate](#donate) +1. [Social Media](#social) +1. [More Examples](#more-examples) +1. [License](#licence) +1. [Creators](#creators) + ## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart) @@ -28,26 +41,23 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the Quick Start :chart_with_upwards_trend:
  • * This method is deprecated because of unclarity. Use setCircleRadius instead. * * @param size @@ -171,9 +189,7 @@ public void setCircleSize(float size) { } /** - * * This function is deprecated because of unclarity. Use getCircleRadius instead. - * */ @Deprecated public float getCircleSize() { @@ -184,13 +200,13 @@ public float getCircleSize() { * Enables the line to be drawn in dashed mode, e.g. like this * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. * Keep in mind that hardware acceleration boosts performance. - * - * @param lineLength the length of the line pieces + * + * @param lineLength the length of the line pieces * @param spaceLength the length of space in between the pieces - * @param phase offset, in degrees (normally, use 0) + * @param phase offset, in degrees (normally, use 0) */ public void enableDashedLine(float lineLength, float spaceLength, float phase) { - mDashPathEffect = new DashPathEffect(new float[] { + mDashPathEffect = new DashPathEffect(new float[]{ lineLength, spaceLength }, phase); } @@ -215,7 +231,7 @@ public DashPathEffect getDashPathEffect() { /** * set this to true to enable the drawing of circle indicators for this * DataSet, default true - * + * * @param enabled */ public void setDrawCircles(boolean enabled) { @@ -243,7 +259,7 @@ public boolean isDrawSteppedEnabled() { /** * returns all colors specified for the circles - * + * * @return */ public List getCircleColors() { @@ -252,11 +268,11 @@ public List getCircleColors() { @Override public int getCircleColor(int index) { - return mCircleColors.get(index % mCircleColors.size()); + return mCircleColors.get(index); } @Override - public int getCircleColorCount(){ + public int getCircleColorCount() { return mCircleColors.size(); } @@ -266,7 +282,7 @@ public int getCircleColorCount(){ * is higher than the size of the colors array. Make sure that the colors * are already prepared (by calling getResources().getColor(...)) before * adding them to the DataSet. - * + * * @param colors */ public void setCircleColors(List colors) { @@ -279,7 +295,7 @@ public void setCircleColors(List colors) { * is higher than the size of the colors array. Make sure that the colors * are already prepared (by calling getResources().getColor(...)) before * adding them to the DataSet. - * + * * @param colors */ public void setCircleColors(int[] colors) { @@ -293,13 +309,13 @@ public void setCircleColors(int[] colors) { * "new String[] { R.color.red, R.color.green, ... }" to provide colors for * this method. Internally, the colors are resolved using * getResources().getColor(...) - * + * * @param colors */ public void setCircleColors(int[] colors, Context c) { List clrs = mCircleColors; - if(clrs == null){ + if (clrs == null) { clrs = new ArrayList<>(); } clrs.clear(); @@ -314,7 +330,7 @@ public void setCircleColors(int[] colors, Context c) { /** * Sets the one and ONLY color that should be used for this DataSet. * Internally, this recreates the colors array and adds the specified color. - * + * * @param color */ public void setCircleColor(int color) { @@ -326,7 +342,7 @@ public void setCircleColor(int color) { * resets the circle-colors array and creates a new one */ public void resetCircleColors() { - if(mCircleColors == null) { + if (mCircleColors == null) { mCircleColors = new ArrayList(); } mCircleColors.clear(); @@ -334,7 +350,7 @@ public void resetCircleColors() { /** * Sets the color of the inner circle of the line-circles. - * + * * @param color */ public void setCircleColorHole(int color) { @@ -348,7 +364,7 @@ public int getCircleHoleColor() { /** * Set this to true to allow drawing a hole in each data circle. - * + * * @param enabled */ public void setDrawCircleHole(boolean enabled) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index d478024808..aac9440111 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -27,36 +27,6 @@ public class LineChartRenderer extends LineRadarRenderer { - private class DataSetImageCache { - - private Bitmap[] circleBitmaps; - private int[] circleColors; - - private void ensureCircleCache(int size) { - if (circleBitmaps == null) { - circleBitmaps = new Bitmap[size]; - } else if (circleBitmaps.length < size) { - Bitmap[] tmp = new Bitmap[size]; - for (int i = 0; i < circleBitmaps.length; i++) { - tmp[i] = circleBitmaps[size]; - } - circleBitmaps = tmp; - } - - if (circleColors == null) { - circleColors = new int[size]; - } else if (circleColors.length < size) { - int[] tmp = new int[size]; - for (int i = 0; i < circleColors.length; i++) { - tmp[i] = circleColors[size]; - } - circleColors = tmp; - } - } - - } - - protected LineDataProvider mChart; /** @@ -95,9 +65,7 @@ public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, } @Override - public void initBuffers() { - - } + public void initBuffers() { } @Override public void drawData(Canvas c) { @@ -595,10 +563,16 @@ public void drawExtras(Canvas c) { drawCircles(c); } - private Path mCirclePathBuffer = new Path(); - private float[] mCirclesBuffer = new float[2]; + /** + * cache for the circle bitmaps of all datasets + */ private HashMap mImageCaches = new HashMap<>(); + /** + * buffer for drawing the circles + */ + private float[] mCirclesBuffer = new float[2]; + protected void drawCircles(Canvas c) { mRenderPaint.setStyle(Paint.Style.FILL); @@ -614,16 +588,6 @@ protected void drawCircles(Canvas c) { ILineDataSet dataSet = dataSets.get(i); - DataSetImageCache imageCache; - - if (mImageCaches.containsKey(dataSet)) { - imageCache = mImageCaches.get(dataSet); - } else { - imageCache = new DataSetImageCache(); - mImageCaches.put(dataSet, imageCache); - } - imageCache.ensureCircleCache(dataSet.getCircleColorCount()); - if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -642,6 +606,22 @@ protected void drawCircles(Canvas c) { boolean drawTransparentCircleHole = drawCircleHole && dataSet.getCircleHoleColor() == ColorTemplate.COLOR_NONE; + DataSetImageCache imageCache; + + if (mImageCaches.containsKey(dataSet)) { + imageCache = mImageCaches.get(dataSet); + } else { + imageCache = new DataSetImageCache(); + mImageCaches.put(dataSet, imageCache); + } + + boolean changeRequired = imageCache.init(dataSet); + + // only fill the cache with new bitmaps if a change is required + if (changeRequired) { + imageCache.fill(dataSet, drawCircleHole, drawTransparentCircleHole); + } + int boundsRangeCount = mXBounds.range + mXBounds.min; for (int j = mXBounds.min; j <= boundsRangeCount; j++) { @@ -658,73 +638,11 @@ protected void drawCircles(Canvas c) { if (!mViewPortHandler.isInBoundsRight(mCirclesBuffer[0])) break; - // make sure the circles don't do shitty things outside - // bounds if (!mViewPortHandler.isInBoundsLeft(mCirclesBuffer[0]) || !mViewPortHandler.isInBoundsY(mCirclesBuffer[1])) continue; - final int circleColor = dataSet.getCircleColor(j); - mRenderPaint.setColor(circleColor); - - Bitmap circleBitmap = null; - - int colorIndex; - - for (colorIndex = 0; colorIndex < imageCache.circleColors.length; colorIndex++) { - int tempColor = imageCache.circleColors[colorIndex]; - Bitmap tempBitmap = imageCache.circleBitmaps[colorIndex]; - if (tempColor == circleColor) { - circleBitmap = tempBitmap; - break; - } else if (tempBitmap == null) { - break; - } - } - - if (circleBitmap == null) { - Bitmap.Config conf = Bitmap.Config.ARGB_8888; - circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1), (int) (circleRadius * 2.1), conf); - Canvas canvas = new Canvas(circleBitmap); - imageCache.circleBitmaps[colorIndex] = circleBitmap; - imageCache.circleColors[colorIndex] = circleColor; - - if (drawTransparentCircleHole) { - // Begin path for circle with hole - mCirclePathBuffer.reset(); - - mCirclePathBuffer.addCircle( - circleRadius, - circleRadius, - circleRadius, - Path.Direction.CW); - - // Cut hole in path - mCirclePathBuffer.addCircle( - circleRadius, - circleRadius, - circleHoleRadius, - Path.Direction.CCW); - - // Fill in-between - canvas.drawPath(mCirclePathBuffer, mRenderPaint); - } else { - - canvas.drawCircle( - circleRadius, - circleRadius, - circleRadius, - mRenderPaint); - - if (drawCircleHole) { - canvas.drawCircle( - circleRadius, - circleRadius, - circleHoleRadius, - mCirclePaintInner); - } - } - } + Bitmap circleBitmap = imageCache.getBitmap(j); if (circleBitmap != null) { c.drawBitmap(circleBitmap, mCirclesBuffer[0] - circleRadius, mCirclesBuffer[1] - circleRadius, mRenderPaint); @@ -795,4 +713,103 @@ public void releaseBitmap() { mDrawBitmap = null; } } + + private class DataSetImageCache { + + private Path mCirclePathBuffer = new Path(); + + private Bitmap[] circleBitmaps; + + /** + * Sets up the cache, returns true if a change of cache was required. + * + * @param set + * @return + */ + protected boolean init(ILineDataSet set) { + + int size = set.getCircleColorCount(); + boolean changeRequired = false; + + if (circleBitmaps == null) { + circleBitmaps = new Bitmap[size]; + changeRequired = true; + } else if (circleBitmaps.length != size) { + circleBitmaps = new Bitmap[size]; + changeRequired = true; + } + + return changeRequired; + } + + /** + * Fills the cache with bitmaps for the given dataset. + * + * @param set + * @param drawCircleHole + * @param drawTransparentCircleHole + */ + protected void fill(ILineDataSet set, boolean drawCircleHole, boolean drawTransparentCircleHole) { + + int colorCount = set.getCircleColorCount(); + float circleRadius = set.getCircleRadius(); + float circleHoleRadius = set.getCircleHoleRadius(); + + for (int i = 0; i < colorCount; i++) { + + Bitmap.Config conf = Bitmap.Config.ARGB_4444; + Bitmap circleBitmap = Bitmap.createBitmap((int) (circleRadius * 2.1), (int) (circleRadius * 2.1), conf); + + Canvas canvas = new Canvas(circleBitmap); + circleBitmaps[i] = circleBitmap; + mRenderPaint.setColor(set.getCircleColor(i)); + + if (drawTransparentCircleHole) { + // Begin path for circle with hole + mCirclePathBuffer.reset(); + + mCirclePathBuffer.addCircle( + circleRadius, + circleRadius, + circleRadius, + Path.Direction.CW); + + // Cut hole in path + mCirclePathBuffer.addCircle( + circleRadius, + circleRadius, + circleHoleRadius, + Path.Direction.CCW); + + // Fill in-between + canvas.drawPath(mCirclePathBuffer, mRenderPaint); + } else { + + canvas.drawCircle( + circleRadius, + circleRadius, + circleRadius, + mRenderPaint); + + if (drawCircleHole) { + canvas.drawCircle( + circleRadius, + circleRadius, + circleHoleRadius, + mCirclePaintInner); + } + } + } + } + + /** + * Returns the cached Bitmap at the given index. + * + * @param index + * @return + */ + protected Bitmap getBitmap(int index) { + return circleBitmaps[index % circleBitmaps.length]; + } + } } From 360cc24b971d68529ca0d0686e7e5bff19ac540e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 00:11:48 +0200 Subject: [PATCH 1079/1390] Cleanup --- .../com/xxmassdeveloper/mpchartexample/BarChartActivity.java | 1 + .../mikephil/charting/formatter/DefaultValueFormatter.java | 2 -- .../mikephil/charting/formatter/StackedValueFormatter.java | 2 +- .../com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java | 3 +-- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 775c925bbf..eb17690354 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -259,6 +259,7 @@ private void setData(int count, float range) { } protected RectF mOnValueSelectedRectF = new RectF(); + @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index b6965435aa..8d169b1405 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -53,9 +53,7 @@ public void setup(int digits) { @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormattedStringCache.getFormattedValue(value, dataSetIndex); - } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 618b1b1fe4..bc020d5637 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -21,7 +21,6 @@ public class StackedValueFormatter implements ValueFormatter { private FormattedStringCache.Generic mFormattedStringCacheWholeStack; private FormattedStringCache.Generic mFormattedStringCache; - /** * a string that should be appended behind the value */ @@ -57,6 +56,7 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View FormattedStringCache.Generic chosenCache = mFormattedStringCache; int chosenIndex = dataSetIndex; float chosenValue = value; + if (!mDrawWholeStack && entry instanceof BarEntry) { BarEntry barEntry = (BarEntry) entry; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java index 00bddc2427..8f953a06aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/AnimatedMoveViewJob.java @@ -1,6 +1,5 @@ package com.github.mikephil.charting.jobs; -import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.view.View; @@ -31,7 +30,7 @@ public static AnimatedMoveViewJob getInstance(ViewPortHandler viewPortHandler, f result.view = v; result.xOrigin = xOrigin; result.yOrigin = yOrigin; - result.resetAnimator(); + //result.resetAnimator(); result.animator.setDuration(duration); return result; } From 3f0f3a82c27b139470db884e62fdfee86b68c204 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 00:23:56 +0200 Subject: [PATCH 1080/1390] Improve setColors methods, cleanup --- .../mpchartexample/LineChartActivity2.java | 1 - .../mikephil/charting/data/BaseDataSet.java | 2 +- .../mikephil/charting/data/LineDataSet.java | 2 +- .../github/mikephil/charting/utils/FSize.java | 1 - .../mikephil/charting/utils/Transformer.java | 34 +++++++++---------- .../utils/TransformerHorizontalBarChart.java | 2 +- .../github/mikephil/charting/utils/Utils.java | 27 --------------- 7 files changed, 19 insertions(+), 50 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 738e08814a..81097debea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -58,7 +58,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (LineChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); - mChart.setLogEnabled(true); // no description text mChart.setDescription(""); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 4c9f8e13e4..28dd77ceb4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -150,7 +150,7 @@ public void setColors(List colors) { * * @param colors */ - public void setColors(int[] colors) { + public void setColors(int... colors) { this.mColors = ColorTemplate.createColors(colors); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index 0d7147e5dd..2f1af59d1d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -298,7 +298,7 @@ public void setCircleColors(List colors) { * * @param colors */ - public void setCircleColors(int[] colors) { + public void setCircleColors(int... colors) { this.mCircleColors = ColorTemplate.createColors(colors); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java index ecb8c2e312..d4ff8974d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/FSize.java @@ -73,5 +73,4 @@ public String toString() { public int hashCode() { return Float.floatToIntBits(width) ^ Float.floatToIntBits(height); } - } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java index be6d4cefe8..d9a57c3f82 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Transformer.java @@ -84,16 +84,10 @@ public void prepareMatrixOffset(boolean inverted) { .setTranslate(mViewPortHandler.offsetLeft(), -mViewPortHandler.offsetTop()); mMatrixOffset.postScale(1.0f, -1.0f); } - - // mMatrixOffset.set(offset); - - // mMatrixOffset.reset(); - // - // mMatrixOffset.postTranslate(mOffsetLeft, getHeight() - - // mOffsetBottom); } protected float[] valuePointsForGenerateTransformedValuesScatter = new float[1]; + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the SCATTERCHART. @@ -106,7 +100,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas final int count = (int) ((to - from) * phaseX + 1) * 2; - if(valuePointsForGenerateTransformedValuesScatter.length != count){ + if (valuePointsForGenerateTransformedValuesScatter.length != count) { valuePointsForGenerateTransformedValuesScatter = new float[count]; } float[] valuePoints = valuePointsForGenerateTransformedValuesScatter; @@ -118,7 +112,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; - }else{ + } else { valuePoints[j] = 0; valuePoints[j + 1] = 0; } @@ -130,6 +124,7 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, float phas } protected float[] valuePointsForGenerateTransformedValuesBubble = new float[1]; + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BUBBLECHART. @@ -141,7 +136,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY final int count = (to - from + 1) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; - if(valuePointsForGenerateTransformedValuesBubble.length != count){ + if (valuePointsForGenerateTransformedValuesBubble.length != count) { valuePointsForGenerateTransformedValuesBubble = new float[count]; } float[] valuePoints = valuePointsForGenerateTransformedValuesBubble; @@ -153,7 +148,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; - }else{ + } else { valuePoints[j] = 0; valuePoints[j + 1] = 0; } @@ -165,6 +160,7 @@ public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseY } protected float[] valuePointsForGenerateTransformedValuesLine = new float[1]; + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the LINECHART. @@ -177,7 +173,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, final int count = (int) ((to - from) * phaseX + 1) * 2; - if(valuePointsForGenerateTransformedValuesLine.length != count){ + if (valuePointsForGenerateTransformedValuesLine.length != count) { valuePointsForGenerateTransformedValuesLine = new float[count]; } float[] valuePoints = valuePointsForGenerateTransformedValuesLine; @@ -189,7 +185,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getY() * phaseY; - }else{ + } else { valuePoints[j] = 0; valuePoints[j + 1] = 0; } @@ -201,6 +197,7 @@ public float[] generateTransformedValuesLine(ILineDataSet data, } protected float[] valuePointsForGenerateTransformedValuesCandle = new float[1]; + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the CANDLESTICKCHART. @@ -213,7 +210,7 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, final int count = (int) ((to - from) * phaseX + 1) * 2; - if(valuePointsForGenerateTransformedValuesCandle.length != count){ + if (valuePointsForGenerateTransformedValuesCandle.length != count) { valuePointsForGenerateTransformedValuesCandle = new float[count]; } float[] valuePoints = valuePointsForGenerateTransformedValuesCandle; @@ -225,7 +222,7 @@ public float[] generateTransformedValuesCandle(ICandleDataSet data, if (e != null) { valuePoints[j] = e.getX(); valuePoints[j + 1] = e.getHigh() * phaseY; - }else{ + } else { valuePoints[j] = 0; valuePoints[j + 1] = 0; } @@ -357,6 +354,7 @@ public void rectValuesToPixel(List rects) { } protected Matrix mPixelsToValueMatrixBuffer = new Matrix(); + /** * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) * into values on the chart. @@ -397,12 +395,12 @@ public void pixelsToValue(float[] pixels) { */ public MPPointD getValuesByTouchPoint(float x, float y) { - MPPointD result = MPPointD.getInstance(0,0); - getValuesByTouchPoint(x,y,result); + MPPointD result = MPPointD.getInstance(0, 0); + getValuesByTouchPoint(x, y, result); return result; } - public void getValuesByTouchPoint(float x, float y, MPPointD outputPoint){ + public void getValuesByTouchPoint(float x, float y, MPPointD outputPoint) { ptsBuffer[0] = x; ptsBuffer[1] = y; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java index aee132cca2..05fa82ae29 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/TransformerHorizontalBarChart.java @@ -15,7 +15,7 @@ public TransformerHorizontalBarChart(ViewPortHandler viewPortHandler) { /** * Prepares the matrix that contains all offsets. * - * @param chart + * @param inverted */ public void prepareMatrixOffset(boolean inverted) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index e599fc1db7..0799679114 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -6,7 +6,6 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.PointF; import android.graphics.Rect; import android.os.Build; import android.text.Layout; @@ -728,30 +727,4 @@ public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, flo public static int getSDKInt() { return android.os.Build.VERSION.SDK_INT; } - - /** - * Calculates the granularity (minimum axis interval) based on axis range and labelcount. - * Default granularity is 1/10th of interval. - * - * @param range - * @param labelCount - * @return - */ - public static double granularity(float range, int labelCount) { - - // Find out how much spacing (in y value space) between axis values - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - - // Normalize interval - double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10 - (interval))); - int intervalSigDigit = (int) (interval / intervalMagnitude); - - if (intervalSigDigit > 5) { - interval = Math.floor(10 * intervalMagnitude); - } - - return interval * 0.1; // granularity is 1/10th of interval - } } From 08b2d550496214aae9e4b6a01bb683dc43329edd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 00:26:11 +0200 Subject: [PATCH 1081/1390] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 256000ca76..10f104b7f0 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ If you are having questions or problems, you should: - **Review your code**. Make absolutely sure that everything is correct on your side. - Make sure you are using the **latest version** of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.5/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0-beta1/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please :fire: **search known issues before** :fire:, do not create duplicate issues) @@ -91,7 +91,7 @@ Features - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart - Gradle support - - Plotting data directly from [**Realm.io**](https://realm.io) mobile database + - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) Usage ----- @@ -107,7 +107,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.2.5' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' } ``` @@ -122,7 +122,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.2.5 + v3.0.0-beta1 ``` @@ -142,7 +142,7 @@ dependencies { Documentation ----- -For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.5/javadoc/). +For a **detailed documentation** :notebook_with_decorative_cover:, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.0-beta1/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From a4ac12aebff0809dc01863c771445cc046a046f8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 01:17:15 +0200 Subject: [PATCH 1082/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 10f104b7f0..01a321ba2b 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Features - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart - Gradle support - - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) + - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) :zap: Usage ----- From 83a4bf90755a56476158713da6674d4011f804f5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 09:50:34 +0200 Subject: [PATCH 1083/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 01a321ba2b..842d720470 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Features - Fully customizable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart - Gradle support - - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) :zap: + - Plotting data directly from [**Realm.io**](https://realm.io) mobile database: [**MPAndroidChart-Realm**](https://github.com/PhilJay/MPAndroidChart-Realm) :zap: Usage ----- From bad43a5e1319c26ac68db62dc765f8ba176a8b42 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 11:48:04 +0200 Subject: [PATCH 1084/1390] Move example to realm v1.1.0 --- MPChartExample/build.gradle | 2 +- build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index f0ed2a5a33..9605392372 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -56,7 +56,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile project(':MPChartLib-Realm') // clone "https://github.com/PhilJay/MPAndroidChart-Realm" to get this or uncomment the gradle dependency below: - compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.0.2@aar' + compile 'com.github.PhilJay:MPAndroidChart-Realm:v1.1.0@aar' compile project(':MPChartLib') compile 'com.android.support:appcompat-v7:23.1.1' diff --git a/build.gradle b/build.gradle index 0eb3f4e7bf..3dfff3b287 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath "io.realm:realm-gradle-plugin:1.0.1" + classpath "io.realm:realm-gradle-plugin:1.1.0" classpath 'com.android.tools.build:gradle:2.1.2' classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' } From 1a39ac9b1215f2512762f0ce34695ae4aa6587c8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 14:49:47 +0200 Subject: [PATCH 1085/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 842d720470..eac1681bfa 100644 --- a/README.md +++ b/README.md @@ -216,4 +216,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [ph1lb4](https://github.com/ph1lb4) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. +**Special thanks** to [danielgindi](https://github.com/danielgindi), [mikegr](https://github.com/mikegr), [tony](https://github.com/tonypatino-monoclesociety) and [jitpack.io](https://github.com/jitpack-io) for their contributions to this project. From db70835cbc7003e920f23abb3bb0b079e2977d4b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 14:53:58 +0200 Subject: [PATCH 1086/1390] Update README.md --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index eac1681bfa..ef80f3a05e 100644 --- a/README.md +++ b/README.md @@ -100,14 +100,20 @@ In order to use the library, there are 4 different options: **1. Gradle dependency** (recommended) - - Add the following to your `build.gradle`: + - Add the following to your project level `build.gradle`: + - ```gradle -repositories { - maven { url "https://jitpack.io" } +allprojects { + repositories { + maven { url "https://jitpack.io" } + } } - +``` + - Add this to your app `build.gradle`: + +```gradle dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' + compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' } ``` From 75ba4f69fc1a745eb511f67a41fc48cd37fee39f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 14:54:43 +0200 Subject: [PATCH 1087/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ef80f3a05e..fe395d5c34 100644 --- a/README.md +++ b/README.md @@ -100,16 +100,16 @@ In order to use the library, there are 4 different options: **1. Gradle dependency** (recommended) - - Add the following to your project level `build.gradle`: - - - ```gradle + - Add the following to your project level `build.gradle`: + +```gradle allprojects { repositories { maven { url "https://jitpack.io" } } } ``` - - Add this to your app `build.gradle`: + - Add this to your app `build.gradle`: ```gradle dependencies { From e2cbafa049fd160267b277bce71a9e5e7b424273 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 20:22:56 +0200 Subject: [PATCH 1088/1390] Code cleanup & new zoom method --- .../charting/charts/BarLineChartBase.java | 86 ++++++++++++------- .../charting/charts/HorizontalBarChart.java | 8 +- .../mikephil/charting/jobs/ZoomJob.java | 21 +++-- .../charting/utils/ViewPortHandler.java | 33 ++++--- 4 files changed, 88 insertions(+), 60 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index a794c6a5ef..cc6cca64ff 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -590,6 +590,7 @@ public void computeScroll() { */ protected Matrix mZoomInMatrixBuffer = new Matrix(); + /** * Zooms in by 1.4f, into the charts center. center. */ @@ -610,6 +611,7 @@ public void zoomIn() { } protected Matrix mZoomOutMatrixBuffer = new Matrix(); + /** * Zooms out by 0.7f, from the charts center. center. */ @@ -630,6 +632,7 @@ public void zoomOut() { } protected Matrix mZoomMatrixBuffer = new Matrix(); + /** * Zooms in or out by the given scale factor. x and y are the coordinates * (in pixels) of the zoom center. @@ -641,7 +644,7 @@ public void zoomOut() { */ public void zoom(float scaleX, float scaleY, float x, float y) { Matrix save = mZoomMatrixBuffer; - mViewPortHandler.zoom(scaleX, scaleY, x, y, save); + mViewPortHandler.zoom(scaleX, scaleY, x, -y, save); mViewPortHandler.refresh(save, this, false); // Range might have changed, which means that Y-axis labels @@ -653,7 +656,7 @@ public void zoom(float scaleX, float scaleY, float x, float y) { /** * Zooms in or out by the given scale factor. - * x and y are the values (NOT PIXELS) which to zoom to or from (the values of the zoom center). + * x and y are the values (NOT PIXELS) of the zoom center.. * * @param scaleX * @param scaleY @@ -661,12 +664,27 @@ public void zoom(float scaleX, float scaleY, float x, float y) { * @param yValue * @param axis the axis relative to which the zoom should take place */ - public void zoomAndCenter(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { + public void zoom(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis) { Runnable job = ZoomJob.getInstance(mViewPortHandler, scaleX, scaleY, xValue, yValue, getTransformer(axis), axis, this); addViewportJob(job); } + /** + * Zooms to the center of the chart with the given scale factor. + * + * @param scaleX + * @param scaleY + */ + public void zoomCenter(float scaleX, float scaleY) { + + MPPointF center = getCenterOffsets(); + + Matrix save = mZoomMatrixBuffer; + mViewPortHandler.zoom(scaleX, scaleY, center.x, -center.y, save); + mViewPortHandler.refresh(save, this, false); + } + /** * Zooms by the specified scale factor to the specified values on the specified axis. * @@ -686,7 +704,7 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis - .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), xValue, yValue, (float) origin.x, (float) origin.y, duration); addViewportJob(job); @@ -698,6 +716,7 @@ public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, floa } protected Matrix mFitScreenMatrixBuffer = new Matrix(); + /** * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. @@ -771,7 +790,7 @@ public void setVisibleXRange(float minXRange, float maxXRange) { * @param axis the axis for which this limit should apply */ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { - float yScale = getDeltaY(axis) / maxYRange; + float yScale = getAxisRange(axis) / maxYRange; mViewPortHandler.setMinimumScaleY(yScale); } @@ -782,7 +801,7 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { * @param axis the axis for which this limit should apply */ public void setVisibleYRangeMinimum(float minYRange, AxisDependency axis) { - float yScale = getDeltaY(axis) / minYRange; + float yScale = getAxisRange(axis) / minYRange; mViewPortHandler.setMaximumScaleY(yScale); } @@ -794,8 +813,8 @@ public void setVisibleYRangeMinimum(float minYRange, AxisDependency axis) { * @param axis */ public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency axis) { - float minScale = getDeltaY(axis) / minYRange; - float maxScale = getDeltaY(axis) / maxYRange; + float minScale = getAxisRange(axis) / minYRange; + float maxScale = getAxisRange(axis) / maxYRange; mViewPortHandler.setMinMaxScaleY(minScale, maxScale); } @@ -825,7 +844,7 @@ public void moveViewToX(float xValue) { */ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { - float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); Runnable job = MoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this); @@ -850,7 +869,7 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); @@ -872,7 +891,7 @@ public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, */ public void centerViewToY(float yValue, AxisDependency axis) { - float valsInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float valsInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); Runnable job = MoveViewJob.getInstance(mViewPortHandler, 0f, yValue + valsInView / 2f, getTransformer(axis), this); @@ -891,7 +910,7 @@ public void centerViewToY(float yValue, AxisDependency axis) { */ public void centerViewTo(float xValue, float yValue, AxisDependency axis) { - float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = MoveViewJob.getInstance(mViewPortHandler, @@ -917,7 +936,7 @@ public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float yInView = getDeltaY(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, @@ -980,12 +999,12 @@ public void resetViewPortOffsets() { /** CODE BELOW IS GETTERS AND SETTERS */ /** - * Returns the delta-y value (y-value range) of the specified axis. + * Returns the range of the specified axis. * * @param axis * @return */ - public float getDeltaY(AxisDependency axis) { + protected float getAxisRange(AxisDependency axis) { if (axis == AxisDependency.LEFT) return mAxisLeft.mAxisRange; else @@ -1011,6 +1030,7 @@ public OnDrawListener getDrawListener() { } protected float[] mGetPositionBuffer = new float[2]; + /** * Returns a recyclable MPPointF instance. * Returns the position (in pixels) the provided Entry has inside the chart @@ -1213,12 +1233,12 @@ public void setKeepPositionOnRotation(boolean keepPositionOnRotation) { * @return */ public MPPointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { - MPPointD result = MPPointD.getInstance(0,0); - getValuesByTouchPoint(x,y,axis,result); + MPPointD result = MPPointD.getInstance(0, 0); + getValuesByTouchPoint(x, y, axis, result); return result; } - public void getValuesByTouchPoint(float x, float y, AxisDependency axis, MPPointD outputPoint){ + public void getValuesByTouchPoint(float x, float y, AxisDependency axis, MPPointD outputPoint) { getTransformer(axis).getValuesByTouchPoint(x, y, outputPoint); } @@ -1235,7 +1255,8 @@ public MPPointD getPixelsForValues(float x, float y, AxisDependency axis) { return getTransformer(axis).getPixelsForValues(x, y); } - MPPointD pointForGetYValueByTouchPoint = MPPointD.getInstance(0,0); + MPPointD pointForGetYValueByTouchPoint = MPPointD.getInstance(0, 0); + /** * Returns y value at the given touch position (must not necessarily be * a value contained in one of the datasets) @@ -1280,8 +1301,10 @@ public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float return null; } - /** buffer for storing lowest visible x point */ - protected MPPointD posForGetLowestVisibleX = MPPointD.getInstance(0,0); + /** + * buffer for storing lowest visible x point + */ + protected MPPointD posForGetLowestVisibleX = MPPointD.getInstance(0, 0); /** * Returns the lowest x-index (value on the x-axis) that is still visible on @@ -1297,8 +1320,10 @@ public float getLowestVisibleX() { return result; } - /** buffer for storing highest visible x point */ - protected MPPointD posForGetHighestVisibleX = MPPointD.getInstance(0,0); + /** + * buffer for storing highest visible x point + */ + protected MPPointD posForGetHighestVisibleX = MPPointD.getInstance(0, 0); /** * Returns the highest x-index (value on the x-axis) that is still visible @@ -1547,16 +1572,17 @@ public Paint getPaint(int which) { } protected float[] mOnSizeChangedBuffer = new float[2]; + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { // Saving current position of chart. - float[] pts = mOnSizeChangedBuffer; - pts[0] = pts[1] = 0; + mOnSizeChangedBuffer[0] = mOnSizeChangedBuffer[1] = 0; + if (mKeepPositionOnRotation) { - pts[0] = mViewPortHandler.contentLeft(); - pts[1] = mViewPortHandler.contentTop(); - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + mOnSizeChangedBuffer[0] = mViewPortHandler.contentLeft(); + mOnSizeChangedBuffer[1] = mViewPortHandler.contentTop(); + getTransformer(AxisDependency.LEFT).pixelsToValue(mOnSizeChangedBuffer); } //Superclass transforms chart. @@ -1565,8 +1591,8 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (mKeepPositionOnRotation) { //Restoring old position of chart. - getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); - mViewPortHandler.centerViewPort(pts, this); + getTransformer(AxisDependency.LEFT).pointValuesToPixel(mOnSizeChangedBuffer); + mViewPortHandler.centerViewPort(mOnSizeChangedBuffer, this); } else { mViewPortHandler.refresh(mViewPortHandler.getMatrixTouch(), this, true); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 806717a620..49047da63f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -248,20 +248,20 @@ public void setVisibleXRange(float minXRange, float maxXRange) { @Override public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { - float yScale = getDeltaY(axis) / maxYRange; + float yScale = getAxisRange(axis) / maxYRange; mViewPortHandler.setMinimumScaleX(yScale); } @Override public void setVisibleYRangeMinimum(float minYRange, AxisDependency axis) { - float yScale = getDeltaY(axis) / minYRange; + float yScale = getAxisRange(axis) / minYRange; mViewPortHandler.setMaximumScaleX(yScale); } @Override public void setVisibleYRange(float minYRange, float maxYRange, AxisDependency axis) { - float minScale = getDeltaY(axis) / minYRange; - float maxScale = getDeltaY(axis) / maxYRange; + float minScale = getAxisRange(axis) / minYRange; + float maxScale = getAxisRange(axis) / maxYRange; mViewPortHandler.setMinMaxScaleX(minScale, maxScale); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java index 00b67df0fc..c39586ca87 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/jobs/ZoomJob.java @@ -18,11 +18,12 @@ public class ZoomJob extends ViewPortJob { private static ObjectPool pool; static { - pool = ObjectPool.create(1, new ZoomJob(null,0,0,0,0,null,null,null)); + pool = ObjectPool.create(1, new ZoomJob(null, 0, 0, 0, 0, null, null, null)); pool.setReplenishPercentage(0.5f); } - public static ZoomJob getInstance(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, Transformer trans, YAxis.AxisDependency axis, View v) { + public static ZoomJob getInstance(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, + Transformer trans, YAxis.AxisDependency axis, View v) { ZoomJob result = pool.get(); result.xValue = xValue; result.yValue = yValue; @@ -35,7 +36,7 @@ public static ZoomJob getInstance(ViewPortHandler viewPortHandler, float scaleX, return result; } - public static void recycleInstance(ZoomJob instance){ + public static void recycleInstance(ZoomJob instance) { pool.recycle(instance); } @@ -44,7 +45,8 @@ public static void recycleInstance(ZoomJob instance){ protected YAxis.AxisDependency axisDependency; - public ZoomJob(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, Transformer trans, YAxis.AxisDependency axis, View v) { + public ZoomJob(ViewPortHandler viewPortHandler, float scaleX, float scaleY, float xValue, float yValue, Transformer trans, + YAxis.AxisDependency axis, View v) { super(viewPortHandler, xValue, yValue, trans, v); this.scaleX = scaleX; @@ -53,6 +55,7 @@ public ZoomJob(ViewPortHandler viewPortHandler, float scaleX, float scaleY, floa } protected Matrix mRunMatrixBuffer = new Matrix(); + @Override public void run() { @@ -60,11 +63,11 @@ public void run() { mViewPortHandler.zoom(scaleX, scaleY, save); mViewPortHandler.refresh(save, view, false); - float valsInView = ((BarLineChartBase) view).getDeltaY(axisDependency) / mViewPortHandler.getScaleY(); - float xsInView = ((BarLineChartBase) view).getXAxis().mAxisRange / mViewPortHandler.getScaleX(); + float yValsInView = ((BarLineChartBase) view).getAxis(axisDependency).mAxisRange / mViewPortHandler.getScaleY(); + float xValsInView = ((BarLineChartBase) view).getXAxis().mAxisRange / mViewPortHandler.getScaleX(); - pts[0] = xValue - xsInView / 2f; - pts[1] = yValue + valsInView / 2f; + pts[0] = xValue - xValsInView / 2f; + pts[1] = yValue + yValsInView / 2f; mTrans.pointValuesToPixel(pts); @@ -79,6 +82,6 @@ public void run() { @Override protected ObjectPool.Poolable instantiate() { - return new ZoomJob(null,0,0,0,0,null,null,null); + return new ZoomJob(null, 0, 0, 0, 0, null, null, null); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java index 9aa8109054..eedd190456 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -2,9 +2,7 @@ package com.github.mikephil.charting.utils; import android.graphics.Matrix; -import android.graphics.PointF; import android.graphics.RectF; -import android.util.Log; import android.view.View; /** @@ -198,11 +196,11 @@ public float getSmallestContentExtension() { public Matrix zoomIn(float x, float y) { Matrix save = new Matrix(); - zoomIn(x,y,save); + zoomIn(x, y, save); return save; } - public void zoomIn(float x, float y, Matrix outputMatrix){ + public void zoomIn(float x, float y, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); outputMatrix.postScale(1.4f, 1.4f, x, y); @@ -215,11 +213,11 @@ public void zoomIn(float x, float y, Matrix outputMatrix){ public Matrix zoomOut(float x, float y) { Matrix save = new Matrix(); - zoomOut(x,y,save); + zoomOut(x, y, save); return save; } - public void zoomOut(float x, float y, Matrix outputMatrix){ + public void zoomOut(float x, float y, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); outputMatrix.postScale(0.7f, 0.7f, x, y); @@ -235,11 +233,11 @@ public void zoomOut(float x, float y, Matrix outputMatrix){ public Matrix zoom(float scaleX, float scaleY) { Matrix save = new Matrix(); - zoom(scaleX,scaleY,save); + zoom(scaleX, scaleY, save); return save; } - public void zoom(float scaleX, float scaleY, Matrix outputMatrix){ + public void zoom(float scaleX, float scaleY, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); outputMatrix.postScale(scaleX, scaleY); @@ -257,14 +255,14 @@ public void zoom(float scaleX, float scaleY, Matrix outputMatrix){ public Matrix zoom(float scaleX, float scaleY, float x, float y) { Matrix save = new Matrix(); - zoom(scaleX,scaleY,x,y,save); + zoom(scaleX, scaleY, x, y, save); return save; } - public void zoom(float scaleX, float scaleY, float x, float y, Matrix outputMatrix){ + public void zoom(float scaleX, float scaleY, float x, float y, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); - outputMatrix.postScale(scaleX,scaleY,x,y); + outputMatrix.postScale(scaleX, scaleY, x, y); } /** @@ -277,14 +275,14 @@ public void zoom(float scaleX, float scaleY, float x, float y, Matrix outputMatr public Matrix setZoom(float scaleX, float scaleY) { Matrix save = new Matrix(); - setZoom(scaleX,scaleY,save); + setZoom(scaleX, scaleY, save); return save; } - public void setZoom(float scaleX, float scaleY, Matrix outputMatrix){ + public void setZoom(float scaleX, float scaleY, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); - outputMatrix.setScale(scaleX,scaleY); + outputMatrix.setScale(scaleX, scaleY); } /** @@ -323,14 +321,14 @@ public Matrix fitScreen() { * Resets all zooming and dragging and makes the chart fit exactly it's * bounds. Output Matrix is available for those who wish to cache the object. */ - public void fitScreen(Matrix outputMatrix){ + public void fitScreen(Matrix outputMatrix) { mMinScaleX = 1f; mMinScaleY = 1f; outputMatrix.set(mMatrixTouch); float[] vals = valsBufferForFitScreen; - for(int i = 0 ; i < 9 ; i++){ + for (int i = 0; i < 9; i++) { vals[i] = 0; } @@ -364,7 +362,7 @@ public Matrix translate(final float[] transformedPts) { * @param transformedPts * @return */ - public void translate(final float[] transformedPts, Matrix outputMatrix){ + public void translate(final float[] transformedPts, Matrix outputMatrix) { outputMatrix.reset(); outputMatrix.set(mMatrixTouch); final float x = transformedPts[0] - offsetLeft(); @@ -373,6 +371,7 @@ public void translate(final float[] transformedPts, Matrix outputMatrix){ } protected Matrix mCenterViewPortMatrixBuffer = new Matrix(); + /** * Centers the viewport around the specified position (x-index and y-value) * in the chart. Centering the viewport outside the bounds of the chart is From 16738ef4809197fb84e73adf771e9fd7490a6c90 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 3 Jul 2016 20:38:12 +0200 Subject: [PATCH 1089/1390] Import cleanup --- .../mikephil/charting/charts/BarChart.java | 2 +- .../charting/charts/BarLineChartBase.java | 44 ++----------------- .../mikephil/charting/charts/BubbleChart.java | 1 - .../charting/charts/CandleStickChart.java | 3 +- .../mikephil/charting/charts/Chart.java | 14 +++--- .../charting/charts/HorizontalBarChart.java | 3 +- .../mikephil/charting/charts/LineChart.java | 6 +-- .../mikephil/charting/charts/PieChart.java | 13 +++--- .../charting/charts/PieRadarChartBase.java | 6 +-- .../mikephil/charting/charts/RadarChart.java | 19 -------- .../charting/charts/ScatterChart.java | 4 ++ 11 files changed, 30 insertions(+), 85 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java index f3d39b97f5..6f3692c2f3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarChart.java @@ -118,7 +118,7 @@ public RectF getBarBounds(BarEntry e) { * @param e * @return */ - public void getBarBounds(BarEntry e, RectF outputRect){ + public void getBarBounds(BarEntry e, RectF outputRect) { RectF bounds = outputRect; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index cc6cca64ff..a208e73837 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -511,25 +511,6 @@ public void calculateOffsets() { prepareValuePxMatrix(); } -// @Override -// protected float[] getMarkerPosition(Highlight high) { -// return new float[] { high.getXPx(), high.getYPx() }; -// -// int dataSetIndex = highlight.getDataSetIndex(); -// float xPos = e.getX(); -// float yPos = e.getY() * mAnimator.getPhaseY(); -// -// // position of the marker depends on selected value index and value -// float[] pts = new float[]{ -// xPos, yPos -// }; -// -// getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) -// .pointValuesToPixel(pts); -// -// return pts; -// } - /** * draws the grid background */ @@ -1044,13 +1025,12 @@ public MPPointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; - float[] vals = mGetPositionBuffer; - vals[0] = e.getX(); - vals[1] = e.getY(); + mGetPositionBuffer[0] = e.getX(); + mGetPositionBuffer[1] = e.getY(); - getTransformer(axis).pointValuesToPixel(vals); + getTransformer(axis).pointValuesToPixel(mGetPositionBuffer); - return MPPointF.getInstance(vals[0], vals[1]); + return MPPointF.getInstance(mGetPositionBuffer[0], mGetPositionBuffer[1]); } /** @@ -1255,22 +1235,6 @@ public MPPointD getPixelsForValues(float x, float y, AxisDependency axis) { return getTransformer(axis).getPixelsForValues(x, y); } - MPPointD pointForGetYValueByTouchPoint = MPPointD.getInstance(0, 0); - - /** - * Returns y value at the given touch position (must not necessarily be - * a value contained in one of the datasets) - * - * @param x - * @param y - * @return - */ - public float getYValueByTouchPoint(float x, float y, AxisDependency axis) { - getValuesByTouchPoint(x, y, axis, pointForGetYValueByTouchPoint); - float result = (float) pointForGetYValueByTouchPoint.y; - return result; - } - /** * returns the Entry object displayed at the touched position of the chart * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java index 58532d2084..23dac5780f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BubbleChart.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.renderer.BubbleChartRenderer; /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java index 029a2bb490..61dff4bb61 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/CandleStickChart.java @@ -10,7 +10,7 @@ /** * Financial chart type that draws candle-sticks (OHCL chart). - * + * * @author Philipp Jahoda */ public class CandleStickChart extends BarLineChartBase implements CandleDataProvider { @@ -32,7 +32,6 @@ protected void init() { super.init(); mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); - mXAxis.mAxisMinimum = -0.5f; } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index c7ae8a57ff..c4fc594cc0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -308,8 +308,8 @@ public void setData(T data) { IDataSet set; final List sets = mData.getDataSets(); final int count = sets.size(); - for(int i = 0 ; i < count ; i++){ - set = (IDataSet)sets.get(i); + for (int i = 0; i < count; i++) { + set = (IDataSet) sets.get(i); if (set.needsFormatter() || set.getValueFormatter() == mDefaultFormatter) set.setValueFormatter(mDefaultFormatter); } @@ -486,7 +486,7 @@ protected void drawDescription(Canvas c) { protected Highlight[] mIndicesToHighlight; /** - * The maximum distance in screen pixels away from an entry causing it to highlight. + * The maximum distance in dp away from an entry causing it to highlight. */ protected float mMaxHighlightDistance = 0f; @@ -1100,9 +1100,9 @@ public void setDescription(String desc) { * @param y - ycoordinate */ public void setDescriptionPosition(float x, float y) { - if(mDescriptionPosition == null){ - mDescriptionPosition = MPPointF.getInstance(x,y); - }else { + if (mDescriptionPosition == null) { + mDescriptionPosition = MPPointF.getInstance(x, y); + } else { mDescriptionPosition.x = x; mDescriptionPosition.y = y; } @@ -1478,12 +1478,12 @@ public Highlighter getHighlighter() { * @param highlighter */ public void setHighlighter(ChartHighlighter highlighter) { - mHighlighter = highlighter; } /** * Returns a recyclable MPPointF instance. + * * @return */ @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index 49047da63f..e4ec309d9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -144,7 +144,7 @@ public void getBarBounds(BarEntry e, RectF outputRect) { RectF bounds = outputRect; IBarDataSet set = mData.getDataSetForEntry(e); - if (set == null){ + if (set == null) { outputRect.set(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE); return; } @@ -166,6 +166,7 @@ public void getBarBounds(BarEntry e, RectF outputRect) { } protected float[] mGetPositionBuffer = new float[2]; + /** * Returns a recyclable MPPointF instance. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java index c96926017f..aa7afc4c85 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/LineChart.java @@ -10,7 +10,7 @@ /** * Chart that draws lines, surfaces, circles, ... - * + * * @author Philipp Jahoda */ public class LineChart extends BarLineChartBase implements LineDataProvider { @@ -33,7 +33,7 @@ protected void init() { mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); } - + @Override public LineData getLineData() { return mData; @@ -42,7 +42,7 @@ public LineData getLineData() { @Override protected void onDetachedFromWindow() { // releases the bitmap in the renderer to avoid oom error - if(mRenderer != null && mRenderer instanceof LineChartRenderer) { + if (mRenderer != null && mRenderer instanceof LineChartRenderer) { ((LineChartRenderer) mRenderer).releaseBitmap(); } super.onDetachedFromWindow(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 5dfd5263ff..bad10dbbb4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -4,7 +4,6 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.PointF; import android.graphics.RectF; import android.graphics.Typeface; import android.util.AttributeSet; @@ -210,17 +209,17 @@ private void calcAngles() { int entryCount = mData.getEntryCount(); - if(mDrawAngles.length != entryCount) { + if (mDrawAngles.length != entryCount) { mDrawAngles = new float[entryCount]; - }else{ - for(int i = 0 ; i < entryCount ; i++){ + } else { + for (int i = 0; i < entryCount; i++) { mDrawAngles[i] = 0; } } - if(mAbsoluteAngles.length != entryCount) { + if (mAbsoluteAngles.length != entryCount) { mAbsoluteAngles = new float[entryCount]; - }else{ - for(int i = 0 ; i < entryCount ; i++){ + } else { + for (int i = 0; i < entryCount; i++) { mAbsoluteAngles[i] = 0; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 2cf3da0b66..637be47cab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -6,7 +6,6 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; import android.annotation.SuppressLint; import android.content.Context; -import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; @@ -17,7 +16,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.MPPointF; @@ -297,12 +295,12 @@ public float getAngleForPoint(float x, float y) { */ public MPPointF getPosition(MPPointF center, float dist, float angle) { - MPPointF p = MPPointF.getInstance(0,0); + MPPointF p = MPPointF.getInstance(0, 0); getPosition(center, dist, angle, p); return p; } - public void getPosition(MPPointF center, float dist, float angle, MPPointF outputPoint){ + public void getPosition(MPPointF center, float dist, float angle, MPPointF outputPoint) { outputPoint.x = (float) (center.x + dist * Math.cos(Math.toRadians(angle))); outputPoint.y = (float) (center.y + dist * Math.sin(Math.toRadians(angle))); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index ab953d79f9..1cc1bd6d60 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -4,15 +4,12 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.RadarHighlighter; import com.github.mikephil.charting.renderer.RadarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererRadarChart; @@ -106,22 +103,6 @@ protected void calcMinMax() { mXAxis.calculate(0, mData.getMaxEntryCountSet().getEntryCount()); } -// @Override -// protected float[] getMarkerPosition(Highlight highlight) { -// return null; -// -//// float angle = getSliceAngle() * e.getX() * mAnimator.getPhaseX() + getRotationAngle(); -//// float val = e.getY() * getFactor() * mAnimator.getPhaseY(); -//// PointF c = getCenterOffsets(); -//// -//// PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), -//// (float) (c.y + val * Math.sin(Math.toRadians(angle)))); -//// -//// return new float[]{ -//// p.x, p.y -//// }; -// } - @Override public void notifyDataSetChanged() { if (mData == null) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java index cbaf0694b0..0f68457b55 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/ScatterChart.java @@ -42,6 +42,10 @@ public ScatterData getScatterData() { return mData; } + /** + * Predefined ScatterShapes that allow the specification of a shape a ScatterDataSet should be drawn with. + * If a ScatterShape is specified for a ScatterDataSet, the required renderer is set. + */ public enum ScatterShape { SQUARE("SQUARE"), CIRCLE("CIRCLE"), TRIANGLE("TRIANGLE"), CROSS("CROSS"), X("X"), CHEVRON_UP("CHEVRON_UP"), From 89104c28587bc3f67b375675a02fc3948b1904d0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 7 Jul 2016 11:34:08 +0200 Subject: [PATCH 1090/1390] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fe395d5c34..03d657b560 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,14 @@ Donations If you just want to be nice, you can check out my [**Amazon-Wishlist**]( https://www.amazon.de/registry/wishlist/2DYHJ69VMF8HM/ref=cm_sw_em_r_mt_ws_WVCyxb4KKQ2G6). -## 3rd party bindings +## Xamarin Xamarin (by @Flash3001): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). +## Realm.io + +[MPAndroidChart-Realm](https://github.com/PhilJay/MPAndroidChart-Realm) allows to directly plot / draw data from [Realm.io](https://realm.io) mobile database. + Spread the word ----- From 2fa4a094e79d6a15d9df41de7491d00528a1e8e2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 7 Jul 2016 11:36:01 +0200 Subject: [PATCH 1091/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 03d657b560..518240d305 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ If you just want to be nice, you can check out my [**Amazon-Wishlist**]( https:/ ## Xamarin -Xamarin (by @Flash3001): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). +Xamarin port (by [Flash3001](https://github.com/Flash3001)): *Android* - [GitHub](https://github.com/Flash3001/MPAndroidChart.Xamarin)/[NuGet](https://www.nuget.org/packages/MPAndroidChart/). *iOS* - [GitHub](https://github.com/Flash3001/iOSCharts.Xamarin)/[NuGet](https://www.nuget.org/packages/iOSCharts/). ## Realm.io From 9ccf58feab2c1e52dfa25beff4878763d12b38b9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 7 Jul 2016 16:48:59 +0200 Subject: [PATCH 1092/1390] Fixes related to legend rendering (issue #1969) --- .../mpchartexample/PieChartActivity.java | 8 +- .../mpchartexample/ScatterChartActivity.java | 1 + .../mikephil/charting/components/Legend.java | 310 ++++++------------ .../charting/renderer/LegendRenderer.java | 80 ++--- .../github/mikephil/charting/utils/Utils.java | 8 +- 5 files changed, 157 insertions(+), 250 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index b77bbd1d18..f514110d59 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -52,12 +52,9 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - + mSeekBarX.setProgress(4); mSeekBarY.setProgress(10); - mSeekBarX.setOnSeekBarChangeListener(this); - mSeekBarY.setOnSeekBarChangeListener(this); - mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); mChart.setDescription(""); @@ -95,6 +92,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); // mChart.spin(2000, 0, 360); + mSeekBarX.setOnSeekBarChangeListener(this); + mSeekBarY.setOnSeekBarChangeListener(this); + Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); l.setXEntrySpace(7f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index b288b162e9..fbcea85d2f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -74,6 +74,7 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); l.setTypeface(mTfLight); + l.setXOffset(5f); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(mTfLight); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index 65824ac978..b12a39b394 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -15,13 +15,14 @@ * Class representing the legend of the chart. The legend will contain one entry * per color and DataSet. Multiple colors in one DataSet are grouped together. * The legend object is NOT available before setting data to the chart. - * + * * @author Philipp Jahoda */ public class Legend extends ComponentBase { /** - * This property is deprecated - Use `position`, `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, `direction`. + * This property is deprecated - Use `position`, `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, + * `direction`. */ public enum LegendPosition { RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, @@ -35,18 +36,15 @@ public enum LegendForm { SQUARE, CIRCLE, LINE } - public enum LegendHorizontalAlignment - { + public enum LegendHorizontalAlignment { LEFT, CENTER, RIGHT } - public enum LegendVerticalAlignment - { + public enum LegendVerticalAlignment { TOP, CENTER, BOTTOM } - public enum LegendOrientation - { + public enum LegendOrientation { HORIZONTAL, VERTICAL } @@ -60,7 +58,9 @@ public enum LegendDirection { */ private int[] mColors; - /** the legend text array. a null label will start a group. */ + /** + * the legend text array. a null label will start a group. + */ private String[] mLabels; /** @@ -86,13 +86,19 @@ public enum LegendDirection { private LegendOrientation mOrientation = LegendOrientation.HORIZONTAL; private boolean mDrawInside = false; - /** the text direction for the legend */ + /** + * the text direction for the legend + */ private LegendDirection mDirection = LegendDirection.LEFT_TO_RIGHT; - /** the shape/form the legend colors are drawn in */ + /** + * the shape/form the legend colors are drawn in + */ private LegendForm mShape = LegendForm.SQUARE; - /** the size of the legend forms/shapes */ + /** + * the size of the legend forms/shapes + */ private float mFormSize = 8f; /** @@ -112,13 +118,19 @@ public enum LegendDirection { */ private float mFormToTextSpace = 5f; - /** the space that should be left between stacked forms */ + /** + * the space that should be left between stacked forms + */ private float mStackSpace = 3f; - /** the maximum relative size out of the whole chart view in percent */ + /** + * the maximum relative size out of the whole chart view in percent + */ private float mMaxSizePercent = 0.95f; - /** default constructor */ + /** + * default constructor + */ public Legend() { mFormSize = Utils.convertDpToPixel(8f); @@ -133,7 +145,7 @@ public Legend() { /** * Constructor. Provide colors and labels for the legend. - * + * * @param colors * @param labels */ @@ -155,7 +167,7 @@ public Legend(int[] colors, String[] labels) { /** * Constructor. Provide colors and labels for the legend. - * + * * @param colors * @param labels */ @@ -171,30 +183,32 @@ public Legend(List colors, List labels) { "colors array and labels array need to be of same size"); } - this.setComputedColors(colors); - this.setComputedLabels(labels); + this.mColors = Utils.convertIntegers(colors); + this.mLabels = Utils.convertStrings(labels); } /** * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. + * * @param colors */ public void setComputedColors(List colors) { - if(mColors != null && colors.size() == mColors.length){ + if (mColors != null && colors.size() == mColors.length) { Utils.copyIntegers(colors, mColors); - }else { + } else { mColors = Utils.convertIntegers(colors); } } /** * This method sets the automatically computed labels for the legend. Use setCustom(...) to set custom labels. + * * @param labels */ public void setComputedLabels(List labels) { - if(mLabels != null && mLabels.length == labels.size()){ + if (mLabels != null && mLabels.length == labels.size()) { Utils.copyStrings(labels, mLabels); - }else { + } else { mLabels = Utils.convertStrings(labels); } } @@ -202,7 +216,7 @@ public void setComputedLabels(List labels) { /** * returns the maximum length in pixels across all legend labels + formsize * + formtotextspace - * + * * @param p the paint object used for rendering the text * @return */ @@ -226,7 +240,7 @@ public float getMaximumEntryWidth(Paint p) { /** * returns the maximum height in pixels across all legend labels - * + * * @param p the paint object used for rendering the text * @return */ @@ -250,7 +264,7 @@ public float getMaximumEntryHeight(Paint p) { /** * returns all the colors the legend uses - * + * * @return */ public int[] getColors() { @@ -259,7 +273,7 @@ public int[] getColors() { /** * returns all the labels the legend uses - * + * * @return */ public String[] getLabels() { @@ -268,7 +282,7 @@ public String[] getLabels() { /** * Returns the legend-label at the given index. - * + * * @param index * @return */ @@ -299,15 +313,15 @@ public String[] getExtraLabels() { * let the changes take effect) */ public void setExtra(List colors, List labels) { - if(mExtraColors != null && mExtraColors.length == colors.size()){ + if (mExtraColors != null && mExtraColors.length == colors.size()) { Utils.copyIntegers(colors, mExtraColors); - }else { + } else { this.mExtraColors = Utils.convertIntegers(colors); } - if(mExtraLabels != null && mExtraLabels.length == labels.size()){ + if (mExtraLabels != null && mExtraLabels.length == labels.size()) { Utils.copyStrings(labels, mExtraLabels); - }else { + } else { this.mExtraLabels = Utils.convertStrings(labels); } } @@ -360,8 +374,8 @@ public void setCustom(List colors, List labels) { "colors array and labels array need to be of same size"); } - this.setComputedColors(colors); - this.setComputedLabels(labels); + mColors = Utils.convertIntegers(colors); + mLabels = Utils.convertStrings(labels); mIsLegendCustom = true; } @@ -376,7 +390,7 @@ public void resetCustom() { /** * @return true if a custom legend labels and colors has been set default - * false (automatic legend) + * false (automatic legend) */ public boolean isLegendCustom() { return mIsLegendCustom; @@ -384,7 +398,7 @@ public boolean isLegendCustom() { /** * returns the position of the legend relative to the chart - * + * * @return */ public LegendPosition getPosition() { @@ -393,8 +407,7 @@ public LegendPosition getPosition() { && mHorizontalAlignment == LegendHorizontalAlignment.CENTER && mVerticalAlignment == LegendVerticalAlignment.CENTER) { return LegendPosition.PIECHART_CENTER; - } - else if (mOrientation == LegendOrientation.HORIZONTAL) { + } else if (mOrientation == LegendOrientation.HORIZONTAL) { if (mVerticalAlignment == LegendVerticalAlignment.TOP) return mHorizontalAlignment == LegendHorizontalAlignment.LEFT ? LegendPosition.ABOVE_CHART_LEFT @@ -407,8 +420,7 @@ else if (mOrientation == LegendOrientation.HORIZONTAL) { : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT ? LegendPosition.BELOW_CHART_RIGHT : LegendPosition.BELOW_CHART_CENTER); - } - else { + } else { if (mHorizontalAlignment == LegendHorizontalAlignment.LEFT) return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside ? LegendPosition.LEFT_OF_CHART_INSIDE @@ -426,7 +438,7 @@ else if (mOrientation == LegendOrientation.HORIZONTAL) { /** * sets the position of the legend relative to the whole chart - * + * * @param newValue */ public void setPosition(LegendPosition newValue) { @@ -579,7 +591,7 @@ public void setDirection(LegendDirection pos) { /** * returns the current form/shape that is set for the legend - * + * * @return */ public LegendForm getForm() { @@ -588,7 +600,7 @@ public LegendForm getForm() { /** * sets the form/shape of the legend forms - * + * * @param shape */ public void setForm(LegendForm shape) { @@ -598,7 +610,7 @@ public void setForm(LegendForm shape) { /** * sets the size in pixels of the legend forms, this is internally converted * in dp, default 8f - * + * * @param size */ public void setFormSize(float size) { @@ -607,7 +619,7 @@ public void setFormSize(float size) { /** * returns the size in dp of the legend forms - * + * * @return */ public float getFormSize() { @@ -617,7 +629,7 @@ public float getFormSize() { /** * returns the space between the legend entries on a horizontal axis in * pixels - * + * * @return */ public float getXEntrySpace() { @@ -627,7 +639,7 @@ public float getXEntrySpace() { /** * sets the space between the legend entries on a horizontal axis in pixels, * converts to dp internally - * + * * @param space */ public void setXEntrySpace(float space) { @@ -636,7 +648,7 @@ public void setXEntrySpace(float space) { /** * returns the space between the legend entries on a vertical axis in pixels - * + * * @return */ public float getYEntrySpace() { @@ -646,7 +658,7 @@ public float getYEntrySpace() { /** * sets the space between the legend entries on a vertical axis in pixels, * converts to dp internally - * + * * @param space */ public void setYEntrySpace(float space) { @@ -655,7 +667,7 @@ public void setYEntrySpace(float space) { /** * returns the space between the form and the actual label/text - * + * * @return */ public float getFormToTextSpace() { @@ -665,7 +677,7 @@ public float getFormToTextSpace() { /** * sets the space between the form and the actual label/text, converts to dp * internally - * + * * @param space */ public void setFormToTextSpace(float space) { @@ -674,7 +686,7 @@ public void setFormToTextSpace(float space) { /** * returns the space that is left out between stacked forms (with no label) - * + * * @return */ public float getStackSpace() { @@ -683,7 +695,7 @@ public float getStackSpace() { /** * sets the space that is left out between stacked forms (with no label) - * + * * @param space */ public void setStackSpace(float space) { @@ -691,73 +703,22 @@ public void setStackSpace(float space) { } /** - * calculates the full width the fully drawn legend will use in pixels - * - * @return + * the total width of the legend (needed width space) */ - public float getFullWidth(Paint labelpaint) { - - float width = 0f; - - for (int i = 0; i < mLabels.length; i++) { - - // grouped forms have null labels - if (mLabels[i] != null) { - - // make a step to the left - if (mColors[i] != ColorTemplate.COLOR_SKIP) - width += mFormSize + mFormToTextSpace; - - width += Utils.calcTextWidth(labelpaint, mLabels[i]); - - if (i < mLabels.length - 1) - width += mXEntrySpace; - } else { - width += mFormSize; - if (i < mLabels.length - 1) - width += mStackSpace; - } - } - - return width; - } + public float mNeededWidth = 0f; /** - * Calculates the full height of the drawn legend. - * - * @param labelpaint - * @return + * the total height of the legend (needed height space) */ - public float getFullHeight(Paint labelpaint) { - - float height = 0f; - - for (int i = 0; i < mLabels.length; i++) { - - // grouped forms have null labels - if (mLabels[i] != null) { - - height += Utils.calcTextHeight(labelpaint, mLabels[i]); - - if (i < mLabels.length - 1) - height += mYEntrySpace; - } - } - - return height; - } - - /** the total width of the legend (needed width space) */ - public float mNeededWidth = 0f; - - /** the total height of the legend (needed height space) */ public float mNeededHeight = 0f; public float mTextHeightMax = 0f; public float mTextWidthMax = 0f; - /** flag that indicates if word wrapping is enabled */ + /** + * flag that indicates if word wrapping is enabled + */ private boolean mWordWrapEnabled = false; /** @@ -766,7 +727,7 @@ public float getFullHeight(Paint labelpaint) { * wrapping a legend takes a toll on performance. / you may want to set * maxSizePercent when word wrapping, to set the point where the text wraps. * / default: false - * + * * @param enabled */ public void setWordWrapEnabled(boolean enabled) { @@ -776,7 +737,7 @@ public void setWordWrapEnabled(boolean enabled) { /** * If this is set, then word wrapping the legend is enabled. This means the * legend will not be cut off if too long. - * + * * @return */ public boolean isWordWrapEnabled() { @@ -790,7 +751,7 @@ public boolean isWordWrapEnabled() { * affects the height of the legend. / If the legend is the center of the * piechart, then this defines the size of the rectangular bounds out of the * size of the "hole". / default: 0.95f (95%) - * + * * @return */ public float getMaxSizePercent() { @@ -802,45 +763,34 @@ public float getMaxSizePercent() { * the legend is to the right/left of the chart, then this affects the width * of the legend. / If the legend is to the top/bottom of the chart, then * this affects the height of the legend. / default: 0.95f (95%) - * + * * @param maxSize */ public void setMaxSizePercent(float maxSize) { mMaxSizePercent = maxSize; } - private boolean isCalculatedLineSizesArrayListResized = true; - private FSize[] mCalculatedLabelSizes = new FSize[] {}; - private Boolean[] mCalculatedLabelBreakPoints = new Boolean[] {}; - private FSize[] mCalculatedLineSizes = new FSize[] {}; + private List mCalculatedLabelSizes = new ArrayList<>(16); + private List mCalculatedLabelBreakPoints = new ArrayList<>(16); + private List mCalculatedLineSizes = new ArrayList<>(16); - public FSize[] getCalculatedLabelSizes() { + public List getCalculatedLabelSizes() { return mCalculatedLabelSizes; } - public Boolean[] getCalculatedLabelBreakPoints() { + public List getCalculatedLabelBreakPoints() { return mCalculatedLabelBreakPoints; } - public FSize[] getCalculatedLineSizes() { - if(mCalculatedLineSizes == null || isCalculatedLineSizesArrayListResized){ - - mCalculatedLineSizes = calculatedLineSizesForCalculateDimensions - .toArray(new FSize[calculatedLineSizesForCalculateDimensions.size()]); - - isCalculatedLineSizesArrayListResized = false; - - } + public List getCalculatedLineSizes() { return mCalculatedLineSizes; } - protected Paint.FontMetrics fontMetricsForCalculateDimensions = new Paint.FontMetrics(); - protected ArrayList calculatedLineSizesForCalculateDimensions = new ArrayList<>(); /** * Calculates the dimensions of the Legend. This includes the maximum width * and height of a single entry, as well as the total width and height of * the Legend. - * + * * @param labelpaint */ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandler) { @@ -852,7 +802,7 @@ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandle case VERTICAL: { float maxWidth = 0f, maxHeight = 0f, width = 0f; - float labelLineHeight = Utils.getLineHeight(labelpaint, fontMetricsForCalculateDimensions); + float labelLineHeight = Utils.getLineHeight(labelpaint); final int count = mLabels.length; boolean wasStacked = false; @@ -886,8 +836,7 @@ else if (wasStacked) { if (i < count - 1) maxHeight += labelLineHeight + mYEntrySpace; - } - else { + } else { wasStacked = true; width += mFormSize; if (i < count - 1) @@ -905,81 +854,44 @@ else if (wasStacked) { case HORIZONTAL: { int labelCount = mLabels.length; - float labelLineHeight = Utils.getLineHeight(labelpaint, fontMetricsForCalculateDimensions); - float labelLineSpacing = Utils.getLineSpacing(labelpaint, fontMetricsForCalculateDimensions) + mYEntrySpace; + float labelLineHeight = Utils.getLineHeight(labelpaint); + float labelLineSpacing = Utils.getLineSpacing(labelpaint) + mYEntrySpace; float contentWidth = viewPortHandler.contentWidth() * mMaxSizePercent; - // Prepare arrays for calculated layout - - //ArrayList calculatedLabelBreakPoints = new ArrayList(labelCount); - - if(mCalculatedLabelSizes.length != labelCount){ - FSize[] temp = new FSize[labelCount]; - int count = mCalculatedLabelSizes.length; - for(int i = 0 ; i < count && i < labelCount ; i++){ - temp[i] = mCalculatedLabelSizes[i]; - } - while(count > labelCount){ - count--; - FSize.recycleInstance(mCalculatedLabelSizes[count]); - } - mCalculatedLabelSizes = temp; - } - int calculatedLabelSizesIndex = 0; - - if(mCalculatedLabelBreakPoints.length != labelCount){ - mCalculatedLabelBreakPoints = new Boolean[labelCount]; - } - int calculatedLabelBreakIndex = 0; - - ArrayList calculatedLineSizes = calculatedLineSizesForCalculateDimensions; - FSize.recycleInstances(calculatedLineSizes); - calculatedLineSizes.clear(); - // Start calculating layout float maxLineWidth = 0.f; float currentLineWidth = 0.f; float requiredWidth = 0.f; int stackedStartIndex = -1; + mCalculatedLabelBreakPoints.clear(); + mCalculatedLabelSizes.clear(); + mCalculatedLineSizes.clear(); + for (int i = 0; i < labelCount; i++) { boolean drawingForm = mColors[i] != ColorTemplate.COLOR_SKIP; - mCalculatedLabelBreakPoints[calculatedLabelBreakIndex] = false; - calculatedLabelBreakIndex++; + mCalculatedLabelBreakPoints.add(false); if (stackedStartIndex == -1) { // we are not stacking, so required width is for this label // only requiredWidth = 0.f; - } - else { + } else { // add the spacing appropriate for stacked labels/forms requiredWidth += mStackSpace; } // grouped forms have null labels if (mLabels[i] != null) { - if(mCalculatedLabelSizes[calculatedLabelSizesIndex] == null){ - mCalculatedLabelSizes[calculatedLabelSizesIndex] = Utils.calcTextSize(labelpaint, mLabels[i]); - }else{ - Utils.calcTextSize(labelpaint, mLabels[i], mCalculatedLabelSizes[calculatedLabelSizesIndex]); - } - FSize labelSize = mCalculatedLabelSizes[calculatedLabelSizesIndex]; - calculatedLabelSizesIndex++; + + mCalculatedLabelSizes.add(Utils.calcTextSize(labelpaint, mLabels[i])); requiredWidth += drawingForm ? mFormToTextSpace + mFormSize : 0.f; - requiredWidth += labelSize.width; - } - else { + requiredWidth += mCalculatedLabelSizes.get(i).width; + } else { - if(mCalculatedLabelSizes[calculatedLabelSizesIndex] == null){ - mCalculatedLabelSizes[calculatedLabelSizesIndex] = FSize.getInstance(0.f, 0.f); - }else{ - mCalculatedLabelSizes[calculatedLabelSizesIndex].width = 0.f; - mCalculatedLabelSizes[calculatedLabelSizesIndex].height = 0.f; - } - calculatedLabelSizesIndex++; + mCalculatedLabelSizes.add(FSize.getInstance(0.f, 0.f)); requiredWidth += drawingForm ? mFormSize : 0.f; if (stackedStartIndex == -1) { @@ -1000,23 +912,22 @@ else if (wasStacked) { requiredSpacing + requiredWidth)) { // Expand current line currentLineWidth += requiredSpacing + requiredWidth; - } - else { // It doesn't fit, we need to wrap a line + } else { // It doesn't fit, we need to wrap a line // Add current line size to array - calculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); + mCalculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); maxLineWidth = Math.max(maxLineWidth, currentLineWidth); // Start a new line - mCalculatedLabelBreakPoints[ + mCalculatedLabelBreakPoints.set( stackedStartIndex > -1 ? stackedStartIndex - : i] = true; + : i, true); currentLineWidth = requiredWidth; } if (i == labelCount - 1) { // Add last line size to array - calculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); + mCalculatedLineSizes.add(FSize.getInstance(currentLineWidth, labelLineHeight)); maxLineWidth = Math.max(maxLineWidth, currentLineWidth); } } @@ -1024,24 +935,19 @@ else if (wasStacked) { stackedStartIndex = mLabels[i] != null ? -1 : stackedStartIndex; } - if(calculatedLineSizes.size() != mCalculatedLineSizes.length) { - isCalculatedLineSizesArrayListResized = true; - }else{ - for(int i = 0 ; i < mCalculatedLineSizes.length ; i++){ - mCalculatedLineSizes[i] = calculatedLineSizes.get(i); - } - } - mNeededWidth = maxLineWidth; mNeededHeight = labelLineHeight - * (float) (mCalculatedLineSizes.length) + * (float) (mCalculatedLineSizes.size()) + labelLineSpacing * - (float) (mCalculatedLineSizes.length == 0 + (float) (mCalculatedLineSizes.size() == 0 ? 0 - : (mCalculatedLineSizes.length - 1)); + : (mCalculatedLineSizes.size() - 1)); break; } } + + mNeededHeight += mYOffset; + mNeededWidth += mXOffset; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index fb8937a303..f621afcf35 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -70,8 +70,10 @@ public Paint getFormPaint() { return mLegendFormPaint; } - protected ArrayList labelsForComputeLegend = new ArrayList<>(16); - protected ArrayList colorsForComputeLegend = new ArrayList<>(16); + + protected List computedLabels = new ArrayList<>(16); + protected List computedColors = new ArrayList<>(16); + /** * Prepares the legend and calculates all needed forms, labels and colors. * @@ -81,11 +83,8 @@ public void computeLegend(ChartData data) { if (!mLegend.isLegendCustom()) { - ArrayList labels = labelsForComputeLegend; - ArrayList colors = colorsForComputeLegend; - - labels.clear(); - colors.clear(); + computedLabels.clear(); + computedColors.clear(); // loop for building up the colors and labels used in the legend for (int i = 0; i < data.getDataSetCount(); i++) { @@ -103,14 +102,14 @@ public void computeLegend(ChartData data) { for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { - labels.add(sLabels[j % sLabels.length]); - colors.add(clrs.get(j)); + computedLabels.add(sLabels[j % sLabels.length]); + computedColors.add(clrs.get(j)); } if (bds.getLabel() != null) { // add the legend description label - colors.add(ColorTemplate.COLOR_SKIP); - labels.add(bds.getLabel()); + computedColors.add(ColorTemplate.COLOR_SKIP); + computedLabels.add(bds.getLabel()); } } else if (dataSet instanceof IPieDataSet) { @@ -119,27 +118,27 @@ public void computeLegend(ChartData data) { for (int j = 0; j < clrs.size() && j < entryCount; j++) { - labels.add(pds.getEntryForIndex(j).getLabel()); - colors.add(clrs.get(j)); + computedLabels.add(pds.getEntryForIndex(j).getLabel()); + computedColors.add(clrs.get(j)); } if (pds.getLabel() != null) { // add the legend description label - colors.add(ColorTemplate.COLOR_SKIP); - labels.add(pds.getLabel()); + computedColors.add(ColorTemplate.COLOR_SKIP); + computedLabels.add(pds.getLabel()); } } else if (dataSet instanceof ICandleDataSet && ((ICandleDataSet) dataSet).getDecreasingColor() != ColorTemplate.COLOR_NONE) { int decreasingColor = ((ICandleDataSet) dataSet).getDecreasingColor(); - colors.add(decreasingColor); + computedColors.add(decreasingColor); int increasingColor = ((ICandleDataSet) dataSet).getIncreasingColor(); - colors.add(increasingColor); + computedColors.add(increasingColor); - labels.add(null); - labels.add(dataSet.getLabel()); + computedLabels.add(null); + computedLabels.add(dataSet.getLabel()); } else { // all others @@ -148,26 +147,26 @@ public void computeLegend(ChartData data) { // if multiple colors are set for a DataSet, group them if (j < clrs.size() - 1 && j < entryCount - 1) { - labels.add(null); + computedLabels.add(null); } else { // add label to the last entry String label = data.getDataSetByIndex(i).getLabel(); - labels.add(label); + computedLabels.add(label); } - colors.add(clrs.get(j)); + computedColors.add(clrs.get(j)); } } } if (mLegend.getExtraColors() != null && mLegend.getExtraLabels() != null) { for (int color : mLegend.getExtraColors()) - colors.add(color); - Collections.addAll(labels, mLegend.getExtraLabels()); + computedColors.add(color); + Collections.addAll(computedLabels, mLegend.getExtraLabels()); } - mLegend.setComputedColors(colors); - mLegend.setComputedLabels(labels); + mLegend.setComputedColors(computedColors); + mLegend.setComputedLabels(computedLabels); } Typeface tf = mLegend.getTypeface(); @@ -182,7 +181,8 @@ public void computeLegend(ChartData data) { mLegend.calculateDimensions(mLegendLabelPaint, mViewPortHandler); } - protected Paint.FontMetrics fontMetricsForRenderLegent = new Paint.FontMetrics(); + protected Paint.FontMetrics legendFontMetrics = new Paint.FontMetrics(); + public void renderLegend(Canvas c) { if (!mLegend.isEnabled()) @@ -196,8 +196,8 @@ public void renderLegend(Canvas c) { mLegendLabelPaint.setTextSize(mLegend.getTextSize()); mLegendLabelPaint.setColor(mLegend.getTextColor()); - float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint, fontMetricsForRenderLegent); - float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, fontMetricsForRenderLegent) + mLegend.getYEntrySpace(); + float labelLineHeight = Utils.getLineHeight(mLegendLabelPaint, legendFontMetrics); + float labelLineSpacing = Utils.getLineSpacing(mLegendLabelPaint, legendFontMetrics) + mLegend.getYEntrySpace(); float formYOffset = labelLineHeight - Utils.calcTextHeight(mLegendLabelPaint, "ABC") / 2.f; String[] labels = mLegend.getLabels(); @@ -269,11 +269,11 @@ public void renderLegend(Canvas c) { switch (orientation) { case HORIZONTAL: { - FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); - FSize[] calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); - Boolean[] calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints(); + List calculatedLineSizes = mLegend.getCalculatedLineSizes(); + List calculatedLabelSizes = mLegend.getCalculatedLabelSizes(); + List calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints(); - float posX = originPosX; + float posX = originPosX + xoffset; float posY = 0.f; switch (verticalAlignment) { @@ -293,17 +293,17 @@ public void renderLegend(Canvas c) { int lineIndex = 0; for (int i = 0, count = labels.length; i < count; i++) { - if (i < calculatedLabelBreakPoints.length && calculatedLabelBreakPoints[i]) { + if (i < calculatedLabelBreakPoints.size() && calculatedLabelBreakPoints.get(i)) { posX = originPosX; posY += labelLineHeight + labelLineSpacing; } if (posX == originPosX && horizontalAlignment == Legend.LegendHorizontalAlignment.CENTER && - lineIndex < calculatedLineSizes.length) { + lineIndex < calculatedLineSizes.size()) { posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT - ? calculatedLineSizes[lineIndex].width - : -calculatedLineSizes[lineIndex].width) / 2.f; + ? calculatedLineSizes.get(lineIndex).width + : -calculatedLineSizes.get(lineIndex).width) / 2.f; lineIndex++; } @@ -326,12 +326,12 @@ public void renderLegend(Canvas c) { formToTextSpace; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) - posX -= calculatedLabelSizes[i].width; + posX -= calculatedLabelSizes.get(i).width; drawLabel(c, posX, posY + labelLineHeight, labels[i]); if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) - posX += calculatedLabelSizes[i].width; + posX += calculatedLabelSizes.get(i).width; posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -xEntrySpace : xEntrySpace; } else @@ -372,7 +372,7 @@ public void renderLegend(Canvas c) { for (int i = 0; i < labels.length; i++) { Boolean drawingForm = colors[i] != ColorTemplate.COLOR_SKIP; - float posX = originPosX; + float posX = originPosX + xoffset; if (drawingForm) { if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 0799679114..bee377dcf9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -163,9 +163,10 @@ public static int calcTextHeight(Paint paint, String demoText) { return r.height(); } + private static Paint.FontMetrics mFontMetrics = new Paint.FontMetrics(); + public static float getLineHeight(Paint paint) { - Paint.FontMetrics metrics = new Paint.FontMetrics(); - return getLineHeight(paint, metrics); + return getLineHeight(paint, mFontMetrics); } public static float getLineHeight(Paint paint, Paint.FontMetrics fontMetrics){ @@ -174,8 +175,7 @@ public static float getLineHeight(Paint paint, Paint.FontMetrics fontMetrics){ } public static float getLineSpacing(Paint paint) { - Paint.FontMetrics metrics = new Paint.FontMetrics(); - return getLineSpacing(paint, metrics); + return getLineSpacing(paint, mFontMetrics); } public static float getLineSpacing(Paint paint, Paint.FontMetrics fontMetrics){ From 8c67ec19f73b01c059f65c6631356680717ac693 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 8 Jul 2016 19:15:52 +0200 Subject: [PATCH 1093/1390] Fix #1978 --- .../charting/renderer/BarChartRenderer.java | 4 ++-- .../BarLineScatterCandleBubbleRenderer.java | 17 +++++++++++++++-- .../charting/renderer/BubbleChartRenderer.java | 4 ++-- .../renderer/CandleStickChartRenderer.java | 4 ++-- .../renderer/HorizontalBarChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 4 ++-- .../charting/renderer/RadarChartRenderer.java | 5 ++--- .../charting/renderer/ScatterChartRenderer.java | 2 +- 8 files changed, 27 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index cffcc1c3da..3260d4c470 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -74,7 +74,7 @@ public void drawData(Canvas c) { IBarDataSet set = barData.getDataSetByIndex(i); - if (set.isVisible() && set.getEntryCount() > 0) { + if (set.isVisible()) { drawDataSet(c, set, i); } } @@ -195,7 +195,7 @@ public void drawValues(Canvas c) { IBarDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java index aa400caa61..8f2447d960 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarLineScatterCandleBubbleRenderer.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -12,13 +13,25 @@ */ public abstract class BarLineScatterCandleBubbleRenderer extends DataRenderer { - /** buffer for storing the current minimum and maximum visible x */ + /** + * buffer for storing the current minimum and maximum visible x + */ protected XBounds mXBounds = new XBounds(); public BarLineScatterCandleBubbleRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); } + /** + * Returns true if the DataSet values should be drawn, false if not. + * + * @param set + * @return + */ + protected boolean shouldDrawValues(IDataSet set) { + return set.isVisible() && set.isDrawValuesEnabled(); + } + /** * Checks if the provided entry object is in bounds for drawing considering the current animation phase. * @@ -66,7 +79,7 @@ protected class XBounds { * @param chart * @param dataSet */ - public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet){ + public void set(BarLineScatterCandleBubbleDataProvider chart, IBarLineScatterCandleBubbleDataSet dataSet) { float phaseX = Math.max(0.f, Math.min(1.f, mAnimator.getPhaseX())); float low = chart.getLowestVisibleX(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 6ff540cc7c..458a46f884 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -52,7 +52,7 @@ public void drawData(Canvas c) { for (int i = 0; i < setCount; i++) { set = dataSets.get(i); - if (set.isVisible() && set.getEntryCount() > 0) + if (set.isVisible()) drawDataSet(c, set); } } @@ -133,7 +133,7 @@ public void drawValues(Canvas c) { IBubbleDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 2aa11482f0..734b4301e5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -50,7 +50,7 @@ public void drawData(Canvas c) { for (int i = 0; i < setCount; i++) { set = dataSets.get(i); - if (set.isVisible() && set.getEntryCount() > 0) + if (set.isVisible()) drawDataSet(c, set); } } @@ -266,7 +266,7 @@ public void drawValues(Canvas c) { ICandleDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 66f3e96539..2162a28b06 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -116,7 +116,7 @@ public void drawValues(Canvas c) { IBarDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index aac9440111..48c7a4be3c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -94,7 +94,7 @@ public void drawData(Canvas c) { for (int i = 0; i < setCount; i++) { set = lineData.getDataSets().get(i); - if (set.isVisible() && set.getEntryCount() > 0) + if (set.isVisible()) drawDataSet(c, set); } @@ -519,7 +519,7 @@ public void drawValues(Canvas c) { ILineDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index c346c6f6a3..4d0a8d9b0f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -5,7 +5,6 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.PointF; import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; @@ -70,7 +69,7 @@ public void drawData(Canvas c) { for(int i = 0 ; i < setCount ; i++){ set = dataSets.get(i); - if (set.isVisible() && set.getEntryCount() > 0) { + if (set.isVisible()) { drawDataSet(c, set, mostEntries); } } @@ -174,7 +173,7 @@ public void drawValues(Canvas c) { IRadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 1d45c4974d..484bcba551 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -94,7 +94,7 @@ public void drawValues(Canvas c) { IScatterDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) + if (!shouldDrawValues(dataSet)) continue; // apply the text-styling defined by the DataSet From d7e659a1fac34f1d187d2ac259a415302ba2cadf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 9 Jul 2016 15:42:17 +0200 Subject: [PATCH 1094/1390] Change max-highlight-distance default to 500dp --- .../main/java/com/github/mikephil/charting/charts/Chart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index c4fc594cc0..f6596aaccc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -229,7 +229,7 @@ public void onAnimationUpdate(ValueAnimator animation) { // initialize the utils Utils.init(getContext()); - mMaxHighlightDistance = Utils.convertDpToPixel(100f); + mMaxHighlightDistance = Utils.convertDpToPixel(500f); mLegend = new Legend(); From 4d5ce149dd6cbb9c72975d479588c7d7d075d867 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 16 Jul 2016 15:17:54 +0200 Subject: [PATCH 1095/1390] Ignore ds_store files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 31581642ab..a340b1d6b3 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ build/ # maven target/ + +.DS_Store From 37c4eef38eb707e359dc5cec6383007fe9bed1a5 Mon Sep 17 00:00:00 2001 From: Philipp Date: Sat, 16 Jul 2016 15:41:37 +0200 Subject: [PATCH 1096/1390] Update build tools --- MPChartExample/build.gradle | 2 +- MPChartLib/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 9605392372..c0d4745dcc 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'realm-android' android { compileSdkVersion 23 - buildToolsVersion '23.0.2' + buildToolsVersion '23.0.3' defaultConfig { minSdkVersion 16 targetSdkVersion 23 diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index f8f8455805..b3e89b84fa 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -5,7 +5,7 @@ apply plugin: 'maven' android { compileSdkVersion 23 - buildToolsVersion '23.0.2' + buildToolsVersion '23.0.3' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 9 From ef575decbb572a71b8055d8742172be868826d78 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 16 Jul 2016 15:43:26 +0200 Subject: [PATCH 1097/1390] Remove old screenshot --- screenshots/simpledesign_barchart1.png | Bin 179237 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 screenshots/simpledesign_barchart1.png diff --git a/screenshots/simpledesign_barchart1.png b/screenshots/simpledesign_barchart1.png deleted file mode 100644 index e1c3f14155cc6c6a9b337a8e709a537efbb9b2aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 179237 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െ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 Date: Sat, 16 Jul 2016 22:51:08 +0200 Subject: [PATCH 1098/1390] Create new XYMarkerView (#2029) --- .../mpchartexample/custom/XYMarkerView.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java new file mode 100644 index 0000000000..772927b02c --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -0,0 +1,7 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +/** + * Created by philipp on 16/07/16. + */ +public class XYMarkerView { +} From 3ea1db57abb08780d6c0182480c3eda5a09050a9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 16 Jul 2016 22:53:01 +0200 Subject: [PATCH 1099/1390] Create example for XYMarkerView (#2029) --- .../mpchartexample/BarChartActivity.java | 7 ++- .../custom/DayAxisValueFormatter.java | 2 +- .../mpchartexample/custom/XYMarkerView.java | 53 ++++++++++++++++++- 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index eb17690354..b51735f1e6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -37,6 +37,7 @@ import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.XYMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -79,13 +80,15 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); + AxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(mChart); + XAxis xAxis = mChart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setTypeface(mTfLight); xAxis.setDrawGridLines(false); xAxis.setGranularity(1f); // only intervals of 1 day xAxis.setLabelCount(7); - xAxis.setValueFormatter(new DayAxisValueFormatter(mChart)); + xAxis.setValueFormatter(xAxisFormatter); AxisValueFormatter custom = new MyAxisValueFormatter(); @@ -116,6 +119,8 @@ protected void onCreate(Bundle savedInstanceState) { // l.setCustom(ColorTemplate.VORDIPLOM_COLORS, new String[] { "abc", // "def", "ghj", "ikl", "mno" }); + mChart.setMarkerView(new XYMarkerView(this, xAxisFormatter)); + setData(12, 50); // setting data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 8e906c4921..d989104e48 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -32,7 +32,7 @@ public String getFormattedValue(float value, AxisBase axis) { String monthName = mMonths[month % mMonths.length]; String yearName = String.valueOf(year); - if (chart.getVisibleXRange() > 30 * axis.getLabelCount()) { + if (chart.getVisibleXRange() > 30 * 6) { return monthName + " " + yearName; } else { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 772927b02c..6bfa313c77 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,7 +1,56 @@ + package com.xxmassdeveloper.mpchartexample.custom; +import android.content.Context; +import android.widget.TextView; + +import com.github.mikephil.charting.components.MarkerView; +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.AxisValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.Utils; +import com.xxmassdeveloper.mpchartexample.R; + +import java.text.DecimalFormat; + /** - * Created by philipp on 16/07/16. + * Custom implementation of the MarkerView. + * + * @author Philipp Jahoda */ -public class XYMarkerView { +public class XYMarkerView extends MarkerView { + + private TextView tvContent; + private AxisValueFormatter xAxisValueFormatter; + + private DecimalFormat format; + + public XYMarkerView(Context context, AxisValueFormatter xAxisValueFormatter) { + super(context, R.layout.custom_marker_view); + + this.xAxisValueFormatter = xAxisValueFormatter; + tvContent = (TextView) findViewById(R.id.tvContent); + format = new DecimalFormat("###.0"); + } + + // callbacks everytime the MarkerView is redrawn, can be used to update the + // content (user-interface) + @Override + public void refreshContent(Entry e, Highlight highlight) { + + tvContent.setText("x: " + xAxisValueFormatter.getFormattedValue(e.getX(), null) + ", y: " + format.format(e.getY())); + } + + @Override + public int getXOffset(float xpos) { + // this will center the marker-view horizontally + return -(getWidth() / 2); + } + + @Override + public int getYOffset(float ypos) { + // this will cause the marker-view to be above the selected value + return -getHeight(); + } } From a91de26a5291471d9e705d0836771636bc2725b8 Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sun, 7 Aug 2016 10:17:18 +0200 Subject: [PATCH 1100/1390] axis line dash effect --- .../charting/components/AxisBase.java | 57 +++++++++++++++++++ .../charting/renderer/XAxisRenderer.java | 1 + 2 files changed, 58 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 378a3eb49e..d21675d613 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -92,6 +92,11 @@ public abstract class AxisBase extends ComponentBase { protected boolean mCenterAxisLabels = false; + /** + * the path effect of the axis line that makes dashed lines possible + */ + private DashPathEffect mAxisLineDashPathEffect = null; + /** * the path effect of the grid lines that makes dashed lines possible */ @@ -524,6 +529,58 @@ public boolean isGridDashedLineEnabled() { public DashPathEffect getGridDashPathEffect() { return mGridDashPathEffect; } + + + /** + * Enables the axis line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. + * + * @param lineLength the length of the line pieces + * @param spaceLength the length of space in between the pieces + * @param phase offset, in degrees (normally, use 0) + */ + public void enableAxisLineDashedLine(float lineLength, float spaceLength, float phase) { + mAxisLineDashPathEffect = new DashPathEffect(new float[]{ + lineLength, spaceLength + }, phase); + } + + /** + * Enables the axis line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. + * + * @param effect the DashPathEffect + */ + public void setAxisLineDashedLine(DashPathEffect effect) { + mAxisLineDashPathEffect = effect; + } + + /** + * Disables the axis line to be drawn in dashed mode. + */ + public void disableAxisLineDashedLine() { + mAxisLineDashPathEffect = null; + } + + /** + * Returns true if the axis dashed-line effect is enabled, false if not. + * + * @return + */ + public boolean isAxisLineDashedLineEnabled() { + return mAxisLineDashPathEffect == null ? false : true; + } + + /** + * returns the DashPathEffect that is set for axis line + * + * @return + */ + public DashPathEffect getAxisLineDashPathEffect() { + return mAxisLineDashPathEffect; + } /** * ###### BELOW CODE RELATED TO CUSTOM AXIS VALUES ###### diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 1973aa3a47..4410ba1122 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -152,6 +152,7 @@ public void renderAxisLine(Canvas c) { mAxisLinePaint.setColor(mXAxis.getAxisLineColor()); mAxisLinePaint.setStrokeWidth(mXAxis.getAxisLineWidth()); + mAxisLinePaint.setPathEffect(mXAxis.getAxisLineDashPathEffect()); if (mXAxis.getPosition() == XAxisPosition.TOP || mXAxis.getPosition() == XAxisPosition.TOP_INSIDE From 2f6fb103a239a291b6e55d4fdebf4cd6b028d97d Mon Sep 17 00:00:00 2001 From: Martin Guillon Date: Sun, 7 Aug 2016 10:17:32 +0200 Subject: [PATCH 1101/1390] method to set the dash effect --- .../github/mikephil/charting/components/AxisBase.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index d21675d613..02ff48a397 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -504,6 +504,17 @@ public void enableGridDashedLine(float lineLength, float spaceLength, float phas lineLength, spaceLength }, phase); } + + /** + * Enables the grid line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. + * + * @param effect the DashPathEffect + */ + public void setGridDashedLine(DashPathEffect effect) { + mGridDashPathEffect = effect; + } /** * Disables the grid line to be drawn in dashed mode. From 099a9cf8c19ea695865229e339fa9fb013959d7c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 7 Aug 2016 10:55:42 +0200 Subject: [PATCH 1102/1390] Minor changes --- .../main/java/com/github/mikephil/charting/charts/Chart.java | 2 +- .../src/main/java/com/github/mikephil/charting/data/Entry.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index f6596aaccc..ec4d38402b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -497,7 +497,7 @@ public float getMaxHighlightDistance() { /** * Sets the maximum distance in screen dp a touch can be away from an entry to cause it to get highlighted. - * Default: 100dp + * Default: 500dp * * @param distDp */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java index f5847a029d..6848540aaa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/Entry.java @@ -101,7 +101,7 @@ public boolean equalTo(Entry e) { */ @Override public String toString() { - return "Entry, x: " + x + " y (sum): " + getY(); + return "Entry, x: " + x + " y: " + getY(); } @Override From 946475b6d5317f1fcbdf071214d6676c56c0463b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 7 Aug 2016 22:34:41 +0200 Subject: [PATCH 1103/1390] Add grouped barchart wiki image --- screenshots/grouped_barchart_wiki.png | Bin 0 -> 46857 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/grouped_barchart_wiki.png diff --git a/screenshots/grouped_barchart_wiki.png b/screenshots/grouped_barchart_wiki.png new file mode 100644 index 0000000000000000000000000000000000000000..c4d9e66836c57a4a54383d2007402343979d6794 GIT binary patch literal 46857 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 Date: Sun, 7 Aug 2016 22:52:40 +0200 Subject: [PATCH 1104/1390] Add wiki piechart --- screenshots/piechart_wiki.png | Bin 0 -> 152866 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 screenshots/piechart_wiki.png diff --git a/screenshots/piechart_wiki.png b/screenshots/piechart_wiki.png new file mode 100644 index 0000000000000000000000000000000000000000..deaed3613705c5e6baebd24c07c1e8536251ecda GIT binary patch literal 152866 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

    + +Add the library to your Android project, then check out the examples below! -**Gradle** +### Gradle Setup -- **Project level `build.gradle`** ```gradle -allprojects { - repositories { - maven { url 'https://jitpack.io' } - } +repositories { + maven { url 'https://jitpack.io' } } -``` -- **App level `build.gradle`** -```gradle + dependencies { implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' } ``` -**Maven** +### Maven Setup ```xml @@ -56,7 +66,6 @@ dependencies { https://jitpack.io - com.github.PhilJay @@ -67,7 +76,7 @@ dependencies {
    -## Documentation :notebook_with_decorative_cover: +

    Documentation :notebook_with_decorative_cover:

    See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. @@ -75,14 +84,14 @@ See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0
    -## Examples :eyes: +

    Examples :eyes:

    Download the [MPAndroidChart Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) or look at the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample). [![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI)
    -## Questions & Issues :thinking: +

    Questions & Issues :thinking:

    This repository's issue tracker is only for bugs and feature requests. The maintainers ask that you refrain from asking questions about how to use MPAndroidChart through the issue tracker. @@ -90,7 +99,7 @@ Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wi
    -## Donations :heart: + **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! @@ -106,13 +115,13 @@ Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wi - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! - [**Donate 10 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4C9TPE67F5PUQ): Wow, I am stunned. Let me take you to the movies! -- [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! +- [**Donate 15 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YKMPTFMVK3JMC): I really appreciate your work, let's grab some lunch! - [**Donate 25 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - Or you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome!
    -## Social Media :fire: +

    Social Media :fire:

    If you like this library, please tell others about it :two_hearts: :two_hearts: @@ -124,7 +133,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah
    -## More Examples :+1: +

    More Examples :+1:


    @@ -194,7 +203,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah
    -# License :page_facing_up: +

    License :page_facing_up:

    Copyright 2018 Philipp Jahoda @@ -202,7 +211,7 @@ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +> http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, @@ -212,7 +221,7 @@ limitations under the License.
    -## Special Thanks :heart: +

    Special Thanks :heart:

    These people rock! diff --git a/build.gradle b/build.gradle index fb18d8fe7d..58f50401d3 100644 --- a/build.gradle +++ b/build.gradle @@ -4,9 +4,8 @@ buildscript { google() } dependencies { - classpath "io.realm:realm-gradle-plugin:4.2.0" classpath 'com.android.tools.build:gradle:3.2.1' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } } From 9148f37f9eca975335bf64a9096808e659343610 Mon Sep 17 00:00:00 2001 From: almic Date: Mon, 29 Oct 2018 13:23:18 -0600 Subject: [PATCH 1323/1390] Bump version to 3.1.0-alpha --- .github/ISSUE_TEMPLATE.md | 4 ++-- .github/ISSUE_TEMPLATE/Bug_report.md | 4 ++-- .github/ISSUE_TEMPLATE/Support_help.md | 2 +- MPChartExample/build.gradle | 2 +- .../xxmassdeveloper/mpchartexample/LineChartActivity1.java | 2 +- .../xxmassdeveloper/mpchartexample/LineChartActivity2.java | 2 +- MPChartLib/build.gradle | 2 +- README.md | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 49ed0dfc1d..b75838b907 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -28,10 +28,10 @@ cannot answer support questions here. We will close your issue without a respons **Device (please complete the following information):** - Device: [e.g. Google Pixel] - Android Version [e.g. 7.0] - - Library Version (e.g. 3.0.3) + - Library Version (e.g. 3.1.0-alpha) **Additional Context** diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 496d0a0d8d..7989a9d655 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -33,10 +33,10 @@ support questions here. We will close your issue without a response. **Device (please complete the following information):** - Device: [e.g. Google Pixel] - Android Version [e.g. 7.0] - - Library Version (e.g. 3.0.3) + - Library Version (e.g. 3.1.0-alpha) **Additional Context** diff --git a/.github/ISSUE_TEMPLATE/Support_help.md b/.github/ISSUE_TEMPLATE/Support_help.md index 64c87763df..5a2c5fd41b 100644 --- a/.github/ISSUE_TEMPLATE/Support_help.md +++ b/.github/ISSUE_TEMPLATE/Support_help.md @@ -14,7 +14,7 @@ Instead, do the following: 1. Download the [Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) and check out the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample). 90% of the time there is an example that does exactly what you are trying to do. -1. Look at the [Wiki](https://github.com/PhilJay/MPAndroidChart/wiki) for the official documentation for MPAndroidChart. You can also browse the [javadoc](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for a more detailed tutorial of the API. +1. Look at the [Wiki](https://github.com/PhilJay/MPAndroidChart/wiki) for the official documentation for MPAndroidChart. You can also browse the [javadoc](https://jitpack.io/com/github/philjay/mpandroidchart/v3.1.0-alpha/javadoc/) for a more detailed tutorial of the API. 1. Go to [StackOverflow](https://stackoverflow.com/questions/tagged/mpandroidchart) and ask your questions there. The community will be much more helpful and willing to offer guidance. diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 647aca2b51..0a60389ede 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,7 +7,7 @@ android { minSdkVersion 16 targetSdkVersion 28 versionCode 56 - versionName '3.0.3' + versionName '3.1.0' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 9505838810..dd43b056eb 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -45,7 +45,7 @@ * Example of a heavily customized {@link LineChart} with limit lines, custom line shapes, etc. * * @since 1.7.4 - * @version 3.0.3 + * @version 3.1.0 */ public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9e0c98f89b..6b9cbb5f22 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -38,7 +38,7 @@ * Example of a dual axis {@link LineChart} with multiple data sets. * * @since 1.7.4 - * @version 3.0.3 + * @version 3.1.0 */ public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 881cfd5365..0fb6dc7036 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -10,7 +10,7 @@ android { minSdkVersion 14 targetSdkVersion 28 versionCode 3 - versionName '3.0.3' + versionName '3.1.0' } buildTypes { release { diff --git a/README.md b/README.md index d6c9ea60d2..2e031bdf93 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ repositories { } dependencies { - implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha' } ``` @@ -70,7 +70,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.0.3 + v3.1.0-alpha ``` @@ -80,7 +80,7 @@ dependencies { See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. -See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.0.3/javadoc/) for more advanced documentation. +See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0-alpha/javadoc/) for more advanced documentation.
    From 608d9e29f59ebd63e234e13a4b4e1f3b3158e8c7 Mon Sep 17 00:00:00 2001 From: Mick A Date: Tue, 30 Oct 2018 08:59:58 -0600 Subject: [PATCH 1324/1390] Fix link error --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2e031bdf93..53f278aba7 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,7 @@ See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1

    Examples :eyes:

    + Download the [MPAndroidChart Example App](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample) or look at the [source code](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample). [![ScreenShot](https://github.com/PhilJay/MPAndroidChart/blob/master/design/video_thumbnail.png)](https://www.youtube.com/watch?v=ufaK_Hd6BpI) From e5b66192e7b303d7d25fc172b1878c055b554047 Mon Sep 17 00:00:00 2001 From: almic Date: Wed, 7 Nov 2018 12:41:53 -0700 Subject: [PATCH 1325/1390] New ValueFormatter I created a simplified value formatter class, which is an abstract class rather than an interface. The switch was chosen because the new format has all the methods predefined (something an interface wouldn't allow) meaning you can extend it and only change what you want. This also means that you only need one value formatting class for labels rather than two different classes, it just makes more sense. Please check the method signatures to learn how to use them, I'm sure you'll find this new format is much more customizable and faster to use. I've made the class abstract even though there are no abstract methods or fields, this is because it would certainly be a mistake to create a ValueFormatter and not override any methods. To convert existing code, just use 'extends' instead of 'implements' and change the names to 'ValueFormatter'. You'll need to change the methods you overwrite as well, just check the class and use the one you need. --- .gitignore | 6 +- .../mpchartexample/BarChartActivity.java | 9 +- .../BarChartActivityMultiDataset.java | 8 +- .../BarChartPositiveNegative.java | 19 +-- .../mpchartexample/CombinedChartActivity.java | 8 +- .../mpchartexample/LineChartTime.java | 8 +- .../mpchartexample/PieChartActivity.java | 2 +- .../mpchartexample/RadarChartActivity.java | 8 +- .../mpchartexample/StackedBarActivity.java | 6 +- .../StackedBarActivityNegative.java | 21 +-- .../custom/DayAxisValueFormatter.java | 7 +- .../custom/MyAxisValueFormatter.java | 21 --- .../custom/MyCustomXAxisValueFormatter.java | 7 +- .../custom/MyValueFormatter.java | 27 +++- .../mpchartexample/custom/XYMarkerView.java | 9 +- .../custom/YearXAxisFormatter.java | 6 +- .../mikephil/charting/charts/Chart.java | 5 +- .../charting/components/AxisBase.java | 11 +- .../mikephil/charting/data/BaseDataSet.java | 8 +- .../mikephil/charting/data/ChartData.java | 5 +- .../formatter/DefaultAxisValueFormatter.java | 8 +- .../formatter/DefaultValueFormatter.java | 8 +- .../formatter/IAxisValueFormatter.java | 6 + .../charting/formatter/IValueFormatter.java | 10 +- .../formatter/IndexAxisValueFormatter.java | 12 +- .../formatter/LargeValueFormatter.java | 16 +- .../charting/formatter/PercentFormatter.java | 39 +++-- .../formatter/StackedValueFormatter.java | 24 ++- .../charting/formatter/ValueFormatter.java | 137 ++++++++++++++++++ .../dataprovider/ChartInterface.java | 4 +- .../interfaces/datasets/IDataSet.java | 7 +- .../charting/renderer/BarChartRenderer.java | 25 ++-- .../renderer/BubbleChartRenderer.java | 13 +- .../renderer/CandleStickChartRenderer.java | 20 +-- .../renderer/CombinedChartRenderer.java | 7 +- .../charting/renderer/DataRenderer.java | 21 +-- .../renderer/HorizontalBarChartRenderer.java | 17 +-- .../charting/renderer/LineChartRenderer.java | 13 +- .../charting/renderer/PieChartRenderer.java | 29 ++-- .../charting/renderer/RadarChartRenderer.java | 20 +-- .../renderer/ScatterChartRenderer.java | 19 +-- .../charting/renderer/XAxisRenderer.java | 3 +- .../XAxisRendererHorizontalBarChart.java | 7 +- .../renderer/XAxisRendererRadarChart.java | 4 +- .../github/mikephil/charting/utils/Utils.java | 24 ++- .../test/LargeValueFormatterTest.java | 50 +++---- .../charting/test/ObjectPoolTest.java | 2 +- 47 files changed, 408 insertions(+), 338 deletions(-) delete mode 100644 MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java diff --git a/.gitignore b/.gitignore index a340b1d6b3..1120426ac8 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ bin/ gen/ generated/ -docs/ finalOutput/ build.xml @@ -23,6 +22,8 @@ local.properties # Eclipse project files .classpath .project +.settings/ +.vscode/ # Proguard folder generated by Eclipse proguard/ @@ -31,7 +32,8 @@ proguard/ *.iml *.ipr *.iws -.idea/ +/.idea/* +!/.idea/runConfigurations .directory diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 77875972c3..4af0441ddb 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -28,7 +27,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -36,7 +35,7 @@ import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.XYMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -86,7 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { chart.setDrawGridBackground(false); // chart.setDrawYLabels(false); - IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); + ValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); @@ -96,7 +95,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setLabelCount(7); xAxis.setValueFormatter(xAxisFormatter); - IAxisValueFormatter custom = new MyAxisValueFormatter(); + ValueFormatter custom = new MyValueFormatter("$"); YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tfLight); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 075af0edbc..3369dbf6e2 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -17,7 +16,6 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -25,8 +23,8 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.LargeValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -100,9 +98,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(tfLight); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return String.valueOf((int) value); } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 4fec7dd6ab..8960dc770f 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -10,17 +9,13 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; -import com.github.mikephil.charting.formatter.IValueFormatter; -import com.github.mikephil.charting.utils.ViewPortHandler; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -88,9 +83,9 @@ protected void onCreate(Bundle savedInstanceState) { data.add(new Data(3f, -442.3f, "01-01")); data.add(new Data(4f, -2280.1f, "01-02")); - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; } }); @@ -135,7 +130,7 @@ private void setData(List dataList) { BarData data = new BarData(set); data.setValueTextSize(13f); data.setValueTypeface(tfRegular); - data.setValueFormatter(new ValueFormatter()); + data.setValueFormatter(new Formatter()); data.setBarWidth(0.8f); chart.setData(data); @@ -159,17 +154,17 @@ private class Data { } } - private class ValueFormatter implements IValueFormatter + private class Formatter extends ValueFormatter { private final DecimalFormat mFormat; - ValueFormatter() { + Formatter() { mFormat = new DecimalFormat("######.0"); } @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + public String getFormattedValue(float value) { return mFormat.format(value); } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 0308b9a891..53dd3806bc 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -11,7 +10,6 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -31,7 +29,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -83,9 +81,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return months[(int) value % months.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java index 212b90ff87..e9ae3c0e43 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -16,7 +15,6 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.LineChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -24,7 +22,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -92,12 +90,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.rgb(255, 192, 56)); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); // one hour - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { long millis = TimeUnit.HOURS.toMillis((long) value); return mFormat.format(new Date(millis)); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 3c94e2ad5d..48bd4306c3 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -160,7 +160,7 @@ private void setData(int count, float range) { //dataSet.setSelectionShift(0f); PieData data = new PieData(dataSet); - data.setValueFormatter(new PercentFormatter()); + data.setValueFormatter(new PercentFormatter(chart)); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); data.setValueTypeface(tfLight); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index 883eb7dfc1..9fdae983d0 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -14,7 +13,6 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; @@ -22,7 +20,7 @@ import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; @@ -69,12 +67,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { private final String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return mActivities[(int) value % mActivities.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 676e0e62b0..1def86e8ef 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -24,11 +24,11 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.StackedValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -78,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis leftAxis = chart.getAxisLeft(); - leftAxis.setValueFormatter(new MyAxisValueFormatter()); + leftAxis.setValueFormatter(new MyValueFormatter("K")); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) chart.getAxisRight().setEnabled(false); @@ -142,7 +142,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set1); BarData data = new BarData(dataSets); - data.setValueFormatter(new MyValueFormatter()); + data.setValueFormatter(new StackedValueFormatter(false, "", 1)); data.setValueTextColor(Color.WHITE); chart.setData(data); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 7af58c85ca..a4e510a20f 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -14,7 +13,6 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -23,12 +21,10 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IValueFormatter; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -80,12 +76,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setLabelCount(12); xAxis.setGranularity(10f); - xAxis.setValueFormatter(new IAxisValueFormatter() { + xAxis.setValueFormatter(new ValueFormatter() { private final DecimalFormat format = new DecimalFormat("###"); @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return format.format(value) + "-" + format.format(value + 10); } }); @@ -242,7 +238,7 @@ public void onNothingSelected() { Log.i("NOTING SELECTED", ""); } - private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { + private class CustomFormatter extends ValueFormatter { private final DecimalFormat mFormat; @@ -250,15 +246,8 @@ private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { mFormat = new DecimalFormat("###"); } - // data - @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(Math.abs(value)) + "m"; - } - - // YAxis @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return mFormat.format(Math.abs(value)) + "m"; } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index ba4d860d92..1fba5cc98e 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -1,13 +1,12 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; /** * Created by philipp on 02/06/16. */ -public class DayAxisValueFormatter implements IAxisValueFormatter +public class DayAxisValueFormatter extends ValueFormatter { private final String[] mMonths = new String[]{ @@ -21,7 +20,7 @@ public DayAxisValueFormatter(BarLineChartBase chart) { } @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { int days = (int) value; diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java deleted file mode 100644 index e7cdbfcd10..0000000000 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.xxmassdeveloper.mpchartexample.custom; - -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; - -import java.text.DecimalFormat; - -public class MyAxisValueFormatter implements IAxisValueFormatter -{ - - private final DecimalFormat mFormat; - - public MyAxisValueFormatter() { - mFormat = new DecimalFormat("###,###,###,##0.0"); - } - - @Override - public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(value) + " $"; - } -} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index bea4908ef2..2cf2eab7ba 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,7 +1,6 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -12,7 +11,7 @@ * @deprecated The {@link MyAxisValueFormatter} does exactly the same thing and is more functional. */ @Deprecated -public class MyCustomXAxisValueFormatter implements IAxisValueFormatter +public class MyCustomXAxisValueFormatter extends ValueFormatter { private final DecimalFormat mFormat; @@ -25,7 +24,7 @@ public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { } @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index ec1c119818..0b0bf2f2ab 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,22 +1,35 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IValueFormatter; -import com.github.mikephil.charting.utils.ViewPortHandler; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.text.DecimalFormat; -public class MyValueFormatter implements IValueFormatter +public class MyValueFormatter extends ValueFormatter { private final DecimalFormat mFormat; + private String suffix; - public MyValueFormatter() { + public MyValueFormatter(String suffix) { mFormat = new DecimalFormat("###,###,###,##0.0"); + this.suffix = suffix; } @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return mFormat.format(value) + " $"; + public String getFormattedValue(float value) { + return mFormat.format(value) + suffix; + } + + @Override + public String getAxisLabel(float value, AxisBase axis) { + if (axis instanceof XAxis) { + return mFormat.format(value); + } else if (value > 0) { + return mFormat.format(value) + suffix; + } else { + return mFormat.format(value); + } } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index 51e4247d35..ed9dcb8a23 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,4 +1,3 @@ - package com.xxmassdeveloper.mpchartexample.custom; import android.annotation.SuppressLint; @@ -7,7 +6,7 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.R; @@ -23,11 +22,11 @@ public class XYMarkerView extends MarkerView { private final TextView tvContent; - private final IAxisValueFormatter xAxisValueFormatter; + private final ValueFormatter xAxisValueFormatter; private final DecimalFormat format; - public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { + public XYMarkerView(Context context, ValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); this.xAxisValueFormatter = xAxisValueFormatter; @@ -40,7 +39,7 @@ public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX(), null), format.format(e.getY()))); + tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX()), format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index 7122e0d80c..d45853f8d4 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -1,13 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ @SuppressWarnings("unused") -public class YearXAxisFormatter implements IAxisValueFormatter +public class YearXAxisFormatter extends ValueFormatter { private final String[] mMonths = new String[]{ @@ -19,7 +19,7 @@ public YearXAxisFormatter() { } @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getAxisLabel(float value, AxisBase axis) { float percent = value / axis.mAxisRange; return mMonths[(int) (mMonths.length * percent)]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 718d7e2acb..5c82f9ab0e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.charts; import android.animation.ValueAnimator; @@ -35,7 +34,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.IHighlighter; @@ -1015,7 +1014,7 @@ public XAxis getXAxis() { * * @return */ - public IValueFormatter getDefaultValueFormatter() { + public ValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 3c8028c24b..c1f02828be 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.components; import android.graphics.Color; @@ -6,7 +5,7 @@ import android.util.Log; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; -import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -22,7 +21,7 @@ public abstract class AxisBase extends ComponentBase { /** * custom formatter that is used instead of the auto-formatter if set */ - protected IAxisValueFormatter mAxisValueFormatter; + protected ValueFormatter mAxisValueFormatter; private int mGridColor = Color.GRAY; @@ -486,7 +485,7 @@ public String getFormattedLabel(int index) { if (index < 0 || index >= mEntries.length) return ""; else - return getValueFormatter().getFormattedValue(mEntries[index], this); + return getValueFormatter().getAxisLabel(mEntries[index], this); } /** @@ -498,7 +497,7 @@ public String getFormattedLabel(int index) { * * @param f */ - public void setValueFormatter(IAxisValueFormatter f) { + public void setValueFormatter(ValueFormatter f) { if (f == null) mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); @@ -511,7 +510,7 @@ public void setValueFormatter(IAxisValueFormatter f) { * * @return */ - public IAxisValueFormatter getValueFormatter() { + public ValueFormatter getValueFormatter() { if (mAxisValueFormatter == null || (mAxisValueFormatter instanceof DefaultAxisValueFormatter && diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 7800986dcd..8ca3e68d42 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; @@ -56,7 +56,7 @@ public abstract class BaseDataSet implements IDataSet { /** * custom formatter that is used instead of the auto-formatter if set */ - protected transient IValueFormatter mValueFormatter; + protected transient ValueFormatter mValueFormatter; /** * the typeface used for the value text @@ -313,7 +313,7 @@ public boolean isHighlightEnabled() { } @Override - public void setValueFormatter(IValueFormatter f) { + public void setValueFormatter(ValueFormatter f) { if (f == null) return; @@ -322,7 +322,7 @@ public void setValueFormatter(IValueFormatter f) { } @Override - public IValueFormatter getValueFormatter() { + public ValueFormatter getValueFormatter() { if (needsFormatter()) return Utils.getDefaultValueFormatter(); return mValueFormatter; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 60d89f4753..9bd460290d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -1,11 +1,10 @@ - package com.github.mikephil.charting.data; import android.graphics.Typeface; import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -659,7 +658,7 @@ public T getFirstRight(List sets) { * * @param f */ - public void setValueFormatter(IValueFormatter f) { + public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index 552c150e69..c8834c3e45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -1,13 +1,11 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.AxisBase; - import java.text.DecimalFormat; /** * Created by philipp on 02/06/16. */ -public class DefaultAxisValueFormatter implements IAxisValueFormatter +public class DefaultAxisValueFormatter extends ValueFormatter { /** @@ -18,7 +16,7 @@ public class DefaultAxisValueFormatter implements IAxisValueFormatter /** * the number of decimal digits this formatter uses */ - protected int digits = 0; + protected int digits; /** * Constructor that specifies to how many digits the value should be @@ -40,7 +38,7 @@ public DefaultAxisValueFormatter(int digits) { } @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { // avoid memory allocations here (for performance) return mFormat.format(value); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index e2fea4b079..40668b91ab 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -1,9 +1,5 @@ - package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.ViewPortHandler; - import java.text.DecimalFormat; /** @@ -12,7 +8,7 @@ * * @author Philipp Jahoda */ -public class DefaultValueFormatter implements IValueFormatter +public class DefaultValueFormatter extends ValueFormatter { /** @@ -52,7 +48,7 @@ public void setup(int digits) { } @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + public String getFormattedValue(float value) { // put more logic here ... // avoid memory allocations here (for performance reasons) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java index 51939b5432..970ea6fca8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java @@ -6,7 +6,10 @@ * Created by Philipp Jahoda on 20/09/15. * Custom formatter interface that allows formatting of * axis labels before they are being drawn. + * + * @deprecated Extend {@link ValueFormatter} instead */ +@Deprecated public interface IAxisValueFormatter { @@ -18,6 +21,9 @@ public interface IAxisValueFormatter * @param value the value to be formatted * @param axis the axis the value belongs to * @return + * + * @deprecated Extend {@link ValueFormatter} and use {@link ValueFormatter#getAxisLabel(float, AxisBase)} */ + @Deprecated String getFormattedValue(float value, AxisBase axis); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java index 75d2363f26..0dde7012e3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java @@ -4,13 +4,12 @@ import com.github.mikephil.charting.utils.ViewPortHandler; /** - * Interface that allows custom formatting of all values inside the chart before they are - * being drawn to the screen. Simply create your own formatting class and let - * it implement IValueFormatter. Then override the getFormattedValue(...) method - * and return whatever you want. + * Interface to format all values before they are drawn as labels. * * @author Philipp Jahoda + * @deprecated Extend {@link ValueFormatter} instead */ +@Deprecated public interface IValueFormatter { @@ -24,6 +23,9 @@ public interface IValueFormatter * @param dataSetIndex the index of the DataSet the entry in focus belongs to * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return the formatted label ready for being drawn + * + * @deprecated Extend {@link ValueFormatter} and override an appropriate method */ + @Deprecated String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java index 07349a6a0e..7ab7bdbe7d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java @@ -1,18 +1,11 @@ - package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.ViewPortHandler; - -import java.text.DecimalFormat; -import java.util.Arrays; import java.util.Collection; /** * This formatter is used for passing an array of x-axis labels, on whole x steps. */ -public class IndexAxisValueFormatter implements IAxisValueFormatter +public class IndexAxisValueFormatter extends ValueFormatter { private String[] mValues = new String[] {}; private int mValueCount = 0; @@ -44,7 +37,8 @@ public IndexAxisValueFormatter(Collection values) { setValues(values.toArray(new String[values.size()])); } - public String getFormattedValue(float value, AxisBase axis) { + @Override + public String getFormattedValue(float value) { int index = Math.round(value); if (index < 0 || index >= mValueCount || index != (int)value) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 211401ad8a..4870a4cff4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -1,10 +1,5 @@ - package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.ViewPortHandler; - import java.text.DecimalFormat; /** @@ -17,7 +12,7 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter +public class LargeValueFormatter extends ValueFormatter { private String[] mSuffix = new String[]{ @@ -41,15 +36,8 @@ public LargeValueFormatter(String appendix) { mText = appendix; } - // IValueFormatter - @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return makePretty(value) + mText; - } - - // IAxisValueFormatter @Override - public String getFormattedValue(float value, AxisBase axis) { + public String getFormattedValue(float value) { return makePretty(value) + mText; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index de8a10255a..6bf1bd3c33 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -1,9 +1,7 @@ - package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.ViewPortHandler; +import com.github.mikephil.charting.charts.PieChart; +import com.github.mikephil.charting.data.PieEntry; import java.text.DecimalFormat; @@ -13,37 +11,36 @@ * * @author Philipp Jahoda */ -public class PercentFormatter implements IValueFormatter, IAxisValueFormatter +public class PercentFormatter extends ValueFormatter { - protected DecimalFormat mFormat; + public DecimalFormat mFormat; + private PieChart pieChart; public PercentFormatter() { mFormat = new DecimalFormat("###,###,##0.0"); } - /** - * Allow a custom decimalformat - * - * @param format - */ - public PercentFormatter(DecimalFormat format) { - this.mFormat = format; + // Can be used to remove percent signs if the chart isn't in percent mode + public PercentFormatter(PieChart pieChart) { + this(); + this.pieChart = pieChart; } - // IValueFormatter @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + public String getFormattedValue(float value) { return mFormat.format(value) + " %"; } - // IAxisValueFormatter @Override - public String getFormattedValue(float value, AxisBase axis) { - return mFormat.format(value) + " %"; + public String getPieLabel(float value, PieEntry pieEntry) { + if (pieChart != null && pieChart.isUsePercentValuesEnabled()) { + // Converted to percent + return getFormattedValue(value); + } else { + // raw value, skip percent sign + return mFormat.format(value); + } } - public int getDecimalDigits() { - return 1; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 0e8351634f..7c69dcf5d6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -1,8 +1,6 @@ package com.github.mikephil.charting.formatter; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -12,7 +10,7 @@ * A formatter specifically for stacked BarChart that allows to specify whether the all stack values * or just the top value should be drawn. */ -public class StackedValueFormatter implements IValueFormatter +public class StackedValueFormatter extends ValueFormatter { /** @@ -23,7 +21,7 @@ public class StackedValueFormatter implements IValueFormatter /** * a string that should be appended behind the value */ - private String mAppendix; + private String mSuffix; private DecimalFormat mFormat; @@ -31,12 +29,12 @@ public class StackedValueFormatter implements IValueFormatter * Constructor. * * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top - * @param appendix a string that should be appended behind the value + * @param suffix a string that should be appended behind the value * @param decimals the number of decimal digits to use */ - public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { + public StackedValueFormatter(boolean drawWholeStack, String suffix, int decimals) { this.mDrawWholeStack = drawWholeStack; - this.mAppendix = appendix; + this.mSuffix = suffix; StringBuffer b = new StringBuffer(); for (int i = 0; i < decimals; i++) { @@ -49,12 +47,10 @@ public StackedValueFormatter(boolean drawWholeStack, String appendix, int decima } @Override - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + public String getBarStackedLabel(float value, BarEntry entry) { + if (!mDrawWholeStack) { - if (!mDrawWholeStack && entry instanceof BarEntry) { - - BarEntry barEntry = (BarEntry) entry; - float[] vals = barEntry.getYVals(); + float[] vals = entry.getYVals(); if (vals != null) { @@ -62,7 +58,7 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View if (vals[vals.length - 1] == value) { // return the "sum" across all stack values - return mFormat.format(barEntry.getY()) + mAppendix; + return mFormat.format(entry.getY()) + mSuffix; } else { return ""; // return empty } @@ -70,6 +66,6 @@ public String getFormattedValue(float value, Entry entry, int dataSetIndex, View } // return the "proposed" value - return mFormat.format(value) + mAppendix; + return mFormat.format(value) + mSuffix; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java new file mode 100644 index 0000000000..d2f53cb78b --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java @@ -0,0 +1,137 @@ +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.PieEntry; +import com.github.mikephil.charting.data.RadarEntry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Class to format all values before they are drawn as labels. + */ +public abstract class ValueFormatter implements IAxisValueFormatter, IValueFormatter{ + + /** + * DO NOT USE, only for backwards compatibility and will be removed in future versions. + * + * @param value the value to be formatted + * @param axis the axis the value belongs to + * @return formatted string label + */ + @Override + @Deprecated + public String getFormattedValue(float value, AxisBase axis) { + return getFormattedValue(value); + } + + /** + * DO NOT USE, only for backwards compatibility and will be removed in future versions. + * @param value the value to be formatted + * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry + * @param dataSetIndex the index of the DataSet the entry in focus belongs to + * @param viewPortHandler provides information about the current chart state (scale, translation, ...) + * @return formatted string label + */ + @Override + @Deprecated + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return getFormattedValue(value); + } + + /** + * Called when drawing any label, used to change numbers into formatted strings. + * + * @param value float to be formatted + * @return formatted string label + */ + public String getFormattedValue(float value) { + return String.valueOf(value); + } + + /** + * Used to draw axis labels, calls {@link #getFormattedValue(float)} by default. + * + * @param value float to be formatted + * @param axis axis being labeled + * @return formatted string label + */ + public String getAxisLabel(float value, AxisBase axis) { + return getFormattedValue(value); + } + + /** + * Used to draw bar labels, calls {@link #getFormattedValue(float)} by default. + * + * @param barEntry bar being labeled + * @return formatted string label + */ + public String getBarLabel(BarEntry barEntry) { + return getFormattedValue(barEntry.getY()); + } + + /** + * Used to draw stacked bar labels, calls {@link #getFormattedValue(float)} by default. + * + * @param value current value to be formatted + * @param stackedEntry stacked entry being labeled, contains all Y values + * @return formatted string label + */ + public String getBarStackedLabel(float value, BarEntry stackedEntry) { + return getFormattedValue(value); + } + + /** + * Used to draw line and scatter labels, calls {@link #getFormattedValue(float)} by default. + * + * @param entry point being labeled, contains X value + * @return formatted string label + */ + public String getPointLabel(Entry entry) { + return getFormattedValue(entry.getY()); + } + + /** + * Used to draw pie value labels, calls {@link #getFormattedValue(float)} by default. + * + * @param value float to be formatted, may have been converted to percentage + * @param pieEntry slice being labeled, contains original, non-percentage Y value + * @return formatted string label + */ + public String getPieLabel(float value, PieEntry pieEntry) { + return getFormattedValue(value); + } + + /** + * Used to draw radar value labels, calls {@link #getFormattedValue(float)} by default. + * + * @param radarEntry entry being labeled + * @return formatted string label + */ + public String getRadarLabel(RadarEntry radarEntry) { + return getFormattedValue(radarEntry.getY()); + } + + /** + * Used to draw bubble size labels, calls {@link #getFormattedValue(float)} by default. + * + * @param bubbleEntry bubble being labeled, also contains X and Y values + * @return formatted string label + */ + public String getBubbleLabel(BubbleEntry bubbleEntry) { + return getFormattedValue(bubbleEntry.getSize()); + } + + /** + * Used to draw high labels, calls {@link #getFormattedValue(float)} by default. + * + * @param candleEntry candlestick being labeled + * @return formatted string label + */ + public String getCandleLabel(CandleEntry candleEntry) { + return getFormattedValue(candleEntry.getHigh()); + } + +} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 219b46bd82..182aa28757 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -3,7 +3,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.MPPointF; /** @@ -61,7 +61,7 @@ public interface ChartInterface { RectF getContentRect(); - IValueFormatter getDefaultValueFormatter(); + ValueFormatter getDefaultValueFormatter(); ChartData getData(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index f64db706e0..73a54470c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -1,14 +1,13 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; -import android.graphics.PointF; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.model.GradientColor; @@ -341,14 +340,14 @@ public interface IDataSet { * * @param f */ - void setValueFormatter(IValueFormatter f); + void setValueFormatter(ValueFormatter f); /** * Returns the formatter used for drawing the values inside the chart. * * @return */ - IValueFormatter getValueFormatter(); + ValueFormatter getValueFormatter(); /** * Returns true if the valueFormatter object of this DataSet is null. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index d3f71af02c..b5de65b02e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -11,6 +10,7 @@ import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; @@ -254,6 +254,8 @@ public void drawValues(Canvas c) { final float phaseY = mAnimator.getPhaseY(); + ValueFormatter formatter = dataSet.getValueFormatter(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -276,8 +278,7 @@ public void drawValues(Canvas c) { float val = entry.getY(); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, - val >= 0 ? + drawValue(c, formatter.getBarLabel(entry), x, val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), dataSet.getValueTextColor(j / 4)); @@ -335,8 +336,7 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, - buffer.buffer[bufferIndex + 1] + + drawValue(c, formatter.getBarLabel(entry), x, buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), color); } @@ -407,14 +407,7 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, - dataSet.getValueFormatter(), - vals[k / 2], - entry, - i, - x, - y, - color); + drawValue(c, formatter.getBarStackedLabel(val, entry), x, y, color); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -442,6 +435,12 @@ public void drawValues(Canvas c) { } } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawHighlighted(Canvas c, Highlight[] indices) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index d53dcd4785..57b81c1d9c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -9,6 +8,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -150,6 +150,8 @@ public void drawValues(Canvas c) { final float alpha = phaseX == 1 ? phaseY : phaseX; + ValueFormatter formatter = dataSet.getValueFormatter(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -172,8 +174,7 @@ public void drawValues(Canvas c) { BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, - y + (0.5f * lineHeight), valueTextColor); + drawValue(c, formatter.getBubbleLabel(entry), x, y + (0.5f * lineHeight), valueTextColor); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -195,6 +196,12 @@ public void drawValues(Canvas c) { } } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 991b702117..027dda31d8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -8,6 +7,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -279,6 +279,8 @@ public void drawValues(Canvas c) { float yOffset = Utils.convertDpToPixel(5f); + ValueFormatter formatter = dataSet.getValueFormatter(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -297,15 +299,7 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, - dataSet.getValueFormatter(), - entry.getHigh(), - entry, - i, - x, - y - yOffset, - dataSet - .getValueTextColor(j / 2)); + drawValue(c, formatter.getCandleLabel(entry), x, y - yOffset, dataSet.getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -327,6 +321,12 @@ public void drawValues(Canvas c) { } } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 6d0d4d3da0..8f6be3c054 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.Chart; @@ -9,7 +10,6 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; @@ -89,6 +89,11 @@ public void drawData(Canvas c) { renderer.drawData(c); } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + Log.e("MPAndroidChart", "Erroneous call to drawValue() in CombinedChartRenderer!"); + } + @Override public void drawValues(Canvas c) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index e8e5446f4d..da4a26edca 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -6,15 +5,11 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; -import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -138,19 +133,13 @@ protected void applyValueTextStyle(IDataSet set) { /** * Draws the value of the given entry by using the provided IValueFormatter. * - * @param c canvas - * @param formatter formatter for custom value-formatting - * @param value the value to be drawn - * @param entry the entry the value belongs to - * @param dataSetIndex the index of the DataSet the drawn Entry belongs to - * @param x position - * @param y position + * @param c canvas + * @param valueText label to draw + * @param x position + * @param y position * @param color */ - public void drawValue(Canvas c, IValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); - } + public abstract void drawValue(Canvas c, String valueText, float x, float y, int color); /** * Draws any kind of additional information (e.g. line-circles). diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index a1e1650865..7607abdd92 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -11,7 +10,7 @@ import com.github.mikephil.charting.buffer.HorizontalBarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; @@ -167,7 +166,7 @@ public void drawValues(Canvas c) { applyValueTextStyle(dataSet); final float halfTextHeight = Utils.calcTextHeight(mValuePaint, "10") / 2f; - IValueFormatter formatter = dataSet.getValueFormatter(); + ValueFormatter formatter = dataSet.getValueFormatter(); // get the buffer BarBuffer buffer = mBarBuffers[i]; @@ -196,7 +195,7 @@ public void drawValues(Canvas c) { BarEntry entry = dataSet.getEntryForIndex(j / 4); float val = entry.getY(); - String formattedValue = formatter.getFormattedValue(val, entry, i, mViewPortHandler); + String formattedValue = formatter.getBarLabel(entry); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -265,9 +264,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1])) continue; - float val = entry.getY(); - String formattedValue = formatter.getFormattedValue(val, - entry, i, mViewPortHandler); + String formattedValue = formatter.getBarLabel(entry); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -337,8 +334,7 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { final float val = vals[k / 2]; - String formattedValue = formatter.getFormattedValue(val, - entry, i, mViewPortHandler); + String formattedValue = formatter.getBarStackedLabel(val, entry); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -396,7 +392,8 @@ public void drawValues(Canvas c) { } } - protected void drawValue(Canvas c, String valueText, float x, float y, int color) { + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { mValuePaint.setColor(color); c.drawText(valueText, x, y, mValuePaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 7beb6ca5be..ead9d6d701 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -294,7 +295,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); + final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; final int pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -547,6 +548,7 @@ public void drawValues(Canvas c) { float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator .getPhaseY(), mXBounds.min, mXBounds.max); + ValueFormatter formatter = dataSet.getValueFormatter(); MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); @@ -566,8 +568,7 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, - y - valOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, formatter.getPointLabel(entry), x, y - valOffset, dataSet.getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -589,6 +590,12 @@ public void drawValues(Canvas c) { } } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawExtras(Canvas c) { drawCircles(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 8c37a0b83d..b14657cefc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Bitmap; @@ -22,7 +21,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -438,7 +437,7 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); - IValueFormatter formatter = dataSet.getValueFormatter(); + ValueFormatter formatter = dataSet.getValueFormatter(); int entryCount = dataSet.getEntryCount(); @@ -472,6 +471,7 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getY() / yValueSum * 100f : entry.getY(); + String formattedValue = formatter.getPieLabel(value, entry); final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD); @@ -550,14 +550,7 @@ public void drawValues(Canvas c) { // draw everything, depending on settings if (drawXOutside && drawYOutside) { - drawValue(c, - formatter, - value, - entry, - 0, - labelPtx, - labelPty, - dataSet.getValueTextColor(j)); + drawValue(c, formattedValue, labelPtx, labelPty, dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entry.getLabel() != null) { drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight); @@ -569,8 +562,7 @@ public void drawValues(Canvas c) { } } else if (drawYOutside) { - drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet - .getValueTextColor(j)); + drawValue(c, formattedValue, labelPtx, labelPty + lineHeight / 2.f, dataSet.getValueTextColor(j)); } } @@ -584,7 +576,7 @@ public void drawValues(Canvas c) { // draw everything, depending on settings if (drawXInside && drawYInside) { - drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); + drawValue(c, formattedValue, x, y, dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entry.getLabel() != null) { drawEntryLabel(c, entry.getLabel(), x, y + lineHeight); @@ -595,8 +587,7 @@ public void drawValues(Canvas c) { drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f); } } else if (drawYInside) { - - drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); + drawValue(c, formattedValue, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); } } @@ -626,6 +617,12 @@ public void drawValues(Canvas c) { c.restore(); } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + /** * Draws an entry label at the specified position. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index dbf0e8f807..3f932f8725 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -11,6 +10,7 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -174,6 +174,8 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); + ValueFormatter formatter = dataSet.getValueFormatter(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -189,15 +191,7 @@ public void drawValues(Canvas c) { pOut); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, - dataSet.getValueFormatter(), - entry.getY(), - entry, - i, - pOut.x, - pOut.y - yoffset, - dataSet.getValueTextColor - (j)); + drawValue(c, formatter.getRadarLabel(entry), pOut.x, pOut.y - yoffset, dataSet.getValueTextColor(j)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -231,6 +225,12 @@ public void drawValues(Canvas c) { MPPointF.recycleInstance(pIcon); } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawExtras(Canvas c) { drawWeb(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index ccd077e55c..98dddb93f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -8,6 +7,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -118,6 +118,8 @@ public void drawValues(Canvas c) { float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); + ValueFormatter formatter = dataSet.getValueFormatter(); + MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -135,14 +137,7 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, - dataSet.getValueFormatter(), - entry.getY(), - entry, - i, - positions[j], - positions[j + 1] - shapeSize, - dataSet.getValueTextColor(j / 2 + mXBounds.min)); + drawValue(c, formatter.getPointLabel(entry), positions[j], positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -164,6 +159,12 @@ public void drawValues(Canvas c) { } } + @Override + public void drawValue(Canvas c, String valueText, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(valueText, x, y, mValuePaint); + } + @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 8adb56c73a..046f3469bc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -202,7 +201,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mViewPortHandler.isInBoundsX(x)) { - String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); + String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis); if (mXAxis.isAvoidFirstLastClippingEnabled()) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 86047cf1b8..9054dcb679 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -57,10 +56,10 @@ public void computeAxis(float min, float max, boolean inverted) { computeAxisValues(min, max); } - + @Override protected void computeSize() { - + mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -156,7 +155,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mViewPortHandler.isInBoundsY(y)) { - String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); + String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis); drawLabel(c, label, pos, y, anchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 956e8c7d5c..6d83cf59e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -1,8 +1,6 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.graphics.PointF; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.XAxis; @@ -43,7 +41,7 @@ public void renderAxisLabels(Canvas c) { MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < mChart.getData().getMaxEntryCountSet().getEntryCount(); i++) { - String label = mXAxis.getValueFormatter().getFormattedValue(i, mXAxis); + String label = mXAxis.getValueFormatter().getAxisLabel(i, mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index c302673919..60ff6ba3da 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.utils; import android.annotation.SuppressLint; @@ -7,7 +6,6 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; @@ -15,14 +13,13 @@ import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; -import android.util.SizeF; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.List; @@ -229,15 +226,14 @@ public static void calcTextSize(Paint paint, String demoText, FSize outputFSize) 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; - private static IValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); + private static ValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); - private static IValueFormatter generateDefaultValueFormatter() { - final DefaultValueFormatter formatter = new DefaultValueFormatter(1); - return formatter; + private static ValueFormatter generateDefaultValueFormatter() { + return new DefaultValueFormatter(1); } /// - returns: The default value formatter used for all chart components that needs a default - public static IValueFormatter getDefaultValueFormatter() + public static ValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } @@ -353,11 +349,11 @@ public static String formatNumber(float number, int digitCount, boolean separate * @return */ public static float roundToNextSignificant(double number) { - if (Double.isInfinite(number) || - Double.isNaN(number) || + if (Double.isInfinite(number) || + Double.isNaN(number) || number == 0.0) return 0; - + final float d = (float) Math.ceil((float) Math.log10(number < 0 ? -number : number)); final int pw = 1 - (int) d; final float magnitude = (float) Math.pow(10, pw); @@ -375,10 +371,10 @@ public static float roundToNextSignificant(double number) { public static int getDecimals(float number) { float i = roundToNextSignificant(number); - + if (Float.isInfinite(i)) return 0; - + return (int) Math.ceil(-Math.log10(i)) + 2; } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java index f1e1e0279e..fc7eb93e75 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java @@ -16,80 +16,80 @@ public void test() { LargeValueFormatter formatter = new LargeValueFormatter(); - String result = formatter.getFormattedValue(5f, null); + String result = formatter.getFormattedValue(5f); assertEquals("5", result); - result = formatter.getFormattedValue(5.5f, null); + result = formatter.getFormattedValue(5.5f); assertEquals("5.5", result); - result = formatter.getFormattedValue(50f, null); + result = formatter.getFormattedValue(50f); assertEquals("50", result); - result = formatter.getFormattedValue(50.5f, null); + result = formatter.getFormattedValue(50.5f); assertEquals("50.5", result); - result = formatter.getFormattedValue(500f, null); + result = formatter.getFormattedValue(500f); assertEquals("500", result); - result = formatter.getFormattedValue(1100f, null); + result = formatter.getFormattedValue(1100f); assertEquals("1.1k", result); - result = formatter.getFormattedValue(10000f, null); + result = formatter.getFormattedValue(10000f); assertEquals("10k", result); - result = formatter.getFormattedValue(10500f, null); + result = formatter.getFormattedValue(10500f); assertEquals("10.5k", result); - result = formatter.getFormattedValue(100000f, null); + result = formatter.getFormattedValue(100000f); assertEquals("100k", result); - result = formatter.getFormattedValue(1000000f, null); + result = formatter.getFormattedValue(1000000f); assertEquals("1m", result); - result = formatter.getFormattedValue(1500000f, null); + result = formatter.getFormattedValue(1500000f); assertEquals("1.5m", result); - result = formatter.getFormattedValue(9500000f, null); + result = formatter.getFormattedValue(9500000f); assertEquals("9.5m", result); - result = formatter.getFormattedValue(22200000f, null); + result = formatter.getFormattedValue(22200000f); assertEquals("22.2m", result); - result = formatter.getFormattedValue(222000000f, null); + result = formatter.getFormattedValue(222000000f); assertEquals("222m", result); - result = formatter.getFormattedValue(1000000000f, null); + result = formatter.getFormattedValue(1000000000f); assertEquals("1b", result); - result = formatter.getFormattedValue(9900000000f, null); + result = formatter.getFormattedValue(9900000000f); assertEquals("9.9b", result); - result = formatter.getFormattedValue(99000000000f, null); + result = formatter.getFormattedValue(99000000000f); assertEquals("99b", result); - result = formatter.getFormattedValue(99500000000f, null); + result = formatter.getFormattedValue(99500000000f); assertEquals("99.5b", result); - result = formatter.getFormattedValue(999000000000f, null); + result = formatter.getFormattedValue(999000000000f); assertEquals("999b", result); - result = formatter.getFormattedValue(1000000000000f, null); + result = formatter.getFormattedValue(1000000000000f); assertEquals("1t", result); formatter.setSuffix(new String[]{"", "k", "m", "b", "t", "q"}); // quadrillion support - result = formatter.getFormattedValue(1000000000000000f, null); + result = formatter.getFormattedValue(1000000000000000f); assertEquals("1q", result); - result = formatter.getFormattedValue(1100000000000000f, null); + result = formatter.getFormattedValue(1100000000000000f); assertEquals("1.1q", result); - result = formatter.getFormattedValue(10000000000000000f, null); + result = formatter.getFormattedValue(10000000000000000f); assertEquals("10q", result); - result = formatter.getFormattedValue(13300000000000000f, null); + result = formatter.getFormattedValue(13300000000000000f); assertEquals("13.3q", result); - result = formatter.getFormattedValue(100000000000000000f, null); + result = formatter.getFormattedValue(100000000000000000f); assertEquals("100q", result); } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java index e1dbe81be9..44946cf4da 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.utils.ObjectPool; -import junit.framework.Assert; +import org.junit.Assert; import org.junit.Test; From fc0e2342984758849384199f0225e0c6b5555168 Mon Sep 17 00:00:00 2001 From: almic Date: Wed, 7 Nov 2018 14:52:25 -0700 Subject: [PATCH 1326/1390] Remove Deprecated Things Long deprecated Legend constructor and positioning has been removed, it was replaced with a new way to position the Legend. The old Easing options have been removed now, accessing them is as easy as removing the `EasingOption` part, such that the names look like `Easing.Linear` or `Easing.EaseInOutQuad` now. --- .../charting/animation/ChartAnimator.java | 93 --------------- .../mikephil/charting/animation/Easing.java | 107 ----------------- .../mikephil/charting/charts/Chart.java | 54 --------- .../mikephil/charting/components/Legend.java | 110 ------------------ 4 files changed, 364 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java index b33b3fb69d..e5b82db0b6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/ChartAnimator.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.animation; import android.animation.ObjectAnimator; @@ -160,98 +159,6 @@ public void animateY(int durationMillis, EasingFunction easing) { animatorY.start(); } - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. - * - * @param durationMillisX animation duration along the X axis - * @param durationMillisY animation duration along the Y axis - * @param easingX EasingFunction for the X axis - * @param easingY EasingFunction for the Y axis - * - * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} - * @see #animateXY(int, int, EasingFunction, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easingY)); - animatorY.setDuration( - durationMillisY); - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easingX)); - animatorX.setDuration( - durationMillisX); - - // make sure only one animator produces update-callbacks (which then - // call invalidate()) - if (durationMillisX > durationMillisY) { - animatorX.addUpdateListener(mListener); - } else { - animatorY.addUpdateListener(mListener); - } - - animatorX.start(); - animatorY.start(); - } - - /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. - * - * @param durationMillis animation duration - * @param easing EasingFunction - * - * @deprecated Use {@link #animateX(int, EasingFunction)} - * @see #animateX(int, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateX(int durationMillis, Easing.EasingOption easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorX = ObjectAnimator.ofFloat(this, "phaseX", 0f, 1f); - animatorX.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorX.setDuration(durationMillis); - animatorX.addUpdateListener(mListener); - animatorX.start(); - } - - /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. - * - * @param durationMillis animation duration - * @param easing EasingFunction - * - * @deprecated Use {@link #animateY(int, EasingFunction)} - * @see #animateY(int, EasingFunction) - */ - @SuppressWarnings("deprecation") - @Deprecated - public void animateY(int durationMillis, Easing.EasingOption easing) { - - if (android.os.Build.VERSION.SDK_INT < 11) - return; - - ObjectAnimator animatorY = ObjectAnimator.ofFloat(this, "phaseY", 0f, 1f); - animatorY.setInterpolator(Easing.getEasingFunctionFromOption(easing)); - animatorY.setDuration(durationMillis); - animatorY.addUpdateListener(mListener); - animatorY.start(); - } - /** * Gets the Y axis phase of the animation. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java index 2c64777a6a..acb7dcc965 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/animation/Easing.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.animation; import android.animation.TimeInterpolator; @@ -19,112 +18,6 @@ public interface EasingFunction extends TimeInterpolator { float getInterpolation(float input); } - /** - * Enum holding EasingOption constants - * - * @deprecated Use Easing.Linear instead of Easing.EasingOption.Linear - */ - @Deprecated - public enum EasingOption { - Linear, - EaseInQuad, - EaseOutQuad, - EaseInOutQuad, - EaseInCubic, - EaseOutCubic, - EaseInOutCubic, - EaseInQuart, - EaseOutQuart, - EaseInOutQuart, - EaseInSine, - EaseOutSine, - EaseInOutSine, - EaseInExpo, - EaseOutExpo, - EaseInOutExpo, - EaseInCirc, - EaseOutCirc, - EaseInOutCirc, - EaseInElastic, - EaseOutElastic, - EaseInOutElastic, - EaseInBack, - EaseOutBack, - EaseInOutBack, - EaseInBounce, - EaseOutBounce, - EaseInOutBounce, - } - - /** - * Returns the EasingFunction of the given EasingOption - * - * @param easing EasingOption to get - * @return EasingFunction - */ - @Deprecated - public static EasingFunction getEasingFunctionFromOption(EasingOption easing) { - switch (easing) { - default: - case Linear: - return Easing.Linear; - case EaseInQuad: - return Easing.EaseInQuad; - case EaseOutQuad: - return Easing.EaseOutQuad; - case EaseInOutQuad: - return Easing.EaseInOutQuad; - case EaseInCubic: - return Easing.EaseInCubic; - case EaseOutCubic: - return Easing.EaseOutCubic; - case EaseInOutCubic: - return Easing.EaseInOutCubic; - case EaseInQuart: - return Easing.EaseInQuart; - case EaseOutQuart: - return Easing.EaseOutQuart; - case EaseInOutQuart: - return Easing.EaseInOutQuart; - case EaseInSine: - return Easing.EaseInSine; - case EaseOutSine: - return Easing.EaseOutSine; - case EaseInOutSine: - return Easing.EaseInOutSine; - case EaseInExpo: - return Easing.EaseInExpo; - case EaseOutExpo: - return Easing.EaseOutExpo; - case EaseInOutExpo: - return Easing.EaseInOutExpo; - case EaseInCirc: - return Easing.EaseInCirc; - case EaseOutCirc: - return Easing.EaseOutCirc; - case EaseInOutCirc: - return Easing.EaseInOutCirc; - case EaseInElastic: - return Easing.EaseInElastic; - case EaseOutElastic: - return Easing.EaseOutElastic; - case EaseInOutElastic: - return Easing.EaseInOutElastic; - case EaseInBack: - return Easing.EaseInBack; - case EaseOutBack: - return Easing.EaseOutBack; - case EaseInOutBack: - return Easing.EaseInOutBack; - case EaseInBounce: - return Easing.EaseInBounce; - case EaseOutBounce: - return Easing.EaseOutBounce; - case EaseInOutBounce: - return Easing.EaseInOutBounce; - } - } - private static final float DOUBLE_PI = 2f * (float) Math.PI; @SuppressWarnings("unused") diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 5c82f9ab0e..0a1869e543 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -891,60 +891,6 @@ public void animateY(int durationMillis, EasingFunction easing) { */ /** CODE BELOW FOR PREDEFINED EASING OPTIONS */ - /** - * Animates the drawing / rendering of the chart on both x- and y-axis with - * the specified animation time. If animate(...) is called, no further - * calling of invalidate() is necessary to refresh the chart. ANIMATIONS - * ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillisX - * @param durationMillisY - * @param easingX a predefined easing option - * @param easingY a predefined easing option - * - * @deprecated Use {@link #animateXY(int, int, EasingFunction, EasingFunction)} - * @see #animateXY(int, int, EasingFunction, EasingFunction) - */ - @Deprecated - public void animateXY(int durationMillisX, int durationMillisY, Easing.EasingOption easingX, - Easing.EasingOption easingY) { - mAnimator.animateXY(durationMillisX, durationMillisY, easingX, easingY); - } - - /** - * Animates the rendering of the chart on the x-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillis - * @param easing a predefined easing option - * - * @deprecated Use {@link #animateX(int, EasingFunction)} - * @see #animateX(int, EasingFunction) - */ - @Deprecated - public void animateX(int durationMillis, Easing.EasingOption easing) { - mAnimator.animateX(durationMillis, easing); - } - - /** - * Animates the rendering of the chart on the y-axis with the specified - * animation time. If animate(...) is called, no further calling of - * invalidate() is necessary to refresh the chart. ANIMATIONS ONLY WORK FOR - * API LEVEL 11 (Android 3.0.x) AND HIGHER. - * - * @param durationMillis - * @param easing a predefined easing option - * - * @deprecated Use {@link #animateY(int, EasingFunction)} - * @see #animateY(int, EasingFunction) - */ - @Deprecated - public void animateY(int durationMillis, Easing.EasingOption easing) { - mAnimator.animateY(durationMillis, easing); - } - /** * ################ ################ ################ ################ * ANIMATIONS ONLY WORK FOR API LEVEL 11 (Android 3.0.x) AND HIGHER. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index fb1afc8bba..e3782e7cdd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -1,10 +1,8 @@ - package com.github.mikephil.charting.components; import android.graphics.DashPathEffect; import android.graphics.Paint; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; @@ -214,11 +212,6 @@ else if (entry.formColor == ColorTemplate.COLOR_NONE || mEntries = entries.toArray(new LegendEntry[entries.size()]); } - @Deprecated - public Legend(List colors, List labels) { - this(Utils.convertIntegers(colors), Utils.convertStrings(labels)); - } - /** * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. * @@ -423,109 +416,6 @@ public boolean isLegendCustom() { return mIsLegendCustom; } - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public LegendPosition getPosition() { - - if (mOrientation == LegendOrientation.VERTICAL - && mHorizontalAlignment == LegendHorizontalAlignment.CENTER - && mVerticalAlignment == LegendVerticalAlignment.CENTER) { - return LegendPosition.PIECHART_CENTER; - } else if (mOrientation == LegendOrientation.HORIZONTAL) { - if (mVerticalAlignment == LegendVerticalAlignment.TOP) - return mHorizontalAlignment == LegendHorizontalAlignment.LEFT - ? LegendPosition.ABOVE_CHART_LEFT - : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT - ? LegendPosition.ABOVE_CHART_RIGHT - : LegendPosition.ABOVE_CHART_CENTER); - else - return mHorizontalAlignment == LegendHorizontalAlignment.LEFT - ? LegendPosition.BELOW_CHART_LEFT - : (mHorizontalAlignment == LegendHorizontalAlignment.RIGHT - ? LegendPosition.BELOW_CHART_RIGHT - : LegendPosition.BELOW_CHART_CENTER); - } else { - if (mHorizontalAlignment == LegendHorizontalAlignment.LEFT) - return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside - ? LegendPosition.LEFT_OF_CHART_INSIDE - : (mVerticalAlignment == LegendVerticalAlignment.CENTER - ? LegendPosition.LEFT_OF_CHART_CENTER - : LegendPosition.LEFT_OF_CHART); - else - return mVerticalAlignment == LegendVerticalAlignment.TOP && mDrawInside - ? LegendPosition.RIGHT_OF_CHART_INSIDE - : (mVerticalAlignment == LegendVerticalAlignment.CENTER - ? LegendPosition.RIGHT_OF_CHART_CENTER - : LegendPosition.RIGHT_OF_CHART); - } - } - - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public void setPosition(LegendPosition newValue) { - - switch (newValue) { - case LEFT_OF_CHART: - case LEFT_OF_CHART_INSIDE: - case LEFT_OF_CHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.LEFT; - mVerticalAlignment = newValue == LegendPosition.LEFT_OF_CHART_CENTER - ? LegendVerticalAlignment.CENTER - : LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.VERTICAL; - break; - - case RIGHT_OF_CHART: - case RIGHT_OF_CHART_INSIDE: - case RIGHT_OF_CHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.RIGHT; - mVerticalAlignment = newValue == LegendPosition.RIGHT_OF_CHART_CENTER - ? LegendVerticalAlignment.CENTER - : LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.VERTICAL; - break; - - case ABOVE_CHART_LEFT: - case ABOVE_CHART_CENTER: - case ABOVE_CHART_RIGHT: - mHorizontalAlignment = newValue == LegendPosition.ABOVE_CHART_LEFT - ? LegendHorizontalAlignment.LEFT - : (newValue == LegendPosition.ABOVE_CHART_RIGHT - ? LegendHorizontalAlignment.RIGHT - : LegendHorizontalAlignment.CENTER); - mVerticalAlignment = LegendVerticalAlignment.TOP; - mOrientation = LegendOrientation.HORIZONTAL; - break; - - case BELOW_CHART_LEFT: - case BELOW_CHART_CENTER: - case BELOW_CHART_RIGHT: - mHorizontalAlignment = newValue == LegendPosition.BELOW_CHART_LEFT - ? LegendHorizontalAlignment.LEFT - : (newValue == LegendPosition.BELOW_CHART_RIGHT - ? LegendHorizontalAlignment.RIGHT - : LegendHorizontalAlignment.CENTER); - mVerticalAlignment = LegendVerticalAlignment.BOTTOM; - mOrientation = LegendOrientation.HORIZONTAL; - break; - - case PIECHART_CENTER: - mHorizontalAlignment = LegendHorizontalAlignment.CENTER; - mVerticalAlignment = LegendVerticalAlignment.CENTER; - mOrientation = LegendOrientation.VERTICAL; - break; - } - - mDrawInside = newValue == LegendPosition.LEFT_OF_CHART_INSIDE - || newValue == LegendPosition.RIGHT_OF_CHART_INSIDE; - } - /** * returns the horizontal alignment of the legend * From 29f4cc5c2c5c7e5468759bb5ad414e9855cd09c6 Mon Sep 17 00:00:00 2001 From: almic Date: Sun, 11 Nov 2018 09:40:37 -0700 Subject: [PATCH 1327/1390] Remove unnecessary API checks Also added run configuration for the MPChartExample. Removed deprecated Legend stuff. --- .idea/runConfigurations/MPChartExample.xml | 52 ++++++++++ .../charting/charts/BarLineChartBase.java | 56 ++++------- .../mikephil/charting/charts/Chart.java | 34 +++---- .../charting/charts/PieRadarChartBase.java | 3 - .../mikephil/charting/components/Legend.java | 94 ------------------- 5 files changed, 84 insertions(+), 155 deletions(-) create mode 100644 .idea/runConfigurations/MPChartExample.xml diff --git a/.idea/runConfigurations/MPChartExample.xml b/.idea/runConfigurations/MPChartExample.xml new file mode 100644 index 0000000000..e6bcf50331 --- /dev/null +++ b/.idea/runConfigurations/MPChartExample.xml @@ -0,0 +1,52 @@ + + + + + \ No newline at end of file diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 0b0219e445..71f8a2d8a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -708,20 +708,14 @@ public void zoomToCenter(float scaleX, float scaleY) { public void zoomAndCenterAnimated(float scaleX, float scaleY, float xValue, float yValue, AxisDependency axis, long duration) { - if (android.os.Build.VERSION.SDK_INT >= 11) { + MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - MPPointD origin = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - - Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis - .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), - xValue, yValue, (float) origin.x, (float) origin.y, duration); - addViewportJob(job); - - MPPointD.recycleInstance(origin); + Runnable job = AnimatedZoomJob.getInstance(mViewPortHandler, this, getTransformer(axis), getAxis(axis), mXAxis + .mAxisRange, scaleX, scaleY, mViewPortHandler.getScaleX(), mViewPortHandler.getScaleY(), + xValue, yValue, (float) origin.x, (float) origin.y, duration); + addViewportJob(job); - } else { - Log.e(LOG_TAG, "Unable to execute zoomAndCenterAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(origin); } protected Matrix mFitScreenMatrixBuffer = new Matrix(); @@ -874,21 +868,16 @@ public void moveViewTo(float xValue, float yValue, AxisDependency axis) { @TargetApi(11) public void moveViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { - if (android.os.Build.VERSION.SDK_INT >= 11) { + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - - float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); - Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, xValue, yValue + yInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - addViewportJob(job); + addViewportJob(job); - MPPointD.recycleInstance(bounds); - } else { - Log.e(LOG_TAG, "Unable to execute moveViewToAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(bounds); } /** @@ -941,23 +930,18 @@ public void centerViewTo(float xValue, float yValue, AxisDependency axis) { @TargetApi(11) public void centerViewToAnimated(float xValue, float yValue, AxisDependency axis, long duration) { - if (android.os.Build.VERSION.SDK_INT >= 11) { - - MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); + MPPointD bounds = getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), axis); - float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); - float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); + float yInView = getAxisRange(axis) / mViewPortHandler.getScaleY(); + float xInView = getXAxis().mAxisRange / mViewPortHandler.getScaleX(); - Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, - xValue - xInView / 2f, yValue + yInView / 2f, - getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); + Runnable job = AnimatedMoveViewJob.getInstance(mViewPortHandler, + xValue - xInView / 2f, yValue + yInView / 2f, + getTransformer(axis), this, (float) bounds.x, (float) bounds.y, duration); - addViewportJob(job); + addViewportJob(job); - MPPointD.recycleInstance(bounds); - } else { - Log.e(LOG_TAG, "Unable to execute centerViewToAnimated(...) on API level < 11"); - } + MPPointD.recycleInstance(bounds); } /** diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 0a1869e543..1889a9f6d4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -208,18 +208,14 @@ protected void init() { setWillNotDraw(false); // setLayerType(View.LAYER_TYPE_HARDWARE, null); - if (Build.VERSION.SDK_INT < 11) { - mAnimator = new ChartAnimator(); - } else { - mAnimator = new ChartAnimator(new AnimatorUpdateListener() { - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - // ViewCompat.postInvalidateOnAnimation(Chart.this); - postInvalidate(); - } - }); - } + mAnimator = new ChartAnimator(new AnimatorUpdateListener() { + + @Override + public void onAnimationUpdate(ValueAnimator animation) { + // ViewCompat.postInvalidateOnAnimation(Chart.this); + postInvalidate(); + } + }); // initialize the utils Utils.init(getContext()); @@ -1697,16 +1693,10 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { */ public void setHardwareAccelerationEnabled(boolean enabled) { - if (android.os.Build.VERSION.SDK_INT >= 11) { - - if (enabled) - setLayerType(View.LAYER_TYPE_HARDWARE, null); - else - setLayerType(View.LAYER_TYPE_SOFTWARE, null); - } else { - Log.e(LOG_TAG, - "Cannot enable/disable hardware acceleration for devices below API level 11."); - } + if (enabled) + setLayerType(View.LAYER_TYPE_HARDWARE, null); + else + setLayerType(View.LAYER_TYPE_SOFTWARE, null); } @Override diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java index 618de18a34..e6d38d3a01 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -480,9 +480,6 @@ public float getYChartMin() { @SuppressLint("NewApi") public void spin(int durationmillis, float fromangle, float toangle, EasingFunction easing) { - if (android.os.Build.VERSION.SDK_INT < 11) - return; - setRotationAngle(fromangle); ObjectAnimator spinAnimator = ObjectAnimator.ofFloat(this, "rotationAngle", fromangle, diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index e3782e7cdd..b785098881 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -20,19 +20,6 @@ */ public class Legend extends ComponentBase { - /** - * This property is deprecated - Use `horizontalAlignment`, `verticalAlignment`, `orientation`, `drawInside`, - * `direction`. - */ - @Deprecated - public enum LegendPosition { - RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, - LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, - BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, - ABOVE_CHART_LEFT, ABOVE_CHART_RIGHT, ABOVE_CHART_CENTER, - PIECHART_CENTER - } - public enum LegendForm { /** * Avoid drawing a form @@ -180,38 +167,6 @@ public Legend(LegendEntry[] entries) { this.mEntries = entries; } - @Deprecated - public Legend(int[] colors, String[] labels) { - this(); - - if (colors == null || labels == null) { - throw new IllegalArgumentException("colors array or labels array is NULL"); - } - - if (colors.length != labels.length) { - throw new IllegalArgumentException( - "colors array and labels array need to be of same size"); - } - - List entries = new ArrayList<>(); - - for (int i = 0; i < Math.min(colors.length, labels.length); i++) { - final LegendEntry entry = new LegendEntry(); - entry.formColor = colors[i]; - entry.label = labels[i]; - - if (entry.formColor == ColorTemplate.COLOR_SKIP) - entry.form = LegendForm.NONE; - else if (entry.formColor == ColorTemplate.COLOR_NONE || - entry.formColor == 0) - entry.form = LegendForm.EMPTY; - - entries.add(entry); - } - - mEntries = entries.toArray(new LegendEntry[entries.size()]); - } - /** * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. * @@ -280,50 +235,6 @@ public float getMaximumEntryHeight(Paint p) { return max; } - @Deprecated - public int[] getColors() { - - int[] old = new int[mEntries.length]; - for (int i = 0; i < mEntries.length; i++) { - old[i] = mEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : - (mEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : - mEntries[i].formColor); - } - return old; - } - - @Deprecated - public String[] getLabels() { - - String[] old = new String[mEntries.length]; - for (int i = 0; i < mEntries.length; i++) { - old[i] = mEntries[i].label; - } - return old; - } - - @Deprecated - public int[] getExtraColors() { - - int[] old = new int[mExtraEntries.length]; - for (int i = 0; i < mExtraEntries.length; i++) { - old[i] = mExtraEntries[i].form == LegendForm.NONE ? ColorTemplate.COLOR_SKIP : - (mExtraEntries[i].form == LegendForm.EMPTY ? ColorTemplate.COLOR_NONE : - mExtraEntries[i].formColor); - } - return old; - } - - @Deprecated - public String[] getExtraLabels() { - - String[] old = new String[mExtraEntries.length]; - for (int i = 0; i < mExtraEntries.length; i++) { - old[i] = mExtraEntries[i].label; - } - return old; - } - public LegendEntry[] getExtraEntries() { return mExtraEntries; @@ -339,11 +250,6 @@ public void setExtra(LegendEntry[] entries) { mExtraEntries = entries; } - @Deprecated - public void setExtra(List colors, List labels) { - setExtra(Utils.convertIntegers(colors), Utils.convertStrings(labels)); - } - /** * Entries that will be appended to the end of the auto calculated * entries after calculating the legend. From 42cdba535f5af8076f3a376afba543c7e41eb9d0 Mon Sep 17 00:00:00 2001 From: almic Date: Mon, 12 Nov 2018 10:58:17 -0700 Subject: [PATCH 1328/1390] Add Curved Slices to Pie Chart Finally added support for rounded slices, and somewhat improved the code for the PieChartRenderer class. --- .../mpchartexample/PieChartActivity.java | 12 + .../PiePolylineChartActivity.java | 12 + MPChartExample/src/main/res/menu/pie.xml | 4 + .../src/main/res/values/strings.xml | 1 + .../mikephil/charting/charts/PieChart.java | 10 + .../charting/renderer/PieChartRenderer.java | 273 ++++++++++-------- 6 files changed, 193 insertions(+), 119 deletions(-) diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 48bd4306c3..993941268c 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -210,6 +210,18 @@ public boolean onOptionsItemSelected(MenuItem item) { chart.invalidate(); break; } + case R.id.actionToggleCurvedSlices: { + boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); + chart.setDrawRoundedSlices(toSet); + if (toSet && !chart.isDrawHoleEnabled()) { + chart.setDrawHoleEnabled(true); + } + if (toSet && chart.isDrawSlicesUnderHoleEnabled()) { + chart.setDrawSlicesUnderHole(false); + } + chart.invalidate(); + break; + } case R.id.actionDrawCenter: { if (chart.isDrawCenterTextEnabled()) chart.setDrawCenterText(false); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index dc26f48297..157b93a638 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -205,6 +205,18 @@ public boolean onOptionsItemSelected(MenuItem item) { chart.invalidate(); break; } + case R.id.actionToggleCurvedSlices: { + boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); + chart.setDrawRoundedSlices(toSet); + if (toSet && !chart.isDrawHoleEnabled()) { + chart.setDrawHoleEnabled(true); + } + if (toSet && chart.isDrawSlicesUnderHoleEnabled()) { + chart.setDrawSlicesUnderHole(false); + } + chart.invalidate(); + break; + } case R.id.actionDrawCenter: { if (chart.isDrawCenterTextEnabled()) chart.setDrawCenterText(false); diff --git a/MPChartExample/src/main/res/menu/pie.xml b/MPChartExample/src/main/res/menu/pie.xml index b2de043409..56a892ed07 100644 --- a/MPChartExample/src/main/res/menu/pie.xml +++ b/MPChartExample/src/main/res/menu/pie.xml @@ -25,6 +25,10 @@ android:id="@+id/actionToggleHole" android:title="@string/actionToggleHole"> + + diff --git a/MPChartExample/src/main/res/values/strings.xml b/MPChartExample/src/main/res/values/strings.xml index 1e96d8b6b6..4afde3b1e4 100644 --- a/MPChartExample/src/main/res/values/strings.xml +++ b/MPChartExample/src/main/res/values/strings.xml @@ -41,6 +41,7 @@ Toggle Percent Toggle Hole + Toggle Curved Slices Draw Center Text Toggle Highlight Circle Toggle Rotation diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 660fd29bdc..0ed4502769 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -650,6 +650,16 @@ public void setEntryLabelTextSize(float size) { ((PieChartRenderer) mRenderer).getPaintEntryLabels().setTextSize(Utils.convertDpToPixel(size)); } + /** + * Sets whether to draw slices in a curved fashion, only works if drawing the hole is enabled + * and if the slices are not drawn under the hole. + * + * @param enabled draw curved ends of slices + */ + public void setDrawRoundedSlices(boolean enabled) { + mDrawRoundedSlices = enabled; + } + /** * Returns true if the chart is set to draw each end of a pie-slice * "rounded". diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index b14657cefc..c9f653e808 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -230,6 +230,9 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; + final float roundedRadius = (radius - (radius * mChart.getHoleRadius() / 100f)) / 2f; + final RectF roundedCircleBox = new RectF(); + final boolean drawRoundedSlices = drawInnerArc && mChart.isDrawRoundedSlicesEnabled(); int visibleAngleCount = 0; for (int j = 0; j < entryCount; j++) { @@ -249,133 +252,151 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero - if ((Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { + if (!(Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) { + angle += sliceAngle * phaseX; + continue; + } - if (!mChart.needsHighlight(j)) { + // Don't draw if it's highlighted, unless the chart uses rounded slices + if (mChart.needsHighlight(j) && !drawRoundedSlices) { + angle += sliceAngle * phaseX; + continue; + } - final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; + final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(dataSet.getColor(j)); + mRenderPaint.setColor(dataSet.getColor(j)); - final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? - 0.f : - sliceSpace / (Utils.FDEG2RAD * radius); - final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; - float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; - if (sweepAngleOuter < 0.f) { - sweepAngleOuter = 0.f; - } + final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * radius); + final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY; + float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY; + if (sweepAngleOuter < 0.f) { + sweepAngleOuter = 0.f; + } - mPathBuffer.reset(); + mPathBuffer.reset(); - float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); - float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); + if (drawRoundedSlices) { + float x = center.x + (radius - roundedRadius) * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + float y = center.y + (radius - roundedRadius) * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); + roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius); + } - if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { - // Android is doing "mod 360" - mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); - } else { + float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD); + float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD); - mPathBuffer.moveTo(arcStartPointX, arcStartPointY); + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW); + } else { - mPathBuffer.arcTo( - circleBox, - startAngleOuter, - sweepAngleOuter - ); - } + if (drawRoundedSlices) { + mPathBuffer.arcTo(roundedCircleBox, startAngleOuter + 180, -180); + } - // API < 21 does not receive floats in addArc, but a RectF - mInnerRectBuffer.set( - center.x - innerRadius, - center.y - innerRadius, - center.x + innerRadius, - center.y + innerRadius); - - if (drawInnerArc && - (innerRadius > 0.f || accountForSliceSpacing)) { - - if (accountForSliceSpacing) { - float minSpacedRadius = - calculateMinimumRadiusForSpacedSlice( - center, radius, - sliceAngle * phaseY, - arcStartPointX, arcStartPointY, - startAngleOuter, - sweepAngleOuter); - - if (minSpacedRadius < 0.f) - minSpacedRadius = -minSpacedRadius; - - innerRadius = Math.max(innerRadius, minSpacedRadius); - } + mPathBuffer.arcTo( + circleBox, + startAngleOuter, + sweepAngleOuter + ); + } - final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? - 0.f : - sliceSpace / (Utils.FDEG2RAD * innerRadius); - final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; - float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; - if (sweepAngleInner < 0.f) { - sweepAngleInner = 0.f; - } - final float endAngleInner = startAngleInner + sweepAngleInner; - - if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { - // Android is doing "mod 360" - mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); - } else { - - mPathBuffer.lineTo( - center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), - center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); - - mPathBuffer.arcTo( - mInnerRectBuffer, - endAngleInner, - -sweepAngleInner - ); - } - } else { + // API < 21 does not receive floats in addArc, but a RectF + mInnerRectBuffer.set( + center.x - innerRadius, + center.y - innerRadius, + center.x + innerRadius, + center.y + innerRadius); - if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { - if (accountForSliceSpacing) { - - float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; - - float sliceSpaceOffset = - calculateMinimumRadiusForSpacedSlice( - center, - radius, - sliceAngle * phaseY, - arcStartPointX, - arcStartPointY, - startAngleOuter, - sweepAngleOuter); - - float arcEndPointX = center.x + - sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); - float arcEndPointY = center.y + - sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); - - mPathBuffer.lineTo( - arcEndPointX, - arcEndPointY); - - } else { - mPathBuffer.lineTo( - center.x, - center.y); - } - } + if (drawInnerArc && (innerRadius > 0.f || accountForSliceSpacing)) { - } + if (accountForSliceSpacing) { + float minSpacedRadius = + calculateMinimumRadiusForSpacedSlice( + center, radius, + sliceAngle * phaseY, + arcStartPointX, arcStartPointY, + startAngleOuter, + sweepAngleOuter); - mPathBuffer.close(); + if (minSpacedRadius < 0.f) + minSpacedRadius = -minSpacedRadius; - mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); + innerRadius = Math.max(innerRadius, minSpacedRadius); } + + final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ? + 0.f : + sliceSpace / (Utils.FDEG2RAD * innerRadius); + final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY; + float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY; + if (sweepAngleInner < 0.f) { + sweepAngleInner = 0.f; + } + final float endAngleInner = startAngleInner + sweepAngleInner; + + if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) { + // Android is doing "mod 360" + mPathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW); + } else { + + if (drawRoundedSlices) { + float x = center.x + (radius - roundedRadius) * (float) Math.cos(endAngleInner * Utils.FDEG2RAD); + float y = center.y + (radius - roundedRadius) * (float) Math.sin(endAngleInner * Utils.FDEG2RAD); + roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius); + mPathBuffer.arcTo(roundedCircleBox, endAngleInner, 180); + } else + mPathBuffer.lineTo( + center.x + innerRadius * (float) Math.cos(endAngleInner * Utils.FDEG2RAD), + center.y + innerRadius * (float) Math.sin(endAngleInner * Utils.FDEG2RAD)); + + mPathBuffer.arcTo( + mInnerRectBuffer, + endAngleInner, + -sweepAngleInner + ); + } + } else { + + if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) { + if (accountForSliceSpacing) { + + float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f; + + float sliceSpaceOffset = + calculateMinimumRadiusForSpacedSlice( + center, + radius, + sliceAngle * phaseY, + arcStartPointX, + arcStartPointY, + startAngleOuter, + sweepAngleOuter); + + float arcEndPointX = center.x + + sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD); + float arcEndPointY = center.y + + sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD); + + mPathBuffer.lineTo( + arcEndPointX, + arcEndPointY); + + } else { + mPathBuffer.lineTo( + center.x, + center.y); + } + } + } + mPathBuffer.close(); + + mBitmapCanvas.drawPath(mPathBuffer, mRenderPaint); + angle += sliceAngle * phaseX; } @@ -396,11 +417,17 @@ public void drawValues(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); + final float roundedRadius = (radius - (radius * mChart.getHoleRadius() / 100f)) / 2f; final float holeRadiusPercent = mChart.getHoleRadius() / 100.f; float labelRadiusOffset = radius / 10f * 3.6f; if (mChart.isDrawHoleEnabled()) { labelRadiusOffset = (radius - (radius * holeRadiusPercent)) / 2f; + + if (!mChart.isDrawSlicesUnderHoleEnabled() && mChart.isDrawRoundedSlicesEnabled()) { + // Add curved circle slice and spacing to rotation angle, so that it sits nicely inside + rotationAngle += roundedRadius * 360 / (Math.PI * 2 * radius); + } } final float labelRadius = radius - labelRadiusOffset; @@ -472,6 +499,7 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getY() / yValueSum * 100f : entry.getY(); String formattedValue = formatter.getPieLabel(value, entry); + String entryLabel = entry.getLabel(); final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD); @@ -552,13 +580,13 @@ public void drawValues(Canvas c) { drawValue(c, formattedValue, labelPtx, labelPty, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight); } } else if (drawXOutside) { - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight / 2.f); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight / 2.f); } } else if (drawYOutside) { @@ -578,13 +606,13 @@ public void drawValues(Canvas c) { drawValue(c, formattedValue, x, y, dataSet.getValueTextColor(j)); - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), x, y + lineHeight); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, x, y + lineHeight); } } else if (drawXInside) { - if (j < data.getEntryCount() && entry.getLabel() != null) { - drawEntryLabel(c, entry.getLabel(), x, y + lineHeight / 2f); + if (j < data.getEntryCount() && entryLabel != null) { + drawEntryLabel(c, entryLabel, x, y + lineHeight / 2f); } } else if (drawYInside) { drawValue(c, formattedValue, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); @@ -637,7 +665,6 @@ protected void drawEntryLabel(Canvas c, String label, float x, float y) { @Override public void drawExtras(Canvas c) { - // drawCircles(c); drawHole(c); c.drawBitmap(mDrawBitmap.get(), 0, 0, null); drawCenterText(c); @@ -763,6 +790,15 @@ protected void drawCenterText(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { + /* Skip entirely if using rounded circle slices, because it doesn't make sense to highlight + * in this way. + * TODO: add support for changing slice color with highlighting rather than only shifting the slice + */ + + final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); + if (drawInnerArc && mChart.isDrawRoundedSlicesEnabled()) + return; + float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -773,7 +809,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] absoluteAngles = mChart.getAbsoluteAngles(); final MPPointF center = mChart.getCenterCircleBox(); final float radius = mChart.getRadius(); - final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled(); final float userInnerRadius = drawInnerArc ? radius * (mChart.getHoleRadius() / 100.f) : 0.f; From aea2ff3417e30d6d4b1ce7e777cbd8bc83e1c95d Mon Sep 17 00:00:00 2001 From: almic Date: Thu, 15 Nov 2018 09:51:46 -0700 Subject: [PATCH 1329/1390] Add option to set minimum angles Allows to force minimum slice angles when drawing charts, which means that any slices with angles lower than the minimum will be drawn with the minimum angle. When changing this setting on the fly, you have to call `notifyDataSetChanged()` and `invalidate()` for the minimum angle to take effect. This only functions if all slices can be drawn with the minimum angle. For example if a chart has 5 slices, the largest functioning minimum angle is `72f` degrees on a 360 degree chart, or 20% of the chart's `maxAngle`. --- .../mpchartexample/PieChartActivity.java | 9 +++ .../PiePolylineChartActivity.java | 9 +++ MPChartExample/src/main/res/menu/pie.xml | 4 ++ .../src/main/res/values/strings.xml | 1 + .../mikephil/charting/charts/PieChart.java | 66 ++++++++++++++++++- 5 files changed, 88 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 993941268c..4aeb1b3e9f 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -210,6 +210,15 @@ public boolean onOptionsItemSelected(MenuItem item) { chart.invalidate(); break; } + case R.id.actionToggleMinAngles: { + if (chart.getMinAngleForSlices() == 0f) + chart.setMinAngleForSlices(36f); + else + chart.setMinAngleForSlices(0f); + chart.notifyDataSetChanged(); + chart.invalidate(); + break; + } case R.id.actionToggleCurvedSlices: { boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); chart.setDrawRoundedSlices(toSet); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index 157b93a638..b276806c7d 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -205,6 +205,15 @@ public boolean onOptionsItemSelected(MenuItem item) { chart.invalidate(); break; } + case R.id.actionToggleMinAngles: { + if (chart.getMinAngleForSlices() == 0f) + chart.setMinAngleForSlices(36f); + else + chart.setMinAngleForSlices(0f); + chart.notifyDataSetChanged(); + chart.invalidate(); + break; + } case R.id.actionToggleCurvedSlices: { boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled(); chart.setDrawRoundedSlices(toSet); diff --git a/MPChartExample/src/main/res/menu/pie.xml b/MPChartExample/src/main/res/menu/pie.xml index 56a892ed07..09a05a9ccd 100644 --- a/MPChartExample/src/main/res/menu/pie.xml +++ b/MPChartExample/src/main/res/menu/pie.xml @@ -21,6 +21,10 @@ android:id="@+id/actionTogglePercent" android:title="@string/actionTogglePercent"> + + diff --git a/MPChartExample/src/main/res/values/strings.xml b/MPChartExample/src/main/res/values/strings.xml index 4afde3b1e4..91a25bb89e 100644 --- a/MPChartExample/src/main/res/values/strings.xml +++ b/MPChartExample/src/main/res/values/strings.xml @@ -40,6 +40,7 @@ Clear chart Toggle Percent + Toggle Minimum Angles Toggle Hole Toggle Curved Slices Draw Center Text diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java index 0ed4502769..de11b3a844 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/PieChart.java @@ -94,6 +94,12 @@ public class PieChart extends PieRadarChartBase { protected float mMaxAngle = 360f; + /** + * Minimum angle to draw slices, this only works if there is enough room for all slices to have + * the minimum angle, default 0f. + */ + private float mMinAngleForSlices = 0f; + public PieChart(Context context) { super(context); } @@ -228,7 +234,12 @@ private void calcAngles() { List dataSets = mData.getDataSets(); + boolean hasMinAngle = mMinAngleForSlices != 0f && entryCount * mMinAngleForSlices <= mMaxAngle; + float[] minAngles = new float[entryCount]; + int cnt = 0; + float offset = 0f; + float diff = 0f; for (int i = 0; i < mData.getDataSetCount(); i++) { @@ -236,7 +247,20 @@ private void calcAngles() { for (int j = 0; j < set.getEntryCount(); j++) { - mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum); + float drawAngle = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum); + + if (hasMinAngle) { + float temp = drawAngle - mMinAngleForSlices; + if (temp <= 0) { + minAngles[cnt] = mMinAngleForSlices; + offset += -temp; + } else { + minAngles[cnt] = drawAngle; + diff += temp; + } + } + + mDrawAngles[cnt] = drawAngle; if (cnt == 0) { mAbsoluteAngles[cnt] = mDrawAngles[cnt]; @@ -248,6 +272,20 @@ private void calcAngles() { } } + if (hasMinAngle) { + // Correct bigger slices by relatively reducing their angles based on the total angle needed to subtract + // This requires that `entryCount * mMinAngleForSlices <= mMaxAngle` be true to properly work! + for (int i = 0; i < entryCount; i++) { + minAngles[i] -= (minAngles[i] - mMinAngleForSlices) / diff * offset; + if (i == 0) { + mAbsoluteAngles[0] = minAngles[0]; + } else { + mAbsoluteAngles[i] = mAbsoluteAngles[i - 1] + minAngles[i]; + } + } + + mDrawAngles = minAngles; + } } /** @@ -729,6 +767,32 @@ public void setMaxAngle(float maxangle) { this.mMaxAngle = maxangle; } + /** + * The minimum angle slices on the chart are rendered with, default is 0f. + * + * @return minimum angle for slices + */ + public float getMinAngleForSlices() { + return mMinAngleForSlices; + } + + /** + * Set the angle to set minimum size for slices, you must call {@link #notifyDataSetChanged()} + * and {@link #invalidate()} when changing this, only works if there is enough room for all + * slices to have the minimum angle. + * + * @param minAngle minimum 0, maximum is half of {@link #setMaxAngle(float)} + */ + public void setMinAngleForSlices(float minAngle) { + + if (minAngle > (mMaxAngle / 2f)) + minAngle = mMaxAngle / 2f; + else if (minAngle < 0) + minAngle = 0f; + + this.mMinAngleForSlices = minAngle; + } + @Override protected void onDetachedFromWindow() { // releases the bitmap in the renderer to avoid oom error From c886bb342accd1596ed7211314081f776f257c14 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Feb 2019 22:51:10 +0100 Subject: [PATCH 1330/1390] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 53f278aba7..f26034da24 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,9 @@ Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wi 0x04ef098bf9f91871391363e3caf791afa3adc39b +[**Lightning Network (tippin.me)**](https://tippin.me/@PhilippJahoda) + + **PayPal** - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! From 59028d3bf3fcc7a6f337772ea8f7faa338e793c1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 21 Feb 2019 09:04:28 +0100 Subject: [PATCH 1331/1390] Update Bug_report.md --- .github/ISSUE_TEMPLATE/Bug_report.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md index 7989a9d655..3a5938eee9 100644 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ b/.github/ISSUE_TEMPLATE/Bug_report.md @@ -40,3 +40,5 @@ support questions here. We will close your issue without a response. If you have source code demonstrating this bug, create a Gist: https://help.github.com/articles/creating-gists/ and link to it here. --> + +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. From 7df8a4cedc17c5bda07e8edb38010dcd8e39b74f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 21 Feb 2019 09:04:40 +0100 Subject: [PATCH 1332/1390] Update Feature_request.md --- .github/ISSUE_TEMPLATE/Feature_request.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md index 823b940961..54b30c983b 100644 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ b/.github/ISSUE_TEMPLATE/Feature_request.md @@ -31,3 +31,4 @@ support questions here. We will close your issue without a response. **Additional context** +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. From 971640b29dc698c1c636549f4d94e254cf659d03 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 21 Feb 2019 09:05:06 +0100 Subject: [PATCH 1333/1390] Update Support_help.md --- .github/ISSUE_TEMPLATE/Support_help.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/Support_help.md b/.github/ISSUE_TEMPLATE/Support_help.md index 5a2c5fd41b..70a086d3d7 100644 --- a/.github/ISSUE_TEMPLATE/Support_help.md +++ b/.github/ISSUE_TEMPLATE/Support_help.md @@ -22,3 +22,6 @@ Instead, do the following: ### You have been warned! From now on, any issues asking for help will get closed with a link to this file. + +### Additional Context +ADD A REWARD using [Speed](speedoss.com) to SOLVE this issue QUICKLY and SUPPORT this project. From 2058f7bf5dd1c365f78174b09a91db3e4c2e480c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 16 Mar 2019 11:42:04 +0100 Subject: [PATCH 1334/1390] Minor changes to project and example --- .gitignore | 1 + MPChartExample/src/main/res/layout/list_item.xml | 1 + build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1120426ac8..1f0e3083c2 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ bin/ gen/ generated/ finalOutput/ +projectFilesBackup/ build.xml diff --git a/MPChartExample/src/main/res/layout/list_item.xml b/MPChartExample/src/main/res/layout/list_item.xml index a6e5b5f3eb..420add1193 100644 --- a/MPChartExample/src/main/res/layout/list_item.xml +++ b/MPChartExample/src/main/res/layout/list_item.xml @@ -12,6 +12,7 @@ android:layout_alignParentTop="true" android:layout_marginLeft="4dp" android:text="Medium Text" + android:textColor="@android:color/black" android:textSize="16sp"/> Date: Sat, 16 Mar 2019 11:53:42 +0100 Subject: [PATCH 1335/1390] New example app release --- MPChartExample/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 0a60389ede..2d607e9991 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -6,7 +6,7 @@ android { applicationId "com.xxmassdeveloper.mpchartexample" minSdkVersion 16 targetSdkVersion 28 - versionCode 56 + versionCode 57 versionName '3.1.0' testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -20,7 +20,7 @@ android { } dependencies { - implementation "androidx.appcompat:appcompat:1.0.0" + implementation "androidx.appcompat:appcompat:1.0.2" implementation 'com.google.android.material:material:1.0.0' implementation project(':MPChartLib') } From e95c1eb26a533e41017dbd49cc3d750457cdd435 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Mar 2019 17:56:58 +0100 Subject: [PATCH 1336/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f26034da24..d358d90f17 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ repositories { } dependencies { - implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha' + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' } ``` @@ -70,7 +70,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v3.1.0-alpha + v3.1.0 ``` @@ -80,7 +80,7 @@ dependencies { See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. -See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0-alpha/javadoc/) for more advanced documentation. +See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/) for more advanced documentation.
    From adb56e75bd5f5a2f1c3cf9dec556c22dc97b4ac0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 7 Apr 2019 16:20:14 +0200 Subject: [PATCH 1337/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d358d90f17..fa7a1c8386 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ dependencies {

    Documentation :notebook_with_decorative_cover:

    -See the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) for examples and general use of MPAndroidChart. +See the [**documentation**](https://weeklycoding.com/mpandroidchart/) for examples and general use of MPAndroidChart. See the [**javadocs**](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/) for more advanced documentation. @@ -96,7 +96,7 @@ Download the [MPAndroidChart Example App](https://play.google.com/store/apps/det This repository's issue tracker is only for bugs and feature requests. The maintainers ask that you refrain from asking questions about how to use MPAndroidChart through the issue tracker. -Please read the [**documentation**](https://github.com/PhilJay/MPAndroidChart/wiki) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer. +Please read the [**documentation**](https://weeklycoding.com/mpandroidchart/) first, then ask all your questions on [stackoverflow.com](https://stackoverflow.com/questions/tagged/mpandroidchart) for the fastest answer.
    @@ -209,7 +209,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah

    License :page_facing_up:

    -Copyright 2018 Philipp Jahoda +Copyright 2019 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 12b4351d0c862212ddb77f73716799cb97f58c04 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 7 Apr 2019 16:27:59 +0200 Subject: [PATCH 1338/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fa7a1c8386..4603c7b44e 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ All MPAndroidChart users are entitled to a special **discount of 5%** off the
    -## [Daily Coding Newsletter](https://philjay.substack.com/subscribe) +## [Bi-Weekly Coding Newsletter](https://weeklycoding.com) -Sign up for my [daily coding newsletter](https://philjay.substack.com/subscribe) to get quick updates on Kotlin and Android development related topics. +Sign up for my [coding newsletter](https://weeklycoding.com) to get quick updates on Kotlin and Android development related topics.

    Quick Start :chart_with_upwards_trend:

    From ed8876cef283249b63f12e2bb8931dd9e444ee17 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 7 Apr 2019 16:37:14 +0200 Subject: [PATCH 1339/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4603c7b44e..044a84f9a6 100644 --- a/README.md +++ b/README.md @@ -133,7 +133,7 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: [![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) [![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**daily coding newsletter**](https://philjay.substack.com/subscribe). +You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**coding newsletter**](https://weeklycoding.com).
    From 0563fb48b0fdc713ab1789c7544db413b26b1ae9 Mon Sep 17 00:00:00 2001 From: duchampdev Date: Sat, 27 Apr 2019 16:06:10 +0200 Subject: [PATCH 1340/1390] PercentFormatter: make space between number and percent sign optional --- .../mikephil/charting/formatter/PercentFormatter.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 6bf1bd3c33..3ee1447ecc 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -16,9 +16,11 @@ public class PercentFormatter extends ValueFormatter public DecimalFormat mFormat; private PieChart pieChart; + private boolean percentSignSeparated; public PercentFormatter() { mFormat = new DecimalFormat("###,###,##0.0"); + percentSignSeparated = true; } // Can be used to remove percent signs if the chart isn't in percent mode @@ -27,9 +29,15 @@ public PercentFormatter(PieChart pieChart) { this.pieChart = pieChart; } + // Can be used to remove percent signs if the chart isn't in percent mode + public PercentFormatter(PieChart pieChart, boolean percentSignSeparated) { + this(pieChart); + this.percentSignSeparated = percentSignSeparated; + } + @Override public String getFormattedValue(float value) { - return mFormat.format(value) + " %"; + return mFormat.format(value) + (percentSignSeparated ? " %" : "%"); } @Override From c5667d4f141962c29f6a8ffd59958026d1a10663 Mon Sep 17 00:00:00 2001 From: duchampdev Date: Sat, 27 Apr 2019 16:06:37 +0200 Subject: [PATCH 1341/1390] fix little typo --- .../github/mikephil/charting/formatter/PercentFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 3ee1447ecc..012fab77f9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -7,7 +7,7 @@ /** * This IValueFormatter is just for convenience and simply puts a "%" sign after - * each value. (Recommeded for PieChart) + * each value. (Recommended for PieChart) * * @author Philipp Jahoda */ From fffe9a297eb3972a353c7c4e70941c0c90d09344 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 27 Apr 2019 17:38:37 +0200 Subject: [PATCH 1342/1390] Update gradle --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index f083210162..cee7a83e80 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.2' + classpath 'com.android.tools.build:gradle:3.4.0' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c54dbf0954..0f8bc4e375 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Mar 16 11:37:10 CET 2019 +#Sat Apr 27 15:48:29 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip From dc5917152436d5e231f9b687c4862d4a30cb072b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 8 Oct 2019 14:15:21 +0200 Subject: [PATCH 1343/1390] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..41e266eed3 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: https://www.patreon.com/mpandroidchart +open_collective: philippjahoda +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From cb26ed4ef4ecab63390d73eaff1fb28ef40e0c98 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 8 Oct 2019 14:15:52 +0200 Subject: [PATCH 1344/1390] Update FUNDING.yml --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 41e266eed3..0a213d6792 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,7 +1,7 @@ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: https://www.patreon.com/mpandroidchart +patreon: mpandroidchart open_collective: philippjahoda ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel From d86f39cc917ced800fdd93dafe3da886686822f2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 20 Jan 2020 11:15:12 +0100 Subject: [PATCH 1345/1390] Update README.md --- README.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/README.md b/README.md index 044a84f9a6..c4325f61e5 100644 --- a/README.md +++ b/README.md @@ -23,21 +23,7 @@ 1. [License](#licence) 1. [Creators](#creators) -## [Realtime Graphing Solution | SciChart](https://scichart.com/android-chart-features?source=MPAndroidChart) - - - - -MPAndroidChart is free software, as a result **dynamic & realtime data is not officially supported**. If you are looking for an enterprise-grade chart solution with extreme realtime performance and tech support, we recommend -
    SciChart Android. - - - -All MPAndroidChart users are entitled to a special **discount of 5%** off the SciChart store, using the following discount code: **MPANDROIDCHART** - -
    - -## [Bi-Weekly Coding Newsletter](https://weeklycoding.com) +## [Coding Newsletter](https://weeklycoding.com) Sign up for my [coding newsletter](https://weeklycoding.com) to get quick updates on Kotlin and Android development related topics. From 95027fa6a7f4762d52ffa23cabd45135d7d26ff4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 09:55:00 +0200 Subject: [PATCH 1346/1390] Safe guards These will be even more important when moving to Kotlin ranges --- .../main/java/com/github/mikephil/charting/data/DataSet.java | 2 ++ .../com/github/mikephil/charting/renderer/LegendRenderer.java | 1 + 2 files changed, 3 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 3c69d9c58f..b474bfd894 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -86,6 +86,8 @@ public void calcMinMaxY(float fromX, float toX) { int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); + if (indexTo < indexFrom) return; + for (int i = indexFrom; i <= indexTo; i++) { // only recalculate y diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 85597db6a1..4e7e5d6448 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -90,6 +90,7 @@ public void computeLegend(ChartData data) { for (int i = 0; i < data.getDataSetCount(); i++) { IDataSet dataSet = data.getDataSetByIndex(i); + if (dataSet == null) continue; List clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); From 6ebf3fa57a2d3ae0a7c7cf57dfd7a31aa1758dab Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 10:27:55 +0200 Subject: [PATCH 1347/1390] Added highlightColor parameter for pie charts https://github.com/danielgindi/Charts/pull/2961 --- .../mikephil/charting/data/PieDataSet.java | 17 +++++++++++++++++ .../interfaces/datasets/IPieDataSet.java | 8 ++++++++ .../charting/renderer/PieChartRenderer.java | 5 ++++- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index e592399513..c473e0a752 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; +import android.support.annotation.Nullable; import java.util.ArrayList; import java.util.List; @@ -29,6 +30,7 @@ public class PieDataSet extends DataSet implements IPieDataSet { private float mValueLinePart1Length = 0.3f; private float mValueLinePart2Length = 0.4f; private boolean mValueLineVariableLength = true; + private Integer mHighlightColor = null; public PieDataSet(List yVals, String label) { super(yVals, label); @@ -218,6 +220,21 @@ public void setValueLineVariableLength(boolean valueLineVariableLength) { this.mValueLineVariableLength = valueLineVariableLength; } + /** Gets the color for the highlighted sector */ + @Override + @Nullable + public Integer getHighlightColor() + { + return mHighlightColor; + } + + /** Sets the color for the highlighted sector (null for using entry color) */ + public void setHighlightColor(@Nullable Integer color) + { + this.mHighlightColor = color; + } + + public enum ValuePosition { INSIDE_SLICE, OUTSIDE_SLICE diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 1698ef786b..1e1ca23532 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,5 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; +import android.support.annotation.Nullable; + import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; @@ -70,5 +72,11 @@ public interface IPieDataSet extends IDataSet { * */ boolean isValueLineVariableLength(); + /** + * Gets the color for the highlighted sector + * */ + @Nullable + Integer getHighlightColor(); + } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index c9f653e808..be3593adcb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -857,7 +857,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f; - mRenderPaint.setColor(set.getColor(index)); + Integer highlightColor = set.getHighlightColor(); + if (highlightColor == null) + highlightColor = set.getColor(index); + mRenderPaint.setColor(highlightColor); final float sliceSpaceAngleOuter = visibleAngleCount == 1 ? 0.f : From 1987d7eb64cfe07e378e1a79db6c9637138d7d54 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 11:04:57 +0200 Subject: [PATCH 1348/1390] Consider axis dependency in Combined chart https://github.com/danielgindi/Charts/pull/2874 --- .../mikephil/charting/data/CombinedData.java | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java index 39625b30f9..0b36aa3bef 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CombinedData.java @@ -3,6 +3,7 @@ import android.util.Log; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; @@ -91,18 +92,26 @@ public void calcMinMax() { if (data.getXMin() < mXMin) mXMin = data.getXMin(); - if (data.mLeftAxisMax > mLeftAxisMax) - mLeftAxisMax = data.mLeftAxisMax; - - if (data.mLeftAxisMin < mLeftAxisMin) - mLeftAxisMin = data.mLeftAxisMin; - - if (data.mRightAxisMax > mRightAxisMax) - mRightAxisMax = data.mRightAxisMax; - - if (data.mRightAxisMin < mRightAxisMin) - mRightAxisMin = data.mRightAxisMin; - + for (IBarLineScatterCandleBubbleDataSet dataset : sets) { + if (dataset.getAxisDependency() == YAxis.AxisDependency.LEFT) { + if (dataset.getYMax() > mLeftAxisMax) { + mLeftAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mLeftAxisMin) { + mLeftAxisMin = dataset.getYMin(); + } + } + else { + if (dataset.getYMax() > mRightAxisMax) { + mRightAxisMax = dataset.getYMax(); + } + + if (dataset.getYMin() < mRightAxisMin) { + mRightAxisMin = dataset.getYMin(); + } + } + } } } From 634a690d6a318aa3b3fa4e277f29359901e47b8b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 11:44:27 +0200 Subject: [PATCH 1349/1390] Added an implementation of Douglas Peucker with resultCount input https://github.com/danielgindi/Charts/pull/2848 --- .../charting/data/filter/ApproximatorN.java | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java new file mode 100644 index 0000000000..9351341c76 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/filter/ApproximatorN.java @@ -0,0 +1,146 @@ + +package com.github.mikephil.charting.data.filter; + +import java.util.ArrayList; + +/** + * Implemented according to modified Douglas Peucker {@link} + * http://psimpl.sourceforge.net/douglas-peucker.html + */ +public class ApproximatorN +{ + public float[] reduceWithDouglasPeucker(float[] points, float resultCount) { + + int pointCount = points.length / 2; + + // if a shape has 2 or less points it cannot be reduced + if (resultCount <= 2 || resultCount >= pointCount) + return points; + + boolean[] keep = new boolean[pointCount]; + + // first and last always stay + keep[0] = true; + keep[pointCount - 1] = true; + + int currentStoredPoints = 2; + + ArrayList queue = new ArrayList<>(); + Line line = new Line(0, pointCount - 1, points); + queue.add(line); + + do { + line = queue.remove(queue.size() - 1); + + // store the key + keep[line.index] = true; + + // check point count tolerance + currentStoredPoints += 1; + + if (currentStoredPoints == resultCount) + break; + + // split the polyline at the key and recurse + Line left = new Line(line.start, line.index, points); + if (left.index > 0) { + int insertionIndex = insertionIndex(left, queue); + queue.add(insertionIndex, left); + } + + Line right = new Line(line.index, line.end, points); + if (right.index > 0) { + int insertionIndex = insertionIndex(right, queue); + queue.add(insertionIndex, right); + } + } while (queue.isEmpty()); + + float[] reducedEntries = new float[currentStoredPoints * 2]; + + for (int i = 0, i2 = 0, r2 = 0; i < currentStoredPoints; i++, r2 += 2) { + if (keep[i]) { + reducedEntries[i2++] = points[r2]; + reducedEntries[i2++] = points[r2 + 1]; + } + } + + return reducedEntries; + } + + private static float distanceToLine( + float ptX, float ptY, float[] + fromLinePoint1, float[] fromLinePoint2) { + float dx = fromLinePoint2[0] - fromLinePoint1[0]; + float dy = fromLinePoint2[1] - fromLinePoint1[1]; + + float dividend = Math.abs( + dy * ptX - + dx * ptY - + fromLinePoint1[0] * fromLinePoint2[1] + + fromLinePoint2[0] * fromLinePoint1[1]); + double divisor = Math.sqrt(dx * dx + dy * dy); + + return (float)(dividend / divisor); + } + + private static class Line { + int start; + int end; + + float distance = 0; + int index = 0; + + Line(int start, int end, float[] points) { + this.start = start; + this.end = end; + + float[] startPoint = new float[]{points[start * 2], points[start * 2 + 1]}; + float[] endPoint = new float[]{points[end * 2], points[end * 2 + 1]}; + + if (end <= start + 1) return; + + for (int i = start + 1, i2 = i * 2; i < end; i++, i2 += 2) { + float distance = distanceToLine( + points[i2], points[i2 + 1], + startPoint, endPoint); + + if (distance > this.distance) { + this.index = i; + this.distance = distance; + } + } + } + + boolean equals(final Line rhs) { + return (start == rhs.start) && (end == rhs.end) && index == rhs.index; + } + + boolean lessThan(final Line rhs) { + return distance < rhs.distance; + } + } + + private static int insertionIndex(Line line, ArrayList queue) { + int min = 0; + int max = queue.size(); + + while (!queue.isEmpty()) { + int midIndex = min + (max - min) / 2; + Line midLine = queue.get(midIndex); + + if (midLine.equals(line)) { + return midIndex; + } + else if (line.lessThan(midLine)) { + // perform search in left half + max = midIndex; + } + else { + // perform search in right half + min = midIndex + 1; + } + } + + return min; + } +} From a4ca1f3fba59f7fe0865298968f564be9e4d0a1e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 11:47:45 +0200 Subject: [PATCH 1350/1390] Fixed axis label disappearing when zooming in https://github.com/danielgindi/Charts/pull/3132 --- .../com/github/mikephil/charting/renderer/AxisRenderer.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 90528a1359..8c21f452a9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -214,11 +214,14 @@ protected void computeAxisValues(float min, float max) { double f; int i; - if (interval != 0.0) { + if (interval != 0.0 && last != first) { for (f = first; f <= last; f += interval) { ++n; } } + else if (last == first && n == 0) { + n = 1; + } mAxis.mEntryCount = n; From 2e725e49d3429a58e731efc5257c649fbfbc3fc7 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 11:54:08 +0200 Subject: [PATCH 1351/1390] Make min/max axis labels configurable https://github.com/danielgindi/Charts/pull/2894 --- .../charting/components/AxisBase.java | 41 +++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index c1f02828be..96f706a3a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -151,6 +151,39 @@ public abstract class AxisBase extends ComponentBase { */ public float mAxisRange = 0f; + private int mAxisMinLabels = 2; + private int mAxisMaxLabels = 25; + + /** + * The minumum number of labels on the axis + */ + public int getAxisMinLabels() { + return mAxisMinLabels; + } + + /** + * The minumum number of labels on the axis + */ + public void setAxisMinLabels(int labels) { + if (labels > 0) + mAxisMinLabels = labels; + } + + /** + * The maximum number of labels on the axis + */ + public int getAxisMaxLabels() { + return mAxisMaxLabels; + } + + /** + * The maximum number of labels on the axis + */ + public void setAxisMaxLabels(int labels) { + if (labels > 0) + mAxisMaxLabels = labels; + } + /** * default constructor */ @@ -314,10 +347,10 @@ public boolean isDrawLabelsEnabled() { */ public void setLabelCount(int count) { - if (count > 25) - count = 25; - if (count < 2) - count = 2; + if (count > getAxisMaxLabels()) + count = getAxisMaxLabels(); + if (count < getAxisMinLabels()) + count = getAxisMinLabels(); mLabelCount = count; mForceLabels = false; From 3f5475077e549d08a5da6f95fcf3b4b6fe91eb2e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 11:59:43 +0200 Subject: [PATCH 1352/1390] Avoid race condition for interval/intervalMagnitude https://github.com/danielgindi/Charts/pull/2377 --- .../github/mikephil/charting/renderer/AxisRenderer.java | 9 ++++++--- .../charting/renderer/YAxisRendererRadarChart.java | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java index 8c21f452a9..72ea2d17c8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -174,9 +174,12 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); + } int n = mAxis.isCenterAxisLabelsEnabled() ? 1 : 0; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index ee7392e928..e3f69d7965 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -52,9 +52,11 @@ protected void computeAxisValues(float min, float max) { double intervalMagnitude = Utils.roundToNextSignificant(Math.pow(10, (int) Math.log10(interval))); int intervalSigDigit = (int) (interval / intervalMagnitude); if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); + // Use one order of magnitude higher, to avoid intervals like 0.9 or 90 + // if it's 0.0 after floor(), we use the old value + interval = Math.floor(10.0 * intervalMagnitude) == 0.0 + ? interval + : Math.floor(10.0 * intervalMagnitude); } boolean centeringEnabled = mAxis.isCenterAxisLabelsEnabled(); From 912427e54378602f44db00b4579dd2db50a23404 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:07:37 +0200 Subject: [PATCH 1353/1390] Custom text alignment for no-data https://github.com/danielgindi/Charts/pull/3199 --- .../mikephil/charting/charts/Chart.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 1889a9f6d4..5d3401c430 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -398,8 +398,23 @@ protected void onDraw(Canvas canvas) { boolean hasText = !TextUtils.isEmpty(mNoDataText); if (hasText) { - MPPointF c = getCenter(); - canvas.drawText(mNoDataText, c.x, c.y, mInfoPaint); + MPPointF pt = getCenter(); + + switch (mInfoPaint.getTextAlign()) { + case LEFT: + pt.x = 0; + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + + case RIGHT: + pt.x *= 2.0; + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + + default: + canvas.drawText(mNoDataText, pt.x, pt.y, mInfoPaint); + break; + } } return; @@ -1162,6 +1177,15 @@ public void setNoDataTextTypeface(Typeface tf) { mInfoPaint.setTypeface(tf); } + /** + * alignment of the no data text + * + * @param align + */ + public void setNoDataTextAlignment(Align align) { + mInfoPaint.setTextAlign(align); + } + /** * Set this to false to disable all gestures and touches on the chart, * default: true From 4549ae17b74967671ee218daf4a271c0283a98c1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:15:02 +0200 Subject: [PATCH 1354/1390] Select correct axis for legend distance calculation in horz bar chart https://github.com/danielgindi/Charts/pull/2214 --- .../charting/charts/BarLineChartBase.java | 124 +++++++++--------- .../charting/charts/HorizontalBarChart.java | 78 +++++++++++ 2 files changed, 142 insertions(+), 60 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index 71f8a2d8a8..c7a593736f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -394,66 +394,70 @@ protected void calculateLegendOffsets(RectF offsets) { offsets.top = 0.f; offsets.bottom = 0.f; - // setup offsets for legend - if (mLegend != null && mLegend.isEnabled() && !mLegend.isDrawInsideEnabled()) { - switch (mLegend.getOrientation()) { - case VERTICAL: - - switch (mLegend.getHorizontalAlignment()) { - case LEFT: - offsets.left += Math.min(mLegend.mNeededWidth, - mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) - + mLegend.getXOffset(); - break; - - case RIGHT: - offsets.right += Math.min(mLegend.mNeededWidth, - mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) - + mLegend.getXOffset(); - break; - - case CENTER: - - switch (mLegend.getVerticalAlignment()) { - case TOP: - offsets.top += Math.min(mLegend.mNeededHeight, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) - + mLegend.getYOffset(); - break; - - case BOTTOM: - offsets.bottom += Math.min(mLegend.mNeededHeight, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) - + mLegend.getYOffset(); - break; - - default: - break; - } - } - - break; - - case HORIZONTAL: - - switch (mLegend.getVerticalAlignment()) { - case TOP: - offsets.top += Math.min(mLegend.mNeededHeight, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) - + mLegend.getYOffset(); - break; - - case BOTTOM: - offsets.bottom += Math.min(mLegend.mNeededHeight, - mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) - + mLegend.getYOffset(); - break; - - default: - break; - } - break; - } + if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled()) + return; + + switch (mLegend.getOrientation()) { + case VERTICAL: + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + offsets.left += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case RIGHT: + offsets.right += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case CENTER: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + default: + break; + } + } + + break; + + case HORIZONTAL: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + + break; + + default: + break; + } + break; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java index e4ec309d9f..9aac1ce97c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -60,6 +60,84 @@ protected void init() { private RectF mOffsetsBuffer = new RectF(); + protected void calculateLegendOffsets(RectF offsets) { + + offsets.left = 0.f; + offsets.right = 0.f; + offsets.top = 0.f; + offsets.bottom = 0.f; + + if (mLegend == null || !mLegend.isEnabled() || mLegend.isDrawInsideEnabled()) + return; + + switch (mLegend.getOrientation()) { + case VERTICAL: + + switch (mLegend.getHorizontalAlignment()) { + case LEFT: + offsets.left += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case RIGHT: + offsets.right += Math.min(mLegend.mNeededWidth, + mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset(); + break; + + case CENTER: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + break; + + default: + break; + } + } + + break; + + case HORIZONTAL: + + switch (mLegend.getVerticalAlignment()) { + case TOP: + offsets.top += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisLeft.isEnabled() && mAxisLeft.isDrawLabelsEnabled()) + offsets.top += mAxisLeft.getRequiredHeightSpace( + mAxisRendererLeft.getPaintAxisLabels()); + break; + + case BOTTOM: + offsets.bottom += Math.min(mLegend.mNeededHeight, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()) + + mLegend.getYOffset(); + + if (mAxisRight.isEnabled() && mAxisRight.isDrawLabelsEnabled()) + offsets.bottom += mAxisRight.getRequiredHeightSpace( + mAxisRendererRight.getPaintAxisLabels()); + break; + + default: + break; + } + break; + } + } + @Override public void calculateOffsets() { From bafb0fbbe4a787bad4d64a87bf0df5cc573ca90a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:16:48 +0200 Subject: [PATCH 1355/1390] Use correct color index for bubble chart https://github.com/danielgindi/Charts/pull/3202 --- .../github/mikephil/charting/renderer/BubbleChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 57b81c1d9c..be141c46a0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -108,7 +108,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { if (!mViewPortHandler.isInBoundsRight(pointBuffer[0] - shapeHalf)) break; - final int color = dataSet.getColor((int) entry.getX()); + final int color = dataSet.getColor(j); mRenderPaint.setColor(color); c.drawCircle(pointBuffer[0], pointBuffer[1], shapeHalf, mRenderPaint); From ea816e8d6df174d060cdbab47c993d996b6f156d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:25:34 +0200 Subject: [PATCH 1356/1390] Added dataIndex param for highlightValue (combined charts) https://github.com/danielgindi/Charts/pull/2852 --- .../mikephil/charting/charts/Chart.java | 60 +++++++++++++++++-- .../charting/highlight/Highlight.java | 8 +++ 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index 5d3401c430..b104935d30 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -563,6 +563,18 @@ public void highlightValues(Highlight[] highs) { invalidate(); } + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + */ + public void highlightValue(float x, int dataSetIndex, int dataIndex) { + highlightValue(x, dataSetIndex, dataIndex, true); + } + /** * Highlights any y-value at the given x-value in the given DataSet. * Provide -1 as the dataSetIndex to undo all highlighting. @@ -571,7 +583,20 @@ public void highlightValues(Highlight[] highs) { * @param dataSetIndex The dataset index to search in */ public void highlightValue(float x, int dataSetIndex) { - highlightValue(x, dataSetIndex, true); + highlightValue(x, dataSetIndex, -1, true); + } + + /** + * Highlights the value at the given x-value and y-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * This method will call the listener. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + */ + public void highlightValue(float x, float y, int dataSetIndex, int dataIndex) { + highlightValue(x, y, dataSetIndex, dataIndex, true); } /** @@ -583,7 +608,19 @@ public void highlightValue(float x, int dataSetIndex) { * @param dataSetIndex The dataset index to search in */ public void highlightValue(float x, float y, int dataSetIndex) { - highlightValue(x, y, dataSetIndex, true); + highlightValue(x, y, dataSetIndex, -1, true); + } + + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, int dataSetIndex, int dataIndex, boolean callListener) { + highlightValue(x, Float.NaN, dataSetIndex, dataIndex, callListener); } /** @@ -594,7 +631,7 @@ public void highlightValue(float x, float y, int dataSetIndex) { * @param callListener Should the listener be called for this change */ public void highlightValue(float x, int dataSetIndex, boolean callListener) { - highlightValue(x, Float.NaN, dataSetIndex, callListener); + highlightValue(x, Float.NaN, dataSetIndex, -1, callListener); } /** @@ -603,17 +640,30 @@ public void highlightValue(float x, int dataSetIndex, boolean callListener) { * @param x The x-value to highlight * @param y The y-value to highlight. Supply `NaN` for "any" * @param dataSetIndex The dataset index to search in + * @param dataIndex The data index to search in (only used in CombinedChartView currently) * @param callListener Should the listener be called for this change */ - public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { + public void highlightValue(float x, float y, int dataSetIndex, int dataIndex, boolean callListener) { if (dataSetIndex < 0 || dataSetIndex >= mData.getDataSetCount()) { highlightValue(null, callListener); } else { - highlightValue(new Highlight(x, y, dataSetIndex), callListener); + highlightValue(new Highlight(x, y, dataSetIndex, dataIndex), callListener); } } + /** + * Highlights any y-value at the given x-value in the given DataSet. + * Provide -1 as the dataSetIndex to undo all highlighting. + * @param x The x-value to highlight + * @param y The y-value to highlight. Supply `NaN` for "any" + * @param dataSetIndex The dataset index to search in + * @param callListener Should the listener be called for this change + */ + public void highlightValue(float x, float y, int dataSetIndex, boolean callListener) { + highlightValue(x, y, dataSetIndex, -1, callListener); + } + /** * Highlights the values represented by the provided Highlight object * This method *will not* call the listener. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java index 032698d5e5..62307cbeaf 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/highlight/Highlight.java @@ -60,10 +60,18 @@ public class Highlight { */ private float mDrawY; + public Highlight(float x, float y, int dataSetIndex, int dataIndex) { + this.mX = x; + this.mY = y; + this.mDataSetIndex = dataSetIndex; + this.mDataIndex = dataIndex; + } + public Highlight(float x, float y, int dataSetIndex) { this.mX = x; this.mY = y; this.mDataSetIndex = dataSetIndex; + this.mDataIndex = -1; } public Highlight(float x, int dataSetIndex, int stackIndex) { From 34c3ceaa0599e27f8cb3fb4532988e02eac9a453 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:29:47 +0200 Subject: [PATCH 1357/1390] Reset min/max when clearing ChartDataSet https://github.com/danielgindi/Charts/pull/3265 --- .../com/github/mikephil/charting/data/DataSet.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index b474bfd894..f28f92581b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -61,14 +61,14 @@ public DataSet(List values, String label) { @Override public void calcMinMax() { - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; + if (mValues == null || mValues.isEmpty()) + return; + for (T e : mValues) { calcMinMax(e); } @@ -76,12 +76,11 @@ public void calcMinMax() { @Override public void calcMinMaxY(float fromX, float toX) { - - if (mValues == null || mValues.isEmpty()) - return; - mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; + + if (mValues == null || mValues.isEmpty()) + return; int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); int indexTo = getEntryIndex(toX, Float.NaN, Rounding.UP); From 8df9eda7af8025eb0702baa5ae2f5dd1dcd8e4b1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:39:03 +0200 Subject: [PATCH 1358/1390] Call notifyDataChanged for an opportunity for subclasses --- .../java/com/github/mikephil/charting/data/ChartData.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 9bd460290d..95d439a71d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -399,7 +399,7 @@ public boolean removeDataSet(T d) { // if a DataSet was removed if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; @@ -526,7 +526,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = set.removeEntry(e); if (removed) { - calcMinMax(); + notifyDataChanged(); } return removed; From 4ce14e6cc90fbe8706fb4d0c5fbec4184927f6c3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:42:32 +0200 Subject: [PATCH 1359/1390] Add a warning message if pie chart has more than one data set https://github.com/danielgindi/Charts/pull/3286 --- .../com/github/mikephil/charting/data/PieData.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java index db7972a3fb..96667aede6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import android.util.Log; + import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; @@ -46,6 +48,18 @@ public IPieDataSet getDataSet() { return mDataSets.get(0); } + @Override + public List getDataSets() { + List dataSets = super.getDataSets(); + + if (dataSets.size() < 1) { + Log.e("MPAndroidChart", + "Found multiple data sets while pie chart only allows one"); + } + + return dataSets; + } + /** * The PieData object can only have one DataSet. Use getDataSet() method instead. * From 58545bbbfa04b053d10784df9e041c4fc3d08b9d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 12:46:37 +0200 Subject: [PATCH 1360/1390] Add option to disable clipping data to contentRect https://github.com/danielgindi/Charts/pull/3360 --- .../charting/charts/BarLineChartBase.java | 31 +++++++++++++++++-- .../mikephil/charting/data/PieData.java | 2 +- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java index c7a593736f..0926dff244 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -100,6 +100,8 @@ public abstract class BarLineChartBase getDataSets() { Log.e("MPAndroidChart", "Found multiple data sets while pie chart only allows one"); } - + return dataSets; } From 7752efef7e09a7b782c490ee034bb0295d51f004 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 13:04:11 +0200 Subject: [PATCH 1361/1390] Support for labelXOffset for YAxis label --- .../mikephil/charting/charts/RadarChart.java | 1 + .../mikephil/charting/components/YAxis.java | 21 +++++++++++++++++++ .../charting/renderer/YAxisRenderer.java | 7 ++++++- .../YAxisRendererHorizontalBarChart.java | 7 ++++++- .../renderer/YAxisRendererRadarChart.java | 4 +++- 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java index 3c9aec0dde..8c0885395d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/RadarChart.java @@ -84,6 +84,7 @@ protected void init() { super.init(); mYAxis = new YAxis(AxisDependency.LEFT); + mYAxis.setLabelXOffset(10f); mWebLineWidth = Utils.convertDpToPixel(1.5f); mInnerWebLineWidth = Utils.convertDpToPixel(0.75f); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index 030603f55a..a4e58c1b68 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -73,6 +73,11 @@ public class YAxis extends AxisBase { */ private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + /** + * the horizontal offset of the y-label + */ + private float mXLabelOffset = 0.0f; + /** * enum for the position of the y-labels relative to the chart */ @@ -174,6 +179,22 @@ public void setPosition(YAxisLabelPosition pos) { mPosition = pos; } + /** + * returns the horizontal offset of the y-label + */ + public float getLabelXOffset() { + return mXLabelOffset; + } + + /** + * sets the horizontal offset of the y-label + * + * @param xOffset + */ + public void setLabelXOffset(float xOffset) { + mXLabelOffset = xOffset; + } + /** * returns true if drawing the top y-axis label entry is enabled * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java index a2bf679777..53cca7ee03 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -119,12 +119,17 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + // draw for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); + c.drawText(text, + fixedPosition + xOffset, + positions[i * 2 + 1] + offset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 71275b03c3..fedf8054a1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -142,11 +142,16 @@ protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, flo ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int i = from; i < to; i++) { String text = mYAxis.getFormattedLabel(i); - c.drawText(text, positions[i * 2], fixedPosition - offset, mAxisLabelPaint); + c.drawText(text, + positions[i * 2], + fixedPosition - offset + xOffset, + mAxisLabelPaint); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index e3f69d7965..f7b1ad9e87 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -163,6 +163,8 @@ public void renderAxisLabels(Canvas c) { ? mYAxis.mEntryCount : (mYAxis.mEntryCount - 1); + float xOffset = mYAxis.getLabelXOffset(); + for (int j = from; j < to; j++) { float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; @@ -171,7 +173,7 @@ public void renderAxisLabels(Canvas c) { String label = mYAxis.getFormattedLabel(j); - c.drawText(label, pOut.x + 10, pOut.y, mAxisLabelPaint); + c.drawText(label, pOut.x + xOffset, pOut.y, mAxisLabelPaint); } MPPointF.recycleInstance(center); MPPointF.recycleInstance(pOut); From ae59e7a19e70b53d419eacd3d9520d76ff4553cd Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 13:12:04 +0200 Subject: [PATCH 1362/1390] This is for the inline bubble selection https://github.com/danielgindi/Charts/pull/3548 --- .../main/java/com/github/mikephil/charting/data/DataSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index f28f92581b..08fd76ba01 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -367,7 +367,7 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { if (value.getX() != closestXValue) break; - if (Math.abs(value.getY() - closestToY) < Math.abs(closestYValue - closestToY)) { + if (Math.abs(value.getY() - closestToY) <= Math.abs(closestYValue - closestToY)) { closestYValue = closestToY; closestYIndex = closest; } From c97c8d247f0a882ce1a034d2f08700a5550564f4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 13:23:12 +0200 Subject: [PATCH 1363/1390] Fixed index out of bounds issue when using stacked bar chart https://github.com/danielgindi/Charts/commit/b03cf16ec47437c066e17b5b8f77322111695e6a --- .../github/mikephil/charting/data/BarDataSet.java | 4 +--- .../mikephil/charting/renderer/LegendRenderer.java | 13 +++++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 496f4046f8..ed076dc94a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -38,9 +38,7 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl /** * array of labels used to describe the different values of the stacked bars */ - private String[] mStackLabels = new String[]{ - "Stack" - }; + private String[] mStackLabels = new String[]{}; public BarDataSet(List yVals, String label) { super(yVals, label); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java index 4e7e5d6448..5d49580561 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -101,10 +101,19 @@ public void computeLegend(ChartData data) { IBarDataSet bds = (IBarDataSet) dataSet; String[] sLabels = bds.getStackLabels(); - for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { + int minEntries = Math.min(clrs.size(), bds.getStackSize()); + + for (int j = 0; j < minEntries; j++) { + String label; + if (sLabels.length > 0) { + int labelIndex = j % minEntries; + label = labelIndex < sLabels.length ? sLabels[labelIndex] : null; + } else { + label = null; + } computedEntries.add(new LegendEntry( - sLabels[j % sLabels.length], + label, dataSet.getForm(), dataSet.getFormSize(), dataSet.getFormLineWidth(), From 13aee592b189fdfc803b6380318dba4853d4c476 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 13:43:42 +0200 Subject: [PATCH 1364/1390] Improve min/max calculation https://github.com/danielgindi/Charts/pull/3650 --- .../mikephil/charting/components/YAxis.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java index a4e58c1b68..d2071ec5a8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/YAxis.java @@ -427,6 +427,26 @@ public void calculate(float dataMin, float dataMax) { float min = dataMin; float max = dataMax; + // Make sure max is greater than min + // Discussion: https://github.com/danielgindi/Charts/pull/3650#discussion_r221409991 + if (min > max) + { + if (mCustomAxisMax && mCustomAxisMin) + { + float t = min; + min = max; + max = t; + } + else if (mCustomAxisMax) + { + min = max < 0f ? max * 1.5f : max * 0.5f; + } + else if (mCustomAxisMin) + { + max = min < 0f ? min * 0.5f : min * 1.5f; + } + } + float range = Math.abs(max - min); // in case all values are equal From fcc5af71ce2991e62aeebe48705e1f4076649a27 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 13:49:10 +0200 Subject: [PATCH 1365/1390] Call onChartScale listener after double-tap-zoom https://github.com/danielgindi/Charts/pull/3770 --- .../charting/listener/BarLineChartTouchListener.java | 9 ++++++++- .../charting/listener/OnChartGestureListener.java | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 53ab12a369..5685d32fa0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -580,12 +580,19 @@ public boolean onDoubleTap(MotionEvent e) { MPPointF trans = getTrans(e.getX(), e.getY()); - mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); + float scaleX = mChart.isScaleXEnabled() ? 1.4f : 1f; + float scaleY = mChart.isScaleYEnabled() ? 1.4f : 1f; + + mChart.zoom(scaleX, scaleY, trans.x, trans.y); if (mChart.isLogEnabled()) Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " + trans.y); + if (l != null) { + l.onChartScale(e, scaleX, scaleY); + } + MPPointF.recycleInstance(trans); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java index a17cdde941..da0c5ed180 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -57,7 +57,7 @@ public interface OnChartGestureListener { void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY); /** - * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. + * Callbacks when the chart is scaled / zoomed via pinch zoom / double-tap gesture. * * @param me * @param scaleX scalefactor on the x-axis From e02e9be2fa52d9faf8518f4f9ed81248c8a87346 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 14:13:31 +0200 Subject: [PATCH 1366/1390] Multiple colors for valueline https://github.com/danielgindi/Charts/pull/3709 --- .../PiePolylineChartActivity.java | 1 - .../mikephil/charting/data/PieDataSet.java | 31 +++++++++++++++---- .../interfaces/datasets/IPieDataSet.java | 8 ++--- .../charting/renderer/PieChartRenderer.java | 15 ++++++--- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java index b276806c7d..dd3bd575da 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PiePolylineChartActivity.java @@ -156,7 +156,6 @@ private void setData(int count, float range) { dataSet.setValueLinePart1OffsetPercentage(80.f); dataSet.setValueLinePart1Length(0.2f); dataSet.setValueLinePart2Length(0.4f); - //dataSet.setUsingSliceColorAsValueLineColor(true); //dataSet.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataSet.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index c473e0a752..8aea673dba 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -23,8 +23,8 @@ public class PieDataSet extends DataSet implements IPieDataSet { private ValuePosition mXValuePosition = ValuePosition.INSIDE_SLICE; private ValuePosition mYValuePosition = ValuePosition.INSIDE_SLICE; - private boolean mUsingSliceColorAsValueLineColor = false; private int mValueLineColor = 0xff000000; + private boolean mUseValueColorForLine = false; private float mValueLineWidth = 1.0f; private float mValueLinePart1OffsetPercentage = 75.f; private float mValueLinePart1Length = 0.3f; @@ -137,15 +137,23 @@ public void setYValuePosition(ValuePosition yValuePosition) { } /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * This method is deprecated. + * Use isUseValueColorForLineEnabled() instead. */ - @Override + @Deprecated public boolean isUsingSliceColorAsValueLineColor() { - return mUsingSliceColorAsValueLineColor; + return isUseValueColorForLineEnabled(); } - public void setUsingSliceColorAsValueLineColor(boolean usingSliceColorAsValueLineColor) { - this.mUsingSliceColorAsValueLineColor = usingSliceColorAsValueLineColor; + /** + * This method is deprecated. + * Use setUseValueColorForLine(...) instead. + * + * @param enabled + */ + @Deprecated + public void setUsingSliceColorAsValueLineColor(boolean enabled) { + setUseValueColorForLine(enabled); } /** @@ -160,6 +168,17 @@ public void setValueLineColor(int valueLineColor) { this.mValueLineColor = valueLineColor; } + @Override + public boolean isUseValueColorForLineEnabled() + { + return mUseValueColorForLine; + } + + public void setUseValueColorForLine(boolean enabled) + { + mUseValueColorForLine = enabled; + } + /** * When valuePosition is OutsideSlice, indicates line width */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 1e1ca23532..3720394f25 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -38,14 +38,14 @@ public interface IPieDataSet extends IDataSet { PieDataSet.ValuePosition getYValuePosition(); /** - * When valuePosition is OutsideSlice, use slice colors as line color if true + * When valuePosition is OutsideSlice, indicates line color * */ - boolean isUsingSliceColorAsValueLineColor(); + int getValueLineColor(); /** - * When valuePosition is OutsideSlice, indicates line color + * When valuePosition is OutsideSlice and enabled, line will have the same color as the slice * */ - int getValueLineColor(); + boolean isUseValueColorForLineEnabled(); /** * When valuePosition is OutsideSlice, indicates line width diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index be3593adcb..82654d4816 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -468,7 +468,9 @@ public void drawValues(Canvas c) { int entryCount = dataSet.getEntryCount(); - mValueLinePaint.setColor(dataSet.getValueLineColor()); + boolean isUseValueColorForLineEnabled = dataSet.isUseValueColorForLineEnabled(); + int valueLineColor = dataSet.getValueLineColor(); + mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth())); final float sliceSpace = getSliceSpace(dataSet); @@ -565,12 +567,15 @@ public void drawValues(Canvas c) { labelPty = pt2y; } - if (dataSet.getValueLineColor() != ColorTemplate.COLOR_NONE) { + int lineColor = ColorTemplate.COLOR_NONE; - if (dataSet.isUsingSliceColorAsValueLineColor()) { - mValueLinePaint.setColor(dataSet.getColor(j)); - } + if (isUseValueColorForLineEnabled) + lineColor = dataSet.getColor(j); + else if (valueLineColor != ColorTemplate.COLOR_NONE) + lineColor = valueLineColor; + if (lineColor != ColorTemplate.COLOR_NONE) { + mValueLinePaint.setColor(lineColor); c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint); c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint); } From 14456f475fcfab0875e3f81604c4c7d69eea5fe0 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 14:24:37 +0200 Subject: [PATCH 1367/1390] Renamed values -> entries for consistency https://github.com/danielgindi/Charts/pull/3847 --- .../mikephil/charting/data/BarDataSet.java | 4 +- .../mikephil/charting/data/BubbleDataSet.java | 4 +- .../mikephil/charting/data/CandleDataSet.java | 4 +- .../mikephil/charting/data/DataSet.java | 114 +++++++++++------- .../mikephil/charting/data/LineDataSet.java | 4 +- .../mikephil/charting/data/PieDataSet.java | 4 +- .../mikephil/charting/data/RadarDataSet.java | 4 +- .../charting/data/ScatterDataSet.java | 4 +- 8 files changed, 82 insertions(+), 60 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index ed076dc94a..7b7ee5f916 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -52,8 +52,8 @@ public BarDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BarDataSet copied = new BarDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java index 1f88272dd9..9ef87fb2d5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BubbleDataSet.java @@ -42,8 +42,8 @@ protected void calcMinMax(BubbleEntry e) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } BubbleDataSet copied = new BubbleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java index c7f8362803..dcd5b76cea 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/CandleDataSet.java @@ -80,8 +80,8 @@ public CandleDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } CandleDataSet copied = new CandleDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java index 08fd76ba01..fda07efef2 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/DataSet.java @@ -17,7 +17,7 @@ public abstract class DataSet extends BaseDataSet { /** * the entries that this DataSet represents / holds together */ - protected List mValues = null; + protected List mEntries; /** * maximum y-value in the value array @@ -45,15 +45,15 @@ public abstract class DataSet extends BaseDataSet { * label that describes the DataSet can be specified. The label can also be * used to retrieve the DataSet from a ChartData object. * - * @param values + * @param entries * @param label */ - public DataSet(List values, String label) { + public DataSet(List entries, String label) { super(label); - this.mValues = values; + this.mEntries = entries; - if (mValues == null) - mValues = new ArrayList(); + if (mEntries == null) + mEntries = new ArrayList(); calcMinMax(); } @@ -66,10 +66,10 @@ public void calcMinMax() { mXMax = -Float.MAX_VALUE; mXMin = Float.MAX_VALUE; - if (mValues == null || mValues.isEmpty()) + if (mEntries == null || mEntries.isEmpty()) return; - for (T e : mValues) { + for (T e : mEntries) { calcMinMax(e); } } @@ -79,7 +79,7 @@ public void calcMinMaxY(float fromX, float toX) { mYMax = -Float.MAX_VALUE; mYMin = Float.MAX_VALUE; - if (mValues == null || mValues.isEmpty()) + if (mEntries == null || mEntries.isEmpty()) return; int indexFrom = getEntryIndex(fromX, Float.NaN, Rounding.DOWN); @@ -90,7 +90,7 @@ public void calcMinMaxY(float fromX, float toX) { for (int i = indexFrom; i <= indexTo; i++) { // only recalculate y - calcMinMaxY(mValues.get(i)); + calcMinMaxY(mEntries.get(i)); } } @@ -129,25 +129,47 @@ protected void calcMinMaxY(T e) { @Override public int getEntryCount() { - return mValues.size(); + return mEntries.size(); } /** - * Returns the array of entries that this DataSet represents. + * This method is deprecated. + * Use getEntries() instead. * * @return */ + @Deprecated public List getValues() { - return mValues; + return mEntries; } /** - * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * Returns the array of entries that this DataSet represents. * * @return */ + public List getEntries() { + return mEntries; + } + + /** + * This method is deprecated. + * Use setEntries(...) instead. + * + * @param values + */ + @Deprecated public void setValues(List values) { - mValues = values; + setEntries(values); + } + + /** + * Sets the array of entries that this DataSet represents, and calls notifyDataSetChanged() + * + * @return + */ + public void setEntries(List entries) { + mEntries = entries; notifyDataSetChanged(); } @@ -170,8 +192,8 @@ protected void copy(DataSet dataSet) { public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(toSimpleString()); - for (int i = 0; i < mValues.size(); i++) { - buffer.append(mValues.get(i).toString() + " "); + for (int i = 0; i < mEntries.size(); i++) { + buffer.append(mEntries.get(i).toString() + " "); } return buffer.toString(); } @@ -184,7 +206,7 @@ public String toString() { */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); - buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mValues.size() + + buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mEntries.size() + "\n"); return buffer.toString(); } @@ -215,23 +237,23 @@ public void addEntryOrdered(T e) { if (e == null) return; - if (mValues == null) { - mValues = new ArrayList(); + if (mEntries == null) { + mEntries = new ArrayList(); } calcMinMax(e); - if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getX() > e.getX()) { + if (mEntries.size() > 0 && mEntries.get(mEntries.size() - 1).getX() > e.getX()) { int closestIndex = getEntryIndex(e.getX(), e.getY(), Rounding.UP); - mValues.add(closestIndex, e); + mEntries.add(closestIndex, e); } else { - mValues.add(e); + mEntries.add(e); } } @Override public void clear() { - mValues.clear(); + mEntries.clear(); notifyDataSetChanged(); } @@ -241,9 +263,9 @@ public boolean addEntry(T e) { if (e == null) return false; - List values = getValues(); + List values = getEntries(); if (values == null) { - values = new ArrayList(); + values = new ArrayList<>(); } calcMinMax(e); @@ -258,11 +280,11 @@ public boolean removeEntry(T e) { if (e == null) return false; - if (mValues == null) + if (mEntries == null) return false; // remove the entry - boolean removed = mValues.remove(e); + boolean removed = mEntries.remove(e); if (removed) { calcMinMax(); @@ -273,7 +295,7 @@ public boolean removeEntry(T e) { @Override public int getEntryIndex(Entry e) { - return mValues.indexOf(e); + return mEntries.indexOf(e); } @Override @@ -281,7 +303,7 @@ public T getEntryForXValue(float xValue, float closestToY, Rounding rounding) { int index = getEntryIndex(xValue, closestToY, rounding); if (index > -1) - return mValues.get(index); + return mEntries.get(index); return null; } @@ -292,24 +314,24 @@ public T getEntryForXValue(float xValue, float closestToY) { @Override public T getEntryForIndex(int index) { - return mValues.get(index); + return mEntries.get(index); } @Override public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { - if (mValues == null || mValues.isEmpty()) + if (mEntries == null || mEntries.isEmpty()) return -1; int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; int closest = high; while (low < high) { int m = (low + high) / 2; - final float d1 = mValues.get(m).getX() - xValue, - d2 = mValues.get(m + 1).getX() - xValue, + final float d1 = mEntries.get(m).getX() - xValue, + d2 = mEntries.get(m + 1).getX() - xValue, ad1 = Math.abs(d1), ad2 = Math.abs(d2); if (ad2 < ad1) { @@ -336,10 +358,10 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { } if (closest != -1) { - float closestXValue = mValues.get(closest).getX(); + float closestXValue = mEntries.get(closest).getX(); if (rounding == Rounding.UP) { // If rounding up, and found x-value is lower than specified x, and we can go upper... - if (closestXValue < xValue && closest < mValues.size() - 1) { + if (closestXValue < xValue && closest < mEntries.size() - 1) { ++closest; } } else if (rounding == Rounding.DOWN) { @@ -351,18 +373,18 @@ public int getEntryIndex(float xValue, float closestToY, Rounding rounding) { // Search by closest to y-value if (!Float.isNaN(closestToY)) { - while (closest > 0 && mValues.get(closest - 1).getX() == closestXValue) + while (closest > 0 && mEntries.get(closest - 1).getX() == closestXValue) closest -= 1; - float closestYValue = mValues.get(closest).getY(); + float closestYValue = mEntries.get(closest).getY(); int closestYIndex = closest; while (true) { closest += 1; - if (closest >= mValues.size()) + if (closest >= mEntries.size()) break; - final Entry value = mValues.get(closest); + final Entry value = mEntries.get(closest); if (value.getX() != closestXValue) break; @@ -386,22 +408,22 @@ public List getEntriesForXValue(float xValue) { List entries = new ArrayList(); int low = 0; - int high = mValues.size() - 1; + int high = mEntries.size() - 1; while (low <= high) { int m = (high + low) / 2; - T entry = mValues.get(m); + T entry = mEntries.get(m); // if we have a match if (xValue == entry.getX()) { - while (m > 0 && mValues.get(m - 1).getX() == xValue) + while (m > 0 && mEntries.get(m - 1).getX() == xValue) m--; - high = mValues.size(); + high = mEntries.size(); // loop over all "equal" entries for (; m < high; m++) { - entry = mValues.get(m); + entry = mEntries.get(m); if (entry.getX() == xValue) { entries.add(entry); } else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java index c1018d1fb4..10d1837ecd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineDataSet.java @@ -85,8 +85,8 @@ public LineDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } LineDataSet copied = new LineDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 8aea673dba..38a5d0b89b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -40,8 +40,8 @@ public PieDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList<>(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } PieDataSet copied = new PieDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java index 09c94b417d..8a9740b6b5 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/RadarDataSet.java @@ -102,8 +102,8 @@ public void setHighlightCircleStrokeWidth(float strokeWidth) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } RadarDataSet copied = new RadarDataSet(entries, getLabel()); copy(copied); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java index d234c751a0..85ed808160 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ScatterDataSet.java @@ -48,8 +48,8 @@ public ScatterDataSet(List yVals, String label) { @Override public DataSet copy() { List entries = new ArrayList(); - for (int i = 0; i < mValues.size(); i++) { - entries.add(mValues.get(i).copy()); + for (int i = 0; i < mEntries.size(); i++) { + entries.add(mEntries.get(i).copy()); } ScatterDataSet copied = new ScatterDataSet(entries, getLabel()); copy(copied); From 45240c3723387a0980074a5b4a72e1d2166192a4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 22 Jan 2020 16:01:42 +0200 Subject: [PATCH 1368/1390] Improved negative offset for horz bar chart https://github.com/danielgindi/Charts/pull/3854 --- .../HorizontalBarNegativeChartActivity.java | 288 ++++++++++++++++++ MPChartExample/src/main/AndroidManifest.xml | 1 + .../notimportant/MainActivity.java | 83 ++--- .../renderer/HorizontalBarChartRenderer.java | 3 +- 4 files changed, 335 insertions(+), 40 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java new file mode 100644 index 0000000000..c3de5fa68f --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java @@ -0,0 +1,288 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.annotation.SuppressLint; +import android.graphics.RectF; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.MPPointF; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; +import java.util.List; + +public class HorizontalBarNegativeChartActivity extends DemoBase implements OnSeekBarChangeListener, + OnChartValueSelectedListener { + + protected HorizontalBarChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_horizontalbarchart); + + tvX = findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + + mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + // mChart.setHighlightEnabled(false); + + mChart.setDrawBarShadow(false); + + mChart.setDrawValueAboveBar(true); + + mChart.getDescription().setEnabled(false); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + mChart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + // draw shadows for each bar that show the maximum value + // mChart.setDrawBarShadow(true); + + mChart.setDrawGridBackground(false); + + XAxis xl = mChart.getXAxis(); + xl.setPosition(XAxisPosition.BOTTOM); + xl.setTypeface(mTfLight); + xl.setDrawAxisLine(true); + xl.setDrawGridLines(false); + xl.setGranularity(10f); + + YAxis yl = mChart.getAxisLeft(); + yl.setTypeface(mTfLight); + yl.setDrawAxisLine(true); + yl.setDrawGridLines(true); + yl.setDrawZeroLine(true); // draw a zero line +// yl.setInverted(true); + + YAxis yr = mChart.getAxisRight(); + yr.setTypeface(mTfLight); + yr.setDrawAxisLine(true); + yr.setDrawGridLines(false); +// yr.setInverted(true); + + setData(12, 50); + mChart.setFitBars(true); + mChart.animateY(2500); + + // setting data + mSeekBarY.setProgress(50); + mSeekBarX.setProgress(12); + + mSeekBarY.setOnSeekBarChangeListener(this); + mSeekBarX.setOnSeekBarChangeListener(this); + + Legend l = mChart.getLegend(); + l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + l.setOrientation(Legend.LegendOrientation.HORIZONTAL); + l.setDrawInside(false); + l.setFormSize(8f); + l.setXEntrySpace(4f); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + IBarDataSet set = (BarDataSet) iSet; + set.setDrawValues(!set.isDrawValuesEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleIcons: { + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + IBarDataSet set = (BarDataSet) iSet; + set.setDrawIcons(!set.isDrawIconsEnabled()); + } + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); + mChart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleBarBorders: { + for (IBarDataSet set : mChart.getData().getDataSets()) + ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); + + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + mChart.setFitBars(true); + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + + } + + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range - range / 2); + yVals1.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (mChart.getData() != null && + mChart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); + set1.setValues(yVals1); + mChart.getData().notifyDataChanged(); + mChart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(yVals1, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(mTfLight); + data.setBarWidth(barWidth); + mChart.setData(data); + } + } + + protected RectF mOnValueSelectedRectF = new RectF(); + @SuppressLint("NewApi") + @Override + public void onValueSelected(Entry e, Highlight h) { + + if (e == null) + return; + + RectF bounds = mOnValueSelectedRectF; + mChart.getBarBounds((BarEntry) e, bounds); + + MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + .getAxisDependency()); + + Log.i("bounds", bounds.toString()); + Log.i("position", position.toString()); + + MPPointF.recycleInstance(position); + } + + @Override + public void onNothingSelected() { + }; +} diff --git a/MPChartExample/src/main/AndroidManifest.xml b/MPChartExample/src/main/AndroidManifest.xml index 28c55b89b2..99334e601a 100644 --- a/MPChartExample/src/main/AndroidManifest.xml +++ b/MPChartExample/src/main/AndroidManifest.xml @@ -24,6 +24,7 @@ + diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 67749e742f..88e5dc8d8b 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -26,6 +26,7 @@ import com.xxmassdeveloper.mpchartexample.FilledLineActivity; import com.xxmassdeveloper.mpchartexample.HalfPieChartActivity; import com.xxmassdeveloper.mpchartexample.HorizontalBarChartActivity; +import com.xxmassdeveloper.mpchartexample.HorizontalBarNegativeChartActivity; import com.xxmassdeveloper.mpchartexample.InvertedLineChartActivity; import com.xxmassdeveloper.mpchartexample.LineChartActivity1; import com.xxmassdeveloper.mpchartexample.LineChartActivity2; @@ -87,40 +88,41 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(13, new ContentItem("Horizontal", "Render bar chart horizontally.")); objects.add(14, new ContentItem("Stacked", "Stacked bar chart.")); objects.add(15, new ContentItem("Negative", "Positive and negative values with unique colors.")); - objects.add(16, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); - objects.add(17, new ContentItem("Sine", "Sine function in bar chart format.")); + objects.add(16, new ContentItem("Negative Horizontal", "demonstrates how to create a HorizontalBarChart with positive and negative values.")); + objects.add(17, new ContentItem("Stacked 2", "Stacked bar chart with negative values.")); + objects.add(18, new ContentItem("Sine", "Sine function in bar chart format.")); //// - objects.add(18, new ContentItem("Pie Charts")); + objects.add(19, new ContentItem("Pie Charts")); - objects.add(19, new ContentItem("Basic", "Simple pie chart.")); - objects.add(20, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); - objects.add(21, new ContentItem("Half Pie", "180° (half) pie chart.")); + objects.add(20, new ContentItem("Basic", "Simple pie chart.")); + objects.add(21, new ContentItem("Value Lines", "Stylish lines drawn outward from slices.")); + objects.add(22, new ContentItem("Half Pie", "180° (half) pie chart.")); //// - objects.add(22, new ContentItem("Other Charts")); + objects.add(23, new ContentItem("Other Charts")); - objects.add(23, new ContentItem("Combined Chart", "Bar and line chart together.")); - objects.add(24, new ContentItem("Scatter Plot", "Simple scatter plot.")); - objects.add(25, new ContentItem("Bubble Chart", "Simple bubble chart.")); - objects.add(26, new ContentItem("Candlestick", "Simple financial chart.")); - objects.add(27, new ContentItem("Radar Chart", "Simple web chart.")); + objects.add(24, new ContentItem("Combined Chart", "Bar and line chart together.")); + objects.add(25, new ContentItem("Scatter Plot", "Simple scatter plot.")); + objects.add(26, new ContentItem("Bubble Chart", "Simple bubble chart.")); + objects.add(27, new ContentItem("Candlestick", "Simple financial chart.")); + objects.add(28, new ContentItem("Radar Chart", "Simple web chart.")); //// - objects.add(28, new ContentItem("Scrolling Charts")); + objects.add(29, new ContentItem("Scrolling Charts")); - objects.add(29, new ContentItem("Multiple", "Various types of charts as fragments.")); - objects.add(30, new ContentItem("View Pager", "Swipe through different charts.")); - objects.add(31, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); - objects.add(32, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); + objects.add(30, new ContentItem("Multiple", "Various types of charts as fragments.")); + objects.add(31, new ContentItem("View Pager", "Swipe through different charts.")); + objects.add(32, new ContentItem("Tall Bar Chart", "Bars bigger than your screen!")); + objects.add(33, new ContentItem("Many Bar Charts", "More bars than your screen can handle!")); //// - objects.add(33, new ContentItem("Even More Line Charts")); + objects.add(34, new ContentItem("Even More Line Charts")); - objects.add(34, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); - objects.add(35, new ContentItem("Realtime", "Add data points in realtime.")); - objects.add(36, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); - //objects.add(37, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); + objects.add(35, new ContentItem("Dynamic", "Build a line chart by adding points and sets.")); + objects.add(36, new ContentItem("Realtime", "Add data points in realtime.")); + objects.add(37, new ContentItem("Hourly", "Uses the current time to add a data point for each hour.")); + //objects.add(38, new ContentItem("Realm.io Examples", "See more examples that use Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -179,57 +181,60 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, BarChartPositiveNegative.class); break; case 16: - i = new Intent(this, StackedBarActivityNegative.class); + i = new Intent(this, HorizontalBarNegativeChartActivity.class); break; case 17: + i = new Intent(this, StackedBarActivityNegative.class); + break; + case 18: i = new Intent(this, BarChartActivitySinus.class); break; - case 19: + case 20: i = new Intent(this, PieChartActivity.class); break; - case 20: + case 21: i = new Intent(this, PiePolylineChartActivity.class); break; - case 21: + case 22: i = new Intent(this, HalfPieChartActivity.class); break; - case 23: + case 24: i = new Intent(this, CombinedChartActivity.class); break; - case 24: + case 25: i = new Intent(this, ScatterChartActivity.class); break; - case 25: + case 26: i = new Intent(this, BubbleChartActivity.class); break; - case 26: + case 27: i = new Intent(this, CandleStickChartActivity.class); break; - case 27: + case 28: i = new Intent(this, RadarChartActivity.class); break; - case 29: + case 30: i = new Intent(this, ListViewMultiChartActivity.class); break; - case 30: + case 31: i = new Intent(this, SimpleChartDemo.class); break; - case 31: + case 32: i = new Intent(this, ScrollViewActivity.class); break; - case 32: + case 33: i = new Intent(this, ListViewBarChartActivity.class); break; - case 34: + case 35: i = new Intent(this, DynamicalAddingActivity.class); break; - case 35: + case 36: i = new Intent(this, RealtimeLineChartActivity.class); break; - case 36: + case 37: i = new Intent(this, LineChartTime.class); break; - /*case 37: + /*case 38: i = new Intent(this, RealmMainActivity.class); break;*/ } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 7607abdd92..b692a1f90b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -200,7 +200,8 @@ public void drawValues(Canvas c) { // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); - negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); + negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus) + - (buffer.buffer[j + 2] - buffer.buffer[j]); if (isInverted) { posOffset = -posOffset - valueTextWidth; From 34fefd28e1f50d8d0406e0aac4cb3909c94eb193 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Jan 2020 10:18:28 +0200 Subject: [PATCH 1369/1390] maxHeight didn't account for the last label https://github.com/danielgindi/Charts/pull/3900 --- .../java/com/github/mikephil/charting/components/Legend.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java index b785098881..708129259b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/Legend.java @@ -703,8 +703,7 @@ else if (wasStacked) { width += Utils.calcTextWidth(labelpaint, label); - if (i < entryCount - 1) - maxHeight += labelLineHeight + yEntrySpace; + maxHeight += labelLineHeight + yEntrySpace; } else { wasStacked = true; width += formSize; From 0668d30a6bcf5e3c0b1af945bd25128c36d63d31 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Jan 2020 10:54:28 +0200 Subject: [PATCH 1370/1390] Fixed a bug where a pie slice without highlight enabled is hidden https://github.com/danielgindi/Charts/pull/3969 --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index 82654d4816..f427ffe5d3 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -258,7 +258,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { } // Don't draw if it's highlighted, unless the chart uses rounded slices - if (mChart.needsHighlight(j) && !drawRoundedSlices) { + if (dataSet.isHighlightEnabled() && mChart.needsHighlight(j) && !drawRoundedSlices) { angle += sliceAngle * phaseX; continue; } @@ -830,8 +830,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; IPieDataSet set = mChart.getData() - .getDataSetByIndex(indices[i] - .getDataSetIndex()); + .getDataSetByIndex(indices[i].getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) continue; From 1de836ac650e45ac1dd7e905368016c8fdd6aeef Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Jan 2020 11:19:07 +0200 Subject: [PATCH 1371/1390] Remove unexpected dash line during linear animation https://github.com/danielgindi/Charts/pull/4094 --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index ead9d6d701..2b3c524133 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -326,7 +326,9 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { if (mLineBuffer.length <= pointsPerEntryPair * 2) mLineBuffer = new float[pointsPerEntryPair * 4]; - for (int j = mXBounds.min; j <= mXBounds.range + mXBounds.min; j++) { + int max = mXBounds.min + mXBounds.range; + + for (int j = mXBounds.min; j < max; j++) { Entry e = dataSet.getEntryForIndex(j); if (e == null) continue; From 5e4a32eb414b074a61b6655c55fa713105eb0195 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Jan 2020 12:09:06 +0200 Subject: [PATCH 1372/1390] Corrected check for line in vertical bounds https://github.com/danielgindi/Charts/pull/4100 --- .../charting/renderer/LineChartRenderer.java | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 2b3c524133..849bc4a7aa 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -323,8 +323,10 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // more than 1 color if (dataSet.getColors().size() > 1) { - if (mLineBuffer.length <= pointsPerEntryPair * 2) - mLineBuffer = new float[pointsPerEntryPair * 4]; + int numberOfFloats = pointsPerEntryPair * 2; + + if (mLineBuffer.length <= numberOfFloats) + mLineBuffer = new float[numberOfFloats * 2]; int max = mXBounds.min + mXBounds.range; @@ -359,16 +361,26 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { mLineBuffer[3] = mLineBuffer[1]; } + // Determine the start and end coordinates of the line, and make sure they differ. + float firstCoordinateX = mLineBuffer[0]; + float firstCoordinateY = mLineBuffer[1]; + float lastCoordinateX = mLineBuffer[numberOfFloats - 2]; + float lastCoordinateY = mLineBuffer[numberOfFloats - 1]; + + if (firstCoordinateX == lastCoordinateX && + firstCoordinateY == lastCoordinateY) + continue; + trans.pointValuesToPixel(mLineBuffer); - if (!mViewPortHandler.isInBoundsRight(mLineBuffer[0])) + if (!mViewPortHandler.isInBoundsRight(firstCoordinateX)) break; // make sure the lines don't do shitty things outside // bounds - if (!mViewPortHandler.isInBoundsLeft(mLineBuffer[2]) - || (!mViewPortHandler.isInBoundsTop(mLineBuffer[1]) && !mViewPortHandler - .isInBoundsBottom(mLineBuffer[3]))) + if (!mViewPortHandler.isInBoundsLeft(lastCoordinateX) || + !mViewPortHandler.isInBoundsTop(lastCoordinateY) || + !mViewPortHandler.isInBoundsBottom(firstCoordinateY)) continue; // get the color that is set for this line-segment From f05337768d87bdd57eaed378fd2fe1a6346b0300 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 23 Jan 2020 15:45:57 +0200 Subject: [PATCH 1373/1390] Finalized vertical line collision check --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index 849bc4a7aa..a00860b5a6 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -379,8 +379,8 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { // make sure the lines don't do shitty things outside // bounds if (!mViewPortHandler.isInBoundsLeft(lastCoordinateX) || - !mViewPortHandler.isInBoundsTop(lastCoordinateY) || - !mViewPortHandler.isInBoundsBottom(firstCoordinateY)) + !mViewPortHandler.isInBoundsTop(Math.max(firstCoordinateY, lastCoordinateY)) || + !mViewPortHandler.isInBoundsBottom(Math.min(firstCoordinateY, lastCoordinateY))) continue; // get the color that is set for this line-segment From 351e341ee7498e956c41d307dc2b288223a31821 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 24 Jan 2020 11:42:03 +0200 Subject: [PATCH 1374/1390] Fixed merge residue --- .../HorizontalBarNegativeChartActivity.java | 232 +++++++++--------- .../mikephil/charting/data/PieDataSet.java | 2 +- .../interfaces/datasets/IPieDataSet.java | 2 +- 3 files changed, 120 insertions(+), 116 deletions(-) rename MPChartExample/src/{ => main/java}/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java (54%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java similarity index 54% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java rename to MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java index c3de5fa68f..86d578cc43 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/HorizontalBarNegativeChartActivity.java @@ -1,8 +1,12 @@ package com.xxmassdeveloper.mpchartexample; +import android.Manifest; import android.annotation.SuppressLint; +import android.content.Intent; +import android.content.pm.PackageManager; import android.graphics.RectF; +import android.net.Uri; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -13,6 +17,8 @@ import android.widget.TextView; import android.widget.Toast; +import androidx.core.content.ContextCompat; + import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; @@ -34,8 +40,8 @@ public class HorizontalBarNegativeChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { - protected HorizontalBarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; + private HorizontalBarChart chart; + private SeekBar seekBarX, seekBarY; private TextView tvX, tvY; @Override @@ -45,66 +51,66 @@ protected void onCreate(Bundle savedInstanceState) { WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_horizontalbarchart); + setTitle("HorizontalBarChartActivity"); + tvX = findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); + tvY = findViewById(R.id.tvYMax); - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + seekBarX = findViewById(R.id.seekBar1); + seekBarY = findViewById(R.id.seekBar2); - mChart = (HorizontalBarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - // mChart.setHighlightEnabled(false); + seekBarY.setOnSeekBarChangeListener(this); + seekBarX.setOnSeekBarChangeListener(this); - mChart.setDrawBarShadow(false); + chart = findViewById(R.id.chart1); + chart.setOnChartValueSelectedListener(this); + // chart.setHighlightEnabled(false); - mChart.setDrawValueAboveBar(true); + chart.setDrawBarShadow(false); - mChart.getDescription().setEnabled(false); + chart.setDrawValueAboveBar(true); + + chart.getDescription().setEnabled(false); // if more than 60 entries are displayed in the chart, no values will be // drawn - mChart.setMaxVisibleValueCount(60); + chart.setMaxVisibleValueCount(60); // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); + chart.setPinchZoom(false); // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); + // chart.setDrawBarShadow(true); - mChart.setDrawGridBackground(false); + chart.setDrawGridBackground(false); - XAxis xl = mChart.getXAxis(); + XAxis xl = chart.getXAxis(); xl.setPosition(XAxisPosition.BOTTOM); - xl.setTypeface(mTfLight); + xl.setTypeface(tfLight); xl.setDrawAxisLine(true); xl.setDrawGridLines(false); xl.setGranularity(10f); - YAxis yl = mChart.getAxisLeft(); - yl.setTypeface(mTfLight); + YAxis yl = chart.getAxisLeft(); + yl.setTypeface(tfLight); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); - yl.setDrawZeroLine(true); // draw a zero line // yl.setInverted(true); - YAxis yr = mChart.getAxisRight(); - yr.setTypeface(mTfLight); + YAxis yr = chart.getAxisRight(); + yr.setTypeface(tfLight); yr.setDrawAxisLine(true); yr.setDrawGridLines(false); // yr.setInverted(true); - setData(12, 50); - mChart.setFitBars(true); - mChart.animateY(2500); + chart.setFitBars(true); + chart.animateY(2500); // setting data - mSeekBarY.setProgress(50); - mSeekBarX.setProgress(12); - - mSeekBarY.setOnSeekBarChangeListener(this); - mSeekBarX.setOnSeekBarChangeListener(this); + seekBarY.setProgress(50); + seekBarX.setProgress(12); - Legend l = mChart.getLegend(); + Legend l = chart.getLegend(); l.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); l.setOrientation(Legend.LegendOrientation.HORIZONTAL); @@ -113,6 +119,42 @@ protected void onCreate(Bundle savedInstanceState) { l.setXEntrySpace(4f); } + private void setData(int count, float range) { + + float barWidth = 9f; + float spaceForBar = 10f; + ArrayList values = new ArrayList<>(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * range - range / 2); + values.add(new BarEntry(i * spaceForBar, val, + getResources().getDrawable(R.drawable.star))); + } + + BarDataSet set1; + + if (chart.getData() != null && + chart.getData().getDataSetCount() > 0) { + set1 = (BarDataSet) chart.getData().getDataSetByIndex(0); + set1.setValues(values); + chart.getData().notifyDataChanged(); + chart.notifyDataSetChanged(); + } else { + set1 = new BarDataSet(values, "DataSet 1"); + + set1.setDrawIcons(false); + + ArrayList dataSets = new ArrayList<>(); + dataSets.add(set1); + + BarData data = new BarData(dataSets); + data.setValueTextSize(10f); + data.setValueTypeface(tfLight); + data.setBarWidth(barWidth); + chart.setData(data); + } + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.bar, menu); @@ -123,80 +165,80 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { + case R.id.viewGithub: { + Intent i = new Intent(Intent.ACTION_VIEW); + i.setData(Uri.parse("https://github.com/PhilJay/MPAndroidChart/blob/master/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java")); + startActivity(i); + break; + } case R.id.actionToggleValues: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawValues(!set.isDrawValuesEnabled()); + iSet.setDrawValues(!iSet.isDrawValuesEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleIcons: { - List sets = mChart.getData() + List sets = chart.getData() .getDataSets(); for (IBarDataSet iSet : sets) { - - IBarDataSet set = (BarDataSet) iSet; - set.setDrawIcons(!set.isDrawIconsEnabled()); + iSet.setDrawIcons(!iSet.isDrawIconsEnabled()); } - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { - mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); - mChart.invalidate(); + if(chart.getData() != null) { + chart.getData().setHighlightEnabled(!chart.getData().isHighlightEnabled()); + chart.invalidate(); } break; } case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); + if (chart.isPinchZoomEnabled()) + chart.setPinchZoom(false); else - mChart.setPinchZoom(true); + chart.setPinchZoom(true); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); + chart.setAutoScaleMinMaxEnabled(!chart.isAutoScaleMinMaxEnabled()); + chart.notifyDataSetChanged(); break; } case R.id.actionToggleBarBorders: { - for (IBarDataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : chart.getData().getDataSets()) ((BarDataSet)set).setBarBorderWidth(set.getBarBorderWidth() == 1.f ? 0.f : 1.f); - mChart.invalidate(); + chart.invalidate(); break; } case R.id.animateX: { - mChart.animateX(3000); + chart.animateX(2000); break; } case R.id.animateY: { - mChart.animateY(3000); + chart.animateY(2000); break; } case R.id.animateXY: { - - mChart.animateXY(3000, 3000); + chart.animateXY(2000, 2000); break; } case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); + if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { + saveToGallery(); + } else { + requestStoragePermission(chart); + } break; } } @@ -206,64 +248,27 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); + tvX.setText(String.valueOf(seekBarX.getProgress())); + tvY.setText(String.valueOf(seekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); - mChart.setFitBars(true); - mChart.invalidate(); + setData(seekBarX.getProgress(), seekBarY.getProgress()); + chart.setFitBars(true); + chart.invalidate(); } @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - + protected void saveToGallery() { + saveToGallery(chart, "HorizontalBarChartActivity"); } @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - private void setData(int count, float range) { - - float barWidth = 9f; - float spaceForBar = 10f; - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < count; i++) { - float val = (float) (Math.random() * range - range / 2); - yVals1.add(new BarEntry(i * spaceForBar, val, - getResources().getDrawable(R.drawable.star))); - } - - BarDataSet set1; - - if (mChart.getData() != null && - mChart.getData().getDataSetCount() > 0) { - set1 = (BarDataSet)mChart.getData().getDataSetByIndex(0); - set1.setValues(yVals1); - mChart.getData().notifyDataChanged(); - mChart.notifyDataSetChanged(); - } else { - set1 = new BarDataSet(yVals1, "DataSet 1"); - - set1.setDrawIcons(false); + public void onStartTrackingTouch(SeekBar seekBar) {} - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); + @Override + public void onStopTrackingTouch(SeekBar seekBar) {} - BarData data = new BarData(dataSets); - data.setValueTextSize(10f); - data.setValueTypeface(mTfLight); - data.setBarWidth(barWidth); - mChart.setData(data); - } - } + private final RectF mOnValueSelectedRectF = new RectF(); - protected RectF mOnValueSelectedRectF = new RectF(); - @SuppressLint("NewApi") @Override public void onValueSelected(Entry e, Highlight h) { @@ -271,9 +276,9 @@ public void onValueSelected(Entry e, Highlight h) { return; RectF bounds = mOnValueSelectedRectF; - mChart.getBarBounds((BarEntry) e, bounds); + chart.getBarBounds((BarEntry) e, bounds); - MPPointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(h.getDataSetIndex()) + MPPointF position = chart.getPosition(e, chart.getData().getDataSetByIndex(h.getDataSetIndex()) .getAxisDependency()); Log.i("bounds", bounds.toString()); @@ -283,6 +288,5 @@ public void onValueSelected(Entry e, Highlight h) { } @Override - public void onNothingSelected() { - }; + public void onNothingSelected() {} } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java index 38a5d0b89b..c83b24547b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/PieDataSet.java @@ -3,7 +3,7 @@ import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index 3720394f25..b228fca0e4 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,6 +1,6 @@ package com.github.mikephil.charting.interfaces.datasets; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; From c0e7f56b5d816c08fd6e238c9e08c6dc1fd6142c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 24 Jan 2020 11:35:47 +0200 Subject: [PATCH 1375/1390] Implement a more generic Fill class instead of GradientColor Support HorizontalBarChart too. --- .../mpchartexample/BarChartActivity.java | 22 +- .../mikephil/charting/data/BarDataSet.java | 64 ++++ .../mikephil/charting/data/BaseDataSet.java | 41 --- .../charting/data/LineRadarDataSet.java | 1 + .../interfaces/datasets/IBarDataSet.java | 7 + .../interfaces/datasets/IDataSet.java | 23 -- .../charting/model/GradientColor.java | 73 +++- .../charting/renderer/BarChartRenderer.java | 47 +-- .../renderer/HorizontalBarChartRenderer.java | 21 +- .../github/mikephil/charting/utils/Fill.java | 342 ++++++++++++++++++ 10 files changed, 514 insertions(+), 127 deletions(-) create mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 4af0441ddb..89ec00a892 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -32,7 +32,7 @@ import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.model.GradientColor; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; @@ -164,12 +164,6 @@ private void setData(int count, float range) { set1.setDrawIcons(false); -// set1.setColors(ColorTemplate.MATERIAL_COLORS); - - /*int startColor = ContextCompat.getColor(this, android.R.color.holo_blue_dark); - int endColor = ContextCompat.getColor(this, android.R.color.holo_blue_bright); - set1.setGradientColor(startColor, endColor);*/ - int startColor1 = ContextCompat.getColor(this, android.R.color.holo_orange_light); int startColor2 = ContextCompat.getColor(this, android.R.color.holo_blue_light); int startColor3 = ContextCompat.getColor(this, android.R.color.holo_orange_light); @@ -181,14 +175,14 @@ private void setData(int count, float range) { int endColor4 = ContextCompat.getColor(this, android.R.color.holo_red_dark); int endColor5 = ContextCompat.getColor(this, android.R.color.holo_orange_dark); - List gradientColors = new ArrayList<>(); - gradientColors.add(new GradientColor(startColor1, endColor1)); - gradientColors.add(new GradientColor(startColor2, endColor2)); - gradientColors.add(new GradientColor(startColor3, endColor3)); - gradientColors.add(new GradientColor(startColor4, endColor4)); - gradientColors.add(new GradientColor(startColor5, endColor5)); + List gradientFills = new ArrayList<>(); + gradientFills.add(new Fill(startColor1, endColor1)); + gradientFills.add(new Fill(startColor2, endColor2)); + gradientFills.add(new Fill(startColor3, endColor3)); + gradientFills.add(new Fill(startColor4, endColor4)); + gradientFills.add(new Fill(startColor5, endColor5)); - set1.setGradientColors(gradientColors); + set1.setFills(gradientFills); ArrayList dataSets = new ArrayList<>(); dataSets.add(set1); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java index 7b7ee5f916..e65638805b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BarDataSet.java @@ -4,6 +4,7 @@ import android.graphics.Color; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import java.util.ArrayList; import java.util.List; @@ -40,6 +41,8 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl */ private String[] mStackLabels = new String[]{}; + protected List mFills = null; + public BarDataSet(List yVals, String label) { super(yVals, label); @@ -69,6 +72,67 @@ protected void copy(BarDataSet barDataSet) { barDataSet.mHighLightAlpha = mHighLightAlpha; } + @Override + public List getFills() { + return mFills; + } + + @Override + public Fill getFill(int index) { + return mFills.get(index % mFills.size()); + } + + /** + * This method is deprecated. + * Use getFills() instead. + */ + @Deprecated + public List getGradients() { + return mFills; + } + + /** + * This method is deprecated. + * Use getFill(...) instead. + * + * @param index + */ + @Deprecated + public Fill getGradient(int index) { + return getFill(index); + } + + /** + * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. + * + * @param startColor + * @param endColor + */ + public void setGradientColor(int startColor, int endColor) { + mFills.clear(); + mFills.add(new Fill(startColor, endColor)); + } + + /** + * This method is deprecated. + * Use setFills(...) instead. + * + * @param gradientColors + */ + @Deprecated + public void setGradientColors(List gradientColors) { + this.mFills = gradientColors; + } + + /** + * Sets the fills for the bars in this dataset. + * + * @param fills + */ + public void setFills(List fills) { + this.mFills = fills; + } + /** * Calculates the total number of entries this DataSet represents, including * stacks. All values belonging to a stack are calculated separately. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index 8ca3e68d42..a4279629ad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; -import com.github.mikephil.charting.model.GradientColor; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; @@ -29,10 +28,6 @@ public abstract class BaseDataSet implements IDataSet { */ protected List mColors = null; - protected GradientColor mGradientColor = null; - - protected List mGradientColors = null; - /** * List representing all colors that are used for drawing the actual values for this DataSet */ @@ -146,21 +141,6 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } - @Override - public GradientColor getGradientColor() { - return mGradientColor; - } - - @Override - public List getGradientColors() { - return mGradientColors; - } - - @Override - public GradientColor getGradientColor(int index) { - return mGradientColors.get(index % mGradientColors.size()); - } - /** * ###### ###### COLOR SETTING RELATED METHODS ##### ###### */ @@ -236,25 +216,6 @@ public void setColor(int color) { mColors.add(color); } - /** - * Sets the start and end color for gradient color, ONLY color that should be used for this DataSet. - * - * @param startColor - * @param endColor - */ - public void setGradientColor(int startColor, int endColor) { - mGradientColor = new GradientColor(startColor, endColor); - } - - /** - * Sets the start and end color for gradient colors, ONLY color that should be used for this DataSet. - * - * @param gradientColors - */ - public void setGradientColors(List gradientColors) { - this.mGradientColors = gradientColors; - } - /** * Sets a color with a specific alpha value. * @@ -534,8 +495,6 @@ protected void copy(BaseDataSet baseDataSet) { baseDataSet.mFormLineDashEffect = mFormLineDashEffect; baseDataSet.mFormLineWidth = mFormLineWidth; baseDataSet.mFormSize = mFormSize; - baseDataSet.mGradientColor = mGradientColor; - baseDataSet.mGradientColors = mGradientColors; baseDataSet.mHighlightEnabled = mHighlightEnabled; baseDataSet.mIconsOffset = mIconsOffset; baseDataSet.mValueColors = mValueColors; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java index 688585cbdd..b4347e4647 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -17,6 +17,7 @@ */ public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet implements ILineRadarDataSet { + // TODO: Move to using `Fill` class /** * the color that is used for filling the line surface */ diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index fbdfd79531..5e82a48420 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -1,12 +1,19 @@ package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.Fill; + +import java.util.List; /** * Created by philipp on 21/10/15. */ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { + List getFills(); + + Fill getFill(int index); + /** * Returns true if this DataSet is stacked (stacksize > 1) or not. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 73a54470c8..ccd4cb4f70 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -9,7 +9,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.MPPointF; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -285,28 +284,6 @@ public interface IDataSet { */ int getColor(); - /** - * Returns the Gradient color model - * - * @return - */ - GradientColor getGradientColor(); - - /** - * Returns the Gradient colors - * - * @return - */ - List getGradientColors(); - - /** - * Returns the Gradient colors - * - * @param index - * @return - */ - GradientColor getGradientColor(int index); - /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java index 1162c01198..b5c8715a08 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/model/GradientColor.java @@ -1,28 +1,69 @@ package com.github.mikephil.charting.model; -public class GradientColor { +import com.github.mikephil.charting.utils.Fill; - private int startColor; - private int endColor; - - public GradientColor(int startColor, int endColor) { - this.startColor = startColor; - this.endColor = endColor; +/** + * Deprecated. Use `Fill` + */ +@Deprecated +public class GradientColor extends Fill +{ + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getStartColor() + { + return getGradientColors()[0]; } - public int getStartColor() { - return startColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setStartColor(int startColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + startColor, + getGradientColors() != null && getGradientColors().length > 1 + ? getGradientColors()[1] + : 0 + }); + } else + { + getGradientColors()[0] = startColor; + } } - public void setStartColor(int startColor) { - this.startColor = startColor; + /** + * Deprecated. Use `Fill.getGradientColors()` + */ + @Deprecated + public int getEndColor() + { + return getGradientColors()[1]; } - public int getEndColor() { - return endColor; + /** + * Deprecated. Use `Fill.setGradientColors(...)` + */ + @Deprecated + public void setEndColor(int endColor) + { + if (getGradientColors() == null || getGradientColors().length != 2) + { + setGradientColors(new int[]{ + getGradientColors() != null && getGradientColors().length > 0 + ? getGradientColors()[0] + : 0, + endColor + }); + } else + { + getGradientColors()[1] = endColor; + } } - public void setEndColor(int endColor) { - this.endColor = endColor; - } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index b5de65b02e..d6ce3898e1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -15,12 +15,11 @@ import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import android.graphics.LinearGradient; -import com.github.mikephil.charting.model.GradientColor; import java.util.List; @@ -145,13 +144,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills().size() > 0; final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) continue; @@ -162,38 +163,24 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { if (!isSingleColor) { // Set the color for the currently drawn value. If the index // is out of bounds, reuse colors. - mRenderPaint.setColor(dataSet.getColor(j / 4)); + mRenderPaint.setColor(dataSet.getColor(pos)); } - if (dataSet.getGradientColor() != null) { - GradientColor gradientColor = dataSet.getGradientColor(); - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - gradientColor.getStartColor(), - gradientColor.getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.DOWN : Fill.Direction.UP); } - - if (dataSet.getGradientColors() != null) { - mRenderPaint.setShader( - new LinearGradient( - buffer.buffer[j], - buffer.buffer[j + 3], - buffer.buffer[j], - buffer.buffer[j + 1], - dataSet.getGradientColor(j / 4).getStartColor(), - dataSet.getGradientColor(j / 4).getEndColor(), - android.graphics.Shader.TileMode.MIRROR)); + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); } - - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); - if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mBarBorderPaint); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index b692a1f90b..f9431702ad 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -15,6 +15,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -111,13 +112,15 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); + final boolean isCustomFill = dataSet.getFills().size() > 0; final boolean isSingleColor = dataSet.getColors().size() == 1; + final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); if (isSingleColor) { mRenderPaint.setColor(dataSet.getColor()); } - for (int j = 0; j < buffer.size(); j += 4) { + for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) { if (!mViewPortHandler.isInBoundsTop(buffer.buffer[j + 3])) break; @@ -131,8 +134,20 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { mRenderPaint.setColor(dataSet.getColor(j / 4)); } - c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], - buffer.buffer[j + 3], mRenderPaint); + if (isCustomFill) { + dataSet.getFill(pos) + .fillRect( + c, mRenderPaint, + buffer.buffer[j], + buffer.buffer[j + 1], + buffer.buffer[j + 2], + buffer.buffer[j + 3], + isInverted ? Fill.Direction.LEFT : Fill.Direction.RIGHT); + } + else { + c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], + buffer.buffer[j + 3], mRenderPaint); + } if (drawBorder) { c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java new file mode 100644 index 0000000000..d12e1fb8d7 --- /dev/null +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Fill.java @@ -0,0 +1,342 @@ +package com.github.mikephil.charting.utils; + +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class Fill +{ + public enum Type + { + EMPTY, COLOR, LINEAR_GRADIENT, DRAWABLE + } + + public enum Direction + { + DOWN, UP, RIGHT, LEFT + } + + /** + * the type of fill + */ + private Type mType = Type.EMPTY; + + /** + * the color that is used for filling + */ + @Nullable + private Integer mColor = null; + + private Integer mFinalColor = null; + + /** + * the drawable to be used for filling + */ + @Nullable + protected Drawable mDrawable; + + @Nullable + private int[] mGradientColors; + + @Nullable + private float[] mGradientPositions; + + /** + * transparency used for filling + */ + private int mAlpha = 255; + + public Fill() + { + } + + public Fill(int color) + { + this.mType = Type.COLOR; + this.mColor = color; + calculateFinalColor(); + } + + public Fill(int startColor, int endColor) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = new int[]{startColor, endColor}; + } + + public Fill(@NonNull int[] gradientColors) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + } + + public Fill(@NonNull int[] gradientColors, @NonNull float[] gradientPositions) + { + this.mType = Type.LINEAR_GRADIENT; + this.mGradientColors = gradientColors; + this.mGradientPositions = gradientPositions; + } + + public Fill(@NonNull Drawable drawable) + { + this.mType = Type.DRAWABLE; + this.mDrawable = drawable; + } + + public Type getType() + { + return mType; + } + + public void setType(Type type) + { + this.mType = type; + } + + @Nullable + public Integer getColor() + { + return mColor; + } + + public void setColor(int color) + { + this.mColor = color; + calculateFinalColor(); + } + + public int[] getGradientColors() + { + return mGradientColors; + } + + public void setGradientColors(int[] colors) + { + this.mGradientColors = colors; + } + + public float[] getGradientPositions() + { + return mGradientPositions; + } + + public void setGradientPositions(float[] positions) + { + this.mGradientPositions = positions; + } + + public void setGradientColors(int startColor, int endColor) + { + this.mGradientColors = new int[]{startColor, endColor}; + } + + public int getAlpha() + { + return mAlpha; + } + + public void setAlpha(int alpha) + { + this.mAlpha = alpha; + calculateFinalColor(); + } + + private void calculateFinalColor() + { + if (mColor == null) + { + mFinalColor = null; + } else + { + int alpha = (int) Math.floor(((mColor >> 24) / 255.0) * (mAlpha / 255.0) * 255.0); + mFinalColor = (alpha << 24) | (mColor & 0xffffff); + } + } + + public void fillRect(Canvas c, Paint paint, + float left, float top, float right, float bottom, + Direction gradientDirection) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (isClipPathSupported()) + { + int save = c.save(); + + c.clipRect(left, top, right, bottom); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawRect(left, top, right, bottom, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + (int) (gradientDirection == Direction.RIGHT + ? right + : gradientDirection == Direction.LEFT + ? left + : left), + (int) (gradientDirection == Direction.UP + ? bottom + : gradientDirection == Direction.DOWN + ? top + : top), + (int) (gradientDirection == Direction.RIGHT + ? left + : gradientDirection == Direction.LEFT + ? right + : left), + (int) (gradientDirection == Direction.UP + ? top + : gradientDirection == Direction.DOWN + ? bottom + : top), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawRect(left, top, right, bottom, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom); + mDrawable.draw(c); + } + break; + } + } + + public void fillPath(Canvas c, Path path, Paint paint, + @Nullable RectF clipRect) + { + switch (mType) + { + case EMPTY: + return; + + case COLOR: + { + if (mFinalColor == null) return; + + if (clipRect != null && isClipPathSupported()) + { + int save = c.save(); + + c.clipPath(path); + c.drawColor(mFinalColor); + + c.restoreToCount(save); + } + else + { + // save + Paint.Style previous = paint.getStyle(); + int previousColor = paint.getColor(); + + // set + paint.setStyle(Paint.Style.FILL); + paint.setColor(mFinalColor); + + c.drawPath(path, paint); + + // restore + paint.setColor(previousColor); + paint.setStyle(previous); + } + } + break; + + case LINEAR_GRADIENT: + { + if (mGradientColors == null) return; + + LinearGradient gradient = new LinearGradient( + 0, + 0, + c.getWidth(), + c.getHeight(), + mGradientColors, + mGradientPositions, + android.graphics.Shader.TileMode.MIRROR); + + paint.setShader(gradient); + + c.drawPath(path, paint); + } + break; + + case DRAWABLE: + { + if (mDrawable == null) return; + + ensureClipPathSupported(); + + int save = c.save(); + c.clipPath(path); + + mDrawable.setBounds( + clipRect == null ? 0 : (int) clipRect.left, + clipRect == null ? 0 : (int) clipRect.top, + clipRect == null ? c.getWidth() : (int) clipRect.right, + clipRect == null ? c.getHeight() : (int) clipRect.bottom); + mDrawable.draw(c); + + c.restoreToCount(save); + } + break; + } + } + + private boolean isClipPathSupported() + { + return Utils.getSDKInt() >= 18; + } + + private void ensureClipPathSupported() + { + if (Utils.getSDKInt() < 18) + { + throw new RuntimeException("Fill-drawables not (yet) supported below API level 18, " + + "this code was run on API level " + Utils.getSDKInt() + "."); + } + } +} From 55df9ad63662f36bf8765d9b4f442bc75084ee6d Mon Sep 17 00:00:00 2001 From: Nathan Fiscaletti Date: Sat, 1 Feb 2020 14:02:27 -0600 Subject: [PATCH 1376/1390] Update LICENSE The LICENSE file was not properly filled out. It was missing some templates that were supposed to be filled in at the end of the license. Additionally, the entire Apache 2.0 license is not required on a project that makes use of it. Only this disclaimer is required. See http://www.apache.org/licenses/LICENSE-2.0#apply under the "How to apply the Apache License to your work" for more information. --- LICENSE | 190 +------------------------------------------------------- 1 file changed, 1 insertion(+), 189 deletions(-) diff --git a/LICENSE b/LICENSE index 8dada3edaf..ba648a557d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,192 +1,4 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} + Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From cef967fd71ff18b0908ffa21c795faefde3ff120 Mon Sep 17 00:00:00 2001 From: Anirut Teerabut Date: Fri, 7 Feb 2020 17:53:40 +0700 Subject: [PATCH 1377/1390] fix NPE when use solid color with barchart --- .../github/mikephil/charting/renderer/BarChartRenderer.java | 6 +++++- .../charting/renderer/HorizontalBarChartRenderer.java | 5 ++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index d6ce3898e1..99a1249932 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -144,7 +144,11 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - final boolean isCustomFill = dataSet.getFills().size() > 0; + boolean isCustomFill = false; + if(dataSet.getFills() != null) { + isCustomFill = !dataSet.getFills().isEmpty(); + } + final boolean isSingleColor = dataSet.getColors().size() == 1; final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index f9431702ad..6ca6ff0e8d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -112,7 +112,10 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - final boolean isCustomFill = dataSet.getFills().size() > 0; + boolean isCustomFill = false; + if(dataSet.getFills() != null) { + isCustomFill = !dataSet.getFills().isEmpty(); + } final boolean isSingleColor = dataSet.getColors().size() == 1; final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); From 4b67673da908378fda8fd7449a5a19c30d45c8d2 Mon Sep 17 00:00:00 2001 From: Anirut Teerabut Date: Fri, 7 Feb 2020 22:03:20 +0700 Subject: [PATCH 1378/1390] Update BarChartRenderer.java --- .../github/mikephil/charting/renderer/BarChartRenderer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 99a1249932..ca8b8c1504 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -144,10 +144,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - boolean isCustomFill = false; - if(dataSet.getFills() != null) { - isCustomFill = !dataSet.getFills().isEmpty(); - } + boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); final boolean isSingleColor = dataSet.getColors().size() == 1; final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); From 33240f9225bea0b23d8d82a786867f8446fd5dfd Mon Sep 17 00:00:00 2001 From: Anirut Teerabut Date: Fri, 7 Feb 2020 22:09:07 +0700 Subject: [PATCH 1379/1390] Update HorizontalBarChartRenderer.java --- .../charting/renderer/HorizontalBarChartRenderer.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 6ca6ff0e8d..b42ef1284a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -112,10 +112,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - boolean isCustomFill = false; - if(dataSet.getFills() != null) { - isCustomFill = !dataSet.getFills().isEmpty(); - } + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); final boolean isSingleColor = dataSet.getColors().size() == 1; final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); From 90e523042cfae25c8271b60f2cf68a947c46e018 Mon Sep 17 00:00:00 2001 From: Anirut Teerabut Date: Fri, 7 Feb 2020 22:09:57 +0700 Subject: [PATCH 1380/1390] Update BarChartRenderer.java --- .../github/mikephil/charting/renderer/BarChartRenderer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index ca8b8c1504..18975557cd 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -144,8 +144,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { trans.pointValuesToPixel(buffer.buffer); - boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); - + final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty(); final boolean isSingleColor = dataSet.getColors().size() == 1; final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); From 05f658d4bd32a95a89cbd5a6de1fc40b1fba08c2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 12 Feb 2020 11:14:20 +0100 Subject: [PATCH 1381/1390] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c4325f61e5..881f66b6bd 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,9 @@ 1. [License](#licence) 1. [Creators](#creators) -## [Coding Newsletter](https://weeklycoding.com) +## [Available for Hire](https://weeklycoding.com/about/) -Sign up for my [coding newsletter](https://weeklycoding.com) to get quick updates on Kotlin and Android development related topics. - -

    Quick Start :chart_with_upwards_trend:

    - -Add the library to your Android project, then check out the examples below! +I'm available for hire, if you are interested in working with me, just [send me an email](mailto:philjay.librarysup@gmail.com). ### Gradle Setup From f7509d54d64459fb8272f519ff124037b749df46 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 5 Mar 2020 09:23:41 +0100 Subject: [PATCH 1382/1390] Update README.md --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 881f66b6bd..f0580756dc 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,6 @@ 1. [License](#licence) 1. [Creators](#creators) -## [Available for Hire](https://weeklycoding.com/about/) - -I'm available for hire, if you are interested in working with me, just [send me an email](mailto:philjay.librarysup@gmail.com). - ### Gradle Setup ```gradle From 423fc679a336b84d7a74244eab50c318250306ff Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 12 May 2020 12:39:16 +0200 Subject: [PATCH 1383/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0580756dc..46006a1e06 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJah

    License :page_facing_up:

    -Copyright 2019 Philipp Jahoda +Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 8e4dccf3f8ea76a3ff4d84079054bb8cb2af6602 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 26 May 2020 07:39:12 +0200 Subject: [PATCH 1384/1390] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index ba648a557d..c1551a9dce 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ Copyright 2020 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. + you may not use this software except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 From bc0be2cfe13e32a5d8adefaa507e3512d22d85fb Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 21 Sep 2020 17:40:18 +0300 Subject: [PATCH 1385/1390] Revert: e5b66192 - bring back polymorphism to value formatters If anyone does not know how to add a space or change the format in anyway, please learn how to subclass. --- .gitignore | 6 +- .../mpchartexample/BarChartActivity.java | 9 +- .../BarChartActivityMultiDataset.java | 8 +- .../BarChartPositiveNegative.java | 19 ++- .../mpchartexample/CombinedChartActivity.java | 8 +- .../mpchartexample/LineChartTime.java | 8 +- .../mpchartexample/PieChartActivity.java | 2 +- .../mpchartexample/RadarChartActivity.java | 8 +- .../mpchartexample/StackedBarActivity.java | 6 +- .../StackedBarActivityNegative.java | 21 ++- .../custom/DayAxisValueFormatter.java | 7 +- .../custom/MyAxisValueFormatter.java | 21 +++ .../custom/MyCustomXAxisValueFormatter.java | 7 +- .../custom/MyValueFormatter.java | 27 +--- .../mpchartexample/custom/XYMarkerView.java | 9 +- .../custom/YearXAxisFormatter.java | 6 +- .../mikephil/charting/charts/Chart.java | 5 +- .../charting/components/AxisBase.java | 11 +- .../mikephil/charting/data/BaseDataSet.java | 8 +- .../mikephil/charting/data/ChartData.java | 5 +- .../formatter/DefaultAxisValueFormatter.java | 8 +- .../formatter/DefaultValueFormatter.java | 8 +- .../formatter/IAxisValueFormatter.java | 6 - .../charting/formatter/IValueFormatter.java | 10 +- .../formatter/IndexAxisValueFormatter.java | 12 +- .../formatter/LargeValueFormatter.java | 16 +- .../charting/formatter/PercentFormatter.java | 51 +++---- .../formatter/StackedValueFormatter.java | 24 +-- .../charting/formatter/ValueFormatter.java | 137 ------------------ .../dataprovider/ChartInterface.java | 4 +- .../interfaces/datasets/IDataSet.java | 7 +- .../charting/renderer/BarChartRenderer.java | 25 ++-- .../renderer/BubbleChartRenderer.java | 13 +- .../renderer/CandleStickChartRenderer.java | 20 +-- .../renderer/CombinedChartRenderer.java | 7 +- .../charting/renderer/DataRenderer.java | 21 ++- .../renderer/HorizontalBarChartRenderer.java | 17 ++- .../charting/renderer/LineChartRenderer.java | 13 +- .../charting/renderer/PieChartRenderer.java | 29 ++-- .../charting/renderer/RadarChartRenderer.java | 20 +-- .../renderer/ScatterChartRenderer.java | 19 ++- .../charting/renderer/XAxisRenderer.java | 3 +- .../XAxisRendererHorizontalBarChart.java | 7 +- .../renderer/XAxisRendererRadarChart.java | 4 +- .../github/mikephil/charting/utils/Utils.java | 24 +-- .../test/LargeValueFormatterTest.java | 50 +++---- .../charting/test/ObjectPoolTest.java | 2 +- 47 files changed, 340 insertions(+), 418 deletions(-) create mode 100644 MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java delete mode 100644 MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java diff --git a/.gitignore b/.gitignore index 1f0e3083c2..feed37b27d 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ bin/ gen/ generated/ +docs/ finalOutput/ projectFilesBackup/ @@ -23,8 +24,6 @@ local.properties # Eclipse project files .classpath .project -.settings/ -.vscode/ # Proguard folder generated by Eclipse proguard/ @@ -33,8 +32,7 @@ proguard/ *.iml *.ipr *.iws -/.idea/* -!/.idea/runConfigurations +.idea/ .directory diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 89ec00a892..0d83e3444a 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -27,7 +28,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -35,7 +36,7 @@ import com.github.mikephil.charting.utils.Fill; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.custom.DayAxisValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.XYMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -85,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { chart.setDrawGridBackground(false); // chart.setDrawYLabels(false); - ValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); + IAxisValueFormatter xAxisFormatter = new DayAxisValueFormatter(chart); XAxis xAxis = chart.getXAxis(); xAxis.setPosition(XAxisPosition.BOTTOM); @@ -95,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setLabelCount(7); xAxis.setValueFormatter(xAxisFormatter); - ValueFormatter custom = new MyValueFormatter("$"); + IAxisValueFormatter custom = new MyAxisValueFormatter(); YAxis leftAxis = chart.getAxisLeft(); leftAxis.setTypeface(tfLight); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 3369dbf6e2..075af0edbc 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -16,6 +17,7 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -23,8 +25,8 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.formatter.LargeValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -98,9 +100,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTypeface(tfLight); xAxis.setGranularity(1f); xAxis.setCenterAxisLabels(true); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return String.valueOf((int) value); } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java index 8960dc770f..4fec7dd6ab 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/BarChartPositiveNegative.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -9,13 +10,17 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -83,9 +88,9 @@ protected void onCreate(Bundle savedInstanceState) { data.add(new Data(3f, -442.3f, "01-01")); data.add(new Data(4f, -2280.1f, "01-02")); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return data.get(Math.min(Math.max((int) value, 0), data.size()-1)).xAxisValue; } }); @@ -130,7 +135,7 @@ private void setData(List dataList) { BarData data = new BarData(set); data.setValueTextSize(13f); data.setValueTypeface(tfRegular); - data.setValueFormatter(new Formatter()); + data.setValueFormatter(new ValueFormatter()); data.setBarWidth(0.8f); chart.setData(data); @@ -154,17 +159,17 @@ private class Data { } } - private class Formatter extends ValueFormatter + private class ValueFormatter implements IValueFormatter { private final DecimalFormat mFormat; - Formatter() { + ValueFormatter() { mFormat = new DecimalFormat("######.0"); } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value); } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 53dd3806bc..0308b9a891 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.content.Intent; @@ -10,6 +11,7 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -29,7 +31,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -81,9 +83,9 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTH_SIDED); xAxis.setAxisMinimum(0f); xAxis.setGranularity(1f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return months[(int) value % months.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java index e9ae3c0e43..212b90ff87 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/LineChartTime.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -15,6 +16,7 @@ import android.widget.TextView; import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; @@ -22,7 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -90,12 +92,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextColor(Color.rgb(255, 192, 56)); xAxis.setCenterAxisLabels(true); xAxis.setGranularity(1f); // one hour - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final SimpleDateFormat mFormat = new SimpleDateFormat("dd MMM HH:mm", Locale.ENGLISH); @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { long millis = TimeUnit.HOURS.toMillis((long) value); return mFormat.format(new Date(millis)); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 4aeb1b3e9f..830025fbb1 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -160,7 +160,7 @@ private void setData(int count, float range) { //dataSet.setSelectionShift(0f); PieData data = new PieData(dataSet); - data.setValueFormatter(new PercentFormatter(chart)); + data.setValueFormatter(new PercentFormatter()); data.setValueTextSize(11f); data.setValueTextColor(Color.WHITE); data.setValueTypeface(tfLight); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java index 9fdae983d0..883eb7dfc1 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/RadarChartActivity.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -13,6 +14,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.RadarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.components.XAxis; @@ -20,7 +22,7 @@ import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.xxmassdeveloper.mpchartexample.custom.RadarMarkerView; @@ -67,12 +69,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setTextSize(9f); xAxis.setYOffset(0f); xAxis.setXOffset(0f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final String[] mActivities = new String[]{"Burger", "Steak", "Salad", "Pasta", "Pizza"}; @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return mActivities[(int) value % mActivities.length]; } }); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 1def86e8ef..676e0e62b0 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -24,11 +24,11 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.StackedValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MyAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -78,7 +78,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis leftAxis = chart.getAxisLeft(); - leftAxis.setValueFormatter(new MyValueFormatter("K")); + leftAxis.setValueFormatter(new MyAxisValueFormatter()); leftAxis.setAxisMinimum(0f); // this replaces setStartAtZero(true) chart.getAxisRight().setEnabled(false); @@ -142,7 +142,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { dataSets.add(set1); BarData data = new BarData(dataSets); - data.setValueFormatter(new StackedValueFormatter(false, "", 1)); + data.setValueFormatter(new MyValueFormatter()); data.setValueTextColor(Color.WHITE); chart.setData(data); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index a4e510a20f..7af58c85ca 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample; import android.Manifest; @@ -13,6 +14,7 @@ import android.view.WindowManager; import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; @@ -21,10 +23,12 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ViewPortHandler; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -76,12 +80,12 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setCenterAxisLabels(true); xAxis.setLabelCount(12); xAxis.setGranularity(10f); - xAxis.setValueFormatter(new ValueFormatter() { + xAxis.setValueFormatter(new IAxisValueFormatter() { private final DecimalFormat format = new DecimalFormat("###"); @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return format.format(value) + "-" + format.format(value + 10); } }); @@ -238,7 +242,7 @@ public void onNothingSelected() { Log.i("NOTING SELECTED", ""); } - private class CustomFormatter extends ValueFormatter { + private class CustomFormatter implements IValueFormatter, IAxisValueFormatter { private final DecimalFormat mFormat; @@ -246,8 +250,15 @@ private class CustomFormatter extends ValueFormatter { mFormat = new DecimalFormat("###"); } + // data + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(Math.abs(value)) + "m"; + } + + // YAxis @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return mFormat.format(Math.abs(value)) + "m"; } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java index 1fba5cc98e..ba4d860d92 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/DayAxisValueFormatter.java @@ -1,12 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.charts.BarLineChartBase; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by philipp on 02/06/16. */ -public class DayAxisValueFormatter extends ValueFormatter +public class DayAxisValueFormatter implements IAxisValueFormatter { private final String[] mMonths = new String[]{ @@ -20,7 +21,7 @@ public DayAxisValueFormatter(BarLineChartBase chart) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { int days = (int) value; diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java new file mode 100644 index 0000000000..e7cdbfcd10 --- /dev/null +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyAxisValueFormatter.java @@ -0,0 +1,21 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; + +import java.text.DecimalFormat; + +public class MyAxisValueFormatter implements IAxisValueFormatter +{ + + private final DecimalFormat mFormat; + + public MyAxisValueFormatter() { + mFormat = new DecimalFormat("###,###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(value) + " $"; + } +} diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 2cf2eab7ba..bea4908ef2 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,6 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -11,7 +12,7 @@ * @deprecated The {@link MyAxisValueFormatter} does exactly the same thing and is more functional. */ @Deprecated -public class MyCustomXAxisValueFormatter extends ValueFormatter +public class MyCustomXAxisValueFormatter implements IAxisValueFormatter { private final DecimalFormat mFormat; @@ -24,7 +25,7 @@ public MyCustomXAxisValueFormatter(ViewPortHandler viewPortHandler) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index 0b0bf2f2ab..ec1c119818 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,35 +1,22 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.components.XAxis; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; -public class MyValueFormatter extends ValueFormatter +public class MyValueFormatter implements IValueFormatter { private final DecimalFormat mFormat; - private String suffix; - public MyValueFormatter(String suffix) { + public MyValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); - this.suffix = suffix; } @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + suffix; - } - - @Override - public String getAxisLabel(float value, AxisBase axis) { - if (axis instanceof XAxis) { - return mFormat.format(value); - } else if (value > 0) { - return mFormat.format(value) + suffix; - } else { - return mFormat.format(value); - } + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value) + " $"; } } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java index ed9dcb8a23..51e4247d35 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/XYMarkerView.java @@ -1,3 +1,4 @@ + package com.xxmassdeveloper.mpchartexample.custom; import android.annotation.SuppressLint; @@ -6,7 +7,7 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.MPPointF; import com.xxmassdeveloper.mpchartexample.R; @@ -22,11 +23,11 @@ public class XYMarkerView extends MarkerView { private final TextView tvContent; - private final ValueFormatter xAxisValueFormatter; + private final IAxisValueFormatter xAxisValueFormatter; private final DecimalFormat format; - public XYMarkerView(Context context, ValueFormatter xAxisValueFormatter) { + public XYMarkerView(Context context, IAxisValueFormatter xAxisValueFormatter) { super(context, R.layout.custom_marker_view); this.xAxisValueFormatter = xAxisValueFormatter; @@ -39,7 +40,7 @@ public XYMarkerView(Context context, ValueFormatter xAxisValueFormatter) { @Override public void refreshContent(Entry e, Highlight highlight) { - tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX()), format.format(e.getY()))); + tvContent.setText(String.format("x: %s, y: %s", xAxisValueFormatter.getFormattedValue(e.getX(), null), format.format(e.getY()))); super.refreshContent(e, highlight); } diff --git a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java index d45853f8d4..7122e0d80c 100644 --- a/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java +++ b/MPChartExample/src/main/java/com/xxmassdeveloper/mpchartexample/custom/YearXAxisFormatter.java @@ -1,13 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ @SuppressWarnings("unused") -public class YearXAxisFormatter extends ValueFormatter +public class YearXAxisFormatter implements IAxisValueFormatter { private final String[] mMonths = new String[]{ @@ -19,7 +19,7 @@ public YearXAxisFormatter() { } @Override - public String getAxisLabel(float value, AxisBase axis) { + public String getFormattedValue(float value, AxisBase axis) { float percent = value / axis.mAxisRange; return mMonths[(int) (mMonths.length * percent)]; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java index b104935d30..5cf49ea9d1 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/charts/Chart.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.charts; import android.animation.ValueAnimator; @@ -34,7 +35,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.IHighlighter; @@ -1021,7 +1022,7 @@ public XAxis getXAxis() { * * @return */ - public ValueFormatter getDefaultValueFormatter() { + public IValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java index 96f706a3a1..c90b4fc9b9 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/components/AxisBase.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.components; import android.graphics.Color; @@ -5,7 +6,7 @@ import android.util.Log; import com.github.mikephil.charting.formatter.DefaultAxisValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -21,7 +22,7 @@ public abstract class AxisBase extends ComponentBase { /** * custom formatter that is used instead of the auto-formatter if set */ - protected ValueFormatter mAxisValueFormatter; + protected IAxisValueFormatter mAxisValueFormatter; private int mGridColor = Color.GRAY; @@ -518,7 +519,7 @@ public String getFormattedLabel(int index) { if (index < 0 || index >= mEntries.length) return ""; else - return getValueFormatter().getAxisLabel(mEntries[index], this); + return getValueFormatter().getFormattedValue(mEntries[index], this); } /** @@ -530,7 +531,7 @@ public String getFormattedLabel(int index) { * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IAxisValueFormatter f) { if (f == null) mAxisValueFormatter = new DefaultAxisValueFormatter(mDecimals); @@ -543,7 +544,7 @@ public void setValueFormatter(ValueFormatter f) { * * @return */ - public ValueFormatter getValueFormatter() { + public IAxisValueFormatter getValueFormatter() { if (mAxisValueFormatter == null || (mAxisValueFormatter instanceof DefaultAxisValueFormatter && diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java index a4279629ad..7e7445cac7 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/BaseDataSet.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.MPPointF; @@ -51,7 +51,7 @@ public abstract class BaseDataSet implements IDataSet { /** * custom formatter that is used instead of the auto-formatter if set */ - protected transient ValueFormatter mValueFormatter; + protected transient IValueFormatter mValueFormatter; /** * the typeface used for the value text @@ -274,7 +274,7 @@ public boolean isHighlightEnabled() { } @Override - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; @@ -283,7 +283,7 @@ public void setValueFormatter(ValueFormatter f) { } @Override - public ValueFormatter getValueFormatter() { + public IValueFormatter getValueFormatter() { if (needsFormatter()) return Utils.getDefaultValueFormatter(); return mValueFormatter; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java index 95d439a71d..bfc5ed7016 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/data/ChartData.java @@ -1,10 +1,11 @@ + package com.github.mikephil.charting.data; import android.graphics.Typeface; import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -658,7 +659,7 @@ public T getFirstRight(List sets) { * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(IValueFormatter f) { if (f == null) return; else { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java index c8834c3e45..552c150e69 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultAxisValueFormatter.java @@ -1,11 +1,13 @@ package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; + import java.text.DecimalFormat; /** * Created by philipp on 02/06/16. */ -public class DefaultAxisValueFormatter extends ValueFormatter +public class DefaultAxisValueFormatter implements IAxisValueFormatter { /** @@ -16,7 +18,7 @@ public class DefaultAxisValueFormatter extends ValueFormatter /** * the number of decimal digits this formatter uses */ - protected int digits; + protected int digits = 0; /** * Constructor that specifies to how many digits the value should be @@ -38,7 +40,7 @@ public DefaultAxisValueFormatter(int digits) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { // avoid memory allocations here (for performance) return mFormat.format(value); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index 40668b91ab..e2fea4b079 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -1,5 +1,9 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + import java.text.DecimalFormat; /** @@ -8,7 +12,7 @@ * * @author Philipp Jahoda */ -public class DefaultValueFormatter extends ValueFormatter +public class DefaultValueFormatter implements IValueFormatter { /** @@ -48,7 +52,7 @@ public void setup(int digits) { } @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { // put more logic here ... // avoid memory allocations here (for performance reasons) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java index 970ea6fca8..51939b5432 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IAxisValueFormatter.java @@ -6,10 +6,7 @@ * Created by Philipp Jahoda on 20/09/15. * Custom formatter interface that allows formatting of * axis labels before they are being drawn. - * - * @deprecated Extend {@link ValueFormatter} instead */ -@Deprecated public interface IAxisValueFormatter { @@ -21,9 +18,6 @@ public interface IAxisValueFormatter * @param value the value to be formatted * @param axis the axis the value belongs to * @return - * - * @deprecated Extend {@link ValueFormatter} and use {@link ValueFormatter#getAxisLabel(float, AxisBase)} */ - @Deprecated String getFormattedValue(float value, AxisBase axis); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java index 0dde7012e3..75d2363f26 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IValueFormatter.java @@ -4,12 +4,13 @@ import com.github.mikephil.charting.utils.ViewPortHandler; /** - * Interface to format all values before they are drawn as labels. + * Interface that allows custom formatting of all values inside the chart before they are + * being drawn to the screen. Simply create your own formatting class and let + * it implement IValueFormatter. Then override the getFormattedValue(...) method + * and return whatever you want. * * @author Philipp Jahoda - * @deprecated Extend {@link ValueFormatter} instead */ -@Deprecated public interface IValueFormatter { @@ -23,9 +24,6 @@ public interface IValueFormatter * @param dataSetIndex the index of the DataSet the entry in focus belongs to * @param viewPortHandler provides information about the current chart state (scale, translation, ...) * @return the formatted label ready for being drawn - * - * @deprecated Extend {@link ValueFormatter} and override an appropriate method */ - @Deprecated String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java index 7ab7bdbe7d..07349a6a0e 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/IndexAxisValueFormatter.java @@ -1,11 +1,18 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; +import java.util.Arrays; import java.util.Collection; /** * This formatter is used for passing an array of x-axis labels, on whole x steps. */ -public class IndexAxisValueFormatter extends ValueFormatter +public class IndexAxisValueFormatter implements IAxisValueFormatter { private String[] mValues = new String[] {}; private int mValueCount = 0; @@ -37,8 +44,7 @@ public IndexAxisValueFormatter(Collection values) { setValues(values.toArray(new String[values.size()])); } - @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { int index = Math.round(value); if (index < 0 || index >= mValueCount || index != (int)value) diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 4870a4cff4..211401ad8a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -1,5 +1,10 @@ + package com.github.mikephil.charting.formatter; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + import java.text.DecimalFormat; /** @@ -12,7 +17,7 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter extends ValueFormatter +public class LargeValueFormatter implements IValueFormatter, IAxisValueFormatter { private String[] mSuffix = new String[]{ @@ -36,8 +41,15 @@ public LargeValueFormatter(String appendix) { mText = appendix; } + // IValueFormatter + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return makePretty(value) + mText; + } + + // IAxisValueFormatter @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, AxisBase axis) { return makePretty(value) + mText; } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java index 012fab77f9..de8a10255a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -1,54 +1,49 @@ + package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.charts.PieChart; -import com.github.mikephil.charting.data.PieEntry; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; /** * This IValueFormatter is just for convenience and simply puts a "%" sign after - * each value. (Recommended for PieChart) + * each value. (Recommeded for PieChart) * * @author Philipp Jahoda */ -public class PercentFormatter extends ValueFormatter +public class PercentFormatter implements IValueFormatter, IAxisValueFormatter { - public DecimalFormat mFormat; - private PieChart pieChart; - private boolean percentSignSeparated; + protected DecimalFormat mFormat; public PercentFormatter() { mFormat = new DecimalFormat("###,###,##0.0"); - percentSignSeparated = true; - } - - // Can be used to remove percent signs if the chart isn't in percent mode - public PercentFormatter(PieChart pieChart) { - this(); - this.pieChart = pieChart; } - // Can be used to remove percent signs if the chart isn't in percent mode - public PercentFormatter(PieChart pieChart, boolean percentSignSeparated) { - this(pieChart); - this.percentSignSeparated = percentSignSeparated; + /** + * Allow a custom decimalformat + * + * @param format + */ + public PercentFormatter(DecimalFormat format) { + this.mFormat = format; } + // IValueFormatter @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + (percentSignSeparated ? " %" : "%"); + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value) + " %"; } + // IAxisValueFormatter @Override - public String getPieLabel(float value, PieEntry pieEntry) { - if (pieChart != null && pieChart.isUsePercentValuesEnabled()) { - // Converted to percent - return getFormattedValue(value); - } else { - // raw value, skip percent sign - return mFormat.format(value); - } + public String getFormattedValue(float value, AxisBase axis) { + return mFormat.format(value) + " %"; } + public int getDecimalDigits() { + return 1; + } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java index 7c69dcf5d6..0e8351634f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.formatter; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -10,7 +12,7 @@ * A formatter specifically for stacked BarChart that allows to specify whether the all stack values * or just the top value should be drawn. */ -public class StackedValueFormatter extends ValueFormatter +public class StackedValueFormatter implements IValueFormatter { /** @@ -21,7 +23,7 @@ public class StackedValueFormatter extends ValueFormatter /** * a string that should be appended behind the value */ - private String mSuffix; + private String mAppendix; private DecimalFormat mFormat; @@ -29,12 +31,12 @@ public class StackedValueFormatter extends ValueFormatter * Constructor. * * @param drawWholeStack if true, all stack values of the stacked bar entry are drawn, else only top - * @param suffix a string that should be appended behind the value + * @param appendix a string that should be appended behind the value * @param decimals the number of decimal digits to use */ - public StackedValueFormatter(boolean drawWholeStack, String suffix, int decimals) { + public StackedValueFormatter(boolean drawWholeStack, String appendix, int decimals) { this.mDrawWholeStack = drawWholeStack; - this.mSuffix = suffix; + this.mAppendix = appendix; StringBuffer b = new StringBuffer(); for (int i = 0; i < decimals; i++) { @@ -47,10 +49,12 @@ public StackedValueFormatter(boolean drawWholeStack, String suffix, int decimals } @Override - public String getBarStackedLabel(float value, BarEntry entry) { - if (!mDrawWholeStack) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - float[] vals = entry.getYVals(); + if (!mDrawWholeStack && entry instanceof BarEntry) { + + BarEntry barEntry = (BarEntry) entry; + float[] vals = barEntry.getYVals(); if (vals != null) { @@ -58,7 +62,7 @@ public String getBarStackedLabel(float value, BarEntry entry) { if (vals[vals.length - 1] == value) { // return the "sum" across all stack values - return mFormat.format(entry.getY()) + mSuffix; + return mFormat.format(barEntry.getY()) + mAppendix; } else { return ""; // return empty } @@ -66,6 +70,6 @@ public String getBarStackedLabel(float value, BarEntry entry) { } // return the "proposed" value - return mFormat.format(value) + mSuffix; + return mFormat.format(value) + mAppendix; } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java deleted file mode 100644 index d2f53cb78b..0000000000 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/formatter/ValueFormatter.java +++ /dev/null @@ -1,137 +0,0 @@ -package com.github.mikephil.charting.formatter; - -import com.github.mikephil.charting.components.AxisBase; -import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.utils.ViewPortHandler; - -/** - * Class to format all values before they are drawn as labels. - */ -public abstract class ValueFormatter implements IAxisValueFormatter, IValueFormatter{ - - /** - * DO NOT USE, only for backwards compatibility and will be removed in future versions. - * - * @param value the value to be formatted - * @param axis the axis the value belongs to - * @return formatted string label - */ - @Override - @Deprecated - public String getFormattedValue(float value, AxisBase axis) { - return getFormattedValue(value); - } - - /** - * DO NOT USE, only for backwards compatibility and will be removed in future versions. - * @param value the value to be formatted - * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry - * @param dataSetIndex the index of the DataSet the entry in focus belongs to - * @param viewPortHandler provides information about the current chart state (scale, translation, ...) - * @return formatted string label - */ - @Override - @Deprecated - public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { - return getFormattedValue(value); - } - - /** - * Called when drawing any label, used to change numbers into formatted strings. - * - * @param value float to be formatted - * @return formatted string label - */ - public String getFormattedValue(float value) { - return String.valueOf(value); - } - - /** - * Used to draw axis labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value float to be formatted - * @param axis axis being labeled - * @return formatted string label - */ - public String getAxisLabel(float value, AxisBase axis) { - return getFormattedValue(value); - } - - /** - * Used to draw bar labels, calls {@link #getFormattedValue(float)} by default. - * - * @param barEntry bar being labeled - * @return formatted string label - */ - public String getBarLabel(BarEntry barEntry) { - return getFormattedValue(barEntry.getY()); - } - - /** - * Used to draw stacked bar labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value current value to be formatted - * @param stackedEntry stacked entry being labeled, contains all Y values - * @return formatted string label - */ - public String getBarStackedLabel(float value, BarEntry stackedEntry) { - return getFormattedValue(value); - } - - /** - * Used to draw line and scatter labels, calls {@link #getFormattedValue(float)} by default. - * - * @param entry point being labeled, contains X value - * @return formatted string label - */ - public String getPointLabel(Entry entry) { - return getFormattedValue(entry.getY()); - } - - /** - * Used to draw pie value labels, calls {@link #getFormattedValue(float)} by default. - * - * @param value float to be formatted, may have been converted to percentage - * @param pieEntry slice being labeled, contains original, non-percentage Y value - * @return formatted string label - */ - public String getPieLabel(float value, PieEntry pieEntry) { - return getFormattedValue(value); - } - - /** - * Used to draw radar value labels, calls {@link #getFormattedValue(float)} by default. - * - * @param radarEntry entry being labeled - * @return formatted string label - */ - public String getRadarLabel(RadarEntry radarEntry) { - return getFormattedValue(radarEntry.getY()); - } - - /** - * Used to draw bubble size labels, calls {@link #getFormattedValue(float)} by default. - * - * @param bubbleEntry bubble being labeled, also contains X and Y values - * @return formatted string label - */ - public String getBubbleLabel(BubbleEntry bubbleEntry) { - return getFormattedValue(bubbleEntry.getSize()); - } - - /** - * Used to draw high labels, calls {@link #getFormattedValue(float)} by default. - * - * @param candleEntry candlestick being labeled - * @return formatted string label - */ - public String getCandleLabel(CandleEntry candleEntry) { - return getFormattedValue(candleEntry.getHigh()); - } - -} diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 182aa28757..219b46bd82 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -3,7 +3,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; /** @@ -61,7 +61,7 @@ public interface ChartInterface { RectF getContentRect(); - ValueFormatter getDefaultValueFormatter(); + IValueFormatter getDefaultValueFormatter(); ChartData getData(); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index ccd4cb4f70..fd8af7064b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -1,13 +1,14 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; +import android.graphics.PointF; import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.utils.MPPointF; import java.util.List; @@ -317,14 +318,14 @@ public interface IDataSet { * * @param f */ - void setValueFormatter(ValueFormatter f); + void setValueFormatter(IValueFormatter f); /** * Returns the formatter used for drawing the values inside the chart. * * @return */ - ValueFormatter getValueFormatter(); + IValueFormatter getValueFormatter(); /** * Returns true if the valueFormatter object of this DataSet is null. diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java index 18975557cd..1656a3a37f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,7 +11,6 @@ import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.Range; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; @@ -241,8 +241,6 @@ public void drawValues(Canvas c) { final float phaseY = mAnimator.getPhaseY(); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -265,7 +263,8 @@ public void drawValues(Canvas c) { float val = entry.getY(); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarLabel(entry), x, val >= 0 ? + drawValue(c, dataSet.getValueFormatter(), val, entry, i, x, + val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset), dataSet.getValueTextColor(j / 4)); @@ -323,7 +322,8 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarLabel(entry), x, buffer.buffer[bufferIndex + 1] + + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset), color); } @@ -394,7 +394,14 @@ public void drawValues(Canvas c) { continue; if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBarStackedLabel(val, entry), x, y, color); + drawValue(c, + dataSet.getValueFormatter(), + vals[k / 2], + entry, + i, + x, + y, + color); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -422,12 +429,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawHighlighted(Canvas c, Highlight[] indices) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index be141c46a0..5ce19c2c9f 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -8,7 +9,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; @@ -150,8 +150,6 @@ public void drawValues(Canvas c) { final float alpha = phaseX == 1 ? phaseY : phaseX; - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -174,7 +172,8 @@ public void drawValues(Canvas c) { BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getBubbleLabel(entry), x, y + (0.5f * lineHeight), valueTextColor); + drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, + y + (0.5f * lineHeight), valueTextColor); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -196,12 +195,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 027dda31d8..991b702117 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,7 +8,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; @@ -279,8 +279,6 @@ public void drawValues(Canvas c) { float yOffset = Utils.convertDpToPixel(5f); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -299,7 +297,15 @@ public void drawValues(Canvas c) { CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getCandleLabel(entry), x, y - yOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getHigh(), + entry, + i, + x, + y - yOffset, + dataSet + .getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -321,12 +327,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 8f6be3c054..6d0d4d3da0 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.Chart; @@ -10,6 +9,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; import java.lang.ref.WeakReference; @@ -89,11 +89,6 @@ public void drawData(Canvas c) { renderer.drawData(c); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - Log.e("MPAndroidChart", "Erroneous call to drawValue() in CombinedChartRenderer!"); - } - @Override public void drawValues(Canvas c) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java index da4a26edca..e8e5446f4d 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/DataRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -5,11 +6,15 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.MPPointF; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -133,13 +138,19 @@ protected void applyValueTextStyle(IDataSet set) { /** * Draws the value of the given entry by using the provided IValueFormatter. * - * @param c canvas - * @param valueText label to draw - * @param x position - * @param y position + * @param c canvas + * @param formatter formatter for custom value-formatting + * @param value the value to be drawn + * @param entry the entry the value belongs to + * @param dataSetIndex the index of the DataSet the drawn Entry belongs to + * @param x position + * @param y position * @param color */ - public abstract void drawValue(Canvas c, String valueText, float x, float y, int color); + public void drawValue(Canvas c, IValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y, int color) { + mValuePaint.setColor(color); + c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); + } /** * Draws any kind of additional information (e.g. line-circles). diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index b42ef1284a..0cd72345fb 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,7 +11,7 @@ import com.github.mikephil.charting.buffer.HorizontalBarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; @@ -181,7 +182,7 @@ public void drawValues(Canvas c) { applyValueTextStyle(dataSet); final float halfTextHeight = Utils.calcTextHeight(mValuePaint, "10") / 2f; - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); // get the buffer BarBuffer buffer = mBarBuffers[i]; @@ -210,7 +211,7 @@ public void drawValues(Canvas c) { BarEntry entry = dataSet.getEntryForIndex(j / 4); float val = entry.getY(); - String formattedValue = formatter.getBarLabel(entry); + String formattedValue = formatter.getFormattedValue(val, entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -280,7 +281,9 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1])) continue; - String formattedValue = formatter.getBarLabel(entry); + float val = entry.getY(); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -350,7 +353,8 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { final float val = vals[k / 2]; - String formattedValue = formatter.getBarStackedLabel(val, entry); + String formattedValue = formatter.getFormattedValue(val, + entry, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); @@ -408,8 +412,7 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { + protected void drawValue(Canvas c, String valueText, float x, float y, int color) { mValuePaint.setColor(color); c.drawText(valueText, x, y, mValuePaint); } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java index a00860b5a6..a86c16f76b 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -12,7 +12,6 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.interfaces.datasets.IDataSet; @@ -295,7 +294,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet) { int entryCount = dataSet.getEntryCount(); - final boolean isDrawSteppedEnabled = dataSet.getMode() == LineDataSet.Mode.STEPPED; + final boolean isDrawSteppedEnabled = dataSet.isDrawSteppedEnabled(); final int pointsPerEntryPair = isDrawSteppedEnabled ? 4 : 2; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -562,7 +561,6 @@ public void drawValues(Canvas c) { float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator .getPhaseY(), mXBounds.min, mXBounds.max); - ValueFormatter formatter = dataSet.getValueFormatter(); MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); @@ -582,7 +580,8 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getPointLabel(entry), x, y - valOffset, dataSet.getValueTextColor(j / 2)); + drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x, + y - valOffset, dataSet.getValueTextColor(j / 2)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -604,12 +603,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { drawCircles(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java index f427ffe5d3..f35c775d45 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Bitmap; @@ -21,7 +22,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.PieEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -464,7 +465,7 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); - ValueFormatter formatter = dataSet.getValueFormatter(); + IValueFormatter formatter = dataSet.getValueFormatter(); int entryCount = dataSet.getEntryCount(); @@ -500,7 +501,6 @@ public void drawValues(Canvas c) { float value = mChart.isUsePercentValuesEnabled() ? entry.getY() / yValueSum * 100f : entry.getY(); - String formattedValue = formatter.getPieLabel(value, entry); String entryLabel = entry.getLabel(); final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD); @@ -583,7 +583,14 @@ else if (valueLineColor != ColorTemplate.COLOR_NONE) // draw everything, depending on settings if (drawXOutside && drawYOutside) { - drawValue(c, formattedValue, labelPtx, labelPty, dataSet.getValueTextColor(j)); + drawValue(c, + formatter, + value, + entry, + 0, + labelPtx, + labelPty, + dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entryLabel != null) { drawEntryLabel(c, entryLabel, labelPtx, labelPty + lineHeight); @@ -595,7 +602,8 @@ else if (valueLineColor != ColorTemplate.COLOR_NONE) } } else if (drawYOutside) { - drawValue(c, formattedValue, labelPtx, labelPty + lineHeight / 2.f, dataSet.getValueTextColor(j)); + drawValue(c, formatter, value, entry, 0, labelPtx, labelPty + lineHeight / 2.f, dataSet + .getValueTextColor(j)); } } @@ -609,7 +617,7 @@ else if (valueLineColor != ColorTemplate.COLOR_NONE) // draw everything, depending on settings if (drawXInside && drawYInside) { - drawValue(c, formattedValue, x, y, dataSet.getValueTextColor(j)); + drawValue(c, formatter, value, entry, 0, x, y, dataSet.getValueTextColor(j)); if (j < data.getEntryCount() && entryLabel != null) { drawEntryLabel(c, entryLabel, x, y + lineHeight); @@ -620,7 +628,8 @@ else if (valueLineColor != ColorTemplate.COLOR_NONE) drawEntryLabel(c, entryLabel, x, y + lineHeight / 2f); } } else if (drawYInside) { - drawValue(c, formattedValue, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); + + drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f, dataSet.getValueTextColor(j)); } } @@ -650,12 +659,6 @@ else if (valueLineColor != ColorTemplate.COLOR_NONE) c.restore(); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - /** * Draws an entry label at the specified position. * diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 3f932f8725..dbf0e8f807 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -10,7 +11,6 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarEntry; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -174,8 +174,6 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -191,7 +189,15 @@ public void drawValues(Canvas c) { pOut); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getRadarLabel(entry), pOut.x, pOut.y - yoffset, dataSet.getValueTextColor(j)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + pOut.x, + pOut.y - yoffset, + dataSet.getValueTextColor + (j)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -225,12 +231,6 @@ public void drawValues(Canvas c) { MPPointF.recycleInstance(pIcon); } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { drawWeb(c); diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 98dddb93f9..ccd077e55c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -7,7 +8,6 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -118,8 +118,6 @@ public void drawValues(Canvas c) { float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize()); - ValueFormatter formatter = dataSet.getValueFormatter(); - MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset()); iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x); iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y); @@ -137,7 +135,14 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min); if (dataSet.isDrawValuesEnabled()) { - drawValue(c, formatter.getPointLabel(entry), positions[j], positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min)); + drawValue(c, + dataSet.getValueFormatter(), + entry.getY(), + entry, + i, + positions[j], + positions[j + 1] - shapeSize, + dataSet.getValueTextColor(j / 2 + mXBounds.min)); } if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) { @@ -159,12 +164,6 @@ public void drawValues(Canvas c) { } } - @Override - public void drawValue(Canvas c, String valueText, float x, float y, int color) { - mValuePaint.setColor(color); - c.drawText(valueText, x, y, mValuePaint); - } - @Override public void drawExtras(Canvas c) { } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java index 046f3469bc..8adb56c73a 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -201,7 +202,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mViewPortHandler.isInBoundsX(x)) { - String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis); + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); if (mXAxis.isAvoidFirstLastClippingEnabled()) { diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9054dcb679..86047cf1b8 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -56,10 +57,10 @@ public void computeAxis(float min, float max, boolean inverted) { computeAxisValues(min, max); } - + @Override protected void computeSize() { - + mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -155,7 +156,7 @@ protected void drawLabels(Canvas c, float pos, MPPointF anchor) { if (mViewPortHandler.isInBoundsY(y)) { - String label = mXAxis.getValueFormatter().getAxisLabel(mXAxis.mEntries[i / 2], mXAxis); + String label = mXAxis.getValueFormatter().getFormattedValue(mXAxis.mEntries[i / 2], mXAxis); drawLabel(c, label, pos, y, anchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 6d83cf59e4..956e8c7d5c 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -1,6 +1,8 @@ + package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.PointF; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.components.XAxis; @@ -41,7 +43,7 @@ public void renderAxisLabels(Canvas c) { MPPointF pOut = MPPointF.getInstance(0,0); for (int i = 0; i < mChart.getData().getMaxEntryCountSet().getEntryCount(); i++) { - String label = mXAxis.getValueFormatter().getAxisLabel(i, mXAxis); + String label = mXAxis.getValueFormatter().getFormattedValue(i, mXAxis); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; diff --git a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java index 60ff6ba3da..c302673919 100644 --- a/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/main/java/com/github/mikephil/charting/utils/Utils.java @@ -1,3 +1,4 @@ + package com.github.mikephil.charting.utils; import android.annotation.SuppressLint; @@ -6,6 +7,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; @@ -13,13 +15,14 @@ import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; +import android.util.SizeF; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.formatter.IValueFormatter; import java.util.List; @@ -226,14 +229,15 @@ public static void calcTextSize(Paint paint, String demoText, FSize outputFSize) 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; - private static ValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); + private static IValueFormatter mDefaultValueFormatter = generateDefaultValueFormatter(); - private static ValueFormatter generateDefaultValueFormatter() { - return new DefaultValueFormatter(1); + private static IValueFormatter generateDefaultValueFormatter() { + final DefaultValueFormatter formatter = new DefaultValueFormatter(1); + return formatter; } /// - returns: The default value formatter used for all chart components that needs a default - public static ValueFormatter getDefaultValueFormatter() + public static IValueFormatter getDefaultValueFormatter() { return mDefaultValueFormatter; } @@ -349,11 +353,11 @@ public static String formatNumber(float number, int digitCount, boolean separate * @return */ public static float roundToNextSignificant(double number) { - if (Double.isInfinite(number) || - Double.isNaN(number) || + if (Double.isInfinite(number) || + Double.isNaN(number) || number == 0.0) return 0; - + final float d = (float) Math.ceil((float) Math.log10(number < 0 ? -number : number)); final int pw = 1 - (int) d; final float magnitude = (float) Math.pow(10, pw); @@ -371,10 +375,10 @@ public static float roundToNextSignificant(double number) { public static int getDecimals(float number) { float i = roundToNextSignificant(number); - + if (Float.isInfinite(i)) return 0; - + return (int) Math.ceil(-Math.log10(i)) + 2; } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java index fc7eb93e75..f1e1e0279e 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/LargeValueFormatterTest.java @@ -16,80 +16,80 @@ public void test() { LargeValueFormatter formatter = new LargeValueFormatter(); - String result = formatter.getFormattedValue(5f); + String result = formatter.getFormattedValue(5f, null); assertEquals("5", result); - result = formatter.getFormattedValue(5.5f); + result = formatter.getFormattedValue(5.5f, null); assertEquals("5.5", result); - result = formatter.getFormattedValue(50f); + result = formatter.getFormattedValue(50f, null); assertEquals("50", result); - result = formatter.getFormattedValue(50.5f); + result = formatter.getFormattedValue(50.5f, null); assertEquals("50.5", result); - result = formatter.getFormattedValue(500f); + result = formatter.getFormattedValue(500f, null); assertEquals("500", result); - result = formatter.getFormattedValue(1100f); + result = formatter.getFormattedValue(1100f, null); assertEquals("1.1k", result); - result = formatter.getFormattedValue(10000f); + result = formatter.getFormattedValue(10000f, null); assertEquals("10k", result); - result = formatter.getFormattedValue(10500f); + result = formatter.getFormattedValue(10500f, null); assertEquals("10.5k", result); - result = formatter.getFormattedValue(100000f); + result = formatter.getFormattedValue(100000f, null); assertEquals("100k", result); - result = formatter.getFormattedValue(1000000f); + result = formatter.getFormattedValue(1000000f, null); assertEquals("1m", result); - result = formatter.getFormattedValue(1500000f); + result = formatter.getFormattedValue(1500000f, null); assertEquals("1.5m", result); - result = formatter.getFormattedValue(9500000f); + result = formatter.getFormattedValue(9500000f, null); assertEquals("9.5m", result); - result = formatter.getFormattedValue(22200000f); + result = formatter.getFormattedValue(22200000f, null); assertEquals("22.2m", result); - result = formatter.getFormattedValue(222000000f); + result = formatter.getFormattedValue(222000000f, null); assertEquals("222m", result); - result = formatter.getFormattedValue(1000000000f); + result = formatter.getFormattedValue(1000000000f, null); assertEquals("1b", result); - result = formatter.getFormattedValue(9900000000f); + result = formatter.getFormattedValue(9900000000f, null); assertEquals("9.9b", result); - result = formatter.getFormattedValue(99000000000f); + result = formatter.getFormattedValue(99000000000f, null); assertEquals("99b", result); - result = formatter.getFormattedValue(99500000000f); + result = formatter.getFormattedValue(99500000000f, null); assertEquals("99.5b", result); - result = formatter.getFormattedValue(999000000000f); + result = formatter.getFormattedValue(999000000000f, null); assertEquals("999b", result); - result = formatter.getFormattedValue(1000000000000f); + result = formatter.getFormattedValue(1000000000000f, null); assertEquals("1t", result); formatter.setSuffix(new String[]{"", "k", "m", "b", "t", "q"}); // quadrillion support - result = formatter.getFormattedValue(1000000000000000f); + result = formatter.getFormattedValue(1000000000000000f, null); assertEquals("1q", result); - result = formatter.getFormattedValue(1100000000000000f); + result = formatter.getFormattedValue(1100000000000000f, null); assertEquals("1.1q", result); - result = formatter.getFormattedValue(10000000000000000f); + result = formatter.getFormattedValue(10000000000000000f, null); assertEquals("10q", result); - result = formatter.getFormattedValue(13300000000000000f); + result = formatter.getFormattedValue(13300000000000000f, null); assertEquals("13.3q", result); - result = formatter.getFormattedValue(100000000000000000f); + result = formatter.getFormattedValue(100000000000000000f, null); assertEquals("100q", result); } } diff --git a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java index 44946cf4da..e1dbe81be9 100644 --- a/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java +++ b/MPChartLib/src/test/java/com/github/mikephil/charting/test/ObjectPoolTest.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.utils.ObjectPool; -import org.junit.Assert; +import junit.framework.Assert; import org.junit.Test; From 696ebd06c9311b814428d7ebc2b3a44b19b49ce7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 29 Oct 2020 16:30:36 +0100 Subject: [PATCH 1386/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 46006a1e06..7c9c40e45c 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: [![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) [![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -You can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) or sign up for my [**coding newsletter**](https://weeklycoding.com). +If you like, you can follow me on Twitter [**@PhilippJahoda**].
    From 5a732b04278a983d32856c75ad552f2dcbbd922d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 29 Oct 2020 16:31:19 +0100 Subject: [PATCH 1387/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c9c40e45c..9a31698504 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,7 @@ If you like this library, please tell others about it :two_hearts: :two_hearts: [![Share on Google+](https://github.com/PhilJay/MPAndroidChart/blob/master/design/googleplus_icon.png)](https://plus.google.com/share?url=https://github.com/PhilJay/MPAndroidChart) [![Share on Facebook](https://github.com/PhilJay/MPAndroidChart/blob/master/design/facebook_icon.png)](https://www.facebook.com/sharer/sharer.php?u=https://github.com/PhilJay/MPAndroidChart) -If you like, you can follow me on Twitter [**@PhilippJahoda**]. +If you like, you can follow me on Twitter [**@PhilippJahoda**](https://twitter.com/PhilippJahoda).
    From 9ba46d8618f988bb124f0cb8df23dac84da5c386 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 21 Jun 2021 15:16:32 +0200 Subject: [PATCH 1388/1390] Update README.md --- README.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/README.md b/README.md index 9a31698504..1ab6eb779f 100644 --- a/README.md +++ b/README.md @@ -82,14 +82,6 @@ Please read the [**documentation**](https://weeklycoding.com/mpandroidchart/) fi **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! -**My Bitcoin Wallet** (Bitcoin only) - -1G8G6tqQ3oh38BvDH3xq8o6gGVMvBTkcUg - -**My Ethereum Wallet** (Ethereum only) - -0x04ef098bf9f91871391363e3caf791afa3adc39b - [**Lightning Network (tippin.me)**](https://tippin.me/@PhilippJahoda) From 0550d3f7907c635744c08ad8ff9c45e1b6281cc7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 21 Jun 2021 15:16:58 +0200 Subject: [PATCH 1389/1390] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 1ab6eb779f..a3253e3ff9 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,6 @@ Please read the [**documentation**](https://weeklycoding.com/mpandroidchart/) fi **This project needs you!** If you would like to support this project's further development, the creator of this project or the continuous maintenance of this project, **feel free to donate**. Your donation is highly appreciated (and I love food, coffee and beer). Thank you! -[**Lightning Network (tippin.me)**](https://tippin.me/@PhilippJahoda) - - **PayPal** - [**Donate 5 $**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7G52RA87ED8NY): Thank's for creating this project, here's a coffee (or some beer) for you! From 3aa02094e270bc87940ff872ddcd69edf6152d16 Mon Sep 17 00:00:00 2001 From: Uriel Frankel Date: Sun, 12 May 2024 11:47:39 +0300 Subject: [PATCH 1390/1390] Make MPAndroidChart compatible with Android Studio Iguana (2024) --- MPChartLib/build.gradle | 1 - build.gradle | 7 +++---- gradle/wrapper/gradle-wrapper.properties | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 0fb6dc7036..16d3e3ce10 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -1,5 +1,4 @@ apply plugin: 'com.android.library' -apply plugin: 'com.github.dcendents.android-maven' group='com.github.philjay' diff --git a/build.gradle b/build.gradle index cee7a83e80..ac31f01cf5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,17 +1,16 @@ buildscript { repositories { - jcenter() google() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' - classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' + classpath 'com.android.tools.build:gradle:7.0.4' } } allprojects { repositories { - jcenter() google() + mavenCentral() } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f8bc4e375..ffed3a254e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Sat Apr 27 15:48:29 CEST 2019 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip

    j^kOYD80$1D~7=_;yQEgu8PNk@kjk}%1)J1;G1!1po5p`2s6Bf+G)U+ zxt(+4mLuv5S0tv}7MOqkqsZJG8_&K$a`7}qhvf9?XPVgDl?Lx5q#*mcWbtHwd@W6H zMA;Py;ScrA8fjsbwBXh1v9eTJigO7kgK9b$yGeKBRYuuC2Jd-@`S(5OjFYED$!5B9 z^+3gkR*SiM95Y&}wA@kwI)UR&M4^`!)2%4AK{YflZZSx%sQhhHV*;PM`o5@_lp`Ss zCjN8a8;p8}uj(hC;bzDlm7d@1N-WK zAba$i=sfvx^5b7;`t+|+oOqGq!kY~K)Bl>@2fmNV=YGZ2en#AWC&2E1MY4B&jP&k@ zDZcva*jGOTlT}QXVIKMzo%en>lc)c!t9|mK_5o6_Ch*PvBj!;&@2whpJEc8)@HT4Z z*|WBJ73|cjCHy$?nrTs;pQ>IB(@fYBqPn=5TI+d;80ZWF!(%DWQ7!UPx@OVo5b|*u z)0-ew0E0I-FONf`r7mKByzZK=#l6rSpx4f!YZs8YZ7vF3qxI?Ci%?GO2u8C%nkquL z1ZE@zpsE3w@2z4ompHY45q91O)0-TiY>w$aeh<@2S6O}Pd9q#ebn>%^PJR7H%?=3= zAn^u5;^A&#ldKInUx2_?5 zNk|;FSe$tQv$=vS?IT$|=jf*;8)bIrIin|A8DIr1T7_XBX|MUs0zgdTVT z*|s0D0m+en52O7>?D^M%dfSidQiI2@ujq)YF*z5yz2Hu$@sYjT^2LN^*h& zZL&#r>@&#Pxhipqh-j%a{V!03$&_TiPxtUXK*_I^jGeNO45m>Py}ZSZzQrS;K^zZ~ z2BfluRS`@z)b`ZSDlKcWt+6C*JZHbAIS3>>mgyXS*iAC;(vNK6ig**yM4OS&QkpSK zKBRN>DaQRJbbc=~TD_sE<@G?z;NOga=?F7i2@^e30zfrpcr+}+%C6b%I|j|iF6nCL z5zO)dq&p8A7qJ(P!tkmCPE=tsgvGriyY7YlB6hfnxo{M{b{6S$9S{=5GHQ{#+p^~& zk{ySC+{>?=MlT=pqz$Fa(a&}D{WXH?qM=WNSCFVN$Y=$oqjHjGuRBz@qo95X45uQ`v7hu^-vU}-Pd$T?A<6`M{Ap(@zwO=qVrmANf zgQF&^p$7B3#yglUbKU){t$C2PoX;CS~Wnq=%nGb{>JOi>{u>9{)0W?v-*MF!(8a@zM!>K*~{zTDON9@mO_#cmRsO z8P;oFO^U2vL^dx|>-lfIM(kulx^0oc6ZbJWb(Q?mS<>R7Gcd*w$}%J<^O|zcX7yEB z4a{UzT7yE?V<3nabUH#un@%dxpAVX9Y*C)`7Lvq$UQA>0ssQ-}9go~TQr?4#N3V)@ z2bioA$x)lr<|-~c*xP9F#0!6afWgHJGtEi2Eiri4{dD*5q*&X$wOYWKazL|E4}Sdt z4jM@B>h;-7d<-5pZ+n|DUXosiWY8tqwt!t9QEY5rH%2a9Yno%n<-I|Xo*VpEa`ov5 zos?=yZg1G9=4L1}TztNtU;h?%0MI^pG@vMf2PN!l6M} zAgh=7JkoY|6#UAl)M|?@kf|HA-7F3f?{jGzHRX;Mf45NFf1_XX_Sq{gIv9cE;;VFC z{7ua83fi4-P|s=_lZ|MF+R)Le2W|vu5OLyw_zV&a7l)WC0=1!Kj$X)faPVqhzYqf* z>_D!aCVS;~(e50@u7^s0Plf9jp|^BRXU%BR1CyfIDjsxJh-pCa@}_LomWSL7D9{i{ zsJtwE9e-^!6ukFYfwj2;;|=I9BlFwQi&vnNRR^(%U`Ok)xdPkoa;W9hP1Q}-#iU)x zr{#OLkWau`WY$2A)?lzq^5}QFPtobSG@W}sh<4|&XJ09cUsFwg9i%)|P2dNi0pc8E zVlfLT(0WFuo3+8FG|ipjds$BLvXf7ftQ;@Fhonk?3JM|dXq!RSwKKU)=K6Gx974=# zrYmbzq^?S+^=>n<8$coFS!OJ?Ro1$f_(MX z6owFM^ZsBkqg8jnrad6va@zWi4Hr~hjNVe8#r*|#k21VE=ccAX3}7>(G6a;v>7bt+ z6tHZmV^n?emOpt5+MKp7RHU)(_(f^WR%mLmd@qmL-j21H?i|^kZ6tS1m<%$CsYP=8 zwi0o+@-uUPf0sD(zP0nEe~k%&V()xxq%jdm00Xv%_pHpA3^P-8jgru`E&0q-nW_dp zj1^lgW*g3Y2Jlk_Bw$vAjam==V{t~kNFa|}p-{ZV(uAFiSPOE3h zKl_VFf01>5A?>C8E4$!HZ>*yYUx zOr4k`wHbfKvXIa>C#J*CSgTHMW^bAlomEtu-4cddw0LoMcZcFoG-xTM6xSb@0>R}& zihDwl;!Lg9zUj=M>$Z};=FCuJ>{{E({9CoLhr6|Z3lYH4?=fGZ-U+4A;# z^M3FYFF_1iC`u7>RYla6gj6*A6K?Vzt^9HNz%(4l+%NSyHi1!|)040K5$~^E;DUEC ziZ-E^gM#2Ww4>!(rJwA^Pp11F1SjL~xta@!*q;3VgsuQ(6OBg(ktkD}9di=|^ z$1Puqw^Tk{iE0XGsWj*!7}|fgkEL|88l~Ph|MOCCo|lwfH*}c0xv7JQXZcUca?DoG zy#vEzJ-tn#>ZkM2q_365#DriK*V_yKVqC#g<~$Dc1p6e;ebF= z|M;sOqpIb2j15H%5At*B{|8;aa7Le^;7I%;+;!&6G%k#K`1!Y~(G1uKY8%OR{_%`% zIN#x-ls2Q@|I?rXGfA24ho71u_mn9!{1)7P2!1Z)i~6?Pfw0z{4pQI$)}4=_ zdZdFFw2pb~8F$Yc^m20o6i0ZKM6IYLxz0de;@7nuwoJN%uYJz<8ENbmeXw`%!~&D; zZO3@`6#L?0E|=B)c}C*uGwS-D%|&ssW3VInCq<&`jsF^^l-?!0`#iDOz-RPBU$T6} z@?Fk<8~?nJNoAXS$TOaOlu#s&EXd?_R1PchI1@>5?S&M*A9Rm4{39iBM9f>4mJc_8 zn?&EpXkp7d8U*miE>?M^opVx^RjD{(UJpO~eZ^OCRUry#mwTk07pETaJBRUoE#LEG z(+Z`F9BRcK53QC5)V)R>C2VnJm)Cl;ojNVw{p3m=4cZKu*0va#BpgV~sbc&<{KkT@ zd?mxJAIAQp{}117B=3Dsky>n0@uCqxS5pEBXTRWpSKFd0mH@v*De5|Kd4hl6+bYJO zEg&O$0GqPYv0ha@({+`y=s2V-bRzu4UsFerN@*Pg6|l_xBJbaAiTOS`Wq}ZV=D_pg zN{~D*@fzbdgcSc|IM!?7lT=9@msgx@x-UH?aDqKev#!q;zrH>BLp&n-dV>?t&C^>& zoz7*I;>{36pr0}SEHoMRv^!)4R{FDs?XIiQz7TI_Yl5(9pGNmJ!B)WPdK7CcMdZ!e za~;=!0c3Cny0?zwz+2t6;XKqTRy!ArGtjW^8Lf-ZoMjmLG~>{NlwW3t2+Dm)IbBrE4tDb^;tLp1 zsdH~TPP;gcT?&S#RSBybGS->>69zD{oFSN62wX83hdy^R?cu%AQ~fnYR-q#ilW;66 zSP|PC{sZXU6JpFg__ha`4La?;#>7aG{;1lYUwR`J;Y&0F1vJ%NZWZYnqFnP4gO7YE zF2_A`h0HH}q!gV;7(+mS*#0JU-esASM|p({Y1CI4 zIc4-Yz3tkW`6WNSq;S4mZazjSi?XzMcyjP0fNNKG|DOXXh;9A5YPYl|4KzknLd^*) z>Mpbw9R@W4hJ+uI3nYdYMJDF}Y6bS~N1i(&Xv}0+A;=cPNkf0ZY{WUtDIAO+_6>g} zF7ij+Tmj>hBzb%Zyl*gg%IANCx;%ZY-YaLvIsmHDo6L1{##bNvHHB`|JJ6lq(f)(w z)4AOT`9iVwwrk9)!*>ISYq6?Al~CG&E@}_sdhbRcn!=xw>dqa~_xhpbAY zUl!P4NH5K7PRT&X3AA4t&C2IlV32st<(G{{ta?^Z(?{|7VS|i)?LMLjM_^P%DGP|X z%nJc8N;ln%P0stv<3-NS{>HNa`;>R}npfSyM{;zMAS4G*k>(Y|W_Xj=W1n)$hF+lt z_cNZ_#uL7#c0!4U%Q+#$@D_RsB#P~A{jiQ@Rj{740Z^{I6Durf|Ma$-i2Z>8_kbdI z3wjr!eFFW^Bd^%$?>)?T%3B%?p9*e2bl`FMG`ojnr9r8xg1q|H6qU!wt5{NaMijc( zyc+T+$MXeBQ2rtbxnY^*g8KIvcQ0ScM2^_SUjKAQ3{~yYrwhl!_LB(eF0n~jypEBA zrk8yXdlnoXBrVCe5JSy(^;76m*D7&H(zMp6AQMI)6hPQo631%6!0UAk%~lo|0+=6i zncgf!_Ip_c*23-ZV4NdbT^9~ckSl~;(X?U&izRYj?9&&LK1`BQ8gt=5ZD^>pVq(K* z-bwLGWvK=8V%I9Zu0&2zMw}9?2MZvMkwY;}d?K&+UIsnC0ikwWz4?^3l7RROriT3X6Y=G1D!8wO-=_h={pipB zYPuo3%+p;CbKe~wu~RRi1Lb*X8uu~@^civv{8!plb6DysrCV}c;E8JQa?{o?ZBPk;U_i_2>({E1Y+CD z;GwMD?kZ9H0|OUEeMX`HWsvI3y;fQ7I$2K-bnknsz@1w#VRZ|6^&`zNr)aNJlD!D_ zlnJ#1uJ%YKb&i{LDwsb>^2O-euRce|c)X8b#4hN9(7^rzM*qL%Q6I@YVyFO{~Hv7pb+IXUY6DqwYWb?sOyEicz1KwdjD zW_l~e2%mR58U|dgfBlsI`hy^Bb{3aL-kPi{giy)F zmq`U8E!kn<4?WtN+6t38nzV>Kr~Cj`VLoa!v=*{Hu+v^7)@uJ@175q*u*O5rkzXXqNW4y&^cb%-saO>>PcBLSh+Q0>*%7gKGl;Zac9D|PG=+8`)Z ztI0>Rf6Nc5v*%Nlq=V=BpQ9%jB3f|tz#)tIlePv8KRLoq0uA#q5EYom63RVVm>bI80&&XA$(jd#NGE85q+BG@ zYffJM&;k*j$S_L`g*m>aN1JTgw$9z{ri)g00Tz$6Bu28rTt81C85t*WnPG!6f2~b9!#=gk6iJJULCh3MPJ&$1&|nE7sH@ zAZq;ErCg&dGkgB>-C~B~DsH=6c8Zx0*H5b~rvQq;&JHu|+n7P$D#)r0znkWg5EyIV zloMo5#{bpQ%`Xpv856ykWgHxt>H9OD6JHadYf0W-cXIL!wAIBFG>>Lk6XZ^;HahlT2}&Nw4bD5?#lGyEB;+%*b>S9D#1%&BChbRZPhrAp#emfvbsA@ZR= za1YNLix$~%qonL8mp`5S9bD4q|H|7My}IHP(`_R&5jKUnLvKZm5Dt!G z6>1Xo)4WGiJcS~ys*Z624;GBAAtkHQ4bIpro0|jKB&JkPUxy`5 zL)e`Xfb-<|lQ)kKRy=DjQz^}v(%dc4tzgV5kzKTJgX8InBXpt$Id@M|VWaJpd(qC( z*{cXu@*pY^u#om$LNr_iKk#Vr?Y!!>Xquy|lr9!)YEDQaK}a@{0hE%JwaadNkN$d< z^`a$t+c=iMfJS}Sjtblj0r%XO^X759WHBT$3Rm6|-mO&SZ4Yd(d(_YLlGlGVocG3Q zUmlEK4}Ir6{D|R;7Qfl?W==rEzXS|TPU4Z1lRq7ey>Ps47(ZcDacqvgEJzI*Kd1nI zy<^e@-z_QE`%VpT*-kVvLh6lZeD*z3Kn@5+wr`@laSO?aegoSl%aIWIRj<-_`uZHs zL-A}Ww!*eW6gNch0)5ivCB$`Au0RfUweS_AD3+{s(49;OvyE(<4P zcH8sFnm;b~WT*c2dT5n}H#Yxs*$GO+%a1^G`4#_O4Tx1snf)Y;@3!$N1A}^L43~1; zQ`8)Rn<7Is!BJti%rAckgW)px7ay5auKrIVZH=AB!5>uozeb?xKtu^F=G@1>Z9;igku3&+B=lWqD2_g@?L zYwnqERsb*5G6q)5*G-;Pj#QO(xgPm%IOD!ZLW;ieh5ZSm;%1_wuYVjm$;O(Wl(b_c zm@TC|KKDR{3XX(b{nnTohSN!TU%8%mkm)7!)S3+~>O45s7hRk-4f?U&O-cA~;?s_cw zn@yk+ci&#P^qVk>eIRM6CV1DW_`8F-tG2&dMxY9*9XXR>d2i%F{d@DlgdRV~vr2F5 zR+r`0Q{O#bD7FMz9}IKXh;G3P$9-F%BvX-PzU6^#;Y9J9=k2Z8jd-}kv%$WM#X+-E z)aOelagGU5pl)2hxs~ZE)pfNauSnAjZ3H0q%Q*Dzs>Pe>El6o1YeX1tk(h&i7s}s# zJC*NWCbtw8k>fI-q;P)n#Cv*gT3^U<6qIq>2?v?2fL31=mA}=XUq>nJIF>>mYIqi; zFVQT=o>Ly%kaZUiM{_WoKKZ_6by$SwQ{psS*;bgqxw%a76FWv!TaNMoO{U2J9>6iu zaN64_P;Abdbj1goN7NgoSwz8`^qb9pqBeQzpM9C-VupKzDRaN$H6BT<$($~|5Qysa zIhKiPNSAYRjZ(?am6^fzm*@k&cF8P9pNmoDlG|;c3MZ@v90lIe4mHo;{f4Q%%&I5> zWeeO90_49vp?29z)emDP%=r1x2|%PG!@?`m#uU-xVM!e=Ly(J%J*2j$uH1npzvGfZ z(rz-*byQNHSBB`;9Nrb4Oj8_#1#wV=*Tg94o2ijNETb@lLt@QltO8jDE8{}fy)>mH zoLnnonMr>&<#cr(F>Ldso18TEy&hpx$L33SfuO6T_!|Ap(~(k8&3{SK0858Wx5}Q| zJA`U)<0$K$wreWl+w%SEfZ)St{mk8`5ZD><-4?Udz{~Ta*VB35!up$v>mX_hc z!9gq;XsN1$(*aM4pW$qmfrN(pg-Xh`>)!H7Z_d&KjokJ~NLh84hZfp9!WPeBF>XBlr+ z^jj0yz*GZKd@uM@J%Q=0bDes@r)(XKoaES_uh!XO(yE2i+?FP;@P_Hi7MA1aM<#*suVp; zhyeyh7Nat+sVDuwSTT{&~(iYM(Bfah&@VIo&pMYm?)^d>f(Y!&SB1h#m$W!9uM9N7V%1@veO&3Z_QXHR8G!`Gi-3`&MIf6-8W` z;MNeEra)v?Z_+^pd~@7=<->px43V**H*GW%;x=bGoc}cMsS^F;5Id~f#6H$BaoT_C zi6hrR>xn6ZL)CgISCJ6Q?9?p@Jzj$XzHsPmeo8KIs6#O%Lr7UFf;dD^?Y=uP2s&!y zZm{Y-vZ-=MvZy+l4@9Nv89tV~MDyN31~&v<5q;v7`C{S9?__E&CrhMr6(w9V9@?oW zx7-c1pf}yt#rV|g1q(U*Bg-tJlBJ&2SGxKJkN&|XFNKP~7+I|4#rnT=GG`yo8=W+A zEK34);5U~q)UsKxNbt&Ye1c5@2~-{bmXEYa&>Zh*5qWDk>a5>`u2nwyq1FreMk>-? z>Rs_}P^Qu5s`@Xcq?gsX+0SESQmt>BEpFD*DDzSHxJx%z{G1-*WhlMRS=~5%?E(BZ zq!S{)tG9k$N6qIM|Cn*LPJp&NYCx7>9litG1U(VuA6!3)SG%2hTVrg-B_55}dc_XN6l+uKqz>IFlBF!BrE{eH z0`SdgLABMubE5B&czuiOS&}sV-!WNZb?Pd!L)UKVWOSsRH5oqUHf5PK#GDJsD*x20 zG~kWyVw~SG&V=vBs^{;m*j1lNAsWE4o|2de=B6F7QYqwShaG?aVK1d~gQ|vK8f9s~ z{|x4evXI6;KPMT}dZtHeo<7~4VgwN7H6aJKTaDW^r!PM@%O718ghs-l`z1(vYWhxs zBGvlX>%G+2t?$?^4+Zvp>DmLQ|52ZR^y>@k^;E?7jz>fM9H}psa+CTg7y#NU&HL_} zf!osysMI~Q<*XCqsaxX-2{uEE zUh#ni=wNj+l_EuD!VySgvQw>c?5?$BKa&d1jgL?cbOdI%`+|q6$LhEfFdr<$;Cwq# z#b!j5!<2Q&K0grHk}IA9^Yms#^VfK%4kqU5Dz;F}GV|WjFWy_Iugw|R$g`Qo!K#%L z+ZHPkVmE2%r&U`fSSI>@%wfyiAKN^!J~t#N`Q1LTMg^WAbW?caOc6`TpZ8kv_BPCq zqEldFgl1P>bqO(ccU!Qxe_K@JJkON+vXcLR%}}{41Ojw^f{)WxGI>BVpT3NJF`Y2` z2nU&lZ+S5gA?m~=T)CUZmw7v-lJF5o_!0ugovAJk?VTM9OxgaYwRno zJ&g<}-$E1EUqmHzo_=*7-Yj=JGgZThXY&Wc$>S*S%~5trgJ)OD_LoK#>sVdb-Y@md zd32Abd|-}(zvV0MeVvi?;@RC9sfyZd5|LB}%YuR&+hWC0Qyg4VqcF#<)pCb+wJ1Uy z)^ut*oWq>Zr9sCO91}H+bCbgiQ{XkgVQ^EsT^0~ywvBl+UF}$I&>Ap& z%HVaOVfz1e%4N;eMsjwy4XL(Vs~!V2?fs991J)yqtblx3mov2g4i>`sTPim^#cOFpoZEpriW%qs%i6oW^@!E=;F?Pc1^F_6AM0IyX&I`zh$0Aay zDv=Cs-8Hya{>^ZcJeZTN;wT7bZg%SOjGqY`?m{oACQHLav0U=T(r@WXo~eZ5O&$;@ zbsfCZV3XvUQT1kM7P`IM!0QFKj+C{lD>Nho+5burNHo3+G5+`eQk@(2#P|P`vb^O2 zT|?rU;PsCB)%;~R>z<#)+;by>`HuP}>@|@3E|B^k?Ahs6|7Bh3DeP#qH7zD4=Ac&Y zM{TX3|9-N6MAltI*1yx|R#@NDllbN3Xi(!+Bn)#~mMcm+;fU!QL;6XJX=RN5_W zsx4nHTeTO*FFAo!BwhU;17AdiVjftr<`oi+Qr90=FfUFP3YK(W@37Aem40iR<(~B) z<2;8vTH7B%*@#%!(RIBnSAX6^^0InHPdiS$`qhdoFY=cXwuV;|2MlT|s6)tTk37#q z@3gjDI&3-E&w#(vxCpFNY{jMNV>{~vVP+3ZM%PHep-yUNK4VhSi%eLOZU0EGLvDMr z_Pox`6S%%DwrDcuKKwL^neR*$;5-Q)P-x|pf3H;VZ+3XMr+f3+1ylO#)Y>}nGITU5rDw(EAJG(MozSi@(R!6@$uN%u6^<)%24 ze@mzI%jAKQL2X%Xr=3c*JeX3gA}!DTvR&Dc_^nln!spe$dtH6F3 z0NF2pRRj8(23Pzu#4iltfl#ExJ;%KjfLq;AZ)O&`?XilQKXbSy!#CY&;6y_*#5 z_k$B1EZ(uh7@nq~bh8q*P)QAH<`UUhl#j$<28x}Nu;+NAmiCr!x$4{nZUOmR#;S#M=f!Pv9-SSeZZ z=lYz==r|QZL!KNzfKmrLx+z|IQ(2du5@ntM;{9tr+3NQ}QW{|_cHTfc&GNJ@!kC%VCR!G&NJbGRu>p)HfnMmjzx%wB78bSjS(yGEhw=tn?$h|>$NryDht`$dHW ze312@s};p_cUJrIvp<{`I0~7IhqDIs)Cx&AP~e8xkk4Qd%`Y*0bWrJq>J76qC+@Ns zwJxWcTOs-JRoK!Sa=#oldD;?TyTjpz27`5ZTGtNhluPke~P-tWyn@0y&E zA0M<*n%6X{mP#p^(g@0*P>&|K6Itm5Y*{0m6e!Zfq4_AguJ_9YD;GxdOJ*#9kgXW5 z{UqbxZ-u7I;Weq3K6~K`pUq|h0%qQP4$|ri7t@OT8|5eTSM0Tr@wvNl^uSiQ2OS*)s_4s;M9Gl3B3!7)q>f&DWo+QKR&_~yg~?|hx4N}aU$Fj~*?Yvp+FXwkQ70MC;7?pjrl zXW~PIy5c+F7&pe?K&E9?^a6LWh-rkXGjkP zm6~xMTq#eLj!GB%oVSSu-X`$gkuL!5T$P+6t`MbSy{_PiA;p!mZidpf&%DHc z_7$nix5zxN%^QPvU76+p0!Lj#=<00mx0jbiLB(e^W$&kl2hq7Q!_BP$sQAsi`Lf5F z-ygRBAHvXqACIT7tciY`*xj9-hQqSvySCFu$^U1hys4_oUn+e$%`vC;6V3Z#o!2{& zsl2vucXoE>mzNnpc<{2m4|wXkj{?rQT{gPWBrg);3_PaJfL9OrwYf(2w9%Nc@q%e_ zjYzN@FPBo1CU3F#D0hTgddXnt8CCWm$XL)f7ik4S;%BJW*RudBT~DP1 zDXojTYuLl-r@-y!d46u%V8+4-N+a1ZSnTkrOHAhserzdts|)@M#;y7U? zA4CA8SgmjFk3A8q8^}Ro1oB1`&LDoUIdUZLM;1f0LdWJ4;AJ!`dZvpm>nOF=rOpfU1(dt1n^eOCb}yClx&i>RYH@>Zzh9TutR9xBJHZD`(=We9m{TYp z_gfB^_FHb7;~SBCv!1cw55gnQ@O`ZJwMvDu@I6V843!jto*m?#UMB7FbR0UxC4a(J zQ3K~ys^H^##?6M+@BLmH%>&Je%eNmUiel&}d_rfCOK*MetKv!DbFJe{nniUsI-hsa0 zF(>Ou1Y116v1dNx4Jax#?XwTZ6k-B9a}_g!^cVH&;|bJeTQpdN)DBJs&}NGqWiNo zLmsQmVR8P%9i*1MlR4Tpn;%guaeMMZz}X(U@O(UM%B#NRu5SXM5msyE8z$vWys$Y- z5n(m-nEzGI_Z^>{H<+Yyx%2D4kU3Jx`Y5au--;s|@IE+oE#w!0&jI{i3?y$=p3*+v z89SR)GHgv%Lh~bjm@*ZOrk&3xkDD8RKQ*26dlxVDT;7lEk3VUwfU-0(@)II)2yaHV zn6ylPHIAXx%ti+!?Y?zMC?x#S^$>%kr;L)MNvwo_=AZ*N8^Wvl|6hBhUN5D_Qu(d! z^x=8y`H2TCtyrhrWoMYQio^W%h_y)m;hI=@&l_=R*{uxHAP z$#d-oNN!k_QG#Ys{&D_5(HW8J9aN!f+s##@#*b@S9AEz9cr5L}$$<8YA?Hi+7oya2 zvMT?M{d&YAr;(F{LuX7IQo?)1?CJZ`=)F*x$5pI3%v-^o_|8OD|VI{ok z0VHm_Ocny)4WvVxe;Xdbr9d&o*1u{=80~@&^bDieC^^!9upgkKLK|+u8P(^OWAXY7 zs`LTy88rfY`^oDk2l4pI((hb+yHmF#hKqL;q&PeFtz0*+4msz3P6q|hyN+QkYPx@yqat#Geu{; z7!F^QdE;n@nELV z^;HsGmCs4BZNgh)$j?B$F>Tzk>4dP%zEU`>dh$EX#}O`!_jl(gJAt=maOm(WFqW*~ zHa#*}qE1#Ovs1Grx&kgCfF@ctm{WVXCOdC)+zdz6!oE(rp;Y`?QuJ-|`|`uuZaKN8 zPeuXDqE+p|GPADIsnw8G-4h4uGB-yqmneVUH7S5yfGTrVRLX ztwePv6bV0!s~b>V|2dPCYqeb0UPyZVC*7{c0k}wZQh4K4pVCG`jr-bwYwe@o<|#gs z(id>@uXuN2sE@aqy8X!KozHs8k`+7RTB?Y+L*q7ZJ0kb10? z?@wzOyY4823=XA09F5(toi#njvh6y1NLU*Fws{p_8d>pfdzh)_5k6dg_vj<_)c_tyM0YI=n6t z)+IoOCjm!G^#G2YgIxmrX%b4f?-CHXmVv81;#?N3I|+DX20@f!w3XLyAxa(n77By zF=>iEf{JcG2CN{bCFJPt-5E=fH-5w4Q%4R|&$^lf?Dn=FS#Or{Ne=E{CAGrxF`*RA zyKfuL@LX;V#|>%d1e?}U-+PtdtBUUj$TfcU)bz(XMLeYfiL(}8GvaZM@|5{AJ-QHs zlWOp-OQLCo{zD&;AKD#Ivakfv3;spvK{7{LtL+)iq{eqhBIF?@^Yq$M*yA=Ma!+`- zjYO>oNEpH7T#gw~qR2M=3LcmlsvkciFrUArwr&^qFhW!Jk6YVxGFZJ7NqZ7?9dZc) zi{)P;Hu-oYWkQ0pZzU(( zP#u*4)Px^@guF}FBGICnin;{3ax5>=QxdQ8UKza)kio|YJ7vr!rouOSyYL3T<&q%- z_0!boqtyhY^-;?C-yaeNP~{j91V>4gq|U73yH0cNhF_ys8iF!C$xdEb1|9*pCJ%Tw zk05g8=n0EMWhN;*aI98hO-O(U+nO zQ?vJ)ySJbC)Qj9Uq>LS^WFl@BzVIvt_8c>WQ3pfE;thNvMypJ?S{2S8rWiDQ$>HxV z#kFu>`~|lkqZc>>OvYM6936R{YJn`Pm$6q5i(6Roesxyh`Mla+_VEv<4-3YHcZ-Ee z)Q>DHanCkYhC>W-RDotct{#+j@{_o{$CD&Cm@LqRo>->yG@2!*_qx?Cm8W3(34yED zB>A9?(fP?E9ZRT`12&cIrBdllzOI<5?@e;*aWE6YneSk{^AY6!|A`9%p!do5cur~c zn%VFnjKqF6_@~yVXr&Wx3V0p={rx*!Eu?EIiXMVPi6lhY~J( zN2qF8s?_{CW;UtLSzGeUrX$=tw1#(x-`3dgtc}eunmLO7Rtr}(q5050dP&PMxOB#y zTU)x0y3;@cJx?3evya{mIQ^yLSHkS%uoE|iDLqusv%@H9Mv8w}!@u>E|cmL}oF7zU2*19;q&`k+D8X%eY0}B$`g^C00aZ(CiG>z`)Z|=?c|2EKCu|2~p;Kci!oLhrnvtvJM?4D;tq?tX+Iyx|S(dP@xXCO?Kl zbKx>m?hLuQLGy&FiRml9z@8bbtpYG(lJ zF>}_N#`$)FB$#kbe#xBfr`w*r#8_yJAhhHLMgXh7vQ^)NSuTc{MYf%xF`K4mbm`)_ z{zIGhD(Bxf7TMkCER;RE*D)Lk7lSnq`S9ckUM=cEYJ$~;GbT<<&=iXEHD2Dk%r(P% z%GfuDFaWt##A3-b*~IOhBv*dFl4x*_8lK~(HG_-^%V&S4hgGNPCRzY}}dYJxi!On=2aQYf@wS z=J2ssAUeTH3v+~&F!X!}DZ@baC?hqz9^|z+mccvl9hu48Le%Y|+Y?t1d~t1LX&wsE z{?^>NCG|v6lHQBW-SIK3Q&lNa@H1e}^GKxBKwN$Leu|%)SMm{ar(c3=e(%Y3KBl;T z^|^lqbz-1EMIX-k1Dm>u1`|Dht?4Z!>lSj}eueEm+(ozN*oWt#+(u+0Uxl)!RkfG|hAx6zaUBQ5D*vC3b z%d72IN}n6Shf`kb9MxWP^!;4!m$w5uOwXrx7#6@$d8a2Lk$d&aBsHJc&f4T$C#mIT z;8k(*xEX>?XuOHA&R*+nSbWAUpWiWmw1zJw)Pg57Q7~-91*aG_n=^uh6L8GzKqg2! z?}dBp+ypY{gkU*qlWMPgX+Zze3a02%e_8rRxaZqdOVDiGn*Xhs(4LcmrtQkI{Pg{T z$AW;VEygr@-b9L7U6_Cxyp*qzWRK!JjIPUrIlL?1PSqY6XCmKf&9EP){1JoYxFlV0 zo;&)lSvJnGECrr~3s5CBu*^OT&jd^iC83q;8?Na}m}sw0>ZcUG0$4kx<@A?gGCw!q zT=Tt7!Z}Ip%ljgl*QeLP=}z!A#isoYH|b6f5SQ+YZ72~ZDAC|f>b0)b-zdzxg!6F` zPA;2{wMMskH&J9qp4u<#Sq%_H>r3VQJx@U7hF0Bt!uZAe3%$!uc6jH2vmAGXDP_cM zhgoYF{FzQnGQh+H7?;OB4dEwFH8S*gP5iAd;fB-_y?`Y|dUGIBU@U4l=W)mmrh0t0 z68A!*8fx!*Bg}iLf(@=VDb(`*y&Ek^iLT!+5H>Od{{s)Zce;n}J!sDYo77@xtDbUJ zYq*fsTa&&+f+;j6?g~vL=U|iB+5C|*@Oq05Bt&wj-SG%8%jzWRwt@ep*tUpKQ< z-MC}%aU!dN_gC(KH^F}=pS@6nWf0BZF^KRk))EG--Pj3`IdApjQu!QJ9-NjLHupBV z?%p+KJ&ODv?ec#p1b!Va)mPWm^&T9sE!8{qkpQwu{~0v9$4nJ!paz8FXjKZejad-=H2od{i{`2F^lp!v(%pv)Cm^d?hL^YP8aVX4?%jRLnsj-bed zaB_wf)!3hrp>Z=5XvyEpCYFWEs}`evzot z9BE43(z@6u;HSW2V31+afiLXBLJ`b^nM&cnGr{;bWDK3)XRDJ|>lj?Xk5;r1 z5v(q?JM?~2rPiEJPR_9t`mz&xd0;KCcX(^wlB=w*TZKSQzW2K@9?Bhm)I_|`4SY6` zh-n2QRBF|Tp(d+$&b;PDCqiv=C6>niYl@f*nS+J5+!I=Pi}FkOUt@fK(5^DP4FnBv zQ_Aa%(d*&}qD<^3{d0c9<~XzcbMkE^eOa`L>wlEyg?IjJ!oNIWe(m|<9tt|~F<6lE z_h|(Bl3ETp8CU@~7lD-66RxjR5P$%#s-733S@L@0x~Eyd+}7LhO}?H}`d0#u4oM;X zWQLDsT3%WtC(}F!<62t)We~W@anO-s=4);6F(X5(@iVW>)9w;OC`iO$et!8o$j*P`6F4-y&rG85%S0bMW&RLRRV0@_4;yQ;4P1%0e6a+MriCr_z_K451_CK+t*=5I`CGUX6@% z^4d1N&J^(aZ?&257l#Q`nrah0S2^~?I-_q~OD+ouCJH7>@Zl;9%sySr`qNq{G(#O# z`#*DYL~X_)zNDn2J9c2Z{45G~7v;N-Vf?QUcqsHb>p*3V41zLixZItYR&mg)X>l2~ z^e4AnF(xG^QxXp75fKr+Pe4a%*v<6muZk94^97&-7M&(MG$6b(qt?Mfsb`x2Y|N0%F>R8B z=v?a!B=ny%iGG##*7P$?>IP1*7LtY@Mo_}WOwFA>5|Q<3|{lPyYk|Kmfm!HUyI`m>&KmPtwG>i>s2P^}!N1WEx9` zZZvJ(B6=>~KYxlEpoA7q^pc)RAw+V2&ukRp(mo$%Rxyrc%5Yv|bMZ zNe9sFIlq!qUvr5Vri1D9ki>z_E{bonjGL>AFI!mWm6LX%+lOL;PDj-g&kZRS9rg3X z(|~`Hbb82Ofglp~x+gCI-P;Gt>JO)27RZ+O(3@YxOxF3v{u0zAq}n4(Gfa`7N!qv% zdcBEk-0UhK8FYH+aFz7l_rktM$+qnyom*u5xqm@28J8MkCFykN&M!ElW6jVML{buC z$a+0gCuN$EmlmU7rLx_1!;v(@W|^B#YTJLZji~3>nJBxzx7akL+wG$LJ|?-dvBEa% zk>!2TP7kr8K*$=tmuQM7Tg)7;*Zfroe*(P)dLR7HF>~9{d_;Ed2k0Dn!X-|bgziJ% zhK#S#dGMq3-t~Rxi=Sfp_20pcH;_F?=zaVzVLtq)+4$7|7xE26Qm;7|CnYe33Isc*0NofG0|5{OIEbW3Q4ERCmS8hv#(Pg8nGp`@S(dC&I2;OvDcM#ip2L5VB`f?W zgLd$RB#MJT5+VhF1OZ}3qtT6?s;8RA9Pf0_Uhj{6?m2t!bF#XItnQ|sGXm)Ds?5Ci zp1t?lYklim-v?<6=ocDhigY@asB*32Edl#A?tM0P&KvT8ie2JK#EOuNC)nkqv{w!z z?F31Bw}1C19TFLn&Mc6Q*BpQAs~EEm8m(55g*nXp96EP{@r5hsV9EwC;nZ=%Me9aH zl44}b6`;l>uyKvyzx&_8D(TEzCCHm7m>II?zsBIo>)0!2ohM$ag-PbImtJQ3*Z$vV zHX%vf{*q1)d*c#=fA_zm+nbpFY^C#5HUq1Jn(UBZYHks0F|&PItBZe_y-R32MMs$% zJ2z2GQ$^Gu?KZt$m#ovp!V34@i@Q?$SQc3B3Hr*o#k->IgHt zh>l0t=e|I;eVO#YgQ$O6?3FX*uY4Ob8IjB_6**v&R-||h|9Vp;ZaVB--@0I7a=~`G zbQf2h=21k@nBo~bv4Kj!Bt{^2`gi|pFc@&-#tpjNF0-?(}}9U;p(I>;QQ9 z;fFbP>=>W@>}NT3>J&$h9tGeFU-$xF`qG#9gk94j7m=AB^jd{x!46E4hRv-t>bloOh;6fWYSnmupCkzvFQs(5UFPQJ z$tPLEyie4=o{E24*1FbBzPC-ZitvNR351L{n451iI(irxZr$D8D+YV;AW3^fXZ=OA zn8yx_TB(%xwW)XS^^uwYrP_fL?{d?+5Ltv~RKjZE^Gwo|;b4fWGQTiSo@E4cPPMge z@Xxvlqoq;d9~#|KplR}_0Uen3KeGY4a3ATh2U*&?2qS+_aJSv1J=Y?c>7u=bPz>0c z&Co^#|2GC6f<%Z=3^lfh4QW$e(F-?yzQ!1a!y%*5n7R46(h)=AZ03#LYYEWZT;#FJ zsI_@r8;e|N5QC0hyRc@RlWUCk%wrdiAmgn&OLCJI(%z5mJ*#MGZLkzFE9-BxOI z=8bJo-5GyWQq=-5aXLU!o8!{vQ8}8|E~GtIv9AJ3cX+>Q!KB#5BeV`3L+AG+eVe1LDLyuat&6CRX&=0w^y>4FjW7bOG-ZBv z4w-S|YdUdS4QY}x*PlU+b)us_pr#6K13j0-cRGI^+H-U6&!&QqvCyQj!@OPtO>zpm zcIN5s-;X_T02yuV>XX;@4CaQ?I=h5y+v0vU!F?T^hbBNhPFAPZhGhcp#bE0g7c3ni znOlbOfbNO+(S6{fMO({_Hq3tD&tbRDA`45%c#Fxm{x$6+LHd2{%U@yg@;7Ond>@Oa z-;IBL5Oeh%_&CV%ixXs@58v-f}#ij9wV;K(B3UecYxY-0T- zKLG`>6EyA7+q0M1g9n}X>@EW)+MOXCK18zhGG=hO5XWxrDAk09Rl^wX<0?%Z3?qUl46cN{i$zOjCV+`$1p`{^Rbg)6baRo66o&HRt`&RUHt4%Vs*X<^lZim)^ zRa$!%+-J`%w05FD6yx6W`{^Axi0ywZ)fgtX6R(UpLhIr|%xJAq%zQ_H;Ei(Xruv}? zdGO}HY_^GBzrpOx3{zb_@(exuZL(Lt?lS+hO?PI2UcXPT-zU#9bg~Y^Ys~ihr7)-F zIrj34OfEcAI*#>b=3Raxer>7^bwG0sQJ#g!G@>Se?R{h!LT}GL`bST=G1h-5ceU2m z^iX3=A-(;$=zj6}^XK`U-}xQp=jVC+@yD5+on>QVgXf-mj=%r+|2`l5;0O7spZY0O zl>-M3@RL9Jll6d>5&)n6^rwIMTYu|s@z4MHKWAlSg^i63KJ%H+aQ^&x{=q-^2R!u9 zLktFkH+a7O%H+fHkgfEczkyYf0MpZ^6Fm_(*!unvEvchXzYJx)$capNxEov ziKMgOx=*owYf;xUCJs?}^gNS`H3{8|;)auW>!sFuognv`CF(fcN5R@zH&3gI=9WC4 zGFEg4T3zJc5^w{f^%oEu=Sbe3ikfBA@f>fsI>N;OGZ`}8`!JKmV=&mNE@G2l&VL`f ze#PPQdG0Ytte4a6pdo+Lus*@{81LJ-_6@AXqRZTR4mANYqH<3vkA?-S7OR%r+9=6s z5K+;FCM#}FO!u6%+DIh18DpqC_qMsoxfA#mGSG6k_A>eQ4f44|cYNm5v`O0Y9GsoXLL;Q>!NMC5*GRTzr~n zTMa?g>F>>RH|jHgh+I?bc(f}q?Y04v#EoC2)*@D&t@bTweuO$tzLUkY?VUnrmdW#9 zfbabd(w@P*<3~sy`XPAzyVy%FU^GV&H`Y_wd1Eb!IDLye&x@Qw z(jo>IKc8D24yIN!qk3*t0J!!4Gb9CBp zZCH1FXEKck?Bdv4(adbzYiyWd_4Bw=AeWuVP@;fl0yd6oww z+9C}gm(3vUlF#jDVihK1XO(^@cg|>xN&A@j190JLAw$qGp-|?$^*=8inmnQV9VN7C z%&31VIdYFVfixkv{+<+Q_o>{<1!UxM>f9D z%T0R?4GcAno}5ne<+MlETVyhx+;Ps3-ce{2VPpbzq6Krj5v48)5{>oqZE3AL5t?_sN?%(AXfAJRqc;bmC_@!U^CHC*% zUm`o(+uPi@af7ur7YNcc<*%$-N%3NU;G!m_r33R znjSj{!`>~;Q1XmqwBeNGQ763TFIpU1d<(RAF}u5e!X#bdb@N?&q_WJ5M^Az`7f+6O0GE0lIf>t|AGEar9G(!*Q}YrIg)RwLU@AG8T+6`@{; zHqUhjNMv;o%0#_Ua8QUYp`VBm`Fx##}+3&mTb3_O6Tz+`gWMmMoL$ z!_bCKBRR`NaPLMTj78HX($9@mW*n3euK}dPDfzsaCL`TB{zSgQrPnr`asj7 zwsh%;G%%*IC1&*0Y|QKG{iO@na1A~8RP|S*P1tjSXm>cR0(@)-Docco6ECr%28Y2nt9jOF`r;(maz+m&?K!+PwgIW zU@v;>>KmL@XHURR-F`->8G)Ig48d%nW&kDwu~=hiEnfk0^8O;4C!i^4f|4M%kJ=eD z?}D~~7Gk?ao@wg`+82M<^kcB!Ptba|Rf{57TOH?CwLJ+~p}PPxy8mzW(e9j!TWWF6 zX_16ugelUsYhp3R%6YL+-VUtButuoo2H`lD zFFCGtu7+0-BWdY?8R#e8&N^BPNsD~>1ZmR6XvokHHKQV+MWBDRXOVPij>&~PGG#bQ#xATPZ5JaYKJ5&zRQGmIvXjb zp{VtI?zI3DG%pJzjf9IL=-O>?n-?#d1ZW~&CqC%t7upj(Dqo7~c&gpy88j&}SVJy6 z4flQ29d>`c^8!Nh5q5Sj+0hTsz5F~X29-1rFY-HD0pQ_{K?EHc|Cx9O;97u3LSz#i zu^z%@_kGgU^ZE`i2k|0M%^hM|*eL;;;**6X-bk@FiB>JMdZ(`;-ue11{-4_nyL<|r z*%JtKO@TwReH9rOZYCPL)4)!%%E5?s9Q;Ki$K8J@;6|6AXeCCdH9C%`X%nwql>1li zT9HOm&_(rJ3yA#R<9!fZRDK{2QI6WUm%kT_WKv4-MjN|JKA@+784rHTcS72o0ySqhhAyM4%&N2yVI__T32=xm-tCTc;i7Jrtx8@nr z>R=xF6f7Mf``TyV{7bNS09iWZeroe7x_JeLH;{b~VU9gc_SMfIb9*rl|1i>2Acxg~d<+s_BwJ*lmJ0JsHr zg2yV6>3C?+48cFJmBWQ-&}9ogptY{+Rys9IknsQ=tfAQuoeZEmkA3lv(D9J;(H|#y z_fNY`-R`mdz2C<^_xp6Sk+WOwEg+L^tj&;x14!SE`^e$}WZ^(@M+wrKN6-8*_UwOm z9lJ&9XU_-g!UjYIG&hP`q7CATiY6(xGxvsUsk>T7tK>6#u}jA>>u15V8%J|XP@$0> zWDre&6qO7yBQWb|dJ#>pf=o&aa#f3n`=8T7Q`88iweG-=q(TFVr_CXeoNq$`9~XZSX0lDbdOvpmBY|z}Zsp6k&1=mfyaR^Pm>;``nK%^6_VB(Ycas$t&O$hxnf!g ztpls1D+`!z7fFq02R_YXqVce(!zgOec9(qRQ~?m?cb*T}+_C)@4iyPb2KzibQ+^#3jL~~_ zT09jg5lAcf7@b){myXu!n|sYL0cf||yz5=>+VStVx3?LMMx}tOF@{s8PI3D5>5w@& z7%(m@@FtT9?|kPw%YUB&E5qTCJ$v?W;J|^XIhwP*y^XcDj@aELdMNj{(1Eg)^L8@yUhH8Int#Ny!NMRo!uc( zaXhsExAnx)XF*6bj95=LD}ru-xJt|kuOoKii=}zpzz`%6;`Y?!#D}r-2aw5jz1|rQ zieg&ojH83 zif+RSKCq+=6C;)BMH-75hzGERIxoK9v-pdr6&oz*_LiU3fve;LSFk2+m#E)vyt9s~ zs4FLnPDO@F>UH`W=BiZ#Cjj+39MeyvVKVR6iZ$`OfL0PRjbh4ZP-6O^l~!n_Xe1a| zC%iOh$rQ2NX4rprk9_Zg(3!ecM!kBM*8B27TMe}tJg!{KK$Ik@0$^tbCfnrS{x#PT z9S&p~>0Cl=2Ez^Vr+(cvHcaAJ zWaVpi(2ajfNT(lYGX>|uzsG3O_3~6Y(fTMxa7SCm5b7-4)fst17nkuicKJBj@ek4Y z#=k(@?GV_mH55D+rfnmdI`&BG2AZCOWDUqsGe*rOnCgU{;)$6AWtXDzz-0d!^s$+Np#zv5E1-C2^P zU<7|j5^o?FN$ql0uUJ>V znTrGs8}(fZ)nlz_nE$GG!DwzF%OFWeW_z^vERpm&nAskt+i~laxlwIuv6*IlylH-x zbX+}k3q|-F$2tRP2W@rBCXMd&^R@BzC=Y)SA|NG<*MVtAOexw?Z!w-g&=5-t$k!1g zi?DepWrL7#jMd8rEB3iG3Stwpi33>guetUa+$4z&;m+mcp8G~daWN^KHcxrOjUJ()LI7lNCMWLWb%l&^J z$Lu+Yv^wZ;4SVis?Calg$zYx%dyZp{z8gup(CT7DIP}g9T7xU(m!5&`%Y}-!_m=X^ zxl`=BA9LdU(4Ik(6uWi-`^s0*>t~_eY3{bh;EpzQF*G8`i4(6gE_`SMX0tOskgnJ2LmXD2M}AW$_a!AO&hvG)*E zwb>1aNDrWiz7-=E*$A>BB1utHSw|~xbzPB>O`Ow;Di}eBBkXvHc2n0KZ_Izl3ZPLP z^?%wqkXFx$q)IrS7LT~qE~p5Y^XL49kd_!1B2q_?@UJ=2TpK0|L2 zT|JFnde+4plQi$n1}2;M$xwX!nwU8|tZTCfu++M#qRrx(CAj3vn;?Oa#J{-M8n)XAV~`*L-OzZ8_cy=;ov(l zhu(<}H?Yrr9{c*Y(ZL$hokcHxpZsgTLUR8{Ne;XNCIjp%UuE#!e}`FnjkGrp<1O^^ zi|AmzO6(P+-9xXxhW-BUqZghnM#j<*Jo5lTf8?PF>_$9*6A&!gU3PzW!JUku-O6(} zDYn1jl32CHm|DG&DH?XgDl=c9p`?1l0wx%Hl@ul;?1g9CS#S4>S^ZhCIrjDMl>5`P zTIB2Nt})W;z-Wj)`)yYMwfo3m4ZC)}+*84Lgj$#Mw`a;?KDg{^EK6-HyrzzS^^w^q zZzx2SwL8}^Tf2)uq|JYzJ4?QDA9m>kvU#Ccw8S?S_EH6dXveWd(kqZ&M9c(D9HT^J z=oCW=RtUCJh!R#Puhwp7Q|xb3#q9E*plT|`60Pz_#UjadtQ3qRZK3H^BwNC23$i`P zdb#QA<;sxKO7H?K?f<% z_{{~+n{~kgMuz|NYhzXcX`x_%>CNp-eXu|xE5;bCZ(_yaGe-)$`lh@rYUXKFV^l}Z zk{x*hJAZITfzexU7Q5%2ubjeMdl}ifike<+Vla-^{&UpK;xtDR(&YuzT1>x7zBNE6 z6Y|Xg`T7=QwgP{or|grRRDiuvY7G*h9gGfwW{VRUb^2tE1(D45N#8k`5^R=8|r+j}d8tn~7@zvD?ojx+!x?^BC z^EGk_SHp6Gy!@ z`|d{$zYFpSdht1Qa22!XK9UDN>3+UY_nq0NaOrvU>I(&vqZK06;{j&>{iN^tv#@du zUBBc;;yZsc=%wf3>KULDbcdP@38Z#lJ;Ag9SW(1CS+wpHdTwVeCC?yflOK45*2`Z) zZ@g9{TP76rj62z0N3zCF@Y&Hjf8U)AOJX_`CP&Q3cmY6~VqR4K+{vl1iaqJf20 zFdpcy%?<^UMgW~g;}l_gLmjY|cF9hB2ua)MxG8^`5;Py7HismnJNkO)+EBRF+WJiw z9v&m0?D*^)QMF(~pca|k*0!)IN@Ae+CZL~G+a<+&=sNk2gg z_l|#iNrMd5Fxh}y7HjeDmd{%5G*BidK1}<@tH{PBv@;jbox|ha)H2huI}`{@Yh5S6 zzx*n)mj-MPnNmJ?NLYNGKk)$)pSrvQP+Aka_6zYOh1tE>#UqZgd>8c1;L^X%!b7LS z<6^K2hq385Nrt%t#-k*u7PkX@$z#nGIyZlM?KQI3zJu&Jfmu0^y$+K$;A`s6?A%`WUT+c5x+O+}U-YGIWd4BD6I5Fha1=jrosNGA zK}6fGa)7C}N#nSr`ru#$w2A{rYP54PNO#W5iYx0+YiGH z%u$cISFxBX#+=4?tb}6F(g2`V44%dC9PV~*CxVQ&(Dp3j`#wthyZ_2{Zj(qGY6^fb zf!0OGBuQUKJ1;w}5ls+ngU-}|-!Ol-Q}4`$XE07yl0M zsQq#?3qw!utRXMh(MZx~^m-LzlW$77x8s#)a`)4)vF1XfgnT$cN0ab|DpB%CN26e~R9ZM15cf3doJcFh%=VCWS^zVKba{c+ z>LQXPXr7~!44Y4i$M1nyBDH@JulRl{84cM0JAa()@Z-R4$UgvfjCN+p4?IHp`~|Ri zbZ9 zSc@bnX7xUjhkh6?zr^J8{}X!oMa)B=ApPiHCVk|`$+rGK*lVx4juDVQ^Y5@vf0o1u zXI?wU+)ST+tIJGUolr=0GQ`ZSkUsLKVC5Lu@Bbt0t6zg`jLfb&i@nZVxbwpruxcum z6ekJU0X6GUsfjA?&Vqlq-Vw`0!_y@f^inD z>ly|Zre`zUcpjt9yfn;p)8KsL7uphx8>*K;)Nf>IO5NhfR|tIOi$|F3e++50U57nx z`-=mwMDs{PVuz%q7PG>(m+Zt+3M>?3s;bB60W`~y`BjofeguCx{sBm!c4CXMBfE42o!x`k zz8Zj|G3Hfk_5^>zVd2Ht1Tr>B-b@SHvXj?P;Kuqqb-J^Lu24Jep*W$KeoeN~+5Kck z-v>$SuGuAbeMc5SC!ae&ns!iMtjtT2!~?TKJ(sxaSqO}_ddN~A##`iPzw0!L=JwY1 zn)Fvtwb%>Kx?XvIkwjaF7$*dqc98kKA!tUCJf}UF?}mS@3-y4)*cvq6KaF5Xv0EiU z=k}rPej!dRyPLzPvvAhA{g8A}HXFw3y|WzXWL1f%PcxqC6Zwb1AJ-;gsszHMe)w$C zcq#tO7JLH@>b`Kqt1h4DGsDyaXX|Zd2@pA{57XZxPya$YgNaIm7Mg zm`u=ipL~DcL+FL4kW0@xEgw@@TqB6dKsM0U8g!oma~0Jdymhe20=V;tkk?;BcZjqYSU+_ z4sHe9)`baUovucm%)r0IPp-q!_pssQHCv~wR~2;bfQ$QCwj)?_TRJA-v>j&mLGrv4 zxHcvVFVeVfNMsx^jWd%Row!Cr((lnbHB;V4`Q{dr%Qwi^x6mv{rdo%p?%tT{%lTu| zM%;gUDsr5ui?J9}2rv70R-g91Ws=3&@^?=`5*<%Mu(-zlZy5W)7fbbWvwT9{UuClI zVazQ!72QhBEOvr+X2}jdO8U|l9eY}u-(E0o60?4#frTMblOhP*qtLo5XA`*Zu?;KP zJl7<)Vm*+u&W883F{|cq*zgXd5T>p@_}YIb4Q^)T+m~oGym&_AZSo^eVD~A; z1~ojtDj4b;%|kR=?bZLf2)Owe>CS(VJn)0a@%NK|^Iy6#v+>Y%vo&{}Z4s;_B!hMG z@BI#X@ma>wCd)GVEm!nO(yAWJcz{_tLh}Cq2<^_1f9aoNU-(1J(f5#k;6EmP*H1A% z|2=1snj|&uMmHK5_}KY_Xwok4hI@YjW=Ubustefc0U29;OCT6rEpV)9S)Yf{S{G5`D<&E#6cNbAXm<&_c+_bx z-SaahNHziyCdWTad+i*uc?nF*Jy98>?Q_t18f07m6Z7@yNA(#b{`r6OW6x9qKF$iX zu^315&=E8b?A-PHiB6v^k^fA*es+9-pEU~(L>odPVekaUB`($CgH%MYPI0rUjnT zth+!1+u1MX1NNY={Z@bNp7^pWzsF{f_Q_5>iS`zde7t)LmQB$4{n-98$@W!LI#Gk6 zIU&;~qlq{KSqtOJ?a6f7bPn(Hl8GXYWEQ(U#E!<;%t;ZDJK!a^IY}!;T5U+&NRMf? zFf$!Yt391C47!V&Wi@xfTJb_nRiVL=E$WIYkZ0Kb5_WFYvE_eu?b4rWRJO76`$(=1 zT&*~5hQ*AS*t1h&21m&9jXzl62pVhr)DV*CacCI9FTf9|t`z^{g&~J8Vknl6w6dWKU@d zc}9Nb%jBC89*y*xvbLTh1r4K6*0dFYdvG(}&#fE{f+odyjx zqpcWZe!rtGUwsktjvqmmkHUCJ{_O8M)=FnKbYO|}65dF0PI@%yP z@qWz7C$ZJyc=)3_9|R@9&5T}nMLR4E7y@}LToM4>LD|G zurGeejjn%T(JL=u&wmed;{BMV!|08(?jkF?8*wsNJ3zILt(1uQj-54jmJIMS0m;U$ zaNG?x1D5RIyD+bOndI{G(CSytSTxf#eb!beklfUnCSb?x)b(!K!_t7(?#SXUm<&Du zyc2i3>}F*{SUO5}=v`>Lhm5y(=?=NG`%*kcqjrC0oSwz>ft#3~5Cx@J6}N$ETptsl z_PaE;dzHwcKpF~}20FXcbO|C?vmLdUqR&(45HYvMjV4)p53d}@y2|@Ym>Vsp$3WtB zzG&3b2|Euy+AgKYGtnqn6XUU#_?EWy9@kFmqi@aUCyc2O%*TjjbMp62Th|Rs?Fo7wNVVk`@Ir~g)4=KZ1?-nejP@qF@qy$(k46nIClPk zJ2%MZel`% zo2A!HlQ?ccFaiMrRhga-XXQve6r^#jTzZ$wp*{ zAIDsMiRAjrj)C6L1(Ie=WG6yT7|*?USjIRpRctbXN&6W3USi?uuPn<*k`zgjO5=a7 z5Qud$08yH2L#c!igsuX2Eq!go=A@=~WF`Z25#cm)d~`f%vbwN>Wty0CYLq%2?BG`=VoBtBsxCHGPbg~Wo1=3IaB6MfLq#W7vAo9J> zV$XgPF)c6n2qsBOU4rEF51`rDDeND94B2}h`M3WKdgjZ}ne`Ym(tvLJV*r1l?!b;k zIRzDTx7X56uzMfIUU-J&`m3NBN?IOAX^7yW4Fy&tCRn%eZ5SVjX`JFum}*c+#BU?$ zq)64tt5Hc~AyKb$=u z{^wWkeQH3WkeJxqSZHZ9>mGlKewDUmZcr6jKIX}bqe>=G_*DZ&&o_zQeSvzvzmzZ6MuL{PHJ@_M-Y)F4{;c2HTF45?O zNFZ*l8n$d=U7KL!&r1S#np~4;CR`f2?J<=lF88GNRO{n8c*UaGxWMGd6XZwU8+7m9 z>^rOWy6V8n$)R`C9^P={p{5(KNCMV|hD?X1Bz78^D)2U<%A&WF4TZ&hn5~I=%(oqw zR5hI$4=ia)&eb}Xw0wWhDYQL|8jEUi=#4cdc+MC80(ii2tVdE8>h#$ux+7RFP06kn_KvMSI=8RB zPwz2kB1xOc$sa+QJPABqGFGfD=U9m6y_12;*BXwP5f5_ zUARyqjyg-|W`9>okxe_$8Is(9_P4Nd7Q67nOz!`2Xqnq8>~=%PL?&bMeeYm=|0ig@ z`c*XT)MHdr5QsFhd}goD^o@lngIE=_fg)#}YLlBX*V4FR3~70l;!MduB!NI^6B8~b1cmvh zgpMsrgG#A}Ebb&J8!#2aUol3Ugn>wCUu&!Joj?&F$m<)NNxe-bs*SabZ)gx`tW9-a zmQRrHxepm`?k@6ZGcc(Gu+DvlWOxIL@xegUSR24SqPl;FICO}fj`AWv z40_`{_RN>j@iy}6ev6kaAlr_bN84REYh_>g;fErd_w!+O_i zsbu$k1lhhs`pO@NKo^g|Xfv{J#XFDI&6yW0hH#!WF8uwDWmDHv zf?`=>aS4&yMJoQ8n?AF&Qvie@$KH!cJBV6j`6#mgLGq`53;XIfkl8)ZUqI&flI}eX z-FbhygH4j7U&g%rW$a+xDUnb2cG5z}+vvHcoK5!8Cy?G8%&Z`*C$TU65e(Pe=kQ}h zllW94fTeZSd7rHmTv$?@ua)3Ns3`8@X>HWkZ|7Ls7$?Wu*uAI84!s+5^`-Ix_k~t! z3@IWIB$}mmBEF!Q4xnGzSQy)Ewdb!esgav55iN;BMtH&SKQ8c7OU~ zVdc*o=q)-R_9phWx4WKAYgt;Nt01OR6!K4DSFa+IZOrC1B%ebispSdf{T_&~ha)#r zu%zb1rQC#9LJeRET_|Egym&&e5{!QW`4yrTV>-?NU>!T(COfbV`VHWHAakIbMTRD~ z^-OR6e0TVo49OP{A^RSt{p@dJ=MOZqFC+7WCc;TbXOxOx@ctY=m}iM;7SFUWa!)?*|8_x`LTBf6yJX=A0V4x z_dP&<^u-jLWe1fFy>fUK+I+hNN zk$FPZ7z%B&#oP7)_|U+}5AT2ddOfAhIBo>AcuikF8Sue4tusVwF(RV-#|`38{8nK+ z!0vqjJGU1zT;K6ryitr(Rg5vs43oQIX51|cle|Nze;xQX=LF5=I~=A4}FsCsoy|uoWq{|4qSVM?8SdSbaTIU0^KE& z2R@29_%QahucOQqpoU|2Na}*_~TPK_8B)r5!Cz?*-v`0%OoO}45H)Pq1kPPOKQQ>WcWt}WA|HlKi`6_O*5lDy+n*iIk5{cj*2gK2+N?42YBEsu5DiVJ3N(pqn{J^%ytUZsv~2Q& zkCLsOrS;{mK4BB7D&L6~VIM)J_ zB-ESmogGw(hc-k*aaIXbi6ecIn5|PQO5%YJQyy7of1ZC9R`E&khv6D&WZ}G%9+5_! z;-(l@8y$$)Hjz9{G5bGuS_vyBAxXIx`X#}+RL4d{T998uhTp_&e-UkMlJ9vKtifzu zfOPsSW8ydsLZelIULSFz*12ser|aWAO{Iwh+9tj@Z@uKJ#>d^r(*g3;2a(P;=Ekp~ zy~}9-eUN{wx^tvsZg+_K_T!y89iZ90WQQItoF>KT0O7fNG{lOke^QA-?{Ibc@NEFX z`$bdy_n|!$m4&Sj7;4YB%z03D~}W2ft9i`vHqEI=Zi8UKXq&Eij_#aFJWRkB0x!LFRZ zjJHcIoZZa_EaVd=N8d;L>KV+{7qCgYs<5PC9yB-;)%TR2QtQc5Ft%2L8C7i}k%Owp zRP2A7(%C2`ECzc+BWvSY#L}9zc(q1S{J2&ii0m-FUNg|37}piDBTqQ}CY$rdLW*x3 z>(X06S#~=ytQ-+;j_B-mGOAwiz1e3D*488re3=GzJiXokl9sCe;IT1amWJgn1+IHB29D7>hl=7~>P_J6Qqf_VvP zLx-=fJyUg`G_vMI1j#1Y-W=KC_qgOa&vq>j*>NpZ-6-h32hba5kc~@FIJ8x@PSue{ zb`sldQvCP88Hw0=zKyDg1Nncn0!Un3uqb(TzZgZ5Nde$wl^8e)SW~Qx_3opHCF$oh zwOmE&cU^6y$m?*@z?u{nSF%IzAzQs4idpjASik1A1eKPvWzNna+kZeZ`~#=?HtC=< zhsgIP$oVlcUdK(fi1$qD!(-F2wZK`Zp*#%I$LPDHp-_{?1{H)F1=N2)me6&ju-on| zknedAJAVQ*-b8d0v+=L6_8hkVDM*ikv;!l9TR9)McZU@3bh3q=KfvUXKSSrs|Ja>b zHC}DxwVNciu$Q`fqxc}D*5XR&>ZXximY{aZkS*?QO&mkOD$okW?4-J5-6Cq#l=E3- zTD#}9iIW$!_3I6&hUtF_G#_J^kCPw!KmnHATG4l_F|PVEr(tJTPm>+{0O`wrh@>sF zu=A~r3VRI+X}XVnrg{(~3ZPUnFk@ii01+mr8G;$0W&pStrjmipu+k!-jcNk6g=inO zT}0ccriiu*hp4mwRC33TZfY2agzPK#4(^%16Mqs!2z-3O}+LKzqs&$-=?wIz9)y zENOI%4D5m-9-$WA2q=jG%^XaN$%8+Fo!whw4d2=wQm;Wlqri$;jG0hLvoA+4_KU>|z|p8hTDnXe+<1*A8RP6qDv z)WUc`^4L$o(qZyH_@@O@2FdJ-qk>JgOWQ4x)XgK>4BfisF6e!yk=MR~+6>d`LVpp) z+vw(1N3{>Y?~=}HiYbv1T~MS_cc*VobJsL9D!PceTv{YhFc{$2rQ6<|#?=2E5g zq56NNs9sUg`~)2$5XB2DJ_S8;TBMr1vxTr&SoPL|M}w+aefBgGZ;6?jb8DuxI|5{MpaBi?aYrLA1WzBUwF#Zd@jN?(?+X`KP>f^(Yc1 zL0a>UdGO*Nl21mc2+4c?49UYkg6w?&J^!@Zb4jbR4~@o0g5ofsJcivxRZmyPy8voh zn+@(HqKcY!(OuSCz6{J@ba~wjAN-NPK9PV{ z9qX7#le|S)`qytRU?pjW;^IEDaB3AB0`+G1q&Y@`?IEv$y#((cKJIbS@ zG}1^)R+QKMmK>(tRum&SYDTCTIGbL{u&I#ruLFW@4U6BAg6)E~3wH(M0F;8A62@I$ z=R|_|)wFgMTaspWNsa92e!rbrLHmnNta=yo$og7;8W+naFC&}3jTt?Knx2bo0QmsA zE9Cp%MRM_5FxiUuO(AGfjjz@1fTh8wN~R5x8gC_LplEZxq+T;eYd1@1FF$S4v}efo zJdDmC#!R-Sodq;mM7F;|k`J&mKZdqX6i|-6<@0gdcZj!_wZDR0IgPpULNVf*c#K$& zF%=7cJo^=uMx($D2t&i9C@>wDuwZN%t5g&x#acuRR`5~ zdg@QL;31*elkPAd?&bzZPP^pjd(o?}!1@Jbem`>H0d#N!ooYw)mPigghVDIuUVRnX zizEjhK_&z8tFJiK?D+$jxjonm-v^U_V9$LIbL8Fb=brl_Y+b<|dK9zgBzom#^v2o3 zQZ;%e)Mv;7x?(J-6kEHg+_RCKDv*pI?UEmSlw|F7;yhvl2&RQ0_45tDc%r_r-X63Euk;hOvJ`TcO=nG)QTv<>5- z8`0^^ki6rEu@|4mUV7dMq_+Cbrh8g&iPulehREVU%;}F}&wU5Ia>ji_A^Z#=bF0Y3 z1Tt;3YioQg{x}<90xU6IawmI#x5n`sg{1AC$&RBfApmw;ZH|0|o!iIwoj*v=2!ztqvC{1FamJ7Qlyh?!Z{Jbp z?#;Th++CD7wo_-e0Iy8NoSPO*TO1_F<2{x1fnDyE)Er(|kZJc5W|r@hHjVqTowXnr6hb!R?-#bjX^% zFVu0dAVV}+hjbIn4b*Iqn*mO%!Yl7hLOQ$V)~K_9w!AS)Qm`{%=OJ4}^LdP&DLS%# z$5k5{k@#9w-gOhIaL_z|Q!xE=n_-uZVwaA(5l9{0o7`Y}E=>*Sf4>H`|we!*R@8!F&6YR_?`H7E^KL0uA z*6B4?iE^}xLDJBFuu(5ZkO7)rfz~BRF9VYTz@0X$((tkPd7w&lb_rQ~&J1w_%m&(e z6(xau37zamvK7S6x-lMKAFnY6OX!Fch;C)5X_Fs(3|%~2G-mC+&j%(W?4Fa@)d$ck zFVyb*+9;PlnjaN#{`gC6#GOFj*f)->>Bz--s(*%SPChh$fFZsJeA6*+On&S62~pfA z$Me(yO*+4y$s>OnZTDThco&$2|CQd#!Fn^kc1xZ6P6Ee{-(xMBcCh^w%*J_-4(F?& z$9fYD)w)j;ExOp`8TQq$A$w0_j=l$T@F8@#h0H9&c$56wzYbeh+$hbZ=h5TuBmKc& zgsrP+X9k;pcG2(sJM`6WBHcxjWADYB`~dcI{{S{GW6wQB{=MHJdHiQdfAnuS#>w0& z4A!vEe*xXRf^=rXgW|n?zmuyCh-`y*Y)PfA`Lx}OFFQf|ON<}-QCimT&C{D|? zP6RU^xTNLLpC;dPvMRuC=ZuJH&g{#^b;xHFZK#-JXT2{$n>)~Wf@wZrbmJ`8969 z^<|QORu^;PeaOr**^Tqq%P(P;jyPLxz+QXBQJ+l`iTX+dx=65oH+j(BB~mXor(;}= zRMs5(4_yfV?!fsm&8qX&uL5= z_6rRo6lGbV4I?NbNS-0tfPD1u`4W+^TnP>AlnC%Ly#{cv|abN1dF@hvv92ytPQSl zGTCNwc#UkBO782T?Wpdzg(u?0gw$3?Lana2U znI;;Q1-=$d1s_SR6(i-4Zm4q8R4_Mx=$nXlzXnaL+-Xg87Rgp0f!-c(&ox+DNDC%s zFq^-Q@b(jkRv-ftE6uH zDp^N6FQKj1iyz2~{Z;_NUQi zFs7_IZAM3yXnZMd9tV1s(Q}Nh`koma6jv9LcF^VH=**tt zEatnmA}Mc^uQwAcx%D@dqpdDFy9yVymXIn9)>=w1M=LaK?xGMF4amQL^{=sKzk?}U zJnSo9#a{S6di@nQe$!h-FMN;u3;z>l&k1DlFk;7?`{uu=xA7_~-INTAef6v8l^0>S z0i7AhGpCEPeFL+4674O*nJ=RkpGViuI;W9<2B~$|gy7$OR4_z0r3hAH5=h%`4q~D% z*xK1uChz&bAz%AtlFQG3p`BSL4mC|;G!o=&LOr7kIP4WrxU@tpl2}}JdhorOAKyN5 zN>3D3Pm5A2ie~_>Ih3)YFv9plCy;qnqBl`v(F3rY1=&Eq06mJ3(CsX!yGZpHez zC%~kIq(y%4-HZ``THpIk%;qI*f3f@w{spYwe6#G(Vb=)6tg(K}^2R^Ecp631eO|=a zh9U4k*lpT*$tTEoi~QhYj34{6&Iw>Lym!xT*OS=^c4i5?_dz)G#b`vTiXDM~Xd~N0 zb{3Y7Ikg(u-}tL3vDN~iW0-m(anexm;8D7F`(4jCbWcV#)>$AudERj~}bf*pM4G}>*v*i09!(N{yx$zQY+eq3Y z&|eC;CF+4D60C=?lSM}zO3?9nx7Ck{x_!aYwyrMUMkWdh<-~|0HJZb{~XI?!1xB4;7JismaY zI)O~~7a&(wCa3CaZ~1E{;zn=!i%cH=addWX5#Q{aw;b8XIa(fm+%X&{+m2~k(>2mS ztgI4BjbsW4ErtVHv{pJ?p+=W9x;$zu_897a`-US>jR+H=-FMR=Z*&4`a7LQuKBF!2 zeGf5y_$PJ%#_sMb`5S-ZZ~T`oV*ZEwWsG4k7%&=*SXfxNb#SK0#?9b5$;D?&b(=sN zqN!8oSvZw*im|n#fFvopeFJ;tWw`z-Tz&yP`yDqfV-iSG_dVGVz45vmrMdPhTzH0m z^WXY?T4I@BIe^W^uyF}{<&2x#OYzcJ&nb>O(haCGT1v39yLG(b+xN#lx7*tC+R3ML;oOlI~$R<=RQ4 z@6>Q)1J(8dQq=}@cUo*1N!Z@rLV=lonHkjD8f!v!AcoY@;+@}10HRc=h1bb9$lw~b zv%uuxA9n>uaT(t3a~6|g&VL89d8rT>mD()gPG>?I0&0xL?w7=Gi|NG^W25RMe2GYdC=&Z0NY zyJX?|>jk^3>#T{lZeU;hL-fTzgyDKIp5z?{zkrP7AcF3Z?4aim7aaaWkPyZXN9Ho} zJ*UZ6?{^}&Hor$_t*~5PIEeNZFq;=iHqJZuF!87d<+!=jK(JuUf=H*tdtj9vu+))F zkr1S62wftfTh~-eKqez6+IIYZ156(I)7XWB$Y|?N++8NBXlE8}_c0frcF(C0{goO* zC5``Cb6A!-JHThh`5^yzJSIsJT50O(n1tP?5_oBfc~gtq09>xWwiJby-joR}d= zF%IB$Vx!$JV#p>=7o^o{hit79R4WP^5?5f7gV{oo4M;X1S#$rRjpTC$+ru3{y7H!hRA_+l|>AxEhCPl&9YV}H>*Dv(^akqehB6YY0o4GNU z?hSOK7?b$=-rNnsYB3UD{hfXZK;&&SBPG zN87zO9AEPVq3bLrgW4XFY@?l*pz|EG&!Xu?#B8CGAryk37za*&Qt6WzG3B^wQVPFI z2|!kwKS||0Wd_A~&jy%vNUyoGY8OD;h1O80Yf_Hz7YvPhaPX~cEo4LT;~!*l-^ZXc z=L9R?R5qjAN7`RT`^%W?FJrc^Kx?M3BKJV|@^dC&Q!pc>`#jot0a~xSXQalB|6z)C z@T&*e!7ZvTCL7a#4XT(HS1T^gO>MR%*>WR0$#pQBi0!)(MFb^pW_*cpHni;-vIjmz zcJzIYsqkikCDYGj4BB0SBq2HfUDx!S>Kn;U=S3L zNSdZDAJ7Jus+vY3^}M;^{ncs*8f5DH#99Q|zK&fw%H-jHAIGkoa5>-ZehuF?43oF# zm+P+D&TMg5Tym;`wWrnty-!8*P!fOEuSD-UGmcg{9>8!DO;TiPn^=g>k+h-P0&CID zD`=}lGP{K7%sSO~5wz8J`V6HN6VU27#)syxdBy2Fw7TVIt0j0fj#DU-8q5DrKaZ$D zK0#;pkRNz|^vx_EToOB2Bj02 zH~3Xmmmw7B^cV%D3yQ~OQ9rQ`QEpRwLz7cl99+wQHn@(RS!MFTkCL7I5RzwiRZvUX zL6TNuvq!W6VcW?9EJ$+0?n|RnO#EWg;;h|AhwJ2j-};y6%nB^*cfjLd4e2jJXBM>? zTzifD!n4>{zDhE?!uZ?^46nXM`@jjOMbMoi|Hi+BBtiO1sI}OQ%jmcN4RYp>k@zmPU%DO%|LU=fPk9o6Utgy`;)1!55F5vOl!9fV8?LFn90R4P!_< zOnm{Vsas^?!ij0pyK7*Q31v+?aFOen^#gt`IjAMzQy(RLKA4YpinDOR+ z4qTkOS)SAtV%clR=D)>cuM`eBt#Xk?e?;l|6z;3{UaRZL8| zMoiV+_IPYki6i^vUR||B8!d>H2G<=w7qB^^IX3CS>_PIy6WH1P?(efv!}M!3Usv_u z%jd=99A@+1qH`Uz{b2E|b{ov{-qUb@4ZHUklT#l@wyt1?*U|Po#A_kdxJsZ6SkgmG zSqy9ERcN1u)@!J&Bicu7uP)jfF%^7qd=HH-_d@78GW|1C6#s2E8kb%~Tj!AcGMZdN zCP#|#HbBO1pQ{Ff?ln^lzi`bbU~}y1{Y>uvB=nb^5c!)P^NRPKjmVEZ&SbKGP5Zn5 z1{qvKdrJjq;IS5L%YDA~MQELMBRDcdY!`GEf3PM#8?n4!1eKIq!br7(f$0J2YIQbDKCx5_=?Y<>b5aJpI?OC!Tk7I7U zMsoI>&T_f58jkWIj};BbMIN%&;9t%cvL*YX)Ai;Igvk<#=&g2S42 zkjaqr>^BOuPr}ZA&}k0Q{gPfDQyn~~h_VYH#uaeB_j#=wEs&&`q|LQ|>(}UXI?T?_ zk>`2E{P0~%%GWVqQkQf_{*oaB+rO+r_CQ^C!*5==Lv0t1FnRDtTxU?~>wNF_jX{P3 z?DBr>{4vbNdCYJF(X2pYch-p%q+#4#{HA%aPNoXRW`})i1Y-=_TaGq9Gdt@XnYanF zz#jvWh&^IFkwuY!tz;s9=0RWwl8vCZ%;cSamh8R{IY$CJdBf+r*otV z*Oc16(in)P(HzG|!zJDu#lMUHxr}%t8B!G;Qe3|#McO^b6xqDym?oWhPt!vj+p671 z$J@yEHF9gw&K#XyujukxOs8J}iRv!qq=j^6oPF@tRn$%}-8lz;Kt_i%P$Z}Fudi54 zChP)8oz~>*83fBIUiu&nD80?F2On`liXvtA<7V-+X`OE!KhB&8=JGM@;xT0Filc^4 z2F1FWkn$u^N4#9$s4$m`c@Qv60y=43<=y!EW!fq6X>gg-WYGD8kGd(Ipe9H%hI9?>e+#-#7h$^#q$OB?)KoY~gUMnQa}C*K1PJX` zHv*!(wGavSL5cPxg^r1VpEi}s*U|#C zN;c5e1(^97w9YzqgZ4vV)&}RI7$dWqgDOed@}7%-wr)aC&Ck=W-1#yKs=nBR_@C?{_)dE-)JI=Dw1Af?Yk0nik2G=UrS*T3#*F z0?E<#>(F}|ZM|B=k`Coyt@vW7Ro&Bk4x>{lpjN%T;FnQaK0l4<7G?eAt)*KpgS4)o ztxG_E3Oa{qt7ycy9K;mQJv;FcvIliJfS2pg0&hgSWGLg zF5+oDV2t6$_3L!HU1n!z$gM4tq0-jX^Wb*#%7RtTGg~8*yNK)5G&&j|FrP&ub^?ok zN0=OYAI47ZsqJRtUNr_rLzvlvuH1)gUUb%a`J~hjX*{KIkd}yoCY8vqh{392kjmYm zTo?B}CNXSnZ39Ywwiw9?lBg)rouaQEHBLNxN>g;7-1nM*nSfU;qPD;Y1loPZPkb7C z=rLypdyCAH=5txh&#%2kvVIQ9$B0RPYBW9dOJk7+hDC+_PXnVZTeK3gt^$R7_dd*2 zH>K$rPQgZFLi(P6fh8%Dw8(Qyp67Hs-ST@hu5hMp;UsZ0@dc}_iN@HdX%hjAVj}K@ zRL|EKZ~xLvIgGp5<>$}FWQQL|7mk))pEru9O@DVMohSNBwG5iH97A#AB4)JalBY(AN&?_R(GcA9aer~d{(wnfOqn>1$79kYA#JtX zS`rJyMQiGf>nQaJw)ot+qh}$1?J#=p&tv!AkBl~V?GAaP+@tCH%G)8IKxYo^Es|b% z+KF!ZA4F?2Mqct>{Jvy_cFv&vZy;s^>|C*b3z6?avm(|gi3_%h%3iQ6C1EldqCmUV zDVV3z=1nw4K}-s*8Fc#w-HNesS>v1-_m)6!-+ zLCtmOe;4h%-~>pu=fF#!88QXtBk&~nZ{vz_HnDY zSH5B-N(8#kL+_iYjEk`(&vB+;UIk1=^_o60upGrWEi@~Pks1Kz#>GA31*wE%#S_}7 z7?jh$a{!5UUd0#-`EtQn(qcd5el7C1LY_zJcymX^k}442x&6J`Fcm-B&|%E1k&QWPRKUa=qIKop=fO z?Y@@S3{5-admn_fRnUS77zm}%j)X~|nWACFcx(po7CTCRSObpAl*SZwlYAk+V)KM7 zb*V&0#S=SW&n64<;~4Km(ByYoyQ{Taq5 zKI-06Hg*=6B9TEKQ71;D?nYJI`kf96;z02GO5`b2-b^_LjG{};&j+y~>0Tc#22d@hSl*UVnDGgI#WX%eHJpp-_+?;3+A z(Tt9nvM-|UBp&0yFOH?5$Lde&_#-<(<|tl(Ee@$hAY~PxLw1jk+Q%aeJ8AoA%o6b~ zQi(de<%Q-0xI%rVyXLf3eArgc#U-`3)ls_ZGdUT5g0#pV{1HY^{w2q984pnF0bbIa zV8mcakka}WY|*jM$i>QMA&D5nn`(EkHnI8+oF8FxZA-|6mnOBg0) z!Q%?A{NSTxN8gWjmt4{<~f=8Xx>9Y!iK(*GSskTfp?qD-) zXPJEe`^b-d9J_MLeUxlc<~o$!U-fLlwX%ArL8nqWHAS(#iHa58cb6;{!C_2>`A!x~zIdH8&)LJew1^ToY ztBTLo^k-BwfGUH59hHi~0MLF8X1)kAa(Q>ngH=m`YZ2qd3Hp1;@B0|}-iHdUn*65s z!EQ55Zu)!k31G+$znARcpLAvzs!kt&ruQAR`&7Y3OCoJDshsA~8Z%u>yYg_cqz0V$ z8IPYWI4~t>W_hEal}p$(k5KP>4A?H(dLHe411qEA1uT<;?_zT56WF!sc9rbmKZPzHhVfPz3o5WAo*+;Hmxd|RkR}|Zij780!Qd+*oS~M}mB6`w4<6yY zlxmG*D$#!hz)D=iRkO?Y@*#j=#nJ4 zGtt-b4X2Q#BO{d{TCDHn zGbBO7qj;0UHIRh-z8_%nzz?Gf2OV`-Z(YRg4WDaw5p(rLlC`stcFQh*n20wjEfN%D zO+t?4pBrfw&fRgZ>W&{pg0-j&iY4UNB4Wt144Y?k+MNHDZjQIpn+Y7t7Nn@FsGz@P!+PCWW&jSCi!1?FSNrpm`;_kGlja;)C(#<8s3mHFd0 z^|{{aYf6G$Ie{5(JBoWYhNRu7sitv4GVQi&2!_YlhaW3_hDmJ#ITA38GhVHApS;ei z7#M9r+9o^o3GyS4yD_;tw0ypI`G>mrH?u-=`FYHE-HjCZ%$}fs%V!YVf%X+_|0~XB z6I%*U#wrVbF%}Dm#+_IH&nqSav|61AaBZ@!CoJS@Ff@g$h$51qW&@HNNOlOcU5X_J zjG^hq%ExG{M|SuL@?-C-t>NyR4~5novi%jz=4TNmsB}E;h(s}48Z0ei0e9~v3LFE) z2``!i(k}E?u=7WM(Ah)KnsaAvyzUq%n!E8G&B5jvg>15osHK&*otBv9#R$d(>;%ci z7*(`2kIo-Km+!|eog$w<1f6-uGAXYdt?O_!uIEm2n$5zQXol#9>sYrRbmPo{?d$Hw zJ3-yOF}ugbt{bm8mU7Z6wG_k$#;n^rp<36A?+ z#rRgTfp8Un(Iv*mKS_Sy$I$szH`Z~J99rIFZJ7Y1nA-(gdQ=^zxJgW|tOqY-J#iN4y{^)ku_e3^#;KlJKN;(SkNFg*~bPiV*J>|U~W z{tR~ccokc312DPGTws{q4uyEP4)LwhGI#U!ZuNJ6)xJ*);n$gE*HO|)cu}RXy;LgG zd#@dgE4-+r&wtBv8xX-e(zr-dH!>xuYC<{hISV`(mr9=!FT!ftj{E< zsC_Gc=Bo9os%WCs9J+)^tMAU`slnE&V)foilfv~hnI#(_gEjKy6HM;^6n5W(*zO{d z4R1Se+%yiT#m+m$bhjUDmDp=UR*l@Ce6d=nG%2(!jJ^G?O*viBAt(e;n^+uiz7nKR zT0Kv}lOOYz(g!6=%|fdIa9HOOdZK#1aBpCLwyhz66lf-Epz)xd9jEvzXaRsS6##TL z&vwuKXlKq{6t}vTyIr){%*CMDz2q}XXm6S9$P*+tUMG3&tH@{zO;e=RE9^ZbU^|2& zxe*IaZ?fKnm@DIf)ALw5Mt=V%v2**$mrtOxt4KaZchQn@H^*&u?aOA+o?&w8V<19* z^1|=IXahR4#KWRO>@uuH!s=Z-$c|#*!EaMV3w@?w4NKa!HYTYAF#`vXnFKSqj<#nQ z-~U78$3N%_(|b~A-(~)x3gl>Sf$^h%hVCEzV`S?xI-;2{COeih5Ev|s3OS=3HI$Hlsf2bpVNw2DY^XKB6h<*8yO^K2n9FFuvJHr!yp%j!9ut;(R?R^8`F_^5Bph@{F2G`NqRVJr@i0tV5 zi_xBZR{{51y|do%HPu3%p`AtS;YXQ_ev94Il<;Mi2<2vr1tRP_;HYgJPa zf8sbHar|!JE@)))?zhhT_*&)rDUxkK>pa>1$FRpvp>qcvn3)gnYJ7Kpx0@$boU%@1 z<;de;Gg{C77H0Dj+FLB2LH+ub%Cb5d9}h2sqIOjct%tpQSEkm!9*Cm8?xkPE`1x|M z)4A7}FLPm-^kaIv}2cDt83U3x1&r1wZ2_-&bh?i4JN z7Wt9)lDzzfu9KOz1FCX=?Cw$U!-Lu{a1`QP%!2bWW0@? z*+X{lJ>*B9Alv(p+ehWR;1b2O;|e8{gkXg~IK9Kis(?fd)V!tk0llEE9;>4E zEPPNz14VG+{aXU34cZx62PQrCY^0zLjaET5U`xGVUmu4HK+Gn;_@D^&tIX**MvHv; zB((as-G$%vc&>_njy8}aCEs%jR!?ECpCw;7jM=`1Y+b{wy^d^NL~Mp6E%!N$K_v}D z#vFxHg92P_?zE%Sx_{;w+L^^J9mme?N4xXb#Ut3g51_p{B%8Px{g$ZOzqxm$s={ak z+nr~8>f@wooAk_=Fk6?=R+o~p9=Nm+?kn%VeSNAhMk&#M?0^@aG`fooeNVo=B=?1zJ)VV2u0e}(~KYaDcVo}8fN<{wzpKCYv*m&g7)j! z{&&D!MQlGXzSIB!7Z1?Y+8As+Zdes(T6?Zu>f1nU_d1Eu*n%_^FV(wqLfYDX#TA2t zMUss5gUN zBmk}ab&|rXU1=fdMJMjO^(ZFW2WE_DhK>j5!eJ(-e~A3(6VCBuw0Tb)adxe~Gc!oG zf!X|jP3+19YuaXTpKl=+oND3llr+Q-0OrS}pyZl$W5q*mG&O*ld^P}SOW zHh@_1e+ujblV@mmm3;XGcA<;O{(yY60LcO8{&y46-M6A{F2|ZDBeXq3cJv7lL+iQE zVK&b@7cG-`?xvm=nO}oW1@+6g;DadM-8~(D$@LoXD1q>+`rwK`aiNj+p66^M5-H6` z{~5bvl`NEO=){rtKE&jKPm!k_rGYa2p0};7u)YP!?vAf%UAKO6^23;O z-@a+@N87XH zt4GKVzKiVmlW1=i8E)P6DAY}#X%4o3J%{biA;XQL5c84x*j6+Y9IPoeMH#v>wa|^h z2`R-Tm3r5^#?C5f;#vc(d=MmTqkF~q6wpxKxL^|r`X)XLB(Td-pAkjx@$=P;L_$J}@Y8Lm4ZGtZEJdlG=G5X{!ft||Db!nlkK;E$#cCKdaTH3o$U075zT2m{cD)f2HKe`-f)7pFQC2e zxK4B4uQU?;?2y<=AQHD09~|+UEMfdB87UF*&3{dQ%uzM$zy_l!QD-**PizZmzvMVA zgGa&60*+aslOcBL1mk!96n6C_vc1um#NPQ@YGD-&GW-TIej3p+Dhq*sJ!bg*?hcVi z_if79@zq7E5ophKtD#(0JMFV*5x279`>QjeX~#YBR!Y{MxHXyC<1|Qgnon3ah7#S4 z;RtWVRx~wmzXE|&D(bwSgO;xaUVfuBaLj$R-C9mwMTXzR_CAD|4(Q+>HNgr1x3Eo} zJn%_KTcpo^*2VG8JlcML9qoS`WE=8+EwbOt38zU{jF_3D5{x3&Mu!`iERC<_jj0E( zXFHIdMfwT4oxo@gB*U(rB0KppvP17KZEWAZHunl<7Ic8w{9R<@bCC4O7au@ci7A@TFj@#|mf?^$%;F_%%I-tJjd3YD<|yus_@PhyzRZokF(P z?@fbvhp#lgAme0zFm{vKz4ewI6VO<-_HFaknMLRJqHAYevRAk>lmbVA6|XCJY=F*1 z34>I^qG1Bl5WJ(Vw)h>QXxxEm2OkNVe2R}Is+VlhKxYk;t18hY=;C81WCtH3+y5}8 za5H$TLAF{!Qv??<myXjq_brl_z6hI_G1<@|mq}WGpg`V1EfbTFQYhjjs$N0t zFN-f`rP`ol;wLyBA~j9M3Lda4F2%SJqwXTv$|>@bA0eOL=RlP0wR;~h@(jCp7@a$S z*}8&F+F=qZ8tL*>dnqi;s=q3oZ?r<3OYu5S;oiq(Y60Hss+Mp`ToH%+`_>(|Xyqo7LI~1OOzGIe*HX-dWIr@IIze@VdZ(**# z;_Q`8;yPwD1K=9UzUioyv;=k_{U?SXe9`N#oi_joaP zE%#86!4{JfA4Y6O>#2X`o^{fK)>Y_z8%b_JKC>gqrUYMnhYspNNdu2DMWR2GTJalc zmv|$8x_%)tWtEE0($gkaIXo}cKD1xPib1yCeX`1h#Yc3to39c;uyh%^AJwQ9818c5SzO*9_4l?cR`ic9-K$bLSh@gxuA6plMU zHV(!ocM|h0a{;9s?UoqWsjnjJldf3(vUDjP>MEQw>}u6)PY2e zI+4|%PjjbPZ2CH;t-zCHOOKH~^a}I%e~n&_t~ZwoCaurtQ6xX z)^nVg(iW#XUA%+f7nOlR_4E(&9J_EB?eB3vZY^)-*X`|_A}uIXud}@mk?nm5bLB-^ zFMR=X?InkdtBnM`yzni?iG&q$c+(Xyr9Cu_ZV5GVMO0Bp%vdSMvBc5q4A}lM`N4OS z9eNkqTXJhv0#tHO&SjX;49S;&PmnC1AUXT3h7lF1IRW_kF0m|$l$}(k}Vx1K9RVRk${+VSE9+CGp%^gfV!cw6?bhy+z=Ekn_%%S`J%F zmSq@YoXunOT+72W-may>J|KCoLG~D!y_c_dTWcu-`54KCeDM(Z6MupBbH7V+?%R-! zoQ{GI?3T`H8fYF=2SzK4VJ|sS^~wg-#;&YSpC}VnKcQ;(v8xY~o&Gp>b}x)KgE6)@ zWBqm|_prHZ8XR~GhMS~+FaACxTWIgwVAfIF_JG_eupGK`m7>$yEP5CeYC-_2_+@b% zV^w_pg{Z(Rx_V*aEMCl_7%QlR7pptbIhK&V4&4+PJc{iuGkNEq#x5L0CIi&wwW8tf zbxT@cH!y=gg6w)Z%BK|FPHRIU<3e;-r}`!MzjBXsxgio_>?-s@iD> ztJJ-!@-QiFgf-G*3hk&PK;CBnsdH*^Z__#_K#3(*BH+^d-4ZvBG%kxmxS+Bb-9(08 zL6bQ&T}5b!qj@$Y8_xH zo8KC`dF>=j+5l94204jsqphph{f6<$KMSoCnT!Hp?_S@{cbpHH9%k#`V>W*WO%}cT z08BP;dTJ}D(AibY^_MVP7a^aN41BzC8}V$Kt8uC3QJnIhMjAjA0SF8u(z8ca6`So@#s6M&kVN6uVSKI+9YR0V^5;3J~CLpCq3dfTFdmdil#RyiFw<8*$lgK44qwt^OHtUBe14bs^UvD&@w44 z;6g5}-}VT9=t~+G;iZKf)NfE5(xA)VVZ*sHiRhd(Hn*z473oxnW@INmgxzzp=2iao z-#6|d+vO9CmX2c9&yl|V4a~JO$mXTuHb^TjpoD->V4dsPni3TceiEicpo-Mh?xnB? zR<&;QVD13+(7VZ3Ph-0a-uJ)B=S3|fi4#BWEx0j%5R(Kl9R7!w9U;GlN;d`^{D39V zSX8-fr4e3~##IgV!Z5dZ@t^pANhk^aJHh@5pmdo4Zv%Y;_uP7{9UB>VD36gyeyBX(;PeXUX zv67~L#d|peUIi;Zx$yyX-N|a6kPTTDl!RcZmh9Mvff32Y{~6>)tt%a}da8Mu3YZly_U+J3ZTPc5BTYg|d-cm2I`F>6xvwYX zQR(ACvHCNE=osWR?EDF`)BiE~;)z03KEFqQXCwi81BPF78YZM69jXNLJRn4-O{KcM zWvD$zz>umBU{C@WT0;9wz%Lw)FwDp%8!D z#X9LAlh={)_fUHSl7(7hs@yxRIr7zaptA>&wO5dB2b{Qd^X--E&#&$m<~_&4e!1y; zD$vB!fbt4?Rdu>)V$jYKcK#@KcAs;9_tQWLrMLpM1W07`4M_K*-S>jseB0$&b%PQ? z+p~-x{WGKshe%%h_n7UgXltgfvpN0T;xoauc4p$nNHCQkCXyhaSO*Q3xYjH!F<#x_ z-YQn4a4E9$`^g^oQL>ejkhUF*=`A`VcdcPEH#gTvW7*o;D!TFRzmp_kc6PRZ_Vb&Y zo8|Z2>;v@seOj$n@aLn^h|y?N>tx)Euk!cjIoXL1!}bl5v)_Q;LN!|8C;bu%Zv~=z z{-}UNP^gE0h%s2Th!o=sR;yVtKrw;PnQByD_)LtS1H~p*y-$b176aIct>4->qy?ivqhcK zi^Dw{1YU_LwbVMZ{&1&gB*G}wb#AD-?^2A~O&zF8W{TAsHWWS=0@t9L8;YMj3~V)=Of-XyL&EU6u9a$O=F8%Fvi^TWF)35zge$!@5fH3ph<^( z@BP^R9+FGXki7Con6+1bfdtcXE*&Lk5>v~4hbZ4A%oDU4kV$?bSDTEiFQd_S)q81Z9Er%4@E}XOala^;wItkY@qn5^7zQtP&xL zZBn`i>|}r1RFwEGJ*7sHhR!Sgcu?78pR!J*5JAmyY*(-cXUP|T+mNPrh2!5e?nnph z4P^K&BwsH;zq%l#5Av0>@J+GDdtRkbzQ^z@NPoe|Qk+OtOh^ryA@Mn=xuTWhLyFIG z5o3xwB-H+?A(N4RlJ9;PEU9>fplTqj8SA&yc8vmd3mJV2O;^FJfDZ5R9U>rYWb`6z z{T|wy!7iOdXZMkRTt9=XzYaQfV*OLgYkaX!w^w~OluD(6P>$qk(|e6I*g{PWAQ)v= z|G9f@^a^~;(L4jwC0~6QJ9iju&meZq0e+o#gUsy8eRc2d5J9Cwvi%1z{1!;xI~N|P z>S-KZRahI{7R8~(in~)N?oiy_t+-QMi|gR-P_(!gcXuxmTnn_g)8L+)|31uHGWn9s z*=L`%mzdbj56o0UwVhC8c&L7bN?Gg%sJUr$@ ze8|23z{(V3?SeC%+7zMT@24gZfxauIzCoSdE4(i{I*+PvsgSVzmx=t}Sln5GtKs2@ ztj68rY>+FqYlFU9gA&_csxQN;|E@(L*UcM_jm#U#fKzJ@Vpz@wiTORLIqQCny zcwBfTP7KQp8bC>15Dl9-XR8Q@y1se&&veCYjrKKNMYkoS&?7;u7p9Hf-#&OAqa6I{ zGV6{e0t`o>l$5phKM1PylC&G{C`Vc(V&d_X&B^{p8mSYr@AUNzkU}bpqsz#+&n2vp zHnu~Jgw9AseXlWSk1q%A@D0(XWHBoH!X0kDLGLtG^c$uFq4}TVR%h?>t>df3qHt9`1zqhUP#`IiaPbCA5vz|lAT{VR% zy^8}Ue*cJaj8F5nsRX+Zdc1`jsq8e|!IY0voSiNxYu!Qo_eS%l)^ZW{6)4$v1B84I zz!AeAWNGSIA+IA_3*76`6!ba&kh}DHrt*4Z@&VTT{+aVJ&qE`Jsj;rsbUwe@d-J{s zuPAZ(o4mwatU z{IMVSnaXu~2k$~~1ajk`Q`gm=`(j~f04ZN~A(XPI|GWvysWsiHu?#-7D)X;SY>6l% z_|)z$IG{qNMhy$7Ufv$cvwY+}lVIN0gO~XQo|EY)(_K3({raU6d`0BZhNG%=0MX@G2s3O@nA^ z(_v7yRI_E^)tvsbHV^vM?nR=`S(2+o#C-2aGOIvcpO;Q($Iq#V z;JtjWz{MsUbZU!|Cp&+79e|kwl&kD9Pc3?du$Fvpo}prDeg9dxJBM9y>(j;AGEs*` zf62n}zr?pW(H)(@eH}uKNM;t6hK7cLz9$_>OnIJfOy6r8g!jM5cKMVru=f-J)X?}X z2XfH&cfG|P`daYIH2}J9gWPQ&Ol5Js96}y}ndN1CAM#FNT6u}Q!|t1T#g`SxEij$Y z_wp55U?#4A09UGS??6J=Xu$pDn-M+%fu4y8kZMT9Y)SMO?3DzC?vE8s+#}VMjv9I; zeGH6D3u8i-S^qGYTKhN&!IdB_`(TBF~gTuep7`X*caIeO4876k3KKY{SX`e zf)bQ_C5*Uhr;#^7$n`x*2|vyOvDG0ETbN~X)L^v~M@a=@y82!Gv9I^7u8s`HBxlGQ zRY{>2Vm2Gejw(Cb(lmbeb??a@+TSFhladS{R1gBgv=#CSbQzk(tuw4VpxF>IYW=u% z+&>MD)BRVjSEV#I&P2HziBPg}>-xC&!(FVsmzQh11e;*w+JmFzH==pOv-x*WuD3mi zYRLX#EeqE~lv?HYP6I*dtn+*);nx~uoSRcpCYIL8c(N`DmI#}hpeMQ71-0y;lA|5h ztM34E{c8{Vn%I>!M@^kY*X4Z}wig3EyW=~N*RF$*@a4P7v&Jt(mn`1VJM?EE;*ZXJGh?#kLxEnmq$U(lsR*e;5Mq3P|JMp^4bZNRNV4}) zK$%P(VD^ddat=P@;0fOByCmAmI58;yD{)!R@2{3bCTE7Pd|s0C>e)>*d&{>_CL0Hp zf1;oQVa47j!v6vg3%x8d5-3xn-Hi9n)lIfIOwHr|=4`*vQ4g9t+XM0W&mH*|Zf>cN zUC4vz1L&;@61TtqRV80!`s9SsdgjO9zURv~!92eU{^*qn!LmU z$tEu&CVP>AN0Fbu?a94MQtH#M!PiR%CqlrY2VD7&Xuu;I2*js#O;hL_!Ya56Zql|LB0j>6 z>KuOWI2(*&MtI9c#0b=cz2{CYaQQCASOgutUroG`#K{o;`a$WnOX&#;P*MTrJ$xIn zAccBbQTWw3m|_zI7z6Vhhl;Et#USz4x}iH_Itr>s1Pjw4q4;UHFBJZn(Iaa`*|_=v z?oN2;%|A1%#4cC~i5$C2n_k*(zQ;p-S;jF%RZf>g87pE&n*idaemy$R___WpdHW*w zQtz~FbS?DinH|(xc}(a|TDZI^2q)-*GKN)BR;~fBYA$E}v{g=HAJ|B?Dj6weYc$S# zhK~@G)Uvv!ef3(-Zb0J9pwdVJzV(E;Xv?)&7k>D0|H8FCHA0Bx4w9!sR*}Rw_@zio z(2HDr3x}{J1JJ`OwVtoK^STAeQAO35{|Lk|YTkddHW0SCEnI>I8q`-|n%?KL?&c`H zr{~;L-WI&SoBX_)F|d+6Kv3w>&*7l76NYFYJhgNwX!@(uC(!W&e>IP;R53O07rCT< zwN-?FnI9`0E zl^!>{aU5q$mz=;JMvF&)ye7Xf80!&!QZfp90+`sFFzvA|Ii=dzXhKh=^Ni~2Ja*if zs#%y9S(Xn7Q`1g=nyW2*`_o;LP&scTW_>3xMn0YE1T{I3!?rXeemAB;5}fvD%0p}= z`5aW-1gwuxll8q`R#RhspNp_hBlV|WYmk+Po>2`SFuv`2q_kYK6LnZS>xU~I-ONN4 z18SBo3;sD_aif*wYM~6l4Hgc6-zql|&jzv1plorP%a11fa9JLMwf|aS6=5tL9nS^o zz3D}TL`6;Bp6~8>d-95-`>t~@E$!`NA^X6i$-^+c$bj?9sPn%=$V>hq#oG`t4to6! zn!6Mfy#)naxV`)ay^{WyGX59|`9}dXT7$@uLd72i{d&kVSdDhzDIQ?*p*MN(11>Kc z07xLre@6(=%M{4v^~vMySoF1A=y5OA!C_IjN&7pua);+R@#*O)sj%-2I*+E4ts4Ou zjoU8Xd>u4B#HL4J)+X2ZLX)BRF5X0KlzUoiwD%!bKIPv|EE_wYD5y68c+QF&Lofb3 z7i*i!=BeH&&&5(U59hwMuN1KwE~!NR!~u0|je$D0l_ACp_Mlws@i?Ei3^xQ0x2I`` z8P`o~ss`l$*57)qjU>c~$r5ZCDNWkO#r5G5-OcSO6I&lO6qY=+hmcOljP%y&Y7oQ1 z@MI8gSN_`ANH+B%+jo)!j8IY}?F1O#4!K6z2{DKg$EK#Ic^c&h`N-m*q(T5}+h?0; z8UAm_(J$XEoS*HwEB>ZrqBXpJZCuEwgvxbfjpCLsol;8uykwltd7MvDuIW$wyIVjv zcP2WN@(t3F_-HAZ93&a+_SRnGH^%2VGjQyp?6{k3eq5js1t z6Q^SJE!JT_qWt~$-d{&2abTz+;2&hsy==ihq! z58o|{!qK}nrK|x$U;`3H!qXl;xRbujnI*|98mkAy8n%bgefE;5=#sIWU?r9{ z>eG#>3G3;SAA&Qpez$i5THxM4Sz-!mY_$F^G->b zkJriNaS&n6t@>Tw04uil-j9K3RWIGlQDyyv`x36eW*50U!fbJz8OyLDQfnN*Q`e#_k=i|07h1OEo|*4bG! zkTITMS)W%xK(0!ca@&d<>(@~Po+`gu>0Dj%ccHC7=L|!gaO~zi<=O;Af7zzNFOsdn zLtmPnoRKKl7_hfe`d1}7ob>c`U0s)$U;p*pP;JKZWnUkH&eN;NSOVEDPW}TzKIG*P z`skL}-g>6cnsH|RyP9NkdwcOA4}367&&YrVgnyNI{cn?g*=V)7$}C-BFp8EOq=Vd4Yb%4vHQ9vNa8XS*f4 zP021PSZR{Y<6r$Ls`Wh|8=+Nd12QA%Intq7_sG}PC!BfXLPiEjHF+1fa*-jH^lkj%M<&?I066H1Bef5j|7J!Gp|w zo7Plth2g+^(2IE8Qx(x9N1$6g8Ao%IXHdt#YyaOGf(k~SpNu~S9{aBH*>Pg(CPdxR z&thy6eC{Q)MQ%E1faSII55p%^>Tuep_GB2`$S&W|BW(>ivw$CU+5OEARjAnlEKrV( z8kTEy%-_)sPnJs}KUr)`XlMN*%zhp0(t^VJmV@uPU3~Nh+PT#U1`u3cV3x+cfY&?e zQXVdlxLaOMmVZiYPSEUCXp!wGB>r-KAZ+eRJe%DOXObc3R`^-ehPh!PK5t=j`Pzn% z+5J~v;r*irtsv&!oOR3GCgUO?eAYu)#}QEwT=7$?G;cU|_oD;$>aq8ip0`Y8G!doz z7u@D|nZjZCxi$<(2E~FEKrEJKhOlz<5jJ>CQ<1M-ZB?r!TEWC-boIsfH?`BLuNY)@A@1s0+0x7>l`GOgA z3!ShW{PpWSrqDl_{MR#U`#vstY$)J%2+F4ixh0SZ%5-g7xw$p@=gLw9;0FD5@peuv z%I&>EOTl%K>WTi`ek=e=HtfUp(2;7R>U;mF?a(_QWFkpabei#@D~L`p zsk$BV*dKBr{ig*e%8TD4T0cpq@Wniszfbl@{k~`+zjQVE^l`agY7KU`s#i1$3wxD4 zy~zG+65Fz@GG3RmMwABJI);hOFBoi+SBVffDf4q&#&Y0C|AA|{57DN$PYFU=w$^hE z$*J9RckXI5aq0u9L?@E)s_wTUhN84Gg3PXdaKiDQmTEv_&ofQ>qyuXN>b`n zT)7~3vPO^mC&D{i8%Jt~07ipkNS(rzflTUWA36#fdY?g28vCcsmk`z0lkjmnVZzQe z@Eh36mOZeT_^mc&e=YdMW9kp;>dbQt&!(`e`Uil%HVZm@qHr}f%)z|>!83e19yQ=e zkSp^euUe*}k*YC(j7vXs&LgwBD?|-pf{V5-Njti}g5~A_f9@iNgy?80m|@GHFpD~+ z$m+eF9;3nWczk2SK7#qv`0^!<73Mlbjp_{YWt+;eo{zoQS>RrV$0NN?Y8;Box3Kel zNCY?xtwoo1wfj*Lf=$8pc}dd-lQ^Mn^Ua5+Q#jN~-2TqmhLT)_{!6xx?_uo0a2$j-=G)xweLDD{n&LB=zHO!U-U{_Mo| zYA7+4E&r1TCeOJ*08vXgul^gIXo#R74d4Y8V7ms|>*?zD>ra|IpaQT#ssSgOP5C)41KF6AH4V>(-*}L?-$b{1{TO3ip4)9?D=3t)sfrceOnfJ6N0} zN-ayz+S5+@;h9d;A+`)_O8`*>VmvMiYjA3DGTLK5bC}X%4sSUz1@IlTqS9&igtp+a zhh+I6JM>Z*zY4@f&hWDS`;u^8(egLsCa_#Xby&jKI&BXhNGF-aZP5s8CQU)-){|WD zkm3#EFb^vcEE6W8>LIF=vY~nu+C#Nz4LXWb42cWTRWcv2L`RX0lkeXH_2RGArf8ifUD$E-=-&UH_ zY95^hDmlN?ce^mSVutBhVltgnb0U~M%b_J5nG)SGM7VrV>eQK}w@<2;6gZ91jz6oj zU}=9E39kD}jSg1@tA-UR}>ZrChay6z&OhN#^A|y{h8`*2u&w zh$);X#l|RC2itVu?hY)5jiI&%RahsUCiYY`y(~Vgl~(jbG;9w{1$O^Jy%gwWTz>zB zMZh0PnK#)zJ!bQ7)8|r=JV|CaQ5FQhkxX}R>hjru79Rt9y*{kWZsieP#}TU)5!G?wzV0jW^79Y(2v| zav2p7j8ySL7KM9J)7#qY^xvZ@--jzL#)*AYBh|=dwO9{FQgg#%1yC>dr9K9@!&D zlo3{LdX&~Sc4-Vqn@N@};EHuJvDoc0*<1Gtj9im+oWBcl|I0&HLvA0c9bwNRlcUJ| z`~FkYr4Ke&8-e!Z-fu2L|C4*d7s%@KC8c8HDbP*uT9cb~_~UA6$;lVVf`gne4jzdd zUNVGM4h}&sI_(G#dwap}{T3z71x-FK?Y4#74mzWp{Qc$!^ds7&qEEhJFep(7;_U@3~V`;VHrNlHfdhrqDJJ&}V**p1$J-soze z>-hQ(w#(bq=r9@*4X&<<=wDXrxu2H}apTzBTcLD7{BUfEXY~GG?P?5yXkAHn7x{R% zCZ+uwjOKjTrBviBG79>f_3+gn^)&04pMdZ9-c-!Lm&mM3Th&q^K}_uzHGyJ5r1C)H^1EyXjb z(@70&v%~7%mf9>4cdsDj6*}7>gdTk0s%vWt>+}Z1hNzSl+?j@;niSE2FmWe0Hzil+y;r7?v}sbZ?nQgh3)vKz_my3xsI=+X|hE!1b60#sujmj)B# z8`~>{x}Nl>zHLgde%;;`SZCis@#>z76Ms4UK`1iGZbZq+W}ZHAoa$t)p}y+bC0VLeWfx8U2^n1+8elqOI208Xb?y0mt}LSwq}8R;zY0B{HR;-e-ot>iSjwLtrvr9C|K8T#>p3U? zZE?10wrA_1F_BtHEY8h>yB$UKKUofu9{e6ZS0U*?Eu1O19UmnP^=5;5YRcCJr9y)X z-_nKF3cBpSkBb5Lpj5BJq~kU-CxGuDhNKW6UC5zX_rkF%IiiPft>@JA=G0&W7ciNH zJm3!sdfFw=DLPr#A3AA};MC>2XJ8y|(RUd2JRWk>8~Bt-)#fiIP`(Nzi^P_J#4q($ zLOx!5 zYzCft&GyjH++`y}e#Vg8j<~sfFAk5RK=<|tI!$zvsaE{7WtDmfp;@Dlz!3+HQjRF) zdUGoMU`xDcnY~SIC2PbTSP2TA%B~6?#{MLQW~Ca$(=&}KRV(#nDr52SSkRJmRD)Hz zkiqbQ8x&2ieV@jHzjA_twV|PN^XXC_hf>S=5=UdBlrDjwGAZWJWd3^i@NdJoE5h4IBrE z`F`e438#b^FpYlQbyAfpT{Go_Z*G44(F$-lw(ZlwJkwQ8$YGL^(W+9=91=5!UdMQm zSm7MHMDEc_-F;XVQP_$nmBU@-ZUeVg3^?;7AHzwd`%+D8NTP54fKh>O!LQ0wtI}$b z)xVQ)!MAN{)_&DHLRtP5^bhu<7&4|sll{b5iaq~YVYl_6MIIU_6`?ff>~2m7Pm z9#`K{W3Py{WAaXGzPVfHaQHU!zBjDKNYS{dGwP0e$UrY2@B;I^oG%s0 zL|)o(@$xqyed^wJby_i!~Nmi{h>^Nk0q0u08dl07msMC#8xNXSMe2 zFWRDUN+3KxwHe>U#eD7j$#X+d>-CK9n(D*D5$hCgG~p`W1V%G6KRJc0Ys4I`U40YW zY+~Ib=ihuVj&c>=G<2f3Xv7G40CA4~J8J?#>3(DL^Ydjj^&0^fhEalhN+5yPc9{Z; zsZj`}!A9Z%YJ#s4z$J)DVy4d)0{5X~UC&ZK7W&7&sax)%q||iLNVp-d+J9LUIt-4_ z%#4bU*Ca$+;6f!w?Qj25_{nq751XHb7zZkd&EyZt-9mTGKx`nKCJw2cPnUSW4Ve4s zT@bS>qH~{~6dqu6xL={%#-4$}p1g#aRA+K9s@uuEH2f|M=nC)^_K+>`Z9Rn4UX~OS z)5e$)b=5YhCBhC8GVx-KL9H0@?k+ZD^GXLc_2OM)6JnZ6F7)kxF&fD6Rw{Xae^cJg z`+`t&1Tg1przjhP=iW_xwuOPc^oCo^S_e+Z)?8T z>}vZ+{%_?(Wek3KT?5lYv%e%^{s#jL3%sGl>gwvBjKJfJhau4y$-p~nApQS?Uki(3 zG^=Z&@{RLvr!{TgZkKef!HK{R66fyZjPAXUy7nEHz0d8?>j6vw0jKQv9nBVE|JKz9 z^mm|G@ga09{1?^a0nX&{myY*Rl`&%ff~x3r{_9#k_-Umt@3gM3w}pP4;^7_T!sWf9 zjN-GP7urQkK-}*$$;Kg5w?#&u^rBn%-KL3h)ce)wcNc- zx|xI1%wxq+F=*Y^x-{X(f5=Vsx#&mF_)-4VR8M?+{*%!jaWW@joY_AH-A6{i^W@g% z-YF{AD0iK1wrz9Qmp4d$_r9}f_}NKZm3)|4G?GrUrPl==EM6COsDn7!(5$afzL|JX z+d?Oha84?WcN5ZcA&uC?CJ1%$t>ZZ+Q)6U8rh@3H-w;4q@FZCb-++YzaMy ze)eKF>2fg6S*md|reFeh+YK8?daM-END^L5r}^r3E6L<{KYlGVRQ?9I)k4-YP#TmHiF*Q5J+Ro3)wjcIc3D zhWa`c%b!6#Xv0k{pK?XM8SQqMlB0Mm)~n!t6035vbo0YLbeVh7E)Do6_Ol4rYuPSQ zDU)=x|7HK^MKOt4x)IirWZVXR^i;0(!eNBRtMgNMO?@`QxBgLKhdcrnl<0*wsPNIN zj4I2+Gr<)TOH)_GDyd9Y+o9jH>La#q_Ei-qZHaKr`~5W3u460aAe3dQ6yCS!w%n{4 zt?aZTDvVOP@+0NWp#ngK5yFl0r;+6kcfYv7_h#cYv}Lv^@D^obLVS4aQX}*A77c3f zx3wv(a+j&XKt8*XU$~bTbLnpgl^@%3KGqwD*vDQ;er)fR>3qSf_Hm@T5)o4EFG2Ps zYkDJ0acn=_v)!L8(gsV!y)$(1N4;o#wHt&a5hho()5Q2iRDglkZ<@`w22_&{SQfUK z+s}@as}dAtHqJVyJ3QNV<pp7aUBn97mC&WVQ(YR$ZTDOat$jPEmvCeB+z2{(t0^RV;F zUubOCc6-I#oyLIGrO=8V*zccVLLnlf@YalSiDMQKLsX#y1p*t!Vc`C?gR}LD9UI8&!z=1oPvF$&2(GaK#2m0bc7MJdm^eSFWN@JF>uy z?BiPgt6tzPUts9#^L-PPQFi$3ww zO0@k-L%aR(X)ZaEEL^el_Y|y4A$|(05=+o@y=;Dvdl>CCyGT?m@a`tRy?>y5M?p)? z8*>O4JZBHU)}w$$wb^kec7N>HabP$5YSI&{6YL=6xg=b|2M7wZ{L$OV%X4i`4ffAf zXkp2bH=o5q>kF$6Krquvs!K`#vQAyu+Uu>O{qE}BJWj1y&*eJX7w)}o4l(22Bxujx;dR+J2iP1UDDhKa7!DZI;RZs6sGYkt(vg^T^rJ`(rXh zIYI2uH7WyDj1~iBet@TD-8@(C^6|b^P1#wyMVTXDr%G+^&q#H#X1=6gSMr?lxDB8S zzWphmdRK%US6HN{`ljU1_E$*S@7hwQhxmM2^Hwzf+0dy~hjs7C_CnF%b1=-~`xFrX zX}3JrrI9QM1B;Bm;Y7$QWN?&nUb+-{UU~|R*d*A!Rx-6p+_$1kFx%9bP40OoN72N< zN-*D#<05GRFH!~aTOPij{d23NBT8aGL1A5|^{U1u7EXf`MZtKJhP8MqdG?K|-Gl{> zlHszUqPQg*$yg#aT~V7gn~zg&_^uT2((>7aZly2lriAbJNOx1^L055Lj+Cx>*8%u8L=y! zOb$B;F;blCY^-7*SC1j0~EnZDC>vP-3@7s@E5@Y$Uz@l zKiY07l%Ggd&a0wxm_q6EL33YEcrgC?$kJ<1SlO0-SH6gHu^UrFWwNmJ5 z)VMb*zx)tAP)ofAW>1*UM(5iBa=oyt1w-<$)4mGTBY>~a^BeGPtXB;CrE(~pD0z)W z680|`Zn)vFy?acTU{soy^t3{8*kSz;rd7qheWYIdh=XYu)qd!HYBgwSYah*@e+e)g zrh%sFp#Nxa2wf+x3?n;~Cm6JPKS z7E_OI@)TS*0GyC-<;~aK8UAN#Z#HrBUIWQWoWg8AiM~e;;tSBn$5up*c+)1r&o$Y|D3x?B(+JuYcQU2+zT_+=4~xN34xJH}suJOk03 zkSy6V&UuKz5%9}rR`sb|5d_Y@3p5&Uvstp0U^4aq6uS#>MUj%qDBLTn%#v?7rk;SY znO@{FCz-|;GNJ{yY(?#1t393G6o+=Dt6AiFO~tREN&vRSw&TgsmQ$Ro8GcT_`5s*k zqqsyYp#nUJ!4_4gEx|}Riu|R!eCa4(*>5K1$`BFrO%-qbxs$Hu@L! zRG({Li_?-?ylQrjD8;%Wdg6Xd30ia#u&l0gb0!`2L`Qz|y~`x$6p4x>7n=`FA`_R( zmHE&y#;M*Wx;Wj?WJgNVX&m=meBRph0g-*-g9*l_L4liML*%nlfWy$eAdT26XSyI) zErA7V4(v#H;Ic~mv6a_2QQ%OGdY6iFbf-G7rt|JA&!n|Yj-RoxTe{VzrqTp=g`rxE zCQCwnF02f~@swD)4n?f~WZVO8=RZ=$;P3kLb?EQb%4W+D-Z@;XN5*u4e-q`iW_=;+ z0JDxDR9P}Od;vG(qy6RTk^1>YMl6;AA@f%o?NcQpp@edswZr%$&bJj2yCsL^>%;ox-U%wG@t6c znL<(P+uO&T-wvEPiQ}O>YL$20cORWQ_VJNIVMhsTyDkLY_WNEk{O`R0zDP`pvW@er z#*Ci04X3VnAyC6ICn4HHxXA zpX@F=Pg$YkG0>`)`<$_U0q{c;bx-GaaPFq+%^-n1##Z8uss!hLTGV9NMwKLPbD)LB zH)aJ~E!JOBYS`SO;YI-;$a;g$0)^G@i8EOpGBHKrPRGnVy|VflV~89-Kkq!kuV!p1 zw?gpUj~Q2DbK^rq4hR-bm2w#C7Znc7UW6LKSe6gk^o@39_5`pjmB7uxjb8pdy<^|j zI?bspoAhe2G-^nh+!NZ|2|xqdMp|%&dSUHlEcaW}9L=N{z3S@1HcE#GEsTIn?xFUcs}P=zEddJE?oNkT`X>~FP67g_4_C71NfpGR3)u4 z*y5i-ZC|^GanDlloPVDpqN=jhespI%WTr3`&`Dwr;G6G?xEanb+AWsrmTG*?9Y(!R z!R!s5Uin}+r`Du7K4@^n9Eh69;Lv&mi?Frnz{O6svj*s-oISCg{bQJ4QpHE55+4I8 zQ`==PZ?2nXl4zutTAJ?H)~K@Xbfnjb_r~BW5OsHLgBbNT}EAi^9Q<@gku4|aL*(=?nxthz3t*u||N};eZ0ev{5Tb^ z{IezUkRx;7}&5d-digxluvhM&PvdmqST{b;z2#UuEr z*WfbMch6{1m_JplP!4IIZIQ@32OmB7R3s6ngJDjgP8ma-g=RD{A2p3V|obue6~DeKC=OM4%m4(v|} zqFkrS&rGS_Y(m`PsLk%;ZI+x#{=J$P;x9J zGCw4zx6ZdZlQ&Td-Hwq;mop2%aeP0ETx4hrru^{p_M$2KPV)A#2a=EST}5B<+%=6U znAM<-fLAQWE0p-kW&c6>&Y1qf#{aGOXv5~r&w_{8Iy#n`+}ub$EFT0o{@>B@jmsV2GRBi*!7 zZfUg(`ooTW= z;Blr4J#+p4p&Vb0sdoXvv*<+MezLGyVYBNu!}==+&J+l^PqjI!;@wK?R6m;3wBtH^ zxHK{|ZCI)JG5ZFnt$PDptA1C+Rw2c45xS3tyU;E|p1O@h7O67yV}q&n{Rj*8=ZBhbCjKl+Z6A`)8NLqR0E!^*&= zU2k`?*Jq__v5VYINiSr@lxEzVLK{GZ*-N44Q~QB44*sW$+@liAfXrCIJ#DrSqB)jePga)2ImlzdMTquR z&Z2rKL=unk)9s026}2MzXO0TJ&>6<@4-swDYuMD4sLb}+U*EdMZP2^idDd7iDf`ao zEL|>YbO>%qxw&eIg5pAog1oF#NQtaQka4xG^T;C)F`X=V&A>Znxxcp{S3icFN5(8#%f``@F-UO}3QhhsqGTT}Tc9Y0c9VQY`D+t#*1dJ2Wucby zSiAs6so6&}-IvaLFvXG2ZW^D*^v5EpBp92-7#95Dmz=mtSB2))X8W3dGV%HOZ)rOdkUG7$kB!IBU^4Z!!o&_ zcxGHF!rSrk>Geb9hG3Vu%>OI3qDcan77QmMXwz7e|GY@L_skgmw zcEKBRTsjFtjf)uToA1a6mhT)@~-?%Wu2!e?h$uTPI|3c z8s17)cEkPWOQMekT+~Gx*Th%%`!|>}FS6`hxajD^3#$Ci^tlE|f)yJj7;bJ+nKpJi zhV~f?$09>CXqBy~Yy`dRgEtUwby3!JiJY4t7Wke6b=a-W%>Rl_UiA&H6y3Foumf{1 z@|<;mpI=^q_FKrz8Y+4Jw}c6I&-Q`?S;taLg$(uY^*sv~=~`k5ND1^GcZUf8bbUkr z0)Of!N3zK==H;JcSlO6{sAYC@3V3D$$m|nnDMI08Oc!~qBeGzTCVODw!*s5uJon)i zmtgpMpq|j&PDrO&PCXTmAFrJX*a7lG*=3bIj-J9Z3+vqrhh9n z{=;uvQccAqFYLNUo@fH_Dnh^V%9g~+V+83d9m1&Jzo%zpBD?yVT0$=xMkZ|Zo1+XV zPD#Jb|6gq{k}HN^c9FpE)d8BlT@cMYx>O94Hu-k$taY8*@Fq_W1>V^Fbx?2a zj0tEjrRfzE_k$#7c%?FlGLkbo{x(+vV= zzvXb^%%>*LBFInR_IV!)J^N&emm_LwBZDm4(7AAB=7#rF43c1^tN? zBM2p}?@6M~L(4D)d7kDtt-w61rH6%X2%TImf4;(4PB0e>0{vuyyhGJ>MoE`m4P&=) zpfrRtVyhcz%bR#}CNG=Lq=yUXzaRhH+uEtAGn1^4=)M3Y5*pK^8z~c z0LZFSA#X{er47Nxr(|ox38!H*?jMT2upI=v=LhT9MjY7kEHtpM>rfAt%}WE~IxI^lVroE zUA5FqquB}6_KBu$K+6E$-y6lfV+TZ2*O4r|73`3~bN>f+d<2OWn0m?oPCWY>Z2uAR z;ZsO7)k?(=K%UyE>N6rM_Jd=Ih>n<8C!bpt(>g7pqRLM#G4qGA(cV|y12tG%+in9d zf!f6NrR-+0e|@6qmlMyuwgh#gXzxu|KTW>z6_f}QO(UIaNfus1)H}eG{UYh==TJ5r zKp>_D$P{+9$!_B5mlMz22GS#2|2*0H=O7=r-)VsD(qy@Ax^#mc)Y|V?_nibSP5wTw z++4_xy19|)JdRbVfU%N-8?vve5UkE7m5`jMxdTc}f7e?kLTB$kBI;g4dg^bm*6+02=kaH{`@Kw~#G=lHu~-5>367Wbs>w_Wvk@=l>lxJ%*U6 z1~^*j$Y>2Tsa&(l*zW?fAy0S4%49Ay_x4-OELddoD?M<-@{5S-*z)9L8(+qbo^fqV zdEdDgf2l>H`Qo!!vXxJw`8u6F-;3$pRDI@pyf)Ejk`8(QVY1avkPn~3bgx6CLq0l4 zoa{lRTL{Ppva%jHr_CtScMJ=Jh`c%U-57T;9yr~zw!IKmp81Ydr{qPhQRr(KOQMG{ zc^|SI$#GhnVv02sQ)Ov!Qne)XO6H=W%zgFkAR>c6SEEeG%fgCORSCO{>HkkOnnIK7i@tZcq~=ma>txrz88tD< zqaP_+(mK_+X%9LF(cafk*(fTun}t?QP>FzTB4_#SwUWvxLjgVQ@3v~1Xahp20`+o^ zJ789^Q(r)acOlvCBItBt(2|X@-C5E*e}8~{*EPX=xrLPPMl(e?9Vz zuaWn^R_cmm{YQuw-$vBChJ5%KnyrzqeTKaMRpQxK5l!7t(4uQ_`(%^Y6zLp5;yLW# zF>HDmF&%7n1Uq^LGj$`<*$;!qiUhRv5Uep~q*0x%=jM1C9;IH_`K;B6LkyK|aOM6} zYsV3fjSwh0YR&RhT7mTjn?@>ef6;jMZl^6%oF`&>!+1nVVm5~_VC^$Rw#iL8vY#5WM=nv{-Y?c;ZrsY&q};;L{Y8UT-zf6ppmFM64* zwm@5j`;8%4{8r+**O0E=$N1C-5ECQPA)2`p)4hiAu|FVR`x416Ul%d2l6;>5T*Qy* zsgIJbd<@Oju%pLOyFq8^ov6gk&mog|QCi&jJWY%VQ^-W9bhiDhJKH6SC`1qd|`OU!1xhfJ(0|q;OzPjCIvL=id8W-ZoMm$UH zLeFIU0^_5<>*hV4gWO3Pm}Gx(_N|xhqT)w#q19Ex0V~)8^>`kkVy#vd=a))6uq|N8 zq|L^TAv=r=?nBZ?9kZrb?*hza%XIraglSBkyWJDbA>Ef@d-s6Zf9(l!XD_;Vp#FF9 zxh6{61)7{q@FybMBIsI2tIl>(b}AtA?e9=X(~K-v;%<+qlaQr3*K{7bq_~{wf0dRhm=HptdJVd!Yw&w$Ijb#nM$v#0*zUpOQyVp`m1$*GH=!fy z_z@WF2eat@w?#_l*{;!Zo=dfe&B?ER4J6aZBOk`BJco8?P@RM15Ze6)8m%DO3Ah6j zI%HU%)v%dE+nYPeT3KMLDQ%typ4*hiVDP?Q8(89h7T?;qe_>#(PS8!v8anl5WaABx z&7)C@SwD_W?`Cw*KSAd&ceF>FZhLTargMF3`_h7009{9x|EqJsA%lV)RJGlBxuj|{ z`0(lF?L{ju<)nq(69SgiyEwZ-u}7f)arfI(uK{|F0dtPP;^Sk?PE z8t%lRQ8CWpe_9q$nRdahO$)}w)){W+0tW5W9kTgcPF7`JYbNtFtfYSa({zrIO~7-B zNss@j;~b0+qxps#J?^fXV>_@?*S8AyF)5_=1FW6e>kj3^P~ttRxJg!E5TR-z`ew+ z)W5N{0hqfpDs|OxiO5cUh^+r`@n#V=I|T?)_X?7Qd$FSz7@zzLbo3l_UrKk+_mV8U z-mx0A0?bq`qF|EChZ=q5T}bMrGKgotFGHZF#2uzqTN8Geqxvg1|G4K8<82(PUp(k*ZngmCD~W4;4Rgn*?!{AX`)6LYlOZmbBZW0!vexRBB?ErLdkv zh{mw-88Exix$l5{c;4f>y>ls$4xuxRz2XkWNtfiwPY}KE2=t!A_8vv!qd?qDe?S^w zNP~~uxLPYMlSx&g7VrhINq9X5Iy8Q7dByh$`{I4&_*x)W{k)bohL{!X^!=Fi*JDm> zp!*ImdeuKccV7qD_KK5U*nL@mC3d3_O@6rOT}^^cHh;{6G4k8%RcmccH9vI)a-J4H4}z|+9I&Z&uWa%H6GZ`G2L3c;}|B= zx?+Rcaj_<~wr1-BmKAeCQ0(|QG+!r~f1?Zj#WAL`wJ(wnpK$sT#-P>|e?p^i=VdW$;JmU$rbeW{TP_8bN5INkS_l^j7@fruZN*QmAJBPuC!4~Sy{~yGmlC3pmxY;`ERhp$4Zuj zN%p!#BAQ3cH0jDGu>D6te>do_9U_ZvVs8IiF;h38qolgU?}~c%)&VQm2a1~_`K1DobWoyV9c4(ofJlN# zb~{GPX>5zDX}8{*fA!Xo={Sa+S|Gy2^KK2t`+$SR-i->;X06FaH%pdnB$T?2p=&ub zTgvY)op@lfnR*Z2BgnHe#+$;L{21JIzb`Kt%D(!1n79wMC+J6`6(cC zdQSN&q~AcJedzRCA)1DKR5~baC3d~g9Vl&o7xT^6CHL|de?*?=r7bfPI%M9V*XxkP zg628cL2=-@-^=s-f&}j`&X?;ymEjkW@gr!w$Ez^0Nnf*sRqjSrKs|BRupLAi2U3l5 zEg`BcE#i8Okk@OiEvuDUux9KD7=9VLH=^;?MFstmTFg#dIO$?9yNz*Y&M~K!e+PI1 zm_amlVsd`Kf5d43rZ#)uNw}zOVVTy99cihbweuTV;T6$9%VyI|-oKPILFFlIN8q}D zKzh^nVlTfAS>NDX`#Ue*s{kK$9n=39GWb+M&oney9(7yII<2}TC~h6Ma4l7h?JfEc z!Je`}?7*D-1ZLxdXw-A1}_!DOcpyM}5XvFl*h z>87j1vJ1>!jLe`ii$;rXT}TIwUjoUsF2J&5r*-i6?SA%w^EQw#Sicgk{{|=APeOob z8nFW;-c2<9vcg>~B3u6=*iqHB&^VXsqKkgz)Rxx45-(tS*E&noWUu?xqB<^SSId#B zfe~)of1MWCiTW0|rFO|y6Y5rU^b85W=6A=L@&-45T0ubp0BkYQf;;cTkSx9(6TRCN zsYcI|_aDUO2Mh2RYf`8*$_2T^SMlC(+RnqNy7&$z|B|ICl6XR!(BmW5jc>Bp*D)c;(|n-K$9E-{|Ig^fa0e ze~@UZwAyYuHu=;YtrgXB2Wl2$aq(VJrRSn8`$*e&XuF1-gpQv1Iv7K~{#o+=*HDQ_ z=IqrFo`WMOj4YkCWa>+P-p5Yari}lZi7Ph;P&pg}r*)G&- zJ1mv9`uk`4y-VpkUeF^!)v3;p9>R`Y{0lPr!)#6Yc-WPDwfWKnFrf9q$yJtjx z-DTLl*CFfU>N_brz9-N99EhBtfA8RaWaEEQDUL{EPc$8bY8)cZ=|NSzR)z*=$Q%Dg zenVZUzqz-HO8od?Wc{zObKir;SGo$wrLsRR#`!882bScgAbkSKjv&K_knuM_SBrl3 z2xp@k6^UYuYJ}K6CVL*6rwDmL;zUq(E02l@J!$=AOa=p5-L zFvH|7alo!|z?IFg>2b!(AH_%v(Jqo*ZzGz29r@^4bbQcN8-2ZsMjOr<0%&cf@qPvI z+~+cMlOssSd>xp&XlU_MfAznUO~g@^@O%59uYjm67+6z?bVz1ycWnjnJZQ$~=gmH~)Fj`5{U2&vwt*k*ZO-DQ=PyKiG0tYB?9 zr={+0=Ig8FUXf!fFK5N9W>-<{Xk)X8r_rJw zNx<$3j1TH7P;mN5f6*Lf`WCPQ^1)+3h8-V6Y(_lua^l%L$ksktNCw1C$0Ufey?0hy z=+xj^nBrX|)3-R#a`>cMSEh#`boT!UCfQduNHsL00-(DNYK6tPS`gWKrd?8b&l$mz z0^A!vf(*WZ^gjdiLFUnDZ*hJ!+1x?AD!!JIG!Yc_ScqmCe_;yA2blE_L$rvUz89Uo z*To2SP`U41!s8lWjKueBmG*Z+7573u?`+2Pe4g2+puE##diDphUc9w4_`IW-nR(jO zF2akt@h6q&m1s~QbVzC_Or|yMh9Ed=R2ZsCkkq2WQ2Ad2&Vvhri-1@nup5v*iKLIa zWbkaNYCF7Ee_a)ONHq8&GPn=B|29l#5jpt{7_Yhtw}}FfqPlhK_I2u2#rz~)gP#iO z1X}A~oy@P)G>&Swr8K_#WZnrott6bgN#DF;od!gA5xeUqbm4Mj@FmQ#S#<8*g$~4v zJwiHq3RJO!hnc$S<-`lG#g3nI?1h5fE;Xy-fGww!KJgrh=8@z8 z=sNlO7sxT#@lhmMAX#`D@yzXv29IKrsj55FcVDSrV&#&kSC^~PxpASM?L0~gh@o|0 zR9mh&4@6LH0dhS{*ZR5bxBiK=gDE1Y-N23ye=$D(N7(c@(bP?J_x~vI!kfr9zJ{j9 zKu1IiZ^WiY(eyC$`)(##x~l*TZTb1b4w+i(XIq;vq20PP3Ngj_OUU-~lf}ka?G=L> zj2^$Oq!umNG9TLNzAV6YnRTr%f&N;NWO*$h6|=T3@++X3ON_-})1yQ)w-e9Z6D%Y< ze|&;$-JSoF?{B)1;|mO*FIsmN5j%u@gl4Ob?PC(qoNVQ9Q7oNZ-$r-ekD!{8t=-S) z*ndORBGRqmkHC^v8W)_;K5^`fiQ|houNJ5C&wC1I6U~d|;W_+NBA~NmHHnm9iC3G+Q z3DQ%4#rXJtM~N}f3=+>4zn?W+_SmGMvI2ry^alg5F+nA2aSYphY}+(PE>0{^uu1_L zJ%CyJOEi7K?Ll@IGaG`=!MUi_$cShiaSOrOpoBR&MiYpZKvQJ>1CSqux$i^Ge@tPo zZFe-rI@kO)KARxoLRuu9jg8`q5iHq>@7VVH7h_B>^xE0lxE3e;_%S3uRM-<5>hyg- zNtR}`#)MWaEd>La_}7=0dCldo-a0ZlY^3fgARZc916l$qp!jZ)MGz^dOd)n18Gey` z_KIR#=aI;sv2K z&_!tw&HWjZ7SXXlR9$OpMnmwc{45fqQ+vtx+=6yz-QAn7!T3=aJp#$qsOB$@b4M&P z{yL=3Kr~0AO-d?DRi!D?Si?lZF~zfSn^Z1>%2E>t6b%_-VHrA5WOo0Ie-_cv!6cQ zM8mI;_wIzLR~LbjJ#7-bnT_HlGp-_)UQ2MEXqdK^!F7wcX3@stw{t4)OziCbKGbfI zp86;6RmO3M*F!f5J8{C11Boq|ikGo1LOF_d1frZzJ!2jnVNx0_k9qr2<6A z+#LG41u6kRUENdOspm5Ry%X23Oo~XA{G9Dv21$#y-N^L{#O4W*-;PoPuM}TA+8ehC z*e!n26hpp2dh&yA3ylvU5|OTcnq=W#qTY4Hvv-lMev)kE6U6gxf5PnhK{VSSu`$xU z9PGHJqv^G5O~5v-nl-AJArD4E>V+8UT`StcaL|$+Khmlg>&qlzHWocA4+C|+Q=`XFn^zsT&& zoQn_RJ&cz>$oSL;e_bnlwCJ8~dgN=LX1M+pB$`Kch-N1dNlNXKz#U7a#y_pq(6km~ zNK%RbUzBrBi=vj9hJ2+2WJBOUymg~tT&h92$%~abXtqMue~4u6Rm8J*lV&S`5KZ5P znhyEkA$)$5k3@)1G_oU1=PIJvyHUGFy7CEUO`NR|&%X&fe|na5^*$uIoOt0a?p#Zc z6?cwQ3~~)iGWdFgwYX%WG3eHx)2~wLmY~Dg-XYti$94X(fN`<-;B!Q4e}dJqD`wPV zWswGeB^sWOz94dWJ_YT9VFP_2CM@nQli}B$=GpwaP~&uLktSkHO#H(#C&(DS9{1?6!0iTQ>fc#{sdS1nqp{jq?t}(G4 zERGJ}#lxc&1X?B~^;uerWa1wofl@lHRk%jat4u(fI$^jtrX+USHsdEj`>vv^TkI{~ zWRINJJen!U4k3e2L!p-LK3|S@=g9Zp4l@UcPCWsme^c&RVoHViR$E`unx3N8BwgjS z#Y?GMZ`S{==F$@elg*lQ$W*bAXVBY?UAhsS-h)PQk%%amX=L;y@KJQvKf5Sr-#I7R z5+fU*cJ{%AYl`^Up%?Ur?3_0Bc^UxLWKRe*2RG11@PkfIaIT?u;+2dhAe(fN>?k^Z z0(!4uf6M*%FUmW_fJu=27_#=~$oQaZ(~!6U5{tBJEa{}3%?ApoyTugCMJJkDt3-oO zpy^}i?02G_mlf?$de(QyP8Lv3KbKA%*R>DY8i=dSj*vjZr!HO@x@45+Ry0LCbDN`> z4<1Hj2{UsmNKCf=RmTb`9Xz}pQ_%d~{A7sqe~4yo!`eQ&@g;1&g2Zz~Gk0K?{|1{L z!9g>hDJywrBL^StG7WTan ze_>oqmw4BSMac>fEb`p=Cg57t?xn4T9xa{x8ce4~91_lEJ*vXx551b1Y5%1JQpYAz39b~pW^Fmj$b{Z|a6y|a(&)<%o_KMw+BI)CZ zU2~OBzwJhRfxIdZtAZpA0vlhEe_d+&7ihEBPg|-Y<@+^~?@erq+cd#AC@KmcvX^X|JFF>k6Pl!~Pv$g>(?P7ang~Dc#57A@+yXR(f?sBvwvSG|3i5ss6m9>xbD_pn zQAr#qZ8yR*IHXbGA3*l}Ae}w`fOz4}AQ2{BA|E_O-harg*J#!W z>WV2vGexGWXXHbOc9ZP;L3H#iqwyiKwa+r{Tux`{olITz^JsPge~A{s^cbJ|2zKKE z#Pq_wQ!t0h#Iw=5C>2vi>yWeqZEU>XYfsd(zB0o9Y-y9!W`Q9XTWP;5+gOa1_HNyv zzPioDj*#BfbauT1O^-7?^nYQJy{O$NVhf!8rbK9VihS*}*k~Fd!(`A&?gh=s``>V5 zk*~V*-gMDyg?#WNf62lXt|D*8*nF9I>PDoq&w(_-EmW^ud%%C=J`1y4zm2MD)1kU! zy;@BLK-Ax_y2H+M^Et*;aybkW=geh_@%8|@6133pdr-EuP1a%*G8u)??WLw8=YT#_ zfS|_Pz6FcSZ+TM6gudJdCaTW6K)b6p?i$7mlXdE<_Cqwee+li}=$v*gLLO4ZVpFK; zA*rp1K2p2ql^WBeinXLh?sOwy5Q(wrF~-OK2-CR|)43eTvEygSM^C$Rv;^)2%rx2R zXUO{xVbkM@1>YzALOUV2ajXN&llgT=E4}T zNy4*RYT!@7EfT1L_dTGlRh{(9D6N&oLK8y|5(tI@l{SAsfBHIv2*5ab;;T3YS6hpbGy8-cM_1;jG}y@ zStL6>m)mQ@AmRG9yE6DBVw~E7?@x;X3DXG`k#RAjUbDc)VWhVHwGP}gHJ>H zY>`AoCBPx|;JV@3;oC9Ps=_{V1lmO~gWhj#0js>KU0wgDap@}}J;;w?245!cy{ZbF zq&cozJzLwrkgl2~jf0-$C12hD6r3p<1t^(piC3v;yS{1rH z!zXn9j_Zq0pTn%ZA8Xgqsn-^BV_#f%mRbk;#`~SCkY+_d9#$r+BtnC(i$JWj9$bnc zA3VnB=Ao+8safzRpF4k_4p7=8~ ze_I6|AqeTpCm>tH^j?a@v*_>{^5GLsd&7?1nWS|ckT$Mf&2mo z80|UC>E9*LQ_6`9LCQ& z0ND;vJ3!17Y7$RVqo&Q&*zYyHf0>d6=HF-5X}6hKwo7~N!roiz(tHymgD+y%{~EFr zsF@9z@{IsY!a`KIcPf^BC>J-0%qMYSAtB)9OtgVk5pJV5K0OBjat~T|g zE^?m!O&|NYX%#!}b9UT49QVvPRi!7R031e=Or&Dz&QO zW>%`@1?*FYwXOG+K+9xO@e$3D^bkUhN*uQST&!0VAsY`PqX$r#ZZyr5ppebnKcfg; zxB{8p4byv&{!yfV3>j}A`OtwU##uX-Oap)Rv`#7ZlX5OdI>wT2kkDQGy5R!e>#1Pd{k?8D8elTSHiK7A4P^=Lwm0&`eH|1D2uf%u^c1@ zO)-PdAodhUw_=C{;;ZfM4*{^)QeBru->b*Ys9|I?VYzkuv88tox$=g=mjq&%}i*2$y|e@n`Jr%hl*2yGuH zlVD;;Y0qB3tbGtA!%n>(^xVaFFYYTxOc#=CAbSq-w51Xmwuw|pd#g204NOn4gNGRp zpFrZ>pcythfk=cD4lNUaSv1EEpT=%HK-^tm(*A;UA?uT#_zP5GOg!t}E8iep{+|%t zheY#W*U)SYF}+eJegIFpoQiK4OBDM3L2FO~TZ_#v-Ji8djL^A{;xZ=&H=>bzk z+*L4dCoVeiLil+kcIO$nb6XK9{=14xg4JHIjv8@!Thvl-(X=Co4-`%^m-@Y>Mf_$k z=`+asM<6=}G8Hgs)OWj~MQpkOR<;zb@b{MINT$9Pe~J{xj)pBdI%&^Ikl}+E`5)N1 z?{P(mv#=cANm-Bc0!%jhkQZ9Gt?juN@|kDzJ$K@HlfSzVi({wf@=V|H{GJ!N%Q!uR zXjafJy$$YFwu4HjN>CZlvclq&x?Od>X=hj+#99j`>&^laSma7e=uBPMttOaJ7rYBE zs@%~Vf3s6aythiqFVcDy(}DCjk{xumqGq;MwQka@#ab9|I1Q8eE3k71kaY)|n9&N7 zuA^DsB`Ru*e%FYJt4GbVqlFmnQ?u=96Y@YHShJEstR{x;9CT;VWC5KyfStR{t+hOZ zY|vmJHK?snsg(~t4V@d%gxvpF}Ke?OxLS;5q@_;z|_YNcT^BC=V47?L(a zE8#j!)wmTy(9?(B3a+sD?K!#`u<1Z9@^u(|4!XA$6|DU4*&Sk>h~Ma|nDq}qdI*xj zfrU_zEdX&_onk#rg%)c@Y2C{b3RY|3@L}da*O2uOV`LWFy94NyLG+~`f8=1g*yI|_ zf8c&#quEC30a5C=t@zBidM|kC2x8D^mji~g6;uRM1pn&8D{9^EnO*^S#E7gH^JJZ% zUc6NGypy?~je1~HY<9|>oACm!b;<_v)^(+!_<2mS2eNg>$Nv<@ zhYQV`F4?IMldgRZ%~vt;Tqq1b(OL_HgT3!k2MqArcS5o3Py?ze7?psNr{AC&f1{nt zQPX2HVfiz~=UNw>l?dtG3E5%inqj7!3|vot&IjHDCWQaz6K5aaO**)YmAc7~v^2{} zLu<tvVIGqC{==}D`R$s=Y`1S;{@z;do^GH*0dmN zZe=9^Z03;urxCM=&b^bfF|hEv6E1W-5N~Co&lS-*U-8JT2$`NQ&FNf0e~J3IoNFSp zl@^;i&3mikda>s6TtDO4|DL!WM?K|`^GOe*XLUL`QNshe-gk;qEuRGYSa-OXs8&X| z#de?c!De1Bte=QXEdQwW8WVss6V>(5A*Ys}wCJWV5n>xZ3Z4C67S4F6Z)HBt8r799 zvhe|A^e9C0K_FKN<<_pmf8vKkEu?*Sbxkj!GkdTorhgK%`aCi`<()`+L*p5A{z`OquUiXwhNSBr^+y^Bd#ko@QF)c@ z2&7NB>c1o|x!K~`vAuH{yY(}E!YR%(5#pt_l3syJQgc-hPZ-yCf5fRZ^Jq)*Eq+T} z(|)_!4-x=hq2+Wv05YyRRERZh=l(d~^Zb17kZLZAUi6`ySfu7TQSbINWrqRwVoQt#9`P|Lhb4SKbs1eZOGuJE1 zL1U$t2(*cAQmgJwe-aC#PQYA|03;9Dj+FzjguHZf4k zZ;L^S-TOwf&Tg~R2@0Lz{K{{r@l`9RXuUN>!&qV>F7MmKdg8RGBF3Qcfuc1m-;#Ml zJuwt4wtF*X_*uwa@EC7WGGaP}cpl=Hp!xA)57WvZ35UG3L5#XCPJM6Ui4?20 zyI)mpO`*=8w47e`M)^Qo^}IX(yk#UAE0Hmbu*O0zZ3HHFpB2c2M;w7)JUL&aHNYr)xmug!)T@=v~YR9#^ zqb&&ue*@?;yv?3<`WVsDriHz&0*czuggDJyss($@C8p7w7gS4Q9tbLX1c`3ht^?Ta z9J==wH)q)xGdKx@#5&YOC^5FTh|FD%_LflN ziQU<(c%DDcegIy(af{CpBuy&r5*s}T$+b@Ke@fFWvBI5|HYEe;Zu_)c5p3*t(k!?TA zC)UC1$m)Mb@)Hm(lxLkZqfHO2mDXXdYaVEr--lJ~AX%>q=J{`GK>Ntr2VlPE)bZ`c ze+9ckw(pLdthWv-rX>*fjvJ}1L61@8>uYS*rV|FO?RMGH`q`RUP2F0zO?RervpL-! zZ2?0AmlDB&-4Y|F8?yK|i6I(usg6;i@fC=C67KmBGMwcVp&Vr)bie zJZme+6t1AEVlHj>A%1HPHT{yw-1gAuGS`x$YukEGrs zGY)8*MV+?85WX9Y(t5sXAnH!o3Meg>#^NRY%?pl(^JDnO!GdhNVytPq`h7} z)iGjvB)h(oc;Ss@^+>Z53=jW0cKEboP((At3vZ^g_*N%yD#F6_GmK9BIX3-@C+1lk zG5IOtxwq5Z_rpac&694;hmfz4u6~kq^^?VgY#M>IY)Wq~*bR0K)wK4ze>*vs1siAl zP|-7K0tNtn)k3`RybLais%0>3-lZdjS9{#S&g_Nh-4&}x3Q%ga27^^3?K?*an;|xZ zYy;PR5kZt-C4so({ym;Sy9;P<*3pC~cdap46FULahK+8`Or)jS6~+uLi97~|UxlgH zK<8S-ZoM^Od*?E8f|1#?e?<^$Jdw~z5FstOg-5|vK{YGp*|Y>*3U=()t3*ItqswYx z393OK^5ip=+9RIJfz(~6XcLt+h^8?30y=#!MDwj|tjYe^D$u+0hjRzmK>DAA?5G=m zUw=S1VLt^88MQFRw-;;)a_Sb04MEOE(B-vnrO&|dOQ_ie(c)Rrf1I~6uG?qVS?qo3 zpwZ=+e9f`1iu0lk|4^R}E+GTJ7s-{)s&AW&W1BOT__X-Cg?%F_Bzz}rV{1$*ao*Y1 zILp0Nq%QH&cn>zd?u^<%n=?#I0hlCEFz&Qv{k4hHHXOX9nLzt(Q4R6wmJzGl3x~`d z39Mv2s$?UnuBV;Sf2tYaFEzh~sBZJxG)b0Cfo0$J)~_M7*c6L205O@i5%D+1@>9wC{}Wcsq8FXbNTtI@iMBvo$7lO&rt*e}hFf*X0vw)iY^oo_H-- zJ~_w_u8bF_OA8=h2Y`dN$L2Z@;)6}?lKn!Mh0gU5?Q$*VmvoYrxT4AUNyrX4P>xD> zCeSRAb^s$Rgapx7;}${0$rd!mpPHdX$PO(3+Ben^E~ch`ko4%d@PSXN?;g!z zhfgs&`k%vqz^;+({$5PyiW)t$=7%19pIUNSJVWh>f3p?YyC8Ep`Mmv4BZbIR_?fkl zh?Oe;rMPNMY|cmjtpl1=Kuqi|Wtj^7Z<1M<+58cl$}C-iLiOR zvfD1Jf0qS_Vf$Fy2UVivGM8X7cI=-?UXib%IwqNUCDGjNLyqFbO7_cL999M#H;G>%pr3e@cm z!{GCX9ThEJzU`{iG%BcRH4tbRlmgTuwdCBde|mcrNIw~^fhd)oDHWAnVq|bX(zyZc z?1OA@Mxb{mMc&#!fMZZF^R1AdfblK*P&-pcpvD(DbXf*ymq}0LJ^>-JxL%r3Qk- zf6X=>f80Ww>ngFWyQVbmu39@`YZTR|}2RWH2fLw26}4scqvi-h02 znGyz2PbGWe7>>T^tKS{rjfVuR6RD+|-J%GRZ{L}xW3+Q6Bv&HC&o^_UhGS0+gz(!7 zYH>sPRrPePgjxgtG`OFufmCm;YcO_Fe~TxjO$t>gfhL`PEyR1l4lfbVJqI)AfXZkQ z?4UTeO^t~`O&`a1AP8YgsexP45aX2~aW7jrq@{JVp|j;ZtA>I2Hs?~;0i3Y5bQ23* zd^`2Y4zn(nOm1>5Iktbna-D4f^-T{MJP!R&6@@P)Ona)m9l8%r*e2R^l9CW{e+~Fq z!NpW_AJVXRFgeFWl)4UjrJ2%!>?Qw z#j7SFk4EJ22%VjG45WaD?B-tbwEC=NwXG>SS|%_pf|*hW80u@cb}@;We?qdSA$8*Ur;x#Yh~20(ji^`PwFZFI`tvnZu8;;Vghrt12U_*C zFg#!VK4*0-z5FCH`a0UV##zzorS3j3(b#xtkvI-P=AEFf)*OTIg7aD>R=h*K)iS%r zR=~gWG)%O8_c2wa>GYtXeY%FpL`%(($`%?gk=I7+ffQ?~N-%Q7f6SxN3}k0^IXG>2 zDoL4TiI~tP)~hmCfp|0jm6of3imY#nr0Acbfb+Pf3!-&e5bOoK(J4H0n9-nr&(H?e#U+L$K5@MbL?wW9ZR@2z4Wnnj`o;@MY`EWQObg>AS>b8kyqMb-~^ql;d(*tQ@E zi)2qDe}gYM{TWP6p|>t@twp<$pC(AHzN(GQIthzaG^D3*8lY>_uGo8bH8aTQ>&WoS zr9;Du;}WuHe7OUJZR)ib7D=)vGA%xkAzqu52T;|Wof~IeA&lHe<~0m`(jp>ZDySa&L5GlBiN==|Ou+Nme_J`28K6@z4{P^AjS12Ay*)n^!rz`G z&=cX>5@l#>ENDN&%V((v!q$8HeLaUZ^@mVs7o`bus)nv$J^-nWPgwn~ir2bGt-N2` zyB>H_9gynn*+N$)+6U6R0B5GSs(pMVI&&|?O9jiavbbqVy8A$4*sLZkKPDp8K5P-3 zf3Lr{P#d$_-6=i9GvXn(vBIV3+W54mDFUSH2Tvf;Lh!-EyxYTcRXutf)uCil z&bB4zeD_Fe;$}z4@Jo(eB5@G@X)9h8_R%+x6{=u1q}|qQ=k>13rfz%dn`@{GqfIo1 zMvsl3i_|V{o#?UnE(D&DL`4(#f2oZTWGBF$WUEuMt$Rx%7Z{{R%P*;Z8^K%>RdM?fznXa{?qJXb&p+($vE-R}i$P4SilTcZlgA`7zAse?cd*tfAk7 z)M>KR+iN_)a?)B7Bu~wxOw_Ap);4a1rTNuPttI6Z%Y^KN>$g4&cFCm?M>wl-oq03b zy{;H@g7Zn#19C+Ik+zf`a)R?e9`8>L<@)%Cc)u+hE;Q=78BH*Q?z!bm*Z2) zT7~cD1NlC7QU7$M<*&a^8b4p{A8FmgE#E633~774D6qlZgiWtwXY<^9O_8`{7iMqi z7?P{8GjFTJ^}W_Hp+)R-0y>J+5;<)hj$rH>tWZxbUTQYsr9nW|f2b82^GPM*tJP|f zk`Xb2XfHbb<^puG7c4eA9GzouU2hk~V>fnVH%?>Qwrw|dPHZ)48rx1|qp@u^w$1nc z-;LI!C;S)czm^p?_-%V_E|`*1aI>6j4a9eb{3v%_IJ># zOi(r&DkAcUC~ww)JQxx zqSbL|iEe;+SXgiGEme=fNM$0ki*0Q`pG`H~7t`UMJb=cG%DNK}X-gm+Kq5B!`>WkG zF=E0w8mVmwERV%YK;)x5OoM1*TFrAQbnCRHfQC$igD z{{&^tJLC_z{nM#60%bLtv4vM4WDntMM!OpvSY7e_mAn?yS!^D{ooOqoocg#%XGo@X zLS21=2WEHh)p+L`k+nm1+6B;PNSvNbHC-MPwreOm6dS}_G%0Eazn~LuVG}rBO1~0> zBaPZr(di$ptF2$-MD&)6&eI$D)QBY6MhP~2$uP3#%C;(iBX!H0MW?^RRZ(F|@FaUH zXD`(f{cE-2Tm;Thv*}IOhayj!9$3~sU8bp-4p^lqDJWI561KZfmT~4;z*iw=MnM^E z_CGt;H+9w4?hKgj;Jg&#WqHZ{YC~)BCXv~-vj;OVu8aR{cQX>Q(Gll?sSlX!Ksz)r zXL{4`B6P_i6h9jw`#^r?!SD+B4wKpvQzlNeQ*M%e_#uXf8lB2$Qp{4Ux*>k=Q!p=F z4}`iDRUK&QG$@}G;eG4jJ;szf%tV}Nb5~HlE}G0=o}BXFppQ8B-fWE;xY*;fTe@YO zXk=Y6Q)Q4g(C?CifLcpoagu7l%vdMuOqpGKB?mR}AVtiy>q?`tC#m%>g537cS8aX% z$q~yBs6H4GHH`Q2vru*P#8yramFIaIU}58jDXx!9E`n`gdl|P)iKQxn8I79?jzIiX zk1^oEmNAu77b&h^MSWxm4uB9x{#1krTX(wNySAzTfIxt2&RYs`$TO8J9!_u-&~PE(L}q8?9@7(=je_HTalK^aZwk( zp280jvHAy9?D4GCM6-ap-c3|CA{rW(sb@C{mZOf$k{4uDIoKGh`htNJ0^#=P5h zejN^NLam|ALp|^Gb5^}#z`fxgfJa)wt=Z`!#{aW_l~jW|PKp6ki0AjgQy4bCR^Q3w zF?N|#)Tq~2+Q00KA^a}L9OA=VMIOOIJ-@yXytf;xp!FaONr1OPhr?Rbg>Im-(OFtp zwJY#C)bnaOrRpvUT=Zxsb6=#j553!YjQ4(KOP(FHq zlcG4Yx<`|+-IYRBk$2w>P%LMB88Z?j`lhS)PG;b=HsF)z6W*S}*4=;0zPlXv%rcKW zEloti_B|Zcs+s~a!J1-KJs=++Tb50>G zLVhRkCltcEFq)QdBtf+KUBVh?qTc))E8|ah#axHklYgJLuEa{}!2iRy^y}zN+3=04 z?B9Gb#qYd3Z>ENJSwJvonyASqdNhzR6HS~kb@Vo~*Qj3pTl^FT}M<3a7n^48CK77$j+LoIRQB`oCQ#M! zHR25Jt!{3q1S}~YaaeK^;G57|<7>^vw9Q3x>KCMn9K=U~gkmi^F_O0sav%ze+gXOf9V zE<6(H{dlEBIC%bJI5~G#Sgay$_Py8^*wbn;qF=Zz6G8pD9ymv`m zE*m}sBoU+Rs`%*H5gMhu9LnT3^fC+}X^(@NIOm1P=(Fn-bS{Si z#1g+hqh-M+^i+KtC_E!dEOjaW3A8LD)Z3O42TS$shYfBl!PtcI;%xmK$`&axh@bSQ zn+AW`_h%l|yW=&x6=D>z+(Lf79X|SMHAA(AdQv!;o;cmMnKFi=oh^bSH2tklwO`Q>`uHp1e<8Oej*>vJqd(YI%%4QEopW(Z^|Ev`Q#CMk|SfOKb=U=?^4 zo>e8L6_DLKmWfU9L>YNIjj%BIH;IfE77lFrQ( z3KE5{C!62L^EP8^{O@0gii(O7eWNUea8QyWh9Y0DrNAv-BE`Rj8h`dB10ROn>(qZg zBDjNGT2Mz5+5SCu=#b zh#GY1sc=|F+$UBaWBBBDw(S(oCcB6H(>H*k{pjp{ zIK~_YmjqaGUIyeAb9g95mfTCKbb5x3f6mxMG@RL>B%b2HMZyW)|1bOw16_xc=B-3&z7 z+{m-^9VtP^N05SX_MUc6oj1rcQbE5&zCm03rbuqUQ66<}C&uZ3-}%o)!b`ng!o2wG z(9b(B<}4w(1{p9aHeK;s(o|%s*342DEECwhK5Avc#)dE0_5jrk-$v*qNj$O0tYs}n z1*JI&E}Nn7j&@=wCx-mS$rtzW6KE3nl%&J`0Q2EPS)_C`gJFBQ+zM>2L z2pZ}v6%1^29U$a;A)+VLBYfenw=A_c}5v&;#5^txiqTo@9wlwAYsv~Xa*046uY2$$5Y)Pfq* z=Jcs2G2meaWN;c^qczV$Bv>o6h?_}V2SeP7uYB_;0me|7pexp4@k6nDWUO>DUoA}# zOKRhocdx-x*O{Bg4P}oSZ3C>> z7i+2Zi51U>vKA59E^~pms89o`tPx4$@)Z1?X!}?iIM#etud1MX&rnslm~+@9WXy>z-HFG0yXX;k)|B4$}vO zZ5Hab)q?SqYgT78yW#^qIQsxKiM^GflBTz|5eM9KC>-Eu`_YaEVZ(A)lztFygCRG$H;wL?|(Kq(-bwZU&s9 z%~RH?gi~x!F&9_Cvu5IWCy}%}Dc~A81UsTBD7p#E6E+k}vbnL&oMlOMg!~LyKG15E z@{hQC$}v8#1#6<>@MxV&Ub#o!Y1K5|fvzS0kI`uRn74~VJ63;lYl})^=Wd+x>qaE0 z;3O-@R~51;{^W(SHtBnb3ehEOmx1Cy=^T$*=Lt$9Xt(;0n~V_D`HoZrmsFR6<4;e- zrbA2#l-2k@={qraJriBupebbF++bHLitqjR+XBo_&G}jr49_f_Oh|Z z;1rs@cb&`vTCzrYBbe5tzifSUC3u6WpgpK>)vx_| zWowEN!%u zHXnQDdK<}ZfjOi{b~I$U%sNj()BnV89~Q)Da2Q;59iLGFEWxhPD|4KMCl&u(UmW zX5v(>AIn6(yWp6#-Q~Q0COZ0l5!TWt`p({*v(oCfydLHRbW@aWkm$Cf5DF-CTxsO5 z@X|2sd=-bXs*9)k%;w>cdu2LbrW4SIK6kC5i5kAmeC+;we;agsgCTyI4o^)_-=|fvO?Y;4pdek8kqFd)+@NE}XU_s4uv2ffA5o-*@-fK< zU5_grTercNd5gLdbeN@CcYmp!NRIP8J$#Se1L`P>2om_^U+%}6=r-5(o#rxsa!q$u zd9%rsGKe!8y)0th!DTJTTf31>*nK>LAGSAA_s{ zfG`ODC~;2f{)CHuNo~-ABkj)0_of>+@9V@cY@5HYnR8%Ir8xiY+{~ z5DeFzw31+ESddgM!A4qadUfH(OKrjnXcRaHUDq7fpD{O-+C6va44+3GWAl6$1+ifB zQ(FDh-~5t!@5vG}4kg^mw^QP$XPbFhjwj?SBg`1`cD$lUO=OQl7Ii z*Js2@tMPZ!NBN*Ob|tno_l3R6vZ*2XHX`9*&@1H)SDrm_FrqVscroy4xV`Vm7dk6Fh=8dtRo;dEla1$EG z7a!pfxE6`jpfrFXogxf2p?0zf)QQF65oR8Wo2(y&4g%kZ(n@WXa?ZF#{S_>*ama|4 z>##&I#Vac-ujsmO=*+Z%L8kXvrt8!0k5f5$d1xs|OmV)qtG>6@nsJlNhcO}F%x@gu5GTw>~Y?5s@~cgrCIvi`UPyH*Gk2yX*f zL*IlS&!jSQV=&4<|3N9J4mV@P5Rp*cVOCB`NDT9Qwha@`ym@DKGH`4B2B8lgxeM0m#3~^1Q=IA<~iX@U%t7&4%JfKZWBi?lnuLe1?_2sS00&W?yV!gy(m0Y%1RQK-#WrcuyK+h4YuA+Vearm) zr;o6loPGkupzZw?x0|?Po7UO3a#+P9Y1UY3+YZ2VFWYc%7r4G2AEm;s+SV3J|@2_S{d6eY$B=)fEhs!}xD{$V%#1K zTowD{*Wi*=A31p&?TUkCKcVUom?o_8xehOOS_(!CGc) ztYX7(TKIvx#nggIZEkHGZgMI_zR5&tGQhl_^z|cun-7p`^@82+s;#F-&i|~r_caGn zC8WhUN)5-ws4djRaNarCT1!f)OveO2z;kfGBGUnnIjv#sZG7qtsTp*s{9msu_~;^t zLw^Eqy0_gMOwYu0o3-_v6*FX7+34D?f6=mwy!p`7e7*VDm2&yob!lpCT?QowPzAg1 z^urVR-6{K@l=w%{)pR8CO|cA4pSwSUl1iQY_ci@P|NHqaD8l%iO6zI@CkcVWV$<4d zxYUUr#xGe$RVW!QgUAE~{6_d88jRo0>r5twRM2;6o{w82ggyicOoLKi_E-V$AJ08T zM9Th1xk!w}87pJ~LAq8>-ht9cy~h6Nw2aLI2JrfMT7`kb=4&i-knmb^E1&1D(&fME z@;sH2;w7>E^sZX}0BSh>vuzT0-&DJI7pV@!{BN*);36elEzn74682m03Y4$RHq6g3 zJJv+%GMC7Aq){aNfd`Os9k7(t#DX9&2VJobHwXV2O}vTK+*}F?4RH00o0Qq9k@l^- z+mus3#>;j~5~k>@in?qpV)~szccXTr4gLf8_ecU%Zaygi-%QUBw}8Yde{7JS9mJ?D zc&6pxMP8BK`Ok&>z!(QbmNnXV@SVn$ky5S$*b51RG-?DJWDB)IX7!;)2Z2ZTnvXADf2y=JIvg>W5ZXq-O(+=i z_(XVf7NmpF*mm9x%dE<#)#WEDdm$#bNgYR}rxB*l(*u+KI2PxMB)n=W8EYg-bYm}9@Ls3yf_479|brCG%yrWF(z=a>)zB_KWbETd$72Fcm(})y<4`i8)W7gR%Lk@6s>r74#CGM!cG3y57@03 zO$yaRj2{@l_)ECa-H$&PcC`<#-yK%%4(($!>vupnNi}?e`=|gEOxq(hGwhk;CEh=3 z@`#JXOgFp|B$ovvveN?~>}$tVU{Ne_5_YfYmtF}&$5ON{8FI$V%=q%C>s?wDunJy1 zdvt#9WexQJI=4EibNAx#Nnc(HPMqx;zw3$Q;!sfl1k=Q636bA%vIo1DkrFC25|U+u ze&*RVy@X_yW&8XOIU21t_@B3aXP}mFjB~!+R{F)UN*-mzn{j(`Dw>!0a4&JUn<{tc z)bP_A8ynm6su%Vv0}JRTYGFa0$ZHQRhUNe9;O+W@yDa6S<|+DvV}>8jT{p=!pnVa5 zDxJuTAM3djNevoj^;{;{$0sL$SMz`}!rL#qGT7v`_4SKB_&M|yEK$#Sb-$#z==@C? z2Bl83a{6fKhdzn;Ep2OS;j~Elpsg`g2Fk0Kl%*tdT1R3;juNvDfSdGdI=RC)VT!RX zsiR}%S43?miY_4%z(&37x2G@9Y!?CUWjOOn_l!RlCd7)Vz(FMwW!7dGgmU)u=J9E{`S|o3m@!rXfO_b13mYja}gs73FF=A zG|$LqFUEBk0HQY%3*kIAd_z5sh%3}Fni)tjr6a~ZAXYDSZC*AKGUQ*`A@z_EVM#K7RxcwM6nAe8KS*lvc$?8 zVs^pAE~?9u*Ua_K&lS6SqS1GJGtx$(=^Ac#7eIP;>K}*TF8}7%{T1A|jn4u|PdgeCiGZOVOl?g=GiQoq7`p*NY0K}B3M zeyz%)o-i(OphTd?e=jyUTxX}TK zIv0Da7wzDSR7ZZXPF|kK^-O$h%vm77J%k%n<jk^Xg!B&Lp&?%mXeY7)T!zQIaJFC+8V-l?ONze)*j>KgF{EvXELb zWQ=$nocBt{a0gmd8j8_O=?>+i9{;^NohjobpffSS0OFi(#IwdmCQh)ZlG}RRVhMSk zS5$KKAYq1~HpCz5QP4Ei8Lm?=jyoz*K z_t_M|d|4DU<$-2EZi?eD@|}2HCV&2%=SvvJdjd@qD1#7mfU@%QPt4AuI}xzr#}3!U zgoZ*_cRuLMve`qk-S8dGm#Id;y*`}NEHcTJ% zGHZ^on~0#>TdyL*$iNYR{*3A~kk7n>HQs;}MRnvI`tcG;YgA0Ka=QNg<^wuyY%Xst zNc_kLYxMVMoQ+gkHkSmZdwtL~s!f^j#(?1M7okWCkW~MbA5Nbl-O~4@W?113g~C8c zjQN@jDE46I(1i{>=I5Nz1tAV^J}GoRgDP_6vx()6Z_PmyWKi7Q(Z#1Sh@3S&q1-hH z;$elJnW=~7=+W#nm&}7)qg7vU#H3bu4XG3bXw;TFvoDKk84eXX#Yp6Zo4y+l8pcPZ z4hJe1l;9D5xT%GwmSR*d+;Q!y68Bg7!TbcEY*lZrzwc2qD+js$22t;1n?A5g1R;y& zq9YP&d^15ea;5qVgUrY_6pUz`M4_Ee{h>6(7Wi3huq^deBp)4;7Np<@dw1a)8WK&=9^?U&s%>|PT*wWsbGp$(Pdh3@jVxUH=KWcyT(~RH;qhZ%Dq%>JXj0t90?PxagVL91~VC zyPqP}4faIq|82VT$bdL4C$cEabCk)jjM*uO#21Ut@V?HZR zM#8$xO9fNwtj%^J+n>Sx1^6>ykpm!>s`dT&5 zsrXxZP2TK4E{J@(Y)5!}Cb^?egGcLB^oJtZHEG@@@Wq&Yn2|B@ir5HXrBEcNbIvsrobS#&2FjqBFNdFxlm-`X<0$e&)QI35V3o)p{ zdFx~eTUl8NQ#wn-22GjPwc01SqZ$w;w}0SxHRqe>j*VhSL22&1_Rv==HmKeLBy%9v zhV5bqOrrL$wH|>m3&@02n6Zj|bbGj18L1KVbbPEXcQt~c3nh-c4z7`pn0c= zYWU2NVzc!YP8dlW09p4Pe{PAk)JcCkOMH_+8txLANsR;MRM|+QBZVyvNblZ|^LWK_CCVraDxeU^Vt4XKEU$+7{gnKRvl z0nYpaSQ1^2K+aH%pAx7OsQ1+{tcb_;sFz_!&T=3F%&W8pa~d{~jV00bCy~|SinF?d?j#}PFqy@J`d)Aix3br_`j=#km zlPK4~NkmJ>kPT~2&s>X)H={mAS!UK_!km4#QI%thbqTm$4Aqyo{UudQq5y$VgK|{b z)No!3TJofJ0$+DR^U0REO(`wuEZ3pCMNOtB+1!_f<;40#8ilEx4ntikofa~OF?GO9 zhHqI$vWbQB89{&*X%5d{o+lQM6<)-=0>T8337*B6=ISiCNnmK{0?`kbF0Vskd#8^W z3>|5nFW9)gc#$!d$JH0e&5SfI$THDZv*P(JPnG|;0KH+}J-I2K(^fXZBVWYCfR!gW z4qeKWP@w>4l?By~ORWeuP4OR>9|?%ROfmk z-;$hL0Mdq-1$Zlh3%Z}>bln2g;t~;&`69Bikp-pbY?>X$tY{kc^9MV zi}97{;?+-^FMd%ib!K!pM&@{;I`&Q{8E<{4PUy$mHhE6({89Aa!K}f=gYzqAm@)xYW!yIkADD@__Leo|$Q|VTZ;KLf;x;5E zG3wD1OOZV71aP5MtLxO_rlt`E!z?K*jX_p4KhAjq34F30rU->OT1gJ$%71S#Wek|; zE;4gxEEU?9%pEi1BH<#z><1@N7&GJk0N$Ri7n#b-i!>q|e>XNZqSLSpg5DKFafIYk zxAi)57#3r}C<30V;42PIBcYxe1Vf;{AcbUJ>~Y^N+byqaYo#`cajzwefm_@)_jjmk zR$M07%CZ=jB0q%faPrjxr`Uk{4;}v?h--~sG;z_`ER^4s!6u(&XxwP?w`K@BfRYAR zOBkoBUszlf`iu8PF(`t8>3AWol83X2sK-324_vC=1f+E5v0vZI1cVCbb)3?vnhat` z;CoiSC`C)Z{J7&5I%4Qd(@*J!O!MI#BK}mT@W*%A`4qdwV&e^+(1>V@XZA3UPuuWt zy6Km`xt5k=gNE~JlJIz;b=SY$0FXEp>b&o|K?XheaRL|E&AzwI=4ruuny)2YVG4J+ zd}ZV1*Tb+9zIxRhLk0u_Xew-Xc$GxP&%<+KZEXy%rl&mxws|bi=JYr4WcqZ$7J|aH z0GfvgvoD z=RH;$Nj+${`rIA*#NezJUXBb|TkNz66ju8sw6G$nyawnfmHEZ9h?XVeM~5W?_nSTV z8#^oz_IhJve%&@p`1y>#zrMyf$Z?i38~CF9D6<&n7t|>Fh(>)YZp3S{N@U?=-2bC? z^15Is!kb@=evWUrI+T+Y7)4hg1nrxZd&vr#ROw~<6T~^<_@YMTq@%0jFWuEH8PD`+ zZ4OAcWck_xzxfb%?!o_R-L5Ps9fS#~)=*u4DI*I!O^qa5TwIJQ|F%4?@fZqd$}RiN z)3#TI#U@Re2e720XiYho&9_4H|0d&8f$JXS-XhgarKgrE<+gAIun_sA%v27yRlFhP ze;8cf6z1nD&vuA9G8mqhUKnG)oXsDSVNO=1x@Q-a!%=;&tggmX*AR8MO*d582$V}N zB&(ogo%v*o(---ns}fIYb1nX3=y!lJ%|oS4Z*k?7#o&-8>g|tzsg%6v)HxSjHhh{4 zHpQ7qD*luft{8jmK%}0?qm@x#S(xG8f zQ-tjJH`BDLY|$Pn)GEC*vFmqNF{@TMMQri!38{AiYu++Ya@^Jd2BAn6M>Hho`jf~sUZ z&o=S!(3VlzBT~JOLHKw_>~6Rq0y?YD0B=jr719c1s2L~+=tG36FuLQjAG4HRB7~*JyxC+^PBcdq$Y9E|Ep#I_+x^06| z)6kC{Y)bIc7am(ox&P&b$MF3`Q+9A*1u3fWw?EJgzt z5aMchvfF%}uQ16M{cfSn$;nJ)R+_!)l*S?}LN6*w1nOS;(3Ac0hb`RyHY~$&O0K-? zA_KF%t`0&zNF-^K zy|blv1(?cEW@I}}d{zf&71kL)TvpMHj?`nSxrmF6_jTGQky-SmHhMzcF~ zU(9d*uHcbZkPMNKLMRa5hU-GUaRiX^9CIph=$X%3MnG{Xw{!dL|0-c$`}YzzQ#aJz zDBobQrk~9+;PVxuHJ^wX9|iG8C5*I}N!o-+6l{fD0LKFM1}vX6dew7SNX(?tLaw`e zh3rdJYmi%K>YO>XEJ4oOR6>YdK zbNwKu@zR=6EHwFsK+L67E;v$|jH4yltu;-rg!vdICi~ftYcx*D1(t%9;*FihKTk_g zpO#0p3JMz+Yu-M@Pk0uAq@i^nwPW2uCCR1cp_3`Dis3{I;|nVe&OsI(ZvSIlb{Eo` zBAWjG03%pUzZu-0Kd!hx6)^#E9hZcj@FZWho&$*D=%PMPJ_)j+kVzHX8h;}FmcR@1 zPes=Sll*T751n{~{F8&%@kuB2-)}*f-gc>Y0Vy6X5zHy0dNiBw^jTz+O)-O_WaN~d zTU3Jt*}d>z3(!m#S?-$s)@Rum)_|#U%At~qhIbb_^{i{p@v}4f<}JXV7gXK8{}2tg zi!&TdyjNHL@?ZC3_#Uw4{F~&xq_-;ku{VqcDoua??ABK9|AzePwiDW}yCNp1qiIrP zf**h5KuR?f|Epk74p#G9{e-}p*rAz)McA5S_j>~aw=Q@XN7Ym|Is1p5p>*PpwnP1%_>7ja0Q=_gWpmc9_rsK{EjuwoZ=HBuaGXp8Ebo%vvTov|^SBMet9gaE z_1OLg-*+_0I3nQ%=M{6<;aU14apbc%8CimBvd;XPIz};F47a{^ToM5h9(;)UTnn76l}PFLW2j!~H$`vhfgM#@3tuw!117+@AdZclYahT=40~Hf^}|n&`~e?64n#n`MGz)lT}lh_h#(q2In~Q zoy%2$G?wn#V+%rzfZG=;zcrN+tKk*my9-{nYnmZnKN4r|22NlBR5T|zGcROpUpVtW zB(e#+OL?XW5r{Kdo!n}Mrtu;36&o@&UILw#INOJH07=>7##z$FNF!p>pSYoms5@)R z#lJ}CIL(%o&H_cxlDz7BT@HZ+X|`0R@@U;y`s|oA%xpWhYKhC@Y&moDskCOoHfr0c za2%)NAUF&wi&xh^?=fsDBF@b1loo5r z^1R2-NN4n6@m+@-?$x}AiGziXY(RWU%!6e(EhdHo;Krk#axtAPw zR<{zakL}ziOFJYQOwlu*iwg!1r7ozKZ#g1|)>oE3dp0UFhZ>pI;5Zbr{Eyb6GGk12 zlRj7&hoVbXUa|u^J5jh0Oxt(Ib2LAUKEc=iGKO-$4oo=ff0qszlwGUWTYp(M#h+-F z1hCD`P!QwyUdbCwS-xR^k`Gx_H!t9RT}Getq{c!is2OciP5C*Q^t-kEm7l^J&5%r| zisRfpJapiB875jO?awk_FH506B^6gtl>PG^*iU9E^n{U$uz+%03V z{0a>J5mWkJ<7#lEB>3bIw|UjA<72uUIh@i3kx5q-Y7Nu zal-!-wB%d&e?5QOH~gUVSa*W`Pv%-aS|V`&E!+F#o50&YloBl};0hM#*^L*RoccJM za(>+K*!3cE^gGpke(nDB`M4$qK7V?2>=J_Uy&M(zzRcwuK!OB0oLj!PVJ#F!W1VZ~ z4?=>x)sO@tsG)_TjLK|n;Chk#Q@Bh;%Dr?b`J^D59*N2^Bw8pmc<9siUjM?Vb64HZtt~IHZyX_k%md5A~g`3U{8utz|tCQq#==&1^Y1LQ8$DU0>?F zvR$z2F(i?3X!>v4po)W|EGu^YGC#oaU7b|NV?8o93xC;RXW78HvT!KyzuIs$c=?Lh z^)`saty2_F=fV~2G;l2GEszcV4^|R(&4jQzF@vDHixD*knd$d^m6st;@m2!hz4oA zq}=goN7P4N`rG91b@(|IL@ zuaCpD*o)xl!<=Pl<@X3kzHwu={J6lp_Xailq<3z<;+OnzPhJ;6t=PJLnDch(G?HJb(qNyJ&=nu&h8_LDBJ|+1B z41M=3JpzS_jPH{>fv0yzAL_Pw#qb8-bqe?-->Cl#fbvnU2UYae?D8YYMBgR!oN(D( z>(iI<*6zAr&GqA=^b|~smFE8BSt^G8PuOT zn_TLgs5=^I{Y(`OLskO&w#=Rp>Li32 zwA>>%kEMV_!%Lwb3=nAbT+z_Z1Z;zzZOIp}*eB|ubqcjgAkK!mi}T{x!H|)b3g~ffe=U9$teu~|(pu&P_qCKnEVJ@z~6fZI|T&wK9wvqg( zW*yfb%;slNawEKxrM`8)=@!P1RjaeWs!Q{A6BZ9a{A>}OcrBe30;jM&pjI~q(z#UJ z+jSt1WT0Pz| zwmT2zR%#f(;s>P-`n*E`srB0oW{tKo7n`}ZY-Hup6-mBBh3Ygr%pzFTr5N;1G&!C4 zJT7!Rw=l9v_R9Bo+>+;PcA%xz7WGgT(!gLuYGl$s=)w({rx&O* zI*iLX`&BnFra?MQ->(rhoJp;79r76j(0T)xkuMco?Sprq^%1uLivp(wb6MVn6%!E%e4i*fl~a8k(5@3Z#T-rx0`oU?!A%1=>@u=#cpy!io*1+F>HA_gHgjxk0V;C3T0f_)djBp-EffdTXUv zs6F$>l(53RstChnZ)1}w;8bsNTxKiDT<=)t(a(zs+pSAp4+}yo!rUJifA~i*3cXfH z0q42zZRD161epn4b{<{@e0?Dki`wc0P5EXF@{G9|m43+H9A!2Vb0ivQWlCzVyhwXa zHqOF{zw{@(aM-yQ%QC07k~V+(V#P*uZq4A8684RMf_eIw)|#`Tt+}~+SL6_l-37nP zCFwz}zx;gD-cY#Y`j$h|gjNXCOX_-Y4{%Jce$Y02@Sbea2+tGQ-f@xFi{W z0G5bsZVO9BD5q#fiT;e#sVzQ#Lks5mUX8m=Sq!akyg9d-5mb{j%u^CHt3&P<4mi0w zJ5w)@Gu5!`RAFoCyJ2--A$AMZuM}!j6t&IRh=^G=>U5mjJMR8hiS_mM$CjXj)S>fU!{Fm4<#yd=ij?eZt2<|9MO#BtQ}yKE z1pRbNOkphJq9<7#Pm`BKY!Xnn(s^d7MG8LNf!?Ml{Q7nK(v%@$W-lKheTqQ(Lt$@~ zan}abiEOhNWl6}8YuW@0Q3S%TCJr(c&udUP*+KUp;9$b)9pVw5Ba?5w|??fFDxvX+fuHw)qif$y`Ova$dr~8xdA&y}|)qBfTl8j8M(rIxnfG zpHHMsrP=vQhRw}HTq)MBw%^b!l{QbsJl;LeA9`L<NhnP3`Q?&g{&cJKcTz_BrR<2$D@NCqmH2 z+)bi%^pn1HEN`v~FU-W@cB)Y~aj#qxN7A*4oO61khyHitsomnz=5$@rW$3m!ww$^A z<_Du|zp~KcWC-T3s^8@6K0Zh)5);bjwjTI!*VZD(mBdZ*yUP)MML2V^NV?9EAXyD* zLp%kvsUc1UkUHvlf$XO=tFIaNO&+%yB&<5^+6Rg*eoM*uTv?ju^D@&>EQPhk@9xg# zpXDp^>r+F@$Pnu+{Gm!yfB$Ghm~0?+78f2SGdfYOPQ2Q8ShBQ9Ddov@kX3y8H?>w`l$5BQO*V|)8OoCL>F z+HIQPN~_a0ZfJ=tP9HV3?Kl+1%uS5udAa==I>lu>`7Th3QcE!d;L- zO1XT|)WrpB=Rv(XQ5uVdg+;Y)wF5Y^EI zoH3foaJ}HJH9ds;Oxmvy%P`ZJ5kX@^61VH(0*m~4Pr$-=lvz>j4#_Ga%g8lTL!d_d z)>G*g{ifm|nY1;`_)UQ3lt0pak1#fCP+-YSti>+whS`>GjP$(3!kM@1eKXMCi9H3z z3x1=@YlER}uAvFUnZ;OW6kGlvudt`isE2V)uvZ=N&i}=!WE9gwbz^m}z5W-8(aH{M zR$Yc1wUgn{&bMboHIu57PFbv}?O@O>WtDMMYQ}-W#%*{(Ef&3dD2Y6tcAfR{_NO-E z4n+QrU1AFsH49zzCOgGY>kA-kqy@9)oSg^}F1@gYiP9gT0vwYnE%*rncQ5M0vHkr_ z?yzd1$u5jACW|mZ&um}bP5_~(BtW5}SUy{NZ>|*GvTh2~P$txz-B0$bdviY|22FDBuca}x#TarC@K+fp3+Kg0lK?bPm{i1i9c3d3 z)+D0^o_O4~P3YlmHnEOPQ@)#)$zB&!bF5`PTt(o7=zm}QJ%y9fR2b^vj-fGpR9DU!zEQhnu}9jI$}(kF9nCO z89-xiH%ak;)S-0=! zO`Z_nrMi$6GlRn4!}qmTHTB<97}t09;C?0dr;xyLWafD(gp&ah)XJYc;(D1{NlN;o z7|@q}NS#$1@Zwu~j?d5bRfZ27_Dpa?hHiz6=oMfI?cwQSIGXipc(^{~foo7qvfy-D zs}e}T(D|(QiygI;a%79$@EqX8!#<|^MVP!_QQ?n8(TnNH<(Z9#jYYM|w6B)aYheu6 zX7#)3@4tp_=&n{P@`cu2@q;nbadf3Yd$vdRrK#w|ZS&p@a~?JX(G=Ys*plP)p}9Ud z*3!uD*a@6qS%UZ~lH)(?Y0eFS$8am{)*77u`$_S`y_#RVE>&xftcwXf&_ z3XDAIv*#y^v%^9QQCJwolzDVLEJEXCQygJ7`JRF7|zovE>M>?9E2%&+QeM^x^Q}vA_8R>z}3kWGQnG1V@ z>Bh+sY99df;=6Q-cJBL@oD9d6Pm#jwb`H z|3J!%tP!32K-mbPBVOArvtjnaUB--N;|cX`a^aaZ`Vc3%@7o;s(<xg^oK^X*DES^~Gn22kFhC(GuCY7olC)QJ9p zmG%cvKgyZlCh>4r_k$!d*DQ$<*k*qa{QM1FYeJzc`|v# zm0@w*2NUEQT&}*MsXlhb9h_rUjE6Hd1D^10Hv1lsq`7U{Nzufch)LQo@WN4j3G!<{ zL{7GqMrPgLMMq#4%zK)sOvxvU-^`)PYkUd;* z4G;$*5LiBfJT>fS0_&J=Vfx(3N=e#&*GIC`sbs4?^DBNQzRoL(rMft-;6+z4DwK+4 z|4&9QXZ@TiO*8BxAs&@%UGx|Lq9k{#>(HPbLr-s(Kbhu7 zGDK^`f)GWmL|>VUbT5b_DWuCcPrYUDyLy(g)0*!WP^j=&srOtvQf?Q)>lSZuDktSR zZtij`ge>;V^v-mHQ)U}Wg9d&)6=?V8r8Z$k;3`#V+TUzw-jYyflVd9vBZoAbxZaFctn$FCO_4$UC=8bkqa#p9x4 zsLECklNQP1@vygjLt`IJ@%Q~HIo!V>G$o$eR+IFyE%i!KLs#n_flp-%Mu0SU$Bb!I zFrIq7;m84z!$}hOpxd>VEyz!L#ab|Lur&>U*XcZ@qG2-P&1N}};T z?;t;D);^T*cer~+JAOSgBXJWv5Lam}PzZF)F@RVW>eVf~@!M_20WNLmXq-D0FL$GW zr?7p>bM*0RHihpvr-F&fof?6}qK&PXoiVbmcFs>;-y94L-=Hm52z})Kjy1Ra4+@tP zq{S$HbLuk`r~&isd>Chy-U zHhXyu+a zyp*14o4e=R15Sy>gbvr~MAc9YI&MDkUM^;s*Sf0SKGNcb()tM6s3H#jh_u!9MvlU* zg3nD3g*)!TkMiC9ap0jj!E9EYd~zA_)J8Qxxx^g*NryAQ+IqtBIqZnZi*4Uiyz{9f zqHk8~SEraQs_NW8-RgCK7_5{Q9Xoq?Q&W$-T;oU-0w9}s#58|jEFM+?mJTt@;-+gq z4Z2gDcajgKOhTatJ2x%t*50=s;9BHv5T`WVm&UEsirbGORALjSlYR(aJ2&l*x^X}g zT)K3$+ExvUja3Xnl^kuG=W?_(EN9{8I<@x5w3?eEPUr$i1#Wi=UYN1ZXJq&cDcYvC zy`pEv0Mq=)ug9W@C3 zE8CO5RAc=vUj~#97@ytjr7)Hah_SpbBke9{<=ODV!DG3-@%k0dV9ZL2hGn$qju0%kM)3*fzl z$IK~{FB*lN?Sw9t3H-Q~?aiKg;<~e>5u|Tc>)@=}gD8^si({hd5E#LKyfpk{RuY2~ zbClWhHQ76ptfvrAHs9cc7`558SB`#)*Iv@T(`JFI!CJ~)tN^@0k{R+3H?|hz97VrD z;OqED#f9QpJ0{atk&Im%B}fOirl1Ax{Y-u1+TXbRH0j7CarC0UqPxTt3b5gUO#{Q$ zEc^5GTdU@Jx%}+MqmamVwhSuk`?js!waMMoJth$i2J3gm32so*MPFQt5dOJ8y&*#yV72_E z#P8`$TbzV!XXQ++z4o43VcAK$r7e28~K{|x)A zz|_m9v&K{pvhsc+&o7|z1GC~!{9$V^#)Y2me=f?Ph*9Hf93vY1IIZrmO4MK(GFUF1 z`zEY{jWlc(9!p8Z@R-<%pyiE!1O1phe*QLY75cqcZMd^q_7aO zJF_uqkZTR2;JfBlWv#`WCtgp^ll%E{n4Qz)(al_9btqfP+9>qmnd1t~0-(fp@>6{e zrF?oRSYM<~#XH00c)zD##IalhzAIyJ{ZpA&<2`TL?1I*LMpx+R@!I2j{$OqZ>d9qt z^igEAgW;Lvpbp*_m*>zqD_zz*F_gPdGOelEoUCjAgW}$KsQaxlIffFMTM!yBitpoZ z5UVZZDJjT0Zhd6uNLDpi0MK`rSrERrkz7CM74z%RnDH_CC77f;h}`1uQCMMyc6)N+ zM~n7+*23`bXz}zih$^W5`r)j+&4cB~54YdxflWBQLF9ivO9>zA*JQ zb5^xbQ2hEEvQ**Nha>h2Tv5GGUlempD+Fe1lUCtvh15tT=f^ma;DOOO!%NVawpFA5 zxu6B-gR7dgM}`O42skrLq<)#JKtKx*=im3eAm@y~BFXx+t)HfJW;fg4R%_N_Z7eh$ z-}pNpO;7`ktLvBF2erfYX5rW%8Oe(gbCi!5HHJ~kth*zUPr%Qm5n9i2`m^XWH)RSr zOs3hUR%Y`F3AeJBe(~f7m3q)$*ve0 zi-Rvhc42IyNnJASDC=q9%ZLm^U8m4wR3C{}=UGG2Sz zU|o%#`g}*;IT=_exmU@YSFK7HcF5pRtm4Kl?dV8!TO_ZOl-FAr+GALGV-ozPiFvDF z8K0hv)1tbOuF!7+-(zm|a!`Lx(+jsBU*{t$bOK=;kxS;Gcxt`{{pLLPc&bXmE>d@z zgYZz_rctQK77!{xQ93tkJG`vn_fvvWrjRjccM=CH=3_38#I@`p-z>;~WhH zh7BLzAw%WH9n!hyy`Jw_EuPj_FrCc)5I#;*)Rq48mx8-j&MeP&tvt>ZjiTte_V-O^ zhTaQ77eL$IhjS&=Ncw;Yc+Pc@Dnn2&{>x32+DWg z<~5&b=jffjD-1wzdMQi8TB^~vi(V(I%b?s($?!J&i*K`)fuWU6;9Y8UP1)@2(J#gu zTF2g`Fn_<0&eE#58&A}wr2zMQMHFSro4K-BUf>e`pGgclt2&!kwYftO`fl-bHp|8E z(-$2(jU_YsNaKP8Hx6qWf{IfCsZ#_sv(f%`Q-<`!v4sLVXH2ULaqG+2VAS;1SZ4C^ z?vY1|g7+qPxDE=CIvdKTo z?Epg4mDbh$F!yXD#C@!JO=!O!krwjj>uccqd3eR9o-1?`?yn*U^F$g}@5IPcR=VSi z{0z6!48~z}4S5nnnh2bS)l{U$mm6q;YDF^FHCE;8tf_pu%cyFJ1<;C3Sc|r+Ek9%f zI7{(E{TYpr%dxTzd9O%_po4wqvJcO z$8>$NE|<}XaKKv^mEgko8Lc7|0%c>jI8wfP82$7{wq$BOK8Z2Tv3Za)Ms*WN2_T&b zlC0x6%7-@)Ny4Gk_MiWi&*&Kz1lF@EBhQ}6KT7N)GsVLkJmkc;hZ~sS$Pe9CPMNvl%f5Z}O-p6W(6^d@<9gN0Y5WF%;Z5!9~|~aPodW z?tI;{d7~Hnr>yTYXPC8crw^XW!WZ--!44!~6~$Uam18qk!kPlOE)}|HomoxhqwiT9 zn?NH))ID%N&?jo81QH^wQa_I5P9fk&)bfmKCEQmE?Pdw^5)csb!kr#ZG4=N`JCdv! zt^LknJ~n~_$UC8Tv}<;=ks?DcMRBxBg$L@CNSy6L3s4gBEFh-s8@RX1=* z7?Lj+(W8r=M0qW$(v`iWK99B#vRj?hTd}fzq0*fI`S@D}NB}ynE%@H?VQFq{RRRL% zdR<5Hnpfj2DJ~LmM?0IDW+jP-qEw-*kFHy4gJB+fR1E|v+26Tm(k>_JR+XW!UeaoW zNm`N(w-)&OB`8=7IEG3c{{-sY_cPk}X1Xjc$4Z^a>EIo^a_{XoHEGow%B{*cfOLP?FgLoT=478*P;JOIMDBnAMblCiQh&%M>$mryS z1FCU85&$Gdz;CRf-^NPne2%8%AA4whF*=&-XfbEAy#+M~zBl~)?@A9t%KcsGiGg$Q zN1N59+~~LNK$}+|#_1e})WFCAYH54zfmi*xU040AGNz5^xC(&iluTMjvSNQP>|muX zW7rL=M}$sAW53rB`k?9B+n!KfOL68iT313C=i( zkh-$|Dic1XJCeXMk>@fg6lI+`*V^*b_0>|NIgA-VwG~6qqsA!EQK=-Nao$FfhgJTr zZcbrG-4ej=g~9Cl)8AA0h zt73W#oN8-SQXNXpL1O6*ap^lj-}s<0fW(=x=^=`oJ8~+~kbS}FsB*qXhR8K(QFS$Q zDWo~>v%qVKT$ly_SG(@g8IfVmB zyUi&*2_=MUpU;-1x?#EJf6Ek_ANG=TrU6~WBP0nGb8DJKf|C=pY5HQ3Ap>ckMJ#NEZ5Yte)OA)_>Lr45gpa20oXcfjO z9^UoO!x~p<9-8p{H2m7c0%ftYFW;>awOf6Q`6V>f$Nmq0W3TO17g{`fhmTp8XvXKw zI^%&JB~e42VU`TYy(?KTeXnh8WGK@^EBF92)%VVB)XcxkrlQ~{zxx=}0WF;ekFS5^ z;LT`5aoEN^yNA*?LvrFFggbo;PDu7pqdOeP76mc%IZA1DCgfLt$W|b2V#o$B7zD~)8>;)6 zBtxx+kiF1x6{InJ{|^J*@4h%sHYs}>KNOB+BUnLWDXl)Zd7nvtdYzw<{ob`lK$aK#uanceEIx@h8d`rWB;&a7@@i;YfUh*)985^R;(o2u ziZ0O{q$1U$D@~05Yb;x$$A_u|>D6TA1=tTV}rv!L1Fbf-^(&9n)1d$?RjX#tp*Qt&N z1?MK&Izee1@$Pw{`Oa#Rv zqz5sqLLxs&-QA>ClZZ`eRjRe?x<4 zGcRzX4^{&jSn2~9fZWsgf=|4 z?2>F2T&;7?1Re9OYworfZu}Sg1U7Tz)x7X%#I2p$DBfC_3g0qPL!tKwBQDGG*LbI+ zt23;c$;5az>c~25nPmfU=$p;kvPvIb#mYS&hkw!uL-Y88}dy_R3PDKbVcCx1Wd)nNw%utSO^S3NbCc+R_CTsGD zis&ihc#uZ|?dh~m`B1*>ThHz#{A`;h-FgcVl{<}}E@;TZ-hKlgRxR{!dQ`z+`nyrX*7w4n!`5F)w1|?KcB;yd3#*k@B3htHXZL zFm3*}lHcDLPpp_>mdq~lsnaaxpT(yPAMZC&6<6EK(B&)JaG5L8t(jzP)~g-sSMPWH z%*fEOF*n;|G;Y00&b3-h50r_B5>(GEql!(m2JDO6yrlL)(T8(Bs6Q9efDoN@%xl%_ zhCfyEg(;UNG<2W-A}kF#z_r?;*O`Wz{SCA+aGLdj1Z{~m8KBlFeG_5-(NVVckzO$( zM*X7tpKhW^yjt5iYV29TZEU;YmF)*(=|5&M4>%N$Pk&$FE@k($)Y5ymZ(ZME(pfa7 zB_=kWAFR6|w_AruAekeUm;yvjr?Q2fEZk1wp#dgT;5>&fLOz6I7EH4(s){qp$wK=n z?<`wg(V+gz@=ML9;M`ynICHu#!FRLXLN$BYn2$buS2`2n^?y~j_MAFoVC`GtC2qUDqX4qhbcFA)p>OS4Pr$Fc3`xoUKI){@~;yt#a z^M-iz7XyB%Re`ty3z+l)0w^`r{&~UNUb1u$LkwIxP3%_^pHCAiztI+e)W&< z0reSfkn)799bo>Vk9uBLL&!zHV1&>j3cElJ(TO(@VHQEFTk!N!%3fO%S}s#7*;97s zS9JJ!>&!MuXrKaqPK)if9ZU+&z-`fJsilt38_K|O*&QTP#mT?rT_={oY^iihjw774 zxQLB>A`F`yjcb5yEq^-7j*+SOa`*XtSvs7|&@hgRA|Osf{wFeav1Cej$!GH zdlA;;P$|`%-8smb3waCk`o8~M#O5|@0d;fwe4n3FbkSQ&77d|`<+7v|s)O@$YU}uX zt3o$?MqLi9A1M%Rx1l9r3mv(GP)Ce|Ovo!ehO!&})f&RbChtNfLVil+T`J1(Ikmks zq^3pu0F1TKD5E6W?CDG%cx)bInr{jJs~Fkw(4)hlrT6IXC+lXROUtJVR1BKnA)sNv zUI+gn=tXPxM!Ui=J!K0$V!;Qe7mEJUoQ((PHhEq)9bbMiUa9;(at&Mqr zB=L1mo?m4WWg4ywZIvZ8Y71c_^38!QuzP9z5m*F5m>i( zoz`*7DmzXPiEU6H$=yTo9S+nhybc2y)1!44x;&ma{y(-YvyR-VYPxpG#os37D%EKQOad@3mmX)W*5$j4fA#n@y!m-3a=e zY6Has@yet1$J|UQlGQQ?;XDC?{aoSra5hRSq(TRYnf*o&IN_N!*MR+DhxR}N-IHNL z2DAhL?q9Hf1DgZ!PRZr2)tLc`+v-J6;xyM;#%yo!3)Q|I$&Z-@<;2kOe@nwZV{KX| zMER1pCpl+M+h?Y|9~P|UEdJiD^cy^tLhQ4MKP;OZ}UDu#Dl|1TJ>@%C(OMRgM?EtYx9cSmee z2q{oaQtKa6JvqE&duDrIWjCnB%1?%s=06lh({b#+d^iuDRsqz$NJbc_;nD6FWip=a zD!XdT@7cw;XIM@WazB7j?AmU8<}{_VW&)-^_~nLXr14l=@F%%o+Jx&<$rR{3m^;%$ z0iP@fRT>L0-~V*s%Ks|)@)k|uJ3zeV<|Ga_vi|3&x13uC;;B@Pg;dNOvQ5G| zVV(N9vFi$mECNAkUURL$40+S}Hg2b!n{lKWxS0I!mrwCk4FO*xa*tp&@6~xiY~yIs zT~0gu?mA8`{3O<{>y_Bo%83oo}_}lli8f=J_TtaA&wn{o+ z{*q4hV&QLN%kB@7a!Km0ZQEAcxm}*q$0piBE4kGpV%*rGn-lWDsqY>6l>JOFiTF-E zdNka}e3wcOj}xxfKlb?9sw{#^LbG`8Iqi0BHrCCnim^uAKP)i#!K8U+;%4-M6^Q1cmCjzzWp^8rq>twdN!^5x~>Iw6SEgl z_^nD5BC~WLvF)Rg?#*>3bSi-86Q`P!JKcRtk9SIODLmmb+LCTxv*A0-L2P=srhty?4zKmC$vyE`Nd> zgz~>DZ%oqYa3bZq<}^g^J#_DtWTka6z4f*&!@G!i6?cGK=Av$)Jy|ciV_qnp)3;~s zj>V5{Rqs|6V!h_(;2F@iZ{+AM3wjHD0^`r&kyvDOp)@^8sR+HNeFueZniY62E@WY* zPtT)ewg1zgdn}p(O2rLxILO+Y1P3yxfarLeytjV+uwim3@P*VM9tE-7MT$otZ_=4Q zhZ?UC^p6~me4y_Y7o+?~#GY)jHQ9Vg<;7V}InQ=o#|fM>)5NF@hmWU;1OHiH||atA1eB^lb+oS3}TJHFJGw?6wc?ncziJXJ!xces`Qb8y}7X zndOrwZ@SE0+VkXGfLMIaKWd$TAq4W0kD)C`YmQ@YEJ$W@th>LZ73Jo1QEJIM@JZXE zWODFxaS3@H&s4p_Gknp2P+lh)Yh%O~^MaZ`x1*n6pDiy|)+ad+X6iXjet|PbViuIw zCOKDJYn0CU8L8Teq*{MI*Jnm8Dnz6-r5CqKw03RkUJ5&bE>c_qM_SVN)BF~zrNWW^ zDoq+GH+^A8`sawtY0`8iWalGV<4Q+(RDjxqDSyuk@MyUl=@^-Kef8g& zHPY2(fRAlg+IPma7eu>tI9iAmJQcWjsGgbOpNVU5kKShPgw_EFeXst@)!YaFS5!KL z^w^&DmqZjy_K?T|`DDwv4M?SW90T9aaS5%F|5pCzLh?LHG0TVaxm|X_2aruK=_~BL zVe=$S&~w@KdCGMhu%8CI$Y|WQD5M;k_wnfbE02y^Ztls#Wbua}2e1d(!EKppL`?6` z)YG_>dRd{j^K&=>m8Yp}F`)sgZ=>uO+Bq5U75 zEflfex#hTnO@Z|vS9Qck-^l+-%Gevf5a)rR5d7{C;Gr8VVi0h*{Mh@YZDT9p-ji!& zx`Il3aY$CwZZ3zae*>goYv5*tTwLA5+(c~BGb;~X{@@ND^2YAPrY98A+>2UMC;5o& z&GAOX8Xj^Wp}Sne=VC?`qRzb6yiC(~u<-7IIn+XepuV~CHxV~~*o+uVtbJi1n)hdR zGKwh?VBh!5mtj0to`1Ob987j#=y_ulw+=dHf-SRQ8*R}lPI#9+JoPII{iMw^^!%`S zEQ2%ON$tje{a}XvQk#g=Bw?1AC*wkE#d5*dBOiZs^J8xwFec$)s*EgC-EgM;6L-AWXb{_deel9{Y#d2du zb$xe9mtCjs-82b%i@6+xzBxbS%C_W17&DkJbXOhDecC3(0Y!Pjt{90*{*?~op$Xu% zi4P;i)1V53)DR*;$QK)eb4EPo+Oe!IV4PMERHy8I<3N2^ZYf4?RO~pe6Fk(QIOwG*1vd`dB47<#ad>fPxV7<>`DvjbG<~-qGesxOG`^o z8mJHxL7>V~Wxlp0z1V1{9hkU5`AEmwRRkW>V|CHs@Go$CS;*q+3=^J z(yL#5ZBDnOp9yreCcSk8flzOiLnm%s&MkFK;z`DH8@HW`p*i+#Q{Of^sPVjI&JL*K zbRV-)yyj!_0$LX?wk~Vak?z~KUuvKyTCtRY(7|=V!?GB+S;6U>;McJhRcm{TL<_Yo z_0+4$(Z#}Iq0eypI;)&|EB{@e$;E$(fYR(}FeBm6E}0-Pjyi_O-IBULRG8`D0r>aO z@%QK$!){FZZ6nM{PF-`xjCrKOVh} z8t}WU;A2$0HyS3!oo8_iPU~Hn4~rz)GJe=3wWjdKQ(VlVDbXm|+6QfWy0P2oYFl01 z0o!EohGsAM@&giYsBX*F#aO|!72O)_ z@RRI9lKMGVffkC_ZQgMB2)w%dWQXcn0d=$=-V5fUPg^CMkH)!xbG>fzxc5B2f|Fuh-Jw1}4F%&JqZ z%bh`bA_LKZ;pm#9y1}B$`61M8y0eX5*B0k42I;o`j$7AM@gtHXf%qeyh{gi$UnCxx zkKv)9f>Ro76=xIUdDPUf_FdLm1>LY+PL!kdb_6?Z7#HdXs9w6ct49#%Ek6ea@ zN)&f%UOl}3NF}NehpTKcW@*HLH#N+1;qd0T&)#4`7!yKsLZugK|yREsqbGbMy z2?(i~xO17jm00yK0IbWsy*#6Y**3N_!~RuP+Io$bymmDn_^_XTW{cCR8lIRyhQfHb ziDUnqsp4`72~7sWBCfo?(nskS8h-i^l4488!3b?jC>aC;`#Ht@I2^$+A=g|PMyR0i z(KiJ?mJe6L7&{N|R)(EU9+U^6aniQi=54H-^3DUa8gwfkm_DDT@Z)i?7sB&n;OaMc z^%BPjGJ3ZT`ph&UzyTK=pC_dF@)PRr(#@4ZoT$Xnx@j3dOC$T0VNr!w_l&Xyu$8M` z#5{{cPcSD=j&BjQn2~{XJyy*&{d8CS^T1ee?<6o)s+L>f-glB6&TvCn;k~3S7JaR; zUyiL{UWir!p~G`HiG+1q{RTwZ04+qz6QUzhRG}TMhlPi?9AT0nsQ$%_H<)|GB&JZS z>i5fExecBXmb38Tb>e$R2LeA6y_u>??C{?v~;gPCU zwG8m7s-7f_pZ~926n(ANbuU{t)_$y><%sy<2Z8ha9Hnx4HM@Q#Bovj=(Anz7D3p4@$0;R(!KJdF8p?(p2<2EI{x7bf2_|*r9LFvr$ zMbRuWQ#`w-y?SrSG!vejR601~aQ@f>ZL`O0T!DNb3Zx zClVScKepFahab`16a#U=Z}`YGj;%E{PK9E%NTH{=Y927fjSuOKN7C(Q;MS;fJUUQ5 zM&UxqamM0H(!^#BTvO{H*_z|M`1NHfdM3IbUBhycn2_aXIu0iyS8+|ZPOBt5+6_ox z3ZzdtRD`|K}jh`tlmqvyJc;F3;IYwC5CvQapL+)Q)lP@2vkBSOlI>$0tkBADWHu9HOy!h zN~qBUoH3#2GXi7&Eqbxg$nySTYx4JC1QdBEMc!`8*`W`gPGU7v3*|ZH=w_+mjZb?OTYgXL5eOKHUOPeFS$30rrcR2E3di`ISWW%9jK`=?$TFJbP^Yxw#Ox#Bi!FrK;ybkrP#DOD}kRa%7Z-V+; zXauLw1R&Cyc0muAQpi+HU$l6lQn!i}QUImNx)`;2aOHBHc?f`V*mZeA_8KQyi#H&S z8y+4^Ijba6ni;6X-17Lpp|TK%&u4Yu#r(hA|6$=DulL;r$wXh)W^b+rF>b5+o~yXC zKWn5~=Le)gyRAD8Yu7nv@4uJ6eA$maVF2)y4*bsZyO7ZIdA%NeS`>Rz|4$bV%Co)B zV;diZHEw1v@iRA*Oa|1=<;*nCRu*4uT>CqO+9QXsW}Mc=9<=500uEV z(w9(g=B-tz>`(9&P&1H~JS59CB_{DQF+5RktXwtojmbXFMTkN@weUdx+gkqhf6_WR{4OE?sntzQPyhD$NdCHu=rhb@ zG$1SXJdgW&3EjZc%LY_ z0KEp(LT<@edU~!=yq*lr$y(4=2 z-RbuY6ZBre*LGb923~*z~!IxKYHqCpQ6S94!ly|baHcR zV&yHB7&8retUVAa?=pwhHM~j$g;HNDX2d^vfgbXTO)!Y9;4J%e)LPvhuS^4vtOLVI z9NUBI0wDJ1>p)Ai-$h3R^dW8P?#@Bb7JVGRxcN__1nS>8AcGFv#NBr_PKRTO)c?s6 zdFPEfv~7)48Nb;g@^oU7sG{*}6f9pc}Ax*|9YfdP ze%=XfZ0qty!zv+8`CL3)KI*50y?+q_V zKi0f9Frs@$mu3H^_Abyqz#-*KaO^qGcc$ft(f%`{512CyqUT0r4g%SCB?{+;Z9?aq z(kQ(U40kv$W$4)A-YO_S zcBCPlRo$`(ak3SWx2v}}qlz9FWrZ4sGLiauzf{|VfT?4d>EK7joPpbL;Or~bi8SZ6Tw{=n1zmJpp&#=JDwAgo`T3k2EA3FWt)59F- zkmIK5*TDnJKE6QE6ukdy(q%F?@J#b)M``+mQ#_xpW+-{GH+Q|BCe@3Zz=Yp=cbT5GRO@1o;?L%Im( zvjAXZ1Z)EUU>(31<_s`{cMRaA!LS=(1pgNRuPxvO?B2OcMPuh4jh(xscJ0zo-l?IY zy!;ycp$`DOhxH8f00yuk!*XqU4{!irVq{$Y1%H^qUzT+&EX>R->}+hT>p0mtIXT!l zIJmg^dAYdxxH&j@H}djr5D*j;4Cd<^s|00P3v!tmwiYZt(0Mi53;wsq^-Ilux1yZ|Eu6B8pd z(=ycHU;V+q1I&CZ{F`>|W8GkC$0mJIV0TbV+B%v2x#faKn+dXePG1UM&%RMeSVVO5 z7CHH?+muyQ)ztTD95|?}r+>)cu-UQW<`ySTTH2p+IP2)-?Be0+b=e!?<9p?5NNCu# z>*29+H{)+5{Cqp{Ui$q94>KNRK7N*$Ur<=|ytt&IvZ}hKw(j+tme#iRj?S+4-8lT< z(8o{1Bco%)>6zKN`32JA(sI8T0H&|q0{{Kmvo-zV1N+6u%*@2hw%jiUM(^d0^D(n* z+QrJh&y>yX;s)v6LF)we$E4+!ub0_#lpuKeQZxHTS!LX2;&Ru%^z6@dEch?=>|4iv z>sL3x$;1E>kBJX}0c6a?ffjTw&*8Rd|3~02lhR**&WvLYmb+zfVo-N`!w`__B|9&` zkTkz(RKF|ifg{2juXcrE^T^mPm4rFiF_qeQ$2G%cXRo28#^+HP&oWj*b~3kBYI0X8(6lltY8&vo;m>JT6mXLv^Ou%ge4uUMFGIq= z&vW}5*AxK?4=($pXSRKfEu^JDU(@^z`B<>X&r8f_xt2^=u^>tyrzPVb@ZWFFig_BV z#t`2&v{QSX$`w2Yf-rkk!-qHC;6#($Llm0NrkM9RsxNv!ZG_%r@c4y1FYG*AAD^uB zcDN|`@qT^T-pO7Kjrnbr!O(cv3OpXOl_z?Km2Nm)R3_8u`GN6Wbo0f>Hnnad&^vd7 z%=5J!4T-8rl4+pe8FaPxgYnHUP+lid@@(9m@8%BbZGbJ6vW@g3?hhI@(u zc?kpU5Ww-5PMz$NAfX4QgvR!aF7ZStYoDiaE*6$tPUou19nATtCmW#BvbdU~+UvWJ zMg-d@n8FYTJe76E%B$NvahF8IS zS)PFoeC^k9m>_~&k<7Xi&5yXFPavjT!xp&X3upG$*1rt(na#e#amVIpgV+m&YZ%2X zHbmp|xIwRp<6+GH@{9?;uzKbY*<3AL%LX^a+?73bZSI4bPM&?fwM)Xq9zElS!%`;9 z*stF@Rw9}AfOO{w+N60-%*e6=KId(|=YBJ+x$Oo@13N@EVTJ$Jr0Ku%+3|SWc2CXq zm;!}*f9M;&62m*0=JHLxw@w2TSFwr|J|twYc(XAl>B&LjhDutlXOf=Sy%bY1@c?Cp zv|pr^(_8+&WtoZpCNl*aNZxq;E2Z#9jTs}*?M-tpNP9kYk9J3@@z+Mbh!>6_HL;@q z1_Bc7h-&4&Ic42~2@$hm@7#`bw7SiyOAbK}2)p$^@cMTe$bVO`EdNn}!MlDwy?*`) z^tj}4zpSUDQJ2yxUE_*)xWN4~eatmQ$@+DcB z6gtG*x&u|H9D2KKtZ{SZi3IJ4J%QR6oS0zqY1ErYmVy3Y%i&0~#!m)sQ0h;-okIphv^x1Mu1$~7U% znR8Ox{KebRqO@}Oy3aI$K7?N-jq7RCT!htb&vyY0+KG{BhwfKzeGbt~!Wq0CPN|fe zr(Vx@Bnja&bwtmH5H}bmE}4^`R=vG6Il|iO*cQGNRwY`137wTNw0Id~m-nCW5r!x-eSori?+T$Pw?;NkZ%>vxcYAQ{TzjQ zXsB3SYH>sR#XHA62X?a_eGscFmCiY|b4Xm2_>yg2g0v}(bYYZ-Fk{e8sh0NFH@|8F zKT@lC-!*KplHcG>OfaI_uRk8Xhhj^*gI9{ORcI^YK}wgZwp5bQ8%f=}O1Sv9)VU(W z(my<{dj*q2@*V~*VF||BdV~5TZ=(KTvRgyiKne!}d$g6J?Q!AL{_WD`>mmcDgX$K} zQg)*3Q-Wy%)O$$2#}sE$0&ZMM1c9#6Nb0@8bzZO}yrN-ivT!y|pXJzAy&=v)rUHLM z9OO!(P$m58)&U-NOAd)`J;t{hSmZuk_Ht{{^uBy{du>}H5lh-qFpx5@M<~1_z39E9 z(wClL`wHQ7*6MYNJ$LQ7aFi(UiN-SeG@y|V6wrZ4DA!2M2_#>RlPRf4uT^qCakSN^ z?-;Q_w$ za=DJ2YMh(Wyd^cSlrNnG?Q$w(C#Bf?u=ItTKis_!O9l>h ziy}P;*Fda!w_*B!6#$S=vSpo zIdx}^U{BM=kej~A@=Rlmt0l`fzWKAF=ucHBhJ~l_=fkeh7(29V@LNlx_8f`uIsVDu z?p;|^G~WBPpnhgf=Nn8&fHusKi6ALm>#^T95nPB-hG!KJJ+=k!fX} z3VHY9uc~&nonI{45Pg%OR_=Sw$(aOTK(M8|i?H(tG_^ zw%jC{97H8QmL=}XWr?f%i^NUljN4DtgFg76r#*@~gW~ys@SZ>Z5@rXTJ&Dir)n8l`7F}OqlX&fqR_KaF<*Y;KWo7Drb%1opeAHd$y64 zlwy9PF-v(_;`)!C4c5C>=ie*k@wt7n4_<%-i!#4%I-iez&r}g>Q`4+6S3No8Qpr~D zn!tW>WdD#KAKdKg{Q0MtcIAZorz$+tg5wonEF@zqB6r$!m$RxFyjSw)X!-X&vt~AI z@wN_RquUMjT|SDXQ^og zFz&Gc1!9cfJJrhSgr*2Z)v99NeQwNed4p3`FBrcYe_qrH^-2uDTjmU~q1*u)J3ksHa9lIS^*^*9g!j#3y)oSXQY69wy>qaY;wzx%npr4)uqK z(?ucTf+i2dZtRKVZhuKoFuF3pHt9bIxnjBN7KGU~Q6OMP^K9)U;%LiajmThx+$M=D zsv2B@zQgzFK(I^SdOC0h&OZ7~DFK!KVNAnoh%GeqcxLxZ(jK_I(?CLW!p)Dgz-vj0ldaNqMxr!%Gm^wQ@NkW+{aI# z#XpuxY-r#(^-!Nr?Tw|;NY#xChQ6IW$;XjNAal{K=PQ$jafVN2+Ga7=5^uH~M7VEp zhyB#44NoK zoq&x9*l0zOZ1(i$!1wk^<=?7MTCXe4eQvKBzx91}xXjtz4SPj~qT2hB$meY!7b$g% z^1R2nW1mullR>V!8c~(7vs&zf3!hJg`lOvBv!2@S+zV=6<-)^PNyUVX_4BNRNl?== zzS7z1-0c>5>&7@upk0=1RQTZBOcwk_{EX~T)*IrXGCfiEnewT5XP%QHh)M&Ue9h~#`P3GO zp1l;{U5^;?E|l>4M1(jgIb>5{VyO%yR=Ek%*%DvgKe zb9MhxU%VSi*05RfP39yt^M&Bf_BvahACDA=1y{CaphLHJT1E zQY_?|erhU{9`%49?!PR2JK6?)N_7x=--Hzt1v`bg>WyMQPtnHF0oE=j-*?%!X>U6x z2H!ub^bG&WOe|=oxKH42vJXYW7}R({?WhLx9qTWYEnEm{ zd?7lI=5^^P6KnEPw4K)tZK&ur%pCFvIn?|`h`WA5leQcQ@=B-G()j(JCvGWw{_;iC z3Ht>%4=FSBej%BzaA4`LEQ9{{M!~kmcwN9ae3z~Oa5~ad7Z6StFx6p|uNE+22%qVX zhBK9F6Q{~~a9CckJ7xl-es-Co(>@ly{w zQ7lN!7^EJ-Kje*dEv~lJZ9=;E%tw~Cn2#C2^u8L`Hkh+z%mN@V52VWw|H2e(qw@Jrd|K_5())Tnk|65~L}E@FK4l{!bil^dc5{cgO8a=^q%A9-kemzmZLOu_ zBnPraN*G*>CWAZ(RctG`h@asT)vmycDJF+q>~H0$n6!@e?euaT^n3DpYExK6N&RbQ z`A~IWn{%^#IIIOBaFdeT{g9?#^(Ryj1ncynF(SGBJsoX{E zdGav>Nv(H-_3!gwUU_#fhIf(%39w46B!!nIMr0^1oX#-p;W9Rkd-J08a~#x~P{!S9 zo$@NihKC}%lt5+IXrxk~(Sf0G7*4JYJ7U^_nwm_Y1F|M;jo>5#zee%)$~cL%AhlwU z`hS*?Fqa`iVFGM zrS#r+nO*v5{7`S5S&v{R9ML!aQ_$IBLQbBz+x82gGus;*Wgbi62Vd+)*Cv8uevQBn z+>Nv&pepGAFHNA4K(6L9%pOVDxa<9q8SK>kuHQ{7wo=U-%4xFHROIrsa{Lf{pQ?JbjYnupGKB#?LBVFirUMQWP>ZOs9> z333{erCH^WGI^ZpZPk$zMa#pCO)nNDhLktHoeTs-)JU_&m2BT2bkoB~!F8%BoL;=t)(xE)=rop9G^Jy@t_5SVweHqjSrq?F(vDJ+zZ#aneU| zGw)li`dztiWP;w+!W7a5JKID7T!2VGLk6z1h7MfA@)<{XDOw{+tMt$po`=>uruBL+ zDRC5B+B<#%D}ZvaLi15{i%DUGncD7*iheP;)#ir}d@{OqeOw>iyC{;}{gZ-5AaHJ0 zaQq(&b4drnf%#JfBpW={u@)*#Jd#1=!EelF?6yXPnMbXi9(p?q@nG-PsAH(rgCdpt ziood~r9koUCo#dJN_tP;b%Jt?cs^>-Z9`QzCNMzCnOEfj=32g6WQ$d-ag5dx)q2Sj zH!{TItPiH-7F`dJf{&&TLTYRr@#n8(eAwI@Ac;08Y&n-Bd*CK{e`TD!#DzmNui1Y% z{xpe|1MXo^ZG=Rr3WoZyO;^kNmgub{xp=RP5Be!P5O6lv9OHpQ7_sNnaEkumizJPD zJhmpu4-dOCOaA$DI-zH@aGuZl*`)|C*^|z%wC)b7%&M&!Y1#gRe%Y!liNh5oZ!hNO zR*1dLgK0%Sx)KpR@dhS|NaZ%1ze(bRIl)4Npz9*4ENuBto|j5;&yw!biOPHW@Z+15 zpCWlP3Kdd`VddZ=gR-Aw2CJMB(BDyXulGc)gH{3$d6b=@(1v=SGp!PZI9q^SJ*Aoc zetLnrmr}25+2gsmkPy6aH&bF)0))P3Q*tm(jyQYLKw159+aes(C$ zk9N-b^fV^#j$d#{D|7VWJxbaLISdA1togcDmcJLcF}f#8>a=F1uX?(6qlC*e(I=gJXz*6?}cZzE2=kB(?RBe?LqZd(o}52weP~>**X+Z zn&kKPE9yJZnoH*s|{r!G~y52O6HudKhKzsEFki;%V5d(Zyq(n}>;*=2g>QZG*JFwU%a)R-!HlMbvT>Aw=hAN2eV=HI@s z$2!&Efse`V=N6}R95&sY>E&IgeGOEte~|O*@cxe)o-29ZIi~j=#~b3Ck?F!kkrTm_ zfyK}a_H?RKP(P|uuy6nGFM3$V#ZNrvbOz9zx(n2=J3L8XldGre}` zdkpFLKY45*`*{=r9F6Ld%!M@ATCY(cv;_&=&$D!l=QY zv9o4PY)ZNU79$xm1HV@KFZ!RM195<+wFQi%Nog{lv|IUr)KjD412QJ}Dp4XveFL)O zF_P5#WiVrcp#kCJ!wB4>mc^iwz?j1Q5nqkBn+(p%Y@a?9FyXY*U_pZQ&@@Jr;zhkz z#yqkC(Tdj(*5b)QY-w*U5T=Ovd#Z4(I~ja?-Q9C>&N7=W&N0beNN%1h5c~)chdH@H z2KviWNGB8=pjg4KLZfXJZIiJ}u8}_L)8A?pE8%a%8=TVDp$pR8CCB2Y6qvzN>@lhDNQKoyVe8nDcgN13;|* zBgSgM>B1250i+XYfu$jrVE?L2yp^(XGa?JAKREv4TIfT;@Y|b;g1obQ#5Zb@#e-(m zDvPyFDqZpHAimW&D7md0zo;x1lU2la>Y@XeP@kSw3-w%iwZA@r&!+4=1h&gcsH|F-9A!WluRo#X~%w)*HELzf;O(!yKM~b zX>||?rfer-k4aOh70?RZLefJ`VECPL7_o`P$Df;0U+<5LsX1UDxuKd?-#_gGDM+9O zApGcn!TD_&lkNjA9S5*zWo)TZhqcfIF`#e4P|K15R?%=n@|qR_eN{U5aIhs7l}m` zC3+#5q!@80s5IeSTby%3t5khY{7ts&#K`knv1}KuYbRvQD*Jh{PW|jI=W|KP5J{V{ zXO)|%L$?xyoi@*Hd$l3CCoEfSo)E9ncny}95RzYeQp*&E-ae;p7fGAfJh9vH<^p^1 zQDd@POQ5z4uCdk)Wk!7nx|p^Q9g^=jdDd(CJ63wDn%1HHPSJtwp+=v}lO$p;rS04F z9FOj{8Z5*T>Z{8~1Gc zP$q~pB(1BRJYCLsm$ z@mVCpLGN-f1c?wm22~`Wu5QMLS>(3h)Py#M;-z9fY?ryU&PUd>t1LCzdoW`%iO@3$ zuTT;~FyW}7MZ^u&Wm2u5TC(%4Y#1lCu0J?>efzuZPLE_xL-r0l8f^mw^kaW=7H&;4+iR!HqoF(nuUv`{dmM;>2i`go<{%? z?&lpr<0Vnl5a)-_9@R?Vl6)&ZK&i6V_6zjOD2MSNtSYeUOXcn(woGdus3=VI+%?)6 zb9l25pIcoV0vB1p=_0{f3hhnr{JWgnDZW4L)k{@@)w_a^3}Kd^vrnGYU@|ofRScy zu&$PQ4jWZ>o_+-8Q1twpdXsa?Lh|F=4^IY7Cq(H@T*|(CIh7k;uF*KT4l0T8rU}*t zQn*qPn#Qf!1FfDI!G4<^ncnAPLi7~a7ftpAuCq8R15@R8ZAYEOq6y_gvWIR(FLw)a~MH4HSFG4j;^cdx6r$1)=lZR({uF{d{iJ${v+>@RDKX^$p%r zjcA-0C(DrJ=1;emI{FQ~o-8M_8HqL+QX9I*@#Byb^8nYOru?$~u$-gqb2m zRH+Sj`_xf-d~iLEyoVH5Z5cNvRH5`)p^%ZO--&rvPH^I;37Z1Z7*`lYMBzSR2e7=` zv+ui_XS-_Z95a;kvDp7AaO~CY*mW%WthoV9NKVlDGciY?DXk-2@+0@`^H3S;?9O_k z*xuGs_Q}WQ_yKV@>q&9>24j_xnw zIyD>Xh!+T$!tbRt2I+#)ME_+Mn-z|SM7To(d%Dl6AY=gaOnrMI3imHuUrNaz!cHqa z82zHqU!4zLtHS)f=dbq1QqXuVRP1NaFBDyJgn5>{Ma|& z(i^r{%%M11b+Xg-t{?utkl2n_=)m&Qa~xcHw%e!~Mf`L<{aUWMTdmJKOU&)6wkXS% zyO$kD7Twn4F5Dbx`yd6HK7XG5Tbj}@rq9(r?HunfYk2|GFH3pP$~M3kiOe=0NUM1TQ`LwwF92Y7TU`% z@2q$U0V`p_O22Dq#mmU%HMQRTQB&{MG!@zOD^UN5P059Tp`v@iZ6aiLeL8U8yr9{F z0oN$%Oc`p$1BgY6AE?#L0_FhABkv}4z$QnLK`~yBn zT*C)H8v6ZM`HMI*mH;hJ-2JqQL~q)yN*loolFGz~DHqdUU3Y)Ns3OKj{S<|`!r{#! z`IC+#Q&8JohFG2KDbkVI{>AwY6hR-f#@0A7rQIuD`wmB44Mbo(qMxzO|VrL84 z;j0IhD_c#na_eVL1fSxZgWaPp=$U2=ubulQ``6bv2QFyD1@1m1z|h}py+D!kb*GSB zVI-NCpx&U2s_=eD2O0~(82w<)e%c-|UQDoY?MwYNl^B|SH1rp6q>`7>U!D2B)`R_R zOxcAZUacKF4}BD8mC!_ksklymGgVp2Gsr)<7swyJ@R0Cx<~p9Q>%#Y{F=2s0(Zs$p4NTk3LYy-RO^m{R)`% z)UxKHHpugf;*t-t=3i)4OQdN9WEPr(U?4KTCW_4N+`nYS1?qp_(eu@4`a@^eYRZj+ zL7R9r&{y_NzXr~N8&NF$$01arK4r6aUoN;EMKDU&zq1Xr9@n9(um#|onI*W-^3EEY zg)G!UHG~k~?^{a;kmf1^{>D6%Yp@?>{%`T)TYuvD(_(D0;)|)XLj0etqbigm?VH@9 zP?kmCsAO-d|AmBC$X4JkSlEMwJFs8rw!DD(O3ELFs{hp}NGLEmJ!oEdNUkUMZ0LZS zux5J98F=L-_8*i){>Sp^aYMz^_=;hZWa$@E8Q=gF5xeRvT$|b>N-NL{hh~J)4nn%S z=)fXXsT8#JUdG0G`d(cp;Ao`=scj0IDQNz$t-b&=5DM-xK>E-DsTC9MG0<5o@V(dSNm|#(TQKDQf>~Le zlwPcUxw^@EIi}>`;{H(h1}zohm2wU5h|*1&C|8o7$qe+J&yXR{?T>ZMu-DR0A~kjn zao-j{)x>7JtoFn=BK1}pyK=&d`>*v+8!r!qFP_6$hBv0Vf=gQ|r0)j#d%O5gDDQg= zHWo*1KJu`VmI)0`fhWCe91*6-A6ED{X)(Xh>Y06Xx{AV2s`qqzi1=x~Z-Yg+QI_72 zJ1kzkPP=BCJ99ukREUVK>gOc!qrzbPT8deu@RKsRD1N7lCo9OjFA9J982(5+-Yhb* zMSkggala(0j=Kjo`(+g)I*o~j74n2Z*^oM|r9xgf9uZO{ysQ;f5ZhB>Y3-dYflX{a z@3lLf=QfWNU)^xxr+l97&$alDf`u&Y1tLxTLV`1jVy9}=x z%Ywg8+5V!L%ijwJ5=<>eM^AkQEsV+C8H2iH5&89_-scVk^+u; z)J90Z$y2Pb!0qfII?!QleW>&q?;9OR->Y(S#dgvY8W>A*pCopmxFdiKkx+%=DRn!O zeetZBMIydoUS~a@weHqaZ)ziFMP75N??jbvcZ{x`KmU?YHK3b~@Tjs_3V3iXVAhO{ zt8Pi$ks3D&hxc0RI=gS5se4+ywWDR zW9mrzBrosNzWoo*ywVDM^(4@T;nlE6jv8%!efB6#jCxgz=kZw4Q!u&CP2c+qYTmn< zqlG(7OSZqQ4FsmFGbkGx*6*MLj_whXGEwZ#w$en~g3QtP!aNM&%A9QEx=I=od>dtR zN|j~G#5lnqK<0!s7(tY$9g4Z=`oz%A>$*~oecjiR`ig`xGc13@@cuH$4Fo@XOP zwJD9rRtbtF+pTS0{%5D&5*3qw-ZA^!+_knF+BCy@B8^iZ@VU-ahCqc0lG}uvmg)`X zm~!qr5~+qxlRA9c_d#`n5IvFh;`V|w5DI@k?WfiX*xbS+)Tnhn!<_#Yl|PyE%VG^w z`N34ql(_!iRQ^jh|8t|`B;$FOz$99pW}{%Z#AD+HT@9?JUrN(1l8L8?w!#qR{p-d_ zHnIUlhtvsmBy?PPQBLEP)09+iIR7~=w{Mue@^Ri)azQ7pH)W%WQW%OAet_`WS?l7U z)gy{Z+5wTu#nvQ@)NEJC(+@vC@bw0x;6gOq%auYTg$a7M1bUq2otfS|K||eNZqNA8 zn+I9Q6hPJzHER}7>@asjIw0mE$wI`0D?cD`YN*5z3PTiWi8dcZK9GS1J@i(Z+w+HA{Yd!*;)cuI!Ujj2FbznFoQvK1HM}Zv2CX zNpota@@PSncD&Md{!z~Pk1;j}YLn{Y9qeN2q&n*$g|*j^+Mq=}8kW}?iq!OReuN+! z6XTQ9c0IF`E!6O>D|5b?b6G+4Eo;qWXdv``juJkh3eAcXB7E$OqB#0+M?JKeL!c9Qm#)6@x5SG*MlMB>rE02J58OgWen&@kyX>8x{C=i2g;#E?+3kHQI!t(62O@wpCl%mOJ(V?Z z?otuLb_ldp4r6`)rrm#y+PI!qI~Jh z(6e9z*~pD(-gL9#x@wdEtBzY2Zbb|azo>Upg9qaFlz1*!n9b4gSNOd2y*$^ByA zpj7Z~o{lyXHn~)adW+TuLIZ>aVcVd%#~`n@yW&m1oD1W9#@bi|x$U*Gu?DYIK7uj` zKJh`W68rwZA=17<((F6$b3z^6k(ZB5TfP%tFgwhccTaVHUFjtA&cRfbDKI?j8m%77 zuH{XzsuaZpQH--jX`2bR?p!ddSQu9hrEWLSbo(5W&T&(i{mo=~4FFi&MG8}sp=tpQ z7FfbH5~Ny^qa7-cbbRV`1U$cl*7mF@R;T3vU*uK$s4hpjPkUdnF^z+!qF*dTpef*& z(6C=DMBjwY2vZ#B`kOUdB>XAl{}}@PAC{SYj%t@9-%BzIqaH<-Y@J)|>7@msE27n^ zQ0ug0@KX?kV@*j-+&pNwK{y>&zEiy8?0VNvQO|Z>Q;*CQUc7A}EG)w$5v3>)uH}bM znYcpm9@HyVEf`c{7+osN-D#?tidM{@o-}zNSP4!PG>~SZxO+e+i#zCK(Gls}Oi~-b3L~Z} zla)I>Iou9Z(ImN*U+U>ynC~eWU=(~2^IUvG%oXe5YSeoRoLbG~As47B0h*LOW@}mH z{yLT;bl<|U`V9)anv4jH`Mp4`J2?163L#>k@O}yUiq`sv&Z3E#$FQdsgyeZlp1o-p zPbSHzjDMFY?bpJ8q_PS&P?j}b&|Uu3z553m@9Sn8A5ND1^?ucZ=nmu);QEsDEf<{uoWPD0WoY|5?t3oQ~I!Phn;f3IN^Hq zA_+YW8pOYWfWcu?W_TvFYH9wkm#Etf&0un!-**`TuSCH#fH*QZ(&boAd9oKIhv!Ut|$B(@ZUb~kK&@xfuH{!&}W{UlxFa#&!uo&I^B6e z;oQW&$~ewTLw=`qU`!TZ*zj*O{p$$*BOdx4LX-YW5c;qa~`)8NL0M*&41{b zLT^ux-M$8g+tO?!99Kxk!N}Wx$MN{T+y8&_@%T?E_`3OB`KqryxsE=~CR%Mh`_G2tAV5;->VAW${8nDj2IQKjrxq*pQjMTuyDt0;1#f_3Yq?jI5mzmLWG8iYO zd*9>7UG4P!BMo06iG&7S$iGqU%K`y(pZ>N&0Kld7MI3Btqp~|isG1H`HG^9ehAU9B z+nxGJN}xmddQNyaFpR=kBaCSwQDWehDP*iGDO3(oH5v!F;>Ek(yBD~(pJV|A zH~*#CgPLSH5>7FK5OTD@jV$|XqQFoC5|)%W0;ZQ;-q&=M4vd^=#uDHlKWxyaD4;=` zR#R>|YM@Mswxwj7JX6viK{Z%mPjmPc0+nV{9r39(Rna61$yE?|9y4Ln1UodivP0=> zA+Qk?U}ymSudBKQ4*b=K>D1K)Jg{rK1Y3=mFJLWD6jE092n1_2Vmy^i*uY4|)p!QM zYFvdF8!iC`FfgNdC8C$1@>of(&I7u@1xYc2P^er7@>ndw+aP9Bo2iUN?zOA%XI82L zZUYWK4|vNisDQB_tG{=jP(%sS0wdGy4$*m=yA*@a}kcF;C&M1(nV|Wv`R99nVo)Ma?5`Z*LCoOQdn@e=g@+($r3GR4tdEQ zik~>WNoeBoyFgXK?za~-WBoc&Yi6o^0F+RxMi5zd z4B;zdAiT?oI!^!vcSyqnJCU`6`o+>P60s-kHywciwVIybRQy9m|B>4APo6ofGy?88 z-|yCUws+-<&+>WCQhHk1I`)VFz-k~ze6n(9?yrjVD%CK)fug_4;1&(Kn8C0-V=dEP zeat{3$p|!9rGS=~vfAZcW9zd}Gh=jM0gPE-|0s{iqrIy{Dd8LIU>)MMw15B(N;HPH z;RGERZl?oNxyu{UTp^StEOj1MQG8hbYw1d=9cXCUtE#XwqG=Dga3~qm;Y{>e*zO7o1dsZ?s?~?j9mLBFgW{u)8B}* z&hf732ZO1@ehH?w92rkqv#S48o$LScpm>cMfu=Ue%y|_;T0VA<^0<0m1|6sk!BRcoAI&<4^GLVJlRP;6W)=Z+*#LFIP}%mlir089 zMT(I)#Km9G-Cpep52SSG=e`XwGxp-)SM1M+ z;EC(WilPsvW7W?|){1w)C@PS0^pZj{Gsv;G>Os$b6I+Iu?B1^O3!i%9(YU1LY!&h{~j#(t` zBOjrN7bmLQk@5z79AbiHo$-dd-&PF(%y$!KOTKx^71nana@d?Axbde^81;4EPbzo# zw@n1{|2UH{7>c#LHS8C!WjSaKDg(_B-wcbvfg0PsBVF>h)XK};y&TXUl|>UnFjXZh zw%Ny8N$?zb-j)%qR5mJb?xRKTyEV@BvKMZ`{41yaZmQ0J&}}LUO%7zKdF9M3~D7lDrr2wzqcJNa?L`&ibB3 zo)TyrX^$guV`cfII}v8uGzaIa^^h`r$+&(~uwj7KGcdu+bQ1-{t2&eV>&3jvWM*m_ z%$^D%%aq@6?iYg!kA950h4xbFD(I0{bF7adJ~K(Z%gOJ%?a?cYaSO~fg@-gV??^1F zhH>=tR(s)ILKkyp-44TcfT33F3>W!x5X0^=xpQ@ZWG)^RF3CwSn%Ed1O}reEYSW0` z#$|RiwA)}$tIG>U6#Gc_XXzKgdk5mTgz9p~>XpaeoRx~chgHIY(NK_QiW!v%6?nuF zcys~m`qCn}1&?O>%FdXbo?Igj{G7gHksxM*7K7Hl*XvhGinA289BV zd{25^;hdg+^=^h0)4j5FZfVcC&juZQlf!4D!w@)9oAh1^VgnwOQ+~NbpnIrKsp)j{ zspozMULq>$=6!o_#3Q=*_Z-M%7L=2Ub~UR^-r9_WKYW;;IyNubmpl~mqBZ9zehW0H zDQ2m&0`@fHmC`!oad>#&CSn8H4NuAk58@dsIiK**Res00iO`{2C;3_5u-$l*nk!P} z8tFZnqb2kppdMA^UKs&l=*|hjDP1q|pL_Tu^(5uibq`m_ZE<34Gmrevoq!U$)QM@b zWH>+u%z>yyH2#_cu@jVgRj5U|A)cptc+| zc{Cn5UHdH9f6p}h6)MycQ>oMgCcnE<)g3mEjZ(pcnT;oJYTNh5&|fw6fNVfaO-wC+ zP)%3uPx#d5)U+H>V}FFy9fV6#AfyL5`*63nG*cuT?jcU~c3W0I&swPNJNQAl=K_21 zMlH^}#QHv3XU9?6hg*`Mg*?Q9xYrK-%I!YtR8iP5m#l#9Y5&xHp9brO&r|yme4tqT z+%Fo?2;&TpaYbj5GG0L?iQHKuxdopeWaw%=IA&+zu~l7gT7U95S&OoR$X104O<^hJ zBakb7cf7zGHa{Nsy>6X(o&GbP49Cv+;h&2H>a5+0p5?eWh! zTO!8E7t&izRgD~OWi7L$Ue7vTrbsHnLne8$bcnCW6sm$rtA_UIM5T@MVH`g#18 z#Co*$2-6r@^UyiPO@&2Kc10l@)dy|EQ%^C>GL{*F*5&ID?>uo%VMfBTUfvriL07r$ z9FwNTyLC77yQ?3vin?=RSj(dGcs+@XbH75{Iyzqn-9>0fz`JUmENf;Keen25%~KfvKyoXSERp``AK|nuJQLwo`6+#ZBAKZ;r(5t@4qIE|}dZNL-i z6Q*9lHBSfiUXz|{JqAA?npcXbDAXrQ{QIo-%EduVXd#y|JQAw%i{lgbpS9F zdx{d6jh)!~5cFh#yRtg>4)!lH{Ayqr`5!wW6jDe*+2c?#f^FVolHY#!4ddpQCsiIs zCvY&?s*eiC1hE@uvX-#RGkx@;79io$ca*7#Wm{2h@f8(IzKXX|2RyButm(kU{)!~B z3Ycu}Lq-KEoIo)wENU&lgeTrg%XCT9y&BYN6h10~yfGN+)mQbjZs^hlBYz`s0)Z1S z_^>KE@ZRFp5~>m^S@(4=}A~J@;bE7gs7B2gCykqA-&3-v@*RWj6OX+Zc@{t-HAcv?Qm_t`5 z9pwpI>aXHq9+TYL&Vj0sy?*ggmupNlspiIBNhGkvaax1gqugE zVnX+w33A?cJFP16nCgb)tHeeL@8D9%Lj+TWs8Xn>6H8(I{gc%WuDmqiL6avbWa2a4>nS(0sIPy$Z0WIDxBAZ_rkjVos?g zHP3~^8p>uNCZJ=pF%vbQM2YPF8%?9LOle*VsY{_sG=FeHVL%O?ZMKAisWf3TWBuUD z6$~enXhRLRV|US%{ZFH3FfZBKc7f(NIEe!^rKpCttokk(1NJ!`G^b=QqKWBWVTPtf zfKY+QRlb5RisYLo{MIWpN#6^yIOqNr6$LqwP8pxtHzy9KEG5twL1q2jy?pF%UtZbK zrE179+?VGO=zkq#l>&9&{&O&mcI|P*J_yWuR`N5KR8V}oMZWtG zj`PsR4;50BlQ#oY?Ej}D;@=C0&s&%CK=sp#G1Hl23bIZU1A4*^y3D@f$Jz;TpjjkD z(B-1>Gcc>bHm-wzBd}zRJz+T{g#%URQ3IP703$~ZW&b5@aP4&B)qq$rov?$`$sbP* ze?pi2!$seUHDeBT*057|#hUSWC+)iL_fKG7@qz{IEauDkRhGk{LAmUBTv4p5+;9H zC3p%jH2;;e2cEAu^?DbW5O~E=*a~+^H(>a_Wo^|0zO;GdULX%ix4?KwTqT7(;{Z;4 zv#1Ki$EYUU^1+;UlxX^(1_HxvY=@0p01q~OmjF(>&ERBLm`Mi?gyw;n8o^VgCBcKa z!1=@K7#M_9c@oUastTu|^(oTb8B}i3M(X17>8QT)sZ2CJH#1romm`e=9vi9+Aw;;O z%&NP>7CzO3>coEmB%reW_i>^_DExx1pTeQ z;|BB^hWh^x5>}olEwx9L={7E6)O!JCeV|WuQe7R19`HaLe!B&pD z|NqeR@60++k!rY?dPeruhs(CL-`h2IDC;#>@)?+Yq2`^Pe0O=(UsXi!i9IaOIr%uQH7I0}jr{=wX2MCx1oJ@V+^Wm#@##Sio%oX{G>M82@hq E0KFNCi2wiq diff --git a/screenshots/horizontal_barchart.png b/screenshots/horizontal_barchart.png new file mode 100644 index 0000000000000000000000000000000000000000..f36e399c8ef85388e35acab8db1b535f5607385c GIT binary patch literal 16989 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 Date: Mon, 4 May 2015 16:22:42 +0200 Subject: [PATCH 0347/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c73aaf9a7a..147f0c3d4d 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Features - **Horizontal-BarChart** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.jpg) +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/horizontal_barchart.png) - **PieChart (with selection, ...)** From 39a9d2ea2976a5fedcaf45ac822b79063baa7203 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 4 May 2015 17:06:24 +0200 Subject: [PATCH 0348/1390] Fixed issue concerning elevation (issue #492, #512). --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/project.properties | 2 +- MPChartLib/project.properties | 2 +- .../charting/charts/BarLineChartBase.java | 13 ++++++++++--- screenshots/horizontal_barchart.png | Bin 16989 -> 16845 bytes 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index fba4e3d074..ab53a45c0a 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -6,13 +6,13 @@ + android:targetSdkVersion="22" /> >RNqRcHV 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 H`NRJYJgzSi From 3382c2f1afca2060f302f281cd34a16a0a96e7ec Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 4 May 2015 22:34:46 +0300 Subject: [PATCH 0349/1390] Minor improvements to Bubble chart --- .../mikephil/charting/renderer/BubbleChartRenderer.java | 4 ++-- .../src/com/github/mikephil/charting/utils/Transformer.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 7ba6b9f748..0002e3b605 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -86,7 +86,7 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { trans.pointValuesToPixel(sizeBuffer); // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = sizeBuffer[2] - sizeBuffer[0]; + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); @@ -223,7 +223,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { trans.pointValuesToPixel(sizeBuffer); // calcualte the full width of 1 step on the x-axis - final float maxBubbleWidth = sizeBuffer[2] - sizeBuffer[0]; + final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 349c76aae8..143167e99b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -128,7 +128,7 @@ public float[] generateTransformedValuesScatter(List entries, public float[] generateTransformedValuesBubble(List entries, float phaseX, float phaseY, int from, int to) { - final int count = (int)Math.ceil((to - from) * phaseX) * 2; + final int count = from - to; float[] valuePoints = new float[count]; From 710d5de4e6329f14dcd767d29d310e312126f32f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 4 May 2015 23:43:20 +0200 Subject: [PATCH 0350/1390] Minor fixes on BubbleChart. --- .../mikephil/charting/renderer/BubbleChartRenderer.java | 8 ++------ .../com/github/mikephil/charting/utils/Transformer.java | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 0002e3b605..3031b460b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -79,15 +79,13 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); sizeBuffer[0] = 0f; - sizeBuffer[1] = mChart.getYChartMin(); sizeBuffer[2] = 1f; - sizeBuffer[3] = mChart.getYChartMax(); trans.pointValuesToPixel(sizeBuffer); // calcualte the full width of 1 step on the x-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); + final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); for (int j = minx; j < maxx; j++) { @@ -216,15 +214,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); sizeBuffer[0] = 0f; - sizeBuffer[1] = mChart.getYChartMin(); sizeBuffer[2] = 1f; - sizeBuffer[3] = mChart.getYChartMax(); trans.pointValuesToPixel(sizeBuffer); // calcualte the full width of 1 step on the x-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); - final float maxBubbleHeight = Math.abs(sizeBuffer[1] - sizeBuffer[3]); + final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); final float referenceSize = Math.min(maxBubbleHeight, maxBubbleWidth); pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 143167e99b..349c76aae8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -128,7 +128,7 @@ public float[] generateTransformedValuesScatter(List entries, public float[] generateTransformedValuesBubble(List entries, float phaseX, float phaseY, int from, int to) { - final int count = from - to; + final int count = (int)Math.ceil((to - from) * phaseX) * 2; float[] valuePoints = new float[count]; From 2eca41fc8f71e7f889494df743a078c0b5a389da Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 May 2015 09:04:52 +0200 Subject: [PATCH 0351/1390] Fixed BubbleChart issue. --- .../xxmassdeveloper/mpchartexample/CombinedChartActivity.java | 1 + .../src/com/github/mikephil/charting/utils/Transformer.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 25ff1835ed..3d98460374 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -47,6 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (CombinedChart) findViewById(R.id.chart1); mChart.setDescription(""); + mChart.setBackgroundColor(Color.WHITE); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 349c76aae8..d87a5f5a8a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -128,7 +128,7 @@ public float[] generateTransformedValuesScatter(List entries, public float[] generateTransformedValuesBubble(List entries, float phaseX, float phaseY, int from, int to) { - final int count = (int)Math.ceil((to - from) * phaseX) * 2; + final int count = (int) Math.ceil(to - from) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; float[] valuePoints = new float[count]; @@ -137,7 +137,7 @@ public float[] generateTransformedValuesBubble(List entries, Entry e = entries.get(j / 2 + from); if (e != null) { - valuePoints[j] = (float)(e.getXIndex() - from) * phaseX + from; + valuePoints[j] = (float) (e.getXIndex() - from) * phaseX + from; valuePoints[j + 1] = e.getVal() * phaseY; } } From d94bf5bc0db294e3d848d7c342deac3edea004a3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 May 2015 18:29:45 +0200 Subject: [PATCH 0352/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 147f0c3d4d..bcc93c190c 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.0.9' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.0' } ``` @@ -157,7 +157,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.0.9 + v2.1.0 ``` From d8cb907465eb256ec7cbfde37df776857bc5eb7f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 6 May 2015 12:14:54 +0200 Subject: [PATCH 0353/1390] Minor fix in CombinedData. --- MPChartLib/AndroidManifest.xml | 2 +- .../mikephil/charting/data/CombinedData.java | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/MPChartLib/AndroidManifest.xml b/MPChartLib/AndroidManifest.xml index 57ddacc805..bda2ca4cb0 100644 --- a/MPChartLib/AndroidManifest.xml +++ b/MPChartLib/AndroidManifest.xml @@ -6,7 +6,7 @@ + android:targetSdkVersion="22" /> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java new file mode 100644 index 0000000000..68d57c31b3 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -0,0 +1,72 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +public class ScrollViewActivity extends DemoBase { + + private BarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_scrollview); + + mChart = (BarChart) findViewById(R.id.chart1); + + mChart.setDescription(""); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + mChart.setDrawBarShadow(false); + mChart.setDrawGridBackground(false); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTTOM); + xAxis.setLabelsToSkip(0); + xAxis.setDrawGridLines(false); + + mChart.getAxisLeft().setDrawGridLines(false); + + mChart.getLegend().setEnabled(false); + + setData(10); + } + + private void setData(int count) { + + ArrayList yVals = new ArrayList(); + ArrayList xVals = new ArrayList(); + + for (int i = 0; i < count; i++) { + float val = (float) (Math.random() * count) + 15; + yVals.add(new BarEntry((int) val, i)); + xVals.add((int) val + ""); + } + + BarDataSet set = new BarDataSet(yVals, "Data Set"); + set.setColors(ColorTemplate.VORDIPLOM_COLORS); + set.setDrawValues(false); + + BarData data = new BarData(xVals, set); + + mChart.setData(data); + mChart.invalidate(); + mChart.animateY(800); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index b800acce7a..5f6f7f0d8c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -43,6 +43,7 @@ import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; +import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; @@ -120,6 +121,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Sinus Bar Chart", "A Bar Chart plotting the sinus function with 8.000 values.")); + objects.add(new ContentItem( + "Chart in ScrollView", + "This demonstrates how to use a chart inside a ScrollView.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -241,6 +245,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, BarChartActivitySinus.class); startActivity(i); break; + case 25: + i = new Intent(this, ScrollViewActivity.class); + startActivity(i); + break; } overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index ddd75daba7..353d7e2dca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1510,20 +1510,6 @@ public boolean saveToGallery(String fileName, int quality) { ? false : true; } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - - // prepareContentRect(); - for (int i = 0; i < getChildCount(); i++) { - getChildAt(i).layout(left, top, right, bottom); - } - } - /** tasks to be done after the view is setup */ protected ArrayList mJobs = new ArrayList(); @@ -1555,6 +1541,27 @@ public ArrayList getJobs() { return mJobs; } + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + + for (int i = 0; i < getChildCount(); i++) { + getChildAt(i).layout(left, top, right, bottom); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int size = (int) Utils.convertDpToPixel(50f); + setMeasuredDimension( + Math.max(getSuggestedMinimumWidth(), + resolveSize(size, + widthMeasureSpec)), + Math.max(getSuggestedMinimumHeight(), + resolveSize(size, + heightMeasureSpec))); + } + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { if (mLogEnabled) From a4e1d26805f9b542f5d7f8e20de105ae9adb08f4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 9 Jun 2015 09:24:02 +0200 Subject: [PATCH 0386/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bcc93c190c..b9fc462b47 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Features ======= **Core features:** - - 7 different chart types + - 8 different chart types - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) From 10fedf2e2b27b7f94fed6b18c7fc70122e0bb5d3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 11 Jun 2015 08:17:22 +0200 Subject: [PATCH 0387/1390] Fix issue #740 --- .../mpchartexample/BarChartActivityMultiDataset.java | 5 ++++- .../charting/listener/BarLineChartTouchListener.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index f753146e3f..18488aa409 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -87,6 +87,9 @@ protected void onCreate(Bundle savedInstanceState) { Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART_INSIDE); l.setTypeface(tf); + l.setYOffset(0f); + l.setYEntrySpace(0f); + l.setTextSize(8f); XAxis xl = mChart.getXAxis(); xl.setTypeface(tf); @@ -95,7 +98,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setTypeface(tf); leftAxis.setValueFormatter(new LargeValueFormatter()); leftAxis.setDrawGridLines(false); - leftAxis.setSpaceTop(25f); + leftAxis.setSpaceTop(30f); mChart.getAxisRight().setEnabled(false); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 3d79d88b70..5b6e3827b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -536,7 +536,7 @@ public boolean onDoubleTap(MotionEvent e) { PointF trans = getTrans(e.getX(), e.getY()); - mChart.zoom(1.4f, 1.4f, trans.x, trans.y); + mChart.zoom(mChart.isScaleXEnabled() ? 1.4f : 1f, mChart.isScaleYEnabled() ? 1.4f : 1f, trans.x, trans.y); if (mChart.isLogEnabled()) Log.i("BarlineChartTouch", "Double-Tap, Zooming In, x: " + trans.x + ", y: " From 273828526ff1ce125845f62ac4bd31c0d9d3433c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Jun 2015 12:34:34 +0300 Subject: [PATCH 0388/1390] Bugfix: Highlights on xIndex that miss yValues were still highlighting --- .../mikephil/charting/charts/Chart.java | 22 ++++++++++++------- .../mikephil/charting/data/DataSet.java | 2 +- .../charting/renderer/BarChartRenderer.java | 5 ++--- .../renderer/BubbleChartRenderer.java | 2 ++ .../renderer/CandleStickChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 6 ++++- .../charting/renderer/RadarChartRenderer.java | 3 +++ .../renderer/ScatterChartRenderer.java | 6 ++++- 8 files changed, 33 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 353d7e2dca..ef59fcaed5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -510,6 +510,8 @@ public void highlightValue(int xIndex, int dataSetIndex) { */ public void highlightTouch(Highlight high) { + Entry e = null; + if (high == null) mIndicesToHightlight = null; else { @@ -517,10 +519,17 @@ public void highlightTouch(Highlight high) { if (mLogEnabled) Log.i(LOG_TAG, "Highlighted: " + high.toString()); - // set the indices to highlight - mIndicesToHightlight = new Highlight[] { - high - }; + e = mData.getEntryForHighlight(high); + if (e == null || e.getXIndex() != high.getXIndex()) { + mIndicesToHightlight = null; + high = null; + } + else { + // set the indices to highlight + mIndicesToHightlight = new Highlight[] { + high + }; + } } // redraw the chart @@ -531,9 +540,6 @@ public void highlightTouch(Highlight high) { if (!valuesToHighlight()) mSelectionListener.onNothingSelected(); else { - - Entry e = mData.getEntryForHighlight(high); - // notify the listener mSelectionListener.onValueSelected(e, high.getDataSetIndex(), high); } @@ -570,7 +576,7 @@ protected void drawMarkers(Canvas canvas) { Entry e = mData.getEntryForHighlight(mIndicesToHightlight[i]); // make sure entry not null - if (e == null) + if (e == null || e.getXIndex() != mIndicesToHightlight[i].getXIndex()) continue; float[] pos = getMarkerPosition(e, dataSetIndex); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e5b813349b..75ddc31b03 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -176,7 +176,7 @@ public float getYValForXIndex(int xIndex) { Entry e = getEntryForXIndex(xIndex); - if (e != null) + if (e != null && e.getXIndex() == xIndex) return e.getVal(); else return Float.NaN; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index feae3e4606..941089e94b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -338,10 +338,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (index < mChart.getBarData().getYValCount() && index >= 0 && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { - BarEntry e = mChart.getBarData().getDataSetByIndex(dataSetIndex) - .getEntryForXIndex(index); + BarEntry e = set.getEntryForXIndex(index); - if (e == null) + if (e == null || e.getXIndex() != index) continue; float groupspace = mChart.getBarData().getGroupSpace(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 40d4f06074..c836045510 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -210,6 +210,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); + if (entry == null || entry.getXIndex() != indice.getXIndex()) + continue; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 2dacf4daa5..aeef3b1b72 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -272,7 +272,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { CandleEntry e = set.getEntryForXIndex(xIndex); - if (e == null) + if (e == null || e.getXIndex() != xIndex) continue; float low = e.getLow() * mAnimator.getPhaseY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 9aab70863f..8604575a20 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -546,7 +546,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get + float yValue = set.getYValForXIndex(xIndex); + if (yValue == Float.NaN) + continue; + + float y = yValue * mAnimator.getPhaseY(); // get // the // y-position diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 44cf2e3b4d..268f2acd13 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -219,6 +219,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int xIndex = indices[i].getXIndex(); Entry e = set.getEntryForXIndex(xIndex); + if (e == null || e.getXIndex() != xIndex) + continue; + int j = set.getEntryPosition(e); float y = (e.getVal() - mChart.getYChartMin()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index cb154ef20e..ec1c68fd23 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -266,7 +266,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - float y = set.getYValForXIndex(xIndex) * mAnimator.getPhaseY(); // get + float yValue = set.getYValForXIndex(xIndex); + if (yValue == Float.NaN) + continue; + + float y = yValue * mAnimator.getPhaseY(); // get // the // y-position From c92d32659bd5da7d97e8a6581c9fde3e39c37004 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 11 Jun 2015 12:35:11 +0300 Subject: [PATCH 0389/1390] Bugfix: In some cases involving missing y-values, the highlight would not draw --- .../com/github/mikephil/charting/renderer/BarChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 941089e94b..d95eac622e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -335,7 +335,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mHighlightPaint.setAlpha(set.getHighLightAlpha()); // check outofbounds - if (index < mChart.getBarData().getYValCount() && index >= 0 + if (index >= 0 && index < (mChart.getXChartMax() * mAnimator.getPhaseX()) / setCount) { BarEntry e = set.getEntryForXIndex(index); From 9db1b2f2d607c722abaa96c25797fbf29a8a2092 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jun 2015 11:17:18 +0200 Subject: [PATCH 0390/1390] Add possiblity to set custom axis renderers (#752). --- .../charting/charts/BarLineChartBase.java | 24 +++++++++++++++++++ .../charting/renderer/LineChartRenderer.java | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 3d5e5cdd11..f5712428c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1409,14 +1409,38 @@ public XAxisRenderer getRendererXAxis() { return mXAxisRenderer; } + /** + * Sets a custom XAxisRenderer and overrides the existing (default) one. + * @param xAxisRenderer + */ + public void setXAxisRenderer(XAxisRenderer xAxisRenderer) { + mXAxisRenderer = xAxisRenderer; + } + public YAxisRenderer getRendererLeftYAxis() { return mAxisRendererLeft; } + /** + * Sets a custom axis renderer for the left axis and overwrites the existing one. + * @param rendererLeftYAxis + */ + public void setRendererLeftYAxis(YAxisRenderer rendererLeftYAxis) { + mAxisRendererLeft = rendererLeftYAxis; + } + public YAxisRenderer getRendererRightYAxis() { return mAxisRendererRight; } + /** + * Sets a custom axis renderer for the right acis and overwrites the existing one. + * @param rendererRightYAxis + */ + public void setRendererRightYAxis(YAxisRenderer rendererRightYAxis) { + mAxisRendererRight = rendererRightYAxis; + } + public float getYChartMax() { return Math.max(mAxisLeft.mAxisMaximum, mAxisRight.mAxisMaximum); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 8604575a20..3b1dee5f1e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -219,7 +219,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { cubicFillPath.reset(); cubicFillPath.addPath(cubicPath); // create a new path, this is bad for performance - drawCubicFill(mBitmapCanvas, dataSet, cubicFillPath, trans, + drawCubicFill(dataSet, cubicFillPath, trans, entryFrom.getXIndex(), entryFrom.getXIndex() + size); } @@ -234,7 +234,7 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { mRenderPaint.setPathEffect(null); } - protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans, + protected void drawCubicFill(LineDataSet dataSet, Path spline, Transformer trans, int from, int to) { float fillMin = mChart.getFillFormatter() From 978201c072f2c09c2718da1a207e56fd4ea2aa8b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jun 2015 18:13:16 +0200 Subject: [PATCH 0391/1390] Fixed dashed line issue on x-axis grid (issue #755). --- .../mikephil/charting/renderer/XAxisRenderer.java | 13 ++++++++++--- .../mikephil/charting/renderer/YAxisRenderer.java | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 426abd7c78..76a1ddd7d9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -163,6 +163,7 @@ public void renderGridLines(Canvas c) { if (!mXAxis.isDrawGridLinesEnabled() || !mXAxis.isEnabled()) return; + // pre alloc float[] position = new float[] { 0f, 0f }; @@ -171,18 +172,24 @@ public void renderGridLines(Canvas c) { mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); mGridPaint.setPathEffect(mXAxis.getGridDashPathEffect()); + Path gridLinePath = new Path(); + for (int i = mMinX; i <= mMaxX; i += mXAxis.mAxisLabelModulus) { position[0] = i; - mTrans.pointValuesToPixel(position); if (position[0] >= mViewPortHandler.offsetLeft() && position[0] <= mViewPortHandler.getChartWidth()) { - c.drawLine(position[0], mViewPortHandler.offsetTop(), position[0], - mViewPortHandler.contentBottom(), mGridPaint); + gridLinePath.moveTo(position[0], mViewPortHandler.contentBottom()); + gridLinePath.lineTo(position[0], mViewPortHandler.contentTop()); + + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); } + + gridLinePath.reset(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 7016e1f091..ab46fbffa2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -253,6 +253,7 @@ public void renderGridLines(Canvas c) { gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); + // draw a path because lines don't support dashing on lower android versions c.drawPath(gridLinePath, mGridPaint); gridLinePath.reset(); From f3635b69f7062b08215a7c6ab3073fc9d3a0563b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jun 2015 18:17:14 +0200 Subject: [PATCH 0392/1390] Fix issue that ignored y-offset on YAxis (issue #754). --- .../com/xxmassdeveloper/mpchartexample/LineChartActivity1.java | 1 + .../src/com/github/mikephil/charting/components/YAxis.java | 2 ++ .../com/github/mikephil/charting/renderer/YAxisRenderer.java | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index b19f814418..83cc2c9cfb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -127,6 +127,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); leftAxis.setStartAtZero(false); + //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); // limit lines are drawn behind data (and not on top) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 85eb9327d1..b55e30001f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -93,11 +93,13 @@ public enum AxisDependency { public YAxis() { super(); this.mAxisDependency = AxisDependency.LEFT; + this.mYOffset = 0f; } public YAxis(AxisDependency position) { super(); this.mAxisDependency = position; + this.mYOffset = 0f; } public AxisDependency getAxisDependency() { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index ab46fbffa2..d76eefe272 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -157,7 +157,7 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setColor(mYAxis.getTextColor()); float xoffset = mYAxis.getXOffset(); - float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f; + float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f + mYAxis.getYOffset(); AxisDependency dependency = mYAxis.getAxisDependency(); YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); From 19a0e03efa78fd056bda1ede639a4639e56a5148 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 12 Jun 2015 18:34:37 +0200 Subject: [PATCH 0393/1390] Fix issue concerning highlighting (issue #745). --- .../res/layout/activity_piechart.xml | 2 +- .../charting/charts/BarLineChartBase.java | 26 ++++--------- .../mikephil/charting/charts/Chart.java | 18 ++++++++- .../charting/charts/PieRadarChartBase.java | 26 +++---------- .../listener/BarLineChartTouchListener.java | 19 +-------- .../charting/listener/ChartTouchListener.java | 39 +++++++++++++++++++ .../listener/PieRadarChartTouchListener.java | 30 +++----------- 7 files changed, 77 insertions(+), 83 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java diff --git a/MPChartExample/res/layout/activity_piechart.xml b/MPChartExample/res/layout/activity_piechart.xml index 1cc2734905..1c81ea868d 100644 --- a/MPChartExample/res/layout/activity_piechart.xml +++ b/MPChartExample/res/layout/activity_piechart.xml @@ -6,7 +6,7 @@ >>>( + mChartTouchListener = new BarLineChartTouchListener>>>( this, mViewPortHandler.getMatrixTouch()); mGridBackgroundPaint = new Paint(); @@ -564,28 +565,25 @@ public Transformer getTransformer(AxisDependency which) { return mRightAxisTransformer; } - /** touchlistener that handles touches and gestures on the chart */ - protected OnTouchListener mListener; - @Override public boolean onTouchEvent(MotionEvent event) { super.onTouchEvent(event); - if (mListener == null || mDataNotSet) + if (mChartTouchListener == null || mDataNotSet) return false; // check if touch gestures are enabled if (!mTouchEnabled) return false; else - return mListener.onTouch(this, event); + return mChartTouchListener.onTouch(this, event); } @Override public void computeScroll() { - if (mListener instanceof BarLineChartTouchListener) - ((BarLineChartTouchListener) mListener).computeScroll(); + if (mChartTouchListener instanceof BarLineChartTouchListener) + ((BarLineChartTouchListener) mChartTouchListener).computeScroll(); } /** @@ -850,16 +848,6 @@ public float getDeltaY(AxisDependency axis) { return mAxisRight.mAxisRange; } - /** - * set a new (e.g. custom) charttouchlistener NOTE: make sure to - * setTouchEnabled(true); if you need touch gestures on the chart - * - * @param l - */ - public void setOnTouchListener(OnTouchListener l) { - this.mListener = l; - } - /** * Sets the OnDrawListener * @@ -1466,7 +1454,7 @@ public boolean isAnyAxisInverted() { * Flag that indicates if auto scaling on the y axis is enabled. This is * especially interesting for charts displaying financial data. * - * @param If enabled the y axis automatically adjusts to the min and max y + * @param enabled the y axis automatically adjusts to the min and max y * values of the current x axis range whenever the viewport * changes */ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index ef59fcaed5..fb0c7293a9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -34,6 +34,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; @@ -122,6 +123,8 @@ public abstract class Chart>>> - extends SimpleOnGestureListener implements OnTouchListener { + extends ChartTouchListener { // private static final long REFRESH_MILLIS = 20; @@ -62,9 +62,6 @@ public class BarLineChartTouchListener mClosestDataSetToTouch; /** the chart the listener represents */ @@ -410,20 +407,6 @@ private void performHighlightDrag(MotionEvent e) { */ /** DOING THE MATH BELOW ;-) */ - /** - * returns the distance between two points - * - * @param eventX - * @param startX - * @param eventY - * @param startY - * @return - */ - private static float distance(float eventX, float startX, float eventY, float startY) { - float dx = eventX - startX; - float dy = eventY - startY; - return (float) Math.sqrt(dx * dx + dy * dy); - } /** * Determines the center point between two pointer touch points. diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java new file mode 100644 index 0000000000..baf7da323c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -0,0 +1,39 @@ +package com.github.mikephil.charting.listener; + +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.View; + +import com.github.mikephil.charting.utils.Highlight; + +/** + * Created by philipp on 12/06/15. + */ +public abstract class ChartTouchListener extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { + + /** the last highlighted object (via touch) */ + protected Highlight mLastHighlighted; + + /** + * Sets the last value that was highlighted via touch. + * @param high + */ + public void setLastHighlighted(Highlight high) { + mLastHighlighted = high; + } + + /** + * returns the distance between two points + * + * @param eventX + * @param startX + * @param eventY + * @param startY + * @return + */ + protected static float distance(float eventX, float startX, float eventY, float startY) { + float dx = eventX - startX; + float dy = eventY - startY; + return (float) Math.sqrt(dx * dx + dy * dy); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 78bd9f269a..3620d9e6a3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -25,7 +25,7 @@ * * @author Philipp Jahoda */ -public class PieRadarChartTouchListener extends SimpleOnGestureListener implements OnTouchListener { +public class PieRadarChartTouchListener extends ChartTouchListener { private static final int NONE = 0; private static final int ROTATE = 1; @@ -138,9 +138,6 @@ public boolean onSingleTapConfirmed(MotionEvent e) { return true; } - /** reference to the last highlighted object */ - private Highlight mLastHighlight = null; - @Override public boolean onSingleTapUp(MotionEvent e) { @@ -157,7 +154,7 @@ public boolean onSingleTapUp(MotionEvent e) { // if no slice was touched, highlight nothing mChart.highlightValues(null); - mLastHighlight = null; + mLastHighlighted = null; } else { @@ -173,7 +170,7 @@ public boolean onSingleTapUp(MotionEvent e) { if (index < 0) { mChart.highlightValues(null); - mLastHighlight = null; + mLastHighlighted = null; } else { @@ -192,14 +189,14 @@ public boolean onSingleTapUp(MotionEvent e) { Highlight h = new Highlight(index, dataSetIndex); - if (h.equalTo(mLastHighlight)) { + if (h.equalTo(mLastHighlighted)) { mChart.highlightTouch(null); - mLastHighlight = null; + mLastHighlighted = null; } else { mChart.highlightTouch(h); - mLastHighlight = h; + mLastHighlighted = h; } } } @@ -326,21 +323,6 @@ public void updateGestureRotation(float x, float y) { } - /** - * returns the distance between two points - * - * @param eventX - * @param startX - * @param eventY - * @param startY - * @return - */ - private static float distance(float eventX, float startX, float eventY, float startY) { - float dx = eventX - startX; - float dy = eventY - startY; - return (float) Math.sqrt(dx * dx + dy * dy); - } - public void stopDeceleration() { mDecelerationAngularVelocity = 0.f; } From 28c9eaf6bbfddb8e52fc825acd7e3f353ff6821b Mon Sep 17 00:00:00 2001 From: Matthias Koch Date: Sat, 13 Jun 2015 01:01:59 +0200 Subject: [PATCH 0394/1390] added possibility to skip labels and WebLines in RadarChart --- .../mikephil/charting/charts/RadarChart.java | 22 +++++++++++++++++++ .../charting/renderer/RadarChartRenderer.java | 4 ++-- .../renderer/XAxisRendererRadarChart.java | 4 ++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index ee749362a9..6d6847bbba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -44,6 +44,8 @@ public class RadarChart extends PieRadarChartBase { /** flag indicating if the web lines should be drawn or not */ private boolean mDrawWeb = true; + private int mWebModulus = 1; + /** the object reprsenting the y-axis labels */ private YAxis mYAxis; @@ -317,6 +319,26 @@ public void setDrawWeb(boolean enabled) { mDrawWeb = enabled; } + /** + * Sets the number of lines that should be skipped on the web before the + * next line is drawn. + * + * @param count + */ + public void setSkipWebLines(int count) { + if (count >0) { + mWebModulus = count; + } + } + + /** + * + * @return + */ + public int getWebModulus() { + return mWebModulus; + } + @Override protected float getRequiredBottomOffset() { return mLegendRenderer.getLabelPaint().getTextSize() * 4.f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 268f2acd13..067df7c58a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -167,8 +167,8 @@ protected void drawWeb(Canvas c) { mWebPaint.setColor(mChart.getWebColor()); mWebPaint.setAlpha(mChart.getWebAlpha()); - for (int i = 0; i < mChart.getData().getXValCount(); i++) { - + int mod = mChart.getWebModulus(); + for (int i = 0; i < mChart.getData().getXValCount(); i += mod) { PointF p = Utils.getPosition(center, mChart.getYRange() * factor, sliceangle * i + rotationangle); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index 77eab01792..f6710ebc6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -37,8 +37,8 @@ public void renderAxisLabels(Canvas c) { PointF center = mChart.getCenterOffsets(); - for (int i = 0; i < mXAxis.getValues().size(); i++) { - + int mod = mXAxis.mAxisLabelModulus; + for (int i = 0; i < mXAxis.getValues().size(); i += mod) { String text = mXAxis.getValues().get(i); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; From be95c277e908a959e117bdb15c7c3366202861ab Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 13 Jun 2015 14:40:57 +0200 Subject: [PATCH 0395/1390] Did some refactoring in the touch-listeners. --- .../charting/charts/BarLineChartBase.java | 5 +- .../listener/BarLineChartTouchListener.java | 41 ++-------------- .../charting/listener/ChartTouchListener.java | 36 +++++++++++++- .../listener/PieRadarChartTouchListener.java | 49 +++++-------------- 4 files changed, 55 insertions(+), 76 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b20f8d5b79..41405aa06a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -148,8 +148,7 @@ protected void init() { mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); - mChartTouchListener = new BarLineChartTouchListener>>>( - this, mViewPortHandler.getMatrixTouch()); + mChartTouchListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); mGridBackgroundPaint = new Paint(); mGridBackgroundPaint.setStyle(Style.FILL); @@ -583,7 +582,7 @@ public boolean onTouchEvent(MotionEvent event) { public void computeScroll() { if (mChartTouchListener instanceof BarLineChartTouchListener) - ((BarLineChartTouchListener) mChartTouchListener).computeScroll(); + ((BarLineChartTouchListener) mChartTouchListener).computeScroll(); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index d447dbcf6e..68f8135d64 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -29,10 +29,7 @@ * * @author Philipp Jahoda */ -public class BarLineChartTouchListener>>> - extends ChartTouchListener { - - // private static final long REFRESH_MILLIS = 20; +public class BarLineChartTouchListener extends ChartTouchListener>>> { /** the original touch-matrix from the chart */ private Matrix mMatrix = new Matrix(); @@ -46,30 +43,12 @@ public class BarLineChartTouchListener mClosestDataSetToTouch; - /** the chart the listener represents */ - private T mChart; - - /** the gesturedetector used for detecting taps and longpresses, ... */ - private GestureDetector mGestureDetector; - /** used for tracking velocity of dragging */ private VelocityTracker mVelocityTracker; @@ -77,11 +56,9 @@ public class BarLineChartTouchListener>> chart, Matrix touchMatrix) { + super(chart); this.mMatrix = touchMatrix; - - mGestureDetector = new GestureDetector(chart.getContext(), this); } @SuppressLint("ClickableViewAccessibility") @@ -460,7 +437,8 @@ private static float getYDist(MotionEvent e) { * returns the correct translation depending on the provided x and y touch * points * - * @param e + * @param x + * @param y * @return */ public PointF getTrans(float x, float y) { @@ -495,15 +473,6 @@ public Matrix getMatrix() { return mMatrix; } - /** - * returns the touch mode the listener is currently in - * - * @return - */ - public int getTouchMode() { - return mTouchMode; - } - @Override public boolean onDoubleTap(MotionEvent e) { diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java index baf7da323c..fc607cd210 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -4,16 +4,41 @@ import android.view.MotionEvent; import android.view.View; +import com.github.mikephil.charting.charts.Chart; import com.github.mikephil.charting.utils.Highlight; /** * Created by philipp on 12/06/15. */ -public abstract class ChartTouchListener extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { +public abstract class ChartTouchListener> extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { + + // states + protected static final int NONE = 0; + protected static final int DRAG = 1; + protected static final int X_ZOOM = 2; + protected static final int Y_ZOOM = 3; + protected static final int PINCH_ZOOM = 4; + protected static final int POST_ZOOM = 5; + protected static final int ROTATE = 6; + + /** integer field that holds the current touch-state */ + protected int mTouchMode = NONE; /** the last highlighted object (via touch) */ protected Highlight mLastHighlighted; + /** the gesturedetector used for detecting taps and longpresses, ... */ + protected GestureDetector mGestureDetector; + + /** the chart the listener represents */ + protected T mChart; + + public ChartTouchListener(T chart) { + this.mChart = chart; + + mGestureDetector = new GestureDetector(chart.getContext(), this); + } + /** * Sets the last value that was highlighted via touch. * @param high @@ -22,6 +47,15 @@ public void setLastHighlighted(Highlight high) { mLastHighlighted = high; } + /** + * returns the touch mode the listener is currently in + * + * @return + */ + public int getTouchMode() { + return mTouchMode; + } + /** * returns the distance between two points * diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 3620d9e6a3..113172931e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -25,31 +25,20 @@ * * @author Philipp Jahoda */ -public class PieRadarChartTouchListener extends ChartTouchListener { - - private static final int NONE = 0; - private static final int ROTATE = 1; +public class PieRadarChartTouchListener extends ChartTouchListener> { private PointF mTouchStartPoint = new PointF(); - private PieRadarChartBase mChart; - /** the angle where the dragging started */ private float mStartAngle = 0f; - private int mTouchMode = NONE; - - private GestureDetector mGestureDetector; - private ArrayList _velocitySamples = new ArrayList(); private long mDecelerationLastTime = 0; private float mDecelerationAngularVelocity = 0.f; - public PieRadarChartTouchListener(PieRadarChartBase ctx) { - this.mChart = ctx; - - mGestureDetector = new GestureDetector(ctx.getContext(), this); + public PieRadarChartTouchListener(PieRadarChartBase chart) { + super(chart); } @SuppressLint("ClickableViewAccessibility") @@ -204,23 +193,12 @@ public boolean onSingleTapUp(MotionEvent e) { return true; } - @Override - public boolean onDoubleTap(MotionEvent e) { - OnChartGestureListener l = mChart.getOnChartGestureListener(); - - if (l != null) { - l.onChartDoubleTapped(e); - } - return super.onDoubleTap(e); - } - - private void resetVelocity() - { + private void resetVelocity() { _velocitySamples.clear(); } - private void sampleVelocity(float touchLocationX, float touchLocationY) - { + private void sampleVelocity(float touchLocationX, float touchLocationY) { + long currentTime = AnimationUtils.currentAnimationTimeMillis(); _velocitySamples.add(new AngularVelocitySample(currentTime, mChart.getAngleForPoint(touchLocationX, touchLocationY))); @@ -241,8 +219,8 @@ private void sampleVelocity(float touchLocationX, float touchLocationY) } } - private float calculateVelocity() - { + private float calculateVelocity() { + if (_velocitySamples.isEmpty()) return 0.f; @@ -305,9 +283,7 @@ else if (firstSample.angle - lastSample.angle > 180.0) * @param y */ public void setGestureStartAngle(float x, float y) { - mStartAngle = mChart.getAngleForPoint(x, y) - mChart.getRawRotationAngle(); - } /** @@ -318,11 +294,12 @@ public void setGestureStartAngle(float x, float y) { * @param y */ public void updateGestureRotation(float x, float y) { - mChart.setRotationAngle(mChart.getAngleForPoint(x, y) - mStartAngle); - } + /** + * Sets the deceleration-angular-velocity to 0f + */ public void stopDeceleration() { mDecelerationAngularVelocity = 0.f; } @@ -348,8 +325,8 @@ public void computeScroll() { stopDeceleration(); } - private class AngularVelocitySample - { + private class AngularVelocitySample { + public long time; public float angle; From 633722f90bcc1c6730f7cec8e2e2c22b16874a7a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 17 Jun 2015 09:14:40 +0200 Subject: [PATCH 0396/1390] Legend code cleanup, fix issue #773 --- .../mikephil/charting/components/Legend.java | 22 +++++++++---------- .../charting/renderer/BarChartRenderer.java | 2 +- .../renderer/BubbleChartRenderer.java | 3 +++ .../charting/renderer/LegendRenderer.java | 4 ++-- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index b425d53e25..9ab2e724e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -154,11 +154,19 @@ public Legend(List colors, List labels) { this.mLabels = Utils.convertStrings(labels); } - public void setColors(List colors) { + /** + * This method sets the automatically computed colors for the legend. Use setCustom(...) to set custom colors. + * @param colors + */ + public void setComputedColors(List colors) { mColors = Utils.convertIntegers(colors); } - public void setLabels(List labels) { + /** + * This method sets the automatically computed labels for the legend. Use setCustom(...) to set custom labels. + * @param labels + */ + public void setComputedLabels(List labels) { mLabels = Utils.convertStrings(labels); } @@ -229,16 +237,6 @@ public String[] getLabels() { return mLabels; } - /** - * Sets a custom array of labels for the legend. Make sure the labels array - * has the same length as the colors array. - * - * @param labels - */ - public void setLabels(String[] labels) { - this.mLabels = labels; - } - /** * Returns the legend-label at the given index. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index d95eac622e..b35ded33e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -151,7 +151,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { * * @param x the x-position * @param y the y-position - * @param barspace the space between bars + * @param barspaceHalf the space between bars * @param from * @param trans */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index c836045510..6e7035549d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -136,6 +136,9 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + final float phaseX = mAnimator.getPhaseX(); final float phaseY = mAnimator.getPhaseY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 6f66f58c91..f7bc0dee5f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -144,8 +144,8 @@ public void computeLegend(ChartData data) { Collections.addAll(labels, mLegend.getExtraLabels()); } - mLegend.setColors(colors); - mLegend.setLabels(labels); + mLegend.setComputedColors(colors); + mLegend.setComputedLabels(labels); } Typeface tf = mLegend.getTypeface(); From 9a9c9ab2a6b6f8f8083d9468e8c2403040870bc7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 17 Jun 2015 09:28:32 +0200 Subject: [PATCH 0397/1390] Address moveView issue concerning refresh (issue #765) --- MPChartExample/res/menu/realtime.xml | 4 ++ .../DynamicalAddingActivity.java | 3 - .../RealtimeLineChartActivity.java | 59 ++++++++++--------- .../charting/utils/ViewPortHandler.java | 24 +------- 4 files changed, 39 insertions(+), 51 deletions(-) diff --git a/MPChartExample/res/menu/realtime.xml b/MPChartExample/res/menu/realtime.xml index a90337fd3c..a4b2d22a78 100644 --- a/MPChartExample/res/menu/realtime.xml +++ b/MPChartExample/res/menu/realtime.xml @@ -9,4 +9,8 @@ android:id="@+id/actionClear" android:title="Clear Values"> + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index b06fb8f671..76d1f4827e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -76,9 +76,6 @@ private void addEntry() { // // // this automatically refreshes the chart (calls invalidate()) mChart.moveViewTo(data.getXValCount()-7, 50f, AxisDependency.LEFT); - - // redraw the chart - mChart.invalidate(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 76db0d1dce..6ae34a8683 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -95,30 +95,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); - -// new Thread(new Runnable() { -// -// @Override -// public void run() { -// for(int i = 0; i < 5000; i++) { -// -// runOnUiThread(new Runnable() { -// -// @Override -// public void run() { -// addEntry(); -// } -// }); -// -// try { -// Thread.sleep(35); -// } catch (InterruptedException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// } -// } -// }).start(); + } @Override @@ -140,6 +117,10 @@ public boolean onOptionsItemSelected(MenuItem item) { Toast.makeText(this, "Chart cleared!", Toast.LENGTH_SHORT).show(); break; } + case R.id.actionFeedMultiple: { + feedMultiple(); + break; + } } return true; } @@ -178,9 +159,6 @@ private void addEntry() { // this automatically refreshes the chart (calls invalidate()) // mChart.moveViewTo(data.getXValCount()-7, 55f, // AxisDependency.LEFT); - - // redraw the chart - // mChart.invalidate(); } } @@ -201,6 +179,33 @@ private LineDataSet createSet() { return set; } + private void feedMultiple() { + + new Thread(new Runnable() { + + @Override + public void run() { + for(int i = 0; i < 500; i++) { + + runOnUiThread(new Runnable() { + + @Override + public void run() { + addEntry(); + } + }); + + try { + Thread.sleep(35); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + }).start(); + } + @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index e62a3c0620..3b6e503c3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -222,8 +222,8 @@ public Matrix fitScreen() { * not possible. Makes most sense in combination with the * setScaleMinima(...) method. * - * @param pts the position to center view viewport to - * @param chart + * @param transformedPts the position to center view viewport to + * @param view * @return save */ public synchronized void centerViewPort(final float[] transformedPts, final View view) { @@ -238,25 +238,7 @@ public synchronized void centerViewPort(final float[] transformedPts, final View save.postTranslate(-x, -y); - refresh(save, view, false); - - // final View v = chart.getChartView(); - // - // v.post(new Runnable() { - // - // @Override - // public void run() { - // Matrix save = new Matrix(); - // save.set(mMatrixTouch); - // - // final float x = transformedPts[0] - offsetLeft(); - // final float y = transformedPts[1] - offsetTop(); - // - // save.postTranslate(-x, -y); - // - // refresh(save, chart, false); - // } - // }); + refresh(save, view, true); } /** From 7f79c27469dabefcae1c7d1691428f1f8963e23b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 17 Jun 2015 14:16:31 +0200 Subject: [PATCH 0398/1390] Worked on negative values for stacked-bars, not yet complete, bugs in highlighting. --- MPChartExample/AndroidManifest.xml | 1 + .../res/layout/activity_age_distribution.xml | 12 + .../BarChartActivityMultiDataset.java | 2 +- .../StackedBarActivityNegative.java | 235 ++++++++++++++++++ .../notimportant/MainActivity.java | 39 +-- .../charting/buffer/HorizontalBarBuffer.java | 30 ++- .../mikephil/charting/charts/BarChart.java | 1 - .../charting/charts/HorizontalBarChart.java | 1 - .../mikephil/charting/components/YAxis.java | 2 +- .../mikephil/charting/data/BarDataSet.java | 2 +- .../mikephil/charting/data/BarEntry.java | 42 +++- .../renderer/HorizontalBarChartRenderer.java | 27 +- .../XAxisRendererHorizontalBarChart.java | 6 +- .../YAxisRendererHorizontalBarChart.java | 17 +- 14 files changed, 365 insertions(+), 52 deletions(-) create mode 100644 MPChartExample/res/layout/activity_age_distribution.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 5059f16a1c..41a33d46c3 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -51,6 +51,7 @@ + diff --git a/MPChartExample/res/layout/activity_age_distribution.xml b/MPChartExample/res/layout/activity_age_distribution.xml new file mode 100644 index 0000000000..b023d3ab2d --- /dev/null +++ b/MPChartExample/res/layout/activity_age_distribution.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 18488aa409..428a485fd7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -223,7 +223,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); dataSets.add(set2); - dataSets.add(set3); + // dataSets.add(set3); BarData data = new BarData(xVals, dataSets); // data.setValueFormatter(new LargeValueFormatter()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java new file mode 100644 index 0000000000..b63dd497fd --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -0,0 +1,235 @@ + +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.WindowManager; +import android.widget.SeekBar; +import android.widget.SeekBar.OnSeekBarChangeListener; +import android.widget.TextView; +import android.widget.Toast; + +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.HorizontalBarChart; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.Legend.LegendPosition; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.filter.Approximator; +import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.ValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.text.DecimalFormat; +import java.util.ArrayList; + +public class StackedBarActivityNegative extends DemoBase implements + OnChartValueSelectedListener { + + private HorizontalBarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_age_distribution); + + setTitle("Age Distribution Austria"); + + mChart = (HorizontalBarChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + mChart.setDrawGridBackground(false); + mChart.setDescription(""); + + // if false values are only drawn for the stack sum, else each value is + // drawn + mChart.setDrawValuesForWholeStack(true); + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + mChart.setDrawBarShadow(false); + mChart.setDrawValueAboveBar(true); + + mChart.getAxisLeft().setEnabled(false); + mChart.getAxisRight().setStartAtZero(false); + mChart.getAxisRight().setAxisMaxValue(25f); + mChart.getAxisRight().setAxisMinValue(-25f); + mChart.getAxisRight().setLabelCount(7); + mChart.getAxisRight().setValueFormatter(new CustomFormatter()); + mChart.getAxisRight().setTextSize(9f); + + XAxis xAxis = mChart.getXAxis(); + xAxis.setPosition(XAxisPosition.BOTH_SIDED); + xAxis.setDrawGridLines(false); + xAxis.setDrawAxisLine(false); + xAxis.setTextSize(9f); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.BELOW_CHART_RIGHT); + l.setFormSize(8f); + l.setFormToTextSpace(4f); + l.setXEntrySpace(6f); + + ArrayList yValues = new ArrayList(); + yValues.add(new BarEntry(new float[]{ -10, 10 }, 0)); + yValues.add(new BarEntry(new float[]{ -12, 13 }, 1)); + yValues.add(new BarEntry(new float[]{ -15, 15 }, 2)); + yValues.add(new BarEntry(new float[]{ -17, 17 }, 3)); + yValues.add(new BarEntry(new float[]{ -19, 20 }, 4)); + yValues.add(new BarEntry(new float[]{ -19, 19 }, 5)); + yValues.add(new BarEntry(new float[]{ -16, 16 }, 6)); + yValues.add(new BarEntry(new float[]{ -13, 14 }, 7)); + yValues.add(new BarEntry(new float[]{ -10, 11 }, 8)); + yValues.add(new BarEntry(new float[]{ -5, 6 }, 9)); + yValues.add(new BarEntry(new float[]{ -1, 2 }, 10)); + + BarDataSet set = new BarDataSet(yValues, "Age Distribution"); + set.setValueFormatter(new CustomFormatter()); + set.setValueTextSize(7f); + set.setAxisDependency(YAxis.AxisDependency.RIGHT); + set.setBarSpacePercent(50f); + set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); + set.setStackLabels(new String[]{ + "Men", "Women" + }); + + String []xVals = new String[]{"0-10", "10-20", "20-30", "30-40", "40-50", "50-60", "60-70", "70-80", "80-90", "90-100", "100+"}; + + BarData data = new BarData(xVals, set); + mChart.setData(data); + mChart.invalidate(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); + mChart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleHighlightArrow: { + if (mChart.isDrawHighlightArrowEnabled()) + mChart.setDrawHighlightArrow(false); + else + mChart.setDrawHighlightArrow(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleFilter: { + + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", + Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) + .show(); + break; + } + } + return true; + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + + BarEntry entry = (BarEntry) e; + Log.i("VAL SELECTED", + "Value: " + entry.getVals()[h.getStackIndex()]); + } + + @Override + public void onNothingSelected() { + // TODO Auto-generated method stub + + } + + private class CustomFormatter implements ValueFormatter { + + private DecimalFormat mFormat; + + public CustomFormatter() { + mFormat = new DecimalFormat("###"); + } + + @Override + public String getFormattedValue(float value) { + return mFormat.format(Math.abs(value)) + "m"; + } + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 5f6f7f0d8c..c4d4599bde 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -45,6 +45,7 @@ import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivity; +import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; import java.util.ArrayList; @@ -77,6 +78,8 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem("Bubble Chart", "A simple demonstration of the bubble chart.")); objects.add(new ContentItem("Stacked Bar Chart", "A simple demonstration of a bar chart with stacked bars.")); + objects.add(new ContentItem("Stacked Bar Chart Negative", + "A simple demonstration of stacked bars with negative and positive values.")); objects.add(new ContentItem("Another Bar Chart", "Implementation of a BarChart that only shows values at the bottom.")); objects.add(new ContentItem("Multiple Lines Chart", @@ -176,18 +179,22 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 9: - i = new Intent(this, AnotherBarActivity.class); + i = new Intent(this, StackedBarActivityNegative.class); startActivity(i); break; case 10: - i = new Intent(this, MultiLineChartActivity.class); + i = new Intent(this, AnotherBarActivity.class); startActivity(i); break; case 11: - i = new Intent(this, BarChartActivityMultiDataset.class); + i = new Intent(this, MultiLineChartActivity.class); startActivity(i); break; case 12: + i = new Intent(this, BarChartActivityMultiDataset.class); + startActivity(i); + break; + case 13: // i = new Intent(this, DrawChartActivity.class); // startActivity(i); @@ -197,55 +204,55 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { b.setPositiveButton("OK", null); b.create().show(); break; - case 13: + case 14: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 14: + case 15: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 15: + case 16: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 16: + case 17: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 17: + case 18: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 18: + case 19: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 19: + case 20: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 20: + case 21: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 21: + case 22: i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; - case 22: + case 23: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; - case 23: + case 24: i = new Intent(this, PerformanceLineChart.class); startActivity(i); break; - case 24: + case 25: i = new Intent(this, BarChartActivitySinus.class); startActivity(i); break; - case 25: + case 26: i = new Intent(this, ScrollViewActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 15dde45436..c413abaa59 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -50,13 +50,22 @@ public void feed(List entries) { } else { - float all = e.getVal(); + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); // fill the stack for (int k = 0; k < vals.length; k++) { - all -= vals[k]; - y = vals[k] + all; + float value = vals[k]; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } float bottom = x - barWidth + barSpaceHalf; float top = x + barWidth - barSpaceHalf; @@ -92,13 +101,22 @@ public void feed(List entries) { } else { - float all = e.getVal(); + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); // fill the stack for (int k = 0; k < vals.length; k++) { - all -= vals[k]; - y = vals[k] + all; + float value = vals[k]; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } float bottom = x - barWidth + barSpaceHalf; float top = x + barWidth - barSpaceHalf; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 44e1d2f851..0e187b91c5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -217,7 +217,6 @@ protected Highlight getStackedHighlight(int xIndex, int dataSet, double yValue) * Returns null if the Entry could not be found in the charts data. * * @param e - * @param dataSetIndex * @return */ public RectF getBarBounds(BarEntry e) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index db3fa81b7b..5df259b9ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -83,7 +83,6 @@ protected void calculateOffsets() { float yOffset = mLegend.mTextHeightMax * 2.f; // It's possible that we do not need this offset anymore as it is available through the extraOffsets offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index b55e30001f..79df15ac6f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -321,7 +321,7 @@ public float getRequiredHeightSpace(Paint p) { p.setTextSize(mTextSize); String label = getLongestLabel(); - return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; + return (float) Utils.calcTextHeight(p, label) + Utils.convertDpToPixel(2.5f) * 2f + getYOffset(); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index e03557cef0..d9b95ddd1f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -147,7 +147,7 @@ public float getBarSpace() { } /** - * sets the space between the bars in percent of the total bar width + * sets the space between the bars in percent (0-100) of the total bar width * * @param percent */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index f4a563c5cd..6ad47477dc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import android.util.Log; + /** * Entry class for the BarChart. (especially stacked bars) * @@ -88,7 +90,7 @@ public void setVals(float[] vals) { } /** - * Returns the closest value inside the values array (for stacked barchart) + * Returns the index of the closest value inside the values array (for stacked barchart) * to the value given as a parameter. The closest value must be higher * (above) the provided value. * @@ -99,15 +101,17 @@ public int getClosestIndexAbove(float val) { if (mVals == null) return 0; - + + Log.i("TOUCHVALUE", val + ""); + int index = mVals.length - 1; float remainder = 0f; - while(index > 0 && val > mVals[index] + remainder) { + while (index > 0 && val > mVals[index] + remainder) { remainder += mVals[index]; index--; } - + return index; } @@ -142,4 +146,34 @@ private static float calcSum(float[] vals) { return sum; } + + public float getPositiveSum() { + + if(mVals == null) + return 0f; + + float sum = 0f; + + for (float f : mVals) { + if(f >= 0f) + sum += f; + } + + return sum; + } + + public float getNegativeSum() { + + if(mVals == null) + return 0f; + + float sum = 0f; + + for (float f : mVals) { + if(f <= 0f) + sum += Math.abs(f); + } + + return sum; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 81242a6438..458429da0a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -154,8 +154,7 @@ public void drawValues(Canvas c) { posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); - if (isInverted) - { + if (isInverted) { posOffset = -posOffset - valueTextWidth; negOffset = -negOffset - valueTextWidth; } @@ -195,8 +194,7 @@ public void drawValues(Canvas c) { posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); - if (isInverted) - { + if (isInverted) { posOffset = -posOffset - valueTextWidth; negOffset = -negOffset - valueTextWidth; } @@ -209,12 +207,24 @@ public void drawValues(Canvas c) { float[] transformed = new float[vals.length * 2]; int cnt = 0; - float add = e.getVal(); + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); for (int k = 0; k < transformed.length; k += 2) { - add -= vals[cnt]; - transformed[k] = (vals[cnt] + add) * mAnimator.getPhaseY(); + float value = vals[cnt]; + float y = 0f; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } + + transformed[k] = y * mAnimator.getPhaseY(); cnt++; } @@ -230,8 +240,7 @@ public void drawValues(Canvas c) { posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); - if (isInverted) - { + if (isInverted) { posOffset = -posOffset - valueTextWidth; negOffset = -negOffset - valueTextWidth; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index dc6a52ec6d..d27916e23c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -70,8 +70,10 @@ public void renderAxisLabels(Canvas c) { } else { // BOTH SIDED - drawLabels(c, mViewPortHandler.contentLeft()); - drawLabels(c, mViewPortHandler.contentRight()); + mAxisLabelPaint.setTextAlign(Align.RIGHT); + drawLabels(c, mViewPortHandler.contentLeft() - xoffset); + mAxisLabelPaint.setTextAlign(Align.LEFT); + drawLabels(c, mViewPortHandler.contentRight() + xoffset); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 98c36276e8..79e3aa7faa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -81,7 +81,8 @@ public void renderAxisLabels(Canvas c) { mAxisLabelPaint.setColor(mYAxis.getTextColor()); mAxisLabelPaint.setTextAlign(Align.CENTER); - float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") + mYAxis.getYOffset(); + float baseYOffset = Utils.convertDpToPixel(2.5f); + float textHeight = Utils.calcTextHeight(mAxisLabelPaint, "Q"); AxisDependency dependency = mYAxis.getAxisDependency(); YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); @@ -91,25 +92,21 @@ public void renderAxisLabels(Canvas c) { if (dependency == AxisDependency.LEFT) { if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - yoffset = Utils.convertDpToPixel(3f); - yPos = mViewPortHandler.contentTop(); + yPos = mViewPortHandler.contentTop() - baseYOffset; } else { - yoffset = yoffset * -1f; - yPos = mViewPortHandler.contentTop(); + yPos = mViewPortHandler.contentTop() - baseYOffset; } } else { if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - yoffset = yoffset * -1f; - yPos = mViewPortHandler.contentBottom(); + yPos = mViewPortHandler.contentBottom() + textHeight + baseYOffset; } else { - yoffset = Utils.convertDpToPixel(4f); - yPos = mViewPortHandler.contentBottom(); + yPos = mViewPortHandler.contentBottom() + textHeight + baseYOffset; } } - drawYLabels(c, yPos, positions, yoffset); + drawYLabels(c, yPos, positions, mYAxis.getYOffset()); } @Override From 8cf93369350bc55b54620f872cdbb1d1fd3978d8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 17 Jun 2015 17:33:26 +0200 Subject: [PATCH 0399/1390] Added comparator for comparing entries by their x-index. --- .../charting/utils/EntryXIndexComparator.java | 16 ++++++++++++++++ .../github/mikephil/charting/utils/Utils.java | 1 + 2 files changed, 17 insertions(+) create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java b/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java new file mode 100644 index 0000000000..f83623fecb --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/EntryXIndexComparator.java @@ -0,0 +1,16 @@ +package com.github.mikephil.charting.utils; + +import com.github.mikephil.charting.data.Entry; + +import java.util.Comparator; + +/** + * Comparator for comparing Entry-objects by their x-index. + * Created by philipp on 17/06/15. + */ +public class EntryXIndexComparator implements Comparator { + @Override + public int compare(Entry entry1, Entry entry2) { + return entry1.getXIndex() - entry2.getXIndex(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index f9237a3e61..12248f3319 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -16,6 +16,7 @@ import android.view.ViewConfiguration; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.Entry; import java.text.DecimalFormat; import java.util.List; From 6e456da0429a9995035007a02c256bf7cd05c1a7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 17 Jun 2015 20:59:40 +0200 Subject: [PATCH 0400/1390] Exclude un-highlightable datasets from being highlighted (issue #777). --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 41405aa06a..b5a64233ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1108,6 +1108,10 @@ public List getYValsAtIndex(int xIndex) { DataSet dataSet = mData.getDataSetByIndex(i); + // dont include datasets that cannot be highlighted + if(!dataSet.isHighlightEnabled()) + continue; + // extract all y-values from all DataSets at the given x-index float yVal = dataSet.getYValForXIndex(xIndex); pts[1] = yVal; From 10301a735903d479b833893b4f3c94ea45a3074b Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 19 Jun 2015 16:42:52 +0300 Subject: [PATCH 0401/1390] Fix a crash where dataSetIndex is -1 --- .../listener/PieRadarChartTouchListener.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 113172931e..4c213f85b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -176,16 +176,21 @@ public boolean onSingleTapUp(MotionEvent e) { / ((RadarChart) mChart).getFactor(), null); } - Highlight h = new Highlight(index, dataSetIndex); - - if (h.equalTo(mLastHighlighted)) { - - mChart.highlightTouch(null); + if (dataSetIndex < 0) { + mChart.highlightValues(null); mLastHighlighted = null; } else { + Highlight h = new Highlight(index, dataSetIndex); + + if (h.equalTo(mLastHighlighted)) { - mChart.highlightTouch(h); - mLastHighlighted = h; + mChart.highlightTouch(null); + mLastHighlighted = null; + } else { + + mChart.highlightTouch(h); + mLastHighlighted = h; + } } } } From b6ab5f2475fda9b49addc12a84e052702f4e28e3 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 19 Jun 2015 16:38:31 +0300 Subject: [PATCH 0402/1390] Allow NaN values in Radar chart (Skip points) --- .../com/github/mikephil/charting/data/DataSet.java | 8 ++++---- .../charting/renderer/RadarChartRenderer.java | 13 +++++++++++-- .../charting/renderer/YAxisRendererRadarChart.java | 4 ++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 75ddc31b03..61bd52c9e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -122,14 +122,14 @@ protected void calcMinMax(int start, int end) { mLastStart = start; mLastEnd = endValue; - mYMin = mYVals.get(start).getVal(); - mYMax = mYVals.get(start).getVal(); + mYMin = Float.MAX_VALUE; + mYMax = Float.MIN_VALUE; - for (int i = start + 1; i <= endValue; i++) { + for (int i = start; i <= endValue; i++) { Entry e = mYVals.get(i); - if (e != null) { + if (e != null && !Float.isNaN(e.getVal())) { if (e.getVal() < mYMin) mYMin = e.getVal(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 268f2acd13..c42a2ef2bc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -75,6 +75,8 @@ protected void drawDataSet(Canvas c, RadarDataSet dataSet) { Path surface = new Path(); + boolean hasMovedToPoint = false; + for (int j = 0; j < entries.size(); j++) { mRenderPaint.setColor(dataSet.getColor(j)); @@ -84,9 +86,13 @@ protected void drawDataSet(Canvas c, RadarDataSet dataSet) { PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); - if (j == 0) + if (Float.isNaN(p.x)) + continue; + + if (!hasMovedToPoint) { surface.moveTo(p.x, p.y); - else + hasMovedToPoint = true; + } else surface.lineTo(p.x, p.y); } @@ -225,6 +231,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int j = set.getEntryPosition(e); float y = (e.getVal() - mChart.getYChartMin()); + if (Float.isNaN(y)) + continue; + PointF p = Utils.getPosition(center, y * factor, sliceangle * j + mChart.getRotationAngle()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 0c7a46c307..bae51e0ebe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -63,6 +63,10 @@ protected void computeAxisValues(float min, float max) { } else { double first = Math.ceil(yMin / interval) * interval; + + if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + first = 0.0; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); double f; From 0c81966d677139bc3e44f4766db6921c964c3cc8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 19 Jun 2015 17:36:47 +0200 Subject: [PATCH 0403/1390] Did some refactoring concerning SelInfo. --- .../mikephil/charting/charts/BarLineChartBase.java | 13 ++++++------- .../mikephil/charting/charts/PieRadarChartBase.java | 10 +++++----- .../listener/PieRadarChartTouchListener.java | 7 ++----- .../utils/{SelInfo.java => SelectionDetail.java} | 11 +++++------ .../com/github/mikephil/charting/utils/Utils.java | 9 ++++----- 5 files changed, 22 insertions(+), 28 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/utils/{SelInfo.java => SelectionDetail.java} (72%) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b5a64233ab..a7945df3ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -29,14 +29,13 @@ import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; -import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; import com.github.mikephil.charting.utils.FillFormatter; import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.PointD; -import com.github.mikephil.charting.utils.SelInfo; +import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -1070,7 +1069,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { xIndex = (int) base + 1; } - List valsAtIndex = getYValsAtIndex(xIndex); + List valsAtIndex = getSelectionDetailsAtIndex(xIndex); float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); @@ -1091,16 +1090,16 @@ public Highlight getHighlightByTouchPoint(float x, float y) { } /** - * Returns an array of SelInfo objects for the given x-index. The SelInfo + * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail * objects give information about the value at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * * @return */ - public List getYValsAtIndex(int xIndex) { + protected List getSelectionDetailsAtIndex(int xIndex) { - List vals = new ArrayList(); + List vals = new ArrayList(); float[] pts = new float[2]; @@ -1119,7 +1118,7 @@ public List getYValsAtIndex(int xIndex) { getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); if (!Float.isNaN(pts[1])) { - vals.add(new SelInfo(pts[1], i, dataSet)); + vals.add(new SelectionDetail(pts[1], i, dataSet)); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 8b5f7281b8..ab0a806437 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -19,7 +19,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; -import com.github.mikephil.charting.utils.SelInfo; +import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -410,16 +410,16 @@ public float getYChartMin() { } /** - * Returns an array of SelInfo objects for the given x-index. The SelInfo + * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail * objects give information about the value at the selected index and the * DataSet it belongs to. INFORMATION: This method does calculations at * runtime. Do not over-use in performance critical situations. * * @return */ - public List getYValsAtIndex(int xIndex) { + public List getYValsAtIndex(int xIndex) { - List vals = new ArrayList(); + List vals = new ArrayList(); for (int i = 0; i < mData.getDataSetCount(); i++) { @@ -429,7 +429,7 @@ public List getYValsAtIndex(int xIndex) { float yVal = dataSet.getYValForXIndex(xIndex); if (!Float.isNaN(yVal)) { - vals.add(new SelInfo(yVal, i, dataSet)); + vals.add(new SelectionDetail(yVal, i, dataSet)); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 4c213f85b5..aff98c50c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -3,18 +3,15 @@ import android.annotation.SuppressLint; import android.graphics.PointF; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.View; -import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.utils.Highlight; -import com.github.mikephil.charting.utils.SelInfo; +import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -163,7 +160,7 @@ public boolean onSingleTapUp(MotionEvent e) { } else { - List valsAtIndex = mChart.getYValsAtIndex(index); + List valsAtIndex = mChart.getYValsAtIndex(index); int dataSetIndex = 0; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java similarity index 72% rename from MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java rename to MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java index 4c3749a9a1..20e9feb3f2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelInfo.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java @@ -1,25 +1,24 @@ - package com.github.mikephil.charting.utils; import com.github.mikephil.charting.data.DataSet; /** * Class that encapsulates information of a value that has been - * selected/highlighted and its DataSet index. The SelInfo objects give + * selected/highlighted and its DataSet index. The SelectionDetail objects give * information about the value at the selected index and the DataSet it belongs * to. Needed only for highlighting onTouch(). - * + * * @author Philipp Jahoda */ -public class SelInfo { +public class SelectionDetail { public float val; public int dataSetIndex; public DataSet dataSet; - public SelInfo(float val, int dataSetIndex, DataSet set) { + public SelectionDetail(float val, int dataSetIndex, DataSet set) { this.val = val; this.dataSetIndex = dataSetIndex; this.dataSet = set; } -} +} \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 12248f3319..695fc58ca6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -16,7 +16,6 @@ import android.view.ViewConfiguration; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.Entry; import java.text.DecimalFormat; import java.util.List; @@ -430,7 +429,7 @@ public static double nextUp(double d) { * @param valsAtIndex all the values at a specific index * @return */ - public static int getClosestDataSetIndex(List valsAtIndex, float val, + public static int getClosestDataSetIndex(List valsAtIndex, float val, AxisDependency axis) { int index = -1; @@ -438,7 +437,7 @@ public static int getClosestDataSetIndex(List valsAtIndex, float val, for (int i = 0; i < valsAtIndex.size(); i++) { - SelInfo sel = valsAtIndex.get(i); + SelectionDetail sel = valsAtIndex.get(i); if (axis == null || sel.dataSet.getAxisDependency() == axis) { @@ -464,14 +463,14 @@ public static int getClosestDataSetIndex(List valsAtIndex, float val, * @param axis * @return */ - public static float getMinimumDistance(List valsAtIndex, float val, + public static float getMinimumDistance(List valsAtIndex, float val, AxisDependency axis) { float distance = Float.MAX_VALUE; for (int i = 0; i < valsAtIndex.size(); i++) { - SelInfo sel = valsAtIndex.get(i); + SelectionDetail sel = valsAtIndex.get(i); if (sel.dataSet.getAxisDependency() == axis) { From 43e9c26ef564727a5224b1f03254da192278a2db Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 22 Jun 2015 16:12:23 +0200 Subject: [PATCH 0404/1390] Refactored some stuff. --- .../com/github/mikephil/charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/listener/PieRadarChartTouchListener.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index ab0a806437..b8d028de74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -417,7 +417,7 @@ public float getYChartMin() { * * @return */ - public List getYValsAtIndex(int xIndex) { + public List getSelectionDetailsAtIndex(int xIndex) { List vals = new ArrayList(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index aff98c50c7..af62892344 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -160,7 +160,7 @@ public boolean onSingleTapUp(MotionEvent e) { } else { - List valsAtIndex = mChart.getYValsAtIndex(index); + List valsAtIndex = mChart.getSelectionDetailsAtIndex(index); int dataSetIndex = 0; From 4e8aaf4561d4e844345b301f11eaf206af14a20a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 24 Jun 2015 10:54:19 +0300 Subject: [PATCH 0405/1390] Refactored cnt into idx for clarification --- .../charting/renderer/HorizontalBarChartRenderer.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 458429da0a..5229b9c20c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -206,14 +206,13 @@ public void drawValues(Canvas c) { } else { float[] transformed = new float[vals.length * 2]; - int cnt = 0; float allPos = e.getPositiveSum(); float allNeg = e.getNegativeSum(); - for (int k = 0; k < transformed.length; k += 2) { + for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { - float value = vals[cnt]; - float y = 0f; + float value = vals[idx]; + float y; if(value >= 0f) { @@ -225,7 +224,6 @@ public void drawValues(Canvas c) { } transformed[k] = y * mAnimator.getPhaseY(); - cnt++; } trans.pointValuesToPixel(transformed); From 15b0578aa1b95df9da14af43757dd7b79da4f59d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 24 Jun 2015 10:55:40 +0300 Subject: [PATCH 0406/1390] Support for negative values in stacked vertical bar chart --- .../mikephil/charting/buffer/BarBuffer.java | 34 ++++++++++++++----- .../charting/renderer/BarChartRenderer.java | 22 ++++++++---- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index da20fce995..e0f40273b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -79,14 +79,23 @@ public void feed(List entries) { addBar(left, top, right, bottom); } else { - - float all = e.getVal(); + + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); // fill the stack for (int k = 0; k < vals.length; k++) { - all -= vals[k]; - y = vals[k] + all; + float value = vals[k]; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } float left = x - barWidth + barSpaceHalf; float right = x + barWidth - barSpaceHalf; @@ -121,14 +130,23 @@ public void feed(List entries) { addBar(left, top, right, bottom); } else { - - float all = e.getVal(); + + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); // fill the stack for (int k = 0; k < vals.length; k++) { - all -= vals[k]; - y = vals[k] + all; + float value = vals[k]; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } float left = x - barWidth + barSpaceHalf; float right = x + barWidth - barSpaceHalf; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index b35ded33e0..5933cf3786 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -259,14 +259,24 @@ public void drawValues(Canvas c) { } else { float[] transformed = new float[vals.length * 2]; - int cnt = 0; - float add = e.getVal(); + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); - for (int k = 0; k < transformed.length; k += 2) { + for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { + + float value = vals[idx]; + float y; + + if(value >= 0f) { + + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; + } - add -= vals[cnt]; - transformed[k + 1] = (vals[cnt] + add) * mAnimator.getPhaseY(); - cnt++; + transformed[k + 1] = y * mAnimator.getPhaseY(); } trans.pointValuesToPixel(transformed); From a9e335079da0d2ea11fc2cbd67b446f4d78e3462 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 24 Jun 2015 10:32:05 +0200 Subject: [PATCH 0407/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9fc462b47..941aa2b609 100644 --- a/README.md +++ b/README.md @@ -33,10 +33,10 @@ Donations +[]() - Follow me on **Twitter**: [**PhilippJahoda**](https://twitter.com/PhilippJahoda) +Follow me on **Twitter**: [**PhilippJahoda**](https://twitter.com/PhilippJahoda) - Download my [**iOS apps**](https://itunes.apple.com/us/artist/philipp-jahoda/id951309215). Demo ----- From 932405a2ef6f062a57bcd6fbae1c526b2bc5e963 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 24 Jun 2015 11:49:58 +0300 Subject: [PATCH 0408/1390] Removed duplicate code Testing for `mInverted` in the main `if` or inner `if` do not have a meaning performance-wise, as in both cases it's just one boolean check. --- .../mikephil/charting/buffer/BarBuffer.java | 124 ++++++------------ .../charting/buffer/HorizontalBarBuffer.java | 116 ++++++---------- 2 files changed, 78 insertions(+), 162 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index e0f40273b6..a24a1120c8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -60,67 +60,58 @@ public void feed(List entries) { + mGroupSpace * i + groupSpaceHalf; float y = e.getVal(); float [] vals = e.getVals(); - - if(mInverted) { // inverted axis, here, I chose performance over readability - if(!mContainsStacks || vals == null) { - - float left = x - barWidth + barSpaceHalf; - float right = x + barWidth - barSpaceHalf; - float bottom = y >= 0 ? y : 0; - float top = y <= 0 ? y : 0; - - // multiply the height of the rect with the phase - if (top > 0) - top *= phaseY; - else - bottom *= phaseY; - - addBar(left, top, right, bottom); - + if (!mContainsStacks || vals == null) { + + float left = x - barWidth + barSpaceHalf; + float right = x + barWidth - barSpaceHalf; + float bottom, top; + if (mInverted) { + bottom = y >= 0 ? y : 0; + top = y <= 0 ? y : 0; } else { + top = y >= 0 ? y : 0; + bottom = y <= 0 ? y : 0; + } - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + // multiply the height of the rect with the phase + if (top > 0) + top *= phaseY; + else + bottom *= phaseY; - // fill the stack - for (int k = 0; k < vals.length; k++) { + addBar(left, top, right, bottom); - float value = vals[k]; + } else { - if(value >= 0f) { + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); - allPos -= value; - y = value + allPos; - } else { - allNeg -= Math.abs(value); - y = value + allNeg; - } + // fill the stack + for (int k = 0; k < vals.length; k++) { - float left = x - barWidth + barSpaceHalf; - float right = x + barWidth - barSpaceHalf; - float bottom = y >= 0 ? y : 0; - float top = y <= 0 ? y : 0; + float value = vals[k]; - // multiply the height of the rect with the phase - if (top > 0) - top *= phaseY; - else - bottom *= phaseY; + if(value >= 0f) { - addBar(left, top, right, bottom); + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; } - } - - } else { // non inverted axis - - if(!mContainsStacks || vals == null) { - + float left = x - barWidth + barSpaceHalf; float right = x + barWidth - barSpaceHalf; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - + float bottom, top; + if (mInverted) { + bottom = y >= 0 ? y : 0; + top = y <= 0 ? y : 0; + } else { + top = y >= 0 ? y : 0; + bottom = y <= 0 ? y : 0; + } + // multiply the height of the rect with the phase if (top > 0) top *= phaseY; @@ -128,41 +119,8 @@ public void feed(List entries) { bottom *= phaseY; addBar(left, top, right, bottom); - - } else { - - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); - - // fill the stack - for (int k = 0; k < vals.length; k++) { - - float value = vals[k]; - - if(value >= 0f) { - - allPos -= value; - y = value + allPos; - } else { - allNeg -= Math.abs(value); - y = value + allNeg; - } - - float left = x - barWidth + barSpaceHalf; - float right = x + barWidth - barSpaceHalf; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - - // multiply the height of the rect with the phase - if (top > 0) - top *= phaseY; - else - bottom *= phaseY; - - addBar(left, top, right, bottom); - } - } - } + } + } } reset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index c413abaa59..d405466f69 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -31,65 +31,56 @@ public void feed(List entries) { float y = e.getVal(); float[] vals = e.getVals(); - if(mInverted) { // inverted axis - - if (!mContainsStacks || vals == null) { - - float bottom = x - barWidth + barSpaceHalf; - float top = x + barWidth - barSpaceHalf; - float left = y >= 0 ? y : 0; - float right = y <= 0 ? y : 0; - - // multiply the height of the rect with the phase - if (right > 0) - right *= phaseY; - else - left *= phaseY; - - addBar(left, top, right, bottom); - + if (!mContainsStacks || vals == null) { + + float bottom = x - barWidth + barSpaceHalf; + float top = x + barWidth - barSpaceHalf; + float left, right; + if (mInverted) { + left = y >= 0 ? y : 0; + right = y <= 0 ? y : 0; } else { + right = y >= 0 ? y : 0; + left = y <= 0 ? y : 0; + } - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + // multiply the height of the rect with the phase + if (right > 0) + right *= phaseY; + else + left *= phaseY; - // fill the stack - for (int k = 0; k < vals.length; k++) { + addBar(left, top, right, bottom); - float value = vals[k]; + } else { - if(value >= 0f) { + float allPos = e.getPositiveSum(); + float allNeg = e.getNegativeSum(); - allPos -= value; - y = value + allPos; - } else { - allNeg -= Math.abs(value); - y = value + allNeg; - } + // fill the stack + for (int k = 0; k < vals.length; k++) { - float bottom = x - barWidth + barSpaceHalf; - float top = x + barWidth - barSpaceHalf; - float left = y >= 0 ? y : 0; - float right = y <= 0 ? y : 0; + float value = vals[k]; - // multiply the height of the rect with the phase - if (right > 0) - right *= phaseY; - else - left *= phaseY; + if(value >= 0f) { - addBar(left, top, right, bottom); + allPos -= value; + y = value + allPos; + } else { + allNeg -= Math.abs(value); + y = value + allNeg; } - } - - } else { // not inverted - - if (!mContainsStacks || vals == null) { float bottom = x - barWidth + barSpaceHalf; float top = x + barWidth - barSpaceHalf; - float right = y >= 0 ? y : 0; - float left = y <= 0 ? y : 0; + float left, right; + if (mInverted) { + left = y >= 0 ? y : 0; + right = y <= 0 ? y : 0; + } else { + right = y >= 0 ? y : 0; + left = y <= 0 ? y : 0; + } // multiply the height of the rect with the phase if (right > 0) @@ -98,39 +89,6 @@ public void feed(List entries) { left *= phaseY; addBar(left, top, right, bottom); - - } else { - - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); - - // fill the stack - for (int k = 0; k < vals.length; k++) { - - float value = vals[k]; - - if(value >= 0f) { - - allPos -= value; - y = value + allPos; - } else { - allNeg -= Math.abs(value); - y = value + allNeg; - } - - float bottom = x - barWidth + barSpaceHalf; - float top = x + barWidth - barSpaceHalf; - float right = y >= 0 ? y : 0; - float left = y <= 0 ? y : 0; - - // multiply the height of the rect with the phase - if (right > 0) - right *= phaseY; - else - left *= phaseY; - - addBar(left, top, right, bottom); - } } } } From 9a4c3287d1940cb1ea0e15baecb3d8cfe6c514aa Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 29 Jun 2015 21:51:33 +0300 Subject: [PATCH 0409/1390] Fixed an issue where highlights disappear on multi-datasets They disappeared because of NaN values introduces in the previous iteration, when the previous dataset does not contain a yValue for that specific index. (And a little refactoring to make this thing consistent across all appearances) --- .../github/mikephil/charting/charts/BarLineChartBase.java | 5 ++++- .../mikephil/charting/charts/PieRadarChartBase.java | 8 ++++---- .../mikephil/charting/renderer/LineChartRenderer.java | 6 +++--- .../mikephil/charting/renderer/ScatterChartRenderer.java | 6 +++--- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a7945df3ca..be30ba24b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1112,7 +1112,10 @@ protected List getSelectionDetailsAtIndex(int xIndex) { continue; // extract all y-values from all DataSets at the given x-index - float yVal = dataSet.getYValForXIndex(xIndex); + final float yVal = dataSet.getYValForXIndex(xIndex); + if (yVal == Float.NaN) + continue; + pts[1] = yVal; getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index b8d028de74..48b5bf075e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -426,11 +426,11 @@ public List getSelectionDetailsAtIndex(int xIndex) { DataSet dataSet = mData.getDataSetByIndex(i); // extract all y-values from all DataSets at the given x-index - float yVal = dataSet.getYValForXIndex(xIndex); + final float yVal = dataSet.getYValForXIndex(xIndex); + if (yVal == Float.NaN) + continue; - if (!Float.isNaN(yVal)) { - vals.add(new SelectionDetail(yVal, i, dataSet)); - } + vals.add(new SelectionDetail(yVal, i, dataSet)); } return vals; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 3b1dee5f1e..116a5dfcfc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -546,11 +546,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - float yValue = set.getYValForXIndex(xIndex); - if (yValue == Float.NaN) + final float yVal = set.getYValForXIndex(xIndex); + if (yVal == Float.NaN) continue; - float y = yValue * mAnimator.getPhaseY(); // get + float y = yVal * mAnimator.getPhaseY(); // get // the // y-position diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index ec1c68fd23..4d27bae491 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -266,11 +266,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; - float yValue = set.getYValForXIndex(xIndex); - if (yValue == Float.NaN) + final float yVal = set.getYValForXIndex(xIndex); + if (yVal == Float.NaN) continue; - float y = yValue * mAnimator.getPhaseY(); // get + float y = yVal * mAnimator.getPhaseY(); // get // the // y-position From 3a9ad3db325183d273f57bd151b5d30090140b67 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 29 Jun 2015 22:52:16 +0300 Subject: [PATCH 0410/1390] Fixed a crash after matrix transformation when only one bar is visible Float.MIN_VALUE is not the minimum... -Float.MIN_VALUE is! And of course we need to also account for a case where we are looping over zero elements. --- .../src/com/github/mikephil/charting/data/ChartData.java | 7 ++++++- .../src/com/github/mikephil/charting/data/DataSet.java | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 07ef04a1aa..9d0f0cb2a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -203,7 +203,7 @@ public void calcMinMax(int start, int end) { mLastEnd = end; mYMin = Float.MAX_VALUE; - mYMax = Float.MIN_VALUE; + mYMax = -Float.MIN_VALUE; for (int i = 0; i < mDataSets.size(); i++) { @@ -216,6 +216,11 @@ public void calcMinMax(int start, int end) { mYMax = mDataSets.get(i).getYMax(); } + if (mYMin == Float.MAX_VALUE) { + mYMin = 0.f; + mYMax = 0.f; + } + // left axis T firstLeft = getFirstLeft(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 61bd52c9e7..eb8ff7c405 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -123,7 +123,7 @@ protected void calcMinMax(int start, int end) { mLastEnd = endValue; mYMin = Float.MAX_VALUE; - mYMax = Float.MIN_VALUE; + mYMax = -Float.MIN_VALUE; for (int i = start; i <= endValue; i++) { @@ -138,6 +138,11 @@ protected void calcMinMax(int start, int end) { mYMax = e.getVal(); } } + + if (mYMin == Float.MAX_VALUE) { + mYMin = 0.f; + mYMax = 0.f; + } } /** From 950d6a2354b7fcf643b586e856ac0218af21f96b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 1 Jul 2015 18:28:15 +0200 Subject: [PATCH 0411/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index a35c16c629..4a97a59e6d 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -35,3 +35,6 @@ https://play.google.com/store/apps/details?id=com.hconnect.hfiles&hl=en Яндекс Метрика для Android https://play.google.com/store/apps/details?id=ru.vdmodule.androidmetrix + +Poker Manager +https://play.google.com/store/apps/details?id=com.pokermanagerpro From 44e12a4e5ee520285d9ad4f5186ac53a9616ed7c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 5 Jul 2015 16:35:53 +0200 Subject: [PATCH 0412/1390] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 941aa2b609..30f3aa2a24 100644 --- a/README.md +++ b/README.md @@ -175,12 +175,14 @@ dependencies { Proguard ======= -In case you are using Proguard, you will need to whitelist MPAndroidChart, which requires to add the following line to your Proguard configuration file. +In case you are using Proguard, you will need to **whitelist MPAndroidChart**, which requires to add the following line to your Proguard configuration file. ``` -keep class com.github.mikephil.charting.** { *; } ``` +If you don't do this, animations might not work. + Documentation ======= For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). From 91103911c0ba7db73239a746c39af1be0cb4d4ca Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 16:33:41 +0300 Subject: [PATCH 0413/1390] Feature for making candle shadow color same as inc/dec --- MPChartExample/res/menu/candle.xml | 4 ++ .../CandleStickChartActivity.java | 9 +++ .../mikephil/charting/data/CandleDataSet.java | 21 ++++++ .../renderer/CandleStickChartRenderer.java | 71 +++++++++++++------ 4 files changed, 82 insertions(+), 23 deletions(-) diff --git a/MPChartExample/res/menu/candle.xml b/MPChartExample/res/menu/candle.xml index d858aeda26..bb947aa221 100644 --- a/MPChartExample/res/menu/candle.xml +++ b/MPChartExample/res/menu/candle.xml @@ -37,5 +37,9 @@ android:id="@+id/actionToggleAutoScaleMinMax" android:title="Toggle auto scale min/max"> + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 7fad58c0ec..d9989ab0f7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -122,6 +122,15 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } + case R.id.actionToggleMakeShadowSameColorAsCandle: { + for (CandleDataSet set : mChart.getData().getDataSets()) + { + set.setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); + } + + mChart.invalidate(); + break; + } case R.id.actionToggleStartzero: { mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 1fdda517a7..cc78e8d857 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -22,6 +22,9 @@ public class CandleDataSet extends BarLineScatterCandleDataSet { /** the space between the candle entries, default 0.1f (10%) */ private float mBodySpace = 0.1f; + /** use candle color for the shadow */ + private boolean mShadowColorSameAsCandle = false; + /** paint style when open <= close */ protected Paint.Style mIncreasingPaintStyle = Paint.Style.FILL; @@ -246,4 +249,22 @@ public int getShadowColor() { public void setShadowColor(int shadowColor) { this.mShadowColor = shadowColor; } + + /** + * Is the shadow color same as the candle color? + * + * @return + */ + public boolean getShadowColorSameAsCandle() { + return mShadowColorSameAsCandle; + } + + /** + * Sets shadow color to be the same color as the candle color + * + * @param shadowColorSameAsCandle + */ + public void setShadowColorSameAsCandle(boolean shadowColorSameAsCandle) { + this.mShadowColorSameAsCandle = shadowColorSameAsCandle; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index aeef3b1b72..9912ff5385 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -79,6 +79,15 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { int range = (maxx - minx) * 4; int to = (int)Math.ceil((maxx - minx) * phaseX + minx); + CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; + bodyBuffer.setBodySpace(dataSet.getBodySpace()); + bodyBuffer.setPhases(phaseX, phaseY); + bodyBuffer.limitFrom(minx); + bodyBuffer.limitTo(maxx); + bodyBuffer.feed(entries); + + trans.pointValuesToPixel(bodyBuffer.buffer); + CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex]; shadowBuffer.setPhases(phaseX, phaseY); shadowBuffer.limitFrom(minx); @@ -87,29 +96,8 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { trans.pointValuesToPixel(shadowBuffer.buffer); - mRenderPaint.setStyle(Paint.Style.STROKE); - - // If not set, use default functionality for backward compatibility - if (dataSet.getShadowColor() == ColorTemplate.COLOR_NONE) { - mRenderPaint.setColor(dataSet.getColor()); - } else { - mRenderPaint.setColor(dataSet.getShadowColor()); - } - mRenderPaint.setStrokeWidth(dataSet.getShadowWidth()); - // draw the shadow - c.drawLines(shadowBuffer.buffer, 0, range, mRenderPaint); - - CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; - bodyBuffer.setBodySpace(dataSet.getBodySpace()); - bodyBuffer.setPhases(phaseX, phaseY); - bodyBuffer.limitFrom(minx); - bodyBuffer.limitTo(maxx); - bodyBuffer.feed(entries); - - trans.pointValuesToPixel(bodyBuffer.buffer); - // draw the body for (int j = 0; j < range; j += 4) { @@ -119,6 +107,44 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { if (!fitsBounds(e.getXIndex(), mMinX, to)) continue; + if (dataSet.getShadowColorSameAsCandle()) { + + if (e.getOpen() > e.getClose()) + mRenderPaint.setColor( + dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getDecreasingColor() + ); + + else if (e.getOpen() < e.getClose()) + mRenderPaint.setColor( + dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getIncreasingColor() + ); + + else + mRenderPaint.setColor( + dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getShadowColor() + ); + + } else { + mRenderPaint.setColor( + dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ? + dataSet.getColor(j) : + dataSet.getShadowColor() + ); + } + + mRenderPaint.setStyle(Paint.Style.STROKE); + + // draw the shadow + c.drawLine(shadowBuffer.buffer[j], shadowBuffer.buffer[j + 1], + shadowBuffer.buffer[j + 2], shadowBuffer.buffer[j + 3], + mRenderPaint); + float leftBody = bodyBuffer.buffer[j]; float open = bodyBuffer.buffer[j + 1]; float rightBody = bodyBuffer.buffer[j + 2]; @@ -150,8 +176,7 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { c.drawRect(leftBody, open, rightBody, close, mRenderPaint); } else { // equal values - mRenderPaint.setColor(Color.BLACK); - mRenderPaint.setStyle(Paint.Style.STROKE); + mRenderPaint.setColor(dataSet.getShadowColor()); c.drawLine(leftBody, open, rightBody, close, mRenderPaint); } } From 4d2495c902985ee42e3a103c87f09ca511d6cb7e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 16:05:21 +0300 Subject: [PATCH 0414/1390] Fixed a case where removeEntry(xIndex) removes the wrong entry --- .../src/com/github/mikephil/charting/data/ChartData.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9d0f0cb2a2..d725fafca2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -728,6 +728,9 @@ public boolean removeEntry(int xIndex, int dataSetIndex) { T dataSet = mDataSets.get(dataSetIndex); Entry e = dataSet.getEntryForXIndex(xIndex); + if (e == null || e.getXIndex() != xIndex) + return false; + return removeEntry(e, dataSetIndex); } From d54efba3f12ef8aab347996e9c2ce9c45d64e83f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 16:46:58 +0300 Subject: [PATCH 0415/1390] Fixed possible case of incorrect x/ymax after addEntry --- .../mikephil/charting/data/ChartData.java | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index d725fafca2..e004b08e13 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -636,10 +636,10 @@ public boolean removeDataSet(int index) { } /** - * Adds an Entry to the DataSet at the specified index. Entries are added to - * the end of the list. + * Adds an Entry to the DataSet at the specified index. + * Entries are added to the end of the list. * - * @param entry + * @param e * @param dataSetIndex */ public void addEntry(Entry e, int dataSetIndex) { @@ -647,18 +647,26 @@ public void addEntry(Entry e, int dataSetIndex) { if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { float val = e.getVal(); + T set = mDataSets.get(dataSetIndex); - mYValCount += 1; - mYValueSum += val; - - if (mYMax < val) - mYMax = val; - if (mYMin > val) + if (mYValCount == 0) { mYMin = val; + mYMax = val; - T set = mDataSets.get(dataSetIndex); + if (set.getAxisDependency() == AxisDependency.LEFT) { - if (set != null) { + mLeftAxisMax = e.getVal(); + mLeftAxisMin = e.getVal(); + } else { + mRightAxisMax = e.getVal(); + mRightAxisMin = e.getVal(); + } + } else { + + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; if (set.getAxisDependency() == AxisDependency.LEFT) { @@ -672,12 +680,15 @@ public void addEntry(Entry e, int dataSetIndex) { if (mRightAxisMin > e.getVal()) mRightAxisMin = e.getVal(); } + } - handleEmptyAxis(getFirstLeft(), getFirstRight()); + mYValCount += 1; + mYValueSum += val; - // add the entry to the dataset - set.addEntry(e); - } + handleEmptyAxis(getFirstLeft(), getFirstRight()); + + // add the entry to the dataset + set.addEntry(e); } else { Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); } From b5fb9e9761e94593d013d79948d87d4eb451ef91 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 17:00:21 +0300 Subject: [PATCH 0416/1390] addEntryOrdered to automatically place the entry in the correct index --- .../mikephil/charting/data/DataSet.java | 82 +++++++++++++++++-- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index eb8ff7c405..1d08ad783d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -189,19 +189,37 @@ public float getYValForXIndex(int xIndex) { /** * Returns the first Entry object found at the given xIndex with binary - * search. If the no Entry at the specifed x-index is found, this method - * returns the Entry at the closest x-index. Returns null if no Entry object + * search. If the no Entry at the specified x-index is found, this method + * returns the index at the closest x-index. Returns null if no Entry object * at that index. INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param xIndex + * @param x * @return */ public T getEntryForXIndex(int x) { + int index = getEntryIndex(x); + if (index > -1) + return mYVals.get(index); + return null; + } + + /** + * Returns the first Entry index found at the given xIndex with binary + * search. If the no Entry at the specified x-index is found, this method + * returns the index at the closest x-index. Returns -1 if no Entry object + * at that index. INFORMATION: This method does calculations at runtime. Do + * not over-use in performance critical situations. + * + * @param x + * @return + */ + public int getEntryIndex(int x) { + int low = 0; int high = mYVals.size() - 1; - T closest = null; + int closest = -1; while (low <= high) { int m = (high + low) / 2; @@ -210,7 +228,7 @@ public T getEntryForXIndex(int x) { while (m > 0 && mYVals.get(m - 1).getXIndex() == x) m--; - return mYVals.get(m); + return m; } if (x > mYVals.get(m).getXIndex()) @@ -218,7 +236,7 @@ public T getEntryForXIndex(int x) { else high = m - 1; - closest = mYVals.get(m); + closest = m; } return closest; @@ -442,10 +460,12 @@ public boolean isDrawValuesEnabled() { } /** - * Adds an Entry to the DataSet dynamically. This will also recalculate the - * current minimum and maximum values of the DataSet and the value-sum. + * Adds an Entry to the DataSet dynamically. + * Entries are added to the end of the list. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. * - * @param d + * @param e */ @SuppressWarnings("unchecked") public void addEntry(Entry e) { @@ -475,6 +495,50 @@ public void addEntry(Entry e) { mYVals.add((T) e); } + /** + * Adds an Entry to the DataSet dynamically. + * Entries are added to their appropriate index respective to it's x-index. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. + * + * @param e + */ + @SuppressWarnings("unchecked") + public void addEntryOrdered(Entry e) { + + if (e == null) + return; + + float val = e.getVal(); + + if (mYVals == null) { + mYVals = new ArrayList(); + } + + if (mYVals.size() == 0) { + mYMax = val; + mYMin = val; + } else { + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; + } + + mYValueSum += val; + + if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) + { + int closestIndex = getEntryIndex(e.getXIndex()); + if (mYVals.get(closestIndex).getXIndex() < e.getXIndex()) + closestIndex++; + mYVals.add(closestIndex, (T) e); + return; + } + + mYVals.add((T) e); + } + /** * Removes an Entry from the DataSets entries array. This will also * recalculate the current minimum and maximum values of the DataSet and the From d739467cb263735206e7f6e83aa3d63560d50280 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 17:17:36 +0300 Subject: [PATCH 0417/1390] Update yAxis size after scale/pan --- .../charting/charts/BarLineChartBase.java | 26 ++++++++++++++++++- .../charting/charts/HorizontalBarChart.java | 2 +- .../mikephil/charting/charts/PieChart.java | 2 +- .../charting/charts/PieRadarChartBase.java | 2 +- .../charting/charts/ScatterChart.java | 2 +- .../listener/BarLineChartTouchListener.java | 21 ++++++++++++++- 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index be30ba24b0..db0639e4da 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -382,7 +382,7 @@ protected void calcMinMax() { } @Override - protected void calculateOffsets() { + public void calculateOffsets() { if (!mCustomViewPortEnabled) { @@ -598,6 +598,12 @@ public void computeScroll() { public void zoomIn() { Matrix save = mViewPortHandler.zoomIn(getWidth() / 2f, -(getHeight() / 2f)); mViewPortHandler.refresh(save, this, true); + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + calculateOffsets(); + postInvalidate(); } /** @@ -606,6 +612,12 @@ public void zoomIn() { public void zoomOut() { Matrix save = mViewPortHandler.zoomOut(getWidth() / 2f, -(getHeight() / 2f)); mViewPortHandler.refresh(save, this, true); + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + calculateOffsets(); + postInvalidate(); } /** @@ -620,6 +632,12 @@ public void zoomOut() { public void zoom(float scaleX, float scaleY, float x, float y) { Matrix save = mViewPortHandler.zoom(scaleX, scaleY, x, -y); mViewPortHandler.refresh(save, this, true); + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + calculateOffsets(); + postInvalidate(); } /** @@ -629,6 +647,12 @@ public void zoom(float scaleX, float scaleY, float x, float y) { public void fitScreen() { Matrix save = mViewPortHandler.fitScreen(); mViewPortHandler.refresh(save, this, true); + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + calculateOffsets(); + postInvalidate(); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 5df259b9ac..ee6ff2d7d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -60,7 +60,7 @@ protected void init() { } @Override - protected void calculateOffsets() { + public void calculateOffsets() { float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 99291fe688..5918cd0dd0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -117,7 +117,7 @@ protected void onDraw(Canvas canvas) { } @Override - protected void calculateOffsets() { + public void calculateOffsets() { super.calculateOffsets(); // prevent nullpointer when no data set diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 48b5bf075e..afd1ad1421 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -96,7 +96,7 @@ public void notifyDataSetChanged() { } @Override - protected void calculateOffsets() { + public void calculateOffsets() { float legendLeft = 0f, legendRight = 0f, legendBottom = 0f, legendTop = 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 4011fa0608..3c0e8f852e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -47,7 +47,7 @@ protected void init() { } // @Override - // protected void calculateOffsets() { + // public void calculateOffsets() { // super.calculateOffsets(); // // float offset = mData.getGreatestShapeSize() / 2f; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 68f8135d64..aeee83187c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -183,6 +183,18 @@ public boolean onTouch(View v, MotionEvent event) { } } + if (mTouchMode == X_ZOOM || + mTouchMode == Y_ZOOM || + mTouchMode == PINCH_ZOOM || + mTouchMode == POST_ZOOM) { + + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + mChart.calculateOffsets(); + mChart.postInvalidate(); + } + mTouchMode = NONE; mChart.enableScroll(); @@ -571,7 +583,14 @@ public void computeScroll() { if (Math.abs(mDecelerationVelocity.x) >= 0.01 || Math.abs(mDecelerationVelocity.y) >= 0.01) Utils.postInvalidateOnAnimation(mChart); // This causes computeScroll to fire, recommended for this by Google - else + else { + // Range might have changed, which means that Y-axis labels + // could have changed in size, affecting Y-axis size. + // So we need to recalculate offsets. + mChart.calculateOffsets(); + mChart.postInvalidate(); + stopDeceleration(); + } } } From f5026641586f97bf9d8413af2f74b35e89d2db63 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 19:11:56 +0300 Subject: [PATCH 0418/1390] Fixed highlights in negative stacked bar chart --- .../charting/renderer/BarChartRenderer.java | 34 ++++++++++++------- .../renderer/HorizontalBarChartRenderer.java | 6 ++-- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 5933cf3786..4aa6748434 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -150,20 +150,20 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { * Prepares a bar for being highlighted. * * @param x the x-position - * @param y the y-position + * @param y1 the y1-position + * @param y2 the y2-position * @param barspaceHalf the space between bars - * @param from * @param trans */ - protected void prepareBarHighlight(float x, float y, float barspaceHalf, float from, + protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, Transformer trans) { float barWidth = 0.5f; float left = x - barWidth + barspaceHalf; float right = x + barWidth - barspaceHalf; - float top = y >= from ? y : from; - float bottom = y <= from ? y : from; + float top = y1; + float bottom = y2; mBarRect.set(left, top, right, bottom); @@ -359,13 +359,19 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // calculate the correct x-position float x = index * setCount + dataSetIndex + groupspace / 2f + groupspace * index; - float y = isStack ? e.getVals()[h.getStackIndex()] - + e.getBelowSum(h.getStackIndex()) : e.getVal(); - // this is where the bar starts - float from = isStack ? e.getBelowSum(h.getStackIndex()) : 0f; + final float y1; + final float y2; - prepareBarHighlight(x, y, barspaceHalf, from, trans); + if (isStack) { + y1 = e.getPositiveSum(); + y2 = -e.getNegativeSum(); + } else { + y1 = e.getVal(); + y2 = 0.f; + } + + prepareBarHighlight(x, y1, y2, barspaceHalf, trans); c.drawRect(mBarRect, mHighlightPaint); @@ -376,10 +382,12 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // distance between highlight arrow and bar float offsetY = mAnimator.getPhaseY() * 0.07f; + final float yArrow = y1 > -y2 ? y1 : y1; + Path arrow = new Path(); - arrow.moveTo(x + 0.5f, y + offsetY * 0.3f); - arrow.lineTo(x + 0.2f, y + offsetY); - arrow.lineTo(x + 0.8f, y + offsetY); + arrow.moveTo(x + 0.5f, yArrow + offsetY * 0.3f); + arrow.lineTo(x + 0.2f, yArrow + offsetY); + arrow.lineTo(x + 0.8f, yArrow + offsetY); trans.pathValueToPixel(arrow); c.drawPath(arrow, mHighlightPaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 5229b9c20c..f0576876bc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -266,13 +266,13 @@ public void drawValues(Canvas c) { } @Override - protected void prepareBarHighlight(float x, float y, float barspaceHalf, float from, + protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, Transformer trans) { float top = x - 0.5f + barspaceHalf; float bottom = x + 0.5f - barspaceHalf; - float left = y >= from ? y : from; - float right = y <= from ? y : from; + float left = y1; + float right = y2; mBarRect.set(left, top, right, bottom); From 02590793289ea61accef7c348b4fb18aa9e9b98e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 21:13:11 +0300 Subject: [PATCH 0419/1390] Avoid making too many multiplications in transformer Each value takes 3 multiplications (3 matrices), when each Matrix is actually 9 values. Now for one value, multiplying 3 time with the matrix (X *= M1, X *= M2, X *= M3) When you take 10 values - it's 30 multiplications (and X9) The new approach pre-multiplies the 3 matrices into 1. So: First value is multiplied by the matrix, meaning 3 multiplications for the first value (M1 * M2 * M3 * X) But for 10 values, we have 12 multiplications (M = M1 * M2 * M3, M * X1, M * X2, M * X3 ... M * X10) --- .../mikephil/charting/utils/Transformer.java | 32 ++++++++++++++----- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index d87a5f5a8a..83bac18200 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -66,7 +66,7 @@ public void prepareMatrixValuePx(float xChartMin, float deltaX, float deltaY, fl /** * Prepares the matrix that contains all offsets. * - * @param chart + * @param inverted */ public void prepareMatrixOffset(boolean inverted) { @@ -113,7 +113,7 @@ public float[] generateTransformedValuesScatter(List entries, } } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -142,7 +142,7 @@ public float[] generateTransformedValuesBubble(List entries, } } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -171,7 +171,7 @@ public float[] generateTransformedValuesLine(List entries, } } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -200,7 +200,7 @@ public float[] generateTransformedValuesCandle(List entries, } } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -234,7 +234,7 @@ public float[] generateTransformedValuesBarChart(List entries, valuePoints[j + 1] = y * phaseY; } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -268,7 +268,7 @@ public float[] generateTransformedValuesHorizontalBarChart(List valuePoints[j + 1] = x; } - pointValuesToPixel(valuePoints); + getValueToPixelMatrix().mapPoints(valuePoints); return valuePoints; } @@ -368,8 +368,10 @@ public void rectValueToPixelHorizontal(RectF r, float phaseY) { */ public void rectValuesToPixel(List rects) { + Matrix m = getValueToPixelMatrix(); + for (int i = 0; i < rects.size(); i++) - rectValueToPixel(rects.get(i)); + m.mapRect(rects.get(i)); } /** @@ -444,6 +446,20 @@ public Matrix getValueMatrix() { return mMatrixValueToPx; } + private Matrix mMBuffer1 = new Matrix(); + public Matrix getValueToPixelMatrix() { + mMBuffer1.set(mMatrixValueToPx); + mMBuffer1.postConcat(mViewPortHandler.mMatrixTouch); + mMBuffer1.postConcat(mMatrixOffset); + return mMBuffer1; + } + + private Matrix mMBuffer2 = new Matrix(); + public Matrix getPixelToValueMatrix() { + getValueToPixelMatrix().invert(mMBuffer2); + return mMBuffer2; + } + public Matrix getOffsetMatrix() { return mMatrixOffset; } From 3e08a13ebcf9976762ec77f7b1cb82058fea49ac Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 9 Jul 2015 21:13:19 +0300 Subject: [PATCH 0420/1390] Fixed highlight arrow height to a sensible size in relation to its width --- .../charting/renderer/BarChartRenderer.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 4aa6748434..5bb30e0a85 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -3,6 +3,7 @@ import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; @@ -382,12 +383,19 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // distance between highlight arrow and bar float offsetY = mAnimator.getPhaseY() * 0.07f; + float[] values = new float[9]; + trans.getPixelToValueMatrix().getValues(values); + final float xToYRel = Math.abs(values[Matrix.MSCALE_Y] / values[Matrix.MSCALE_X]); + + final float arrowWidth = set.getBarSpace() / 2.f; + final float arrowHeight = arrowWidth * xToYRel; + final float yArrow = y1 > -y2 ? y1 : y1; Path arrow = new Path(); - arrow.moveTo(x + 0.5f, yArrow + offsetY * 0.3f); - arrow.lineTo(x + 0.2f, yArrow + offsetY); - arrow.lineTo(x + 0.8f, yArrow + offsetY); + arrow.moveTo(x + 0.4f, yArrow + offsetY); + arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY - arrowHeight); + arrow.lineTo(x + 0.4f + arrowWidth, yArrow + offsetY + arrowHeight); trans.pathValueToPixel(arrow); c.drawPath(arrow, mHighlightPaint); From 034e05997d2fad20d8b1a764b651b66483f713f4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 11 Jul 2015 23:58:44 +0200 Subject: [PATCH 0421/1390] Highlight indicator color, width and horizontal vertical can now be set (issue #814). --- MPChartExample/build.gradle | 2 +- .../CandleStickChartActivity.java | 1 + .../CubicLineChartActivity.java | 1 + .../mpchartexample/LineChartActivity1.java | 4 -- .../mpchartexample/LineChartActivity2.java | 1 + .../mikephil/charting/data/CandleDataSet.java | 2 +- .../charting/data/LineRadarDataSet.java | 6 +- .../data/LineScatterCandleRadarDataSet.java | 67 +++++++++++++++++++ .../charting/data/ScatterDataSet.java | 2 +- .../renderer/CandleStickChartRenderer.java | 23 +++---- .../charting/renderer/LineChartRenderer.java | 8 ++- .../LineScatterCandleRadarRenderer.java | 37 ++++++++++ .../charting/renderer/RadarChartRenderer.java | 6 +- .../renderer/ScatterChartRenderer.java | 8 ++- 14 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index baaf9d0c91..3dff846c36 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -7,7 +7,7 @@ android { minSdkVersion 16 targetSdkVersion 21 versionCode 40 - versionName '2.1.0' + versionName '2.1.1' sourceSets { main { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index d9989ab0f7..07cf8ab1f9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -205,6 +205,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setDecreasingPaintStyle(Paint.Style.STROKE); set1.setIncreasingColor(Color.rgb(122, 242, 84)); set1.setIncreasingPaintStyle(Paint.Style.FILL); + //set1.setHighlightLineWidth(1f); CandleData data = new CandleData(xVals, set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 25cdf71373..e86a1367f0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -275,6 +275,7 @@ private void setData(int count, float range) { set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setColor(Color.rgb(104, 241, 175)); set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setDrawHorizontalHighlightIndicator(false); // create a data object with the datasets LineData data = new LineData(xVals, set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 83cc2c9cfb..cc548c5995 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -93,10 +93,6 @@ protected void onCreate(Bundle savedInstanceState) { // set the marker to the chart mChart.setMarkerView(mv); - - // enable/disable highlight indicators (the lines that indicate the - // highlighted Entry) - mChart.setHighlightEnabled(false); // x-axis limit line // LimitLine llXAxis = new LimitLine(10f, "Index 10"); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 0fb11d1e7d..323820e7f3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -292,6 +292,7 @@ private void setData(int count, float range) { set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setDrawCircleHole(false); +// set1.setDrawHorizontalHighlightIndicator(false); // set1.setVisible(false); // set1.setCircleHoleColor(Color.WHITE); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index cc78e8d857..c40152ace3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -14,7 +14,7 @@ * * @author Philipp Jahoda */ -public class CandleDataSet extends BarLineScatterCandleDataSet { +public class CandleDataSet extends LineScatterCandleRadarDataSet { /** the width of the shadow of the candle */ private float mShadowWidth = 3f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 64e0762d30..49adf841aa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -12,7 +12,7 @@ * * @author Philipp Jahoda */ -public abstract class LineRadarDataSet extends BarLineScatterCandleDataSet { +public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet { /** the color that is used for filling the line surface */ private int mFillColor = Color.rgb(140, 234, 255); @@ -64,7 +64,7 @@ public int getFillAlpha() { * sets the alpha value (transparency) that is used for filling the line * surface (0-255), default: 85 * - * @param color + * @param alpha */ public void setFillAlpha(int alpha) { mFillAlpha = alpha; @@ -79,7 +79,7 @@ public void setFillAlpha(int alpha) { public void setLineWidth(float width) { if (width < 0.2f) - width = 0.5f; + width = 0.2f; if (width > 10.0f) width = 10.0f; mLineWidth = Utils.convertDpToPixel(width); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java new file mode 100644 index 0000000000..6c322c2122 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -0,0 +1,67 @@ +package com.github.mikephil.charting.data; + +import com.github.mikephil.charting.utils.Utils; + +import java.util.List; + +/** + * Created by philipp on 11/07/15. + */ +public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleDataSet { + + protected boolean mDrawVerticalHighlightIndicator = true; + protected boolean mDrawHorizontalHighlightIndicator = true; + + /** the width of the highlight indicator lines */ + protected float mHighlightLineWidth = 0.5f; + + public LineScatterCandleRadarDataSet(List yVals, String label) { + super(yVals, label); + mHighlightLineWidth = Utils.convertDpToPixel(0.5f); + } + + /** + * Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn. + * @param enabled + */ + public void setDrawHorizontalHighlightIndicator(boolean enabled) { + this.mDrawHorizontalHighlightIndicator = enabled; + } + + /** + * Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn. + * @param enabled + */ + public void setDrawVerticalHighlightIndicator(boolean enabled) { + this.mDrawVerticalHighlightIndicator = enabled; + } + + /** + * Enables / disables both vertical and horizontal highlight-indicators. + * @param enabled + */ + public void setDrawHighlightIndicators(boolean enabled) { + setDrawVerticalHighlightIndicator(enabled); + setDrawHorizontalHighlightIndicator(enabled); + } + + public boolean isVerticalHighlightIndicatorEnabled() { + return mDrawVerticalHighlightIndicator; + } + + public boolean isHorizontalHighlightIndicatorEnabled() { + return mDrawHorizontalHighlightIndicator; + } + + /** + * Sets the width of the highlight line in dp. + * @param width + */ + public void setHighlightLineWidth(float width) { + mHighlightLineWidth = Utils.convertDpToPixel(width); + } + + public float getHighlightLineWidth() { + return mHighlightLineWidth; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 9efca9b760..f8c6f2ffe8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -9,7 +9,7 @@ import java.util.ArrayList; import java.util.List; -public class ScatterDataSet extends BarLineScatterCandleDataSet { +public class ScatterDataSet extends LineScatterCandleRadarDataSet { /** the size the scattershape will have, in screen pixels */ private float mShapeSize = 15f; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 9912ff5385..74863d3125 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -21,7 +21,7 @@ import java.util.List; -public class CandleStickChartRenderer extends DataRenderer { +public class CandleStickChartRenderer extends LineScatterCandleRadarRenderer { protected CandleDataProvider mChart; @@ -294,6 +294,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); CandleEntry e = set.getEntryForXIndex(xIndex); @@ -302,27 +303,21 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float low = e.getLow() * mAnimator.getPhaseY(); float high = e.getHigh() * mAnimator.getPhaseY(); + float y = (low + high) / 2f; float min = mChart.getYChartMin(); float max = mChart.getYChartMax(); - float[] vertPts = new float[] { - xIndex - 0.5f, max, xIndex - 0.5f, min, xIndex + 0.5f, max, xIndex + 0.5f, - min - }; - float[] horPts = new float[] { - mChart.getXChartMin(), low, mChart.getXChartMax(), low, mChart.getXChartMin(), high, mChart.getXChartMax(), high + float[] pts = new float[] { + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, + mChart.getXChartMax(), y }; - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(vertPts); - mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(horPts); - - // draw the vertical highlight lines - c.drawLines(vertPts, mHighlightPaint); + mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); - // draw the horizontal highlight lines - c.drawLines(horPts, mHighlightPaint); + // draw the lines + drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 116a5dfcfc..86a57a9095 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -20,7 +20,7 @@ import java.util.List; -public class LineChartRenderer extends DataRenderer { +public class LineChartRenderer extends LineScatterCandleRadarRenderer { protected LineDataProvider mChart; @@ -539,6 +539,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); int xIndex = indices[i].getXIndex(); // get the // x-position @@ -560,8 +561,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); - // draw the highlight lines - c.drawLines(pts, mHighlightPaint); + + // draw the lines + drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java new file mode 100644 index 0000000000..2747f792d9 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -0,0 +1,37 @@ +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.data.LineScatterCandleRadarDataSet; +import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by philipp on 11/07/15. + */ +public abstract class LineScatterCandleRadarRenderer extends DataRenderer { + + public LineScatterCandleRadarRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + } + + /** + * Draws vertical & horizontal highlight-lines if enabled. + * @param c + * @param pts + * @param horizontal + * @param vertical + */ + protected void drawHighlightLines(Canvas c, float[] pts, boolean horizontal, boolean vertical) { + + // draw vertical highlight lines + if(vertical) + c.drawLine(pts[0], pts[1], pts[2], pts[3], mHighlightPaint); + + // draw horizontal highlight lines + if(horizontal) + c.drawLine(pts[4], pts[5], pts[6], pts[7], mHighlightPaint); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index c42a2ef2bc..473018a56c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -18,7 +18,7 @@ import java.util.List; -public class RadarChartRenderer extends DataRenderer { +public class RadarChartRenderer extends LineScatterCandleRadarRenderer { protected RadarChart mChart; @@ -220,6 +220,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); // get the index to highlight int xIndex = indices[i].getXIndex(); @@ -242,7 +243,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { mViewPortHandler.getChartWidth(), p.y }; - c.drawLines(pts, mHighlightPaint); + // draw the lines + drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 4d27bae491..65af71999c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -19,7 +19,7 @@ import java.util.List; -public class ScatterChartRenderer extends DataRenderer { +public class ScatterChartRenderer extends LineScatterCandleRadarRenderer { protected ScatterDataProvider mChart; @@ -259,6 +259,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); int xIndex = indices[i].getXIndex(); // get the // x-position @@ -280,8 +281,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); - // draw the highlight lines - c.drawLines(pts, mHighlightPaint); + + // draw the lines + drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); } } } From 5ac58fc69c7a830dc79b33d9f2113a364b816058 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 12 Jul 2015 13:41:37 +0200 Subject: [PATCH 0422/1390] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 30f3aa2a24..a6b5f399c5 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,9 @@ Donations []() -Follow me on **Twitter**: [**PhilippJahoda**](https://twitter.com/PhilippJahoda) +Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) + +Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) Demo From 8963d04e512e5157db7ce92f930435aa9cc9cdb8 Mon Sep 17 00:00:00 2001 From: Josh Friend Date: Mon, 13 Jul 2015 15:54:48 -0400 Subject: [PATCH 0423/1390] Add javadocs to artifacts Also removed `deploy.gradle` which was added in #20 since it was unused and moved the relevant javadoc targets to `build.gradle` instead. Jitpack will host javadocs for you if a javadocs jar is built. The URL ends up being something like: https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.0/javadoc/ Fixes #835 --- MPChartLib/build.gradle | 12 +++++ README.md | 2 +- deploy.gradle | 117 ---------------------------------------- 3 files changed, 13 insertions(+), 118 deletions(-) delete mode 100644 deploy.gradle diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 2b10d4db7c..9530a93bd5 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -50,6 +50,18 @@ task sourcesJar(type: Jar) { classifier = 'sources' } +task javadoc(type: Javadoc) { + failOnError false + source = android.sourceSets.main.java.sourceFiles + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier = 'javadoc' + from javadoc.destinationDir +} + artifacts { archives sourcesJar + archives javadocJar } diff --git a/README.md b/README.md index a6b5f399c5..fc9fe0aee0 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/-SNAPSHOT/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) diff --git a/deploy.gradle b/deploy.gradle deleted file mode 100644 index b9382fe1f1..0000000000 --- a/deploy.gradle +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2013 Chris Banes - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -apply plugin:'maven' -apply plugin:'signing' - -def isReleaseBuild() { - return VERSION_NAME.contains("SNAPSHOT") == false -} - -def getReleaseRepositoryUrl() { - return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL - : "https://oss.sonatype.org/service/local/staging/deploy/maven2/" -} - -def getSnapshotRepositoryUrl() { - return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL - : "https://oss.sonatype.org/content/repositories/snapshots/" -} - -def getRepositoryUsername() { - return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : "" -} - -def getRepositoryPassword() { - return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" -} - - -afterEvaluate { project -> - uploadArchives { - repositories { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - - pom.groupId = GROUP - pom.artifactId = POM_ARTIFACT_ID - pom.version = VERSION_NAME - - repository(url: getReleaseRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - snapshotRepository(url: getSnapshotRepositoryUrl()) { - authentication(userName: getRepositoryUsername(), password: getRepositoryPassword()) - } - - pom.project { - name POM_NAME - packaging POM_PACKAGING - description hasProperty('POM_DESCRIPTION') ? POM_DESCRIPTION : "" - url hasProperty('POM_URL') ? POM_URL : "" - - scm { - url hasProperty('POM_SCM_URL') ? POM_SCM_URL : "" - connection hasProperty('POM_SCM_CONNECTION') ? POM_SCM_CONNECTION : "" - developerConnection hasProperty('POM_SCM_DEV_CONNECTION') ? POM_SCM_DEV_CONNECTION : "" - } - - licenses { - license { - name hasProperty('POM_LICENCE_NAME') ? POM_LICENCE_NAME : "" - url hasProperty('POM_LICENCE_URL') ? POM_LICENCE_URL : "" - distribution hasProperty('POM_LICENCE_DIST') ? POM_LICENCE_DIST : "" - } - } - - developers { - developer { - id POM_DEVELOPER_ID - name POM_DEVELOPER_NAME - } - } - } - } - } - } - - signing { - required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") && hasProperty('signing.keyId') } - sign configurations.archives - } - - task androidJavadocs(type: Javadoc) { - failOnError false - source = android.sourceSets.main.java.sourceFiles - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - } - - task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - classifier = 'javadoc' - from androidJavadocs.destinationDir - } - - task androidSourcesJar(type: Jar) { - classifier = 'sources' - from android.sourceSets.main.java.sourceFiles - } - - artifacts { - archives androidSourcesJar - archives androidJavadocsJar - } -} - From 9611421506816b8b6ee362bf49906d033beee23f Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 17 Jul 2015 16:16:53 +0300 Subject: [PATCH 0424/1390] Maximum negative value was confused... --- MPChartLib/src/com/github/mikephil/charting/data/ChartData.java | 2 +- MPChartLib/src/com/github/mikephil/charting/data/DataSet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index e004b08e13..39db210106 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -203,7 +203,7 @@ public void calcMinMax(int start, int end) { mLastEnd = end; mYMin = Float.MAX_VALUE; - mYMax = -Float.MIN_VALUE; + mYMax = -Float.MAX_VALUE; for (int i = 0; i < mDataSets.size(); i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 1d08ad783d..cc7633a3b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -123,7 +123,7 @@ protected void calcMinMax(int start, int end) { mLastEnd = endValue; mYMin = Float.MAX_VALUE; - mYMax = -Float.MIN_VALUE; + mYMax = -Float.MAX_VALUE; for (int i = start; i <= endValue; i++) { From 3fc5397fe35c29cae68f0eed4e4847cb4c905620 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 17 Jul 2015 16:19:42 +0300 Subject: [PATCH 0425/1390] startAtZeroEnabled killed that range when all values are negative --- .../charting/charts/BarLineChartBase.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index db0639e4da..fad6e03023 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -371,11 +371,25 @@ protected void calcMinMax() { .getAxisMinValue() : minRight - bottomSpaceRight; // consider starting at zero (0) - if (mAxisLeft.isStartAtZeroEnabled()) - mAxisLeft.mAxisMinimum = 0f; + if (mAxisLeft.isStartAtZeroEnabled()) { + if (mAxisLeft.mAxisMinimum < 0f && mAxisLeft.mAxisMaximum < 0f) { + // If the values are all negative, let's stay in the negative zone + mAxisLeft.mAxisMaximum = 0f; + } else { + // We have positive values, stay in the positive zone + mAxisLeft.mAxisMinimum = 0f; + } + } - if (mAxisRight.isStartAtZeroEnabled()) - mAxisRight.mAxisMinimum = 0f; + if (mAxisRight.isStartAtZeroEnabled()) { + if (mAxisRight.mAxisMinimum < 0.0 && mAxisRight.mAxisMaximum < 0.0) { + // If the values are all negative, let's stay in the negative zone + mAxisRight.mAxisMaximum = 0f; + } else { + // We have positive values, stay in the positive zone + mAxisRight.mAxisMinimum = 0f; + } + } mAxisLeft.mAxisRange = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); mAxisRight.mAxisRange = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); From 37e971ef8e597316479be1d9d06c7270043ec3a8 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 17 Jul 2015 16:25:54 +0300 Subject: [PATCH 0426/1390] Fixed negative stacked bars when there's more than two values in stack --- .../mikephil/charting/buffer/BarBuffer.java | 30 +++++++++---------- .../charting/buffer/HorizontalBarBuffer.java | 30 +++++++++---------- .../charting/renderer/BarChartRenderer.java | 16 +++++----- .../renderer/HorizontalBarChartRenderer.java | 16 +++++----- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index a24a1120c8..c143935f74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -84,8 +84,9 @@ public void feed(List entries) { } else { - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + float posY = 0f; + float negY = 0f; + float yStart = 0f; // fill the stack for (int k = 0; k < vals.length; k++) { @@ -93,30 +94,29 @@ public void feed(List entries) { float value = vals[k]; if(value >= 0f) { - - allPos -= value; - y = value + allPos; + y = posY; + yStart = posY + value; + posY = yStart; } else { - allNeg -= Math.abs(value); - y = value + allNeg; + y = negY; + yStart = negY + value; + negY = yStart; } float left = x - barWidth + barSpaceHalf; float right = x + barWidth - barSpaceHalf; float bottom, top; if (mInverted) { - bottom = y >= 0 ? y : 0; - top = y <= 0 ? y : 0; + bottom = y >= yStart ? y : yStart; + top = y <= yStart ? y : yStart; } else { - top = y >= 0 ? y : 0; - bottom = y <= 0 ? y : 0; + top = y >= yStart ? y : yStart; + bottom = y <= yStart ? y : yStart; } // multiply the height of the rect with the phase - if (top > 0) - top *= phaseY; - else - bottom *= phaseY; + top *= phaseY; + bottom *= phaseY; addBar(left, top, right, bottom); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index d405466f69..06814f9fa0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -54,8 +54,9 @@ public void feed(List entries) { } else { - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + float posY = 0f; + float negY = 0f; + float yStart = 0f; // fill the stack for (int k = 0; k < vals.length; k++) { @@ -63,30 +64,29 @@ public void feed(List entries) { float value = vals[k]; if(value >= 0f) { - - allPos -= value; - y = value + allPos; + y = posY; + yStart = posY + value; + posY = yStart; } else { - allNeg -= Math.abs(value); - y = value + allNeg; + y = negY; + yStart = negY + value; + negY = yStart; } float bottom = x - barWidth + barSpaceHalf; float top = x + barWidth - barSpaceHalf; float left, right; if (mInverted) { - left = y >= 0 ? y : 0; - right = y <= 0 ? y : 0; + left = y >= yStart ? y : yStart; + right = y <= yStart ? y : yStart; } else { - right = y >= 0 ? y : 0; - left = y <= 0 ? y : 0; + right = y >= yStart ? y : yStart; + left = y <= yStart ? y : yStart; } // multiply the height of the rect with the phase - if (right > 0) - right *= phaseY; - else - left *= phaseY; + right *= phaseY; + left *= phaseY; addBar(left, top, right, bottom); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 5bb30e0a85..ea912a7c9f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -260,21 +260,21 @@ public void drawValues(Canvas c) { } else { float[] transformed = new float[vals.length * 2]; - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + + float posY = 0f; + float negY = 0f; for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { float value = vals[idx]; float y; - if(value >= 0f) { - - allPos -= value; - y = value + allPos; + if (value >= 0f) { + posY += value; + y = posY; } else { - allNeg -= Math.abs(value); - y = value + allNeg; + negY += value; + y = negY; } transformed[k + 1] = y * mAnimator.getPhaseY(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index f0576876bc..7270969cdc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -206,21 +206,21 @@ public void drawValues(Canvas c) { } else { float[] transformed = new float[vals.length * 2]; - float allPos = e.getPositiveSum(); - float allNeg = e.getNegativeSum(); + + float posY = 0f; + float negY = 0f; for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { float value = vals[idx]; float y; - if(value >= 0f) { - - allPos -= value; - y = value + allPos; + if (value >= 0f) { + posY += value; + y = posY; } else { - allNeg -= Math.abs(value); - y = value + allNeg; + negY += value; + y = negY; } transformed[k] = y * mAnimator.getPhaseY(); From 077b25446be05afa89c93a805e55f47c4b9e99d1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 17 Jul 2015 16:27:08 +0300 Subject: [PATCH 0427/1390] Fixed a crash when removing an entry --- MPChartLib/src/com/github/mikephil/charting/data/DataSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index cc7633a3b0..e370ad4cc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -114,7 +114,7 @@ protected void calcMinMax(int start, int end) { int endValue; - if (end == 0) + if (end == 0 || end >= mYVals.size()) endValue = mYVals.size() - 1; else endValue = end; From 1f571a3d56afd4ff9eaa7d9c3eb725c94d08e2d9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 17 Jul 2015 16:27:57 +0300 Subject: [PATCH 0428/1390] Removed redundant calls --- .../src/com/github/mikephil/charting/data/DataSet.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e370ad4cc1..902d032fdc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -109,13 +109,15 @@ public void notifyDataSetChanged() { * calc minimum and maximum y value */ protected void calcMinMax(int start, int end) { - if (mYVals.size() == 0) + final int yValCount = mYVals.size(); + + if (yValCount == 0) return; int endValue; - if (end == 0 || end >= mYVals.size()) - endValue = mYVals.size() - 1; + if (end == 0 || end >= yValCount) + endValue = yValCount - 1; else endValue = end; From 3b089daa4ca235b0f27b2df6518fc71e6a8eed2d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 20 Jul 2015 13:01:32 +0200 Subject: [PATCH 0429/1390] Minor fix in example. --- MPChartExample/build.gradle | 4 ++-- .../mpchartexample/BarChartActivityMultiDataset.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 3dff846c36..b8246c4f9c 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -4,9 +4,9 @@ android { compileSdkVersion 21 buildToolsVersion '21.1.1' defaultConfig { - minSdkVersion 16 + minSdkVersion 8 targetSdkVersion 21 - versionCode 40 + versionCode 41 versionName '2.1.1' sourceSets { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 428a485fd7..18488aa409 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -223,7 +223,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { ArrayList dataSets = new ArrayList(); dataSets.add(set1); dataSets.add(set2); - // dataSets.add(set3); + dataSets.add(set3); BarData data = new BarData(xVals, dataSets); // data.setValueFormatter(new LargeValueFormatter()); From 374de0da4cbc55c29e6a83f61701100f4404ab41 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 21 Jul 2015 19:33:25 +0200 Subject: [PATCH 0430/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a6b5f399c5..d522e73163 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.0' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' } ``` @@ -159,13 +159,13 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.0 + v2.1.1 ``` **3. jar file only** - Download the [**latest .jar file**](https://github.com/PhilJay/MPAndroidChart/releases) from the releases section - - Copy the **mpandroidchartlibrary-.jar** file into the `libs` folder of your Android application project + - Copy the **mpandroidchartlibrary-version.jar** file into the `libs` folder of your Android application project - Start using the library **4. clone whole repository** From 3514aaedf9624222c985cb3abb12df2d9b514b12 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 13:11:08 +0200 Subject: [PATCH 0431/1390] Major improvements to stacked bars and bar highlighting. --- MPChartExample/AndroidManifest.xml | 2 +- MPChartExample/build.gradle | 2 +- .../mpchartexample/BarChartActivity.java | 2 +- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BubbleChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 2 +- .../HorizontalBarChartActivity.java | 4 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 2 +- .../MultiLineChartActivity.java | 2 +- .../mpchartexample/PieChartActivity.java | 2 +- .../RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 4 +- .../StackedBarActivityNegative.java | 8 +- .../charting/buffer/HorizontalBarBuffer.java | 6 +- .../mikephil/charting/charts/BarChart.java | 158 ++++++-------- .../charting/charts/BarLineChartBase.java | 106 ++++----- .../mikephil/charting/charts/Chart.java | 5 +- .../charting/charts/HorizontalBarChart.java | 32 +-- .../mikephil/charting/data/BarEntry.java | 87 ++++---- .../mikephil/charting/data/ChartData.java | 2 +- .../charting/highlight/BarHighlighter.java | 201 ++++++++++++++++++ .../charting/highlight/ChartHighlighter.java | 144 +++++++++++++ .../{utils => highlight}/Highlight.java | 2 +- .../highlight/HorizontalBarHighlighter.java | 100 +++++++++ .../mikephil/charting/highlight/Range.java | 37 ++++ .../charting/interfaces/BarDataProvider.java | 2 +- ...rLineScatterCandleBubbleDataProvider.java} | 5 +- .../interfaces/BubbleDataProvider.java | 3 +- .../interfaces/CandleDataProvider.java | 2 +- .../charting/interfaces/ChartInterface.java | 3 + .../charting/interfaces/LineDataProvider.java | 2 +- .../interfaces/ScatterDataProvider.java | 2 +- .../listener/BarLineChartTouchListener.java | 5 +- .../charting/listener/ChartTouchListener.java | 3 +- .../OnChartValueSelectedListener.java | 2 +- .../listener/PieRadarChartTouchListener.java | 2 +- .../charting/renderer/BarChartRenderer.java | 11 +- .../renderer/BubbleChartRenderer.java | 2 +- .../renderer/CandleStickChartRenderer.java | 3 +- .../renderer/CombinedChartRenderer.java | 6 +- .../charting/renderer/DataRenderer.java | 2 +- .../renderer/HorizontalBarChartRenderer.java | 27 +-- .../charting/renderer/LineChartRenderer.java | 2 +- .../LineScatterCandleRadarRenderer.java | 3 - .../charting/renderer/PieChartRenderer.java | 2 +- .../charting/renderer/RadarChartRenderer.java | 2 +- .../mikephil/charting/renderer/Renderer.java | 4 +- .../renderer/ScatterChartRenderer.java | 4 +- .../github/mikephil/charting/utils/Utils.java | 6 +- 53 files changed, 735 insertions(+), 294 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java rename MPChartLib/src/com/github/mikephil/charting/{utils => highlight}/Highlight.java (98%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/highlight/Range.java rename MPChartLib/src/com/github/mikephil/charting/interfaces/{BarLineScatterCandleDataProvider.java => BarLineScatterCandleBubbleDataProvider.java} (67%) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 41a33d46c3..e198c821c4 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -2,7 +2,7 @@ + android:versionName="2.1.1" > entries) { } else { float posY = 0f; - float negY = 0f; + float negY = -e.getNegativeSum(); float yStart = 0f; // fill the stack @@ -69,8 +69,8 @@ public void feed(List entries) { posY = yStart; } else { y = negY; - yStart = negY + value; - negY = yStart; + yStart = negY + Math.abs(value); + negY += Math.abs(value); } float bottom = x - barWidth + barSpaceHalf; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 0e187b91c5..9e70a01de0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -12,10 +12,11 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; /** * Chart that draws bars. @@ -65,6 +66,8 @@ protected void init() { mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + mHighlighter = new BarHighlighter(this); + mXChartMin = -0.5f; } @@ -107,19 +110,8 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (mDataNotSet || mData == null) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; - } - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - pts[1] = y; - - mLeftAxisTransformer.pixelsToValue(pts); - - if (pts[0] < mXChartMin || pts[0] > mXChartMax) - return null; - - return getHighlight(pts[0], pts[1]); + } else + return mHighlighter.getHighlight(x, y); } /** @@ -131,85 +123,65 @@ public Highlight getHighlightByTouchPoint(float x, float y) { */ protected Highlight getHighlight(double xPosition, double yPosition) { - int setCount = mData.getDataSetCount(); - int valCount = mData.getXValCount(); - int dataSetIndex = 0; - int xIndex = 0; - - // only one dataset exists - if (!mData.isGrouped()) { - - xIndex = (int) Math.round(xPosition); - - // check bounds - if (xIndex < 0) { - xIndex = 0; - } else if (xIndex >= valCount) { - xIndex = valCount - 1; - } - - // if this bardata is grouped into more datasets - } else { - - // calculate how often the group-space appears - int steps = (int) ((float) xPosition / ((float) setCount + mData.getGroupSpace())); - - float groupSpaceSum = mData.getGroupSpace() * (float) steps; - - float baseNoSpace = (float) xPosition - groupSpaceSum; - - if (mLogEnabled) - Log.i(LOG_TAG, "base: " + xPosition + ", steps: " + steps + ", groupSpaceSum: " - + groupSpaceSum - + ", baseNoSpace: " + baseNoSpace); - - dataSetIndex = (int) baseNoSpace % setCount; - xIndex = (int) baseNoSpace / setCount; - - if (mLogEnabled) - Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - - // check bounds - if (xIndex < 0) { - xIndex = 0; - dataSetIndex = 0; - } else if (xIndex >= valCount) { - xIndex = valCount - 1; - dataSetIndex = setCount - 1; - } - - // check bounds - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; - } - - if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) - return new Highlight(xIndex, dataSetIndex); - else - return getStackedHighlight(xIndex, dataSetIndex, yPosition); - } - - /** - * This method creates the Highlight object that also indicates which value - * of a stacked BarEntry has been selected. - * - * @param xIndex - * @param dataSet - * @param yValue - * @return - */ - protected Highlight getStackedHighlight(int xIndex, int dataSet, double yValue) { - - BarEntry entry = mData.getDataSetByIndex(dataSet).getEntryForXIndex(xIndex); - - if (entry != null) { - int stackIndex = entry.getClosestIndexAbove((float) yValue); - Highlight h = new Highlight(xIndex, dataSet, stackIndex); - return h; - } else - return null; +// int setCount = mData.getDataSetCount(); +// int valCount = mData.getXValCount(); +// int dataSetIndex = 0; +// int xIndex = 0; +// +// // only one dataset exists +// if (!mData.isGrouped()) { +// +// xIndex = (int) Math.round(xPosition); +// +// // check bounds +// if (xIndex < 0) { +// xIndex = 0; +// } else if (xIndex >= valCount) { +// xIndex = valCount - 1; +// } +// +// // if this bardata is grouped into more datasets +// } else { +// +// // calculate how often the group-space appears +// int steps = (int) ((float) xPosition / ((float) setCount + mData.getGroupSpace())); +// +// float groupSpaceSum = mData.getGroupSpace() * (float) steps; +// +// float baseNoSpace = (float) xPosition - groupSpaceSum; +// +// if (mLogEnabled) +// Log.i(LOG_TAG, "base: " + xPosition + ", steps: " + steps + ", groupSpaceSum: " +// + groupSpaceSum +// + ", baseNoSpace: " + baseNoSpace); +// +// dataSetIndex = (int) baseNoSpace % setCount; +// xIndex = (int) baseNoSpace / setCount; +// +// if (mLogEnabled) +// Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); +// +// // check bounds +// if (xIndex < 0) { +// xIndex = 0; +// dataSetIndex = 0; +// } else if (xIndex >= valCount) { +// xIndex = valCount - 1; +// dataSetIndex = setCount - 1; +// } +// +// // check bounds +// if (dataSetIndex < 0) +// dataSetIndex = 0; +// else if (dataSetIndex >= setCount) +// dataSetIndex = setCount - 1; +// } +// +// if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) +// return new Highlight(xIndex, dataSetIndex); +// else +// return getStackedHighlight(xIndex, dataSetIndex, yPosition); + return null; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index fad6e03023..e8354a3408 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -26,14 +26,15 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; +import com.github.mikephil.charting.highlight.ChartHighlighter; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; import com.github.mikephil.charting.utils.FillFormatter; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Transformer; @@ -49,7 +50,7 @@ */ @SuppressLint("RtlHardcoded") public abstract class BarLineChartBase>> - extends Chart implements BarLineScatterCandleDataProvider { + extends Chart implements BarLineScatterCandleBubbleDataProvider { /** the maximum number of entried to which values will be drawn */ protected int mMaxVisibleCount = 100; @@ -147,6 +148,8 @@ protected void init() { mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); + mHighlighter = new ChartHighlighter(this); + mChartTouchListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); mGridBackgroundPaint = new Paint(); @@ -1077,54 +1080,55 @@ public Highlight getHighlightByTouchPoint(float x, float y) { if (mDataNotSet || mData == null) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; - } - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - - // take any transformer to determine the x-axis value - mLeftAxisTransformer.pixelsToValue(pts); - - double xTouchVal = pts[0]; - double base = Math.floor(xTouchVal); - - double touchOffset = mDeltaX * 0.025; - - // touch out of chart - if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset) - return null; - - if (base < 0) - base = 0; - if (base >= mDeltaX) - base = mDeltaX - 1; - - int xIndex = (int) base; - - // check if we are more than half of a x-value or not - if (xTouchVal - base > 0.5) { - xIndex = (int) base + 1; - } - - List valsAtIndex = getSelectionDetailsAtIndex(xIndex); - - float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); - float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); - - if (mData.getFirstRight() == null) - rightdist = Float.MAX_VALUE; - if (mData.getFirstLeft() == null) - leftdist = Float.MAX_VALUE; - - AxisDependency axis = leftdist < rightdist ? AxisDependency.LEFT : AxisDependency.RIGHT; - - int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); - - if (dataSetIndex == -1) - return null; - - return new Highlight(xIndex, dataSetIndex); + } else + return mHighlighter.getHighlight(x, y); + +// // create an array of the touch-point +// float[] pts = new float[2]; +// pts[0] = x; +// +// // take any transformer to determine the x-axis value +// mLeftAxisTransformer.pixelsToValue(pts); +// +// double xTouchVal = pts[0]; +// double base = Math.floor(xTouchVal); +// +// double touchOffset = mDeltaX * 0.025; +// +// // touch out of chart +// if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset) +// return null; +// +// if (base < 0) +// base = 0; +// if (base >= mDeltaX) +// base = mDeltaX - 1; +// +// int xIndex = (int) base; +// +// // check if we are more than half of a x-value or not +// if (xTouchVal - base > 0.5) { +// xIndex = (int) base + 1; +// } +// +// List valsAtIndex = getSelectionDetailsAtIndex(xIndex); +// +// float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); +// float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); +// +// if (mData.getFirstRight() == null) +// rightdist = Float.MAX_VALUE; +// if (mData.getFirstLeft() == null) +// leftdist = Float.MAX_VALUE; +// +// AxisDependency axis = leftdist < rightdist ? AxisDependency.LEFT : AxisDependency.RIGHT; +// +// int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); +// +// if (dataSetIndex == -1) +// return null; +// +// return new Highlight(xIndex, dataSetIndex); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index fb0c7293a9..51db1e93e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -33,6 +33,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; @@ -40,7 +41,7 @@ import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; import com.github.mikephil.charting.utils.DefaultValueFormatter; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -144,6 +145,8 @@ public abstract class Chart mXChartMax) - return null; - - return getHighlight(pts[1], pts[0]); + } else + return mHighlighter.getHighlight(y, x); // switch x and y + +// // create an array of the touch-point +// float[] pts = new float[2]; +// pts[0] = x; +// pts[1] = y; +// +// mLeftAxisTransformer.pixelsToValue(pts); +// +// if (pts[1] < mXChartMin || pts[1] > mXChartMax) +// return null; +// +// return getHighlight(pts[1], pts[0]); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index 6ad47477dc..947542a0d1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -13,8 +13,12 @@ public class BarEntry extends Entry { /** the values the stacked barchart holds */ private float[] mVals; + /** the sum of all negative values this entry (if stacked) contains */ + private float mNegativeSum; + /** - * Constructor for stacked bar entries. + * Constructor for stacked bar entries. Don't forget to order the + * stacked-values in an ascending order e.g. (-2,-1,0,1,2). * * @param vals - the stack values * @param xIndex @@ -23,6 +27,7 @@ public BarEntry(float[] vals, int xIndex) { super(calcSum(vals), xIndex); this.mVals = vals; + calcNegativeSum(); } /** @@ -36,7 +41,8 @@ public BarEntry(float val, int xIndex) { } /** - * Constructor for stacked bar entries. + * Constructor for stacked bar entries. Don't forget to order the + * stacked-values in an ascending order e.g. (-2,-1,0,1,2). * * @param vals - the stack values * @param xIndex @@ -46,6 +52,7 @@ public BarEntry(float[] vals, int xIndex, String label) { super(calcSum(vals), xIndex, label); this.mVals = vals; + calcNegativeSum(); } /** @@ -65,7 +72,7 @@ public BarEntry(float val, int xIndex, Object data) { public BarEntry copy() { BarEntry copied = new BarEntry(getVal(), getXIndex(), getData()); - copied.mVals = mVals; + copied.setVals(mVals); return copied; } @@ -87,32 +94,7 @@ public float[] getVals() { public void setVals(float[] vals) { setVal(calcSum(vals)); mVals = vals; - } - - /** - * Returns the index of the closest value inside the values array (for stacked barchart) - * to the value given as a parameter. The closest value must be higher - * (above) the provided value. - * - * @param val - * @return - */ - public int getClosestIndexAbove(float val) { - - if (mVals == null) - return 0; - - Log.i("TOUCHVALUE", val + ""); - - int index = mVals.length - 1; - float remainder = 0f; - - while (index > 0 && val > mVals[index] + remainder) { - remainder += mVals[index]; - index--; - } - - return index; + calcNegativeSum(); } public float getBelowSum(int stackIndex) { @@ -132,21 +114,9 @@ public float getBelowSum(int stackIndex) { } /** - * Calculates the sum across all values. - * - * @param vals + * Reuturns the sum of all positive values this entry (if stacked) contains. * @return */ - private static float calcSum(float[] vals) { - - float sum = 0f; - - for (float f : vals) - sum += f; - - return sum; - } - public float getPositiveSum() { if(mVals == null) @@ -162,10 +132,19 @@ public float getPositiveSum() { return sum; } + /** + * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) + * @return + */ public float getNegativeSum() { + return mNegativeSum; + } - if(mVals == null) - return 0f; + private void calcNegativeSum() { + if(mVals == null) { + mNegativeSum = 0; + return; + } float sum = 0f; @@ -174,6 +153,26 @@ public float getNegativeSum() { sum += Math.abs(f); } + mNegativeSum = sum; + } + + + /** + * Calculates the sum across all values of the given stack. + * + * @param vals + * @return + */ + private static float calcSum(float[] vals) { + + if(vals == null) + return 0f; + + float sum = 0f; + + for (float f : vals) + sum += f; + return sum; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 39db210106..8bcc59bccc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -5,7 +5,7 @@ import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.ValueFormatter; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java new file mode 100644 index 0000000000..d9727e5eb0 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -0,0 +1,201 @@ +package com.github.mikephil.charting.highlight; + +import android.util.Log; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; + +/** + * Created by Philipp Jahoda on 22/07/15. + */ +public class BarHighlighter extends ChartHighlighter { + + public BarHighlighter(BarDataProvider chart) { + super(chart); + } + + @Override + public Highlight getHighlight(float x, float y) { + + Highlight h = super.getHighlight(x, y); + + if(h == null) + return h; + else { + + BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + + if (set.isStacked()) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = y; + + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + + return getStackedHighlight(set, h.getXIndex(), h.getDataSetIndex(), pts[1]); + } else + return h; + } + } + + @Override + protected int getXIndex(float x) { + + if(!mChart.getBarData().isGrouped()) { + return super.getXIndex(x); + } else { + + float baseNoSpace = getBase(x); + + int setCount = mChart.getBarData().getDataSetCount(); + int xIndex = (int) baseNoSpace / setCount; + + int valCount = mChart.getData().getXValCount(); + + if(xIndex < 0) + xIndex = 0; + else if(xIndex >= valCount) + xIndex = valCount - 1; + + return xIndex; + } + } + + @Override + protected int getDataSetIndex(int xIndex, float x, float y) { + + if(!mChart.getBarData().isGrouped()) { + return 0; + } else { + + float baseNoSpace = getBase(x); + + int setCount = mChart.getBarData().getDataSetCount(); + int dataSetIndex = (int) baseNoSpace % setCount; + + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; + + return dataSetIndex; + } + } + + /** + * This method creates the Highlight object that also indicates which value + * of a stacked BarEntry has been selected. + * + * @param set + * @param xIndex + * @param dataSetIndex + * @param yValue + * @return + */ + protected Highlight getStackedHighlight(BarDataSet set, int xIndex, int dataSetIndex, double yValue) { + + BarEntry entry = set.getEntryForXIndex(xIndex); + + if (entry != null) { + int stackIndex = getClosestStackIndex(entry, (float) yValue); + Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex); + return h; + } else + return null; + } + + /** + * Returns the index of the closest value inside the values array (for stacked barchart) + * to the value given as a parameter. + * + * @param e + * @param value + * @return + */ + protected int getClosestStackIndex(BarEntry e, float value) { + + Range[] ranges = getRanges(e); + int stackIndex = 0; + + for(Range range : ranges) { + if(range.contains(value)) + return stackIndex; + else + stackIndex++; + } + + int length = ranges.length - 1; + + return (value > ranges[length].to) ? length : 0; +// +// float[] vals = e.getVals(); +// +// if (vals == null) +// return -1; +// +// int index = 0; +// float remainder = e.getNegativeSum(); +// +// while (index < vals.length - 1 && value > vals[index] + remainder) { +// remainder += vals[index]; +// index++; +// } +// +// return index; + } + + /** + * Returns the base x-value to the corresponding x-touch value in pixels. + * @param x + * @return + */ + protected float getBase(float x) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + float xVal = pts[0]; + + int setCount = mChart.getBarData().getDataSetCount(); + + // calculate how often the group-space appears + int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); + + float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; + + float baseNoSpace = (float) xVal - groupSpaceSum; + return baseNoSpace; + } + + protected Range[] getRanges(BarEntry entry) { + + float[] values = entry.getVals(); + float negRemain = -entry.getNegativeSum(); + float posRemain = 0f; + + Range[] ranges = new Range[values.length]; + + for(int i = 0; i < ranges.length; i++) { + + float value = values[i]; + + if(value < 0) { + ranges[i] = new Range(negRemain, negRemain+Math.abs(value)); + negRemain += Math.abs(value); + } else { + ranges[i] = new Range(posRemain, posRemain+value); + posRemain += value; + } + } + + return ranges; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java new file mode 100644 index 0000000000..cb16420345 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -0,0 +1,144 @@ +package com.github.mikephil.charting.highlight; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.utils.SelectionDetail; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Philipp Jahoda on 21/07/15. + */ +public class ChartHighlighter { + + /** instance of the data-provider */ + protected T mChart; + + public ChartHighlighter(T chart) { + this.mChart = chart; + } + + /** + * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. + * @param x + * @param y + * @return + */ + public Highlight getHighlight(float x, float y) { + + int xIndex = getXIndex(x); + if (xIndex == -Integer.MAX_VALUE) + return null; + + int dataSetIndex = getDataSetIndex(xIndex, x, y); + if (dataSetIndex == -Integer.MAX_VALUE) + return null; + + return new Highlight(xIndex, dataSetIndex); + } + + /** + * Returns the corresponding x-index for a given touch-position in pixels. + * @param x + * @return + */ + protected int getXIndex(float x) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + + return (int) Math.round(pts[0]); + +// double xTouchVal = pts[0]; +// +// double base = Math.floor(xTouchVal); +// +// // touch out of chart +// if (xTouchVal < -mChart.getXChartMin() || xTouchVal > mChart.getXChartMax()) +// return -Integer.MAX_VALUE; +// +// if (base < 0) +// base = 0; +// +// int xIndex = (int) base; +// +// // check if we are more than half of a x-value or not +// if (xTouchVal - base > 0.5) { +// xIndex = (int) base + 1; +// } +// +// int valCount = mChart.getData().getXValCount(); +// +// if(xIndex < 0) +// xIndex = 0; +// else if(xIndex >= valCount) +// xIndex = valCount - 1; +// +// return xIndex; + } + + /** + * Returns the corresponding dataset-index for a given xIndex and xy-touch position in pixels. + * @param xIndex + * @param x + * @param y + * @return + */ + protected int getDataSetIndex(int xIndex, float x, float y) { + + List valsAtIndex = getSelectionDetailsAtIndex(xIndex); + + float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); + float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); + + YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; + + int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); + + return dataSetIndex; + } + + /** + * Returns a list of SelectionDetail object corresponding to the given xIndex. + * @param xIndex + * @return + */ + protected List getSelectionDetailsAtIndex(int xIndex) { + + List vals = new ArrayList(); + + float[] pts = new float[2]; + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + DataSet dataSet = mChart.getData().getDataSetByIndex(i); + + // dont include datasets that cannot be highlighted + if(!dataSet.isHighlightEnabled()) + continue; + + // extract all y-values from all DataSets at the given x-index + final float yVal = dataSet.getYValForXIndex(xIndex); + if (yVal == Float.NaN) + continue; + + pts[1] = yVal; + + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + + if (!Float.isNaN(pts[1])) { + vals.add(new SelectionDetail(pts[1], i, dataSet)); + } + } + + return vals; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java rename to MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java index 63c4457d34..b45868154c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Highlight.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java @@ -1,5 +1,5 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.highlight; /** * Contains information needed to determine the highlighted value. diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java new file mode 100644 index 0000000000..e14e85e40d --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -0,0 +1,100 @@ +package com.github.mikephil.charting.highlight; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.BarDataProvider; + +/** + * Created by Philipp Jahoda on 22/07/15. + */ +public class HorizontalBarHighlighter extends BarHighlighter { + + public HorizontalBarHighlighter(BarDataProvider chart) { + super(chart); + } + + @Override + public Highlight getHighlight(float x, float y) { + + Highlight h = super.getHighlight(x, y); + + if(h == null) + return h; + else { + + BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + + if (set.isStacked()) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = y; + + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + + return getStackedHighlight(set, h.getXIndex(), h.getDataSetIndex(), pts[0]); + } else + return h; + } + } + + @Override + protected int getXIndex(float x) { + + if(!mChart.getBarData().isGrouped()) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = x; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + + return (int) Math.round(pts[1]); + } else { + + float baseNoSpace = getBase(x); + + int setCount = mChart.getBarData().getDataSetCount(); + int xIndex = (int) baseNoSpace / setCount; + + int valCount = mChart.getData().getXValCount(); + + if(xIndex < 0) + xIndex = 0; + else if(xIndex >= valCount) + xIndex = valCount - 1; + + return xIndex; + } + } + + /** + * Returns the base y-value to the corresponding x-touch value in pixels. + * @param y + * @return + */ + @Override + protected float getBase(float y) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = y; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + float yVal = pts[1]; + + int setCount = mChart.getBarData().getDataSetCount(); + + // calculate how often the group-space appears + int steps = (int) ((float) yVal / ((float) setCount + mChart.getBarData().getGroupSpace())); + + float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; + + float baseNoSpace = (float) yVal - groupSpaceSum; + return baseNoSpace; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java new file mode 100644 index 0000000000..f4fda33e61 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java @@ -0,0 +1,37 @@ +package com.github.mikephil.charting.highlight; + +/** + * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one value in a stacked bar entry. + * e.g. stack values are -10, 5, 20 -> then ranges are (-10 - 0, 0 - 5, 5 - 25). + */ +public final class Range { + + float from; + float to; + + public Range(float from, float to) { + this.from = from; + this.to = to; + } + + /** + * Returns true if this range contains (if the value is in between) the given value, false if not. + * @param value + * @return + */ + public boolean contains(float value) { + + if(value > from && value <= to) + return true; + else + return false; + } + + public boolean isLarger(float value) { + return value > to; + } + + public boolean isSmaller(float value) { + return value < from; + } +} \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java index 6b9b19da8d..fa79672256 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.BarData; -public interface BarDataProvider extends BarLineScatterCandleDataProvider { +public interface BarDataProvider extends BarLineScatterCandleBubbleDataProvider { public BarData getBarData(); public boolean isDrawBarShadowEnabled(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java similarity index 67% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java index 368f87c1ca..1af33d86e2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java @@ -1,9 +1,10 @@ package com.github.mikephil.charting.interfaces; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.utils.Transformer; -public interface BarLineScatterCandleDataProvider extends ChartInterface { +public interface BarLineScatterCandleBubbleDataProvider extends ChartInterface { public Transformer getTransformer(AxisDependency axis); public int getMaxVisibleCount(); @@ -11,4 +12,6 @@ public interface BarLineScatterCandleDataProvider extends ChartInterface { public int getLowestVisibleXIndex(); public int getHighestVisibleXIndex(); + + public BarLineScatterCandleData getData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java index 2161303e01..47bddc83ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java @@ -2,8 +2,7 @@ import com.github.mikephil.charting.data.BubbleData; -public interface BubbleDataProvider extends BarLineScatterCandleDataProvider { +public interface BubbleDataProvider extends BarLineScatterCandleBubbleDataProvider { public BubbleData getBubbleData(); - } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java index 7e58121f8f..077101a705 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.CandleData; -public interface CandleDataProvider extends BarLineScatterCandleDataProvider { +public interface CandleDataProvider extends BarLineScatterCandleBubbleDataProvider { public CandleData getCandleData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index c24b50a36e..ee9d50c620 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -4,6 +4,7 @@ import android.graphics.PointF; import android.graphics.RectF; +import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.utils.ValueFormatter; /** @@ -35,4 +36,6 @@ public interface ChartInterface { public RectF getContentRect(); public ValueFormatter getDefaultValueFormatter(); + + public ChartData getData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java index 479e0d86bc..d6704f37e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -4,7 +4,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.utils.FillFormatter; -public interface LineDataProvider extends BarLineScatterCandleDataProvider { +public interface LineDataProvider extends BarLineScatterCandleBubbleDataProvider { public LineData getLineData(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java index a5570f1483..121ee43ea9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.ScatterData; -public interface ScatterDataProvider extends BarLineScatterCandleDataProvider { +public interface ScatterDataProvider extends BarLineScatterCandleBubbleDataProvider { public ScatterData getScatterData(); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index aeee83187c..6326399c0d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -5,12 +5,9 @@ import android.graphics.Matrix; import android.graphics.PointF; import android.util.Log; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; -import android.view.View.OnTouchListener; import android.view.animation.AnimationUtils; import com.github.mikephil.charting.charts.BarLineChartBase; @@ -19,7 +16,7 @@ import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java index fc607cd210..161731d319 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -1,11 +1,10 @@ package com.github.mikephil.charting.listener; import android.view.GestureDetector; -import android.view.MotionEvent; import android.view.View; import com.github.mikephil.charting.charts.Chart; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; /** * Created by philipp on 12/06/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 798d19f34f..8d8c4a070a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -2,7 +2,7 @@ package com.github.mikephil.charting.listener; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; /** * Listener for callbacks when selecting values inside the chart by diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index af62892344..3df80403a6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.charts.PieRadarChartBase; import com.github.mikephil.charting.charts.RadarChart; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index ea912a7c9f..4d994b4a09 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -14,7 +14,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ValueFormatter; @@ -190,6 +190,9 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); // calculate the correct offset depending on the draw position of @@ -198,15 +201,11 @@ public void drawValues(Canvas c) { posOffset = (drawValueAboveBar ? -valueOffsetPlus : valueTextHeight + valueOffsetPlus); negOffset = (drawValueAboveBar ? valueTextHeight + valueOffsetPlus : -valueOffsetPlus); - if (isInverted) - { + if (isInverted) { posOffset = -posOffset - valueTextHeight; negOffset = -negOffset - valueTextHeight; } - // apply the text-styling defined by the DataSet - applyValueTextStyle(dataSet); - ValueFormatter formatter = dataSet.getValueFormatter(); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 6e7035549d..7c98b77a4a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.BubbleDataProvider; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 74863d3125..ce410f1a8b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -2,7 +2,6 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import com.github.mikephil.charting.animation.ChartAnimator; @@ -14,7 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.CandleDataProvider; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 32f92968bf..2e098ce5a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -6,8 +6,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.ArrayList; @@ -107,7 +107,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } @Override - public void calcXBounds(BarLineScatterCandleDataProvider chart, int xAxisModulus) { + public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { for (DataRenderer renderer : mRenderers) renderer.calcXBounds(chart, xAxisModulus); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 68a9615005..12e2c121f1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 7270969cdc..637a4ab106 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -25,8 +25,6 @@ */ public class HorizontalBarChartRenderer extends BarChartRenderer { - private float mYOffset = 0f; - public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(chart, animator, viewPortHandler); @@ -103,12 +101,7 @@ public void drawValues(Canvas c) { final float valueOffsetPlus = Utils.convertDpToPixel(5f); float posOffset = 0f; float negOffset = 0f; - boolean drawValueAboveBar = mChart.isDrawValueAboveBarEnabled(); - - if (drawValueAboveBar) - mValuePaint.setTextAlign(Align.LEFT); - else - mValuePaint.setTextAlign(Align.RIGHT); + final boolean drawValueAboveBar = mChart.isDrawValueAboveBarEnabled(); for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { @@ -121,8 +114,7 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - - mYOffset = Utils.calcTextHeight(mValuePaint, "10") / 2f; + final float halfTextHeight = Utils.calcTextHeight(mValuePaint, "10") / 2f; ValueFormatter formatter = dataSet.getValueFormatter(); @@ -160,7 +152,7 @@ public void drawValues(Canvas c) { } drawValue(c, valueText, valuePoints[j] + (val >= 0 ? posOffset : negOffset), - valuePoints[j + 1]); + valuePoints[j + 1] + halfTextHeight); } // if each value of a potential stack should be drawn @@ -201,14 +193,14 @@ public void drawValues(Canvas c) { drawValue(c, valueText, valuePoints[j] + (e.getVal() >= 0 ? posOffset : negOffset), - valuePoints[j + 1]); + valuePoints[j + 1] + halfTextHeight); } else { float[] transformed = new float[vals.length * 2]; float posY = 0f; - float negY = 0f; + float negY = -e.getNegativeSum(); for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { @@ -219,8 +211,8 @@ public void drawValues(Canvas c) { posY += value; y = posY; } else { - negY += value; y = negY; + negY -= value; } transformed[k] = y * mAnimator.getPhaseY(); @@ -256,7 +248,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(y)) continue; - drawValue(c, valueText, x, y); + drawValue(c, valueText, x, y + halfTextHeight); } } } @@ -286,11 +278,6 @@ public float[] getTransformedValues(Transformer trans, List entries, mChart.getBarData(), mAnimator.getPhaseY()); } - @Override - protected void drawValue(Canvas c, String value, float xPos, float yPos) { - super.drawValue(c, value, xPos, yPos + mYOffset); - } - @Override protected boolean passesCheck() { return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 86a57a9095..6587d32e63 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -14,7 +14,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.LineDataProvider; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index 2747f792d9..9927face1c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -3,9 +3,6 @@ import android.graphics.Canvas; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.data.LineScatterCandleRadarDataSet; -import com.github.mikephil.charting.utils.Highlight; import com.github.mikephil.charting.utils.ViewPortHandler; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 6764225934..4ce679b2ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -18,7 +18,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 473018a56c..be782af7f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index 6ea83adc52..b17c2da02c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.renderer; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleDataProvider; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -50,7 +50,7 @@ protected boolean fitsBounds(float val, float min, float max) { * @param chart * @param modulus */ - public void calcXBounds(BarLineScatterCandleDataProvider chart, int xAxisModulus) { + public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { int low = chart.getLowestVisibleXIndex(); int high = chart.getHighestVisibleXIndex(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 65af71999c..274250f760 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.interfaces.ScatterDataProvider; -import com.github.mikephil.charting.utils.Highlight; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -276,7 +276,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // y-position float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), 0, y, + xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, mChart.getXChartMax(), y }; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 695fc58ca6..f5ea05a052 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -424,7 +424,7 @@ public static double nextUp(double d) { /** * Returns the index of the DataSet that contains the closest value on the - * y-axis. This is needed for highlighting. + * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. * * @param valsAtIndex all the values at a specific index * @return @@ -432,7 +432,7 @@ public static double nextUp(double d) { public static int getClosestDataSetIndex(List valsAtIndex, float val, AxisDependency axis) { - int index = -1; + int index = -Integer.MAX_VALUE; float distance = Float.MAX_VALUE; for (int i = 0; i < valsAtIndex.size(); i++) { @@ -449,8 +449,6 @@ public static int getClosestDataSetIndex(List valsAtIndex, floa } } - // Log.i(LOG_TAG, "Closest DataSet index: " + index); - return index; } From 539a89446ff690e351995da9e27270e8e20f8b6f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 16:31:36 +0200 Subject: [PATCH 0432/1390] Improvements and bugfixes concerning highlighting. --- .../StackedBarActivityNegative.java | 2 +- .../charting/highlight/BarHighlighter.java | 23 +++++++++++----- .../charting/highlight/Highlight.java | 27 +++++++++++++++++-- .../mikephil/charting/highlight/Range.java | 4 +-- .../charting/renderer/BarChartRenderer.java | 11 ++++---- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 5cdd14fbcc..5b69a394ef 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -93,7 +93,7 @@ protected void onCreate(Bundle savedInstanceState) { set.setValueFormatter(new CustomFormatter()); set.setValueTextSize(7f); set.setAxisDependency(YAxis.AxisDependency.RIGHT); - set.setBarSpacePercent(50f); + set.setBarSpacePercent(40f); set.setColors(new int[] {Color.rgb(67,67,72), Color.rgb(124,181,236)}); set.setStackLabels(new String[]{ "Men", "Women" diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index d9727e5eb0..99a7282d9c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -102,24 +102,26 @@ protected Highlight getStackedHighlight(BarDataSet set, int xIndex, int dataSetI BarEntry entry = set.getEntryForXIndex(xIndex); if (entry != null) { - int stackIndex = getClosestStackIndex(entry, (float) yValue); - Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex); + + Range[] ranges = getRanges(entry); + int stackIndex = getClosestStackIndex(ranges, (float) yValue); + + Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); return h; } else return null; } /** - * Returns the index of the closest value inside the values array (for stacked barchart) + * Returns the index of the closest value inside the values array / ranges (stacked barchart) * to the value given as a parameter. * - * @param e + * @param ranges * @param value * @return */ - protected int getClosestStackIndex(BarEntry e, float value) { + protected int getClosestStackIndex(Range[] ranges, float value) { - Range[] ranges = getRanges(e); int stackIndex = 0; for(Range range : ranges) { @@ -175,9 +177,18 @@ protected float getBase(float x) { return baseNoSpace; } + /** + * Splits up the stack-values of the given bar-entry into Range objects. + * @param entry + * @return + */ protected Range[] getRanges(BarEntry entry) { float[] values = entry.getVals(); + + if(values == null) + return null; + float negRemain = -entry.getNegativeSum(); float posRemain = 0f; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java index b45868154c..07ae315eb1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Highlight.java @@ -17,11 +17,13 @@ public class Highlight { /** index which value of a stacked bar entry is highlighted, default -1 */ private int mStackIndex = -1; + /** the range of the bar that is selected (only for stacked-barchart) */ + private Range mRange; + /** * constructor * * @param x the index of the highlighted value on the x-axis - * @param val the value at the position the user touched * @param dataSet the index of the DataSet the highlighted value belongs to */ public Highlight(int x, int dataSet) { @@ -33,7 +35,6 @@ public Highlight(int x, int dataSet) { * Constructor, only used for stacked-barchart. * * @param x the index of the highlighted value on the x-axis - * @param val the value at the position the user touched * @param dataSet the index of the DataSet the highlighted value belongs to * @param stackIndex references which value of a stacked-bar entry has been * selected @@ -43,6 +44,20 @@ public Highlight(int x, int dataSet, int stackIndex) { mStackIndex = stackIndex; } + /** + * Constructor, only used for stacked-barchart. + * + * @param x the index of the highlighted value on the x-axis + * @param dataSet the index of the DataSet the highlighted value belongs to + * @param stackIndex references which value of a stacked-bar entry has been + * selected + * @param range the range the selected stack-value is in + */ + public Highlight(int x, int dataSet, int stackIndex, Range range) { + this(x, dataSet, stackIndex); + this.mRange = range; + } + /** * returns the index of the DataSet the highlighted value is in * @@ -71,6 +86,14 @@ public int getStackIndex() { return mStackIndex; } + /** + * Returns the range of values the selected value of a stacked bar is in. (this is only relevant for stacked-barchart) + * @return + */ + public Range getRange() { + return mRange; + } + /** * returns true if this highlight object is equal to the other (compares * xIndex and dataSetIndex) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java index f4fda33e61..069592c298 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java @@ -6,8 +6,8 @@ */ public final class Range { - float from; - float to; + public float from; + public float to; public Range(float from, float to) { this.from = from; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 8eb4d5d703..a07956ecdf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -317,10 +317,6 @@ protected void drawValue(Canvas c, String value, float xPos, float yPos) { mValuePaint); } - @Override - public void drawExtras(Canvas c) { - } - @Override public void drawHighlighted(Canvas c, Highlight[] indices) { @@ -364,8 +360,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float y2; if (isStack) { - y1 = e.getPositiveSum(); - y2 = -e.getNegativeSum(); + y1 = h.getRange().from; + y2 = h.getRange().to * mAnimator.getPhaseY(); } else { y1 = e.getVal(); y2 = 0.f; @@ -414,4 +410,7 @@ protected boolean passesCheck() { return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX(); } + + @Override + public void drawExtras(Canvas c) { } } From 8d529bd999359af7eada8ab6a5b0dccd3ecc362f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 17:02:01 +0200 Subject: [PATCH 0433/1390] Fix markerview position when stacked-bars. --- .../res/layout/frag_simple_line.xml | 4 +- MPChartExample/res/layout/frag_simple_pie.xml | 4 +- .../res/layout/frag_simple_scatter.xml | 4 +- .../mpchartexample/custom/MyMarkerView.java | 3 +- .../custom/StackedBarsMarkerView.java | 63 +++++++++++++++++++ .../charting/charts/BarLineChartBase.java | 12 +++- .../mikephil/charting/charts/Chart.java | 15 ++--- .../mikephil/charting/charts/PieChart.java | 3 +- .../mikephil/charting/charts/RadarChart.java | 3 +- .../charting/components/MarkerView.java | 25 ++++---- .../charting/highlight/BarHighlighter.java | 11 +++- .../highlight/HorizontalBarHighlighter.java | 2 +- 12 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java diff --git a/MPChartExample/res/layout/frag_simple_line.xml b/MPChartExample/res/layout/frag_simple_line.xml index ef1b69a35d..7a2757476b 100644 --- a/MPChartExample/res/layout/frag_simple_line.xml +++ b/MPChartExample/res/layout/frag_simple_line.xml @@ -6,7 +6,7 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/MPChartExample/res/layout/frag_simple_pie.xml b/MPChartExample/res/layout/frag_simple_pie.xml index ef63ff3382..ed490ddbe6 100644 --- a/MPChartExample/res/layout/frag_simple_pie.xml +++ b/MPChartExample/res/layout/frag_simple_pie.xml @@ -6,7 +6,7 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/MPChartExample/res/layout/frag_simple_scatter.xml b/MPChartExample/res/layout/frag_simple_scatter.xml index 53c3391526..2e42332db3 100644 --- a/MPChartExample/res/layout/frag_simple_scatter.xml +++ b/MPChartExample/res/layout/frag_simple_scatter.xml @@ -6,7 +6,7 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 0f21a17df9..836e7befb6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; import com.xxmassdeveloper.mpchartexample.R; @@ -28,7 +29,7 @@ public MyMarkerView(Context context, int layoutResource) { // callbacks everytime the MarkerView is redrawn, can be used to update the // content (user-interface) @Override - public void refreshContent(Entry e, int dataSetIndex) { + public void refreshContent(Entry e, Highlight highlight) { if (e instanceof CandleEntry) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java new file mode 100644 index 0000000000..3b3b5e186e --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -0,0 +1,63 @@ + +package com.xxmassdeveloper.mpchartexample.custom; + +import android.content.Context; +import android.widget.TextView; + +import com.github.mikephil.charting.components.MarkerView; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.utils.Utils; +import com.xxmassdeveloper.mpchartexample.R; + +/** + * Custom implementation of the MarkerView. + * + * @author Philipp Jahoda + */ +public class StackedBarsMarkerView extends MarkerView { + + private TextView tvContent; + + public StackedBarsMarkerView(Context context, int layoutResource) { + super(context, layoutResource); + + tvContent = (TextView) findViewById(R.id.tvContent); + } + + // callbacks everytime the MarkerView is redrawn, can be used to update the + // content (user-interface) + @Override + public void refreshContent(Entry e, Highlight highlight) { + + if (e instanceof BarEntry) { + + BarEntry be = (BarEntry) e; + + if(be.getVals() != null) { + + // draw the stack value + tvContent.setText("" + Utils.formatNumber(be.getVals()[highlight.getStackIndex()], 0, true)); + } else { + tvContent.setText("" + Utils.formatNumber(be.getVal(), 0, true)); + } + } else { + + tvContent.setText("" + Utils.formatNumber(e.getVal(), 0, true)); + } + } + + @Override + public int getXOffset() { + // this will center the marker-view horizontally + return -(getWidth() / 2); + } + + @Override + public int getYOffset() { + // this will cause the marker-view to be above the selected value + return -getHeight(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index e8354a3408..99af9f07d2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; import com.github.mikephil.charting.data.DataSet; @@ -522,9 +523,11 @@ protected void calcModulus() { } @Override - protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + protected float[] getMarkerPosition(Entry e, Highlight highlight) { + int dataSetIndex = highlight.getDataSetIndex(); float xPos = e.getXIndex(); + float yPos = e.getVal(); if (this instanceof BarChart) { @@ -537,11 +540,16 @@ protected float[] getMarkerPosition(Entry e, int dataSetIndex) { / 2f; xPos += x; + + BarEntry entry = (BarEntry) e; + if(entry.getVals() != null) { + yPos = highlight.getRange().to; + } } // position of the marker depends on selected value index and value float[] pts = new float[] { - xPos, e.getVal() * mAnimator.getPhaseY() + xPos, yPos * mAnimator.getPhaseY() }; getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 51db1e93e5..576d0a11df 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -587,8 +587,9 @@ protected void drawMarkers(Canvas canvas) { for (int i = 0; i < mIndicesToHightlight.length; i++) { - int xIndex = mIndicesToHightlight[i].getXIndex(); - int dataSetIndex = mIndicesToHightlight[i].getDataSetIndex(); + Highlight highlight = mIndicesToHightlight[i]; + int xIndex = highlight.getXIndex(); + int dataSetIndex = highlight.getDataSetIndex(); if (xIndex <= mDeltaX && xIndex <= mDeltaX * mAnimator.getPhaseX()) { @@ -598,14 +599,14 @@ protected void drawMarkers(Canvas canvas) { if (e == null || e.getXIndex() != mIndicesToHightlight[i].getXIndex()) continue; - float[] pos = getMarkerPosition(e, dataSetIndex); + float[] pos = getMarkerPosition(e, highlight); // check bounds if (!mViewPortHandler.isInBounds(pos[0], pos[1])) continue; // callbacks to update the content - mMarkerView.refreshContent(e, dataSetIndex); + mMarkerView.refreshContent(e, highlight); // mMarkerView.measure(MeasureSpec.makeMeasureSpec(0, // MeasureSpec.UNSPECIFIED), @@ -633,11 +634,11 @@ protected void drawMarkers(Canvas canvas) { * Returns the actual position in pixels of the MarkerView for the given * Entry in the given DataSet. * - * @param xIndex - * @param dataSetIndex + * @param e + * @param highlight * @return */ - protected abstract float[] getMarkerPosition(Entry e, int dataSetIndex); + protected abstract float[] getMarkerPosition(Entry e, Highlight highlight); /** * ################ ################ ################ ################ diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 5918cd0dd0..7ae3007149 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; @@ -144,7 +145,7 @@ protected void calcMinMax() { /** PieChart does not support MarkerView */ @Override - protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + protected float[] getMarkerPosition(Entry e, Highlight highlight) { return new float[0]; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index ee749362a9..5165995181 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.renderer.RadarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererRadarChart; import com.github.mikephil.charting.renderer.YAxisRendererRadarChart; @@ -112,7 +113,7 @@ protected void calcMinMax() { } @Override - protected float[] getMarkerPosition(Entry e, int dataSetIndex) { + protected float[] getMarkerPosition(Entry e, Highlight highlight) { float angle = getSliceAngle() * e.getXIndex() + getRotationAngle(); float val = e.getVal() * getFactor(); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index 14a0aed6c4..cbd64f161d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -8,18 +8,19 @@ import android.widget.RelativeLayout; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; /** * View that can be displayed when selecting values in the chart. Extend this * class to provide custom layouts for your markers. - * + * * @author Philipp Jahoda */ public abstract class MarkerView extends RelativeLayout { /** * Constructor. Sets up the MarkerView with a custom layout resource. - * + * * @param context * @param layoutResource the layout resource to use for the MarkerView */ @@ -30,7 +31,7 @@ public MarkerView(Context context, int layoutResource) { /** * Sets the layout resource for a custom MarkerView. - * + * * @param layoutResource */ private void setupLayoutResource(int layoutResource) { @@ -49,7 +50,7 @@ private void setupLayoutResource(int layoutResource) { /** * Draws the MarkerView on the given position on the screen with the given * Canvas object. - * + * * @param canvas * @param posx * @param posy @@ -69,19 +70,19 @@ public void draw(Canvas canvas, float posx, float posy) { /** * This method enables a specified custom MarkerView to update it's content * everytime the MarkerView is redrawn. - * - * @param e The Entry the MarkerView belongs to. This can also be any - * subclass of Entry, like BarEntry or CandleEntry, simply cast - * it at runtime. - * @param dataSetIndex the index of the DataSet the selected value is in + * + * @param e The Entry the MarkerView belongs to. This can also be any + * subclass of Entry, like BarEntry or CandleEntry, simply cast + * it at runtime. + * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the selected range or stack-index (only stacked bar entries). */ - public abstract void refreshContent(Entry e, int dataSetIndex); + public abstract void refreshContent(Entry e, Highlight highlight); /** * Use this to return the desired offset you wish the MarkerView to have on * the x-axis. By returning -(getWidth() / 2) you will center the MarkerView * horizontally. - * + * * @return */ public abstract int getXOffset(); @@ -90,7 +91,7 @@ public void draw(Canvas canvas, float posx, float posy) { * Use this to return the desired position offset you wish the MarkerView to * have on the y-axis. By returning -getHeight() you will cause the * MarkerView to be above the selected value. - * + * * @return */ public abstract int getYOffset(); diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 99a7282d9c..37dcf12add 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -37,7 +37,7 @@ public Highlight getHighlight(float x, float y) { // take any transformer to determine the x-axis value mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(set, h.getXIndex(), h.getDataSetIndex(), pts[1]); + return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[1]); } else return h; } @@ -91,16 +91,20 @@ else if (dataSetIndex >= setCount) * This method creates the Highlight object that also indicates which value * of a stacked BarEntry has been selected. * + * @param old the old highlight object before looking for stacked values * @param set * @param xIndex * @param dataSetIndex * @param yValue * @return */ - protected Highlight getStackedHighlight(BarDataSet set, int xIndex, int dataSetIndex, double yValue) { + protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xIndex, int dataSetIndex, double yValue) { BarEntry entry = set.getEntryForXIndex(xIndex); + if(entry.getVals() == null) + return old; + if (entry != null) { Range[] ranges = getRanges(entry); @@ -122,6 +126,9 @@ protected Highlight getStackedHighlight(BarDataSet set, int xIndex, int dataSetI */ protected int getClosestStackIndex(Range[] ranges, float value) { + if(ranges == null) + return 0; + int stackIndex = 0; for(Range range : ranges) { diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index e14e85e40d..8ec8027eef 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -34,7 +34,7 @@ public Highlight getHighlight(float x, float y) { // take any transformer to determine the x-axis value mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(set, h.getXIndex(), h.getDataSetIndex(), pts[0]); + return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[0]); } else return h; } From 5d19d4b1bc3227a73dd2b40d2383e55a6a887201 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 17:03:08 +0200 Subject: [PATCH 0434/1390] Code cleanup. --- .../mpchartexample/HorizontalBarChartActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 2a6dd419c4..c98eb2ad8b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -248,7 +248,7 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = (range + 1); float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(new float[] {val, val+5, val+5,val+5}, i)); + yVals1.add(new BarEntry(val, i)); } BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); From bc2c4e2b68b269f65aebe45d43a184d39d5dd3b3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 19:03:59 +0200 Subject: [PATCH 0435/1390] Fixed #868 --- MPChartExample/build.gradle | 2 +- .../src/com/github/mikephil/charting/data/DataSet.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 9fe37e0e91..05533d086d 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -6,7 +6,7 @@ android { defaultConfig { minSdkVersion 8 targetSdkVersion 21 - versionCode 41 + versionCode 42 versionName '2.1.1' sourceSets { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 902d032fdc..f59593772a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -129,6 +129,9 @@ protected void calcMinMax(int start, int end) { for (int i = start; i <= endValue; i++) { + if(i >= mYVals.size()) + break; + Entry e = mYVals.get(i); if (e != null && !Float.isNaN(e.getVal())) { @@ -249,7 +252,7 @@ public int getEntryIndex(int x) { * does calculations at runtime. Do not over-use in performance critical * situations. * - * @param xIndex + * @param x * @return */ public List getEntriesForXIndex(int x) { From a09d6a7ac111f9e6614592d3f77c5a6836f7ab18 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 19:31:05 +0200 Subject: [PATCH 0436/1390] Code cleanup & bugfixing. --- .../mikephil/charting/charts/BarChart.java | 545 ++++++++---------- .../charting/charts/BarLineChartBase.java | 88 --- .../charting/charts/HorizontalBarChart.java | 404 ++++++------- .../charting/components/MarkerView.java | 136 +++-- .../charting/highlight/BarHighlighter.java | 383 ++++++------ .../charting/highlight/ChartHighlighter.java | 236 ++++---- .../highlight/HorizontalBarHighlighter.java | 126 ++-- .../mikephil/charting/highlight/Range.java | 51 +- 8 files changed, 870 insertions(+), 1099 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index eff4ffccc0..6f83efd179 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.charts; import android.content.Context; @@ -13,10 +12,10 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.BarHighlighter; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; -import com.github.mikephil.charting.highlight.Highlight; /** * Chart that draws bars. @@ -25,316 +24,234 @@ */ public class BarChart extends BarLineChartBase implements BarDataProvider { - /** flag that enables or disables the highlighting arrow */ - private boolean mDrawHighlightArrow = false; - - /** - * if set to true, all values are drawn above their bars, instead of below - * their top - */ - private boolean mDrawValueAboveBar = true; - - /** - * if set to true, all values of a stack are drawn individually, and not - * just their sum - */ - //private boolean mDrawValuesForWholeStack = true; - - /** - * if set to true, a grey area is drawn behind each bar that indicates the - * maximum value - */ - private boolean mDrawBarShadow = false; - - public BarChart(Context context) { - super(context); - } - - public BarChart(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public BarChart(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void init() { - super.init(); - - mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); - mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, - this); - - mHighlighter = new BarHighlighter(this); - - mXChartMin = -0.5f; - } - - @Override - protected void calcMinMax() { - super.calcMinMax(); - - // increase deltax by 1 because the bars have a width of 1 - mDeltaX += 0.5f; - - // extend xDelta to make space for multiple datasets (if ther are one) - mDeltaX *= mData.getDataSetCount(); - - int maxEntry = 0; - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - DataSet set = mData.getDataSetByIndex(i); - - if (maxEntry < set.getEntryCount()) - maxEntry = set.getEntryCount(); - } - - float groupSpace = mData.getGroupSpace(); - mDeltaX += maxEntry * groupSpace; - mXChartMax = mDeltaX - mXChartMin; - } - - /** - * Returns the Highlight object (contains x-index and DataSet index) of the - * selected value at the given touch point inside the BarChart. - * - * @param x - * @param y - * @return - */ - @Override - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mDataNotSet || mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else - return mHighlighter.getHighlight(x, y); - } - - /** - * Returns the correct Highlight object (including xIndex and dataSet-index) - * for the specified touch position. - * - * @param xPosition - * @return - */ - protected Highlight getHighlight(double xPosition, double yPosition) { - -// int setCount = mData.getDataSetCount(); -// int valCount = mData.getXValCount(); -// int dataSetIndex = 0; -// int xIndex = 0; -// -// // only one dataset exists -// if (!mData.isGrouped()) { -// -// xIndex = (int) Math.round(xPosition); -// -// // check bounds -// if (xIndex < 0) { -// xIndex = 0; -// } else if (xIndex >= valCount) { -// xIndex = valCount - 1; -// } -// -// // if this bardata is grouped into more datasets -// } else { -// -// // calculate how often the group-space appears -// int steps = (int) ((float) xPosition / ((float) setCount + mData.getGroupSpace())); -// -// float groupSpaceSum = mData.getGroupSpace() * (float) steps; -// -// float baseNoSpace = (float) xPosition - groupSpaceSum; -// -// if (mLogEnabled) -// Log.i(LOG_TAG, "base: " + xPosition + ", steps: " + steps + ", groupSpaceSum: " -// + groupSpaceSum -// + ", baseNoSpace: " + baseNoSpace); -// -// dataSetIndex = (int) baseNoSpace % setCount; -// xIndex = (int) baseNoSpace / setCount; -// -// if (mLogEnabled) -// Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); -// -// // check bounds -// if (xIndex < 0) { -// xIndex = 0; -// dataSetIndex = 0; -// } else if (xIndex >= valCount) { -// xIndex = valCount - 1; -// dataSetIndex = setCount - 1; -// } -// -// // check bounds -// if (dataSetIndex < 0) -// dataSetIndex = 0; -// else if (dataSetIndex >= setCount) -// dataSetIndex = setCount - 1; -// } -// -// if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) -// return new Highlight(xIndex, dataSetIndex); -// else -// return getStackedHighlight(xIndex, dataSetIndex, yPosition); - return null; - } - - /** - * Returns the bounding box of the specified Entry in the specified DataSet. - * Returns null if the Entry could not be found in the charts data. - * - * @param e - * @return - */ - public RectF getBarBounds(BarEntry e) { - - BarDataSet set = mData.getDataSetForEntry(e); - - if (set == null) - return null; - - float barspace = set.getBarSpace(); - float y = e.getVal(); - float x = e.getXIndex(); - - float barWidth = 0.5f; - - float spaceHalf = barspace / 2f; - float left = x - barWidth + spaceHalf; - float right = x + barWidth - spaceHalf; - float top = y >= 0 ? y : 0; - float bottom = y <= 0 ? y : 0; - - RectF bounds = new RectF(left, top, right, bottom); - - getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - - return bounds; - } - - /** - * set this to true to draw the highlightning arrow - * - * @param enabled - */ - public void setDrawHighlightArrow(boolean enabled) { - mDrawHighlightArrow = enabled; - } - - /** - * returns true if drawing the highlighting arrow is enabled, false if not - * - * @return - */ - public boolean isDrawHighlightArrowEnabled() { - return mDrawHighlightArrow; - } - - /** - * If set to true, all values are drawn above their bars, instead of below - * their top. - * - * @param enabled - */ - public void setDrawValueAboveBar(boolean enabled) { - mDrawValueAboveBar = enabled; - } - - /** - * returns true if drawing values above bars is enabled, false if not - * - * @return - */ - public boolean isDrawValueAboveBarEnabled() { - return mDrawValueAboveBar; - } - -// /** -// * if set to true, all values of a stack are drawn individually, and not -// * just their sum -// * -// * @param enabled -// */ -// public void setDrawValuesForWholeStack(boolean enabled) { -// mDrawValuesForWholeStack = enabled; -// } -// -// /** -// * returns true if all values of a stack are drawn, and not just their sum -// * -// * @return -// */ -// public boolean isDrawValuesForWholeStackEnabled() { -// return mDrawValuesForWholeStack; -// } - - /** - * If set to true, a grey area is drawn behind each bar that indicates the - * maximum value. Enabling his will reduce performance by about 50%. - * - * @param enabled - */ - public void setDrawBarShadow(boolean enabled) { - mDrawBarShadow = enabled; - } - - /** - * returns true if drawing shadows (maxvalue) for each bar is enabled, false - * if not - * - * @return - */ - public boolean isDrawBarShadowEnabled() { - return mDrawBarShadow; - } - - @Override - public BarData getBarData() { - return mData; - } - - /** - * Returns the lowest x-index (value on the x-axis) that is still visible on - * the chart. - * - * @return - */ - @Override - public int getLowestVisibleXIndex() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { - mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() - }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (int) ((pts[0] <= getXChartMin()) ? 0 : (pts[0] / div) + 1); - } - - /** - * Returns the highest x-index (value on the x-axis) that is still visible - * on the chart. - * - * @return - */ - @Override - public int getHighestVisibleXIndex() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { - mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() - }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (int) ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); - } + /** flag that enables or disables the highlighting arrow */ + private boolean mDrawHighlightArrow = false; + + /** + * if set to true, all values are drawn above their bars, instead of below their top + */ + private boolean mDrawValueAboveBar = true; + + /** + * if set to true, all values of a stack are drawn individually, and not just their sum + */ + // private boolean mDrawValuesForWholeStack = true; + + /** + * if set to true, a grey area is drawn behind each bar that indicates the maximum value + */ + private boolean mDrawBarShadow = false; + + public BarChart(Context context) { + super(context); + } + + public BarChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BarChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); + mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + + mHighlighter = new BarHighlighter(this); + + mXChartMin = -0.5f; + } + + @Override + protected void calcMinMax() { + super.calcMinMax(); + + // increase deltax by 1 because the bars have a width of 1 + mDeltaX += 0.5f; + + // extend xDelta to make space for multiple datasets (if ther are one) + mDeltaX *= mData.getDataSetCount(); + + int maxEntry = 0; + + for (int i = 0; i < mData.getDataSetCount(); i++) { + + DataSet set = mData.getDataSetByIndex(i); + + if (maxEntry < set.getEntryCount()) + maxEntry = set.getEntryCount(); + } + + float groupSpace = mData.getGroupSpace(); + mDeltaX += maxEntry * groupSpace; + mXChartMax = mDeltaX - mXChartMin; + } + + /** + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point + * inside the BarChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { + + if (mDataNotSet || mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else + return mHighlighter.getHighlight(x, y); + } + + /** + * Returns the bounding box of the specified Entry in the specified DataSet. Returns null if the Entry could not be + * found in the charts data. + * + * @param e + * @return + */ + public RectF getBarBounds(BarEntry e) { + + BarDataSet set = mData.getDataSetForEntry(e); + + if (set == null) + return null; + + float barspace = set.getBarSpace(); + float y = e.getVal(); + float x = e.getXIndex(); + + float barWidth = 0.5f; + + float spaceHalf = barspace / 2f; + float left = x - barWidth + spaceHalf; + float right = x + barWidth - spaceHalf; + float top = y >= 0 ? y : 0; + float bottom = y <= 0 ? y : 0; + + RectF bounds = new RectF(left, top, right, bottom); + + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); + + return bounds; + } + + /** + * set this to true to draw the highlightning arrow + * + * @param enabled + */ + public void setDrawHighlightArrow(boolean enabled) { + mDrawHighlightArrow = enabled; + } + + /** + * returns true if drawing the highlighting arrow is enabled, false if not + * + * @return + */ + public boolean isDrawHighlightArrowEnabled() { + return mDrawHighlightArrow; + } + + /** + * If set to true, all values are drawn above their bars, instead of below their top. + * + * @param enabled + */ + public void setDrawValueAboveBar(boolean enabled) { + mDrawValueAboveBar = enabled; + } + + /** + * returns true if drawing values above bars is enabled, false if not + * + * @return + */ + public boolean isDrawValueAboveBarEnabled() { + return mDrawValueAboveBar; + } + + // /** + // * if set to true, all values of a stack are drawn individually, and not + // * just their sum + // * + // * @param enabled + // */ + // public void setDrawValuesForWholeStack(boolean enabled) { + // mDrawValuesForWholeStack = enabled; + // } + // + // /** + // * returns true if all values of a stack are drawn, and not just their sum + // * + // * @return + // */ + // public boolean isDrawValuesForWholeStackEnabled() { + // return mDrawValuesForWholeStack; + // } + + /** + * If set to true, a grey area is drawn behind each bar that indicates the maximum value. Enabling his will reduce + * performance by about 50%. + * + * @param enabled + */ + public void setDrawBarShadow(boolean enabled) { + mDrawBarShadow = enabled; + } + + /** + * returns true if drawing shadows (maxvalue) for each bar is enabled, false if not + * + * @return + */ + public boolean isDrawBarShadowEnabled() { + return mDrawBarShadow; + } + + @Override + public BarData getBarData() { + return mData; + } + + /** + * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. + * + * @return + */ + @Override + public int getLowestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) ((pts[0] <= getXChartMin()) ? 0 : (pts[0] / div) + 1); + } + + /** + * Returns the highest x-index (value on the x-axis) that is still visible on the chart. + * + * @return + */ + @Override + public int getHighestVisibleXIndex() { + + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); + + float[] pts = new float[] { mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; + + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) ((pts[0] >= getXChartMax()) ? getXChartMax() / div : (pts[0] / div)); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 99af9f07d2..c3d1c72127 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -22,7 +22,6 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BarLineScatterCandleData; import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -37,7 +36,6 @@ import com.github.mikephil.charting.utils.FillFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.PointD; -import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -1090,92 +1088,6 @@ public Highlight getHighlightByTouchPoint(float x, float y) { return null; } else return mHighlighter.getHighlight(x, y); - -// // create an array of the touch-point -// float[] pts = new float[2]; -// pts[0] = x; -// -// // take any transformer to determine the x-axis value -// mLeftAxisTransformer.pixelsToValue(pts); -// -// double xTouchVal = pts[0]; -// double base = Math.floor(xTouchVal); -// -// double touchOffset = mDeltaX * 0.025; -// -// // touch out of chart -// if (xTouchVal < -touchOffset || xTouchVal > mDeltaX + touchOffset) -// return null; -// -// if (base < 0) -// base = 0; -// if (base >= mDeltaX) -// base = mDeltaX - 1; -// -// int xIndex = (int) base; -// -// // check if we are more than half of a x-value or not -// if (xTouchVal - base > 0.5) { -// xIndex = (int) base + 1; -// } -// -// List valsAtIndex = getSelectionDetailsAtIndex(xIndex); -// -// float leftdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.LEFT); -// float rightdist = Utils.getMinimumDistance(valsAtIndex, y, AxisDependency.RIGHT); -// -// if (mData.getFirstRight() == null) -// rightdist = Float.MAX_VALUE; -// if (mData.getFirstLeft() == null) -// leftdist = Float.MAX_VALUE; -// -// AxisDependency axis = leftdist < rightdist ? AxisDependency.LEFT : AxisDependency.RIGHT; -// -// int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); -// -// if (dataSetIndex == -1) -// return null; -// -// return new Highlight(xIndex, dataSetIndex); - } - - /** - * Returns an array of SelectionDetail objects for the given x-index. The SelectionDetail - * objects give information about the value at the selected index and the - * DataSet it belongs to. INFORMATION: This method does calculations at - * runtime. Do not over-use in performance critical situations. - * - * @return - */ - protected List getSelectionDetailsAtIndex(int xIndex) { - - List vals = new ArrayList(); - - float[] pts = new float[2]; - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - DataSet dataSet = mData.getDataSetByIndex(i); - - // dont include datasets that cannot be highlighted - if(!dataSet.isHighlightEnabled()) - continue; - - // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValForXIndex(xIndex); - if (yVal == Float.NaN) - continue; - - pts[1] = yVal; - - getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], i, dataSet)); - } - } - - return vals; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 6894a1d666..44f316554d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.charts; import android.content.Context; @@ -14,262 +13,233 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.HorizontalBarHighlighter; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.TransformerHorizontalBarChart; import com.github.mikephil.charting.utils.Utils; /** - * BarChart with horizontal bar orientation. In this implementation, x- and - * y-axis are switched, meaning the YAxis class represents the horizontal values - * and the XAxis class represents the vertical values. + * BarChart with horizontal bar orientation. In this implementation, x- and y-axis are switched, meaning the YAxis class + * represents the horizontal values and the XAxis class represents the vertical values. * * @author Philipp Jahoda */ public class HorizontalBarChart extends BarChart { - public HorizontalBarChart(Context context) { - super(context); - } + public HorizontalBarChart(Context context) { + super(context); + } + + public HorizontalBarChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public HorizontalBarChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init() { + super.init(); + + mLeftAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); + mRightAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); + + mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler); + mHighlighter = new HorizontalBarHighlighter(this); + + mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); + mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, mRightAxisTransformer); + mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); + } + + @Override + public void calculateOffsets() { + + float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; + + // setup offsets for legend + if (mLegend != null && mLegend.isEnabled()) { + + if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { + + offsetRight += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset() * 2f; + + } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART + || mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) { + + offsetLeft += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + + mLegend.getXOffset() * 2f; + + } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + + float yOffset = mLegend.mTextHeightMax * 2.f; // It's possible that we do not need this offset anymore + // as it is available through the extraOffsets + offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + } + } + + // offsets for y-labels + if (mAxisLeft.needsOffset()) { + offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels()); + } + + if (mAxisRight.needsOffset()) { + offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getPaintAxisLabels()); + } + + float xlabelwidth = mXAxis.mLabelWidth; + + if (mXAxis.isEnabled()) { + + // offsets for x-labels + if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + + offsetLeft += xlabelwidth; + + } else if (mXAxis.getPosition() == XAxisPosition.TOP) { + + offsetRight += xlabelwidth; + + } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + + offsetLeft += xlabelwidth; + offsetRight += xlabelwidth; + } + } + + offsetTop += getExtraTopOffset(); + offsetRight += getExtraRightOffset(); + offsetBottom += getExtraBottomOffset(); + offsetLeft += getExtraLeftOffset(); + + float min = Utils.convertDpToPixel(10f); + + mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), Math.max(min, offsetRight), + Math.max(min, offsetBottom)); + + if (mLogEnabled) { + Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop + ", offsetRight: " + offsetRight + ", offsetBottom: " + + offsetBottom); + Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); + } - public HorizontalBarChart(Context context, AttributeSet attrs) { - super(context, attrs); - } + prepareOffsetMatrix(); + prepareValuePxMatrix(); + } - public HorizontalBarChart(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - } + @Override + protected void prepareValuePxMatrix() { + mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, mDeltaX, mXChartMin); + mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, mDeltaX, mXChartMin); + } - @Override - protected void init() { - super.init(); - - mLeftAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); - mRightAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); + @Override + protected void calcModulus() { + float[] values = new float[9]; + mViewPortHandler.getMatrixTouch().getValues(values); - mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler); - mHighlighter = new HorizontalBarHighlighter(this); + mXAxis.mAxisLabelModulus = (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelHeight) + / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); - mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft, - mLeftAxisTransformer); - mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, - mRightAxisTransformer); - mXAxisRenderer = new XAxisRendererHorizontalBarChart(mViewPortHandler, mXAxis, - mLeftAxisTransformer, this); - } + if (mXAxis.mAxisLabelModulus < 1) + mXAxis.mAxisLabelModulus = 1; + } - @Override - public void calculateOffsets() { + @Override + public RectF getBarBounds(BarEntry e) { - float offsetLeft = 0f, offsetRight = 0f, offsetTop = 0f, offsetBottom = 0f; + BarDataSet set = mData.getDataSetForEntry(e); - // setup offsets for legend - if (mLegend != null && mLegend.isEnabled()) { + if (set == null) + return null; - if (mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART - || mLegend.getPosition() == LegendPosition.RIGHT_OF_CHART_CENTER) { + float barspace = set.getBarSpace(); + float y = e.getVal(); + float x = e.getXIndex(); - offsetRight += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + mLegend.getXOffset() * 2f; + float spaceHalf = barspace / 2f; - } else if (mLegend.getPosition() == LegendPosition.LEFT_OF_CHART - || mLegend.getPosition() == LegendPosition.LEFT_OF_CHART_CENTER) { + float top = x - 0.5f + spaceHalf; + float bottom = x + 0.5f - spaceHalf; + float left = y >= 0 ? y : 0; + float right = y <= 0 ? y : 0; - offsetLeft += Math.min(mLegend.mNeededWidth, mViewPortHandler.getChartWidth() * mLegend.getMaxSizePercent()) + mLegend.getXOffset() * 2f; + RectF bounds = new RectF(left, top, right, bottom); - } else if (mLegend.getPosition() == LegendPosition.BELOW_CHART_LEFT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT - || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - float yOffset = mLegend.mTextHeightMax * 2.f; // It's possible that we do not need this offset anymore as it is available through the extraOffsets - offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); - } - } + return bounds; + } - // offsets for y-labels - if (mAxisLeft.needsOffset()) { - offsetTop += mAxisLeft.getRequiredHeightSpace(mAxisRendererLeft.getPaintAxisLabels()); - } + @Override + public PointF getPosition(Entry e, AxisDependency axis) { - if (mAxisRight.needsOffset()) { - offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight - .getPaintAxisLabels()); - } + if (e == null) + return null; - float xlabelwidth = mXAxis.mLabelWidth; + float[] vals = new float[] { e.getVal(), e.getXIndex() }; - if (mXAxis.isEnabled()) { + getTransformer(axis).pointValuesToPixel(vals); - // offsets for x-labels - if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + return new PointF(vals[0], vals[1]); + } - offsetLeft += xlabelwidth; + /** + * Returns the Highlight object (contains x-index and DataSet index) of the selected value at the given touch point + * inside the BarChart. + * + * @param x + * @param y + * @return + */ + @Override + public Highlight getHighlightByTouchPoint(float x, float y) { - } else if (mXAxis.getPosition() == XAxisPosition.TOP) { + if (mDataNotSet || mData == null) { + Log.e(LOG_TAG, "Can't select by touch. No data set."); + return null; + } else + return mHighlighter.getHighlight(y, x); // switch x and y + } - offsetRight += xlabelwidth; + /** + * Returns the lowest x-index (value on the x-axis) that is still visible on the chart. + * + * @return + */ + @Override + public int getLowestVisibleXIndex() { - } else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - offsetLeft += xlabelwidth; - offsetRight += xlabelwidth; - } - } + float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; - offsetTop += getExtraTopOffset(); - offsetRight += getExtraRightOffset(); - offsetBottom += getExtraBottomOffset(); - offsetLeft += getExtraLeftOffset(); + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); + } - float min = Utils.convertDpToPixel(10f); + /** + * Returns the highest x-index (value on the x-axis) that is still visible on the chart. + * + * @return + */ + @Override + public int getHighestVisibleXIndex() { - mViewPortHandler.restrainViewPort(Math.max(min, offsetLeft), Math.max(min, offsetTop), - Math.max(min, offsetRight), Math.max(min, offsetBottom)); + float step = mData.getDataSetCount(); + float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - if (mLogEnabled) { - Log.i(LOG_TAG, "offsetLeft: " + offsetLeft + ", offsetTop: " + offsetTop - + ", offsetRight: " + offsetRight + ", offsetBottom: " + offsetBottom); - Log.i(LOG_TAG, "Content: " + mViewPortHandler.getContentRect().toString()); - } + float[] pts = new float[] { mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() }; - prepareOffsetMatrix(); - prepareValuePxMatrix(); - } - - @Override - protected void prepareValuePxMatrix() { - mRightAxisTransformer.prepareMatrixValuePx(mAxisRight.mAxisMinimum, mAxisRight.mAxisRange, - mDeltaX, - mXChartMin); - mLeftAxisTransformer.prepareMatrixValuePx(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisRange, - mDeltaX, - mXChartMin); - } - - @Override - protected void calcModulus() { - float[] values = new float[9]; - mViewPortHandler.getMatrixTouch().getValues(values); - - mXAxis.mAxisLabelModulus = (int) Math - .ceil((mData.getXValCount() * mXAxis.mLabelHeight) - / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); - - if (mXAxis.mAxisLabelModulus < 1) - mXAxis.mAxisLabelModulus = 1; - } - - @Override - public RectF getBarBounds(BarEntry e) { - - BarDataSet set = mData.getDataSetForEntry(e); - - if (set == null) - return null; - - float barspace = set.getBarSpace(); - float y = e.getVal(); - float x = e.getXIndex(); - - float spaceHalf = barspace / 2f; - - float top = x - 0.5f + spaceHalf; - float bottom = x + 0.5f - spaceHalf; - float left = y >= 0 ? y : 0; - float right = y <= 0 ? y : 0; - - RectF bounds = new RectF(left, top, right, bottom); - - getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); - - return bounds; - } - - @Override - public PointF getPosition(Entry e, AxisDependency axis) { - - if (e == null) - return null; - - float[] vals = new float[] { - e.getVal(), e.getXIndex() - }; - - getTransformer(axis).pointValuesToPixel(vals); - - return new PointF(vals[0], vals[1]); - } - - /** - * Returns the Highlight object (contains x-index and DataSet index) of the - * selected value at the given touch point inside the BarChart. - * - * @param x - * @param y - * @return - */ - @Override - public Highlight getHighlightByTouchPoint(float x, float y) { - - if (mDataNotSet || mData == null) { - Log.e(LOG_TAG, "Can't select by touch. No data set."); - return null; - } else - return mHighlighter.getHighlight(y, x); // switch x and y - -// // create an array of the touch-point -// float[] pts = new float[2]; -// pts[0] = x; -// pts[1] = y; -// -// mLeftAxisTransformer.pixelsToValue(pts); -// -// if (pts[1] < mXChartMin || pts[1] > mXChartMax) -// return null; -// -// return getHighlight(pts[1], pts[0]); - } - - /** - * Returns the lowest x-index (value on the x-axis) that is still visible on - * the chart. - * - * @return - */ - @Override - public int getLowestVisibleXIndex() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { - mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() - }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (int) (((pts[1] <= 0) ? 0 : ((pts[1])) / div) + 1); - } - - /** - * Returns the highest x-index (value on the x-axis) that is still visible - * on the chart. - * - * @return - */ - @Override - public int getHighestVisibleXIndex() { - - float step = mData.getDataSetCount(); - float div = (step <= 1) ? 1 : step + mData.getGroupSpace(); - - float[] pts = new float[] { - mViewPortHandler.contentLeft(), mViewPortHandler.contentTop() - }; - - getTransformer(AxisDependency.LEFT).pixelsToValue(pts); - return (int) ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); - } + getTransformer(AxisDependency.LEFT).pixelsToValue(pts); + return (int) ((pts[1] >= getXChartMax()) ? getXChartMax() / div : (pts[1] / div)); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index cbd64f161d..7a65b7e236 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.components; import android.content.Context; @@ -11,88 +10,85 @@ import com.github.mikephil.charting.highlight.Highlight; /** - * View that can be displayed when selecting values in the chart. Extend this - * class to provide custom layouts for your markers. + * View that can be displayed when selecting values in the chart. Extend this class to provide custom layouts for your + * markers. * * @author Philipp Jahoda */ public abstract class MarkerView extends RelativeLayout { - /** - * Constructor. Sets up the MarkerView with a custom layout resource. - * - * @param context - * @param layoutResource the layout resource to use for the MarkerView - */ - public MarkerView(Context context, int layoutResource) { - super(context); - setupLayoutResource(layoutResource); - } + /** + * Constructor. Sets up the MarkerView with a custom layout resource. + * + * @param context + * @param layoutResource + * the layout resource to use for the MarkerView + */ + public MarkerView(Context context, int layoutResource) { + super(context); + setupLayoutResource(layoutResource); + } - /** - * Sets the layout resource for a custom MarkerView. - * - * @param layoutResource - */ - private void setupLayoutResource(int layoutResource) { + /** + * Sets the layout resource for a custom MarkerView. + * + * @param layoutResource + */ + private void setupLayoutResource(int layoutResource) { - View inflated = LayoutInflater.from(getContext()).inflate(layoutResource, this); + View inflated = LayoutInflater.from(getContext()).inflate(layoutResource, this); - inflated.setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT)); - inflated.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + inflated.setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); + inflated.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - // measure(getWidth(), getHeight()); - inflated.layout(0, 0, inflated.getMeasuredWidth(), inflated.getMeasuredHeight()); - } + // measure(getWidth(), getHeight()); + inflated.layout(0, 0, inflated.getMeasuredWidth(), inflated.getMeasuredHeight()); + } - /** - * Draws the MarkerView on the given position on the screen with the given - * Canvas object. - * - * @param canvas - * @param posx - * @param posy - */ - public void draw(Canvas canvas, float posx, float posy) { + /** + * Draws the MarkerView on the given position on the screen with the given Canvas object. + * + * @param canvas + * @param posx + * @param posy + */ + public void draw(Canvas canvas, float posx, float posy) { - // take offsets into consideration - posx += getXOffset(); - posy += getYOffset(); + // take offsets into consideration + posx += getXOffset(); + posy += getYOffset(); - // translate to the correct position and draw - canvas.translate(posx, posy); - draw(canvas); - canvas.translate(-posx, -posy); - } + // translate to the correct position and draw + canvas.translate(posx, posy); + draw(canvas); + canvas.translate(-posx, -posy); + } - /** - * This method enables a specified custom MarkerView to update it's content - * everytime the MarkerView is redrawn. - * - * @param e The Entry the MarkerView belongs to. This can also be any - * subclass of Entry, like BarEntry or CandleEntry, simply cast - * it at runtime. - * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the selected range or stack-index (only stacked bar entries). - */ - public abstract void refreshContent(Entry e, Highlight highlight); + /** + * This method enables a specified custom MarkerView to update it's content everytime the MarkerView is redrawn. + * + * @param e + * The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or + * CandleEntry, simply cast it at runtime. + * @param highlight + * the highlight object contains information about the highlighted value such as it's dataset-index, the + * selected range or stack-index (only stacked bar entries). + */ + public abstract void refreshContent(Entry e, Highlight highlight); - /** - * Use this to return the desired offset you wish the MarkerView to have on - * the x-axis. By returning -(getWidth() / 2) you will center the MarkerView - * horizontally. - * - * @return - */ - public abstract int getXOffset(); + /** + * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / + * 2) you will center the MarkerView horizontally. + * + * @return + */ + public abstract int getXOffset(); - /** - * Use this to return the desired position offset you wish the MarkerView to - * have on the y-axis. By returning -getHeight() you will cause the - * MarkerView to be above the selected value. - * - * @return - */ - public abstract int getYOffset(); + /** + * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning + * -getHeight() you will cause the MarkerView to be above the selected value. + * + * @return + */ + public abstract int getYOffset(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 37dcf12add..f521975a19 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -1,219 +1,218 @@ package com.github.mikephil.charting.highlight; -import android.util.Log; - import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; /** * Created by Philipp Jahoda on 22/07/15. */ public class BarHighlighter extends ChartHighlighter { - public BarHighlighter(BarDataProvider chart) { - super(chart); - } - - @Override - public Highlight getHighlight(float x, float y) { + public BarHighlighter(BarDataProvider chart) { + super(chart); + } - Highlight h = super.getHighlight(x, y); + @Override + public Highlight getHighlight(float x, float y) { - if(h == null) - return h; - else { + Highlight h = super.getHighlight(x, y); - BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + if (h == null) + return h; + else { - if (set.isStacked()) { + BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = y; + if (set.isStacked()) { - // take any transformer to determine the x-axis value - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = y; - return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[1]); - } else - return h; - } - } + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - @Override - protected int getXIndex(float x) { + return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[1]); + } else + return h; + } + } - if(!mChart.getBarData().isGrouped()) { - return super.getXIndex(x); - } else { + @Override + protected int getXIndex(float x) { - float baseNoSpace = getBase(x); - - int setCount = mChart.getBarData().getDataSetCount(); - int xIndex = (int) baseNoSpace / setCount; - - int valCount = mChart.getData().getXValCount(); - - if(xIndex < 0) - xIndex = 0; - else if(xIndex >= valCount) - xIndex = valCount - 1; - - return xIndex; - } - } - - @Override - protected int getDataSetIndex(int xIndex, float x, float y) { - - if(!mChart.getBarData().isGrouped()) { - return 0; - } else { - - float baseNoSpace = getBase(x); - - int setCount = mChart.getBarData().getDataSetCount(); - int dataSetIndex = (int) baseNoSpace % setCount; - - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; - - return dataSetIndex; - } - } - - /** - * This method creates the Highlight object that also indicates which value - * of a stacked BarEntry has been selected. - * - * @param old the old highlight object before looking for stacked values - * @param set - * @param xIndex - * @param dataSetIndex - * @param yValue - * @return - */ - protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xIndex, int dataSetIndex, double yValue) { - - BarEntry entry = set.getEntryForXIndex(xIndex); + if (!mChart.getBarData().isGrouped()) { + return super.getXIndex(x); + } else { - if(entry.getVals() == null) - return old; + float baseNoSpace = getBase(x); + + int setCount = mChart.getBarData().getDataSetCount(); + int xIndex = (int) baseNoSpace / setCount; + + int valCount = mChart.getData().getXValCount(); + + if (xIndex < 0) + xIndex = 0; + else if (xIndex >= valCount) + xIndex = valCount - 1; + + return xIndex; + } + } + + @Override + protected int getDataSetIndex(int xIndex, float x, float y) { + + if (!mChart.getBarData().isGrouped()) { + return 0; + } else { + + float baseNoSpace = getBase(x); + + int setCount = mChart.getBarData().getDataSetCount(); + int dataSetIndex = (int) baseNoSpace % setCount; + + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; + + return dataSetIndex; + } + } + + /** + * This method creates the Highlight object that also indicates which value of a stacked BarEntry has been selected. + * + * @param old + * the old highlight object before looking for stacked values + * @param set + * @param xIndex + * @param dataSetIndex + * @param yValue + * @return + */ + protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xIndex, int dataSetIndex, double yValue) { + + BarEntry entry = set.getEntryForXIndex(xIndex); + + if (entry.getVals() == null) + return old; - if (entry != null) { + if (entry != null) { - Range[] ranges = getRanges(entry); - int stackIndex = getClosestStackIndex(ranges, (float) yValue); + Range[] ranges = getRanges(entry); + int stackIndex = getClosestStackIndex(ranges, (float) yValue); - Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); - return h; - } else - return null; - } - - /** - * Returns the index of the closest value inside the values array / ranges (stacked barchart) - * to the value given as a parameter. - * - * @param ranges - * @param value - * @return - */ - protected int getClosestStackIndex(Range[] ranges, float value) { - - if(ranges == null) - return 0; - - int stackIndex = 0; - - for(Range range : ranges) { - if(range.contains(value)) - return stackIndex; - else - stackIndex++; - } - - int length = ranges.length - 1; - - return (value > ranges[length].to) ? length : 0; -// -// float[] vals = e.getVals(); -// -// if (vals == null) -// return -1; -// -// int index = 0; -// float remainder = e.getNegativeSum(); -// -// while (index < vals.length - 1 && value > vals[index] + remainder) { -// remainder += vals[index]; -// index++; -// } -// -// return index; - } - - /** - * Returns the base x-value to the corresponding x-touch value in pixels. - * @param x - * @return - */ - protected float getBase(float x) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - float xVal = pts[0]; - - int setCount = mChart.getBarData().getDataSetCount(); - - // calculate how often the group-space appears - int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); - - float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; - - float baseNoSpace = (float) xVal - groupSpaceSum; - return baseNoSpace; - } - - /** - * Splits up the stack-values of the given bar-entry into Range objects. - * @param entry - * @return - */ - protected Range[] getRanges(BarEntry entry) { - - float[] values = entry.getVals(); - - if(values == null) - return null; - - float negRemain = -entry.getNegativeSum(); - float posRemain = 0f; - - Range[] ranges = new Range[values.length]; - - for(int i = 0; i < ranges.length; i++) { - - float value = values[i]; - - if(value < 0) { - ranges[i] = new Range(negRemain, negRemain+Math.abs(value)); - negRemain += Math.abs(value); - } else { - ranges[i] = new Range(posRemain, posRemain+value); - posRemain += value; - } - } - - return ranges; - } + Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); + return h; + } else + return null; + } + + /** + * Returns the index of the closest value inside the values array / ranges (stacked barchart) to the value given as + * a parameter. + * + * @param ranges + * @param value + * @return + */ + protected int getClosestStackIndex(Range[] ranges, float value) { + + if (ranges == null) + return 0; + + int stackIndex = 0; + + for (Range range : ranges) { + if (range.contains(value)) + return stackIndex; + else + stackIndex++; + } + + int length = ranges.length - 1; + + return (value > ranges[length].to) ? length : 0; + // + // float[] vals = e.getVals(); + // + // if (vals == null) + // return -1; + // + // int index = 0; + // float remainder = e.getNegativeSum(); + // + // while (index < vals.length - 1 && value > vals[index] + remainder) { + // remainder += vals[index]; + // index++; + // } + // + // return index; + } + + /** + * Returns the base x-value to the corresponding x-touch value in pixels. + * + * @param x + * @return + */ + protected float getBase(float x) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + float xVal = pts[0]; + + int setCount = mChart.getBarData().getDataSetCount(); + + // calculate how often the group-space appears + int steps = (int) ((float) xVal / ((float) setCount + mChart.getBarData().getGroupSpace())); + + float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; + + float baseNoSpace = (float) xVal - groupSpaceSum; + return baseNoSpace; + } + + /** + * Splits up the stack-values of the given bar-entry into Range objects. + * + * @param entry + * @return + */ + protected Range[] getRanges(BarEntry entry) { + + float[] values = entry.getVals(); + + if (values == null) + return null; + + float negRemain = -entry.getNegativeSum(); + float posRemain = 0f; + + Range[] ranges = new Range[values.length]; + + for (int i = 0; i < ranges.length; i++) { + + float value = values[i]; + + if (value < 0) { + ranges[i] = new Range(negRemain, negRemain + Math.abs(value)); + negRemain += Math.abs(value); + } else { + ranges[i] = new Range(posRemain, posRemain + value); + posRemain += value; + } + } + + return ranges; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index cb16420345..c4070d066b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -1,144 +1,120 @@ package com.github.mikephil.charting.highlight; +import java.util.ArrayList; +import java.util.List; + import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; -import com.github.mikephil.charting.interfaces.ChartInterface; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; -import java.util.List; - /** * Created by Philipp Jahoda on 21/07/15. */ public class ChartHighlighter { - /** instance of the data-provider */ - protected T mChart; - - public ChartHighlighter(T chart) { - this.mChart = chart; - } - - /** - * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. - * @param x - * @param y - * @return - */ - public Highlight getHighlight(float x, float y) { - - int xIndex = getXIndex(x); - if (xIndex == -Integer.MAX_VALUE) - return null; - - int dataSetIndex = getDataSetIndex(xIndex, x, y); - if (dataSetIndex == -Integer.MAX_VALUE) - return null; - - return new Highlight(xIndex, dataSetIndex); - } - - /** - * Returns the corresponding x-index for a given touch-position in pixels. - * @param x - * @return - */ - protected int getXIndex(float x) { - - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = x; - - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - - return (int) Math.round(pts[0]); - -// double xTouchVal = pts[0]; -// -// double base = Math.floor(xTouchVal); -// -// // touch out of chart -// if (xTouchVal < -mChart.getXChartMin() || xTouchVal > mChart.getXChartMax()) -// return -Integer.MAX_VALUE; -// -// if (base < 0) -// base = 0; -// -// int xIndex = (int) base; -// -// // check if we are more than half of a x-value or not -// if (xTouchVal - base > 0.5) { -// xIndex = (int) base + 1; -// } -// -// int valCount = mChart.getData().getXValCount(); -// -// if(xIndex < 0) -// xIndex = 0; -// else if(xIndex >= valCount) -// xIndex = valCount - 1; -// -// return xIndex; - } - - /** - * Returns the corresponding dataset-index for a given xIndex and xy-touch position in pixels. - * @param xIndex - * @param x - * @param y - * @return - */ - protected int getDataSetIndex(int xIndex, float x, float y) { - - List valsAtIndex = getSelectionDetailsAtIndex(xIndex); - - float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); - float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); - - YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; - - int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); - - return dataSetIndex; - } - - /** - * Returns a list of SelectionDetail object corresponding to the given xIndex. - * @param xIndex - * @return - */ - protected List getSelectionDetailsAtIndex(int xIndex) { - - List vals = new ArrayList(); - - float[] pts = new float[2]; - - for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { - - DataSet dataSet = mChart.getData().getDataSetByIndex(i); - - // dont include datasets that cannot be highlighted - if(!dataSet.isHighlightEnabled()) - continue; - - // extract all y-values from all DataSets at the given x-index - final float yVal = dataSet.getYValForXIndex(xIndex); - if (yVal == Float.NaN) - continue; - - pts[1] = yVal; - - mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); - - if (!Float.isNaN(pts[1])) { - vals.add(new SelectionDetail(pts[1], i, dataSet)); - } - } - - return vals; - } + /** instance of the data-provider */ + protected T mChart; + + public ChartHighlighter(T chart) { + this.mChart = chart; + } + + /** + * Returns a Highlight object corresponding to the given x- and y- touch positions in pixels. + * + * @param x + * @param y + * @return + */ + public Highlight getHighlight(float x, float y) { + + int xIndex = getXIndex(x); + if (xIndex == -Integer.MAX_VALUE) + return null; + + int dataSetIndex = getDataSetIndex(xIndex, x, y); + if (dataSetIndex == -Integer.MAX_VALUE) + return null; + + return new Highlight(xIndex, dataSetIndex); + } + + /** + * Returns the corresponding x-index for a given touch-position in pixels. + * + * @param x + * @return + */ + protected int getXIndex(float x) { + + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = x; + + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + + return (int) Math.round(pts[0]); + } + + /** + * Returns the corresponding dataset-index for a given xIndex and xy-touch position in pixels. + * + * @param xIndex + * @param x + * @param y + * @return + */ + protected int getDataSetIndex(int xIndex, float x, float y) { + + List valsAtIndex = getSelectionDetailsAtIndex(xIndex); + + float leftdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.LEFT); + float rightdist = Utils.getMinimumDistance(valsAtIndex, y, YAxis.AxisDependency.RIGHT); + + YAxis.AxisDependency axis = leftdist < rightdist ? YAxis.AxisDependency.LEFT : YAxis.AxisDependency.RIGHT; + + int dataSetIndex = Utils.getClosestDataSetIndex(valsAtIndex, y, axis); + + return dataSetIndex; + } + + /** + * Returns a list of SelectionDetail object corresponding to the given xIndex. + * + * @param xIndex + * @return + */ + protected List getSelectionDetailsAtIndex(int xIndex) { + + List vals = new ArrayList(); + + float[] pts = new float[2]; + + for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { + + DataSet dataSet = mChart.getData().getDataSetByIndex(i); + + // dont include datasets that cannot be highlighted + if (!dataSet.isHighlightEnabled()) + continue; + + // extract all y-values from all DataSets at the given x-index + final float yVal = dataSet.getYValForXIndex(xIndex); + if (yVal == Float.NaN) + continue; + + pts[1] = yVal; + + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + + if (!Float.isNaN(pts[1])) { + vals.add(new SelectionDetail(pts[1], i, dataSet)); + } + } + + return vals; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 8ec8027eef..f6343615b6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -2,7 +2,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.interfaces.BarDataProvider; /** @@ -10,91 +9,92 @@ */ public class HorizontalBarHighlighter extends BarHighlighter { - public HorizontalBarHighlighter(BarDataProvider chart) { - super(chart); - } + public HorizontalBarHighlighter(BarDataProvider chart) { + super(chart); + } - @Override - public Highlight getHighlight(float x, float y) { + @Override + public Highlight getHighlight(float x, float y) { - Highlight h = super.getHighlight(x, y); + Highlight h = super.getHighlight(x, y); - if(h == null) - return h; - else { + if (h == null) + return h; + else { - BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); - if (set.isStacked()) { + if (set.isStacked()) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[0] = y; + // create an array of the touch-point + float[] pts = new float[2]; + pts[0] = y; - // take any transformer to determine the x-axis value - mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); + // take any transformer to determine the x-axis value + mChart.getTransformer(set.getAxisDependency()).pixelsToValue(pts); - return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[0]); - } else - return h; - } - } + return getStackedHighlight(h, set, h.getXIndex(), h.getDataSetIndex(), pts[0]); + } else + return h; + } + } - @Override - protected int getXIndex(float x) { + @Override + protected int getXIndex(float x) { - if(!mChart.getBarData().isGrouped()) { + if (!mChart.getBarData().isGrouped()) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = x; + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = x; - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - return (int) Math.round(pts[1]); - } else { + return (int) Math.round(pts[1]); + } else { - float baseNoSpace = getBase(x); + float baseNoSpace = getBase(x); - int setCount = mChart.getBarData().getDataSetCount(); - int xIndex = (int) baseNoSpace / setCount; + int setCount = mChart.getBarData().getDataSetCount(); + int xIndex = (int) baseNoSpace / setCount; - int valCount = mChart.getData().getXValCount(); + int valCount = mChart.getData().getXValCount(); - if(xIndex < 0) - xIndex = 0; - else if(xIndex >= valCount) - xIndex = valCount - 1; + if (xIndex < 0) + xIndex = 0; + else if (xIndex >= valCount) + xIndex = valCount - 1; - return xIndex; - } - } + return xIndex; + } + } - /** - * Returns the base y-value to the corresponding x-touch value in pixels. - * @param y - * @return - */ - @Override - protected float getBase(float y) { + /** + * Returns the base y-value to the corresponding x-touch value in pixels. + * + * @param y + * @return + */ + @Override + protected float getBase(float y) { - // create an array of the touch-point - float[] pts = new float[2]; - pts[1] = y; + // create an array of the touch-point + float[] pts = new float[2]; + pts[1] = y; - // take any transformer to determine the x-axis value - mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); - float yVal = pts[1]; + // take any transformer to determine the x-axis value + mChart.getTransformer(YAxis.AxisDependency.LEFT).pixelsToValue(pts); + float yVal = pts[1]; - int setCount = mChart.getBarData().getDataSetCount(); + int setCount = mChart.getBarData().getDataSetCount(); - // calculate how often the group-space appears - int steps = (int) ((float) yVal / ((float) setCount + mChart.getBarData().getGroupSpace())); + // calculate how often the group-space appears + int steps = (int) ((float) yVal / ((float) setCount + mChart.getBarData().getGroupSpace())); - float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; + float groupSpaceSum = mChart.getBarData().getGroupSpace() * (float) steps; - float baseNoSpace = (float) yVal - groupSpaceSum; - return baseNoSpace; - } + float baseNoSpace = (float) yVal - groupSpaceSum; + return baseNoSpace; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java index 069592c298..96dd592b8f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/Range.java @@ -1,37 +1,38 @@ package com.github.mikephil.charting.highlight; /** - * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one value in a stacked bar entry. - * e.g. stack values are -10, 5, 20 -> then ranges are (-10 - 0, 0 - 5, 5 - 25). + * Created by Philipp Jahoda on 24/07/15. Class that represents the range of one value in a stacked bar entry. e.g. + * stack values are -10, 5, 20 -> then ranges are (-10 - 0, 0 - 5, 5 - 25). */ public final class Range { - public float from; - public float to; + public float from; + public float to; - public Range(float from, float to) { - this.from = from; - this.to = to; - } + public Range(float from, float to) { + this.from = from; + this.to = to; + } - /** - * Returns true if this range contains (if the value is in between) the given value, false if not. - * @param value - * @return - */ - public boolean contains(float value) { + /** + * Returns true if this range contains (if the value is in between) the given value, false if not. + * + * @param value + * @return + */ + public boolean contains(float value) { - if(value > from && value <= to) - return true; - else - return false; - } + if (value > from && value <= to) + return true; + else + return false; + } - public boolean isLarger(float value) { - return value > to; - } + public boolean isLarger(float value) { + return value > to; + } - public boolean isSmaller(float value) { - return value < from; - } + public boolean isSmaller(float value) { + return value < from; + } } \ No newline at end of file From d07ceda265830d585cda65d1132ebba283f2941c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 24 Jul 2015 23:57:41 +0200 Subject: [PATCH 0437/1390] Added feature that allows the label-count to be exactly set and evenly distributed over the y-axis. --- .../mpchartexample/BarChartActivity.java | 4 +- .../mpchartexample/BarChartActivitySinus.java | 4 +- .../CandleStickChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../ListViewBarChartActivity.java | 4 +- .../mpchartexample/RadarChartActivitry.java | 2 +- .../StackedBarActivityNegative.java | 2 +- .../listviewitems/BarChartItem.java | 4 +- .../listviewitems/LineChartItem.java | 4 +- .../mikephil/charting/components/YAxis.java | 770 +++++++++--------- .../charting/renderer/YAxisRenderer.java | 475 +++++------ .../renderer/YAxisRendererRadarChart.java | 249 +++--- 12 files changed, 779 insertions(+), 743 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index c483761e17..1db0e0232e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -96,7 +96,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(8); + leftAxis.setLabelCount(8, false); leftAxis.setValueFormatter(custom); leftAxis.setPosition(YAxisLabelPosition.OUTSIDE_CHART); leftAxis.setSpaceTop(15f); @@ -104,7 +104,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); rightAxis.setTypeface(mTf); - rightAxis.setLabelCount(8); + rightAxis.setLabelCount(8, false); rightAxis.setValueFormatter(custom); rightAxis.setSpaceTop(15f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 28b1ee56dd..5e53f2b147 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -86,7 +86,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(6); + leftAxis.setLabelCount(6, false); leftAxis.setStartAtZero(false); leftAxis.setAxisMinValue(-2.5f); leftAxis.setAxisMaxValue(2.5f); @@ -94,7 +94,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis rightAxis = mChart.getAxisRight(); rightAxis.setDrawGridLines(false); rightAxis.setTypeface(mTf); - rightAxis.setLabelCount(6); + rightAxis.setLabelCount(6, false); rightAxis.setStartAtZero(false); rightAxis.setAxisMinValue(-2.5f); rightAxis.setAxisMaxValue(2.5f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 07cf8ab1f9..384983f42b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -66,7 +66,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); // leftAxis.setEnabled(false); - leftAxis.setLabelCount(7); + leftAxis.setLabelCount(7, false); leftAxis.setDrawGridLines(false); leftAxis.setDrawAxisLine(false); leftAxis.setStartAtZero(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index e86a1367f0..6b663c95ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -82,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); - y.setLabelCount(5); + y.setLabelCount(5, false); y.setEnabled(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index f2a66d1942..d314c3166f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -98,12 +98,12 @@ public View getView(int position, View convertView, ViewGroup parent) { YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(5); + leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(15f); YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); - rightAxis.setLabelCount(5); + rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(15f); // set data diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 524e7694c5..9660723760 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -61,7 +61,7 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yAxis = mChart.getYAxis(); yAxis.setTypeface(tf); - yAxis.setLabelCount(5); + yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); yAxis.setStartAtZero(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 5b69a394ef..c242a7f2f8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -59,7 +59,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisRight().setStartAtZero(false); mChart.getAxisRight().setAxisMaxValue(25f); mChart.getAxisRight().setAxisMinValue(-25f); - mChart.getAxisRight().setLabelCount(7); + mChart.getAxisRight().setLabelCount(7, false); mChart.getAxisRight().setValueFormatter(new CustomFormatter()); mChart.getAxisRight().setTextSize(9f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java index d886c9d485..dabdb9a2a8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/BarChartItem.java @@ -60,12 +60,12 @@ public View getView(int position, View convertView, Context c) { YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(5); + leftAxis.setLabelCount(5, false); leftAxis.setSpaceTop(20f); YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); - rightAxis.setLabelCount(5); + rightAxis.setLabelCount(5, false); rightAxis.setSpaceTop(20f); mChartData.setValueTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java index 16346251dd..1e2ab2301f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/LineChartItem.java @@ -61,11 +61,11 @@ public View getView(int position, View convertView, Context c) { YAxis leftAxis = holder.chart.getAxisLeft(); leftAxis.setTypeface(mTf); - leftAxis.setLabelCount(5); + leftAxis.setLabelCount(5, false); YAxis rightAxis = holder.chart.getAxisRight(); rightAxis.setTypeface(mTf); - rightAxis.setLabelCount(5); + rightAxis.setLabelCount(5, false); rightAxis.setDrawGridLines(false); // set data diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 79df15ac6f..12a93559c6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.components; import android.graphics.Paint; @@ -8,404 +7,407 @@ import com.github.mikephil.charting.utils.ValueFormatter; /** - * Class representing the y-axis labels settings and its entries. Only use the - * setter methods to modify it. Do not access public variables directly. Be - * aware that not all features the YLabels class provides are suitable for the - * RadarChart. Customizations that affect the value range of the axis need to be - * applied before setting data for the chart. + * Class representing the y-axis labels settings and its entries. Only use the setter methods to modify it. Do not + * access public variables directly. Be aware that not all features the YLabels class provides are suitable for the + * RadarChart. Customizations that affect the value range of the axis need to be applied before setting data for the + * chart. * * @author Philipp Jahoda */ public class YAxis extends AxisBase { - /** custom formatter that is used instead of the auto-formatter if set */ - protected ValueFormatter mValueFormatter; + /** custom formatter that is used instead of the auto-formatter if set */ + protected ValueFormatter mValueFormatter; + + /** the actual array of entries */ + public float[] mEntries = new float[] {}; - /** the actual array of entries */ - public float[] mEntries = new float[] {}; + /** the number of entries the legend contains */ + public int mEntryCount; - /** the number of entries the legend contains */ - public int mEntryCount; + /** the number of decimal digits to use */ + public int mDecimals; - /** the number of decimal digits to use */ - public int mDecimals; + /** the number of y-label entries the y-labels should have, default 6 */ + private int mLabelCount = 6; - /** the number of y-label entries the y-labels should have, default 6 */ - private int mLabelCount = 6; + /** indicates if the top y-label entry is drawn or not */ + private boolean mDrawTopYLabelEntry = true; - /** indicates if the top y-label entry is drawn or not */ - private boolean mDrawTopYLabelEntry = true; + /** if true, the y-labels show only the minimum and maximum value */ + protected boolean mShowOnlyMinMax = false; - /** if true, the y-labels show only the minimum and maximum value */ - protected boolean mShowOnlyMinMax = false; + /** flag that indicates if the axis is inverted or not */ + protected boolean mInverted = false; - /** flag that indicates if the axis is inverted or not */ - protected boolean mInverted = false; + /** if true, the y-label entries will always start at zero */ + protected boolean mStartAtZero = true; - /** if true, the y-label entries will always start at zero */ - protected boolean mStartAtZero = true; + /** if true, the set number of y-labels will be forced */ + protected boolean mForceLabels = false; /** custom minimum value this axis represents */ - protected float mCustomAxisMin = Float.NaN; - - /** custom maximum value this axis represents */ - protected float mCustomAxisMax = Float.NaN; - - /** - * axis space from the largest value to the top in percent of the total axis - * range - */ - protected float mSpacePercentTop = 10f; - - /** - * axis space from the smallest value to the bottom in percent of the total - * axis range - */ - protected float mSpacePercentBottom = 10f; - - public float mAxisMaximum = 0f; - public float mAxisMinimum = 0f; - - /** the total range of values this axis covers */ - public float mAxisRange = 0f; - - /** the position of the y-labels relative to the chart */ - private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; - - /** enum for the position of the y-labels relative to the chart */ - public enum YAxisLabelPosition { - OUTSIDE_CHART, INSIDE_CHART - } - - /** the side this axis object represents */ - private AxisDependency mAxisDependency; - - /** - * Enum that specifies the axis a DataSet should be plotted against, either - * LEFT or RIGHT. - * - * @author Philipp Jahoda - */ - public enum AxisDependency { - LEFT, RIGHT - } - - public YAxis() { - super(); - this.mAxisDependency = AxisDependency.LEFT; - this.mYOffset = 0f; - } - - public YAxis(AxisDependency position) { - super(); - this.mAxisDependency = position; - this.mYOffset = 0f; - } - - public AxisDependency getAxisDependency() { - return mAxisDependency; - } - - /** - * returns the position of the y-labels - */ - public YAxisLabelPosition getLabelPosition() { - return mPosition; - } - - /** - * sets the position of the y-labels - * - * @param pos - */ - public void setPosition(YAxisLabelPosition pos) { - mPosition = pos; - } - - /** - * returns true if drawing the top y-axis label entry is enabled - * - * @return - */ - public boolean isDrawTopYLabelEntryEnabled() { - return mDrawTopYLabelEntry; - } - - /** - * set this to true to enable drawing the top y-label entry. Disabling this - * can be helpful when the top y-label and left x-label interfere with each - * other. default: true - * - * @param enabled - */ - public void setDrawTopYLabelEntry(boolean enabled) { - mDrawTopYLabelEntry = enabled; - } - - /** - * sets the number of label entries for the y-axis max = 25, min = 2, - * default: 6, be aware that this number is not fixed and can only be - * approximated - * - * @param yCount - */ - public void setLabelCount(int yCount) { - - if (yCount > 25) - yCount = 25; - if (yCount < 2) - yCount = 2; - - mLabelCount = yCount; - } - - /** - * Returns the number of label entries the y-axis should have - * - * @return - */ - public int getLabelCount() { - return mLabelCount; - } - - /** - * If enabled, the YLabels will only show the minimum and maximum value of - * the chart. This will ignore/override the set label count. - * - * @param enabled - */ - public void setShowOnlyMinMax(boolean enabled) { - mShowOnlyMinMax = enabled; - } - - /** - * Returns true if showing only min and max value is enabled. - * - * @return - */ - public boolean isShowOnlyMinMaxEnabled() { - return mShowOnlyMinMax; - } - - /** - * If this is set to true, the y-axis is inverted which means that low - * values are on top of the chart, high values on bottom. - * - * @param enabled - */ - public void setInverted(boolean enabled) { - mInverted = enabled; - } - - /** - * If this returns true, the y-axis is inverted. - * - * @return - */ - public boolean isInverted() { - return mInverted; - } - - /** - * enable this to force the y-axis labels to always start at zero - * - * @param enabled - */ - public void setStartAtZero(boolean enabled) { - this.mStartAtZero = enabled; - } - - /** - * returns true if the chart is set to start at zero, false otherwise - * - * @return - */ - public boolean isStartAtZeroEnabled() { - return mStartAtZero; - } + protected float mCustomAxisMin = Float.NaN; + + /** custom maximum value this axis represents */ + protected float mCustomAxisMax = Float.NaN; + + /** + * axis space from the largest value to the top in percent of the total axis range + */ + protected float mSpacePercentTop = 10f; + + /** + * axis space from the smallest value to the bottom in percent of the total axis range + */ + protected float mSpacePercentBottom = 10f; + + public float mAxisMaximum = 0f; + public float mAxisMinimum = 0f; + + /** the total range of values this axis covers */ + public float mAxisRange = 0f; + + /** the position of the y-labels relative to the chart */ + private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + + /** enum for the position of the y-labels relative to the chart */ + public enum YAxisLabelPosition { + OUTSIDE_CHART, INSIDE_CHART + } + + /** the side this axis object represents */ + private AxisDependency mAxisDependency; + + /** + * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. + * + * @author Philipp Jahoda + */ + public enum AxisDependency { + LEFT, RIGHT + } + + public YAxis() { + super(); + this.mAxisDependency = AxisDependency.LEFT; + this.mYOffset = 0f; + } + + public YAxis(AxisDependency position) { + super(); + this.mAxisDependency = position; + this.mYOffset = 0f; + } + + public AxisDependency getAxisDependency() { + return mAxisDependency; + } + + /** + * returns the position of the y-labels + */ + public YAxisLabelPosition getLabelPosition() { + return mPosition; + } + + /** + * sets the position of the y-labels + * + * @param pos + */ + public void setPosition(YAxisLabelPosition pos) { + mPosition = pos; + } + + /** + * returns true if drawing the top y-axis label entry is enabled + * + * @return + */ + public boolean isDrawTopYLabelEntryEnabled() { + return mDrawTopYLabelEntry; + } + + /** + * set this to true to enable drawing the top y-label entry. Disabling this can be helpful when the top y-label and + * left x-label interfere with each other. default: true + * + * @param enabled + */ + public void setDrawTopYLabelEntry(boolean enabled) { + mDrawTopYLabelEntry = enabled; + } + + /** + * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware that this number is not + * fixed (if force == false) and can only be approximated. + * + * @param count + * the number of y-axis labels that sould be displayed + * @param force + * if enabled, the set label count will be forced, meaning that the exact specified count of labels will + * be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values + */ + public void setLabelCount(int count, boolean force) { + + if (count > 25) + count = 25; + if (count < 2) + count = 2; + + mLabelCount = count; + mForceLabels = force; + } + + /** + * Returns the number of label entries the y-axis should have + * + * @return + */ + public int getLabelCount() { + return mLabelCount; + } + + /** + * Returns true if focing the y-label count is enabled. Default: false + * + * @return + */ + public boolean isForceLabelsEnabled() { + return mForceLabels; + } + + /** + * If enabled, the YLabels will only show the minimum and maximum value of the chart. This will ignore/override the + * set label count. + * + * @param enabled + */ + public void setShowOnlyMinMax(boolean enabled) { + mShowOnlyMinMax = enabled; + } + + /** + * Returns true if showing only min and max value is enabled. + * + * @return + */ + public boolean isShowOnlyMinMaxEnabled() { + return mShowOnlyMinMax; + } + + /** + * If this is set to true, the y-axis is inverted which means that low values are on top of the chart, high values + * on bottom. + * + * @param enabled + */ + public void setInverted(boolean enabled) { + mInverted = enabled; + } + + /** + * If this returns true, the y-axis is inverted. + * + * @return + */ + public boolean isInverted() { + return mInverted; + } + + /** + * enable this to force the y-axis labels to always start at zero + * + * @param enabled + */ + public void setStartAtZero(boolean enabled) { + this.mStartAtZero = enabled; + } + + /** + * returns true if the chart is set to start at zero, false otherwise + * + * @return + */ + public boolean isStartAtZeroEnabled() { + return mStartAtZero; + } public float getAxisMinValue() { - return mCustomAxisMin; - } - - /** - * Set a custom minimum value for this axis. If set, this value will not be - * calculated automatically depending on the provided data. Use - * resetAxisMinValue() to undo this. Do not forget to call - * setStartAtZero(false) if you use this method. Otherwise, the axis-minimum - * value will still be forced to 0. - * - * @param min - */ - public void setAxisMinValue(float min) { - mCustomAxisMin = min; - } - - /** - * By calling this method, any custom minimum value that has been previously - * set is reseted, and the calculation is done automatically. - */ - public void resetAxisMinValue() { - mCustomAxisMin = Float.NaN; - } - - public float getAxisMaxValue() { - return mCustomAxisMax; - } - - /** - * Set a custom maximum value for this axis. If set, this value will not be - * calculated automatically depending on the provided data. Use - * resetAxisMaxValue() to undo this. - * - * @param max - */ - public void setAxisMaxValue(float max) { - mCustomAxisMax = max; - } - - /** - * By calling this method, any custom maximum value that has been previously - * set is reseted, and the calculation is done automatically. - */ - public void resetAxisMaxValue() { - mCustomAxisMax = Float.NaN; - } - - /** - * Sets the top axis space in percent of the full range. Default 10f - * - * @param percent - */ - public void setSpaceTop(float percent) { - mSpacePercentTop = percent; - } - - /** - * Returns the top axis space in percent of the full range. Default 10f - * - * @return - */ - public float getSpaceTop() { - return mSpacePercentTop; - } - - /** - * Sets the bottom axis space in percent of the full range. Default 10f - * - * @param percent - */ - public void setSpaceBottom(float percent) { - mSpacePercentBottom = percent; - } - - /** - * Returns the bottom axis space in percent of the full range. Default 10f - * - * @return - */ - public float getSpaceBottom() { - return mSpacePercentBottom; - } - - public float getRequiredWidthSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(); - return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; - } - - public float getRequiredHeightSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(); - return (float) Utils.calcTextHeight(p, label) + Utils.convertDpToPixel(2.5f) * 2f + getYOffset(); - } - - @Override - public String getLongestLabel() { - - String longest = ""; - - for (int i = 0; i < mEntries.length; i++) { - String text = getFormattedLabel(i); - - if (longest.length() < text.length()) - longest = text; - } - - return longest; - } - - /** - * Returns the formatted y-label at the specified index. This will either - * use the auto-formatter or the custom formatter (if one is set). - * - * @param index - * @return - */ - public String getFormattedLabel(int index) { - - if (index < 0 || index >= mEntries.length) - return ""; - else - return getValueFormatter().getFormattedValue(mEntries[index]); - } - - /** - * Sets the formatter to be used for drawing the values inside the chart. If - * no formatter is set, the chart will automatically determine a reasonable - * formatting (concerning decimals) for all the values that are drawn inside - * the chart. Use chart.getDefaultValueFormatter() to use the formatter - * calculated by the chart. - * - * @param f - */ - public void setValueFormatter(ValueFormatter f) { - - if (f == null) - return; - else - mValueFormatter = f; - } - - /** - * Returns the formatter used for drawing the values inside the chart. - * - * @return - */ - public ValueFormatter getValueFormatter() { - return mValueFormatter; - } - - /** - * If this component has no ValueFormatter or is only equipped with the - * default one (no custom set), return true. - * - * @return - */ - public boolean needsDefaultFormatter() { - if (mValueFormatter == null) - return true; - if (mValueFormatter instanceof DefaultValueFormatter) - return true; - - return false; - } - - /** - * Returns true if this axis needs horizontal offset, false if no offset is - * needed. - * - * @return - */ - public boolean needsOffset() { - if (isEnabled() && isDrawLabelsEnabled() - && getLabelPosition() == YAxisLabelPosition.OUTSIDE_CHART) - return true; - else - return false; - } + return mCustomAxisMin; + } + + /** + * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use + * this method. Otherwise, the axis-minimum value will still be forced to 0. + * + * @param min + */ + public void setAxisMinValue(float min) { + mCustomAxisMin = min; + } + + /** + * By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is + * done automatically. + */ + public void resetAxisMinValue() { + mCustomAxisMin = Float.NaN; + } + + public float getAxisMaxValue() { + return mCustomAxisMax; + } + + /** + * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMaxValue() to undo this. + * + * @param max + */ + public void setAxisMaxValue(float max) { + mCustomAxisMax = max; + } + + /** + * By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is + * done automatically. + */ + public void resetAxisMaxValue() { + mCustomAxisMax = Float.NaN; + } + + /** + * Sets the top axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceTop(float percent) { + mSpacePercentTop = percent; + } + + /** + * Returns the top axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceTop() { + return mSpacePercentTop; + } + + /** + * Sets the bottom axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceBottom(float percent) { + mSpacePercentBottom = percent; + } + + /** + * Returns the bottom axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceBottom() { + return mSpacePercentBottom; + } + + public float getRequiredWidthSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(); + return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + } + + public float getRequiredHeightSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(); + return (float) Utils.calcTextHeight(p, label) + Utils.convertDpToPixel(2.5f) * 2f + getYOffset(); + } + + @Override + public String getLongestLabel() { + + String longest = ""; + + for (int i = 0; i < mEntries.length; i++) { + String text = getFormattedLabel(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } + + /** + * Returns the formatted y-label at the specified index. This will either use the auto-formatter or the custom + * formatter (if one is set). + * + * @param index + * @return + */ + public String getFormattedLabel(int index) { + + if (index < 0 || index >= mEntries.length) + return ""; + else + return getValueFormatter().getFormattedValue(mEntries[index]); + } + + /** + * Sets the formatter to be used for drawing the values inside the chart. If no formatter is set, the chart will + * automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside + * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. + * + * @param f + */ + public void setValueFormatter(ValueFormatter f) { + + if (f == null) + return; + else + mValueFormatter = f; + } + + /** + * Returns the formatter used for drawing the values inside the chart. + * + * @return + */ + public ValueFormatter getValueFormatter() { + return mValueFormatter; + } + + /** + * If this component has no ValueFormatter or is only equipped with the default one (no custom set), return true. + * + * @return + */ + public boolean needsDefaultFormatter() { + if (mValueFormatter == null) + return true; + if (mValueFormatter instanceof DefaultValueFormatter) + return true; + + return false; + } + + /** + * Returns true if this axis needs horizontal offset, false if no offset is needed. + * + * @return + */ + public boolean needsOffset() { + if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition.OUTSIDE_CHART) + return true; + else + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index d76eefe272..b437eca7fb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -23,65 +22,64 @@ public class YAxisRenderer extends AxisRenderer { protected YAxis mYAxis; - public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { - super(viewPortHandler, trans); - - this.mYAxis = yAxis; - - mAxisLabelPaint.setColor(Color.BLACK); - mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); - } - - /** - * Computes the axis values. - * - * @param yMin - the minimum y-value in the data object for this axis - * @param yMax - the maximum y-value in the data object for this axis - */ - public void computeAxis(float yMin, float yMax) { - - // calculate the starting and entry point of the y-labels (depending on - // zoom / contentrect bounds) - if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { - - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom()); - - if (!mYAxis.isInverted()) { - yMin = (float) p2.y; - yMax = (float) p1.y; - } else { - - yMin = (float) p1.y; - yMax = (float) p2.y; - } - } - - computeAxisValues(yMin, yMax); - } - - /** - * Sets up the y-axis labels. Computes the desired number of labels between - * the two given extremes. Unlike the papareXLabels() method, this method - * needs to be called upon every refresh of the view. - * - * @return - */ - protected void computeAxisValues(float min, float max) { - - float yMin = min; - float yMax = max; - - int labelCount = mYAxis.getLabelCount(); - double range = Math.abs(yMax - yMin); - - if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[] {}; - mYAxis.mEntryCount = 0; - return; - } + public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { + super(viewPortHandler, trans); + + this.mYAxis = yAxis; + + mAxisLabelPaint.setColor(Color.BLACK); + mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + } + + /** + * Computes the axis values. + * + * @param yMin + * - the minimum y-value in the data object for this axis + * @param yMax + * - the maximum y-value in the data object for this axis + */ + public void computeAxis(float yMin, float yMax) { + + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + + if (!mYAxis.isInverted()) { + yMin = (float) p2.y; + yMax = (float) p1.y; + } else { + + yMin = (float) p1.y; + yMax = (float) p2.y; + } + } + + computeAxisValues(yMin, yMax); + } + + /** + * Sets up the y-axis labels. Computes the desired number of labels between the two given extremes. Unlike the + * papareXLabels() method, this method needs to be called upon every refresh of the view. + * + * @return + */ + protected void computeAxisValues(float min, float max) { + + float yMin = min; + float yMax = max; + + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[] {}; + mYAxis.mEntryCount = 0; + return; + } double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -93,238 +91,253 @@ protected void computeAxisValues(float min, float max) { interval = Math.floor(10 * intervalMagnitude); } - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { + // force label count + if (mYAxis.isForceLabelsEnabled()) { - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; + float step = (float) range / (float) (labelCount-1); + mYAxis.mEntryCount = labelCount; - } else { + if (mYAxis.mEntries.length < labelCount) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[labelCount]; + } - double first = Math.ceil(yMin / interval) * interval; - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + float v = min; - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; + for(int i = 0; i < labelCount; i++) { + mYAxis.mEntries[i] = v; + v += step; } - mYAxis.mEntryCount = n; + // no forced count + } else { - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { - for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; - } - } + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; + + } else { + + double first = Math.ceil(yMin / interval) * interval; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } + + mYAxis.mEntryCount = n; + + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + } + + // set decimals if (interval < 1) { mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); } else { mYAxis.mDecimals = 0; } - } + } - /** - * draws the y-axis labels to the screen - */ - @Override - public void renderAxisLabels(Canvas c) { + /** + * draws the y-axis labels to the screen + */ + @Override + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) + return; - float[] positions = new float[mYAxis.mEntryCount * 2]; + float[] positions = new float[mYAxis.mEntryCount * 2]; - for (int i = 0; i < positions.length; i += 2) { - // only fill y values, x values are not needed since the y-labels - // are - // static on the x-axis - positions[i + 1] = mYAxis.mEntries[i / 2]; - } + for (int i = 0; i < positions.length; i += 2) { + // only fill y values, x values are not needed since the y-labels + // are + // static on the x-axis + positions[i + 1] = mYAxis.mEntries[i / 2]; + } - mTrans.pointValuesToPixel(positions); + mTrans.pointValuesToPixel(positions); - mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); - mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setColor(mYAxis.getTextColor()); + mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); + mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setColor(mYAxis.getTextColor()); - float xoffset = mYAxis.getXOffset(); - float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f + mYAxis.getYOffset(); + float xoffset = mYAxis.getXOffset(); + float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f + mYAxis.getYOffset(); - AxisDependency dependency = mYAxis.getAxisDependency(); - YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); + AxisDependency dependency = mYAxis.getAxisDependency(); + YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); - float xPos = 0f; + float xPos = 0f; - if (dependency == AxisDependency.LEFT) { + if (dependency == AxisDependency.LEFT) { - if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - xPos = mViewPortHandler.offsetLeft() - xoffset; - } else { - mAxisLabelPaint.setTextAlign(Align.LEFT); - xPos = mViewPortHandler.offsetLeft() + xoffset; - } + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { + mAxisLabelPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.offsetLeft() - xoffset; + } else { + mAxisLabelPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.offsetLeft() + xoffset; + } - } else { + } else { - if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - mAxisLabelPaint.setTextAlign(Align.LEFT); - xPos = mViewPortHandler.contentRight() + xoffset; - } else { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - xPos = mViewPortHandler.contentRight() - xoffset; - } - } + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { + mAxisLabelPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.contentRight() + xoffset; + } else { + mAxisLabelPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.contentRight() - xoffset; + } + } - drawYLabels(c, xPos, positions, yoffset); - } + drawYLabels(c, xPos, positions, yoffset); + } - @Override - public void renderAxisLine(Canvas c) { + @Override + public void renderAxisLine(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) + return; - mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); - mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); + mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); - if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { - c.drawLine(mViewPortHandler.contentLeft(), - mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom(), mAxisLinePaint); - } else { - c.drawLine(mViewPortHandler.contentRight(), - mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), - mViewPortHandler.contentBottom(), mAxisLinePaint); - } - } + if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { + c.drawLine(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } else { + c.drawLine(mViewPortHandler.contentRight(), mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } + } - /** - * draws the y-labels on the specified x-position - * - * @param fixedPosition - * @param positions - */ - protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { + /** + * draws the y-labels on the specified x-position + * + * @param fixedPosition + * @param positions + */ + protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { - // draw - for (int i = 0; i < mYAxis.mEntryCount; i++) { + // draw + for (int i = 0; i < mYAxis.mEntryCount; i++) { - String text = mYAxis.getFormattedLabel(i); + String text = mYAxis.getFormattedLabel(i); - if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) - return; + if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) + return; - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); - } - } + c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); + } + } - @Override - public void renderGridLines(Canvas c) { + @Override + public void renderGridLines(Canvas c) { - if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) - return; + if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) + return; - // pre alloc - float[] position = new float[2]; + // pre alloc + float[] position = new float[2]; - mGridPaint.setColor(mYAxis.getGridColor()); - mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); - mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); + mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); - Path gridLinePath = new Path(); + Path gridLinePath = new Path(); - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { - position[1] = mYAxis.mEntries[i]; - mTrans.pointValuesToPixel(position); + position[1] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); - gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); - gridLinePath.lineTo(mViewPortHandler.contentRight(), - position[1]); + gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); + gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); - // draw a path because lines don't support dashing on lower android versions - c.drawPath(gridLinePath, mGridPaint); + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); - gridLinePath.reset(); - } - } - - /** - * Draws the LimitLines associated with this axis to the screen. - * - * @param c - */ - @Override + gridLinePath.reset(); + } + } + + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + @Override public void renderLimitLines(Canvas c) { - List limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); - if (limitLines == null || limitLines.size() <= 0) - return; + if (limitLines == null || limitLines.size() <= 0) + return; - float[] pts = new float[2]; - Path limitLinePath = new Path(); + float[] pts = new float[2]; + Path limitLinePath = new Path(); - for (int i = 0; i < limitLines.size(); i++) { + for (int i = 0; i < limitLines.size(); i++) { - LimitLine l = limitLines.get(i); - - mLimitLinePaint.setStyle(Paint.Style.STROKE); - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + LimitLine l = limitLines.get(i); - pts[1] = l.getLimit(); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - mTrans.pointValuesToPixel(pts); + pts[1] = l.getLimit(); - limitLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); - limitLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); - - c.drawPath(limitLinePath, mLimitLinePaint); - limitLinePath.reset(); - // c.drawLines(pts, mLimitLinePaint); + mTrans.pointValuesToPixel(pts); - String label = l.getLabel(); + limitLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); + limitLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); - // if drawing the limit-value label is enabled - if (label != null && !label.equals("")) { + c.drawPath(limitLinePath, mLimitLinePaint); + limitLinePath.reset(); + // c.drawLines(pts, mLimitLinePaint); - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) - / 2f; + String label = l.getLabel(); - mLimitLinePaint.setStyle(l.getTextStyle()); - mLimitLinePaint.setPathEffect(null); - mLimitLinePaint.setColor(l.getTextColor()); - mLimitLinePaint.setStrokeWidth(0.5f); - mLimitLinePaint.setTextSize(l.getTextSize()); + // if drawing the limit-value label is enabled + if (label != null && !label.equals("")) { - if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { + float xOffset = Utils.convertDpToPixel(4f); + float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) / 2f; - mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, mViewPortHandler.contentRight() - - xOffset, - pts[1] - yOffset, mLimitLinePaint); + mLimitLinePaint.setStyle(l.getTextStyle()); + mLimitLinePaint.setPathEffect(null); + mLimitLinePaint.setColor(l.getTextColor()); + mLimitLinePaint.setStrokeWidth(0.5f); + mLimitLinePaint.setTextSize(l.getTextSize()); - } else { - mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, mViewPortHandler.offsetLeft() - + xOffset, - pts[1] - yOffset, mLimitLinePaint); - } - } - } - } + if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, mViewPortHandler.contentRight() - xOffset, pts[1] - yOffset, mLimitLinePaint); + + } else { + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, mViewPortHandler.offsetLeft() + xOffset, pts[1] - yOffset, mLimitLinePaint); + } + } + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index bae51e0ebe..a2399fcb6c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.renderer; import android.graphics.Canvas; @@ -15,163 +14,185 @@ public class YAxisRendererRadarChart extends YAxisRenderer { - private RadarChart mChart; + private RadarChart mChart; + + public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { + super(viewPortHandler, yAxis, null); + + this.mChart = chart; + } + + @Override + public void computeAxis(float yMin, float yMax) { + computeAxisValues(yMin, yMax); + } + + @Override + protected void computeAxisValues(float min, float max) { + float yMin = min; + float yMax = max; + + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[] {}; + mYAxis.mEntryCount = 0; + return; + } + + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } - public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { - super(viewPortHandler, yAxis, null); + // force label count + if (mYAxis.isForceLabelsEnabled()) { - this.mChart = chart; - } + float step = (float) range / (float) (labelCount-1); + mYAxis.mEntryCount = labelCount; - @Override - public void computeAxis(float yMin, float yMax) { - computeAxisValues(yMin, yMax); - } + if (mYAxis.mEntries.length < labelCount) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[labelCount]; + } - @Override - protected void computeAxisValues(float min, float max) { - float yMin = min; - float yMax = max; + float v = min; - int labelCount = mYAxis.getLabelCount(); - double range = Math.abs(yMax - yMin); + for (int i = 0; i < labelCount; i++) { + mYAxis.mEntries[i] = v; + v += step; + } - if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[] {}; - mYAxis.mEntryCount = 0; - return; - } + // no forced count + } else { - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); - int intervalSigDigit = (int) (interval / intervalMagnitude); - if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); - } + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; + } else { - } else { + double first = Math.ceil(yMin / interval) * interval; - double first = Math.ceil(yMin / interval) * interval; + if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + first = 0.0; - if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) - first = 0.0; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } + if (Float.isNaN(mYAxis.getAxisMaxValue())) + n += 1; - if (Float.isNaN(mYAxis.getAxisMaxValue())) - n += 1; - - mYAxis.mEntryCount = n; + mYAxis.mEntryCount = n; - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } - for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; - } - } + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + } - if (interval < 1) { - mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); - } else { - mYAxis.mDecimals = 0; - } + if (interval < 1) { + mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mYAxis.mDecimals = 0; + } - mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; - mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); - } + mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; + mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); + } - @Override - public void renderAxisLabels(Canvas c) { + @Override + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) + return; - mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); - mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setColor(mYAxis.getTextColor()); + mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); + mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setColor(mYAxis.getTextColor()); - PointF center = mChart.getCenterOffsets(); - float factor = mChart.getFactor(); + PointF center = mChart.getCenterOffsets(); + float factor = mChart.getFactor(); - int labelCount = mYAxis.mEntryCount; + int labelCount = mYAxis.mEntryCount; - for (int j = 0; j < labelCount; j++) { + for (int j = 0; j < labelCount; j++) { - if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) - break; + if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) + break; - float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; + float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; - PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); + PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); - String label = mYAxis.getFormattedLabel(j); + String label = mYAxis.getFormattedLabel(j); - c.drawText(label, p.x + 10, p.y, mAxisLabelPaint); - } - } + c.drawText(label, p.x + 10, p.y, mAxisLabelPaint); + } + } - @Override - public void renderLimitLines(Canvas c) { + @Override + public void renderLimitLines(Canvas c) { - List limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); - if (limitLines == null) - return; + if (limitLines == null) + return; - float sliceangle = mChart.getSliceAngle(); + float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to - // pixels - float factor = mChart.getFactor(); + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); + PointF center = mChart.getCenterOffsets(); - for (int i = 0; i < limitLines.size(); i++) { + for (int i = 0; i < limitLines.size(); i++) { - LimitLine l = limitLines.get(i); + LimitLine l = limitLines.get(i); - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - float r = (l.getLimit() - mChart.getYChartMin()) * factor; + float r = (l.getLimit() - mChart.getYChartMin()) * factor; - Path limitPath = new Path(); + Path limitPath = new Path(); - for (int j = 0; j < mChart.getData().getXValCount(); j++) { + for (int j = 0; j < mChart.getData().getXValCount(); j++) { - PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); + PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); - if (j == 0) - limitPath.moveTo(p.x, p.y); - else - limitPath.lineTo(p.x, p.y); - } + if (j == 0) + limitPath.moveTo(p.x, p.y); + else + limitPath.lineTo(p.x, p.y); + } - limitPath.close(); + limitPath.close(); - c.drawPath(limitPath, mLimitLinePaint); - } - } + c.drawPath(limitPath, mLimitLinePaint); + } + } } From 5ab7242aaca81b4da142cbbccbf038fff6964934 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 25 Jul 2015 00:08:42 +0200 Subject: [PATCH 0438/1390] update version --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d522e73163..032bdb01ac 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.2' } ``` @@ -159,7 +159,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.1 + v2.1.2 ``` From cd96679bdaf837325243e5b2aec19a314bbf61d9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 25 Jul 2015 00:16:00 +0200 Subject: [PATCH 0439/1390] Update build.gradle --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index e198c821c4..5b50820b43 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="43" + android:versionName="2.1.2" > Date: Sat, 25 Jul 2015 17:13:47 +0200 Subject: [PATCH 0440/1390] Fix issue concerning combined-data reset (#851) --- .../mpchartexample/CombinedChartActivity.java | 14 +- .../mpchartexample/ScrollViewActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 467 +++++++++--------- .../charting/charts/CombinedChart.java | 9 +- .../mikephil/charting/data/BarEntry.java | 362 +++++++------- .../mikephil/charting/data/ChartData.java | 2 +- .../renderer/CombinedChartRenderer.java | 238 ++++----- 7 files changed, 559 insertions(+), 535 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 3d98460374..4a19d117cd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -207,10 +207,16 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleBarValues: { - for (DataSet set : mChart.getData().getDataSets()) { - if (set instanceof BarDataSet) - set.setDrawValues(!set.isDrawValuesEnabled()); - } +// for (DataSet set : mChart.getData().getDataSets()) { +// if (set instanceof BarDataSet) +// set.setDrawValues(!set.isDrawValuesEnabled()); +// } + + CombinedData data = new CombinedData(mMonths); + + data.setData(generateLineData()); + + mChart.setData(data); mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java index 68d57c31b3..61244bad2e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScrollViewActivity.java @@ -40,7 +40,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setPosition(XAxisPosition.BOTTOM); xAxis.setLabelsToSkip(0); xAxis.setDrawGridLines(false); - + mChart.getAxisLeft().setDrawGridLines(false); mChart.getLegend().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 96242ab8d3..ef3f295e80 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -1,6 +1,7 @@ - package com.xxmassdeveloper.mpchartexample; +import java.util.ArrayList; + import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -24,246 +25,236 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; -import java.util.ArrayList; - -public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, - OnChartValueSelectedListener { - - private BarChart mChart; - private SeekBar mSeekBarX, mSeekBarY; - private TextView tvX, tvY; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, - WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart); - - tvX = (TextView) findViewById(R.id.tvXMax); - tvY = (TextView) findViewById(R.id.tvYMax); - - mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); - mSeekBarX.setOnSeekBarChangeListener(this); - - mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); - mSeekBarY.setOnSeekBarChangeListener(this); - - mChart = (BarChart) findViewById(R.id.chart1); - mChart.setOnChartValueSelectedListener(this); - - mChart.setDescription(""); - - // if more than 60 entries are displayed in the chart, no values will be - // drawn - mChart.setMaxVisibleValueCount(60); - - // scaling can now only be done on x- and y-axis separately - mChart.setPinchZoom(false); - - mChart.setDrawGridBackground(false); - mChart.setDrawBarShadow(false); - - mChart.setDrawValueAboveBar(false); - - // change the position of the y-labels - YAxis yLabels = mChart.getAxisLeft(); - yLabels.setValueFormatter(new MyValueFormatter()); - mChart.getAxisRight().setEnabled(false); - - XAxis xLabels = mChart.getXAxis(); - xLabels.setPosition(XAxisPosition.TOP); - - // mChart.setDrawXLabels(false); - // mChart.setDrawYLabels(false); - - // setting data - mSeekBarX.setProgress(12); - mSeekBarY.setProgress(100); - - Legend l = mChart.getLegend(); - l.setPosition(LegendPosition.BELOW_CHART_RIGHT); - l.setFormSize(8f); - l.setFormToTextSpace(4f); - l.setXEntrySpace(6f); - - // mChart.setDrawLegend(false); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.bar, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - - switch (item.getItemId()) { - case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) - set.setDrawValues(!set.isDrawValuesEnabled()); - - mChart.invalidate(); - break; - } - case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); - break; - } - case R.id.actionTogglePinch: { - if (mChart.isPinchZoomEnabled()) - mChart.setPinchZoom(false); - else - mChart.setPinchZoom(true); - - mChart.invalidate(); - break; - } - case R.id.actionToggleAutoScaleMinMax: { - mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); - mChart.notifyDataSetChanged(); - break; - } - case R.id.actionToggleHighlightArrow: { - if (mChart.isDrawHighlightArrowEnabled()) - mChart.setDrawHighlightArrow(false); - else - mChart.setDrawHighlightArrow(true); - mChart.invalidate(); - break; - } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } - case R.id.animateX: { - mChart.animateX(3000); - break; - } - case R.id.animateY: { - mChart.animateY(3000); - break; - } - case R.id.animateXY: { - - mChart.animateXY(3000, 3000); - break; - } - case R.id.actionToggleFilter: { - - Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); - - if (!mChart.isFilteringEnabled()) { - mChart.enableFiltering(a); - } else { - mChart.disableFiltering(); - } - mChart.invalidate(); - break; - } - case R.id.actionSave: { - if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { - Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", - Toast.LENGTH_SHORT).show(); - } else - Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT) - .show(); - break; - } - } - return true; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - - tvX.setText("" + (mSeekBarX.getProgress() + 1)); - tvY.setText("" + (mSeekBarY.getProgress())); - - ArrayList xVals = new ArrayList(); - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - xVals.add(mMonths[i % mMonths.length]); - } - - ArrayList yVals1 = new ArrayList(); - - for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { - float mult = (mSeekBarY.getProgress() + 1); - float val1 = (float) (Math.random() * mult) + mult / 3; - float val2 = (float) (Math.random() * mult) + mult / 3; - float val3 = (float) (Math.random() * mult) + mult / 3; - - yVals1.add(new BarEntry(new float[] { - val1, val2, val3 - }, i)); - } - - BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); - set1.setColors(getColors()); - set1.setStackLabels(new String[] { - "Births", "Divorces", "Marriages" - }); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); - - BarData data = new BarData(xVals, dataSets); - data.setValueFormatter(new MyValueFormatter()); - - mChart.setData(data); - mChart.invalidate(); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - // TODO Auto-generated method stub - - } - - @Override - public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { - - BarEntry entry = (BarEntry) e; - Log.i("VAL SELECTED", - "Value: " + entry.getVals()[h.getStackIndex()]); - } - - @Override - public void onNothingSelected() { - // TODO Auto-generated method stub - - } - - private int[] getColors() { - - int stacksize = 3; - - // have as many colors as stack-values per entry - int []colors = new int[stacksize]; - - for(int i = 0; i < stacksize; i++) { - colors[i] = ColorTemplate.VORDIPLOM_COLORS[i]; - } - - return colors; - } +public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { + + private BarChart mChart; + private SeekBar mSeekBarX, mSeekBarY; + private TextView tvX, tvY; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart); + + tvX = (TextView) findViewById(R.id.tvXMax); + tvY = (TextView) findViewById(R.id.tvYMax); + + mSeekBarX = (SeekBar) findViewById(R.id.seekBar1); + mSeekBarX.setOnSeekBarChangeListener(this); + + mSeekBarY = (SeekBar) findViewById(R.id.seekBar2); + mSeekBarY.setOnSeekBarChangeListener(this); + + mChart = (BarChart) findViewById(R.id.chart1); + mChart.setOnChartValueSelectedListener(this); + + mChart.setDescription(""); + + // if more than 60 entries are displayed in the chart, no values will be + // drawn + mChart.setMaxVisibleValueCount(60); + + // scaling can now only be done on x- and y-axis separately + mChart.setPinchZoom(false); + + mChart.setDrawGridBackground(false); + mChart.setDrawBarShadow(false); + + mChart.setDrawValueAboveBar(false); + + // change the position of the y-labels + YAxis yLabels = mChart.getAxisLeft(); + yLabels.setValueFormatter(new MyValueFormatter()); + mChart.getAxisRight().setEnabled(false); + + XAxis xLabels = mChart.getXAxis(); + xLabels.setPosition(XAxisPosition.TOP); + + // mChart.setDrawXLabels(false); + // mChart.setDrawYLabels(false); + + // setting data + mSeekBarX.setProgress(12); + mSeekBarY.setProgress(100); + + Legend l = mChart.getLegend(); + l.setPosition(LegendPosition.BELOW_CHART_RIGHT); + l.setFormSize(8f); + l.setFormToTextSpace(4f); + l.setXEntrySpace(6f); + + // mChart.setDrawLegend(false); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.bar, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + switch (item.getItemId()) { + case R.id.actionToggleValues: { + for (DataSet set : mChart.getData().getDataSets()) + set.setDrawValues(!set.isDrawValuesEnabled()); + + mChart.invalidate(); + break; + } + case R.id.actionToggleHighlight: { + if (mChart.isHighlightEnabled()) + mChart.setHighlightEnabled(false); + else + mChart.setHighlightEnabled(true); + mChart.invalidate(); + break; + } + case R.id.actionTogglePinch: { + if (mChart.isPinchZoomEnabled()) + mChart.setPinchZoom(false); + else + mChart.setPinchZoom(true); + + mChart.invalidate(); + break; + } + case R.id.actionToggleAutoScaleMinMax: { + mChart.setAutoScaleMinMaxEnabled(!mChart.isAutoScaleMinMaxEnabled()); + mChart.notifyDataSetChanged(); + break; + } + case R.id.actionToggleHighlightArrow: { + if (mChart.isDrawHighlightArrowEnabled()) + mChart.setDrawHighlightArrow(false); + else + mChart.setDrawHighlightArrow(true); + mChart.invalidate(); + break; + } + case R.id.actionToggleStartzero: { + mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); + mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.invalidate(); + break; + } + case R.id.animateX: { + mChart.animateX(3000); + break; + } + case R.id.animateY: { + mChart.animateY(3000); + break; + } + case R.id.animateXY: { + + mChart.animateXY(3000, 3000); + break; + } + case R.id.actionToggleFilter: { + + Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); + + if (!mChart.isFilteringEnabled()) { + mChart.enableFiltering(a); + } else { + mChart.disableFiltering(); + } + mChart.invalidate(); + break; + } + case R.id.actionSave: { + if (mChart.saveToGallery("title" + System.currentTimeMillis(), 50)) { + Toast.makeText(getApplicationContext(), "Saving SUCCESSFUL!", Toast.LENGTH_SHORT).show(); + } else + Toast.makeText(getApplicationContext(), "Saving FAILED!", Toast.LENGTH_SHORT).show(); + break; + } + } + return true; + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + + tvX.setText("" + (mSeekBarX.getProgress() + 1)); + tvY.setText("" + (mSeekBarY.getProgress())); + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { + xVals.add(mMonths[i % mMonths.length]); + } + + ArrayList yVals1 = new ArrayList(); + + for (int i = 0; i < mSeekBarX.getProgress() + 1; i++) { + float mult = (mSeekBarY.getProgress() + 1); + float val1 = (float) (Math.random() * mult) + mult / 3; + float val2 = (float) (Math.random() * mult) + mult / 3; + float val3 = (float) (Math.random() * mult) + mult / 3; + + yVals1.add(new BarEntry(new float[] { val1, val2, val3 }, i)); + } + + BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2015"); + set1.setColors(getColors()); + set1.setStackLabels(new String[] { "Births", "Divorces", "Marriages" }); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); + + BarData data = new BarData(xVals, dataSets); + data.setValueFormatter(new MyValueFormatter()); + + mChart.setData(data); + mChart.invalidate(); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // TODO Auto-generated method stub + } + + @Override + public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + + BarEntry entry = (BarEntry) e; + + if (entry.isStacked()) + Log.i("VAL SELECTED", "Value: " + entry.getVals()[h.getStackIndex()]); + else + Log.i("VAL SELECTED", "Value: " + entry.getVal()); + } + + @Override + public void onNothingSelected() { + // TODO Auto-generated method stub + } + + private int[] getColors() { + + int stacksize = 3; + + // have as many colors as stack-values per entry + int[] colors = new int[stacksize]; + + for (int i = 0; i < stacksize; i++) { + colors[i] = ColorTemplate.VORDIPLOM_COLORS[i]; + } + + return colors; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index e3069640a0..8579f79ded 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -101,13 +101,18 @@ protected void calcMinMax() { mXChartMax = xmax; } } - - mDeltaX = Math.abs(mXChartMax - mXChartMin); + } else { + mXChartMin = 0f; + mXChartMax = mData.getXValCount()-1; } + + mDeltaX = Math.abs(mXChartMax - mXChartMin); } @Override public void setData(CombinedData data) { + mData = null; + mRenderer = null; super.setData(data); mRenderer = new CombinedChartRenderer(this, mAnimator, mViewPortHandler); mRenderer.initBuffers(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index d802613d41..4c07a1502c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -1,8 +1,5 @@ - package com.github.mikephil.charting.data; -import android.util.Log; - /** * Entry class for the BarChart. (especially stacked bars) * @@ -10,176 +7,191 @@ */ public class BarEntry extends Entry { - /** the values the stacked barchart holds */ - private float[] mVals; - - /** the sum of all negative values this entry (if stacked) contains */ - private float mNegativeSum; - - /** the sum of all positive values this entry (if stacked) contains */ - private float mPositiveSum; - - /** - * Constructor for stacked bar entries. Don't forget to order the - * stacked-values in an ascending order e.g. (-2,-1,0,1,2). - * - * @param vals - the stack values - * @param xIndex - */ - public BarEntry(float[] vals, int xIndex) { - super(calcSum(vals), xIndex); - - this.mVals = vals; - calcPosNegSum(); - } - - /** - * Constructor for normal bars (not stacked). - * - * @param val - * @param xIndex - */ - public BarEntry(float val, int xIndex) { - super(val, xIndex); - } - - /** - * Constructor for stacked bar entries. Don't forget to order the - * stacked-values in an ascending order e.g. (-2,-1,0,1,2). - * - * @param vals - the stack values - * @param xIndex - * @param label Additional description label. - */ - public BarEntry(float[] vals, int xIndex, String label) { - super(calcSum(vals), xIndex, label); - - this.mVals = vals; - calcPosNegSum(); - } - - /** - * Constructor for normal bars (not stacked). - * - * @param val - * @param xIndex - * @param data Spot for additional data this Entry represents. - */ - public BarEntry(float val, int xIndex, Object data) { - super(val, xIndex, data); - } - - /** - * Returns an exact copy of the BarEntry. - */ - public BarEntry copy() { - - BarEntry copied = new BarEntry(getVal(), getXIndex(), getData()); - copied.setVals(mVals); - return copied; - } - - /** - * Returns the stacked values this BarEntry represents, or null, if only a - * single value is represented (then, use getVal()). - * - * @return - */ - public float[] getVals() { - return mVals; - } - - /** - * Set the array of values this BarEntry should represent. - * - * @param vals - */ - public void setVals(float[] vals) { - setVal(calcSum(vals)); - mVals = vals; - calcPosNegSum(); - } - - /** - * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. - * @return - */ - @Override - public float getVal() { - return super.getVal(); - } - - public float getBelowSum(int stackIndex) { - - if (mVals == null) - return 0; - - float remainder = 0f; - int index = mVals.length - 1; - - while(index > stackIndex && index >= 0) { - remainder += mVals[index]; - index--; - } - - return remainder; - } - - /** - * Reuturns the sum of all positive values this entry (if stacked) contains. - * @return - */ - public float getPositiveSum() { - return mPositiveSum; - } - - /** - * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) - * @return - */ - public float getNegativeSum() { - return mNegativeSum; - } - - private void calcPosNegSum() { - - if(mVals == null) { - mNegativeSum = 0; - mPositiveSum = 0; - return; - } - - float sumNeg = 0f; - float sumPos = 0f; - - for (float f : mVals) { - if(f <= 0f) - sumNeg += Math.abs(f); - else - sumPos += f; - } - - mNegativeSum = sumNeg; - mPositiveSum = sumPos; - } - - - /** - * Calculates the sum across all values of the given stack. - * - * @param vals - * @return - */ - private static float calcSum(float[] vals) { - - if(vals == null) - return 0f; - - float sum = 0f; - - for (float f : vals) - sum += f; - - return sum; - } + /** the values the stacked barchart holds */ + private float[] mVals; + + /** the sum of all negative values this entry (if stacked) contains */ + private float mNegativeSum; + + /** the sum of all positive values this entry (if stacked) contains */ + private float mPositiveSum; + + /** + * Constructor for stacked bar entries. Don't forget to order the stacked-values in an ascending order e.g. + * (-2,-1,0,1,2). + * + * @param vals + * - the stack values, use at lest 2 + * @param xIndex + */ + public BarEntry(float[] vals, int xIndex) { + super(calcSum(vals), xIndex); + + this.mVals = vals; + calcPosNegSum(); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param val + * @param xIndex + */ + public BarEntry(float val, int xIndex) { + super(val, xIndex); + } + + /** + * Constructor for stacked bar entries. Don't forget to order the stacked-values in an ascending order e.g. + * (-2,-1,0,1,2). + * + * @param vals + * - the stack values, use at least 2 + * @param xIndex + * @param label + * Additional description label. + */ + public BarEntry(float[] vals, int xIndex, String label) { + super(calcSum(vals), xIndex, label); + + this.mVals = vals; + calcPosNegSum(); + } + + /** + * Constructor for normal bars (not stacked). + * + * @param val + * @param xIndex + * @param data + * Spot for additional data this Entry represents. + */ + public BarEntry(float val, int xIndex, Object data) { + super(val, xIndex, data); + } + + /** + * Returns an exact copy of the BarEntry. + */ + public BarEntry copy() { + + BarEntry copied = new BarEntry(getVal(), getXIndex(), getData()); + copied.setVals(mVals); + return copied; + } + + /** + * Returns the stacked values this BarEntry represents, or null, if only a single value is represented (then, use + * getVal()). + * + * @return + */ + public float[] getVals() { + return mVals; + } + + /** + * Set the array of values this BarEntry should represent. + * + * @param vals + */ + public void setVals(float[] vals) { + setVal(calcSum(vals)); + mVals = vals; + calcPosNegSum(); + } + + /** + * Returns the value of this BarEntry. If the entry is stacked, it returns the positive sum of all values. + * + * @return + */ + @Override + public float getVal() { + return super.getVal(); + } + + /** + * Returns true if this BarEntry is stacked (has a values array), false if not. + * + * @return + */ + public boolean isStacked() { + return mVals != null; + } + + public float getBelowSum(int stackIndex) { + + if (mVals == null) + return 0; + + float remainder = 0f; + int index = mVals.length - 1; + + while (index > stackIndex && index >= 0) { + remainder += mVals[index]; + index--; + } + + return remainder; + } + + /** + * Reuturns the sum of all positive values this entry (if stacked) contains. + * + * @return + */ + public float getPositiveSum() { + return mPositiveSum; + } + + /** + * Returns the sum of all negative values this entry (if stacked) contains. (this is a positive number) + * + * @return + */ + public float getNegativeSum() { + return mNegativeSum; + } + + private void calcPosNegSum() { + + if (mVals == null) { + mNegativeSum = 0; + mPositiveSum = 0; + return; + } + + float sumNeg = 0f; + float sumPos = 0f; + + for (float f : mVals) { + if (f <= 0f) + sumNeg += Math.abs(f); + else + sumPos += f; + } + + mNegativeSum = sumNeg; + mPositiveSum = sumPos; + } + + /** + * Calculates the sum across all values of the given stack. + * + * @param vals + * @return + */ + private static float calcSum(float[] vals) { + + if (vals == null) + return 0f; + + float sum = 0f; + + for (float f : vals) + sum += f; + + return sum; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 8bcc59bccc..be59c48988 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -433,7 +433,7 @@ public List getDataSets() { * situations. * * @param dataSets the DataSet array to search - * @param type + * @param label * @param ignorecase if true, the search is not case-sensitive * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 2e098ce5a2..596200b994 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -1,127 +1,137 @@ - package com.github.mikephil.charting.renderer; +import java.util.ArrayList; +import java.util.List; + import android.graphics.Canvas; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.ArrayList; -import java.util.List; - +/** + * Renderer class that is responsible for rendering multiple different data-types. + */ public class CombinedChartRenderer extends DataRenderer { - /** - * all rederers for the different kinds of data this combined-renderer can - * draw - */ - protected List mRenderers; - - public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { - super(animator, viewPortHandler); - - createRenderers(chart, animator, viewPortHandler); - } - - /** - * Creates the renderers needed for this combined-renderer in the required - * order. Also takes the DrawOrder into consideration. - * - * @param chart - * @param animator - * @param viewPortHandler - */ - protected void createRenderers(CombinedChart chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { - - mRenderers = new ArrayList(); - - DrawOrder[] orders = chart.getDrawOrder(); - - for (DrawOrder order : orders) { - - switch (order) { - case BAR: - if (chart.getBarData() != null) - mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); - break; - - case BUBBLE: - if (chart.getBubbleData() != null) - mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); - break; - case LINE: - if (chart.getLineData() != null) - mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); - break; - case CANDLE: - if (chart.getCandleData() != null) - mRenderers.add(new CandleStickChartRenderer(chart, animator, - viewPortHandler)); - break; - case SCATTER: - if (chart.getScatterData() != null) - mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); - break; - } - } - } - - @Override - public void initBuffers() { - - for (DataRenderer renderer : mRenderers) - renderer.initBuffers(); - } - - @Override - public void drawData(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawData(c); - } - - @Override - public void drawValues(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawValues(c); - } - - @Override - public void drawExtras(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawExtras(c); - } - - @Override - public void drawHighlighted(Canvas c, Highlight[] indices) { - for (DataRenderer renderer : mRenderers) - renderer.drawHighlighted(c, indices); - } - - @Override - public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { - for (DataRenderer renderer : mRenderers) - renderer.calcXBounds(chart, xAxisModulus); - } - - /** - * Returns the sub-renderer object at the specified index. - * - * @param index - * @return - */ - public DataRenderer getSubRenderer(int index) { - if (index >= mRenderers.size() || index < 0) - return null; - else - return mRenderers.get(index); - } + /** + * all rederers for the different kinds of data this combined-renderer can draw + */ + protected List mRenderers; + + public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + + createRenderers(chart, animator, viewPortHandler); + } + + /** + * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into + * consideration. + * + * @param chart + * @param animator + * @param viewPortHandler + */ + protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { + + mRenderers = new ArrayList(); + + DrawOrder[] orders = chart.getDrawOrder(); + + for (DrawOrder order : orders) { + + switch (order) { + case BAR: + if (chart.getBarData() != null) + mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); + break; + case BUBBLE: + if (chart.getBubbleData() != null) + mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); + break; + case LINE: + if (chart.getLineData() != null) + mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); + break; + case CANDLE: + if (chart.getCandleData() != null) + mRenderers.add(new CandleStickChartRenderer(chart, animator, viewPortHandler)); + break; + case SCATTER: + if (chart.getScatterData() != null) + mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); + break; + } + } + } + + @Override + public void initBuffers() { + + for (DataRenderer renderer : mRenderers) + renderer.initBuffers(); + } + + @Override + public void drawData(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawData(c); + } + + @Override + public void drawValues(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawValues(c); + } + + @Override + public void drawExtras(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawExtras(c); + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + for (DataRenderer renderer : mRenderers) + renderer.drawHighlighted(c, indices); + } + + @Override + public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { + for (DataRenderer renderer : mRenderers) + renderer.calcXBounds(chart, xAxisModulus); + } + + /** + * Returns the sub-renderer object at the specified index. + * + * @param index + * @return + */ + public DataRenderer getSubRenderer(int index) { + if (index >= mRenderers.size() || index < 0) + return null; + else + return mRenderers.get(index); + } + + /** + * Returns all sub-renderers. + * + * @return + */ + public List getSubRenderers() { + return mRenderers; + } + + public void setSubRenderers(List renderers) { + this.mRenderers = renderers; + } } From 54023aaf566e21469f9672139f3ef2a9f8074a53 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 25 Jul 2015 17:14:41 +0200 Subject: [PATCH 0441/1390] Undo testing changes --- .../mpchartexample/CombinedChartActivity.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 4a19d117cd..3d98460374 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -207,16 +207,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleBarValues: { -// for (DataSet set : mChart.getData().getDataSets()) { -// if (set instanceof BarDataSet) -// set.setDrawValues(!set.isDrawValuesEnabled()); -// } - - CombinedData data = new CombinedData(mMonths); - - data.setData(generateLineData()); - - mChart.setData(data); + for (DataSet set : mChart.getData().getDataSets()) { + if (set instanceof BarDataSet) + set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; From 464bbd9133b61f35c6b402efc6a45670575ffccf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jul 2015 20:39:23 +0200 Subject: [PATCH 0442/1390] Fixed issue in vertical stacked bars --- .../xxmassdeveloper/mpchartexample/StackedBarActivity.java | 7 +++++-- .../src/com/github/mikephil/charting/buffer/BarBuffer.java | 6 +++--- .../mikephil/charting/renderer/BarChartRenderer.java | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index ef3f295e80..4edc128f74 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -204,7 +204,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { yVals1.add(new BarEntry(new float[] { val1, val2, val3 }, i)); } - BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2015"); + BarDataSet set1 = new BarDataSet(yVals1, "Statistics Vienna 2014"); set1.setColors(getColors()); set1.setStackLabels(new String[] { "Births", "Divorces", "Marriages" }); @@ -221,11 +221,13 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { @Override public void onStartTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub + } @Override public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub + } @Override @@ -233,7 +235,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { BarEntry entry = (BarEntry) e; - if (entry.isStacked()) + if (entry.getVals() != null) Log.i("VAL SELECTED", "Value: " + entry.getVals()[h.getStackIndex()]); else Log.i("VAL SELECTED", "Value: " + entry.getVal()); @@ -242,6 +244,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { @Override public void onNothingSelected() { // TODO Auto-generated method stub + } private int[] getColors() { diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index c143935f74..50de771824 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -85,7 +85,7 @@ public void feed(List entries) { } else { float posY = 0f; - float negY = 0f; + float negY = -e.getNegativeSum(); float yStart = 0f; // fill the stack @@ -99,8 +99,8 @@ public void feed(List entries) { posY = yStart; } else { y = negY; - yStart = negY + value; - negY = yStart; + yStart = negY + Math.abs(value); + negY += Math.abs(value); } float left = x - barWidth + barSpaceHalf; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index a07956ecdf..db2c80d7ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -262,7 +262,7 @@ public void drawValues(Canvas c) { float[] transformed = new float[vals.length * 2]; float posY = 0f; - float negY = 0f; + float negY = -e.getNegativeSum(); for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { @@ -273,8 +273,8 @@ public void drawValues(Canvas c) { posY += value; y = posY; } else { - negY += value; y = negY; + negY -= value; } transformed[k + 1] = y * mAnimator.getPhaseY(); From af9ac446cfe2f56177b2aac71aefd081ca23310b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 26 Jul 2015 22:00:02 +0200 Subject: [PATCH 0443/1390] More fixes. --- .../com/github/mikephil/charting/data/DataSet.java | 3 --- .../charting/highlight/BarHighlighter.java | 14 +++++--------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index f59593772a..83cb4ae224 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -129,9 +129,6 @@ protected void calcMinMax(int start, int end) { for (int i = start; i <= endValue; i++) { - if(i >= mYVals.size()) - break; - Entry e = mYVals.get(i); if (e != null && !Float.isNaN(e.getVal())) { diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index f521975a19..07e476acd6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -99,18 +99,14 @@ protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xInde BarEntry entry = set.getEntryForXIndex(xIndex); - if (entry.getVals() == null) + if (entry == null || entry.getVals() == null) return old; - if (entry != null) { + Range[] ranges = getRanges(entry); + int stackIndex = getClosestStackIndex(ranges, (float) yValue); - Range[] ranges = getRanges(entry); - int stackIndex = getClosestStackIndex(ranges, (float) yValue); - - Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); - return h; - } else - return null; + Highlight h = new Highlight(xIndex, dataSetIndex, stackIndex, ranges[stackIndex]); + return h; } /** From 39b4e0f70d58748c925888217249753b9376427c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 27 Jul 2015 23:10:45 +0200 Subject: [PATCH 0444/1390] Added outofbounds check in getEntryForHighlight (#898) --- .../src/com/github/mikephil/charting/data/BarEntry.java | 6 ++---- .../src/com/github/mikephil/charting/data/ChartData.java | 5 ++++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index 4c07a1502c..c21bf791cf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -17,8 +17,7 @@ public class BarEntry extends Entry { private float mPositiveSum; /** - * Constructor for stacked bar entries. Don't forget to order the stacked-values in an ascending order e.g. - * (-2,-1,0,1,2). + * Constructor for stacked bar entries. * * @param vals * - the stack values, use at lest 2 @@ -42,8 +41,7 @@ public BarEntry(float val, int xIndex) { } /** - * Constructor for stacked bar entries. Don't forget to order the stacked-values in an ascending order e.g. - * (-2,-1,0,1,2). + * Constructor for stacked bar entries. * * @param vals * - the stack values, use at least 2 diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index be59c48988..10513dac36 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -486,7 +486,10 @@ protected String[] getDataSetLabels() { * @return the entry that is highlighted */ public Entry getEntryForHighlight(Highlight highlight) { - return mDataSets.get(highlight.getDataSetIndex()).getEntryForXIndex( + if(highlight.getDataSetIndex() >= mDataSets.size()) + return null; + else + return mDataSets.get(highlight.getDataSetIndex()).getEntryForXIndex( highlight.getXIndex()); } From 6dada9eaea33c9333ba7f7ab18b8f712a4be4ae8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 27 Jul 2015 23:50:40 +0200 Subject: [PATCH 0445/1390] Fixed issue concerning grouped-barchart (issue danielgindi/ios-charts#242) --- .../HorizontalBarChartActivity.java | 15 ++++----------- .../mikephil/charting/buffer/BarBuffer.java | 4 ++-- .../charting/buffer/HorizontalBarBuffer.java | 4 ++-- .../mikephil/charting/utils/Transformer.java | 6 ++++-- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index c98eb2ad8b..4df4497da1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -238,21 +238,15 @@ public void onStopTrackingTouch(SeekBar seekBar) { private void setData(int count, float range) { - ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { - xVals.add(mMonths[i % 12]); - } - ArrayList yVals1 = new ArrayList(); + ArrayList xVals = new ArrayList(); for (int i = 0; i < count; i++) { - float mult = (range + 1); - float val = (float) (Math.random() * mult); - yVals1.add(new BarEntry(val, i)); + xVals.add(mMonths[i % 12]); + yVals1.add(new BarEntry((float) (Math.random() * range), i)); } - BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); - set1.setBarSpacePercent(35f); + BarDataSet set1 = new BarDataSet(yVals1, "DataSet 1"); ArrayList dataSets = new ArrayList(); dataSets.add(set1); @@ -261,7 +255,6 @@ private void setData(int count, float range) { data.setValueTextSize(10f); data.setValueTypeface(tf); - mChart.setDrawValueAboveBar(false); mChart.setData(data); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 50de771824..7387231698 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -56,8 +56,8 @@ public void feed(List entries) { BarEntry e = entries.get(i); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + i * dataSetOffset + mDataSetIndex - + mGroupSpace * i + groupSpaceHalf; + float x = e.getXIndex() + e.getXIndex() * dataSetOffset + mDataSetIndex + + mGroupSpace * e.getXIndex() + groupSpaceHalf; float y = e.getVal(); float [] vals = e.getVals(); diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 41fd70551e..8555206fc9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -26,8 +26,8 @@ public void feed(List entries) { BarEntry e = entries.get(i); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + i * dataSetOffset + mDataSetIndex - + mGroupSpace * i + groupSpaceHalf; + float x = e.getXIndex() + e.getXIndex() * dataSetOffset + mDataSetIndex + + mGroupSpace * e.getXIndex() + groupSpaceHalf; float y = e.getVal(); float[] vals = e.getVals(); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 83bac18200..f74c8c0227 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -224,9 +224,10 @@ public float[] generateTransformedValuesBarChart(List entries, for (int j = 0; j < valuePoints.length; j += 2) { Entry e = entries.get(j / 2); + int i = e.getXIndex(); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + space * (j / 2) + float x = e.getXIndex() + i * (setCount - 1) + dataSet + space * i + space / 2f; float y = e.getVal(); @@ -258,9 +259,10 @@ public float[] generateTransformedValuesHorizontalBarChart(List for (int j = 0; j < valuePoints.length; j += 2) { Entry e = entries.get(j / 2); + int i = e.getXIndex(); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + (j / 2 * (setCount - 1)) + dataSet + space * (j / 2) + float x = e.getXIndex() + i * (setCount - 1) + dataSet + space * i + space / 2f ; float y = e.getVal(); From a451672c4345a8404f5176a24eefab91dbdad65f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 28 Jul 2015 19:08:44 +0200 Subject: [PATCH 0446/1390] Code cleanup (#900). --- .../com/github/mikephil/charting/charts/Chart.java | 12 ------------ .../github/mikephil/charting/charts/LineChart.java | 7 ------- .../github/mikephil/charting/charts/PieChart.java | 2 -- .../mikephil/charting/charts/ScatterChart.java | 12 ------------ 4 files changed, 33 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 576d0a11df..e9a0cf6d27 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -370,13 +370,6 @@ protected void calculateFormatter(float min, float max) { /** flag that indicates if offsets calculation has already been done or not */ private boolean mOffsetsCalculated = false; - /** - * Bitmap object used for drawing. This is necessary because hardware - * acceleration uses OpenGL which only allows a specific texture size to be - * drawn on the canvas directly. - **/ - protected Bitmap mDrawBitmap; - /** paint object used for drawing the bitmap */ protected Paint mDrawPaint; @@ -1594,12 +1587,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { Log.i(LOG_TAG, "OnSizeChanged()"); if (w > 0 && h > 0 && w < 10000 && h < 10000) { - // create a new bitmap with the new dimensions - - if (mDrawBitmap != null) - mDrawBitmap.recycle(); - mDrawBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_4444); mViewPortHandler.setChartDimens(w, h); if (mLogEnabled) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index dc3ed28b9a..9afa24ab5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -35,7 +35,6 @@ protected void init() { super.init(); mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); - mFillFormatter = new DefaultFillFormatter(); } @@ -43,12 +42,6 @@ protected void init() { protected void calcMinMax() { super.calcMinMax(); - // // if there is only one value in the chart - // if (mOriginalData.getYValCount() == 1 - // || mOriginalData.getYValCount() <= mOriginalData.getDataSetCount()) { - // mDeltaX = 1; - // } - if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 7ae3007149..5e23b5af90 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -113,8 +113,6 @@ protected void onDraw(Canvas canvas) { mLegendRenderer.renderLegend(canvas); drawDescription(canvas); - - // canvas.drawBitmap(mDrawBitmap, 0, 0, mDrawPaint); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 3c0e8f852e..0a9303f173 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -46,18 +46,6 @@ protected void init() { mXChartMin = -0.5f; } - // @Override - // public void calculateOffsets() { - // super.calculateOffsets(); - // - // float offset = mData.getGreatestShapeSize() / 2f; - // mViewPortHandler.restrainViewPort(mViewPortHandler.offsetLeft() - offset, - // mViewPortHandler.offsetTop(), mViewPortHandler.offsetRight() - offset, - // mViewPortHandler.offsetBottom()); - // - // prepareOffsetMatrix(); - // } - @Override protected void calcMinMax() { super.calcMinMax(); From 4bb9076debba4edd69dfe693e003a527d06db4ed Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Jul 2015 18:25:04 +0200 Subject: [PATCH 0447/1390] Fix markerposition for grouped bars --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c3d1c72127..6c9df411c0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -531,10 +531,8 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { BarData bd = (BarData) mData; float space = bd.getGroupSpace(); - float j = mData.getDataSetByIndex(dataSetIndex) - .getEntryPosition(e); - float x = (j * (mData.getDataSetCount() - 1)) + dataSetIndex + space * j + space + float x = e.getXIndex() * (mData.getDataSetCount() - 1) + dataSetIndex + space * e.getXIndex() + space / 2f; xPos += x; From 4aabae1de084a077f0a396b4514590e8974f61ca Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 29 Jul 2015 18:39:21 +0200 Subject: [PATCH 0448/1390] Allow setting transparency amout for transparent circle / hole (#902). --- .../mpchartexample/PieChartActivity.java | 3 ++- .../mikephil/charting/charts/PieChart.java | 24 +++++++++++++++++-- .../charting/renderer/PieChartRenderer.java | 7 +++--- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 7e9f2cc52b..613426259c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -67,8 +67,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawHoleEnabled(true); mChart.setHoleColorTransparent(true); - + mChart.setTransparentCircleColor(Color.WHITE); + mChart.setTransparentCircleAlpha(110); mChart.setHoleRadius(58f); mChart.setTransparentCircleRadius(61f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 5e23b5af90..151056cfc3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -3,6 +3,7 @@ import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.PointF; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; @@ -66,7 +67,7 @@ public class PieChart extends PieRadarChartBase { /** * the radius of the transparent circle next to the chart-hole in the center */ - private float mTransparentCircleRadiusPercent = 55f; + protected float mTransparentCircleRadiusPercent = 55f; /** if enabled, centertext is drawn */ private boolean mDrawCenterText = true; @@ -455,8 +456,16 @@ public float getHoleRadius() { return mHoleRadiusPercent; } + /** + * Sets the color the transparent-circle should have. + * @param color + */ public void setTransparentCircleColor(int color) { - ((PieChartRenderer) mRenderer).getPaintTransparentCircle().setColor(color); + + Paint p = ((PieChartRenderer) mRenderer).getPaintTransparentCircle(); + int alpha = p.getAlpha(); + p.setColor(color); + p.setAlpha(alpha); } /** @@ -475,6 +484,17 @@ public float getTransparentCircleRadius() { return mTransparentCircleRadiusPercent; } + /** + * Sets the amount of transparency the transparent circle should have 0 = fully transparent, 255 = fully opaque. + * Default value is 100. + * + * @param alpha + * 0-255 + */ + public void setTransparentCircleAlpha(int alpha) { + ((PieChartRenderer) mRenderer).getPaintTransparentCircle().setAlpha(alpha); + } + /** * set this to true to draw the x-value text into the pie slices * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 4ce679b2ff..819e6a938b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -63,6 +63,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mTransparentCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTransparentCirclePaint.setColor(Color.WHITE); mTransparentCirclePaint.setStyle(Style.FILL); + mTransparentCirclePaint.setAlpha(100); mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); @@ -260,16 +261,16 @@ protected void drawHole(Canvas c) { if (transparentCircleRadius > holeRadius && mAnimator.getPhaseX() >= 1f && mAnimator.getPhaseY() >= 1f) { - int color = mTransparentCirclePaint.getColor(); + //int color = mTransparentCirclePaint.getColor(); // make transparent - mTransparentCirclePaint.setColor(color & 0x60FFFFFF); + //mTransparentCirclePaint.setColor(color & 0x60FFFFFF); // draw the transparent-circle mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * transparentCircleRadius, mTransparentCirclePaint); - mTransparentCirclePaint.setColor(color); + //mTransparentCirclePaint.setColor(color); } // draw the hole-circle From d722da590a8ea429b0e416288f5f12ff1f6d3498 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 31 Jul 2015 22:36:36 +0200 Subject: [PATCH 0449/1390] Minor fix in BarChart --- .../github/mikephil/charting/charts/BarChart.java | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 6f83efd179..f118c145b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -76,18 +76,8 @@ protected void calcMinMax() { // extend xDelta to make space for multiple datasets (if ther are one) mDeltaX *= mData.getDataSetCount(); - int maxEntry = 0; - - for (int i = 0; i < mData.getDataSetCount(); i++) { - - DataSet set = mData.getDataSetByIndex(i); - - if (maxEntry < set.getEntryCount()) - maxEntry = set.getEntryCount(); - } - float groupSpace = mData.getGroupSpace(); - mDeltaX += maxEntry * groupSpace; + mDeltaX += mData.getXValCount() * groupSpace; mXChartMax = mDeltaX - mXChartMin; } From d473196b36577f0bdfa5ea2fe490693cd8182bd6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 31 Jul 2015 23:59:40 +0200 Subject: [PATCH 0450/1390] Update gradle and manifest --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 5b50820b43..18a347ea17 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="44" + android:versionName="2.1.3" > Date: Sat, 1 Aug 2015 00:10:42 +0200 Subject: [PATCH 0451/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 032bdb01ac..366af2e6f2 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.2' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.3' } ``` @@ -159,7 +159,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.2 + v2.1.3 ``` From 51f79400392dc68e9ae57a6253a60f9833e3781d Mon Sep 17 00:00:00 2001 From: Davide Oddone Date: Sun, 2 Aug 2015 23:50:53 +0200 Subject: [PATCH 0452/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index 4a97a59e6d..cc6cb3542a 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -38,3 +38,6 @@ https://play.google.com/store/apps/details?id=ru.vdmodule.androidmetrix Poker Manager https://play.google.com/store/apps/details?id=com.pokermanagerpro + +Speaker Recognition +https://github.com/C-piace-il-C/Speaker_Recognition From 1a52eff83352d20fc4d7b1fc11620f6d4b591908 Mon Sep 17 00:00:00 2001 From: Dakota Sanchez Date: Sun, 2 Aug 2015 21:50:55 -0700 Subject: [PATCH 0453/1390] Do not serialize ValueFormetter interface member variable --- MPChartLib/src/com/github/mikephil/charting/data/DataSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 83cb4ae224..0784f203b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -64,7 +64,7 @@ public abstract class DataSet { private Typeface mValueTypeface; /** custom formatter that is used instead of the auto-formatter if set */ - protected ValueFormatter mValueFormatter; + protected transient ValueFormatter mValueFormatter; /** this specifies which axis this DataSet should be plotted against */ protected AxisDependency mAxisDependency = AxisDependency.LEFT; From c9623fc74be3a9d0db8cebf3c94353fe72da0c4e Mon Sep 17 00:00:00 2001 From: Abhijit Das Date: Sun, 9 Aug 2015 18:24:50 +0530 Subject: [PATCH 0454/1390] Updated the list of projects Added a new project that uses the following library. --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index cc6cb3542a..526e9ef763 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -41,3 +41,6 @@ https://play.google.com/store/apps/details?id=com.pokermanagerpro Speaker Recognition https://github.com/C-piace-il-C/Speaker_Recognition + +ExpenseDroid - Expense Manager +https://play.google.com/store/apps/details?id=com.tphoneix.avi.myapplication From d51de23d8a58f11223bc704c74f3da9db3474a9d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 11 Aug 2015 16:26:37 +0300 Subject: [PATCH 0455/1390] More control over limit line labels' position --- .../mpchartexample/LineChartActivity1.java | 21 +++++----- .../charting/components/LimitLine.java | 4 +- .../charting/renderer/XAxisRenderer.java | 31 ++++++++++---- .../XAxisRendererHorizontalBarChart.java | 41 +++++++++++++------ .../charting/renderer/YAxisRenderer.java | 34 ++++++++++++--- .../YAxisRendererHorizontalBarChart.java | 30 ++++++++++---- 6 files changed, 116 insertions(+), 45 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3c9f2ebdb9..eedb3ababc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; +import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; @@ -95,25 +96,25 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setMarkerView(mv); // x-axis limit line -// LimitLine llXAxis = new LimitLine(10f, "Index 10"); -// llXAxis.setLineWidth(4f); -// llXAxis.enableDashedLine(10f, 10f, 0f); -// llXAxis.setLabelPosition(LimitLabelPosition.POS_RIGHT); -// llXAxis.setTextSize(10f); -// -// XAxis xAxis = mChart.getXAxis(); -// xAxis.addLimitLine(llXAxis); + LimitLine llXAxis = new LimitLine(10f, "Index 10"); + llXAxis.setLineWidth(4f); + llXAxis.enableDashedLine(10f, 10f, 0f); + llXAxis.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); + llXAxis.setTextSize(10f); + + XAxis xAxis = mChart.getXAxis(); + xAxis.addLimitLine(llXAxis); LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); ll1.enableDashedLine(10f, 10f, 0f); - ll1.setLabelPosition(LimitLabelPosition.POS_RIGHT); + ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); ll1.setTextSize(10f); LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); ll2.setLineWidth(4f); ll2.enableDashedLine(10f, 10f, 0f); - ll2.setLabelPosition(LimitLabelPosition.POS_RIGHT); + ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); ll2.setTextSize(10f); YAxis leftAxis = mChart.getAxisLeft(); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java index b332761c22..f7bd8e5a05 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java @@ -41,11 +41,11 @@ public class LimitLine { private DashPathEffect mDashPathEffect = null; /** indicates the position of the LimitLine label */ - private LimitLabelPosition mLabelPosition = LimitLabelPosition.POS_RIGHT; + private LimitLabelPosition mLabelPosition = LimitLabelPosition.RIGHT_TOP; /** enum that indicates the position of the LimitLine label */ public enum LimitLabelPosition { - POS_LEFT, POS_RIGHT + LEFT_TOP, LEFT_BOTTOM, RIGHT_TOP, RIGHT_BOTTOM } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 76a1ddd7d9..f56066b811 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -237,21 +237,36 @@ public void renderLimitLines(Canvas c) { // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { - float xOffset = l.getLineWidth(); - float add = Utils.convertDpToPixel(4f); - mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - float yOffset = Utils.calcTextHeight(mLimitLinePaint, label) + add / 2f; + float xOffset = l.getLineWidth(); + float add = Utils.convertDpToPixel(4f); + float yOffset = add / 2f; + + final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + + if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { + + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); + } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + } else { - if (l.getLabelPosition() == LimitLine.LimitLabelPosition.POS_RIGHT) { - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); - } else { - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset, mLimitLinePaint); + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index d27916e23c..9edcb80b00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -213,28 +213,45 @@ public void renderLimitLines(Canvas c) { // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) - / 2f; - mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - if (l.getLabelPosition() == LimitLine.LimitLabelPosition.POS_RIGHT) { + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + float xOffset = Utils.convertDpToPixel(4f); + float yOffset = l.getLineWidth() + labelLineHeight; + + final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + + if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, mViewPortHandler.contentRight() - - xOffset, - pts[1] - yOffset, mLimitLinePaint); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); + + } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] + yOffset, mLimitLinePaint); + + } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, + mViewPortHandler.contentLeft() + xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); + + } else { - } else { mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, mViewPortHandler.offsetLeft() - + xOffset, - pts[1] - yOffset, mLimitLinePaint); + c.drawText(label, + mViewPortHandler.offsetLeft() + xOffset, + pts[1] + yOffset, mLimitLinePaint); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index b437eca7fb..9fda5280ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -319,23 +319,45 @@ public void renderLimitLines(Canvas c) { // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + Utils.calcTextHeight(mLimitLinePaint, label) / 2f; - mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + float xOffset = Utils.convertDpToPixel(4f); + float yOffset = l.getLineWidth() + labelLineHeight; + + final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + + if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); + + } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, mViewPortHandler.contentRight() - xOffset, pts[1] - yOffset, mLimitLinePaint); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] + yOffset, mLimitLinePaint); + + } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, + mViewPortHandler.contentLeft() + xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); } else { + mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, mViewPortHandler.offsetLeft() + xOffset, pts[1] - yOffset, mLimitLinePaint); + c.drawText(label, + mViewPortHandler.offsetLeft() + xOffset, + pts[1] + yOffset, mLimitLinePaint); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 79e3aa7faa..c23656e4af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -222,22 +222,38 @@ public void renderLimitLines(Canvas c) { // if drawing the limit-value label is enabled if (label != null && !label.equals("")) { - float xOffset = l.getLineWidth(); - float add = Utils.convertDpToPixel(4f); - mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - - float yOffset = Utils.calcTextHeight(mLimitLinePaint, label) + add / 2f; - if (l.getLabelPosition() == LimitLabelPosition.POS_RIGHT) { + float xOffset = l.getLineWidth(); + float add = Utils.convertDpToPixel(4f); + float yOffset = add / 2f; + + final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + + if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { + + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + + mLimitLinePaint.setTextAlign(Align.LEFT); c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); + } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); } else { - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset, mLimitLinePaint); + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); } + } } } From 35d6928422f8b110f09df13616ab8f8fe62a6123 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 12 Aug 2015 16:07:08 +0300 Subject: [PATCH 0456/1390] Handle negative values when startAtZeroEnabled --- .../github/mikephil/charting/charts/BarLineChartBase.java | 8 ++++---- .../com/github/mikephil/charting/charts/RadarChart.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 6c9df411c0..d2f0dd4e06 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -377,8 +377,8 @@ protected void calcMinMax() { if (mAxisLeft.mAxisMinimum < 0f && mAxisLeft.mAxisMaximum < 0f) { // If the values are all negative, let's stay in the negative zone mAxisLeft.mAxisMaximum = 0f; - } else { - // We have positive values, stay in the positive zone + } else if (mAxisLeft.mAxisMinimum >= 0f) { + // We have positive values only, stay in the positive zone mAxisLeft.mAxisMinimum = 0f; } } @@ -387,8 +387,8 @@ protected void calcMinMax() { if (mAxisRight.mAxisMinimum < 0.0 && mAxisRight.mAxisMaximum < 0.0) { // If the values are all negative, let's stay in the negative zone mAxisRight.mAxisMaximum = 0f; - } else { - // We have positive values, stay in the positive zone + } else if (mAxisRight.mAxisMinimum >= 0f) { + // We have positive values only, stay in the positive zone mAxisRight.mAxisMinimum = 0f; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 5165995181..1e64e56bb3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -107,7 +107,7 @@ protected void calcMinMax() { // consider starting at zero (0) if (mYAxis.isStartAtZeroEnabled()) - mYAxis.mAxisMinimum = 0f; + mYAxis.mAxisMinimum = Math.min(0f, mYAxis.mAxisMinimum); mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); } From 5f8666b4ee3a427bb5e2c33bab0726d171e9296d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 12 Aug 2015 16:13:36 +0300 Subject: [PATCH 0457/1390] Prevent yAxis in radar charts from bleeding into another x index on the other side --- .../charting/renderer/YAxisRendererRadarChart.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index a2399fcb6c..f54f3b8579 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -82,7 +82,13 @@ protected void computeAxisValues(float min, float max) { } else { - double first = Math.ceil(yMin / interval) * interval; + final double rawCount = yMin / interval; + double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; + + if (first < yMin && mYAxis.isStartAtZeroEnabled()) { + // Force the first label to be at the 0 (or smallest negative value) + first = yMin; + } if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) first = 0.0; @@ -118,6 +124,12 @@ protected void computeAxisValues(float min, float max) { mYAxis.mDecimals = 0; } + if (!mYAxis.isStartAtZeroEnabled() && mYAxis.mEntries[0] < yMin) { + // If startAtZero is disabled, and the first label is lower that the axis minimum, + // Then adjust the axis minimum + mYAxis.mAxisMinimum = mYAxis.mEntries[0]; + } + mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); } From 72e4ec3c5520c1b6f91b149fde8bc5bf31dced52 Mon Sep 17 00:00:00 2001 From: Vladislav Bauer Date: Sun, 16 Aug 2015 06:13:46 +0600 Subject: [PATCH 0458/1390] Remove redundant modifiers from interfaces --- .../charting/animation/EasingFunction.java | 3 +-- .../charting/interfaces/BarDataProvider.java | 9 +++---- ...arLineScatterCandleBubbleDataProvider.java | 12 ++++----- .../interfaces/BubbleDataProvider.java | 2 +- .../interfaces/CandleDataProvider.java | 2 +- .../charting/interfaces/ChartInterface.java | 25 +++++++++---------- .../charting/interfaces/LineDataProvider.java | 7 +++--- .../interfaces/ScatterDataProvider.java | 2 +- .../listener/OnChartGestureListener.java | 13 +++++----- .../OnChartValueSelectedListener.java | 5 ++-- .../charting/listener/OnDrawListener.java | 6 ++--- .../charting/utils/ColorFormatter.java | 3 +-- .../charting/utils/FillFormatter.java | 3 +-- .../charting/utils/ValueFormatter.java | 3 +-- 14 files changed, 43 insertions(+), 52 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java index 54202984d0..98d934da23 100644 --- a/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java +++ b/MPChartLib/src/com/github/mikephil/charting/animation/EasingFunction.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.animation; import android.animation.TimeInterpolator; @@ -12,5 +11,5 @@ public interface EasingFunction extends TimeInterpolator { @Override - public float getInterpolation(float input); + float getInterpolation(float input); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java index 4a55fd11a2..3de8ee3e48 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java @@ -4,9 +4,8 @@ public interface BarDataProvider extends BarLineScatterCandleBubbleDataProvider { - public BarData getBarData(); - public boolean isDrawBarShadowEnabled(); - public boolean isDrawValueAboveBarEnabled(); - public boolean isDrawHighlightArrowEnabled(); - //public boolean isDrawValuesForWholeStackEnabled(); + BarData getBarData(); + boolean isDrawBarShadowEnabled(); + boolean isDrawValueAboveBarEnabled(); + boolean isDrawHighlightArrowEnabled(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java index 1af33d86e2..c92d1b513f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java @@ -6,12 +6,12 @@ public interface BarLineScatterCandleBubbleDataProvider extends ChartInterface { - public Transformer getTransformer(AxisDependency axis); - public int getMaxVisibleCount(); - public boolean isInverted(AxisDependency axis); + Transformer getTransformer(AxisDependency axis); + int getMaxVisibleCount(); + boolean isInverted(AxisDependency axis); - public int getLowestVisibleXIndex(); - public int getHighestVisibleXIndex(); + int getLowestVisibleXIndex(); + int getHighestVisibleXIndex(); - public BarLineScatterCandleData getData(); + BarLineScatterCandleData getData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java index 47bddc83ff..2d1847af6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java @@ -4,5 +4,5 @@ public interface BubbleDataProvider extends BarLineScatterCandleBubbleDataProvider { - public BubbleData getBubbleData(); + BubbleData getBubbleData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java index 077101a705..67b58f2462 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java @@ -4,5 +4,5 @@ public interface CandleDataProvider extends BarLineScatterCandleBubbleDataProvider { - public CandleData getCandleData(); + CandleData getCandleData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index ee9d50c620..9c4d0628d8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.interfaces; import android.graphics.PointF; @@ -15,27 +14,27 @@ */ public interface ChartInterface { - public float getXChartMin(); + float getXChartMin(); - public float getXChartMax(); + float getXChartMax(); - public float getYChartMin(); + float getYChartMin(); - public float getYChartMax(); + float getYChartMax(); - public int getXValCount(); + int getXValCount(); - public int getWidth(); + int getWidth(); - public int getHeight(); + int getHeight(); - public PointF getCenterOfView(); + PointF getCenterOfView(); - public PointF getCenterOffsets(); + PointF getCenterOffsets(); - public RectF getContentRect(); + RectF getContentRect(); - public ValueFormatter getDefaultValueFormatter(); + ValueFormatter getDefaultValueFormatter(); - public ChartData getData(); + ChartData getData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java index d6704f37e8..1aa7909135 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.interfaces; import com.github.mikephil.charting.data.LineData; @@ -6,7 +5,7 @@ public interface LineDataProvider extends BarLineScatterCandleBubbleDataProvider { - public LineData getLineData(); + LineData getLineData(); /** * Sets a custom FillFormatter to the chart that handles the position of the @@ -14,12 +13,12 @@ public interface LineDataProvider extends BarLineScatterCandleBubbleDataProvider * * @param formatter */ - public void setFillFormatter(FillFormatter formatter); + void setFillFormatter(FillFormatter formatter); /** * Returns the FillFormatter that handles the position of the filled-line. * * @return */ - public FillFormatter getFillFormatter(); + FillFormatter getFillFormatter(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java index 121ee43ea9..bddffb1f20 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java @@ -4,6 +4,6 @@ public interface ScatterDataProvider extends BarLineScatterCandleBubbleDataProvider { - public ScatterData getScatterData(); + ScatterData getScatterData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java index 6ebad1ecc5..9674b2c7b7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.listener; import android.view.MotionEvent; @@ -15,21 +14,21 @@ public interface OnChartGestureListener { * * @param me */ - public void onChartLongPressed(MotionEvent me); + void onChartLongPressed(MotionEvent me); /** * Callbacks when the chart is double-tapped. * * @param me */ - public void onChartDoubleTapped(MotionEvent me); + void onChartDoubleTapped(MotionEvent me); /** * Callbacks when the chart is single-tapped. * * @param me */ - public void onChartSingleTapped(MotionEvent me); + void onChartSingleTapped(MotionEvent me); /** * Callbacks then a fling gesture is made on the chart. @@ -39,7 +38,7 @@ public interface OnChartGestureListener { * @param velocityX * @param velocityY */ - public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY); + void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY); /** * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. @@ -48,7 +47,7 @@ public interface OnChartGestureListener { * @param scaleX scalefactor on the x-axis * @param scaleY scalefactor on the y-axis */ - public void onChartScale(MotionEvent me, float scaleX, float scaleY); + void onChartScale(MotionEvent me, float scaleX, float scaleY); /** * Callbacks when the chart is moved / translated via drag gesture. @@ -57,6 +56,6 @@ public interface OnChartGestureListener { * @param dX translation distance on the x-axis * @param dY translation distance on the y-axis */ - public void onChartTranslate(MotionEvent me, float dX, float dY); + void onChartTranslate(MotionEvent me, float dX, float dY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java index 8d8c4a070a..4c6da2e8c9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartValueSelectedListener.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.listener; import com.github.mikephil.charting.data.Entry; @@ -21,10 +20,10 @@ public interface OnChartValueSelectedListener { * @param h the corresponding highlight object that contains information * about the highlighted position */ - public void onValueSelected(Entry e, int dataSetIndex, Highlight h); + void onValueSelected(Entry e, int dataSetIndex, Highlight h); /** * Called when nothing has been selected or an "un-select" has been made. */ - public void onNothingSelected(); + void onNothingSelected(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java index 940d0ed18a..5890350bcd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnDrawListener.java @@ -18,14 +18,14 @@ public interface OnDrawListener { * @param entry * the last drawn entry */ - public void onEntryAdded(Entry entry); + void onEntryAdded(Entry entry); /** * Called whenever an entry is moved by the user after beeing highlighted * * @param entry */ - public void onEntryMoved(Entry entry); + void onEntryMoved(Entry entry); /** * Called when drawing finger is lifted and the draw is finished. @@ -33,6 +33,6 @@ public interface OnDrawListener { * @param dataSet * the last drawn DataSet */ - public void onDrawFinished(DataSet dataSet); + void onDrawFinished(DataSet dataSet); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java index f646d0e4a9..81da6ae089 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.utils; import com.github.mikephil.charting.data.Entry; @@ -11,5 +10,5 @@ */ public interface ColorFormatter { - public int getColor(Entry e, int index); + int getColor(Entry e, int index); } \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java index 0fe37914b3..7181cdc885 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.utils; import com.github.mikephil.charting.data.LineData; @@ -22,6 +21,6 @@ public interface FillFormatter { * @param chartMinY * @return */ - public float getFillLinePosition(LineDataSet dataSet, LineData data, float chartMaxY, + float getFillLinePosition(LineDataSet dataSet, LineData data, float chartMaxY, float chartMinY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java index 843fa9c7d6..70f19472ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java @@ -1,4 +1,3 @@ - package com.github.mikephil.charting.utils; /** @@ -19,5 +18,5 @@ public interface ValueFormatter { * @param value the value to be formatted * @return the formatted label ready for being drawn */ - public String getFormattedValue(float value); + String getFormattedValue(float value); } From 9eb62989606de6a44716731f12b1977915c2ea9a Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 19 Aug 2015 14:00:11 +0300 Subject: [PATCH 0459/1390] Improved startAtZero logic to ignore spacing when needed And still allow negative ranges when necessary (negative charts, stacked negative etc.) --- .../charting/charts/BarLineChartBase.java | 53 ++++++++++++------- .../mikephil/charting/charts/RadarChart.java | 30 ++++++++--- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index d2f0dd4e06..b2a6fc5ee3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -363,35 +363,52 @@ protected void calcMinMax() { mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft - .getAxisMaxValue() : maxLeft + topSpaceLeft; - mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight - .getAxisMaxValue() : maxRight + topSpaceRight; - mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft - .getAxisMinValue() : minLeft - bottomSpaceLeft; - mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight - .getAxisMinValue() : minRight - bottomSpaceRight; - - // consider starting at zero (0) + // Consider sticking one of the edges of the axis to zero (0.0) + if (mAxisLeft.isStartAtZeroEnabled()) { - if (mAxisLeft.mAxisMinimum < 0f && mAxisLeft.mAxisMaximum < 0f) { + if (minLeft < 0.f && maxLeft < 0.f) { // If the values are all negative, let's stay in the negative zone - mAxisLeft.mAxisMaximum = 0f; - } else if (mAxisLeft.mAxisMinimum >= 0f) { + mAxisLeft.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft)); + mAxisLeft.mAxisMaximum = 0.f; + } + else if (minLeft >= 0.0) { // We have positive values only, stay in the positive zone - mAxisLeft.mAxisMinimum = 0f; + mAxisLeft.mAxisMinimum = 0.f; + mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); } + else { + // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) + mAxisLeft.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft)); + mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); + } + } + else { + // Use the values as they are + mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); + mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); } if (mAxisRight.isStartAtZeroEnabled()) { - if (mAxisRight.mAxisMinimum < 0.0 && mAxisRight.mAxisMaximum < 0.0) { + if (minRight < 0.f && maxRight < 0.f) { // If the values are all negative, let's stay in the negative zone - mAxisRight.mAxisMaximum = 0f; - } else if (mAxisRight.mAxisMinimum >= 0f) { + mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); + mAxisRight.mAxisMaximum = 0.f; + } + else if (minRight >= 0.f) { // We have positive values only, stay in the positive zone - mAxisRight.mAxisMinimum = 0f; + mAxisRight.mAxisMinimum = 0.f; + mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); + } + else { + // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) + mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); + mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); } } + else { + mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight); + mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight); + } mAxisLeft.mAxisRange = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); mAxisRight.mAxisRange = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 1e64e56bb3..df3d57c408 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -100,14 +100,28 @@ protected void calcMinMax() { mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis - .getAxisMaxValue() : maxLeft + topSpaceLeft; - mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis - .getAxisMinValue() : minLeft - bottomSpaceLeft; - - // consider starting at zero (0) - if (mYAxis.isStartAtZeroEnabled()) - mYAxis.mAxisMinimum = Math.min(0f, mYAxis.mAxisMinimum); + if (mYAxis.isStartAtZeroEnabled()) { + if (minLeft < 0.f && maxLeft < 0.f) { + // If the values are all negative, let's stay in the negative zone + mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); + mYAxis.mAxisMaximum = 0.f; + } + else if (minLeft >= 0.0) { + // We have positive values only, stay in the positive zone + mYAxis.mAxisMinimum = 0.f; + mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); + } + else { + // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) + mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); + mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); + } + } + else { + // Use the values as they are + mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft); + mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft); + } mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); } From 9952c222fde742683570d359a503d9b59fdd5303 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Wed, 19 Aug 2015 14:01:34 +0300 Subject: [PATCH 0460/1390] Exclude label width when drawLabelsEnabled=false --- .../com/github/mikephil/charting/charts/PieRadarChartBase.java | 2 +- .../src/com/github/mikephil/charting/charts/RadarChart.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index afd1ad1421..5c38f42418 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -199,7 +199,7 @@ public void calculateOffsets() { if (this instanceof RadarChart) { XAxis x = ((RadarChart) this).getXAxis(); - if (x.isEnabled()) { + if (x.isEnabled() && x.isDrawLabelsEnabled()) { min = Math.max(Utils.convertDpToPixel(10f), x.mLabelWidth); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index df3d57c408..0b639e0e5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -339,7 +339,7 @@ protected float getRequiredBottomOffset() { @Override protected float getRequiredBaseOffset() { - return mXAxis.isEnabled() ? mXAxis.mLabelWidth : Utils.convertDpToPixel(10f); + return mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled() ? mXAxis.mLabelWidth : Utils.convertDpToPixel(10f); } @Override From ee183816b535ec07a2913d0dea4f86dece744f17 Mon Sep 17 00:00:00 2001 From: Xizhi Zhu Date: Wed, 26 Aug 2015 14:14:37 +0300 Subject: [PATCH 0461/1390] Updated build tools. --- MPChartExample/build.gradle | 10 +++++----- MPChartLib/build.gradle | 6 +++--- build.gradle | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 14eb708b4d..5ab68d604b 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 21 - buildToolsVersion '21.1.1' + compileSdkVersion 23 + buildToolsVersion '23.0.0' defaultConfig { minSdkVersion 8 - targetSdkVersion 21 + targetSdkVersion 23 versionCode 44 versionName '2.1.3' @@ -38,7 +38,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.1.0' + classpath 'com.android.tools.build:gradle:1.3.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -52,6 +52,6 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project - compile 'com.android.support:appcompat-v7:21.0.3' + compile 'com.android.support:appcompat-v7:23.0.0' //compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 2b10d4db7c..334cdc3176 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -2,12 +2,12 @@ apply plugin: 'com.android.library' apply plugin: 'android-maven' android { - compileSdkVersion 21 - buildToolsVersion '21.1.1' + compileSdkVersion 23 + buildToolsVersion '23.0.0' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 8 - targetSdkVersion 21 + targetSdkVersion 23 versionCode 1 versionName '1.0' diff --git a/build.gradle b/build.gradle index 8d6e95140e..3661c05050 100644 --- a/build.gradle +++ b/build.gradle @@ -3,7 +3,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.0.0' + classpath 'com.android.tools.build:gradle:1.3.1' classpath 'com.github.dcendents:android-maven-plugin:1.2' } } From 318c308d1b7f5e296236c593bc13b3141e0ec86d Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 27 Aug 2015 17:46:06 +0300 Subject: [PATCH 0462/1390] Avoid crashes when datasets are empty --- .../github/mikephil/charting/renderer/BarChartRenderer.java | 4 ++-- .../mikephil/charting/renderer/BubbleChartRenderer.java | 4 ++-- .../mikephil/charting/renderer/CandleStickChartRenderer.java | 4 ++-- .../charting/renderer/HorizontalBarChartRenderer.java | 2 +- .../github/mikephil/charting/renderer/LineChartRenderer.java | 4 ++-- .../github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- .../github/mikephil/charting/renderer/RadarChartRenderer.java | 4 ++-- .../mikephil/charting/renderer/ScatterChartRenderer.java | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index db2c80d7ea..5324ef1121 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -71,7 +71,7 @@ public void drawData(Canvas c) { BarDataSet set = barData.getDataSetByIndex(i); - if (set.isVisible()) { + if (set.isVisible() && set.getEntryCount() > 0) { drawDataSet(c, set, i); } } @@ -187,7 +187,7 @@ public void drawValues(Canvas c) { BarDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 7c98b77a4a..bf198eeb5d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -49,7 +49,7 @@ public void drawData(Canvas c) { for (BubbleDataSet set : bubbleData.getDataSets()) { - if (set.isVisible()) + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } @@ -133,7 +133,7 @@ public void drawValues(Canvas c) { for (BubbleDataSet dataSet : dataSets) { - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index ce410f1a8b..9a5c53e2c6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -53,7 +53,7 @@ public void drawData(Canvas c) { for (CandleDataSet set : candleData.getDataSets()) { - if (set.isVisible()) + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } @@ -233,7 +233,7 @@ public void drawValues(Canvas c) { CandleDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index ef9506ce01..25c902853a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -107,7 +107,7 @@ public void drawValues(Canvas c) { BarDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; boolean isInverted = mChart.isInverted(dataSet.getAxisDependency()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 6587d32e63..5e8da0d24c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -94,7 +94,7 @@ public void drawData(Canvas c) { for (LineDataSet set : lineData.getDataSets()) { - if (set.isVisible()) + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } @@ -410,7 +410,7 @@ public void drawValues(Canvas c) { LineDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 819e6a938b..323a332804 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -117,7 +117,7 @@ public void drawData(Canvas c) { for (PieDataSet set : pieData.getDataSets()) { - if (set.isVisible()) + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index be782af7f4..58ab05cc1f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -56,7 +56,7 @@ public void drawData(Canvas c) { for (RadarDataSet set : radarData.getDataSets()) { - if (set.isVisible()) + if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } @@ -131,7 +131,7 @@ public void drawValues(Canvas c) { RadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 274250f760..23619fc8a3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -209,7 +209,7 @@ public void drawValues(Canvas c) { ScatterDataSet dataSet = dataSets.get(i); - if (!dataSet.isDrawValuesEnabled()) + if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; // apply the text-styling defined by the DataSet From a7e9f19ecc9c6995fe6324a6e742587707eddf57 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 27 Aug 2015 17:51:36 +0300 Subject: [PATCH 0463/1390] Prevent pie slices from clipping when selected --- .../mikephil/charting/charts/PieChart.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 151056cfc3..cdca775b32 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -125,14 +125,27 @@ public void calculateOffsets() { return; float diameter = getDiameter(); - float boxSize = diameter / 2f; + float radius = diameter / 2f; PointF c = getCenterOffsets(); + final List dataSets = mData.getDataSets(); + + float maxShift = 0.f; + for (int i = 0; i < dataSets.size(); i++) { + final float shift = dataSets.get(i).getSelectionShift(); + if (shift > maxShift) + maxShift = shift; + } + + final float halfMaxShift = maxShift / 2.f; + // create the circle box that will contain the pie-chart (the bounds of // the pie-chart) - mCircleBox.set(c.x - boxSize, c.y - boxSize, - c.x + boxSize, c.y + boxSize); + mCircleBox.set(c.x - radius + halfMaxShift, + c.y - radius + halfMaxShift, + c.x + radius - halfMaxShift, + c.y + radius - halfMaxShift); } @Override From f9d8e365f058922522e2feb912cdecc1d2acc886 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 27 Aug 2015 17:53:44 +0300 Subject: [PATCH 0464/1390] Minor performance improvement to candle chart --- .../mikephil/charting/data/CandleDataSet.java | 2 +- .../renderer/CandleStickChartRenderer.java | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index c40152ace3..cbbc98c55b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -79,7 +79,7 @@ protected void calcMinMax(int start, int end) { int endValue; - if (end == 0) + if (end == 0 || end >= mYVals.size()) endValue = mYVals.size() - 1; else endValue = end; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 9a5c53e2c6..6d6db7197f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -69,11 +69,8 @@ protected void drawDataSet(Canvas c, CandleDataSet dataSet) { List entries = dataSet.getYVals(); - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int minx = Math.max(mMinX, 0); + int maxx = Math.min(mMaxX + 1, entries.size()); int range = (maxx - minx) * 4; int to = (int)Math.ceil((maxx - minx) * phaseX + minx); @@ -243,11 +240,8 @@ public void drawValues(Canvas c) { List entries = dataSet.getYVals(); - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int minx = Math.max(mMinX, 0); + int maxx = Math.min(mMaxX + 1, entries.size()); float[] positions = trans.generateTransformedValuesCandle( entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); From fe95442413fe3470f150eeae6c81dd858bd7876e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sat, 5 Sep 2015 20:57:36 +0300 Subject: [PATCH 0465/1390] Fixes an issue with X min/max in combined charts without bubble data --- .../src/com/github/mikephil/charting/charts/CombinedChart.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 8579f79ded..8f15192d3f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -101,9 +101,6 @@ protected void calcMinMax() { mXChartMax = xmax; } } - } else { - mXChartMin = 0f; - mXChartMax = mData.getXValCount()-1; } mDeltaX = Math.abs(mXChartMax - mXChartMin); From 9ecce154e2a6ed3c29d53f4a612a98ea4f8da878 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 8 Sep 2015 10:45:43 +0200 Subject: [PATCH 0466/1390] Update Projects_using_MPAndroidChart.txt --- Projects_using_MPAndroidChart.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt index 526e9ef763..ca64fb9c96 100644 --- a/Projects_using_MPAndroidChart.txt +++ b/Projects_using_MPAndroidChart.txt @@ -44,3 +44,6 @@ https://github.com/C-piace-il-C/Speaker_Recognition ExpenseDroid - Expense Manager https://play.google.com/store/apps/details?id=com.tphoneix.avi.myapplication + +Live Tracking +https://play.google.com/store/apps/details?id=com.aorbegozo005.livetrack From 16d011b2bf618686c467ab227e850c8a370fc075 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Sep 2015 10:46:58 +0200 Subject: [PATCH 0467/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 366af2e6f2..c230f8758d 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Donations Follow me on **Twitter**: [**@PhilippJahoda**](https://twitter.com/PhilippJahoda) +Contact me on **LinkedIn**: [**PhilippJahoda**](https://www.linkedin.com/in/philippjahoda/en) + Look me up on **StackOverflow**: [**Philipp Jahoda**](http://stackoverflow.com/users/1590502/philipp-jahoda) From 75be29ef038f960b686430ab8a75dff89575c6ac Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Sep 2015 12:04:19 +0200 Subject: [PATCH 0468/1390] Added markerview support for HorizontalBarChart (#1010) - still bugfixing needed. --- MPChartExample/build.gradle | 2 +- .../HorizontalBarChartActivity.java | 6 ++++ MPChartLib/build.gradle | 2 +- .../charting/charts/BarLineChartBase.java | 31 +++++++++++++++---- .../mikephil/charting/utils/Transformer.java | 2 +- 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 5ab68d604b..12482e3428 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion '23.0.0' + buildToolsVersion '23.0.1' defaultConfig { minSdkVersion 8 targetSdkVersion 23 diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 4df4497da1..d5c6205adb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -31,6 +31,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -105,6 +106,11 @@ protected void onCreate(Bundle savedInstanceState) { yr.setDrawGridLines(false); // yr.setInverted(true); + MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); + + // set the marker to the chart + mChart.setMarkerView(mv); + setData(12, 50); mChart.animateY(2500); diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 334cdc3176..12365dbeaf 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'android-maven' android { compileSdkVersion 23 - buildToolsVersion '23.0.0' + buildToolsVersion '23.0.1' // resourcePrefix 'mpcht' defaultConfig { minSdkVersion 8 diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b2a6fc5ee3..085eca8ac2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -548,15 +548,34 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { BarData bd = (BarData) mData; float space = bd.getGroupSpace(); + int setCount = mData.getDataSetCount(); + int i = e.getXIndex(); - float x = e.getXIndex() * (mData.getDataSetCount() - 1) + dataSetIndex + space * e.getXIndex() + space - / 2f; + if(this instanceof HorizontalBarChart) { - xPos += x; + // calculate the x-position, depending on datasetcount + float y = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f ; - BarEntry entry = (BarEntry) e; - if(entry.getVals() != null) { - yPos = highlight.getRange().to; + yPos = y; + + BarEntry entry = (BarEntry) e; + if(entry.getVals() != null) { + xPos = highlight.getRange().to; + } else { + xPos = e.getVal(); + } + } else { + + float x = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; + + xPos = x; + + BarEntry entry = (BarEntry) e; + if(entry.getVals() != null) { + yPos = highlight.getRange().to; + } else { + yPos = e.getVal(); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index f74c8c0227..978fa8684c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -262,7 +262,7 @@ public float[] generateTransformedValuesHorizontalBarChart(List int i = e.getXIndex(); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + i * (setCount - 1) + dataSet + space * i + float x = i + i * (setCount - 1) + dataSet + space * i + space / 2f ; float y = e.getVal(); From fcfea4e1819ea9a518c52c0d2c83df44a8c6dca7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Sep 2015 12:07:44 +0200 Subject: [PATCH 0469/1390] Fixed horizontal-markerview animation issues. --- .../github/mikephil/charting/charts/BarLineChartBase.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 085eca8ac2..29983a511a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -564,6 +564,8 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { } else { xPos = e.getVal(); } + + xPos *= mAnimator.getPhaseY(); } else { float x = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; @@ -576,12 +578,16 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { } else { yPos = e.getVal(); } + + yPos *= mAnimator.getPhaseY(); } + } else { + yPos *= mAnimator.getPhaseY(); } // position of the marker depends on selected value index and value float[] pts = new float[] { - xPos, yPos * mAnimator.getPhaseY() + xPos, yPos }; getTransformer(mData.getDataSetByIndex(dataSetIndex).getAxisDependency()) From 3712d8589d173c626c358f8e5d39cc87148c580a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 10 Sep 2015 12:19:09 +0200 Subject: [PATCH 0470/1390] Added markerview support for PieChart. --- .../HorizontalBarChartActivity.java | 6 - .../mikephil/charting/charts/PieChart.java | 138 ++++++++++++------ 2 files changed, 90 insertions(+), 54 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index d5c6205adb..4df4497da1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -31,7 +31,6 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.ColorTemplate; -import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -106,11 +105,6 @@ protected void onCreate(Bundle savedInstanceState) { yr.setDrawGridLines(false); // yr.setInverted(true); - MyMarkerView mv = new MyMarkerView(this, R.layout.custom_marker_view); - - // set the marker to the chart - mChart.setMarkerView(mv); - setData(12, 50); mChart.animateY(2500); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index cdca775b32..91511ed6c0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -23,7 +23,7 @@ /** * View that represents a pie chart. Draws cake like slices. - * + * * @author Philipp Jahoda */ public class PieChart extends PieRadarChartBase { @@ -34,22 +34,34 @@ public class PieChart extends PieRadarChartBase { */ private RectF mCircleBox = new RectF(); - /** flag indicating if the x-labels should be drawn or not */ + /** + * flag indicating if the x-labels should be drawn or not + */ private boolean mDrawXLabels = true; - /** array that holds the width of each pie-slice in degrees */ + /** + * array that holds the width of each pie-slice in degrees + */ private float[] mDrawAngles; - /** array that holds the absolute angle in degrees of each slice */ + /** + * array that holds the absolute angle in degrees of each slice + */ private float[] mAbsoluteAngles; - /** if true, the white hole inside the chart will be drawn */ + /** + * if true, the white hole inside the chart will be drawn + */ private boolean mDrawHole = true; - /** if true, the values inside the piechart are drawn as percent values */ + /** + * if true, the values inside the piechart are drawn as percent values + */ private boolean mUsePercentValues = false; - - /** if true, the slices of the piechart are rounded */ + + /** + * if true, the slices of the piechart are rounded + */ private boolean mDrawRoundedSlices = false; /** @@ -69,7 +81,9 @@ public class PieChart extends PieRadarChartBase { */ protected float mTransparentCircleRadiusPercent = 55f; - /** if enabled, centertext is drawn */ + /** + * if enabled, centertext is drawn + */ private boolean mDrawCenterText = true; private boolean mCenterTextWordWrapEnabled = false; @@ -114,6 +128,8 @@ protected void onDraw(Canvas canvas) { mLegendRenderer.renderLegend(canvas); drawDescription(canvas); + + drawMarkers(canvas); } @Override @@ -155,10 +171,36 @@ protected void calcMinMax() { calcAngles(); } - /** PieChart does not support MarkerView */ @Override protected float[] getMarkerPosition(Entry e, Highlight highlight) { - return new float[0]; + + PointF center = getCenterCircleBox(); + float r = getRadius(); + + float off = r / 10f * 3.6f; + + if (isDrawHoleEnabled()) { + off = (r - (r / 100f * getHoleRadius())) / 2f; + } + + r -= off; // offset to keep things inside the chart + + float rotationAngle = getRotationAngle(); + + int i = e.getXIndex(); + + // offset needed to center the drawn text in the slice + float offset = mDrawAngles[i] / 2; + + // calculate the text position + float x = (float) (r + * Math.cos(Math.toRadians((rotationAngle + mAbsoluteAngles[i] - offset) + * mAnimator.getPhaseY())) + center.x); + float y = (float) (r + * Math.sin(Math.toRadians((rotationAngle + mAbsoluteAngles[i] - offset) + * mAnimator.getPhaseY())) + center.y); + + return new float[]{x, y}; } /** @@ -197,7 +239,7 @@ private void calcAngles() { /** * checks if the given index in the given DataSet is set for highlighting or * not - * + * * @param xIndex * @param dataSetIndex * @return @@ -220,7 +262,7 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { /** * calculates the needed angle for a given value - * + * * @param value * @return */ @@ -244,7 +286,7 @@ public int getIndexForAngle(float angle) { /** * Returns the index of the DataSet this x-index belongs to. - * + * * @param xIndex * @return */ @@ -264,7 +306,7 @@ public int getDataSetIndexForIndex(int xIndex) { * returns an integer array of all the different angles the chart slices * have the angles in the returned array determine how much space (of 360°) * each slice takes - * + * * @return */ public float[] getDrawAngles() { @@ -274,7 +316,7 @@ public float[] getDrawAngles() { /** * returns the absolute angles of the different chart slices (where the * slices end) - * + * * @return */ public float[] getAbsoluteAngles() { @@ -285,7 +327,7 @@ public float[] getAbsoluteAngles() { * Sets the color for the hole that is drawn in the center of the PieChart * (if enabled). NOTE: Use setHoleColorTransparent(boolean enabled) to make * the hole transparent. - * + * * @param color */ public void setHoleColor(int color) { @@ -296,9 +338,9 @@ public void setHoleColor(int color) { /** * Set the hole in the center of the PieChart transparent. Thank you, code * provided by: - * - * @link https://github.com/tbarthel-fr + * * @param enable + * @link https://github.com/tbarthel-fr */ public void setHoleColorTransparent(boolean enable) { if (enable) { @@ -322,7 +364,7 @@ public boolean isHoleTransparent() { /** * set this to true to draw the pie center empty - * + * * @param enabled */ public void setDrawHoleEnabled(boolean enabled) { @@ -332,7 +374,7 @@ public void setDrawHoleEnabled(boolean enabled) { /** * returns true if the hole in the center of the pie-chart is set to be * visible, false if not - * + * * @return */ public boolean isDrawHoleEnabled() { @@ -342,7 +384,7 @@ public boolean isDrawHoleEnabled() { /** * sets the text that is displayed in the center of the pie-chart. By * default, the text is "Total Value + sumofallvalues" - * + * * @param text */ public void setCenterText(String text) { @@ -351,7 +393,7 @@ public void setCenterText(String text) { /** * returns the text that is drawn in the center of the pie-chart - * + * * @return */ public String getCenterText() { @@ -361,7 +403,7 @@ public String getCenterText() { /** * set this to true to draw the text that is displayed in the center of the * pie chart - * + * * @param enabled */ public void setDrawCenterText(boolean enabled) { @@ -370,7 +412,7 @@ public void setDrawCenterText(boolean enabled) { /** * returns true if drawing the center text is enabled - * + * * @return */ public boolean isDrawCenterTextEnabled() { @@ -397,7 +439,7 @@ public float getRadius() { /** * returns the circlebox, the boundingbox of the pie-chart slices - * + * * @return */ public RectF getCircleBox() { @@ -406,7 +448,7 @@ public RectF getCircleBox() { /** * returns the center of the circlebox - * + * * @return */ public PointF getCenterCircleBox() { @@ -415,7 +457,7 @@ public PointF getCenterCircleBox() { /** * sets the typeface for the center-text paint - * + * * @param t */ public void setCenterTextTypeface(Typeface t) { @@ -424,7 +466,7 @@ public void setCenterTextTypeface(Typeface t) { /** * Sets the size of the center text of the PieChart in dp. - * + * * @param size */ public void setCenterTextSize(float sizeDp) { @@ -434,7 +476,7 @@ public void setCenterTextSize(float sizeDp) { /** * Sets the size of the center text of the PieChart in pixels. - * + * * @param size */ public void setCenterTextSizePixels(float sizePixels) { @@ -443,7 +485,7 @@ public void setCenterTextSizePixels(float sizePixels) { /** * Sets the color of the center text of the PieChart. - * + * * @param color */ public void setCenterTextColor(int color) { @@ -453,7 +495,7 @@ public void setCenterTextColor(int color) { /** * sets the radius of the hole in the center of the piechart in percent of * the maximum radius (max = the radius of the whole chart), default 50% - * + * * @param size */ public void setHoleRadius(final float percent) { @@ -462,7 +504,7 @@ public void setHoleRadius(final float percent) { /** * Returns the size of the hole radius in percent of the total radius. - * + * * @return */ public float getHoleRadius() { @@ -471,6 +513,7 @@ public float getHoleRadius() { /** * Sets the color the transparent-circle should have. + * * @param color */ public void setTransparentCircleColor(int color) { @@ -486,7 +529,7 @@ public void setTransparentCircleColor(int color) { * in the piechart in percent of the maximum radius (max = the radius of the * whole chart), default 55% -> means 5% larger than the center-hole by * default - * + * * @param percent */ public void setTransparentCircleRadius(final float percent) { @@ -497,20 +540,19 @@ public float getTransparentCircleRadius() { return mTransparentCircleRadiusPercent; } - /** - * Sets the amount of transparency the transparent circle should have 0 = fully transparent, 255 = fully opaque. + /** + * Sets the amount of transparency the transparent circle should have 0 = fully transparent, 255 = fully opaque. * Default value is 100. - * - * @param alpha - * 0-255 - */ - public void setTransparentCircleAlpha(int alpha) { - ((PieChartRenderer) mRenderer).getPaintTransparentCircle().setAlpha(alpha); - } + * + * @param alpha 0-255 + */ + public void setTransparentCircleAlpha(int alpha) { + ((PieChartRenderer) mRenderer).getPaintTransparentCircle().setAlpha(alpha); + } /** * set this to true to draw the x-value text into the pie slices - * + * * @param enabled */ public void setDrawSliceText(boolean enabled) { @@ -519,7 +561,7 @@ public void setDrawSliceText(boolean enabled) { /** * returns true if drawing x-values is enabled, false if not - * + * * @return */ public boolean isDrawSliceTextEnabled() { @@ -529,7 +571,7 @@ public boolean isDrawSliceTextEnabled() { /** * Returns true if the chart is set to draw each end of a pie-slice * "rounded". - * + * * @return */ public boolean isDrawRoundedSlicesEnabled() { @@ -540,7 +582,7 @@ public boolean isDrawRoundedSlicesEnabled() { * If this is enabled, values inside the PieChart are drawn in percent and * not with their original value. Values provided for the ValueFormatter to * format are then provided in percent. - * + * * @param enabled */ public void setUsePercentValues(boolean enabled) { @@ -549,7 +591,7 @@ public void setUsePercentValues(boolean enabled) { /** * Returns true if using percentage values is enabled for the chart. - * + * * @return */ public boolean isUsePercentValuesEnabled() { From 14810e3dfde950803139353e3afe148a6282f2c9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Sep 2015 16:55:55 +0200 Subject: [PATCH 0471/1390] Code cleanup, possible fix #1022 --- .../mikephil/charting/charts/Chart.java | 50 ++---- .../mikephil/charting/data/ChartData.java | 163 +++++++++++------- .../mikephil/charting/data/DataSet.java | 8 + .../charting/renderer/LegendRenderer.java | 4 +- .../charting/renderer/PieChartRenderer.java | 2 +- 5 files changed, 121 insertions(+), 106 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index e9a0cf6d27..7b61ead635 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -299,6 +299,7 @@ public void setData(T data) { public void clear() { mData = null; mDataNotSet = true; + mIndicesToHightlight = null; invalidate(); } @@ -332,7 +333,9 @@ public boolean isEmpty() { /** * Lets the chart know its underlying data has changed and performs all - * necessary recalculations. + * necessary recalculations. It is crucial that this method is called + * everytime data is changed dynamically. Not calling this method can lead + * to crashes or unexpected behaviour. */ public abstract void notifyDataSetChanged(); @@ -438,11 +441,11 @@ protected void drawDescription(Canvas c) { * array of Highlight objects that reference the highlighted slices in the * chart */ - protected Highlight[] mIndicesToHightlight = new Highlight[0]; + protected Highlight[] mIndicesToHightlight; /** - * Returns the array of currently highlighted values. This might be null or - * empty if nothing is highlighted. + * Returns the array of currently highlighted values. This might a null or + * empty array if nothing is highlighted. * * @return */ @@ -895,15 +898,6 @@ public boolean isHighlightEnabled() { return mData == null ? true : mData.isHighlightEnabled(); } - /** - * returns the total value (sum) of all y-values across all DataSets - * - * @return - */ - public float getYValueSum() { - return mData.getYValueSum(); - } - /** * returns the current y-max value across all DataSets * @@ -938,31 +932,7 @@ public int getXValCount() { } /** - * returns the average value of all values the chart holds - * - * @return - */ - public float getAverage() { - return getYValueSum() / mData.getYValCount(); - } - - /** - * returns the average value for a specific DataSet (with a specific label) - * in the chart - * - * @param dataSetLabel - * @return - */ - public float getAverage(String dataSetLabel) { - - DataSet ds = mData.getDataSetByLabel(dataSetLabel, true); - - return ds.getYValueSum() - / ds.getEntryCount(); - } - - /** - * returns the total number of values the chart holds (across all DataSets) + * Returns the total number of (y) values the chart holds (across all DataSets). * * @return */ @@ -1118,8 +1088,8 @@ public float getExtraLeftOffset() { } /** - * Set this to true to enable logcat outputs for the chart. Default: - * disabled + * Set this to true to enable logcat outputs for the chart. Beware that + * logcat output decreases rendering performance. Default: disabled. * * @param enabled */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 10513dac36..21abef6396 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -15,15 +15,19 @@ /** * Class that holds all relevant data that represents the chart. That involves * at least one (or more) DataSets, and an array of x-values. - * + * * @author Philipp Jahoda */ public abstract class ChartData> { - /** maximum y-value in the y-value array across all axes */ + /** + * maximum y-value in the y-value array across all axes + */ protected float mYMax = 0.0f; - /** the minimum y-value in the y-value array across all axes */ + /** + * the minimum y-value in the y-value array across all axes + */ protected float mYMin = 0.0f; protected float mLeftAxisMax = 0.0f; @@ -34,16 +38,24 @@ public abstract class ChartData> { protected float mRightAxisMin = 0.0f; - /** the total sum of all y-values */ + /** + * the total sum of all y-values + */ private float mYValueSum = 0f; - /** total number of y-values across all DataSet objects */ + /** + * total number of y-values across all DataSet objects + */ private int mYValCount = 0; - /** the last start value used for calcMinMax */ + /** + * the last start value used for calcMinMax + */ protected int mLastStart = 0; - /** the last end value used for calcMinMax */ + /** + * the last end value used for calcMinMax + */ protected int mLastEnd = 0; /** @@ -52,10 +64,14 @@ public abstract class ChartData> { */ private float mXValAverageLength = 0; - /** holds all x-values the chart represents */ + /** + * holds all x-values the chart represents + */ protected List mXVals; - /** array that holds all DataSets the ChartData object represents */ + /** + * array that holds all DataSets the ChartData object represents + */ protected List mDataSets; public ChartData() { @@ -66,7 +82,7 @@ public ChartData() { /** * Constructor for only x-values. This constructor can be used for setting * up an empty chart without data. - * + * * @param xVals */ public ChartData(List xVals) { @@ -78,7 +94,7 @@ public ChartData(List xVals) { /** * Constructor for only x-values. This constructor can be used for setting * up an empty chart without data. - * + * * @param xVals */ public ChartData(String[] xVals) { @@ -89,11 +105,11 @@ public ChartData(String[] xVals) { /** * constructor for chart data - * + * * @param xVals The values describing the x-axis. Must be at least as long - * as the highest xIndex in the Entry objects across all - * DataSets. - * @param sets the dataset array + * as the highest xIndex in the Entry objects across all + * DataSets. + * @param sets the dataset array */ public ChartData(List xVals, List sets) { this.mXVals = xVals; @@ -104,11 +120,11 @@ public ChartData(List xVals, List sets) { /** * constructor that takes string array instead of List string - * + * * @param xVals The values describing the x-axis. Must be at least as long - * as the highest xIndex in the Entry objects across all - * DataSets. - * @param sets the dataset array + * as the highest xIndex in the Entry objects across all + * DataSets. + * @param sets the dataset array */ public ChartData(String[] xVals, List sets) { this.mXVals = arrayToList(xVals); @@ -119,7 +135,7 @@ public ChartData(String[] xVals, List sets) { /** * Turns an array of strings into an List of strings. - * + * * @param array * @return */ @@ -282,7 +298,7 @@ protected void calcYValueSum() { /** * Calculates the total number of y-values across all DataSets the ChartData * represents. - * + * * @return */ protected void calcYValueCount() { @@ -305,7 +321,7 @@ protected void calcYValueCount() { /** * returns the number of LineDataSets this object contains - * + * * @return */ public int getDataSetCount() { @@ -314,9 +330,18 @@ public int getDataSetCount() { return mDataSets.size(); } + /** + * Returns the average value across all entries in this Data object + * (all entries from the DataSets this data object holds) + * @return + */ + public float getAverage() { + return (float ) getYValueSum() / (float) getYValCount(); + } + /** * Returns the smallest y-value the data object contains. - * + * * @return */ public float getYMin() { @@ -325,7 +350,7 @@ public float getYMin() { /** * Returns the minimum y-value for the specified axis. - * + * * @param axis * @return */ @@ -338,7 +363,7 @@ public float getYMin(AxisDependency axis) { /** * Returns the greatest y-value the data object contains. - * + * * @return */ public float getYMax() { @@ -347,7 +372,7 @@ public float getYMax() { /** * Returns the maximum y-value for the specified axis. - * + * * @param axis * @return */ @@ -361,7 +386,7 @@ public float getYMax(AxisDependency axis) { /** * returns the average length (in characters) across all values in the * x-vals array - * + * * @return */ public float getXValAverageLength() { @@ -371,7 +396,7 @@ public float getXValAverageLength() { /** * Returns the total y-value sum across all DataSet objects the this object * represents. - * + * * @return */ public float getYValueSum() { @@ -381,7 +406,7 @@ public float getYValueSum() { /** * Returns the total number of y-values across all DataSet objects the this * object represents. - * + * * @return */ public int getYValCount() { @@ -390,7 +415,7 @@ public int getYValCount() { /** * returns the x-values the chart represents - * + * * @return */ public List getXVals() { @@ -399,7 +424,7 @@ public List getXVals() { /** * Adds a new x-value to the chart data. - * + * * @param xVal */ public void addXValue(String xVal) { @@ -410,7 +435,7 @@ public void addXValue(String xVal) { /** * Removes the x-value at the specified index. - * + * * @param index */ public void removeXValue(int index) { @@ -419,7 +444,7 @@ public void removeXValue(int index) { /** * Returns an the array of DataSets this object holds. - * + * * @return */ public List getDataSets() { @@ -431,14 +456,14 @@ public List getDataSets() { * Search can be case sensitive or not. IMPORTANT: This method does * calculations at runtime, do not over-use in performance critical * situations. - * - * @param dataSets the DataSet array to search + * + * @param dataSets the DataSet array to search * @param label * @param ignorecase if true, the search is not case-sensitive * @return */ protected int getDataSetIndexByLabel(List dataSets, String label, - boolean ignorecase) { + boolean ignorecase) { if (ignorecase) { for (int i = 0; i < dataSets.size(); i++) @@ -456,7 +481,7 @@ protected int getDataSetIndexByLabel(List dataSets, String label, /** * returns the total number of x-values this ChartData object represents * (the size of the x-values array) - * + * * @return */ public int getXValCount() { @@ -465,7 +490,7 @@ public int getXValCount() { /** * Returns the labels of all DataSets as a string array. - * + * * @return */ protected String[] getDataSetLabels() { @@ -481,23 +506,23 @@ protected String[] getDataSetLabels() { /** * Get the Entry for a corresponding highlight object - * + * * @param highlight * @return the entry that is highlighted */ public Entry getEntryForHighlight(Highlight highlight) { - if(highlight.getDataSetIndex() >= mDataSets.size()) + if (highlight.getDataSetIndex() >= mDataSets.size()) return null; else return mDataSets.get(highlight.getDataSetIndex()).getEntryForXIndex( - highlight.getXIndex()); + highlight.getXIndex()); } /** * Returns the DataSet object with the given label. Search can be case * sensitive or not. IMPORTANT: This method does calculations at runtime. * Use with care in performance critical situations. - * + * * @param label * @param ignorecase * @return @@ -514,7 +539,7 @@ public T getDataSetByLabel(String label, boolean ignorecase) { /** * Returns the DataSet object at the given index. - * + * * @param index * @return */ @@ -528,7 +553,7 @@ public T getDataSetByIndex(int index) { /** * Adds a DataSet dynamically. - * + * * @param d */ public void addDataSet(T d) { @@ -580,7 +605,7 @@ public void addDataSet(T d) { /** * This adjusts the other axis if one axis is empty and the other is not. - * + * * @param firstLeft * @param firstRight */ @@ -600,7 +625,7 @@ private void handleEmptyAxis(T firstLeft, T firstRight) { * Removes the given DataSet from this data object. Also recalculates all * minimum and maximum values. Returns true if a DataSet was removed, false * if no DataSet could be removed. - * + * * @param d */ public boolean removeDataSet(T d) { @@ -626,7 +651,7 @@ public boolean removeDataSet(T d) { * Removes the DataSet at the given index in the DataSet array from the data * object. Also recalculates all minimum and maximum values. Returns true if * a DataSet was removed, false if no DataSet could be removed. - * + * * @param index */ public boolean removeDataSet(int index) { @@ -641,7 +666,7 @@ public boolean removeDataSet(int index) { /** * Adds an Entry to the DataSet at the specified index. * Entries are added to the end of the list. - * + * * @param e * @param dataSetIndex */ @@ -699,7 +724,7 @@ public void addEntry(Entry e, int dataSetIndex) { /** * Removes the given Entry object from the DataSet at the specified index. - * + * * @param e * @param dataSetIndex */ @@ -729,7 +754,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { * Removes the Entry object at the given xIndex from the DataSet at the * specified index. Returns true if an Entry was removed, false if no Entry * was found that meets the specified requirements. - * + * * @param xIndex * @param dataSetIndex * @return @@ -751,7 +776,7 @@ public boolean removeEntry(int xIndex, int dataSetIndex) { /** * Returns the DataSet that contains the provided Entry, or null, if no * DataSet contains this Entry. - * + * * @param e * @return */ @@ -776,7 +801,7 @@ public T getDataSetForEntry(Entry e) { /** * Returns all colors used across all DataSet objects this object * represents. - * + * * @return */ public int[] getColors() { @@ -809,7 +834,7 @@ public int[] getColors() { /** * Returns the index of the provided DataSet inside the DataSets array of * this data object. Returns -1 if the DataSet was not found. - * + * * @param dataSet * @return */ @@ -823,6 +848,12 @@ public int getIndexOfDataSet(T dataSet) { return -1; } + /** + * Returns the first DataSet from the datasets-array that has it's dependency on the left axis. + * Returns null if no DataSet with left dependency could be found. + * + * @return + */ public T getFirstLeft() { for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) @@ -832,6 +863,12 @@ public T getFirstLeft() { return null; } + /** + * Returns the first DataSet from the datasets-array that has it's dependency on the right axis. + * Returns null if no DataSet with right dependency could be found. + * + * @return + */ public T getFirstRight() { for (T dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) @@ -844,7 +881,7 @@ public T getFirstRight() { /** * Generates an x-values array filled with numbers in range specified by the * parameters. Can be used for convenience. - * + * * @return */ public static List generateXVals(int from, int to) { @@ -860,7 +897,7 @@ public static List generateXVals(int from, int to) { /** * Sets a custom ValueFormatter for all DataSets this data object contains. - * + * * @param f */ public void setValueFormatter(ValueFormatter f) { @@ -876,7 +913,7 @@ public void setValueFormatter(ValueFormatter f) { /** * Sets the color of the value-text (color in which the value-labels are * drawn) for all DataSets this data object contains. - * + * * @param color */ public void setValueTextColor(int color) { @@ -888,8 +925,8 @@ public void setValueTextColor(int color) { /** * Sets the Typeface for all value-labels for all DataSets this data object * contains. - * - * @param color + * + * @param tf */ public void setValueTypeface(Typeface tf) { for (DataSet set : mDataSets) { @@ -900,8 +937,8 @@ public void setValueTypeface(Typeface tf) { /** * Sets the size (in dp) of the value-text for all DataSets this data object * contains. - * - * @param color + * + * @param size */ public void setValueTextSize(float size) { for (DataSet set : mDataSets) { @@ -912,7 +949,7 @@ public void setValueTextSize(float size) { /** * Enables / disables drawing values (value-text) for all DataSets this data * object contains. - * + * * @param enabled */ public void setDrawValues(boolean enabled) { @@ -958,7 +995,7 @@ public void clearValues() { * Checks if this data object contains the specified Entry. Returns true if * so, false if not. NOTE: Performance is pretty bad on this one, do not * over-use in performance critical situations. - * + * * @param e * @return */ @@ -975,7 +1012,7 @@ public boolean contains(Entry e) { /** * Checks if this data object contains the specified DataSet. Returns true * if so, false if not. - * + * * @param dataSet * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 0784f203b4..3726b6d49e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -161,6 +161,14 @@ private void calcYValueSum() { } } + /** + * Returns the average value across all entries in this DataSet. + * @return + */ + public float getAverage() { + return (float ) getYValueSum() / (float) getValueCount(); + } + /** * returns the number of y-values this DataSet represents * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index f7bc0dee5f..dca2b5cbd1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -377,8 +377,8 @@ else if (wasStacked) * index. * * @param c canvas to draw with - * @param x - * @param y + * @param x position + * @param y position * @param index the index of the color to use (in the colors array) */ protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 323a332804..4ed06cccb7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -206,7 +206,7 @@ public void drawValues(Canvas c) { * mAnimator.getPhaseY())) + center.y); float value = mChart.isUsePercentValuesEnabled() ? entries.get(j).getVal() - / mChart.getYValueSum() * 100f : entries.get(j).getVal(); + / data.getYValueSum() * 100f : entries.get(j).getVal(); String val = dataSet.getValueFormatter().getFormattedValue(value); From f7f509ffb2a7f73e35e9898a6549bd313862d4f8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Sep 2015 16:58:42 +0200 Subject: [PATCH 0472/1390] Added bounds check for issue #952 --- .../com/github/mikephil/charting/renderer/LegendRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index dca2b5cbd1..f42da3a08b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -230,12 +230,12 @@ else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { int lineIndex = 0; for (int i = 0, count = labels.length; i < count; i++) { - if (calculatedLabelBreakPoints[i]) { + if (i < calculatedLabelBreakPoints.length && calculatedLabelBreakPoints[i]) { posX = originPosX; posY += labelLineHeight + labelLineSpacing; } - if (posX == originPosX && legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER) { + if (posX == originPosX && legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER && lineIndex < calculatedLineSizes.length) { posX += (direction == Legend.LegendDirection.RIGHT_TO_LEFT ? calculatedLineSizes[lineIndex].width : -calculatedLineSizes[lineIndex].width) / 2.f; lineIndex++; } From 1c2b45e52c257d2cdf4a43eaeedc20dc8f39322e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Sep 2015 16:59:46 +0200 Subject: [PATCH 0473/1390] Formatting --- .../charting/renderer/LegendRenderer.java | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index f42da3a08b..d9dfb50fdd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -23,13 +23,19 @@ public class LegendRenderer extends Renderer { - /** paint for the legend labels */ + /** + * paint for the legend labels + */ protected Paint mLegendLabelPaint; - /** paint used for the legend forms */ + /** + * paint used for the legend forms + */ protected Paint mLegendFormPaint; - /** the legend object this renderer renders */ + /** + * the legend object this renderer renders + */ protected Legend mLegend; public LegendRenderer(ViewPortHandler viewPortHandler, Legend legend) { @@ -48,7 +54,7 @@ public LegendRenderer(ViewPortHandler viewPortHandler, Legend legend) { /** * Returns the Paint object used for drawing the Legend labels. - * + * * @return */ public Paint getLabelPaint() { @@ -57,7 +63,7 @@ public Paint getLabelPaint() { /** * Returns the Paint object used for drawing the Legend forms. - * + * * @return */ public Paint getFormPaint() { @@ -66,7 +72,7 @@ public Paint getFormPaint() { /** * Prepares the legend and calculates all needed forms, labels and colors. - * + * * @param data */ public void computeLegend(ChartData data) { @@ -198,26 +204,22 @@ public void renderLegend(Canvas c) { switch (legendPosition) { case BELOW_CHART_LEFT: case BELOW_CHART_RIGHT: - case BELOW_CHART_CENTER: - { + case BELOW_CHART_CENTER: { float contentWidth = mViewPortHandler.contentWidth(); float originPosX; - if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT) - { + if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT) { originPosX = mViewPortHandler.contentLeft() + xoffset; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) originPosX += mLegend.mNeededWidth; - } - else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { + } else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { originPosX = mViewPortHandler.contentRight() - xoffset; if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) originPosX -= mLegend.mNeededWidth; - } - else // if (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER) + } else // if (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER) originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f; FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); @@ -266,13 +268,12 @@ else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { posX += calculatedLabelSizes[i].width; posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -xEntrySpace : xEntrySpace; - } - else + } else posX += direction == Legend.LegendDirection.RIGHT_TO_LEFT ? -stackSpace : stackSpace; } } - break; + break; case PIECHART_CENTER: case RIGHT_OF_CHART: @@ -280,8 +281,7 @@ else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { case RIGHT_OF_CHART_INSIDE: case LEFT_OF_CHART: case LEFT_OF_CHART_CENTER: - case LEFT_OF_CHART_INSIDE: - { + case LEFT_OF_CHART_INSIDE: { // contains the stacked legend size in pixels float stack = 0f; boolean wasStacked = false; @@ -319,7 +319,7 @@ else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { * Legend.LegendPosition.RIGHT_OF_CHART_INSIDE || * legendPosition == * Legend.LegendPosition.LEFT_OF_CHART_INSIDE) - */{ + */ { posY = mViewPortHandler.contentTop() + yoffset; } } @@ -375,10 +375,10 @@ else if (wasStacked) /** * Draws the Legend-form at the given position with the color at the given * index. - * - * @param c canvas to draw with - * @param x position - * @param y position + * + * @param c canvas to draw with + * @param x position + * @param y position * @param index the index of the color to use (in the colors array) */ protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { @@ -406,8 +406,8 @@ protected void drawForm(Canvas c, float x, float y, int index, Legend legend) { /** * Draws the provided label at the given position. - * - * @param c canvas to draw with + * + * @param c canvas to draw with * @param x * @param y * @param label the label to draw From ff86e1772cc17130c4d4f2e50ad3b0e9fc7990a7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Sep 2015 20:50:35 +0200 Subject: [PATCH 0474/1390] Added more documentation. Possible fix of #927. --- .../mikephil/charting/charts/BarLineChartBase.java | 12 ++++-------- .../github/mikephil/charting/data/CombinedData.java | 2 ++ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 29983a511a..33e6ca2858 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -785,6 +785,7 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { /** * Moves the left side of the current viewport to the specified x-index. + * This also refreshes the chart by calling invalidate(). * * @param xIndex */ @@ -798,18 +799,11 @@ public void moveViewToX(float xIndex) { } else { mJobs.add(job); } - - // float[] pts = new float[] { - // xIndex, 0f - // }; - // - // getTransformer(AxisDependency.LEFT).pointValuesToPixel(pts); - // - // mViewPortHandler.centerViewPort(pts, this); } /** * Centers the viewport to the specified y-value on the y-axis. + * This also refreshes the chart by calling invalidate(). * * @param yValue * @param axis - which axis should be used as a reference for the y-axis @@ -832,6 +826,7 @@ public void moveViewToY(float yValue, AxisDependency axis) { * This will move the left side of the current viewport to the specified * x-index on the x-axis, and center the viewport to the specified y-value * on the y-axis. + * This also refreshes the chart by calling invalidate(). * * @param xIndex * @param yValue @@ -854,6 +849,7 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { /** * This will move the center of the current viewport to the specified * x-index and y-value. + * This also refreshes the chart by calling invalidate(). * * @param xIndex * @param yValue diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 13a2ef0c6b..0542b58f5b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -91,5 +91,7 @@ public void notifyDataChanged() { mScatterData.notifyDataChanged(); if (mBubbleData != null) mBubbleData.notifyDataChanged(); + + init(); // recalculate everything } } From 0a0fca165c6bcf2cd1915e99d7fdab2cca59fd95 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 11 Sep 2015 21:43:41 +0200 Subject: [PATCH 0475/1390] Added feature for dashed-highlight-lines (#938). --- .../mpchartexample/LineChartActivity1.java | 3 +- .../charting/data/LineRadarDataSet.java | 5 +- .../data/LineScatterCandleRadarDataSet.java | 46 ++++++++++++++++- .../renderer/CandleStickChartRenderer.java | 8 +-- .../charting/renderer/DataRenderer.java | 5 ++ .../charting/renderer/LineChartRenderer.java | 8 +-- .../LineScatterCandleRadarRenderer.java | 50 +++++++++++++++---- .../charting/renderer/RadarChartRenderer.java | 8 +-- .../renderer/ScatterChartRenderer.java | 13 ++--- 9 files changed, 103 insertions(+), 43 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index eedb3ababc..2145a25b42 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -103,7 +103,7 @@ protected void onCreate(Bundle savedInstanceState) { llXAxis.setTextSize(10f); XAxis xAxis = mChart.getXAxis(); - xAxis.addLimitLine(llXAxis); + //xAxis.addLimitLine(llXAxis); // add x-axis limit line LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); @@ -345,6 +345,7 @@ private void setData(int count, float range) { // set the line to be drawn like this "- - - - - -" set1.enableDashedLine(10f, 5f, 0f); + set1.enableDashedHighlightLine(10f, 5f, 0f); set1.setColor(Color.BLACK); set1.setCircleColor(Color.BLACK); set1.setLineWidth(1f); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 49adf841aa..1328122017 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -25,9 +25,8 @@ public abstract class LineRadarDataSet extends LineScatterCandl /** if true, the data will also be drawn filled */ private boolean mDrawFilled = false; - -// private Shader mShader; - + + public LineRadarDataSet(List yVals, String label) { super(yVals, label); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index 6c322c2122..e2c632b75f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -1,11 +1,13 @@ package com.github.mikephil.charting.data; +import android.graphics.DashPathEffect; + import com.github.mikephil.charting.utils.Utils; import java.util.List; /** - * Created by philipp on 11/07/15. + * Created by Philipp Jahoda on 11/07/15. */ public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleDataSet { @@ -15,6 +17,10 @@ public abstract class LineScatterCandleRadarDataSet extends Bar /** the width of the highlight indicator lines */ protected float mHighlightLineWidth = 0.5f; + /** the path effect for dashed highlight-lines */ + protected DashPathEffect mHighlightDashPathEffect = null; + + public LineScatterCandleRadarDataSet(List yVals, String label) { super(yVals, label); mHighlightLineWidth = Utils.convertDpToPixel(0.5f); @@ -61,7 +67,45 @@ public void setHighlightLineWidth(float width) { mHighlightLineWidth = Utils.convertDpToPixel(width); } + /** + * Returns the line-width in which highlight lines are to be drawn. + * @return + */ public float getHighlightLineWidth() { return mHighlightLineWidth; } + + /** + * Enables the highlight-line to be drawn in dashed mode, e.g. like this "- - - - - -" + * + * @param lineLength the length of the line pieces + * @param spaceLength the length of space inbetween the line-pieces + * @param phase offset, in degrees (normally, use 0) + */ + public void enableDashedHighlightLine(float lineLength, float spaceLength, float phase) { + mHighlightDashPathEffect = new DashPathEffect(new float[] { + lineLength, spaceLength + }, phase); + } + + /** + * Disables the highlight-line to be drawn in dashed mode. + */ + public void disableDashedHighlightLine() { + mHighlightDashPathEffect = null; + } + + /** + * Returns true if the dashed-line effect is enabled for highlight lines, false if not. + * Default: disabled + * + * @return + */ + public boolean isDashedHighlightLineEnabled() { + return mHighlightDashPathEffect == null ? false : true; + } + + public DashPathEffect getDashPathEffectHighlight() { + return mHighlightDashPathEffect; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 6d6db7197f..67545ccae8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -286,9 +286,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); - CandleEntry e = set.getEntryForXIndex(xIndex); if (e == null || e.getXIndex() != xIndex) @@ -303,14 +300,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, - mChart.getXChartMax(), y + xIndex, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); // draw the lines - drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); + drawHighlightLines(c, pts, set); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 12e2c121f1..1959862a42 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -13,6 +13,11 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; +/** + * Superclass of all render classes for the different data types (line, bar, ...). + * + * @author Philipp Jahoda + */ public abstract class DataRenderer extends Renderer { /** the animator object used to perform animations on the chart data */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5e8da0d24c..f78366fad2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -538,9 +538,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); - int xIndex = indices[i].getXIndex(); // get the // x-position @@ -556,14 +553,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // y-position float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, - mChart.getXChartMax(), y + xIndex, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); // draw the lines - drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); + drawHighlightLines(c, pts, set); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index 9927face1c..bc5ebd063e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -1,34 +1,62 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.data.LineScatterCandleRadarDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; /** - * Created by philipp on 11/07/15. + * Created by Philipp Jahoda on 11/07/15. */ public abstract class LineScatterCandleRadarRenderer extends DataRenderer { + /** + * path that is used for drawing highlight-lines (drawLines(...) cannot be used because of dashes) + */ + private Path mHighlightLinePath = new Path(); + public LineScatterCandleRadarRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); } /** * Draws vertical & horizontal highlight-lines if enabled. + * * @param c - * @param pts - * @param horizontal - * @param vertical + * @param pts the transformed x- and y-position of the lines + * @param set the currently drawn dataset */ - protected void drawHighlightLines(Canvas c, float[] pts, boolean horizontal, boolean vertical) { + protected void drawHighlightLines(Canvas c, float[] pts, LineScatterCandleRadarDataSet set) { + + // set color and stroke-width + mHighlightPaint.setColor(set.getHighLightColor()); + mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); + + // draw highlighted lines (if enabled) + mHighlightPaint.setPathEffect(set.getDashPathEffectHighlight()); + + // draw vertical highlight lines + if (set.isVerticalHighlightIndicatorEnabled()) { + + // create vertical path + mHighlightLinePath.reset(); + mHighlightLinePath.moveTo(pts[0], mViewPortHandler.contentTop()); + mHighlightLinePath.lineTo(pts[0], mViewPortHandler.contentBottom()); + + c.drawPath(mHighlightLinePath, mHighlightPaint); + } + + // draw horizontal highlight lines + if (set.isHorizontalHighlightIndicatorEnabled()) { - // draw vertical highlight lines - if(vertical) - c.drawLine(pts[0], pts[1], pts[2], pts[3], mHighlightPaint); + // create horizontal path + mHighlightLinePath.reset(); + mHighlightLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); + mHighlightLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); - // draw horizontal highlight lines - if(horizontal) - c.drawLine(pts[4], pts[5], pts[6], pts[7], mHighlightPaint); + c.drawPath(mHighlightLinePath, mHighlightPaint); + } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 58ab05cc1f..be4382a1ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -219,9 +219,6 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); - // get the index to highlight int xIndex = indices[i].getXIndex(); @@ -239,12 +236,11 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { sliceangle * j + mChart.getRotationAngle()); float[] pts = new float[] { - p.x, 0, p.x, mViewPortHandler.getChartHeight(), 0, p.y, - mViewPortHandler.getChartWidth(), p.y + p.x, p.y }; // draw the lines - drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); + drawHighlightLines(c, pts, set); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 23619fc8a3..d236531639 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -258,12 +258,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (set == null || !set.isHighlightEnabled()) continue; - mHighlightPaint.setColor(set.getHighLightColor()); - mHighlightPaint.setStrokeWidth(set.getHighlightLineWidth()); - int xIndex = indices[i].getXIndex(); // get the // x-position + if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) continue; @@ -271,19 +269,16 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (yVal == Float.NaN) continue; - float y = yVal * mAnimator.getPhaseY(); // get - // the - // y-position + float y = yVal * mAnimator.getPhaseY(); float[] pts = new float[] { - xIndex, mChart.getYChartMax(), xIndex, mChart.getYChartMin(), mChart.getXChartMin(), y, - mChart.getXChartMax(), y + xIndex, y }; mChart.getTransformer(set.getAxisDependency()).pointValuesToPixel(pts); // draw the lines - drawHighlightLines(c, pts, set.isHorizontalHighlightIndicatorEnabled(), set.isVerticalHighlightIndicatorEnabled()); + drawHighlightLines(c, pts, set); } } } From 4b9af4c189855294eb8bd5408713af2b3a8f72e7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 00:24:46 +0200 Subject: [PATCH 0476/1390] Fix #931. --- .../src/com/github/mikephil/charting/data/ChartData.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 21abef6396..c44388650c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -149,7 +149,7 @@ private List arrayToList(String[] array) { */ protected void init() { - isLegal(); + checkLegal(); calcMinMax(mLastStart, mLastEnd); calcYValueSum(); @@ -181,11 +181,14 @@ private void calcXValAverageLength() { * Checks if the combination of x-values array and DataSet array is legal or * not. */ - private void isLegal() { + private void checkLegal() { if (mDataSets == null) return; + if(this instanceof ScatterData) + return; + for (int i = 0; i < mDataSets.size(); i++) { if (mDataSets.get(i) .getYVals() From 239cf862b50645d031e5eb10ae08d589cd2f227f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 09:25:41 +0200 Subject: [PATCH 0477/1390] Fix #970 --- .../src/com/github/mikephil/charting/charts/LineChart.java | 2 +- .../com/github/mikephil/charting/utils/FillFormatter.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 9afa24ab5a..a5e3689155 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -50,7 +50,7 @@ protected void calcMinMax() { public void setFillFormatter(FillFormatter formatter) { if (formatter == null) - formatter = new DefaultFillFormatter(); + mFillFormatter = new DefaultFillFormatter(); else mFillFormatter = formatter; } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java index 0fe37914b3..71a6aed250 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java @@ -5,8 +5,8 @@ import com.github.mikephil.charting.data.LineDataSet; /** - * Interface for providing a custom logic to where the filling line of a DataSet - * should end. If setFillEnabled(...) is set to true. + * Interface for providing a custom logic to where the filling line of a LineDataSet + * should end. This of course only works if setFillEnabled(...) is set to true. * * @author Philipp Jahoda */ @@ -14,7 +14,7 @@ public interface FillFormatter { /** * Returns the vertical (y-axis) position where the filled-line of the - * DataSet should end. + * LineDataSet should end. * * @param dataSet * @param data From 71965049c8838621d8d49279370163cfd8c71ece Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 10:40:03 +0200 Subject: [PATCH 0478/1390] CombinedChart highlight improvements - WIP --- .../mpchartexample/LineChartActivity1.java | 13 ---- .../charting/charts/CombinedChart.java | 5 +- .../mikephil/charting/data/CombinedData.java | 22 +++++++ .../highlight/CombinedHighlighter.java | 66 +++++++++++++++++++ .../charting/renderer/DataRenderer.java | 26 ++++++-- .../mikephil/charting/renderer/Renderer.java | 22 ++----- 6 files changed, 118 insertions(+), 36 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 2145a25b42..d662fe21df 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -266,19 +266,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.disableFiltering(); } mChart.invalidate(); - - // - // for(int i = 0; i < 10; i++) { - // mChart.addEntry(new Entry((float) (Math.random() * 100), - // i+2), 0); - // mChart.invalidate(); - // } - // - // Toast.makeText(getApplicationContext(), "valcount: " + - // mChart.getDataOriginal().getYValCount() + ", valsum: " + - // mChart.getDataOriginal().getYValueSum(), - // Toast.LENGTH_SHORT).show(); - // break; } case R.id.actionSave: { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 8f15192d3f..22b295b81f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; +import com.github.mikephil.charting.highlight.CombinedHighlighter; import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.interfaces.BubbleDataProvider; import com.github.mikephil.charting.interfaces.CandleDataProvider; @@ -74,6 +75,8 @@ public CombinedChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); + mHighlighter = new CombinedHighlighter(this); + mFillFormatter = new DefaultFillFormatter(); // mRenderer = new CombinedChartRenderer(this, mAnimator, // mViewPortHandler); @@ -118,7 +121,7 @@ public void setData(CombinedData data) { public void setFillFormatter(FillFormatter formatter) { if (formatter == null) - formatter = new DefaultFillFormatter(); + mFillFormatter = new DefaultFillFormatter(); else mFillFormatter = formatter; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 0542b58f5b..176c047c43 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import java.util.ArrayList; import java.util.List; /** @@ -79,6 +80,27 @@ public CandleData getCandleData() { return mCandleData; } + /** + * Returns all data objects in row: line-bar-scatter-candle-bubble if not null. + * @return + */ + public List getAllData() { + + List data = new ArrayList<>(); + if(mLineData != null) + data.add(mLineData); + if(mBarData != null) + data.add(mBarData); + if(mScatterData != null) + data.add(mScatterData); + if(mCandleData != null) + data.add(mCandleData); + if(mBubbleData != null) + data.add(mBubbleData); + + return data; + } + @Override public void notifyDataChanged() { if (mLineData != null) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java new file mode 100644 index 0000000000..bb335256ea --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -0,0 +1,66 @@ +package com.github.mikephil.charting.highlight; + +import com.github.mikephil.charting.data.ChartData; +import com.github.mikephil.charting.data.CombinedData; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.utils.SelectionDetail; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Philipp Jahoda on 12/09/15. + */ +public class CombinedHighlighter extends ChartHighlighter { + + public CombinedHighlighter(BarLineScatterCandleBubbleDataProvider chart) { + super(chart); + } + + /** + * Returns a list of SelectionDetail object corresponding to the given xIndex. + * + * @param xIndex + * @return + */ + @Override + protected List getSelectionDetailsAtIndex(int xIndex) { + + CombinedData data = (CombinedData) mChart.getData(); + + // get all chartdata objects + List dataObjects = data.getAllData(); + + List vals = new ArrayList(); + + float[] pts = new float[2]; + + for (int i = 0; i < dataObjects.size(); i++) { + + for(int j = 0; j < dataObjects.get(i).getDataSetCount(); j++) { + + DataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); + + // dont include datasets that cannot be highlighted + if (!dataSet.isHighlightEnabled()) + continue; + + // extract all y-values from all DataSets at the given x-index + final float yVal = dataSet.getYValForXIndex(xIndex); + if (yVal == Float.NaN) + continue; + + pts[1] = yVal; + + mChart.getTransformer(dataSet.getAxisDependency()).pointValuesToPixel(pts); + + if (!Float.isNaN(pts[1])) { + vals.add(new SelectionDetail(pts[1], j, dataSet)); + } + } + } + + return vals; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 1959862a42..42a4fbaef4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -20,13 +20,19 @@ */ public abstract class DataRenderer extends Renderer { - /** the animator object used to perform animations on the chart data */ + /** + * the animator object used to perform animations on the chart data + */ protected ChartAnimator mAnimator; - /** main paint object used for rendering */ + /** + * main paint object used for rendering + */ protected Paint mRenderPaint; - /** paint used for highlighting values */ + /** + * paint used for highlighting values + */ protected Paint mHighlightPaint; protected Paint mDrawPaint; @@ -60,7 +66,7 @@ public DataRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { /** * Returns the Paint object this renderer uses for drawing the values * (value-text). - * + * * @return */ public Paint getPaintValues() { @@ -70,7 +76,7 @@ public Paint getPaintValues() { /** * Returns the Paint object this renderer uses for drawing highlight * indicators. - * + * * @return */ public Paint getPaintHighlight() { @@ -79,7 +85,7 @@ public Paint getPaintHighlight() { /** * Returns the Paint object used for rendering. - * + * * @return */ public Paint getPaintRender() { @@ -89,7 +95,7 @@ public Paint getPaintRender() { /** * Applies the required styling (provided by the DataSet) to the value-paint * object. - * + * * @param set */ protected void applyValueTextStyle(DataSet set) { @@ -112,5 +118,11 @@ protected void applyValueTextStyle(DataSet set) { public abstract void drawExtras(Canvas c); + /** + * Draws all highlight indicators for the values that are currently highlighted. + * + * @param c + * @param indices the highlighted values + */ public abstract void drawHighlighted(Canvas c, Highlight[] indices); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index b17c2da02c..dd1975e213 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -45,27 +45,19 @@ protected boolean fitsBounds(float val, float min, float max) { /** * Calculates the minimum and maximum x-value the chart can currently - * display (with the given zoom level). + * display (with the given zoom level). -> mMinX, mMaxX * - * @param chart - * @param modulus + * @param dataProvider + * @param xAxisModulus */ - public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { + public void calcXBounds(BarLineScatterCandleBubbleDataProvider dataProvider, int xAxisModulus) { - int low = chart.getLowestVisibleXIndex(); - int high = chart.getHighestVisibleXIndex(); + int low = dataProvider.getLowestVisibleXIndex(); + int high = dataProvider.getHighestVisibleXIndex(); int subLow = (low % xAxisModulus == 0) ? xAxisModulus : 0; mMinX = Math.max((low / xAxisModulus) * (xAxisModulus) - subLow, 0); - mMaxX = Math.min((high / xAxisModulus) * (xAxisModulus) + xAxisModulus, (int) chart.getXChartMax()); - -// double minx = trans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), 0).x; -// double maxx = trans.getValuesByTouchPoint(mViewPortHandler.contentRight(), 0).x; -// -// if (!Double.isInfinite(minx)) -// mMinX = (int) minx; -// if (!Double.isInfinite(maxx)) -// mMaxX = (int) Math.ceil(maxx); + mMaxX = Math.min((high / xAxisModulus) * (xAxisModulus) + xAxisModulus, (int) dataProvider.getXChartMax()); } } From bfd781a4dca3be7ca1a3ceec2a44f4db5971b6c5 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 11:16:13 +0200 Subject: [PATCH 0479/1390] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index c230f8758d..58e6e0cffd 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,6 @@ Donations - [**Donate 25 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H9JA4QX7UHXCY): That's some awesome stuff you did right there, dinner is on me! - [**Donate 50 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=ZPQVJ2XRBSBYY): I really really want to support this project, great job! - [**Donate 100 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=KY7F59RYPCYCQ): You are the man! This project saved me hours (if not days) of struggle and hard work, simply awesome! - - [**Donate 300 $**] (https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=PGW8CXUHZS2T2): I can afford it and want to assure the further development and maintenance of this project. Furthermore, I also want to show my gratitude to it's creator. - Of course, you can also [**choose what you want to donate**](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=EGBENAC5XBCKS), all donations are awesome! **Spread the word** From d93a5614d22d720b5c4985175e8837021b8180a1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 11:29:06 +0200 Subject: [PATCH 0480/1390] Update README.md --- README.md | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 58e6e0cffd..426ab43d81 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,6 @@ Features - **LineChart (cubic lines)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) - - **LineChart (single DataSet)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/linechart.png) - - **Combined-Chart (bar- and linechart in this case)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) @@ -172,19 +169,11 @@ dependencies { **4. clone whole repository** - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - - Import the library folder (`MPChartLib`) into your Eclipse workspace - - Add it as a reference to your project: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) - -Proguard -======= - -In case you are using Proguard, you will need to **whitelist MPAndroidChart**, which requires to add the following line to your Proguard configuration file. - -``` --keep class com.github.mikephil.charting.** { *; } -``` + - Import the library folder (`MPChartLib`) into Android Studio or your Eclipse workspace + - Add it as a reference to your project: + - [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) + - [managing projects from Android Studio](https://developer.android.com/sdk/installing/create-project.html) -If you don't do this, animations might not work. Documentation ======= From a9cb766310048db828a5d741095e2911c0f9809f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 12 Sep 2015 18:27:39 +0200 Subject: [PATCH 0481/1390] Allow FillFormatter for individual LineDataSets. --- .../mpchartexample/LineChartActivity2.java | 3 ++ .../custom/MyFillFormatter.java | 23 +++++++++ .../charting/charts/BarLineChartBase.java | 41 --------------- .../charting/charts/CombinedChart.java | 17 ------- .../mikephil/charting/charts/LineChart.java | 17 ------- .../mikephil/charting/data/LineDataSet.java | 28 +++++++++++ .../charting/interfaces/LineDataProvider.java | 17 ++----- .../charting/renderer/LineChartRenderer.java | 8 ++- .../charting/utils/DefaultFillFormatter.java | 50 +++++++++++++++++++ .../charting/utils/FillFormatter.java | 10 ++-- 10 files changed, 114 insertions(+), 100 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 40c1700aae..6cce635b44 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -29,6 +29,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; +import com.xxmassdeveloper.mpchartexample.custom.MyFillFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -292,6 +293,7 @@ private void setData(int count, float range) { set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setDrawCircleHole(false); + //set1.setFillFormatter(new MyFillFormatter(0f)); // set1.setDrawHorizontalHighlightIndicator(false); // set1.setVisible(false); // set1.setCircleHoleColor(Color.WHITE); @@ -317,6 +319,7 @@ private void setData(int count, float range) { set2.setFillColor(Color.RED); set2.setDrawCircleHole(false); set2.setHighLightColor(Color.rgb(244, 117, 117)); + //set2.setFillFormatter(new MyFillFormatter(900f)); ArrayList dataSets = new ArrayList(); dataSets.add(set2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java new file mode 100644 index 0000000000..443e4a0756 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -0,0 +1,23 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.utils.FillFormatter; + +/** + * Created by Philipp Jahoda on 12/09/15. + */ +public class MyFillFormatter implements FillFormatter { + + private float mFillPos = 0f; + + public MyFillFormatter(float fillpos) { + this.mFillPos = fillpos; + } + + @Override + public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + // your logic could be here + return mFillPos; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 33e6ca2858..b704077dd6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1497,45 +1497,4 @@ public Paint getPaint(int which) { return null; } - - /** - * Default formatter that calculates the position of the filled line. - * - * @author Philipp Jahoda - */ - protected class DefaultFillFormatter implements FillFormatter { - - @Override - public float getFillLinePosition(LineDataSet dataSet, LineData data, - float chartMaxY, float chartMinY) { - - float fillMin = 0f; - - if (dataSet.getYMax() > 0 && dataSet.getYMin() < 0) { - fillMin = 0f; - } else { - - if (!getAxis(dataSet.getAxisDependency()).isStartAtZeroEnabled()) { - - float max, min; - - if (data.getYMax() > 0) - max = 0f; - else - max = chartMaxY; - if (data.getYMin() < 0) - min = 0f; - else - min = chartMinY; - - fillMin = dataSet.getYMin() >= 0 ? min : max; - } else { - fillMin = 0f; - } - - } - - return fillMin; - } - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 22b295b81f..8a82016d85 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -29,9 +29,6 @@ public class CombinedChart extends BarLineChartBase implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider, BubbleDataProvider { - /** the fill-formatter used for determining the position of the fill-line */ - protected FillFormatter mFillFormatter; - /** flag that enables or disables the highlighting arrow */ private boolean mDrawHighlightArrow = false; @@ -77,7 +74,6 @@ protected void init() { mHighlighter = new CombinedHighlighter(this); - mFillFormatter = new DefaultFillFormatter(); // mRenderer = new CombinedChartRenderer(this, mAnimator, // mViewPortHandler); } @@ -118,19 +114,6 @@ public void setData(CombinedData data) { mRenderer.initBuffers(); } - public void setFillFormatter(FillFormatter formatter) { - - if (formatter == null) - mFillFormatter = new DefaultFillFormatter(); - else - mFillFormatter = formatter; - } - - @Override - public FillFormatter getFillFormatter() { - return mFillFormatter; - } - @Override public LineData getLineData() { if (mData == null) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index a5e3689155..d4f577b8ae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -16,8 +16,6 @@ */ public class LineChart extends BarLineChartBase implements LineDataProvider { - private FillFormatter mFillFormatter; - public LineChart(Context context) { super(context); } @@ -35,7 +33,6 @@ protected void init() { super.init(); mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); - mFillFormatter = new DefaultFillFormatter(); } @Override @@ -45,20 +42,6 @@ protected void calcMinMax() { if (mDeltaX == 0 && mData.getYValCount() > 0) mDeltaX = 1; } - - @Override - public void setFillFormatter(FillFormatter formatter) { - - if (formatter == null) - mFillFormatter = new DefaultFillFormatter(); - else - mFillFormatter = formatter; - } - - @Override - public FillFormatter getFillFormatter() { - return mFillFormatter; - } @Override public LineData getLineData() { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index bd3abf544d..c0faad07ca 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -5,7 +5,10 @@ import android.graphics.Color; import android.graphics.DashPathEffect; +import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.DefaultFillFormatter; +import com.github.mikephil.charting.utils.FillFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -28,6 +31,9 @@ public class LineDataSet extends LineRadarDataSet { /** the path effect of this DataSet that makes dashed lines possible */ private DashPathEffect mDashPathEffect = null; + /** formatter for customizing the position of the fill-line */ + private FillFormatter mFillFormatter = new DefaultFillFormatter(); + /** if true, drawing circles is enabled */ private boolean mDrawCircles = true; @@ -308,4 +314,26 @@ public void setDrawCircleHole(boolean enabled) { public boolean isDrawCircleHoleEnabled() { return mDrawCircleHole; } + + /** + * Sets a custom FillFormatter to the chart that handles the position of the + * filled-line for each DataSet. Set this to null to use the default logic. + * + * @param formatter + */ + public void setFillFormatter(FillFormatter formatter) { + + if (formatter == null) + mFillFormatter = new DefaultFillFormatter(); + else + mFillFormatter = formatter; + } + + /** + * Returns the FillFormatter that is set for this DataSet. + * @return + */ + public FillFormatter getFillFormatter() { + return mFillFormatter; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java index d6704f37e8..a8a9eee2a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.interfaces; +import com.github.mikephil.charting.components.AxisBase; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.utils.FillFormatter; @@ -8,18 +10,5 @@ public interface LineDataProvider extends BarLineScatterCandleBubbleDataProvider public LineData getLineData(); - /** - * Sets a custom FillFormatter to the chart that handles the position of the - * filled-line for each DataSet. Set this to null to use the default logic. - * - * @param formatter - */ - public void setFillFormatter(FillFormatter formatter); - - /** - * Returns the FillFormatter that handles the position of the filled-line. - * - * @return - */ - public FillFormatter getFillFormatter(); + public YAxis getAxis(YAxis.AxisDependency dependency); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index f78366fad2..1d80c43920 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -237,9 +237,8 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { protected void drawCubicFill(LineDataSet dataSet, Path spline, Transformer trans, int from, int to) { - float fillMin = mChart.getFillFormatter() - .getFillLinePosition(dataSet, mChart.getLineData(), mChart.getYChartMax(), - mChart.getYChartMin()); + float fillMin = dataSet.getFillFormatter() + .getFillLinePosition(dataSet, mChart); spline.lineTo(to - 1, fillMin); spline.lineTo(from, fillMin); @@ -353,8 +352,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries Path filled = generateFilledPath( entries, - mChart.getFillFormatter().getFillLinePosition(dataSet, mChart.getLineData(), - mChart.getYChartMax(), mChart.getYChartMin()), minx, maxx); + dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart), minx, maxx); trans.pathValueToPixel(filled); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java new file mode 100644 index 0000000000..c2ac68214c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java @@ -0,0 +1,50 @@ +package com.github.mikephil.charting.utils; + + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.LineDataProvider; + +/** + * Default formatter that calculates the position of the filled line. + * + * @author Philipp Jahoda + */ +public class DefaultFillFormatter implements FillFormatter { + + @Override + public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + + float fillMin = 0f; + float chartMaxY = dataProvider.getYChartMax(); + float chartMinY = dataProvider.getYChartMin(); + + LineData data = dataProvider.getLineData(); + + if (dataSet.getYMax() > 0 && dataSet.getYMin() < 0) { + fillMin = 0f; + } else { + + if (!dataProvider.getAxis(dataSet.getAxisDependency()).isStartAtZeroEnabled()) { + + float max, min; + + if (data.getYMax() > 0) + max = 0f; + else + max = chartMaxY; + if (data.getYMin() < 0) + min = 0f; + else + min = chartMinY; + + fillMin = dataSet.getYMin() >= 0 ? min : max; + } else { + fillMin = 0f; + } + } + + return fillMin; + } +} \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java index 71a6aed250..5e03ba930f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.LineDataProvider; /** * Interface for providing a custom logic to where the filling line of a LineDataSet @@ -16,12 +17,9 @@ public interface FillFormatter { * Returns the vertical (y-axis) position where the filled-line of the * LineDataSet should end. * - * @param dataSet - * @param data - * @param chartMaxY - * @param chartMinY + * @param dataSet the LineDataSet that is currently drawn + * @param dataProvider * @return */ - public float getFillLinePosition(LineDataSet dataSet, LineData data, float chartMaxY, - float chartMinY); + public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider); } From 766fb9a009f6d19335b646f99249196302367ed7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 14 Sep 2015 09:56:14 +0200 Subject: [PATCH 0482/1390] Refactoring of PR. --- .../mikephil/charting/charts/RadarChart.java | 91 +++++++++++-------- .../mikephil/charting/components/XAxis.java | 2 - .../charting/renderer/RadarChartRenderer.java | 4 +- 3 files changed, 57 insertions(+), 40 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 3c45c03da4..c4873b6bfd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -22,35 +22,54 @@ /** * Implementation of the RadarChart, a "spidernet"-like chart. It works best * when displaying 5-10 entries per DataSet. - * + * * @author Philipp Jahoda */ public class RadarChart extends PieRadarChartBase { - /** width of the main web lines */ + /** + * width of the main web lines + */ private float mWebLineWidth = 2.5f; - /** width of the inner web lines */ + /** + * width of the inner web lines + */ private float mInnerWebLineWidth = 1.5f; - /** color for the main web lines */ + /** + * color for the main web lines + */ private int mWebColor = Color.rgb(122, 122, 122); - /** color for the inner web */ + /** + * color for the inner web + */ private int mWebColorInner = Color.rgb(122, 122, 122); - /** transparency the grid is drawn with (0-255) */ + /** + * transparency the grid is drawn with (0-255) + */ private int mWebAlpha = 150; - /** flag indicating if the web lines should be drawn or not */ + /** + * flag indicating if the web lines should be drawn or not + */ private boolean mDrawWeb = true; + /** + * modulus that determines how many labels and web-lines are skipped before the next is drawn + */ private int mWebModulus = 1; - /** the object reprsenting the y-axis labels */ + /** + * the object reprsenting the y-axis labels + */ private YAxis mYAxis; - /** the object representing the x-axis labels */ + /** + * the object representing the x-axis labels + */ private XAxis mXAxis; protected YAxisRendererRadarChart mYAxisRenderer; @@ -107,19 +126,16 @@ protected void calcMinMax() { // If the values are all negative, let's stay in the negative zone mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); mYAxis.mAxisMaximum = 0.f; - } - else if (minLeft >= 0.0) { + } else if (minLeft >= 0.0) { // We have positive values only, stay in the positive zone mYAxis.mAxisMinimum = 0.f; mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } - else { + } else { // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); } - } - else { + } else { // Use the values as they are mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft); mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft); @@ -138,7 +154,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { PointF p = new PointF((float) (c.x + val * Math.cos(Math.toRadians(angle))), (float) (c.y + val * Math.sin(Math.toRadians(angle)))); - return new float[] { + return new float[]{ p.x, p.y }; } @@ -195,7 +211,7 @@ protected void onDraw(Canvas canvas) { /** * Returns the factor that is needed to transform values into pixels. - * + * * @return */ public float getFactor() { @@ -206,7 +222,7 @@ public float getFactor() { /** * Returns the angle that each slice in the radar chart occupies. - * + * * @return */ public float getSliceAngle() { @@ -231,7 +247,7 @@ public int getIndexForAngle(float angle) { /** * Returns the object that represents all y-labels of the RadarChart. - * + * * @return */ public YAxis getYAxis() { @@ -241,7 +257,7 @@ public YAxis getYAxis() { /** * Returns the object that represents all x-labels that are placed around * the RadarChart. - * + * * @return */ public XAxis getXAxis() { @@ -250,7 +266,7 @@ public XAxis getXAxis() { /** * Sets the width of the web lines that come from the center. - * + * * @param width */ public void setWebLineWidth(float width) { @@ -264,7 +280,7 @@ public float getWebLineWidth() { /** * Sets the width of the web lines that are in between the lines coming from * the center. - * + * * @param width */ public void setWebLineWidthInner(float width) { @@ -278,7 +294,7 @@ public float getWebLineWidthInner() { /** * Sets the transparency (alpha) value for all web lines, default: 150, 255 * = 100% opaque, 0 = 100% transparent - * + * * @param alpha */ public void setWebAlpha(int alpha) { @@ -287,7 +303,7 @@ public void setWebAlpha(int alpha) { /** * Returns the alpha value for all web lines. - * + * * @return */ public int getWebAlpha() { @@ -298,7 +314,7 @@ public int getWebAlpha() { * Sets the color for the web lines that come from the center. Don't forget * to use getResources().getColor(...) when loading a color from the * resources. Default: Color.rgb(122, 122, 122) - * + * * @param color */ public void setWebColor(int color) { @@ -313,7 +329,7 @@ public int getWebColor() { * Sets the color for the web lines in between the lines that come from the * center. Don't forget to use getResources().getColor(...) when loading a * color from the resources. Default: Color.rgb(122, 122, 122) - * + * * @param color */ public void setWebColorInner(int color) { @@ -327,7 +343,7 @@ public int getWebColorInner() { /** * If set to true, drawing the web is enabled, if set to false, drawing the * whole web is disabled. Default: true - * + * * @param enabled */ public void setDrawWeb(boolean enabled) { @@ -335,22 +351,25 @@ public void setDrawWeb(boolean enabled) { } /** - * Sets the number of lines that should be skipped on the web before the - * next line is drawn. + * Sets the number of web-lines that should be skipped on chart web before the + * next one is drawn. This targets the lines that come from the center of the RadarChart. * - * @param count + * @param count if count = 1 -> 1 line is skipped in between */ - public void setSkipWebLines(int count) { - if (count >0) { - mWebModulus = count; - } + public void setSkipWebLineCount(int count) { + + if (count < 0) + count = 0; + + mWebModulus = count + 1; } /** + * Returns the modulus that is used for skipping web-lines. * * @return */ - public int getWebModulus() { + public int getSkipWebLineCount() { return mWebModulus; } @@ -386,7 +405,7 @@ public float getYChartMin() { /** * Returns the range of y-values this chart can display. - * + * * @return */ public float getYRange() { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 1e03100fbf..5ce722928f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -139,8 +139,6 @@ public boolean isAxisModulusCustom() { /** * Returns the space (in characters) that should be left out between the * x-axis labels - * - * @param space */ public int getSpaceBetweenLabels() { return mSpaceBetweenLabels; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 12132c0a08..57c68ce410 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -173,8 +173,8 @@ protected void drawWeb(Canvas c) { mWebPaint.setColor(mChart.getWebColor()); mWebPaint.setAlpha(mChart.getWebAlpha()); - int mod = mChart.getWebModulus(); - for (int i = 0; i < mChart.getData().getXValCount(); i += mod) { + for (int i = 0; i < mChart.getData().getXValCount(); i += mChart.getSkipWebLineCount()) { + PointF p = Utils.getPosition(center, mChart.getYRange() * factor, sliceangle * i + rotationangle); From e198679f764c7475ef5d2c2439b37d340418568a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 14 Sep 2015 11:27:34 +0200 Subject: [PATCH 0483/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 426ab43d81..37bc958cf5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Twitter](https://img.shields.io/badge/twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) Remember: *It's all about the looks.* From e21e919aa9b80e44179e630cc4a63dcaa298d8f4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 14 Sep 2015 11:36:19 +0200 Subject: [PATCH 0484/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37bc958cf5..a2ed9d8484 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Twitter](https://img.shields.io/badge/twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) Remember: *It's all about the looks.* From 996c79f568f19c42ee39ce65e6344edb5e71091c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 14 Sep 2015 20:47:48 +0200 Subject: [PATCH 0485/1390] Added feature for custom-formatting x-values #848. --- .../mpchartexample/LineChartActivity1.java | 35 ++++++++++--------- .../custom/MyCustomXValueFormatter.java | 30 ++++++++++++++++ .../charting/charts/BarLineChartBase.java | 14 +++----- .../mikephil/charting/components/XAxis.java | 31 ++++++++++++++++ .../mikephil/charting/data/BarData.java | 2 +- .../mikephil/charting/data/BarDataSet.java | 2 +- .../data/BarLineScatterCandleBubbleData.java | 33 +++++++++++++++++ ...=> BarLineScatterCandleBubbleDataSet.java} | 4 +-- .../data/BarLineScatterCandleData.java | 33 ----------------- .../mikephil/charting/data/BubbleData.java | 2 +- .../mikephil/charting/data/BubbleDataSet.java | 2 +- .../mikephil/charting/data/CandleData.java | 2 +- .../mikephil/charting/data/CombinedData.java | 2 +- .../mikephil/charting/data/LineData.java | 2 +- .../data/LineScatterCandleRadarDataSet.java | 2 +- .../mikephil/charting/data/ScatterData.java | 2 +- ...arLineScatterCandleBubbleDataProvider.java | 4 +-- .../listener/BarLineChartTouchListener.java | 8 ++--- .../charting/renderer/XAxisRenderer.java | 9 +++-- .../renderer/XAxisRendererBarChart.java | 4 +-- .../XAxisRendererHorizontalBarChart.java | 3 +- .../renderer/XAxisRendererRadarChart.java | 4 +-- .../utils/DefaultXValueFormatter.java | 14 ++++++++ .../charting/utils/ViewPortHandler.java | 14 ++++++++ .../charting/utils/XValueFormatter.java | 12 +++++++ 25 files changed, 183 insertions(+), 87 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java rename MPChartLib/src/com/github/mikephil/charting/data/{BarLineScatterCandleDataSet.java => BarLineScatterCandleBubbleDataSet.java} (83%) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index d662fe21df..cf1595ca31 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -27,9 +27,9 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -94,7 +94,7 @@ protected void onCreate(Bundle savedInstanceState) { // set the marker to the chart mChart.setMarkerView(mv); - + // x-axis limit line LimitLine llXAxis = new LimitLine(10f, "Index 10"); llXAxis.setLineWidth(4f); @@ -103,8 +103,9 @@ protected void onCreate(Bundle savedInstanceState) { llXAxis.setTextSize(10f); XAxis xAxis = mChart.getXAxis(); + //xAxis.setXValueFormatter(new MyCustomXValueFormatter()); //xAxis.addLimitLine(llXAxis); // add x-axis limit line - + LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); ll1.enableDashedLine(10f, 10f, 0f); @@ -126,7 +127,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); - + // limit lines are drawn behind data (and not on top) leftAxis.setDrawLimitLinesBehindData(true); @@ -134,14 +135,14 @@ protected void onCreate(Bundle savedInstanceState) { // add data setData(45, 100); - + // mChart.setVisibleXRange(20); // mChart.setVisibleYRange(20f, AxisDependency.LEFT); // mChart.centerViewTo(20, 50, AxisDependency.LEFT); - + mChart.animateX(2500, Easing.EasingOption.EaseInOutQuart); // mChart.invalidate(); - + // get the legend (only possible after setting data) Legend l = mChart.getLegend(); @@ -152,7 +153,7 @@ protected void onCreate(Bundle savedInstanceState) { // // dont forget to refresh the drawing // mChart.invalidate(); } - + @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); @@ -168,7 +169,7 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { - case R.id.actionToggleValues: { + case R.id.actionToggleValues: { for (DataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); @@ -320,8 +321,8 @@ private void setData(int count, float range) { float mult = (range + 1); float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10); + // ((mult * + // 0.1) / 10); yVals.add(new Entry(val, i)); } @@ -354,7 +355,7 @@ private void setData(int count, float range) { // set data mChart.setData(data); } - + @Override public void onChartLongPressed(MotionEvent me) { Log.i("LongPress", "Chart longpressed."); @@ -380,12 +381,12 @@ public void onChartScale(MotionEvent me, float scaleX, float scaleY) { Log.i("Scale / Zoom", "ScaleX: " + scaleX + ", ScaleY: " + scaleY); } - @Override - public void onChartTranslate(MotionEvent me, float dX, float dY) { - Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); - } + @Override + public void onChartTranslate(MotionEvent me, float dX, float dY) { + Log.i("Translate / Move", "dX: " + dX + ", dY: " + dY); + } - @Override + @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { Log.i("Entry selected", e.toString()); Log.i("", "low: " + mChart.getLowestVisibleXIndex() + ", high: " + mChart.getHighestVisibleXIndex()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java new file mode 100644 index 0000000000..5762fe4e36 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java @@ -0,0 +1,30 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.utils.ViewPortHandler; +import com.github.mikephil.charting.utils.XValueFormatter; + +/** + * Created by Philipp Jahoda on 14/09/15. + */ +public class MyCustomXValueFormatter implements XValueFormatter { + + public MyCustomXValueFormatter() { + // maybe do something here or provide parameters in constructor + } + + @Override + public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { + + //Log.i("TRANS", "x: " + viewPortHandler.getTransX() + ", y: " + viewPortHandler.getTransY()); + + // e.g. adjust the x-axis values depending on scale / zoom level + if (viewPortHandler.getScaleX() > 5) + return "4"; + else if (viewPortHandler.getScaleX() > 3) + return "3"; + else if (viewPortHandler.getScaleX() > 1) + return "2"; + else + return original; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index b704077dd6..7ee2a07fd3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -20,11 +20,9 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.BarLineScatterCandleData; -import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; @@ -33,22 +31,18 @@ import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; -import com.github.mikephil.charting.utils.FillFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; -import java.util.List; - /** * Base-class of LineChart, BarChart, ScatterChart and CandleStickChart. * * @author Philipp Jahoda */ @SuppressLint("RtlHardcoded") -public abstract class BarLineChartBase>> +public abstract class BarLineChartBase>> extends Chart implements BarLineScatterCandleBubbleDataProvider { /** the maximum number of entried to which values will be drawn */ @@ -1204,7 +1198,7 @@ public Entry getEntryByTouchPoint(float x, float y) { * @param y * @return */ - public BarLineScatterCandleDataSet getDataSetByTouchPoint(float x, float y) { + public BarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float y) { Highlight h = getHighlightByTouchPoint(x, y); if (h != null) { return mData.getDataSetByIndex(h.getDataSetIndex()); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 5ce722928f..76e1cbacdc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -1,6 +1,9 @@ package com.github.mikephil.charting.components; +import com.github.mikephil.charting.utils.DefaultXValueFormatter; +import com.github.mikephil.charting.utils.XValueFormatter; + import java.util.ArrayList; import java.util.List; @@ -60,6 +63,11 @@ public class XAxis extends AxisBase { */ private boolean mAvoidFirstLastClipping = false; + /** + * Custom formatter for adjusting x-value strings + */ + protected XValueFormatter mXValueFormatter = new DefaultXValueFormatter(); + /** the position of the x-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; @@ -181,6 +189,29 @@ public List getValues() { return mValues; } + + /** + * Sets a custom XValueFormatter for the data object that allows custom-formatting + * of all x-values before rendering them. Provide null to reset back to the + * default formatting. + * + * @param formatter + */ + public void setXValueFormatter(XValueFormatter formatter) { + if(formatter == null) + mXValueFormatter = new DefaultXValueFormatter(); + else + mXValueFormatter = formatter; + } + + /** + * Returns the custom XValueFormatter that is set for this data object. + * @return + */ + public XValueFormatter getXValueFormatter() { + return mXValueFormatter; + } + @Override public String getLongestLabel() { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 3cbd1b1e9f..5da2ea5718 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -9,7 +9,7 @@ * * @author Philipp Jahoda */ -public class BarData extends BarLineScatterCandleData { +public class BarData extends BarLineScatterCandleBubbleData { /** the space that is left between groups of bars */ private float mGroupSpace = 0.8f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index 4dc74795ec..e339964e96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -6,7 +6,7 @@ import java.util.ArrayList; import java.util.List; -public class BarDataSet extends BarLineScatterCandleDataSet { +public class BarDataSet extends BarLineScatterCandleBubbleDataSet { /** space indicator between the bars 0.1f == 10 % */ private float mBarSpace = 0.15f; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java new file mode 100644 index 0000000000..884140f378 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -0,0 +1,33 @@ + +package com.github.mikephil.charting.data; + +import java.util.List; + +/** + * Baseclass for all Line, Bar, Scatter, Candle and Bubble data. + * + * @author Philipp Jahoda + */ +public abstract class BarLineScatterCandleBubbleData> + extends ChartData { + + public BarLineScatterCandleBubbleData() { + super(); + } + + public BarLineScatterCandleBubbleData(List xVals) { + super(xVals); + } + + public BarLineScatterCandleBubbleData(String[] xVals) { + super(xVals); + } + + public BarLineScatterCandleBubbleData(List xVals, List sets) { + super(xVals, sets); + } + + public BarLineScatterCandleBubbleData(String[] xVals, List sets) { + super(xVals, sets); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java similarity index 83% rename from MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index b0578704a8..d7499b4b96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -10,12 +10,12 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleDataSet extends DataSet { +public abstract class BarLineScatterCandleBubbleDataSet extends DataSet { /** default highlight color */ protected int mHighLightColor = Color.rgb(255, 187, 115); - public BarLineScatterCandleDataSet(List yVals, String label) { + public BarLineScatterCandleBubbleDataSet(List yVals, String label) { super(yVals, label); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java deleted file mode 100644 index b9dbda531d..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleData.java +++ /dev/null @@ -1,33 +0,0 @@ - -package com.github.mikephil.charting.data; - -import java.util.List; - -/** - * Baseclass for all Line, Bar and ScatterData. - * - * @author Philipp Jahoda - */ -public abstract class BarLineScatterCandleData> - extends ChartData { - - public BarLineScatterCandleData() { - super(); - } - - public BarLineScatterCandleData(List xVals) { - super(xVals); - } - - public BarLineScatterCandleData(String[] xVals) { - super(xVals); - } - - public BarLineScatterCandleData(List xVals, List sets) { - super(xVals, sets); - } - - public BarLineScatterCandleData(String[] xVals, List sets) { - super(xVals, sets); - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index 943cf902eb..67cd2e1bfd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.List; -public class BubbleData extends BarLineScatterCandleData { +public class BubbleData extends BarLineScatterCandleBubbleData { public BubbleData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 106b2ddf6e..759b7307fb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; -public class BubbleDataSet extends BarLineScatterCandleDataSet { +public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet { // NOTE: Do not initialize these, as the calcMinMax is called by the super, // and the initializers are called after that and can reset the values diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index 1b25d5075c..4794207d14 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; -public class CandleData extends BarLineScatterCandleData { +public class CandleData extends BarLineScatterCandleBubbleData { public CandleData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 176c047c43..019c81df96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -10,7 +10,7 @@ * * @author Philipp Jahoda */ -public class CombinedData extends BarLineScatterCandleData> { +public class CombinedData extends BarLineScatterCandleBubbleData> { private LineData mLineData; private BarData mBarData; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index c653072475..245319d07f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -9,7 +9,7 @@ * * @author Philipp Jahoda */ -public class LineData extends BarLineScatterCandleData { +public class LineData extends BarLineScatterCandleBubbleData { public LineData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index e2c632b75f..5c0b7f86af 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -9,7 +9,7 @@ /** * Created by Philipp Jahoda on 11/07/15. */ -public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleDataSet { +public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleBubbleDataSet { protected boolean mDrawVerticalHighlightIndicator = true; protected boolean mDrawHorizontalHighlightIndicator = true; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index 22adb5e55d..faf7066add 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import java.util.List; -public class ScatterData extends BarLineScatterCandleData { +public class ScatterData extends BarLineScatterCandleBubbleData { public ScatterData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java index c92d1b513f..41dd8c4c6a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.interfaces; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.BarLineScatterCandleData; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; import com.github.mikephil.charting.utils.Transformer; public interface BarLineScatterCandleBubbleDataProvider extends ChartInterface { @@ -13,5 +13,5 @@ public interface BarLineScatterCandleBubbleDataProvider extends ChartInterface { int getLowestVisibleXIndex(); int getHighestVisibleXIndex(); - BarLineScatterCandleData getData(); + BarLineScatterCandleBubbleData getData(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 6326399c0d..18d3ee44a7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -12,8 +12,8 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.HorizontalBarChart; -import com.github.mikephil.charting.data.BarLineScatterCandleData; -import com.github.mikephil.charting.data.BarLineScatterCandleDataSet; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; @@ -26,7 +26,7 @@ * * @author Philipp Jahoda */ -public class BarLineChartTouchListener extends ChartTouchListener>>> { +public class BarLineChartTouchListener extends ChartTouchListener>>> { /** the original touch-matrix from the chart */ private Matrix mMatrix = new Matrix(); @@ -53,7 +53,7 @@ public class BarLineChartTouchListener extends ChartTouchListener>> chart, Matrix touchMatrix) { + public BarLineChartTouchListener(BarLineChartBase>> chart, Matrix touchMatrix) { super(chart); this.mMatrix = touchMatrix; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index f56066b811..1d1684a72d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -150,13 +150,16 @@ protected void drawLabels(Canvas c, float pos) { } } - c.drawText(label, position[0], - pos, - mAxisLabelPaint); + drawLabel(c, label, i, position[0], pos); } } } + protected void drawLabel(Canvas c, String label, int xIndex, float x, float y) { + String formattedLabel = mXAxis.getXValueFormatter().getXValue(label, xIndex, mViewPortHandler); + c.drawText(formattedLabel, x, y, mAxisLabelPaint); + } + @Override public void renderGridLines(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index fb792687d4..1a1d304be3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -72,9 +72,7 @@ protected void drawLabels(Canvas c, float pos) { } } - c.drawText(label, position[0], - pos, - mAxisLabelPaint); + drawLabel(c, label, i, position[0], pos); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 9edcb80b00..25a02e7df1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -108,8 +108,7 @@ protected void drawLabels(Canvas c, float pos) { if (mViewPortHandler.isInBoundsY(position[1])) { String label = mXAxis.getValues().get(i); - c.drawText(label, pos, position[1] + mXAxis.mLabelHeight / 2f, - mAxisLabelPaint); + drawLabel(c, label, i, pos, position[1] + mXAxis.mLabelHeight / 2f); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index f6710ebc6d..b5a9ebc594 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -39,14 +39,14 @@ public void renderAxisLabels(Canvas c) { int mod = mXAxis.mAxisLabelModulus; for (int i = 0; i < mXAxis.getValues().size(); i += mod) { - String text = mXAxis.getValues().get(i); + String label = mXAxis.getValues().get(i); float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; PointF p = Utils.getPosition(center, mChart.getYRange() * factor + mXAxis.mLabelWidth / 2f, angle); - c.drawText(text, p.x, p.y + mXAxis.mLabelHeight / 2f, mAxisLabelPaint); + drawLabel(c, label, i, p.x, p.y + mXAxis.mLabelHeight / 2f); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java new file mode 100644 index 0000000000..e284b027af --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java @@ -0,0 +1,14 @@ +package com.github.mikephil.charting.utils; + +/** + * Created by Philipp Jahoda on 14/09/15. + * Default formatter class for adjusting x-values before drawing them. + * This simply returns the original value unmodified. + */ +public class DefaultXValueFormatter implements XValueFormatter { + + @Override + public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { + return original; // just return original, no adjustments + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 3b6e503c3e..1fe4a928ee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -32,6 +32,10 @@ public class ViewPortHandler { /** contains the current scale factor of the y-axis */ private float mScaleY = 1f; + private float mTransX = 0f; + + private float mTransY = 0f; + /** offset that allows the chart to be dragged over its bounds on the x-axis */ private float mTransOffsetX = 0f; @@ -293,6 +297,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float maxTransX = -width * (mScaleX - 1f); float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); + mTransX = newTransX; // if(curScaleX < mMinScaleX) { // newTransX = (-width * (mScaleX - 1f)) / 2f; @@ -300,6 +305,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float maxTransY = height * (mScaleY - 1f); float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); + mTransY = newTransY; // if(curScaleY < mMinScaleY) { // newTransY = (height * (mScaleY - 1f)) / 2f; @@ -419,6 +425,14 @@ public float getScaleY() { return mScaleY; } + public float getTransX() { + return mTransX; + } + + public float getTransY() { + return mTransY; + } + /** * if the chart is fully zoomed out, return true * diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java new file mode 100644 index 0000000000..d254d5c11a --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java @@ -0,0 +1,12 @@ +package com.github.mikephil.charting.utils; + +/** + * Created by Philipp Jahoda on 14/09/15. + * An interface for providing custom x-axis Strings. + * + * @author Philipp Jahoda + */ +public interface XValueFormatter { + + String getXValue(String original, int index, ViewPortHandler viewPortHandler); +} From 2e6bfeb87e2bb0a02fb6350b96a454d77f7c088b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 14 Sep 2015 21:01:15 +0200 Subject: [PATCH 0486/1390] Add documentation. --- .../github/mikephil/charting/utils/XValueFormatter.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java index d254d5c11a..67d835cf51 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java @@ -8,5 +8,13 @@ */ public interface XValueFormatter { + /** + * Returns the customized label that is drawn on the x-axis. + * + * @param original the original x-axis label to be drawn + * @param index the x-index that is currently being drawn + * @param viewPortHandler provides information about the current chart state (scale, translation, ...) + * @return + */ String getXValue(String original, int index, ViewPortHandler viewPortHandler); } From ba152072a6a7adbf8e9e166904798219c1200172 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 15 Sep 2015 12:38:05 +0200 Subject: [PATCH 0487/1390] Allow setting maximum y-scale factor. --- .../mpchartexample/LineChartActivity1.java | 3 +++ .../mikephil/charting/utils/ViewPortHandler.java | 16 +++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index cf1595ca31..3a36aa09de 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -133,6 +133,9 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisRight().setEnabled(false); + mChart.getViewPortHandler().setMaximumScaleY(2f); + mChart.getViewPortHandler().setMaximumScaleX(2f); + // add data setData(45, 100); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 1fe4a928ee..a80432b994 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -20,6 +20,9 @@ public class ViewPortHandler { /** minimum scale value on the y-axis */ private float mMinScaleY = 1f; + /** maximum scale value on the y-axis */ + private float mMaxScaleY = Float.MAX_VALUE; + /** minimum scale value on the x-axis */ private float mMinScaleX = 1f; @@ -285,7 +288,7 @@ public void limitTransAndScale(Matrix matrix, RectF content) { mScaleX = Math.min(Math.max(mMinScaleX, curScaleX), mMaxScaleX); // min scale-y is 1f - mScaleY = Math.max(mMinScaleY, curScaleY); + mScaleY = Math.min(Math.max(mMinScaleY, curScaleY), mMaxScaleY); float width = 0f; float height = 0f; @@ -307,10 +310,6 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); mTransY = newTransY; - // if(curScaleY < mMinScaleY) { - // newTransY = (height * (mScaleY - 1f)) / 2f; - // } - vals[Matrix.MTRANS_X] = newTransX; vals[Matrix.MSCALE_X] = mScaleX; @@ -358,6 +357,13 @@ public void setMinimumScaleY(float yScale) { limitTransAndScale(mMatrixTouch, mContentRect); } + public void setMaximumScaleY(float yScale) { + + mMaxScaleY = yScale; + + limitTransAndScale(mMatrixTouch, mContentRect); + } + /** * Returns the charts-touch matrix used for translation and scale on touch. * From 94dae2ef6f9bbc7510a1cf2f27da9ddd300bb710 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 15 Sep 2015 12:47:31 +0200 Subject: [PATCH 0488/1390] Remove comments --- .../github/mikephil/charting/utils/ViewPortHandler.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index a80432b994..44ae1001c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -302,18 +302,14 @@ public void limitTransAndScale(Matrix matrix, RectF content) { float newTransX = Math.min(Math.max(curTransX, maxTransX - mTransOffsetX), mTransOffsetX); mTransX = newTransX; - // if(curScaleX < mMinScaleX) { - // newTransX = (-width * (mScaleX - 1f)) / 2f; - // } - float maxTransY = height * (mScaleY - 1f); float newTransY = Math.max(Math.min(curTransY, maxTransY + mTransOffsetY), -mTransOffsetY); mTransY = newTransY; - vals[Matrix.MTRANS_X] = newTransX; + vals[Matrix.MTRANS_X] = mTransX; vals[Matrix.MSCALE_X] = mScaleX; - vals[Matrix.MTRANS_Y] = newTransY; + vals[Matrix.MTRANS_Y] = mTransY; vals[Matrix.MSCALE_Y] = mScaleY; matrix.setValues(vals); From 5a15715b25991e3d61d27d552f9eba45975d65e7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 20 Sep 2015 10:21:13 +0200 Subject: [PATCH 0489/1390] New formatters for YAxis and XAxis with greater customizeability. --- .../mpchartexample/BarChartActivity.java | 7 ++-- .../BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/LineChartActivity1.java | 6 +-- .../mpchartexample/PieChartActivity.java | 2 +- .../mpchartexample/StackedBarActivity.java | 3 +- .../StackedBarActivityNegative.java | 15 +++++-- ....java => MyCustomXAxisValueFormatter.java} | 6 +-- .../custom/MyFillFormatter.java | 2 +- .../custom/MyValueFormatter.java | 9 +++-- .../custom/MyYAxisValueFormatter.java | 20 ++++++++++ .../listviewitems/PieChartItem.java | 2 +- .../charting/charts/BarLineChartBase.java | 8 ++-- .../mikephil/charting/charts/Chart.java | 4 +- .../charting/charts/CombinedChart.java | 1 - .../mikephil/charting/charts/LineChart.java | 1 - .../mikephil/charting/charts/RadarChart.java | 6 +-- .../mikephil/charting/components/XAxis.java | 22 +++++----- .../mikephil/charting/components/YAxis.java | 33 ++++++++------- .../mikephil/charting/data/ChartData.java | 2 +- .../mikephil/charting/data/DataSet.java | 4 +- .../mikephil/charting/data/LineDataSet.java | 5 +-- .../{utils => formatter}/ColorFormatter.java | 2 +- .../DefaultFillFormatter.java | 3 +- .../DefaultValueFormatter.java | 14 +++++-- .../DefaultXAxisAxisValueFormatter.java} | 6 ++- .../formatter/DefaultYAxisValueFormatter.java | 40 +++++++++++++++++++ .../{utils => formatter}/FillFormatter.java | 2 +- .../LargeValueFormatter.java | 19 +++++++-- .../charting/formatter/PercentFormatter.java | 35 ++++++++++++++++ .../charting/formatter/ValueFormatter.java | 28 +++++++++++++ .../XAxisValueFormatter.java} | 8 +++- .../formatter/YAxisValueFormatter.java | 22 ++++++++++ .../charting/interfaces/ChartInterface.java | 2 +- .../charting/interfaces/LineDataProvider.java | 2 - .../charting/renderer/BarChartRenderer.java | 33 +++++---------- .../renderer/BubbleChartRenderer.java | 14 +++---- .../renderer/CandleStickChartRenderer.java | 5 +-- .../charting/renderer/DataRenderer.java | 32 +++++++++++++++ .../renderer/HorizontalBarChartRenderer.java | 27 ++++++++----- .../charting/renderer/LineChartRenderer.java | 7 ++-- .../charting/renderer/PieChartRenderer.java | 22 +++++----- .../charting/renderer/RadarChartRenderer.java | 19 ++++----- .../renderer/ScatterChartRenderer.java | 7 ++-- .../charting/renderer/XAxisRenderer.java | 2 +- .../charting/utils/PercentFormatter.java | 24 ----------- .../charting/utils/ValueFormatter.java | 22 ---------- 46 files changed, 355 insertions(+), 202 deletions(-) rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/{MyCustomXValueFormatter.java => MyCustomXAxisValueFormatter.java} (81%) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java rename MPChartLib/src/com/github/mikephil/charting/{utils => formatter}/ColorFormatter.java (86%) rename MPChartLib/src/com/github/mikephil/charting/{utils => formatter}/DefaultFillFormatter.java (92%) rename MPChartLib/src/com/github/mikephil/charting/{utils => formatter}/DefaultValueFormatter.java (62%) rename MPChartLib/src/com/github/mikephil/charting/{utils/DefaultXValueFormatter.java => formatter/DefaultXAxisAxisValueFormatter.java} (65%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java rename MPChartLib/src/com/github/mikephil/charting/{utils => formatter}/FillFormatter.java (93%) rename MPChartLib/src/com/github/mikephil/charting/{utils => formatter}/LargeValueFormatter.java (71%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java rename MPChartLib/src/com/github/mikephil/charting/{utils/XValueFormatter.java => formatter/XAxisValueFormatter.java} (68%) create mode 100644 MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 1db0e0232e..be899270db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -33,8 +33,8 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.ValueFormatter; -import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; +import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -92,7 +92,7 @@ protected void onCreate(Bundle savedInstanceState) { xAxis.setDrawGridLines(false); xAxis.setSpaceBetweenLabels(2); - ValueFormatter custom = new MyValueFormatter(); + YAxisValueFormatter custom = new MyYAxisValueFormatter(); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTf); @@ -267,7 +267,6 @@ private void setData(int count, float range) { dataSets.add(set1); BarData data = new BarData(xVals, dataSets); - // data.setValueFormatter(new MyValueFormatter()); data.setValueTextSize(10f); data.setValueTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 652a314ff1..398d00373f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -24,7 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.LargeValueFormatter; +import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3a36aa09de..2831c89716 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -103,7 +103,7 @@ protected void onCreate(Bundle savedInstanceState) { llXAxis.setTextSize(10f); XAxis xAxis = mChart.getXAxis(); - //xAxis.setXValueFormatter(new MyCustomXValueFormatter()); + //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); //xAxis.addLimitLine(llXAxis); // add x-axis limit line LimitLine ll1 = new LimitLine(130f, "Upper Limit"); @@ -133,8 +133,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getAxisRight().setEnabled(false); - mChart.getViewPortHandler().setMaximumScaleY(2f); - mChart.getViewPortHandler().setMaximumScaleX(2f); + //mChart.getViewPortHandler().setMaximumScaleY(2f); + //mChart.getViewPortHandler().setMaximumScaleX(2f); // add data setData(45, 100); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 613426259c..468f71e79a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -23,7 +23,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.PercentFormatter; +import com.github.mikephil.charting.formatter.PercentFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 4edc128f74..8ed71e49e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -29,6 +29,7 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; +import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -71,7 +72,7 @@ protected void onCreate(Bundle savedInstanceState) { // change the position of the y-labels YAxis yLabels = mChart.getAxisLeft(); - yLabels.setValueFormatter(new MyValueFormatter()); + yLabels.setValueFormatter(new MyYAxisValueFormatter()); mChart.getAxisRight().setEnabled(false); XAxis xLabels = mChart.getXAxis(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index c242a7f2f8..89acfc268e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -24,7 +24,9 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; +import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.text.DecimalFormat; @@ -211,7 +213,7 @@ public void onNothingSelected() { } - private class CustomFormatter implements ValueFormatter { + private class CustomFormatter implements ValueFormatter, YAxisValueFormatter { private DecimalFormat mFormat; @@ -219,8 +221,15 @@ public CustomFormatter() { mFormat = new DecimalFormat("###"); } + // data @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(Math.abs(value)) + "m"; + } + + // YAxis + @Override + public String getFormattedValue(float value, YAxis yAxis) { return mFormat.format(Math.abs(value)) + "m"; } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java similarity index 81% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java index 5762fe4e36..bdf918b1b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyCustomXAxisValueFormatter.java @@ -1,14 +1,14 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.utils.ViewPortHandler; -import com.github.mikephil.charting.utils.XValueFormatter; +import com.github.mikephil.charting.formatter.XAxisValueFormatter; /** * Created by Philipp Jahoda on 14/09/15. */ -public class MyCustomXValueFormatter implements XValueFormatter { +public class MyCustomXAxisValueFormatter implements XAxisValueFormatter { - public MyCustomXValueFormatter() { + public MyCustomXAxisValueFormatter() { // maybe do something here or provide parameters in constructor } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index 443e4a0756..de96237cc5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.LineDataProvider; -import com.github.mikephil.charting.utils.FillFormatter; +import com.github.mikephil.charting.formatter.FillFormatter; /** * Created by Philipp Jahoda on 12/09/15. diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java index c71b1ac1b8..a374b60e7f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyValueFormatter.java @@ -1,6 +1,8 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -11,10 +13,9 @@ public class MyValueFormatter implements ValueFormatter { public MyValueFormatter() { mFormat = new DecimalFormat("###,###,###,##0.0"); } - + @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { return mFormat.format(value) + " $"; } - } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java new file mode 100644 index 0000000000..cae82be1d9 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyYAxisValueFormatter.java @@ -0,0 +1,20 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.formatter.YAxisValueFormatter; + +import java.text.DecimalFormat; + +public class MyYAxisValueFormatter implements YAxisValueFormatter { + + private DecimalFormat mFormat; + + public MyYAxisValueFormatter() { + mFormat = new DecimalFormat("###,###,###,##0.0"); + } + + @Override + public String getFormattedValue(float value, YAxis yAxis) { + return mFormat.format(value) + " $"; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index 82bd6d1032..a8e02c325d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.utils.PercentFormatter; +import com.github.mikephil.charting.formatter.PercentFormatter; import com.xxmassdeveloper.mpchartexample.R; public class PieChartItem extends ChartItem { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 7ee2a07fd3..1fc2ec2ea1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -306,10 +306,10 @@ public void notifyDataSetChanged() { calcMinMax(); - if (mAxisLeft.needsDefaultFormatter()) - mAxisLeft.setValueFormatter(mDefaultFormatter); - if (mAxisRight.needsDefaultFormatter()) - mAxisRight.setValueFormatter(mDefaultFormatter); +// if (mAxisLeft.needsDefaultFormatter()) +// mAxisLeft.setValueFormatter(mDefaultFormatter); +// if (mAxisRight.needsDefaultFormatter()) +// mAxisRight.setValueFormatter(mDefaultFormatter); mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 7b61ead635..f2c86c5160 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -40,10 +40,10 @@ import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.renderer.DataRenderer; import com.github.mikephil.charting.renderer.LegendRenderer; -import com.github.mikephil.charting.utils.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.io.File; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 8a82016d85..9c4be80cf2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -18,7 +18,6 @@ import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.interfaces.ScatterDataProvider; import com.github.mikephil.charting.renderer.CombinedChartRenderer; -import com.github.mikephil.charting.utils.FillFormatter; /** * This chart class allows the combination of lines, bars, scatter and candle diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index d4f577b8ae..e04859fe50 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -7,7 +7,6 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; -import com.github.mikephil.charting.utils.FillFormatter; /** * Chart that draws lines, surfaces, circles, ... diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index c4873b6bfd..961a0a0472 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -166,9 +166,9 @@ public void notifyDataSetChanged() { calcMinMax(); - if (mYAxis.needsDefaultFormatter()) { - mYAxis.setValueFormatter(mDefaultFormatter); - } +// if (mYAxis.needsDefaultFormatter()) { +// mYAxis.setValueFormatter(mDefaultFormatter); +// } mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum); mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 76e1cbacdc..3db471710f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -1,8 +1,8 @@ package com.github.mikephil.charting.components; -import com.github.mikephil.charting.utils.DefaultXValueFormatter; -import com.github.mikephil.charting.utils.XValueFormatter; +import com.github.mikephil.charting.formatter.DefaultXAxisAxisValueFormatter; +import com.github.mikephil.charting.formatter.XAxisValueFormatter; import java.util.ArrayList; import java.util.List; @@ -66,7 +66,7 @@ public class XAxis extends AxisBase { /** * Custom formatter for adjusting x-value strings */ - protected XValueFormatter mXValueFormatter = new DefaultXValueFormatter(); + protected XAxisValueFormatter mXAxisValueFormatter = new DefaultXAxisAxisValueFormatter(); /** the position of the x-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; @@ -101,7 +101,7 @@ public void setPosition(XAxisPosition pos) { * labels, default 4. This only applies if the number of labels that will be * skipped in between drawn axis labels is not custom set. * - * @param space + * @param spaceCharacters */ public void setSpaceBetweenLabels(int spaceCharacters) { mSpaceBetweenLabels = spaceCharacters; @@ -191,25 +191,25 @@ public List getValues() { /** - * Sets a custom XValueFormatter for the data object that allows custom-formatting + * Sets a custom XAxisValueFormatter for the data object that allows custom-formatting * of all x-values before rendering them. Provide null to reset back to the * default formatting. * * @param formatter */ - public void setXValueFormatter(XValueFormatter formatter) { + public void setValueFormatter(XAxisValueFormatter formatter) { if(formatter == null) - mXValueFormatter = new DefaultXValueFormatter(); + mXAxisValueFormatter = new DefaultXAxisAxisValueFormatter(); else - mXValueFormatter = formatter; + mXAxisValueFormatter = formatter; } /** - * Returns the custom XValueFormatter that is set for this data object. + * Returns the custom XAxisValueFormatter that is set for this data object. * @return */ - public XValueFormatter getXValueFormatter() { - return mXValueFormatter; + public XAxisValueFormatter getValueFormatter() { + return mXAxisValueFormatter; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 12a93559c6..0c2365e4e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -2,9 +2,10 @@ import android.graphics.Paint; -import com.github.mikephil.charting.utils.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.DefaultYAxisValueFormatter; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.YAxisValueFormatter; /** * Class representing the y-axis labels settings and its entries. Only use the setter methods to modify it. Do not @@ -17,7 +18,7 @@ public class YAxis extends AxisBase { /** custom formatter that is used instead of the auto-formatter if set */ - protected ValueFormatter mValueFormatter; + protected YAxisValueFormatter mYAxisValueFormatter; /** the actual array of entries */ public float[] mEntries = new float[] {}; @@ -358,42 +359,46 @@ public String getFormattedLabel(int index) { if (index < 0 || index >= mEntries.length) return ""; else - return getValueFormatter().getFormattedValue(mEntries[index]); + return getValueFormatter().getFormattedValue(mEntries[index], this); } /** - * Sets the formatter to be used for drawing the values inside the chart. If no formatter is set, the chart will + * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the chart will * automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. * * @param f */ - public void setValueFormatter(ValueFormatter f) { + public void setValueFormatter(YAxisValueFormatter f) { if (f == null) - return; + mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); else - mValueFormatter = f; + mYAxisValueFormatter = f; } /** - * Returns the formatter used for drawing the values inside the chart. + * Returns the formatter used for formatting the axis labels. * * @return */ - public ValueFormatter getValueFormatter() { - return mValueFormatter; + public YAxisValueFormatter getValueFormatter() { + + if(mYAxisValueFormatter == null) + mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); + + return mYAxisValueFormatter; } /** - * If this component has no ValueFormatter or is only equipped with the default one (no custom set), return true. + * If this component has no YAxisValueFormatter or is only equipped with the default one (no custom set), return true. * * @return */ public boolean needsDefaultFormatter() { - if (mValueFormatter == null) + if (mYAxisValueFormatter == null) return true; - if (mValueFormatter instanceof DefaultValueFormatter) + if (mYAxisValueFormatter instanceof DefaultValueFormatter) return true; return false; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index c44388650c..ff60bbfde7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.ArrayList; import java.util.Arrays; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 3726b6d49e..c3fff6cafc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -7,9 +7,9 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index c0faad07ca..fdbd15d6ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -5,10 +5,9 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.utils.DefaultFillFormatter; -import com.github.mikephil.charting.utils.FillFormatter; +import com.github.mikephil.charting.formatter.DefaultFillFormatter; +import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/ColorFormatter.java similarity index 86% rename from MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/ColorFormatter.java index 81da6ae089..3a7d119e60 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ColorFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/ColorFormatter.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java similarity index 92% rename from MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index c2ac68214c..20ba8fdda4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultFillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -1,7 +1,6 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.LineDataProvider; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultValueFormatter.java similarity index 62% rename from MPChartLib/src/com/github/mikephil/charting/utils/DefaultValueFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/DefaultValueFormatter.java index f63c77edc7..bd66f51d08 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultValueFormatter.java @@ -1,10 +1,13 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; /** - * Default formatter used for formatting values. Uses a DecimalFormat with + * Default formatter used for formatting values inside the chart. Uses a DecimalFormat with * pre-calculated number of digits (depending on max and min value). * * @author Philipp Jahoda @@ -33,8 +36,11 @@ public DefaultValueFormatter(int digits) { } @Override - public String getFormattedValue(float value) { - // avoid memory allocations here (for performance) + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + + // put more logic here ... + // avoid memory allocations here (for performance reasons) + return mFormat.format(value); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java similarity index 65% rename from MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java index e284b027af..4a30df6ff8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/DefaultXValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java @@ -1,11 +1,13 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.utils.ViewPortHandler; /** * Created by Philipp Jahoda on 14/09/15. * Default formatter class for adjusting x-values before drawing them. * This simply returns the original value unmodified. */ -public class DefaultXValueFormatter implements XValueFormatter { +public class DefaultXAxisAxisValueFormatter implements XAxisValueFormatter { @Override public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java new file mode 100644 index 0000000000..5b8cd01452 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultYAxisValueFormatter.java @@ -0,0 +1,40 @@ +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.YAxis; + +import java.text.DecimalFormat; + +/** + * Created by Philipp Jahoda on 20/09/15. + * Default formatter used for formatting labels of the YAxis. Uses a DecimalFormat with + * pre-calculated number of digits (depending on max and min value). + */ +public class DefaultYAxisValueFormatter implements YAxisValueFormatter { + + /** decimalformat for formatting */ + private DecimalFormat mFormat; + + /** + * Constructor that specifies to how many digits the value should be + * formatted. + * + * @param digits + */ + public DefaultYAxisValueFormatter(int digits) { + + StringBuffer b = new StringBuffer(); + for (int i = 0; i < digits; i++) { + if (i == 0) + b.append("."); + b.append("0"); + } + + mFormat = new DecimalFormat("###,###,###,##0" + b.toString()); + } + + @Override + public String getFormattedValue(float value, YAxis yAxis) { + // avoid memory allocations here (for performance) + return mFormat.format(value); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java similarity index 93% rename from MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java index b8fe50bef7..424874a199 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java similarity index 71% rename from MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 119c671588..74b95b7d5c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -1,5 +1,9 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; import java.text.DecimalFormat; @@ -13,7 +17,7 @@ * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ -public class LargeValueFormatter implements ValueFormatter { +public class LargeValueFormatter implements ValueFormatter, YAxisValueFormatter { private static final String[] SUFFIX = new String[] { "", "k", "m", "b", "t" @@ -29,15 +33,22 @@ public LargeValueFormatter() { /** * Creates a formatter that appends a specified text to the result string - * @param text a text that will be appended + * @param appendix a text that will be appended */ public LargeValueFormatter(String appendix) { this(); mText = appendix; } + // ValueFormatter + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return makePretty(value) + mText; + } + + // YAxisValueFormatter @Override - public String getFormattedValue(float value) { + public String getFormattedValue(float value, YAxis yAxis) { return makePretty(value) + mText; } diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java new file mode 100644 index 0000000000..01011ce59b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -0,0 +1,35 @@ + +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; + +/** + * This ValueFormatter is just for convenience and simply puts a "%" sign after + * each value. (Recommeded for PieChart) + * + * @author Philipp Jahoda + */ +public class PercentFormatter implements ValueFormatter, YAxisValueFormatter { + + protected DecimalFormat mFormat; + + public PercentFormatter() { + mFormat = new DecimalFormat("###,###,##0.0"); + } + + // ValueFormatter + @Override + public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { + return mFormat.format(value) + " %"; + } + + // YAxisValueFormatter + @Override + public String getFormattedValue(float value, YAxis yAxis) { + return mFormat.format(value) + " %"; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java new file mode 100644 index 0000000000..1f056bf786 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/ValueFormatter.java @@ -0,0 +1,28 @@ +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Interface that allows custom formatting of all values inside the chart before they are + * being drawn to the screen. Simply create your own formatting class and let + * it implement ValueFormatter. Then override the getFormattedValue(...) method + * and return whatever you want. + * + * @author Philipp Jahoda + */ +public interface ValueFormatter { + + /** + * Called when a value (from labels inside the chart) is formatted + * before being drawn. For performance reasons, avoid excessive calculations + * and memory allocations inside this method. + * + * @param value the value to be formatted + * @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry + * @param dataSetIndex the index of the DataSet the entry in focus belongs to + * @param viewPortHandler provides information about the current chart state (scale, translation, ...) + * @return the formatted label ready for being drawn + */ + String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/XAxisValueFormatter.java similarity index 68% rename from MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/XAxisValueFormatter.java index 67d835cf51..1dcb72b04b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/XValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/XAxisValueFormatter.java @@ -1,4 +1,6 @@ -package com.github.mikephil.charting.utils; +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.utils.ViewPortHandler; /** * Created by Philipp Jahoda on 14/09/15. @@ -6,10 +8,12 @@ * * @author Philipp Jahoda */ -public interface XValueFormatter { +public interface XAxisValueFormatter { /** * Returns the customized label that is drawn on the x-axis. + * For performance reasons, avoid excessive calculations + * and memory allocations inside this method. * * @param original the original x-axis label to be drawn * @param index the x-index that is currently being drawn diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java new file mode 100644 index 0000000000..4bc6c3e987 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/YAxisValueFormatter.java @@ -0,0 +1,22 @@ +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.components.YAxis; + +/** + * Created by Philipp Jahoda on 20/09/15. + * Custom formatter interface that allows formatting of + * YAxis labels before they are being drawn. + */ +public interface YAxisValueFormatter { + + /** + * Called when a value from the YAxis is formatted + * before being drawn. For performance reasons, avoid excessive calculations + * and memory allocations inside this method. + * + * @param value the YAxis value to be formatted + * @param yAxis the YAxis object the value belongs to + * @return + */ + String getFormattedValue(float value, YAxis yAxis); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java index 9c4d0628d8..216e9a6cef 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java @@ -4,7 +4,7 @@ import android.graphics.RectF; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; /** * Interface that provides everything there is to know about the dimensions, diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java index 92d3d2b669..ef4866ef77 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java @@ -1,9 +1,7 @@ package com.github.mikephil.charting.interfaces; -import com.github.mikephil.charting.components.AxisBase; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.utils.FillFormatter; public interface LineDataProvider extends BarLineScatterCandleBubbleDataProvider { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 5324ef1121..1f55d17d8c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -17,7 +17,6 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; @@ -206,8 +205,6 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextHeight; } - ValueFormatter formatter = dataSet.getValueFormatter(); - Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); List entries = dataSet.getYVals(); @@ -226,9 +223,10 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) continue; - float val = entries.get(j / 2).getVal(); + BarEntry entry = entries.get(j / 2); + float val = entry.getVal(); - drawValue(c, formatter.getFormattedValue(val), valuePoints[j], + drawValue(c, dataSet.getValueFormatter(), val, entry, i, valuePoints[j], valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset)); } @@ -237,9 +235,9 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - BarEntry e = entries.get(j / 2); + BarEntry entry = entries.get(j / 2); - float[] vals = e.getVals(); + float[] vals = entry.getVals(); // we still draw stacked bars, but there is one // non-stacked @@ -253,8 +251,8 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) continue; - drawValue(c, formatter.getFormattedValue(e.getVal()), valuePoints[j], - valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset)); + drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, valuePoints[j], + valuePoints[j + 1] + (entry.getVal() >= 0 ? posOffset : negOffset)); // draw stack values } else { @@ -262,7 +260,7 @@ public void drawValues(Canvas c) { float[] transformed = new float[vals.length * 2]; float posY = 0f; - float negY = -e.getNegativeSum(); + float negY = -entry.getNegativeSum(); for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) { @@ -295,7 +293,7 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(x)) continue; - drawValue(c, formatter.getFormattedValue(vals[k / 2]), x, y); + drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y); } } } @@ -304,19 +302,6 @@ public void drawValues(Canvas c) { } } - /** - * Draws a value at the specified x and y position. - * - * @param value - * @param xPos - * @param yPos - * @formatter - */ - protected void drawValue(Canvas c, String value, float xPos, float yPos) { - c.drawText(value, xPos, yPos, - mValuePaint); - } - @Override public void drawHighlighted(Canvas c, Highlight[] indices) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index bf198eeb5d..dae2f1a7d0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -131,7 +131,9 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "1"); - for (BubbleDataSet dataSet : dataSets) { + for (int i = 0; i < dataSets.size(); i++) { + + BubbleDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -171,14 +173,10 @@ public void drawValues(Canvas c) { if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; - final BubbleEntry entry = entries.get(j / 2 + minx); - - final float val = entry.getSize(); + BubbleEntry entry = entries.get(j / 2 + minx); - c.drawText(dataSet.getValueFormatter().getFormattedValue(val), - x, - y + (0.5f * lineHeight), - mValuePaint); + drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, + y + (0.5f * lineHeight)); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 67545ccae8..460f983975 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -259,10 +259,9 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - float val = entries.get(j / 2 + minx).getHigh(); + CandleEntry entry = entries.get(j / 2 + minx); - c.drawText(dataSet.getValueFormatter().getFormattedValue(val), x, y - yOffset, - mValuePaint); + drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 42a4fbaef4..87daddac45 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -9,8 +9,10 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -112,10 +114,40 @@ protected void applyValueTextStyle(DataSet set) { */ public abstract void initBuffers(); + /** + * Draws the actual data in form of lines, bars, ... depending on Renderer subclass. + * + * @param c + */ public abstract void drawData(Canvas c); + /** + * Loops over all Entrys and draws their values. + * + * @param c + */ public abstract void drawValues(Canvas c); + /** + * Draws the value of the given entry by using the provided ValueFormatter. + * + * @param c canvas + * @param formatter formatter for custom value-formatting + * @param value the value to be drawn + * @param entry the entry the value belongs to + * @param dataSetIndex the index of the DataSet the drawn Entry belongs to + * @param x position + * @param y position + */ + public void drawValue(Canvas c, ValueFormatter formatter, float value, Entry entry, int dataSetIndex, float x, float y) { + c.drawText(formatter.getFormattedValue(value, entry, dataSetIndex, mViewPortHandler), x, y, mValuePaint); + } + + /** + * Draws any kind of additional information (e.g. line-circles). + * + * @param c + */ public abstract void drawExtras(Canvas c); /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 25c902853a..850464bea2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.interfaces.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.utils.ValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; @@ -138,11 +138,12 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) continue; - float val = entries.get(j / 2).getVal(); - String valueText = formatter.getFormattedValue(val); + BarEntry e = entries.get(j / 2); + float val = e.getVal(); + String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value - float valueTextWidth = Utils.calcTextWidth(mValuePaint, valueText); + float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -151,7 +152,7 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, valueText, valuePoints[j] + (val >= 0 ? posOffset : negOffset), + drawValue(c, formattedValue, valuePoints[j] + (val >= 0 ? posOffset : negOffset), valuePoints[j + 1] + halfTextHeight); } @@ -179,10 +180,10 @@ public void drawValues(Canvas c) { continue; float val = e.getVal(); - String valueText = formatter.getFormattedValue(val); + String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value - float valueTextWidth = Utils.calcTextWidth(mValuePaint, valueText); + float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -191,7 +192,7 @@ public void drawValues(Canvas c) { negOffset = -negOffset - valueTextWidth; } - drawValue(c, valueText, valuePoints[j] + drawValue(c, formattedValue, valuePoints[j] + (e.getVal() >= 0 ? posOffset : negOffset), valuePoints[j + 1] + halfTextHeight); @@ -223,10 +224,10 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { float val = vals[k / 2]; - String valueText = formatter.getFormattedValue(val); + String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); // calculate the correct offset depending on the draw position of the value - float valueTextWidth = Utils.calcTextWidth(mValuePaint, valueText); + float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue); posOffset = (drawValueAboveBar ? valueOffsetPlus : -(valueTextWidth + valueOffsetPlus)); negOffset = (drawValueAboveBar ? -(valueTextWidth + valueOffsetPlus) : valueOffsetPlus); @@ -248,7 +249,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(y)) continue; - drawValue(c, valueText, x, y + halfTextHeight); + drawValue(c, formattedValue, x, y + halfTextHeight); } } } @@ -257,6 +258,10 @@ public void drawValues(Canvas c) { } } + protected void drawValue(Canvas c, String valueText, float x, float y) { + c.drawText(valueText, x, y, mValuePaint); + } + @Override protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, Transformer trans) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 1d80c43920..186b925d39 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -444,11 +444,10 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - float val = entries.get(j / 2 + minx).getVal(); + Entry entry = entries.get(j / 2 + minx); - c.drawText(dataSet.getValueFormatter().getFormattedValue(val), x, - y - valOffset, - mValuePaint); + drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, x, + y - valOffset); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 4ed06cccb7..5766bd3371 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Utils; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; @@ -189,36 +190,39 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); + float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + + Utils.convertDpToPixel(4f); + List entries = dataSet.getYVals(); for (int j = 0, maxEntry = Math.min( (int) Math.ceil(entries.size() * mAnimator.getPhaseX()), entries.size()); j < maxEntry; j++) { + Entry entry = entries.get(j); + // offset needed to center the drawn text in the slice float offset = drawAngles[cnt] / 2; // calculate the text position float x = (float) (r * Math.cos(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) - * mAnimator.getPhaseY())) + center.x); + * mAnimator.getPhaseY())) + center.x); float y = (float) (r * Math.sin(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) * mAnimator.getPhaseY())) + center.y); - float value = mChart.isUsePercentValuesEnabled() ? entries.get(j).getVal() - / data.getYValueSum() * 100f : entries.get(j).getVal(); + float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() + / data.getYValueSum() * 100f : entry.getVal(); - String val = dataSet.getValueFormatter().getFormattedValue(value); - - float lineHeight = Utils.calcTextHeight(mValuePaint, val) - + Utils.convertDpToPixel(4f); + ValueFormatter formatter = dataSet.getValueFormatter(); boolean drawYVals = dataSet.isDrawValuesEnabled(); // draw everything, depending on settings if (drawXVals && drawYVals) { - c.drawText(val, x, y, mValuePaint); + drawValue(c, formatter, value, entry, 0, x, y); + if (j < data.getXValCount()) c.drawText(data.getXVals().get(j), x, y + lineHeight, mValuePaint); @@ -228,7 +232,7 @@ public void drawValues(Canvas c) { c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); } else if (!drawXVals && drawYVals) { - c.drawText(val, x, y + lineHeight / 2f, mValuePaint); + drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f); } cnt++; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 57c68ce410..04a6893729 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -22,11 +22,13 @@ public class RadarChartRenderer extends LineScatterCandleRadarRenderer { protected RadarChart mChart; - /** paint for drawing the web */ + /** + * paint for drawing the web + */ protected Paint mWebPaint; public RadarChartRenderer(RadarChart chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -46,9 +48,9 @@ public Paint getWebPaint() { @Override public void initBuffers() { // TODO Auto-generated method stub - + } - + @Override public void drawData(Canvas c) { @@ -141,13 +143,12 @@ public void drawValues(Canvas c) { for (int j = 0; j < entries.size(); j++) { - Entry e = entries.get(j); + Entry entry = entries.get(j); - PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, + PointF p = Utils.getPosition(center, (entry.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); - c.drawText(dataSet.getValueFormatter().getFormattedValue(e.getVal()), - p.x, p.y - yoffset, mValuePaint); + drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, p.x, p.y - yoffset); } } } @@ -235,7 +236,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { PointF p = Utils.getPosition(center, y * factor, sliceangle * j + mChart.getRotationAngle()); - float[] pts = new float[] { + float[] pts = new float[]{ p.x, p.y }; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index d236531639..a51c2aad91 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -233,11 +233,10 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; - float val = entries.get(j / 2).getVal(); + Entry entry = entries.get(j / 2); - c.drawText(dataSet.getValueFormatter().getFormattedValue(val), positions[j], - positions[j + 1] - shapeSize, - mValuePaint); + drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, positions[j], + positions[j + 1] - shapeSize); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 1d1684a72d..1f1c0d26fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -156,7 +156,7 @@ protected void drawLabels(Canvas c, float pos) { } protected void drawLabel(Canvas c, String label, int xIndex, float x, float y) { - String formattedLabel = mXAxis.getXValueFormatter().getXValue(label, xIndex, mViewPortHandler); + String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex, mViewPortHandler); c.drawText(formattedLabel, x, y, mAxisLabelPaint); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java deleted file mode 100644 index b69b3e9ba9..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/utils/PercentFormatter.java +++ /dev/null @@ -1,24 +0,0 @@ - -package com.github.mikephil.charting.utils; - -import java.text.DecimalFormat; - -/** - * This ValueFormatter is just for convenience and simply puts a "%" sign after - * each value. (Recommeded for PieChart) - * - * @author Philipp Jahoda - */ -public class PercentFormatter implements ValueFormatter { - - protected DecimalFormat mFormat; - - public PercentFormatter() { - mFormat = new DecimalFormat("###,###,##0.0"); - } - - @Override - public String getFormattedValue(float value) { - return mFormat.format(value) + " %"; - } -} diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java deleted file mode 100644 index 70f19472ac..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ValueFormatter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.github.mikephil.charting.utils; - -/** - * Interface that allows custom formatting of all values and value-labels - * displayed inside the chart. Simply create your own formatting class and let - * it implement ValueFormatter. Then override the getFormattedLabel(...) method - * and return whatever you want. - * - * @author Philipp Jahoda - */ -public interface ValueFormatter { - - /** - * Called when a value (from labels, or inside the chart) is formatted - * before being drawn. For performance reasons, avoid excessive calculations - * and memory allocations inside this method. - * - * @param value the value to be formatted - * @return the formatted label ready for being drawn - */ - String getFormattedValue(float value); -} From eb042930278b148f049fbd0729ef1792605ecbca Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 20 Sep 2015 11:08:44 +0200 Subject: [PATCH 0490/1390] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a2ed9d8484..93b30ac2a5 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.3' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.4' } ``` @@ -157,7 +157,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.3 + v2.1.4 ``` From 6ae1eefc40e446973a2734dd182a8051c7c3c43e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 20 Sep 2015 11:18:33 +0200 Subject: [PATCH 0491/1390] Fixed typo in classname --- .../src/com/github/mikephil/charting/components/XAxis.java | 6 +++--- .../src/com/github/mikephil/charting/data/CombinedData.java | 2 +- ...sValueFormatter.java => DefaultXAxisValueFormatter.java} | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/formatter/{DefaultXAxisAxisValueFormatter.java => DefaultXAxisValueFormatter.java} (85%) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 3db471710f..40172a5999 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.components; -import com.github.mikephil.charting.formatter.DefaultXAxisAxisValueFormatter; +import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; import com.github.mikephil.charting.formatter.XAxisValueFormatter; import java.util.ArrayList; @@ -66,7 +66,7 @@ public class XAxis extends AxisBase { /** * Custom formatter for adjusting x-value strings */ - protected XAxisValueFormatter mXAxisValueFormatter = new DefaultXAxisAxisValueFormatter(); + protected XAxisValueFormatter mXAxisValueFormatter = new DefaultXAxisValueFormatter(); /** the position of the x-labels relative to the chart */ private XAxisPosition mPosition = XAxisPosition.TOP; @@ -199,7 +199,7 @@ public List getValues() { */ public void setValueFormatter(XAxisValueFormatter formatter) { if(formatter == null) - mXAxisValueFormatter = new DefaultXAxisAxisValueFormatter(); + mXAxisValueFormatter = new DefaultXAxisValueFormatter(); else mXAxisValueFormatter = formatter; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 019c81df96..62374172b7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -86,7 +86,7 @@ public CandleData getCandleData() { */ public List getAllData() { - List data = new ArrayList<>(); + List data = new ArrayList(); if(mLineData != null) data.add(mLineData); if(mBarData != null) diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java similarity index 85% rename from MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java rename to MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java index 4a30df6ff8..383e195322 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisAxisValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultXAxisValueFormatter.java @@ -7,7 +7,7 @@ * Default formatter class for adjusting x-values before drawing them. * This simply returns the original value unmodified. */ -public class DefaultXAxisAxisValueFormatter implements XAxisValueFormatter { +public class DefaultXAxisValueFormatter implements XAxisValueFormatter { @Override public String getXValue(String original, int index, ViewPortHandler viewPortHandler) { From c51f00e2a4282c1eb8405885da3590ee4046b2fb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 24 Sep 2015 12:21:46 +0200 Subject: [PATCH 0492/1390] Allow custom Typeface for LimitLine (#1044). --- .../mpchartexample/LineChartActivity1.java | 5 + .../charting/components/ComponentBase.java | 52 +- .../charting/components/LimitLine.java | 22 + .../charting/renderer/YAxisRenderer.java | 460 +++++++++--------- .../YAxisRendererHorizontalBarChart.java | 1 + 5 files changed, 289 insertions(+), 251 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 2831c89716..281fcd06f4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -2,6 +2,7 @@ package com.xxmassdeveloper.mpchartexample; import android.graphics.Color; +import android.graphics.Typeface; import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -106,17 +107,21 @@ protected void onCreate(Bundle savedInstanceState) { //xAxis.setValueFormatter(new MyCustomXAxisValueFormatter()); //xAxis.addLimitLine(llXAxis); // add x-axis limit line + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); ll1.enableDashedLine(10f, 10f, 0f); ll1.setLabelPosition(LimitLabelPosition.RIGHT_TOP); ll1.setTextSize(10f); + ll1.setTypeface(tf); LimitLine ll2 = new LimitLine(-30f, "Lower Limit"); ll2.setLineWidth(4f); ll2.enableDashedLine(10f, 10f, 0f); ll2.setLabelPosition(LimitLabelPosition.RIGHT_BOTTOM); ll2.setTextSize(10f); + ll2.setTypeface(tf); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 0574d3c2c9..51841eabdf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -8,27 +8,39 @@ /** * This class encapsulates everything both Axis and Legend have in common. - * + * * @author Philipp Jahoda */ public abstract class ComponentBase { - /** flag that indicates if this axis / legend is enabled or not */ + /** + * flag that indicates if this axis / legend is enabled or not + */ protected boolean mEnabled = true; - /** the offset in pixels this axis labels have on the x-axis */ + /** + * the offset in pixels this axis labels have on the x-axis + */ protected float mXOffset = 5f; - /** the offset in pixels this axis labels have on the Y-axis */ + /** + * the offset in pixels this axis labels have on the Y-axis + */ protected float mYOffset = 5f; - /** the typeface used for the labels */ + /** + * the typeface used for the labels + */ protected Typeface mTypeface = null; - /** the text size of the labels */ + /** + * the text size of the labels + */ protected float mTextSize = 10f; - /** the text color to use for the labels */ + /** + * the text color to use for the labels + */ protected int mTextColor = Color.BLACK; public ComponentBase() { @@ -38,7 +50,7 @@ public ComponentBase() { /** * Returns the used offset on the x-axis for drawing the axis or legend * labels. This offset is applied before and after the label. - * + * * @return */ public float getXOffset() { @@ -47,7 +59,7 @@ public float getXOffset() { /** * Sets the used x-axis offset for the labels on this axis. - * + * * @param xOffset */ public void setXOffset(float xOffset) { @@ -57,7 +69,7 @@ public void setXOffset(float xOffset) { /** * Returns the used offset on the x-axis for drawing the axis labels. This * offset is applied before and after the label. - * + * * @return */ public float getYOffset() { @@ -68,8 +80,8 @@ public float getYOffset() { * Sets the used y-axis offset for the labels on this axis. For the legend, * higher offset means the legend as a whole will be placed further away * from the top. - * - * @param xOffset + * + * @param yOffset */ public void setYOffset(float yOffset) { mYOffset = Utils.convertDpToPixel(yOffset); @@ -77,7 +89,7 @@ public void setYOffset(float yOffset) { /** * returns the Typeface used for the labels, returns null if none is set - * + * * @return */ public Typeface getTypeface() { @@ -86,7 +98,7 @@ public Typeface getTypeface() { /** * sets a specific Typeface for the labels - * + * * @param tf */ public void setTypeface(Typeface tf) { @@ -96,7 +108,7 @@ public void setTypeface(Typeface tf) { /** * sets the size of the label text in pixels min = 6f, max = 24f, default * 10f - * + * * @param size */ public void setTextSize(float size) { @@ -111,7 +123,7 @@ public void setTextSize(float size) { /** * returns the text size that is currently set for the labels - * + * * @return */ public float getTextSize() { @@ -121,7 +133,7 @@ public float getTextSize() { /** * Sets the text color to use for the labels. Make sure to use * getResources().getColor(...) when using a color from the resources. - * + * * @param color */ public void setTextColor(int color) { @@ -130,7 +142,7 @@ public void setTextColor(int color) { /** * Returns the text color that is set for the labels. - * + * * @return */ public int getTextColor() { @@ -141,7 +153,7 @@ public int getTextColor() { * Set this to true if this component should be enabled (should be drawn), * false if not. If disabled, nothing of this component will be drawn. * Default: true - * + * * @param enabled */ public void setEnabled(boolean enabled) { @@ -150,7 +162,7 @@ public void setEnabled(boolean enabled) { /** * Returns true if this comonent is enabled (should be drawn), false if not. - * + * * @return */ public boolean isEnabled() { diff --git a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java index f7bd8e5a05..606fce97bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java @@ -4,6 +4,7 @@ import android.graphics.Color; import android.graphics.DashPathEffect; import android.graphics.Paint; +import android.graphics.Typeface; import com.github.mikephil.charting.utils.Utils; @@ -37,6 +38,9 @@ public class LimitLine { /** label string that is drawn next to the limit line */ private String mLabel = ""; + /** the typeface used for the labels */ + private Typeface mTypeface = null; + /** the path effect of this LimitLine that makes dashed lines possible */ private DashPathEffect mDashPathEffect = null; @@ -253,4 +257,22 @@ public void setTextSize(float size) { public float getTextSize() { return mTextSize; } + + /** + * returns the Typeface used for the limitline label, returns null if none is set + * + * @return + */ + public Typeface getTypeface() { + return mTypeface; + } + + /** + * Sets a specific Typeface to be used for the limitline label + * + * @param tf + */ + public void setTypeface(Typeface tf) { + mTypeface = tf; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 9fda5280ea..874740ace5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -7,7 +7,6 @@ import android.graphics.Path; import com.github.mikephil.charting.components.LimitLine; -import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.components.YAxis.YAxisLabelPosition; @@ -20,66 +19,64 @@ public class YAxisRenderer extends AxisRenderer { - protected YAxis mYAxis; + protected YAxis mYAxis; - public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { - super(viewPortHandler, trans); + public YAxisRenderer(ViewPortHandler viewPortHandler, YAxis yAxis, Transformer trans) { + super(viewPortHandler, trans); - this.mYAxis = yAxis; + this.mYAxis = yAxis; - mAxisLabelPaint.setColor(Color.BLACK); - mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); - } + mAxisLabelPaint.setColor(Color.BLACK); + mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); + } - /** - * Computes the axis values. - * - * @param yMin - * - the minimum y-value in the data object for this axis - * @param yMax - * - the maximum y-value in the data object for this axis - */ - public void computeAxis(float yMin, float yMax) { + /** + * Computes the axis values. + * + * @param yMin - the minimum y-value in the data object for this axis + * @param yMax - the maximum y-value in the data object for this axis + */ + public void computeAxis(float yMin, float yMax) { - // calculate the starting and entry point of the y-labels (depending on - // zoom / contentrect bounds) - if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { + // calculate the starting and entry point of the y-labels (depending on + // zoom / contentrect bounds) + if (mViewPortHandler.contentWidth() > 10 && !mViewPortHandler.isFullyZoomedOutY()) { - PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); - PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); + PointD p1 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop()); + PointD p2 = mTrans.getValuesByTouchPoint(mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom()); - if (!mYAxis.isInverted()) { - yMin = (float) p2.y; - yMax = (float) p1.y; - } else { + if (!mYAxis.isInverted()) { + yMin = (float) p2.y; + yMax = (float) p1.y; + } else { - yMin = (float) p1.y; - yMax = (float) p2.y; - } - } + yMin = (float) p1.y; + yMax = (float) p2.y; + } + } - computeAxisValues(yMin, yMax); - } + computeAxisValues(yMin, yMax); + } - /** - * Sets up the y-axis labels. Computes the desired number of labels between the two given extremes. Unlike the - * papareXLabels() method, this method needs to be called upon every refresh of the view. - * - * @return - */ - protected void computeAxisValues(float min, float max) { + /** + * Sets up the y-axis labels. Computes the desired number of labels between the two given extremes. Unlike the + * papareXLabels() method, this method needs to be called upon every refresh of the view. + * + * @return + */ + protected void computeAxisValues(float min, float max) { - float yMin = min; - float yMax = max; + float yMin = min; + float yMax = max; - int labelCount = mYAxis.getLabelCount(); - double range = Math.abs(yMax - yMin); + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); - if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[] {}; - mYAxis.mEntryCount = 0; - return; - } + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[]{}; + mYAxis.mEntryCount = 0; + return; + } double rawInterval = range / labelCount; double interval = Utils.roundToNextSignificant(rawInterval); @@ -92,9 +89,9 @@ protected void computeAxisValues(float min, float max) { } // force label count - if (mYAxis.isForceLabelsEnabled()) { + if (mYAxis.isForceLabelsEnabled()) { - float step = (float) range / (float) (labelCount-1); + float step = (float) range / (float) (labelCount - 1); mYAxis.mEntryCount = labelCount; if (mYAxis.mEntries.length < labelCount) { @@ -104,46 +101,46 @@ protected void computeAxisValues(float min, float max) { float v = min; - for(int i = 0; i < labelCount; i++) { + for (int i = 0; i < labelCount; i++) { mYAxis.mEntries[i] = v; v += step; } // no forced count - } else { + } else { - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; - } else { + } else { - double first = Math.ceil(yMin / interval) * interval; - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + double first = Math.ceil(yMin / interval) * interval; + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } - mYAxis.mEntryCount = n; + mYAxis.mEntryCount = n; - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } - for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; - } - } - } + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + } // set decimals if (interval < 1) { @@ -151,215 +148,216 @@ protected void computeAxisValues(float min, float max) { } else { mYAxis.mDecimals = 0; } - } + } - /** - * draws the y-axis labels to the screen - */ - @Override - public void renderAxisLabels(Canvas c) { + /** + * draws the y-axis labels to the screen + */ + @Override + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) + return; - float[] positions = new float[mYAxis.mEntryCount * 2]; + float[] positions = new float[mYAxis.mEntryCount * 2]; - for (int i = 0; i < positions.length; i += 2) { - // only fill y values, x values are not needed since the y-labels - // are - // static on the x-axis - positions[i + 1] = mYAxis.mEntries[i / 2]; - } + for (int i = 0; i < positions.length; i += 2) { + // only fill y values, x values are not needed since the y-labels + // are + // static on the x-axis + positions[i + 1] = mYAxis.mEntries[i / 2]; + } - mTrans.pointValuesToPixel(positions); + mTrans.pointValuesToPixel(positions); - mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); - mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setColor(mYAxis.getTextColor()); + mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); + mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setColor(mYAxis.getTextColor()); - float xoffset = mYAxis.getXOffset(); - float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f + mYAxis.getYOffset(); + float xoffset = mYAxis.getXOffset(); + float yoffset = Utils.calcTextHeight(mAxisLabelPaint, "A") / 2.5f + mYAxis.getYOffset(); - AxisDependency dependency = mYAxis.getAxisDependency(); - YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); + AxisDependency dependency = mYAxis.getAxisDependency(); + YAxisLabelPosition labelPosition = mYAxis.getLabelPosition(); - float xPos = 0f; + float xPos = 0f; - if (dependency == AxisDependency.LEFT) { + if (dependency == AxisDependency.LEFT) { - if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - xPos = mViewPortHandler.offsetLeft() - xoffset; - } else { - mAxisLabelPaint.setTextAlign(Align.LEFT); - xPos = mViewPortHandler.offsetLeft() + xoffset; - } + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { + mAxisLabelPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.offsetLeft() - xoffset; + } else { + mAxisLabelPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.offsetLeft() + xoffset; + } - } else { + } else { - if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { - mAxisLabelPaint.setTextAlign(Align.LEFT); - xPos = mViewPortHandler.contentRight() + xoffset; - } else { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - xPos = mViewPortHandler.contentRight() - xoffset; - } - } + if (labelPosition == YAxisLabelPosition.OUTSIDE_CHART) { + mAxisLabelPaint.setTextAlign(Align.LEFT); + xPos = mViewPortHandler.contentRight() + xoffset; + } else { + mAxisLabelPaint.setTextAlign(Align.RIGHT); + xPos = mViewPortHandler.contentRight() - xoffset; + } + } - drawYLabels(c, xPos, positions, yoffset); - } + drawYLabels(c, xPos, positions, yoffset); + } - @Override - public void renderAxisLine(Canvas c) { + @Override + public void renderAxisLine(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawAxisLineEnabled()) + return; - mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); - mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); + mAxisLinePaint.setColor(mYAxis.getAxisLineColor()); + mAxisLinePaint.setStrokeWidth(mYAxis.getAxisLineWidth()); - if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { - c.drawLine(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), - mViewPortHandler.contentBottom(), mAxisLinePaint); - } else { - c.drawLine(mViewPortHandler.contentRight(), mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), - mViewPortHandler.contentBottom(), mAxisLinePaint); - } - } + if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { + c.drawLine(mViewPortHandler.contentLeft(), mViewPortHandler.contentTop(), mViewPortHandler.contentLeft(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } else { + c.drawLine(mViewPortHandler.contentRight(), mViewPortHandler.contentTop(), mViewPortHandler.contentRight(), + mViewPortHandler.contentBottom(), mAxisLinePaint); + } + } - /** - * draws the y-labels on the specified x-position - * - * @param fixedPosition - * @param positions - */ - protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { + /** + * draws the y-labels on the specified x-position + * + * @param fixedPosition + * @param positions + */ + protected void drawYLabels(Canvas c, float fixedPosition, float[] positions, float offset) { - // draw - for (int i = 0; i < mYAxis.mEntryCount; i++) { + // draw + for (int i = 0; i < mYAxis.mEntryCount; i++) { - String text = mYAxis.getFormattedLabel(i); + String text = mYAxis.getFormattedLabel(i); - if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) - return; + if (!mYAxis.isDrawTopYLabelEntryEnabled() && i >= mYAxis.mEntryCount - 1) + return; - c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); - } - } + c.drawText(text, fixedPosition, positions[i * 2 + 1] + offset, mAxisLabelPaint); + } + } - @Override - public void renderGridLines(Canvas c) { + @Override + public void renderGridLines(Canvas c) { - if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) - return; + if (!mYAxis.isDrawGridLinesEnabled() || !mYAxis.isEnabled()) + return; - // pre alloc - float[] position = new float[2]; + // pre alloc + float[] position = new float[2]; - mGridPaint.setColor(mYAxis.getGridColor()); - mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); - mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); + mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); + mGridPaint.setPathEffect(mYAxis.getGridDashPathEffect()); - Path gridLinePath = new Path(); + Path gridLinePath = new Path(); - // draw the horizontal grid - for (int i = 0; i < mYAxis.mEntryCount; i++) { + // draw the horizontal grid + for (int i = 0; i < mYAxis.mEntryCount; i++) { - position[1] = mYAxis.mEntries[i]; - mTrans.pointValuesToPixel(position); + position[1] = mYAxis.mEntries[i]; + mTrans.pointValuesToPixel(position); - gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); - gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); + gridLinePath.moveTo(mViewPortHandler.offsetLeft(), position[1]); + gridLinePath.lineTo(mViewPortHandler.contentRight(), position[1]); - // draw a path because lines don't support dashing on lower android versions - c.drawPath(gridLinePath, mGridPaint); + // draw a path because lines don't support dashing on lower android versions + c.drawPath(gridLinePath, mGridPaint); - gridLinePath.reset(); - } - } + gridLinePath.reset(); + } + } - /** - * Draws the LimitLines associated with this axis to the screen. - * - * @param c - */ - @Override - public void renderLimitLines(Canvas c) { + /** + * Draws the LimitLines associated with this axis to the screen. + * + * @param c + */ + @Override + public void renderLimitLines(Canvas c) { - List limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); - if (limitLines == null || limitLines.size() <= 0) - return; + if (limitLines == null || limitLines.size() <= 0) + return; - float[] pts = new float[2]; - Path limitLinePath = new Path(); + float[] pts = new float[2]; + Path limitLinePath = new Path(); - for (int i = 0; i < limitLines.size(); i++) { + for (int i = 0; i < limitLines.size(); i++) { - LimitLine l = limitLines.get(i); + LimitLine l = limitLines.get(i); - mLimitLinePaint.setStyle(Paint.Style.STROKE); - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - pts[1] = l.getLimit(); + pts[1] = l.getLimit(); - mTrans.pointValuesToPixel(pts); + mTrans.pointValuesToPixel(pts); - limitLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); - limitLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); + limitLinePath.moveTo(mViewPortHandler.contentLeft(), pts[1]); + limitLinePath.lineTo(mViewPortHandler.contentRight(), pts[1]); - c.drawPath(limitLinePath, mLimitLinePaint); - limitLinePath.reset(); - // c.drawLines(pts, mLimitLinePaint); + c.drawPath(limitLinePath, mLimitLinePaint); + limitLinePath.reset(); + // c.drawLines(pts, mLimitLinePaint); - String label = l.getLabel(); + String label = l.getLabel(); - // if drawing the limit-value label is enabled - if (label != null && !label.equals("")) { + // if drawing the limit-value label is enabled + if (label != null && !label.equals("")) { - mLimitLinePaint.setStyle(l.getTextStyle()); - mLimitLinePaint.setPathEffect(null); - mLimitLinePaint.setColor(l.getTextColor()); - mLimitLinePaint.setStrokeWidth(0.5f); - mLimitLinePaint.setTextSize(l.getTextSize()); + mLimitLinePaint.setStyle(l.getTextStyle()); + mLimitLinePaint.setPathEffect(null); + mLimitLinePaint.setColor(l.getTextColor()); + mLimitLinePaint.setTypeface(l.getTypeface()); + mLimitLinePaint.setStrokeWidth(0.5f); + mLimitLinePaint.setTextSize(l.getTextSize()); - final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + labelLineHeight; + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + float xOffset = Utils.convertDpToPixel(4f); + float yOffset = l.getLineWidth() + labelLineHeight; - final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + final LimitLine.LimitLabelPosition position = l.getLabelPosition(); - if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { + if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { - mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, - mViewPortHandler.contentRight() - xOffset, - pts[1] - yOffset + labelLineHeight, mLimitLinePaint); + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); - } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { - mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, - mViewPortHandler.contentRight() - xOffset, - pts[1] + yOffset, mLimitLinePaint); + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, + mViewPortHandler.contentRight() - xOffset, + pts[1] + yOffset, mLimitLinePaint); - } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { - mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, - mViewPortHandler.contentLeft() + xOffset, - pts[1] - yOffset + labelLineHeight, mLimitLinePaint); + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, + mViewPortHandler.contentLeft() + xOffset, + pts[1] - yOffset + labelLineHeight, mLimitLinePaint); - } else { + } else { - mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, - mViewPortHandler.offsetLeft() + xOffset, - pts[1] + yOffset, mLimitLinePaint); - } - } - } - } + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, + mViewPortHandler.offsetLeft() + xOffset, + pts[1] + yOffset, mLimitLinePaint); + } + } + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index c23656e4af..216f545571 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -225,6 +225,7 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setStyle(l.getTextStyle()); mLimitLinePaint.setPathEffect(null); mLimitLinePaint.setColor(l.getTextColor()); + mLimitLinePaint.setTypeface(l.getTypeface()); mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); From f11cd2caf848582703f58bf98659403b4a544e43 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 25 Sep 2015 23:20:48 +0200 Subject: [PATCH 0493/1390] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 93b30ac2a5..a89f23a38d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -[![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) +[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart)[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) Remember: *It's all about the looks.* From 5effa1ed54b3e9c0ae3b66d1beec60c767ecd6ba Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 25 Sep 2015 23:21:14 +0200 Subject: [PATCH 0494/1390] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a89f23a38d..21135e5a8e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ [![Twitter](https://img.shields.io/badge/Twitter-@PhilippJahoda-blue.svg?style=flat)](http://twitter.com/philippjahoda) -[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart)[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) +[![Twitter](https://img.shields.io/badge/Twitter-@mpandroidchart-blue.svg?style=flat)](http://twitter.com/mpandroidchart) +[![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-orange.svg?style=flat)](http://android-arsenal.com/details/1/741) +[![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) Remember: *It's all about the looks.* From 48619deabb2e9d84d2a5052e4bed6340803e6e18 Mon Sep 17 00:00:00 2001 From: AngelOfMors Date: Wed, 30 Sep 2015 13:59:41 +0600 Subject: [PATCH 0495/1390] Added in function formatNumber new param: separateChar. Corrected params in Log.e --- .../github/mikephil/charting/utils/Utils.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index f5ea05a052..c8345f8ec6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -37,7 +37,7 @@ public abstract class Utils { /** * initialize method, called inside the Chart.init() method. * - * @param res + * @param context */ @SuppressWarnings("deprecation") public static void init(Context context) { @@ -48,7 +48,8 @@ public static void init(Context context) { // noinspection deprecation mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); - Log.e("MPAndroidChart, Utils.init(...)", "PROVIDED CONTEXT OBJECT IS NULL"); + Log.e("MPChartLib-Utils" + ,"Utils.init(...) PROVIDED CONTEXT OBJECT IS NULL"); } else { ViewConfiguration viewConfiguration = ViewConfiguration.get(context); @@ -225,7 +226,7 @@ public static FSize calcTextSize(Paint paint, String demoText) { /** * returns the appropriate number of format digits for a legend value * - * @param delta + * @param step * @param bonus - additional digits * @return */ @@ -256,16 +257,30 @@ public static int getLegendFormatDigits(float step, int bonus) { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + /** + * Formats the given number to the given number of decimals, and returns the + * number as a string, maximum 35 characters. + * + * @param number + * @param digitCount + * @param separateThousands set this to true to separate thousands values + * @return + */ + public static String formatNumber(float number, int digitCount, boolean separateThousands) { + return formatNumber(number, digitCount, separateThousands, '.'); + } + /** * Formats the given number to the given number of decimals, and returns the * number as a string, maximum 35 characters. * * @param number * @param digitCount - * @param separateTousands set this to true to separate thousands values + * @param separateThousands set this to true to separate thousands values + * @param separateChar * @return */ - public static String formatNumber(float number, int digitCount, boolean separateThousands) { + public static String formatNumber(float number, int digitCount, boolean separateThousands, char separateChar) { char[] out = new char[35]; @@ -312,14 +327,14 @@ public static String formatNumber(float number, int digitCount, boolean separate if (decimalPointAdded) { if ((charCount - digitCount) % 4 == 0) { - out[ind--] = '.'; + out[ind--] = separateChar; charCount++; } } else { if ((charCount - digitCount) % 4 == 3) { - out[ind--] = '.'; + out[ind--] = separateChar; charCount++; } } @@ -391,7 +406,7 @@ public static int[] convertIntegers(List integers) { /** * Converts the provided String List to a String array. * - * @param labels + * @param strings * @return */ public static String[] convertStrings(List strings) { From 507a75c006c5a71bf0ff348f63d77f5bcd7b39f6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 30 Sep 2015 12:49:49 +0200 Subject: [PATCH 0496/1390] Add possibility to remove first and last Entry from DataSet. --- .../RealtimeLineChartActivity.java | 3 +- .../mikephil/charting/data/DataSet.java | 199 ++++++++++++------ 2 files changed, 140 insertions(+), 62 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index b1dc9320d3..286bd4182b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -83,7 +83,7 @@ protected void onCreate(Bundle savedInstanceState) { xl.setDrawGridLines(false); xl.setAvoidFirstLastClipping(true); xl.setSpaceBetweenLabels(5); - xl.setEnabled(false); + xl.setEnabled(true); YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); @@ -146,6 +146,7 @@ private void addEntry() { + (year + data.getXValCount() / 12)); data.addEntry(new Entry((float) (Math.random() * 40) + 30f, set.getEntryCount()), 0); + // let the chart know it's data has changed mChart.notifyDataSetChanged(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index c3fff6cafc..a90562b5ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -19,64 +19,96 @@ * Chart that belong together. It is designed to logically separate different * groups of values inside the Chart (e.g. the values for a specific line in the * LineChart, or the values of a specific group of bars in the BarChart). - * + * * @author Philipp Jahoda */ public abstract class DataSet { - /** List representing all colors that are used for this DataSet */ + /** + * List representing all colors that are used for this DataSet + */ protected List mColors = null; - /** the entries that this dataset represents / holds together */ + /** + * the entries that this dataset represents / holds together + */ protected List mYVals = null; - /** maximum y-value in the y-value array */ + /** + * maximum y-value in the y-value array + */ protected float mYMax = 0.0f; - /** the minimum y-value in the y-value array */ + /** + * the minimum y-value in the y-value array + */ protected float mYMin = 0.0f; - /** the total sum of all y-values */ + /** + * the total sum of all y-values + */ private float mYValueSum = 0f; - /** the last start value used for calcMinMax */ + /** + * the last start value used for calcMinMax + */ protected int mLastStart = 0; - /** the last end value used for calcMinMax */ + /** + * the last end value used for calcMinMax + */ protected int mLastEnd = 0; - /** label that describes the DataSet or the data the DataSet represents */ + /** + * label that describes the DataSet or the data the DataSet represents + */ private String mLabel = "DataSet"; - /** flag that indicates if the DataSet is visible or not */ + /** + * flag that indicates if the DataSet is visible or not + */ private boolean mVisible = true; - /** if true, y-values are drawn on the chart */ + /** + * if true, y-values are drawn on the chart + */ protected boolean mDrawValues = true; - /** the color used for the value-text */ + /** + * the color used for the value-text + */ private int mValueColor = Color.BLACK; - /** the size of the value-text labels */ + /** + * the size of the value-text labels + */ private float mValueTextSize = 17f; - /** the typeface used for the value text */ + /** + * the typeface used for the value text + */ private Typeface mValueTypeface; - /** custom formatter that is used instead of the auto-formatter if set */ + /** + * custom formatter that is used instead of the auto-formatter if set + */ protected transient ValueFormatter mValueFormatter; - /** this specifies which axis this DataSet should be plotted against */ + /** + * this specifies which axis this DataSet should be plotted against + */ protected AxisDependency mAxisDependency = AxisDependency.LEFT; - /** if true, value highlightning is enabled */ + /** + * if true, value highlightning is enabled + */ protected boolean mHighlightEnabled = true; /** * Creates a new DataSet object with the given values it represents. Also, a * label that describes the DataSet can be specified. The label can also be * used to retrieve the DataSet from a ChartData object. - * + * * @param yVals * @param label */ @@ -163,15 +195,16 @@ private void calcYValueSum() { /** * Returns the average value across all entries in this DataSet. + * * @return */ public float getAverage() { - return (float ) getYValueSum() / (float) getValueCount(); + return (float) getYValueSum() / (float) getValueCount(); } /** * returns the number of y-values this DataSet represents - * + * * @return */ public int getEntryCount() { @@ -183,7 +216,7 @@ public int getEntryCount() { * Float.NaN if no value is at the given x-index. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. - * + * * @param xIndex * @return */ @@ -203,7 +236,7 @@ public float getYValForXIndex(int xIndex) { * returns the index at the closest x-index. Returns null if no Entry object * at that index. INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. - * + * * @param x * @return */ @@ -256,7 +289,7 @@ public int getEntryIndex(int x) { * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical * situations. - * + * * @param x * @return */ @@ -276,15 +309,11 @@ public List getEntriesForXIndex(int x) { m--; high = mYVals.size(); - for (; m < high; m++) - { + for (; m < high; m++) { entry = mYVals.get(m); - if (entry.getXIndex() == x) - { + if (entry.getXIndex() == x) { entries.add(entry); - } - else - { + } else { break; } } @@ -301,7 +330,7 @@ public List getEntriesForXIndex(int x) { /** * returns the DataSets Entry array - * + * * @return */ public List getYVals() { @@ -310,7 +339,7 @@ public List getYVals() { /** * gets the sum of all y-values - * + * * @return */ public float getYValueSum() { @@ -319,7 +348,7 @@ public float getYValueSum() { /** * returns the minimum y-value this DataSet holds - * + * * @return */ public float getYMin() { @@ -328,7 +357,7 @@ public float getYMin() { /** * returns the maximum y-value this DataSet holds - * + * * @return */ public float getYMax() { @@ -337,7 +366,7 @@ public float getYMax() { /** * Returns the number of entries this DataSet holds. - * + * * @return */ public int getValueCount() { @@ -349,7 +378,7 @@ public int getValueCount() { * index in the Entry array of the DataSet. IMPORTANT: This method does * calculations at runtime, do not over-use in performance critical * situations. - * + * * @param xIndex * @return */ @@ -365,7 +394,7 @@ public int getIndexInEntries(int xIndex) { /** * Provides an exact copy of the DataSet this method is used on. - * + * * @return */ public abstract DataSet copy(); @@ -383,7 +412,7 @@ public String toString() { /** * Returns a simple string representation of the DataSet with the type and * the number of Entries. - * + * * @return */ public String toSimpleString() { @@ -413,7 +442,7 @@ public String getLabel() { /** * Set the visibility of this DataSet. If not visible, the DataSet will not * be drawn to the chart upon refreshing it. - * + * * @param visible */ public void setVisible(boolean visible) { @@ -423,7 +452,7 @@ public void setVisible(boolean visible) { /** * Returns true if this DataSet is visible inside the chart, or false if it * is currently hidden. - * + * * @return */ public boolean isVisible() { @@ -432,7 +461,7 @@ public boolean isVisible() { /** * Returns the axis this DataSet should be plotted against. - * + * * @return */ public AxisDependency getAxisDependency() { @@ -442,7 +471,7 @@ public AxisDependency getAxisDependency() { /** * Set the y-axis this DataSet should be plotted against (either LEFT or * RIGHT). Default: LEFT - * + * * @param dependency */ public void setAxisDependency(AxisDependency dependency) { @@ -537,8 +566,7 @@ public void addEntryOrdered(Entry e) { mYValueSum += val; - if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) - { + if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) { int closestIndex = getEntryIndex(e.getXIndex()); if (mYVals.get(closestIndex).getXIndex() < e.getXIndex()) closestIndex++; @@ -554,7 +582,7 @@ public void addEntryOrdered(Entry e) { * recalculate the current minimum and maximum values of the DataSet and the * value-sum. Returns true if an Entry was removed, false if no Entry could * be removed. - * + * * @param e */ public boolean removeEntry(T e) { @@ -579,7 +607,7 @@ public boolean removeEntry(T e) { /** * Removes the Entry object that has the given xIndex from the DataSet. * Returns true if an Entry was removed, false if no Entry could be removed. - * + * * @param xIndex */ public boolean removeEntry(int xIndex) { @@ -588,6 +616,55 @@ public boolean removeEntry(int xIndex) { return removeEntry(e); } + /** + * Removes the first Entry (at index 0) of this DataSet from the entries array. + * Returns true if successful, false if not. + * + * @return + */ + public boolean removeFirst() { + + T entry = mYVals.remove(0); + + boolean removed = entry != null; + + if (removed) { + + float val = entry.getVal(); + mYValueSum -= val; + + calcMinMax(mLastStart, mLastEnd); + } + + return removed; + } + + /** + * Removes the last Entry (at index size-1) of this DataSet from the entries array. + * Returns true if successful, false if not. + * + * @return + */ + public boolean removeLast() { + + if (mYVals.size() <= 0) + return false; + + T entry = mYVals.remove(mYVals.size() - 1); + + boolean removed = entry != null; + + if (removed) { + + float val = entry.getVal(); + mYValueSum -= val; + + calcMinMax(mLastStart, mLastEnd); + } + + return removed; + } + /** BELOW THIS COLOR HANDLING */ /** @@ -596,7 +673,7 @@ public boolean removeEntry(int xIndex) { * the size of the colors array. If you are using colors from the resources, * make sure that the colors are already prepared (by calling * getResources().getColor(...)) before adding them to the DataSet. - * + * * @param colors */ public void setColors(List colors) { @@ -609,7 +686,7 @@ public void setColors(List colors) { * the size of the colors array. If you are using colors from the resources, * make sure that the colors are already prepared (by calling * getResources().getColor(...)) before adding them to the DataSet. - * + * * @param colors */ public void setColors(int[] colors) { @@ -623,7 +700,7 @@ public void setColors(int[] colors) { * "new int[] { R.color.red, R.color.green, ... }" to provide colors for * this method. Internally, the colors are resolved using * getResources().getColor(...) - * + * * @param colors */ public void setColors(int[] colors, Context c) { @@ -639,7 +716,7 @@ public void setColors(int[] colors, Context c) { /** * Adds a new color to the colors array of the DataSet. - * + * * @param color */ public void addColor(int color) { @@ -651,7 +728,7 @@ public void addColor(int color) { /** * Sets the one and ONLY color that should be used for this DataSet. * Internally, this recreates the colors array and adds the specified color. - * + * * @param color */ public void setColor(int color) { @@ -661,7 +738,7 @@ public void setColor(int color) { /** * returns all the colors that are set for this DataSet - * + * * @return */ public List getColors() { @@ -671,7 +748,7 @@ public List getColors() { /** * Returns the color at the given index of the DataSet's color array. * Performs a IndexOutOfBounds check by modulus. - * + * * @param index * @return */ @@ -682,7 +759,7 @@ public int getColor(int index) { /** * Returns the first color (index 0) of the colors-array this DataSet * contains. - * + * * @return */ public int getColor() { @@ -718,7 +795,7 @@ public boolean isHighlightEnabled() { /** * Returns the position of the provided entry in the DataSets Entry array. * Returns -1 if doesn't exist. - * + * * @param e * @return */ @@ -763,7 +840,7 @@ public ValueFormatter getValueFormatter() { /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. - * + * * @return */ public boolean needsDefaultFormatter() { @@ -777,7 +854,7 @@ public boolean needsDefaultFormatter() { /** * Sets the color the value-labels of this DataSet should have. - * + * * @param color */ public void setValueTextColor(int color) { @@ -790,7 +867,7 @@ public int getValueTextColor() { /** * Sets a Typeface for the value-labels of this DataSet. - * + * * @param tf */ public void setValueTypeface(Typeface tf) { @@ -803,7 +880,7 @@ public Typeface getValueTypeface() { /** * Sets the text-size of the value-labels of this DataSet in dp. - * + * * @param size */ public void setValueTextSize(float size) { @@ -812,7 +889,7 @@ public void setValueTextSize(float size) { /** * Returns the text-size of the labels that are displayed above the values. - * + * * @return */ public float getValueTextSize() { @@ -823,7 +900,7 @@ public float getValueTextSize() { * Checks if this DataSet contains the specified Entry. Returns true if so, * false if not. NOTE: Performance is pretty bad on this one, do not * over-use in performance critical situations. - * + * * @param e * @return */ From e4a6764361a795e8db42873e73c9fad9602e4f23 Mon Sep 17 00:00:00 2001 From: AngelOfMors Date: Thu, 1 Oct 2015 10:57:48 +0600 Subject: [PATCH 0497/1390] Set custom Suffix for Large Value --- .../charting/utils/LargeValueFormatter.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java index 119c671588..ea90b04bba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/LargeValueFormatter.java @@ -19,6 +19,9 @@ public class LargeValueFormatter implements ValueFormatter { "", "k", "m", "b", "t" }; private static final int MAX_LENGTH = 4; + private static String[] customSUFFIX = null; + private static boolean useCustomSuffix = false; + private DecimalFormat mFormat; private String mText = ""; @@ -29,7 +32,7 @@ public LargeValueFormatter() { /** * Creates a formatter that appends a specified text to the result string - * @param text a text that will be appended + * @param appendix a text that will be appended */ public LargeValueFormatter(String appendix) { this(); @@ -41,6 +44,33 @@ public String getFormattedValue(float value) { return makePretty(value) + mText; } + /** + * Set custom Suffix for the language of the country + * @param suff new suffix + */ + public void setCustomSuffix(String[] suff) { + if (suff.length == 5) { + useCustomSuffix = true; + customSUFFIX = suff; + } + } + + /** + * Remove custom Suffix + */ + public void removeCustomSuffix() { + useCustomSuffix = false; + customSUFFIX = null; + } + + /** + * Check state for custom Suffix + * @return state + */ + public boolean isUseCustomSuffix(){ + return useCustomSuffix; + } + /** * Formats each number properly. Special thanks to Roman Gromov * (https://github.com/romangromov) for this piece of code. @@ -49,7 +79,8 @@ private String makePretty(double number) { String r = mFormat.format(number); - r = r.replaceAll("E[0-9]", SUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); + if (useCustomSuffix) r = r.replaceAll("E[0-9]", customSUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); + else r = r.replaceAll("E[0-9]", SUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); while (r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")) { r = r.substring(0, r.length() - 2) + r.substring(r.length() - 1); From ae10a9fdb54db056d90c28f408f7d5923d6c874c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 1 Oct 2015 15:55:06 +0300 Subject: [PATCH 0498/1390] Make skipWebLineCount consistent --- .../com/github/mikephil/charting/charts/RadarChart.java | 9 +++------ .../mikephil/charting/renderer/RadarChartRenderer.java | 4 +++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 961a0a0472..b77713b4db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -60,7 +60,7 @@ public class RadarChart extends PieRadarChartBase { /** * modulus that determines how many labels and web-lines are skipped before the next is drawn */ - private int mWebModulus = 1; + private int mSkipWebLineCount = 1; /** * the object reprsenting the y-axis labels @@ -358,10 +358,7 @@ public void setDrawWeb(boolean enabled) { */ public void setSkipWebLineCount(int count) { - if (count < 0) - count = 0; - - mWebModulus = count + 1; + mSkipWebLineCount = Math.max(0, count); } /** @@ -370,7 +367,7 @@ public void setSkipWebLineCount(int count) { * @return */ public int getSkipWebLineCount() { - return mWebModulus; + return mSkipWebLineCount; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 04a6893729..70e1c6bc55 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -174,7 +174,9 @@ protected void drawWeb(Canvas c) { mWebPaint.setColor(mChart.getWebColor()); mWebPaint.setAlpha(mChart.getWebAlpha()); - for (int i = 0; i < mChart.getData().getXValCount(); i += mChart.getSkipWebLineCount()) { + final int xIncrements = 1 + mChart.getSkipWebLineCount(); + + for (int i = 0; i < mChart.getData().getXValCount(); i += xIncrements) { PointF p = Utils.getPosition(center, mChart.getYRange() * factor, sliceangle * i + rotationangle); From c5c19d4f9197ce9348833b0aa70725fb7cc3d467 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 1 Oct 2015 16:13:40 +0300 Subject: [PATCH 0499/1390] Allow the minimum offset to be customized --- .../charting/charts/BarLineChartBase.java | 12 +++++++++--- .../charting/charts/HorizontalBarChart.java | 9 ++++++--- .../charting/charts/PieRadarChartBase.java | 15 +++++++++------ 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 1fc2ec2ea1..cf7fac5ef6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -88,6 +88,9 @@ public abstract class BarLineChartBase Date: Thu, 1 Oct 2015 17:27:37 +0300 Subject: [PATCH 0500/1390] Add support for a legend above the chart --- .../charting/charts/BarLineChartBase.java | 27 ++++++++++++------- .../charting/charts/HorizontalBarChart.java | 18 +++++++++++-- .../mikephil/charting/charts/PieChart.java | 2 +- .../charting/charts/PieRadarChartBase.java | 21 ++++++++++++--- .../mikephil/charting/charts/RadarChart.java | 2 +- .../mikephil/charting/components/Legend.java | 6 ++++- .../charting/renderer/LegendRenderer.java | 22 +++++++++++---- 7 files changed, 75 insertions(+), 23 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index cf7fac5ef6..70c54ca7e4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -439,19 +439,26 @@ public void calculateOffsets() { || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - float yOffset = mLegend.mTextHeightMax; // It's - // possible - // that we do - // not need - // this offset - // anymore as - // it is - // available - // through the - // extraOffsets + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = mLegend.mTextHeightMax; + offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { + + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = mLegend.mTextHeightMax; + + offsetTop += Math.min(mLegend.mNeededHeight + yOffset, + mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 9e52b3150d..021a5b8257 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -79,9 +79,23 @@ public void calculateOffsets() { || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - float yOffset = mLegend.mTextHeightMax * 2.f; // It's possible that we do not need this offset anymore - // as it is available through the extraOffsets + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = mLegend.mTextHeightMax * 2.f; + offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + + } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { + + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = mLegend.mTextHeightMax * 2.f; + + offsetTop += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 91511ed6c0..554d114236 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -420,7 +420,7 @@ public boolean isDrawCenterTextEnabled() { } @Override - protected float getRequiredBottomOffset() { + protected float getRequiredLegendOffset() { return mLegendRenderer.getLabelPaint().getTextSize() * 2.f; } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 925d32a4cd..1acc57aef9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -187,9 +187,24 @@ public void calculateOffsets() { || mLegend.getPosition() == LegendPosition.BELOW_CHART_RIGHT || mLegend.getPosition() == LegendPosition.BELOW_CHART_CENTER) { - float yOffset = getRequiredBottomOffset(); // It's possible that we do not need this offset anymore as it is available through the extraOffsets + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = getRequiredLegendOffset(); + legendBottom = Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + } else if (mLegend.getPosition() == LegendPosition.ABOVE_CHART_LEFT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_RIGHT + || mLegend.getPosition() == LegendPosition.ABOVE_CHART_CENTER) { + + // It's possible that we do not need this offset anymore as it + // is available through the extraOffsets, but changing it can mean + // changing default visibility for existing apps. + float yOffset = getRequiredLegendOffset(); + + legendTop = Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); + } legendLeft += getRequiredBaseOffset(); @@ -386,11 +401,11 @@ public float getDiameter() { public abstract float getRadius(); /** - * Returns the required bottom offset for the chart. + * Returns the required offset for the chart legend. * * @return */ - protected abstract float getRequiredBottomOffset(); + protected abstract float getRequiredLegendOffset(); /** * Returns the base offset needed for the chart without calculating the diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 961a0a0472..adcaabe635 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -374,7 +374,7 @@ public int getSkipWebLineCount() { } @Override - protected float getRequiredBottomOffset() { + protected float getRequiredLegendOffset() { return mLegendRenderer.getLabelPaint().getTextSize() * 4.f; } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 9ab2e724e8..9990abbe6b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -24,6 +24,7 @@ public enum LegendPosition { RIGHT_OF_CHART, RIGHT_OF_CHART_CENTER, RIGHT_OF_CHART_INSIDE, LEFT_OF_CHART, LEFT_OF_CHART_CENTER, LEFT_OF_CHART_INSIDE, BELOW_CHART_LEFT, BELOW_CHART_RIGHT, BELOW_CHART_CENTER, + ABOVE_CHART_LEFT, ABOVE_CHART_RIGHT, ABOVE_CHART_CENTER, PIECHART_CENTER } @@ -651,7 +652,10 @@ public void calculateDimensions(Paint labelpaint, ViewPortHandler viewPortHandle } else if (mPosition == LegendPosition.BELOW_CHART_LEFT || mPosition == LegendPosition.BELOW_CHART_RIGHT - || mPosition == LegendPosition.BELOW_CHART_CENTER) { + || mPosition == LegendPosition.BELOW_CHART_CENTER + || mPosition == LegendPosition.ABOVE_CHART_LEFT + || mPosition == LegendPosition.ABOVE_CHART_RIGHT + || mPosition == LegendPosition.ABOVE_CHART_CENTER) { int labelCount = mLabels.length; float labelLineHeight = Utils.getLineHeight(labelpaint); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index d9dfb50fdd..9d87300347 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -204,22 +204,27 @@ public void renderLegend(Canvas c) { switch (legendPosition) { case BELOW_CHART_LEFT: case BELOW_CHART_RIGHT: - case BELOW_CHART_CENTER: { + case BELOW_CHART_CENTER: + case ABOVE_CHART_LEFT: + case ABOVE_CHART_RIGHT: + case ABOVE_CHART_CENTER: { float contentWidth = mViewPortHandler.contentWidth(); float originPosX; - if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT) { + if (legendPosition == Legend.LegendPosition.BELOW_CHART_LEFT + || legendPosition == Legend.LegendPosition.ABOVE_CHART_LEFT) { originPosX = mViewPortHandler.contentLeft() + xoffset; if (direction == Legend.LegendDirection.RIGHT_TO_LEFT) originPosX += mLegend.mNeededWidth; - } else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT) { + } else if (legendPosition == Legend.LegendPosition.BELOW_CHART_RIGHT + || legendPosition == Legend.LegendPosition.ABOVE_CHART_RIGHT) { originPosX = mViewPortHandler.contentRight() - xoffset; if (direction == Legend.LegendDirection.LEFT_TO_RIGHT) originPosX -= mLegend.mNeededWidth; - } else // if (legendPosition == Legend.LegendPosition.BELOW_CHART_CENTER) + } else // BELOW_CHART_CENTER || ABOVE_CHART_CENTER originPosX = mViewPortHandler.contentLeft() + contentWidth / 2.f; FSize[] calculatedLineSizes = mLegend.getCalculatedLineSizes(); @@ -227,7 +232,14 @@ public void renderLegend(Canvas c) { Boolean[] calculatedLabelBreakPoints = mLegend.getCalculatedLabelBreakPoints(); posX = originPosX; - posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight; + + if (legendPosition == Legend.LegendPosition.ABOVE_CHART_LEFT || + legendPosition == Legend.LegendPosition.ABOVE_CHART_RIGHT || + legendPosition == Legend.LegendPosition.ABOVE_CHART_CENTER) { + posY = 0.f; + } else { + posY = mViewPortHandler.getChartHeight() - yoffset - mLegend.mNeededHeight; + } int lineIndex = 0; From 5b1b98fabc6af55a6447b332b63c197b3c3e0bf1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 1 Oct 2015 18:25:45 +0300 Subject: [PATCH 0501/1390] Avoid trying to draw cubic fill when there's no points More info: https://github.com/danielgindi/ios-charts/issues/419 --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 186b925d39..913ed47fba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -237,6 +237,9 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { protected void drawCubicFill(LineDataSet dataSet, Path spline, Transformer trans, int from, int to) { + if (to - from <= 1) + return; + float fillMin = dataSet.getFillFormatter() .getFillLinePosition(dataSet, mChart); From ade17f53288417f7c29e48224e0da4bcdbe8cdc6 Mon Sep 17 00:00:00 2001 From: AngelOfMors Date: Thu, 1 Oct 2015 23:16:16 +0600 Subject: [PATCH 0502/1390] Set custom Suffix for Large Value --- .../formatter/LargeValueFormatter.java | 30 +++---------------- 1 file changed, 4 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java index eab1b95860..3766baf0a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -19,14 +19,10 @@ */ public class LargeValueFormatter implements ValueFormatter, YAxisValueFormatter { - private static final String[] SUFFIX = new String[] { + private static String[] SUFFIX = new String[] { "", "k", "m", "b", "t" }; private static final int MAX_LENGTH = 4; - private static String[] customSUFFIX = null; - private static boolean useCustomSuffix = false; - - private DecimalFormat mFormat; private String mText = ""; @@ -59,29 +55,12 @@ public String getFormattedValue(float value, YAxis yAxis) { * Set custom Suffix for the language of the country * @param suff new suffix */ - public void setCustomSuffix(String[] suff) { + public void setSuffix(String[] suff) { if (suff.length == 5) { - useCustomSuffix = true; - customSUFFIX = suff; + SUFFIX = suff; } } - /** - * Remove custom Suffix - */ - public void removeCustomSuffix() { - useCustomSuffix = false; - customSUFFIX = null; - } - - /** - * Check state for custom Suffix - * @return state - */ - public boolean isUseCustomSuffix(){ - return useCustomSuffix; - } - /** * Formats each number properly. Special thanks to Roman Gromov * (https://github.com/romangromov) for this piece of code. @@ -90,8 +69,7 @@ private String makePretty(double number) { String r = mFormat.format(number); - if (useCustomSuffix) r = r.replaceAll("E[0-9]", customSUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); - else r = r.replaceAll("E[0-9]", SUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); + r = r.replaceAll("E[0-9]", SUFFIX[Character.getNumericValue(r.charAt(r.length() - 1)) / 3]); while (r.length() > MAX_LENGTH || r.matches("[0-9]+\\.[a-z]")) { r = r.substring(0, r.length() - 2) + r.substring(r.length() - 1); From 8bb5e1ad541ec85df2f1003ba08651a709249eec Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 2 Oct 2015 00:28:01 +0300 Subject: [PATCH 0503/1390] Fix highlight animation bug in stacked bar chart --- .../charting/renderer/BarChartRenderer.java | 4 +-- .../mikephil/charting/utils/Transformer.java | 25 +++++++++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 1f55d17d8c..ce6036a8c1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -346,7 +346,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (isStack) { y1 = h.getRange().from; - y2 = h.getRange().to * mAnimator.getPhaseY(); + y2 = h.getRange().to; } else { y1 = e.getVal(); y2 = 0.f; @@ -370,7 +370,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { final float arrowWidth = set.getBarSpace() / 2.f; final float arrowHeight = arrowWidth * xToYRel; - final float yArrow = y1 > -y2 ? y1 : y1; + final float yArrow = (y1 > -y2 ? y1 : y1) * mAnimator.getPhaseY(); Path arrow = new Path(); arrow.moveTo(x + 0.4f, yArrow + offsetY); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 978fa8684c..cf8f5b2c4c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -334,10 +334,21 @@ public void rectValueToPixel(RectF r) { public void rectValueToPixel(RectF r, float phaseY) { // multiply the height of the rect with the phase - if (r.top > 0) - r.top *= phaseY; - else - r.bottom *= phaseY; + r.top *= phaseY; + r.bottom *= phaseY; + + mMatrixValueToPx.mapRect(r); + mViewPortHandler.getMatrixTouch().mapRect(r); + mMatrixOffset.mapRect(r); + } + + /** + * Transform a rectangle with all matrices with potential animation phases. + * + * @param r + + */ + public void rectValueToPixelHorizontal(RectF r) { mMatrixValueToPx.mapRect(r); mViewPortHandler.getMatrixTouch().mapRect(r); @@ -353,10 +364,8 @@ public void rectValueToPixel(RectF r, float phaseY) { public void rectValueToPixelHorizontal(RectF r, float phaseY) { // multiply the height of the rect with the phase - if (r.left > 0) - r.left *= phaseY; - else - r.right *= phaseY; + r.left *= phaseY; + r.right *= phaseY; mMatrixValueToPx.mapRect(r); mViewPortHandler.getMatrixTouch().mapRect(r); From 89b864f9b2dda3a13df5a74ded4b0d27f0fcd980 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 4 Oct 2015 11:40:10 +0200 Subject: [PATCH 0504/1390] Code cleanup. --- .../formatter/LargeValueFormatter.java | 2 +- .../github/mikephil/charting/utils/Utils.java | 146 +++++------------- 2 files changed, 39 insertions(+), 109 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 3766baf0a1..5bd55edfd1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -52,7 +52,7 @@ public String getFormattedValue(float value, YAxis yAxis) { } /** - * Set custom Suffix for the language of the country + * Set custom suffix to be appended after the values * @param suff new suffix */ public void setSuffix(String[] suff) { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index c8345f8ec6..8f86e36d72 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -17,7 +17,6 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; -import java.text.DecimalFormat; import java.util.List; /** @@ -25,7 +24,7 @@ * calling Utils.init(...) before usage. Inside the Chart.init() method, this is * done, if the Utils are used before that, Utils.init(...) needs to be called * manually. - * + * * @author Philipp Jahoda */ public abstract class Utils { @@ -36,7 +35,7 @@ public abstract class Utils { /** * initialize method, called inside the Chart.init() method. - * + * * @param context */ @SuppressWarnings("deprecation") @@ -49,7 +48,7 @@ public static void init(Context context) { mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); Log.e("MPChartLib-Utils" - ,"Utils.init(...) PROVIDED CONTEXT OBJECT IS NULL"); + , "Utils.init(...) PROVIDED CONTEXT OBJECT IS NULL"); } else { ViewConfiguration viewConfiguration = ViewConfiguration.get(context); @@ -78,36 +77,14 @@ public static void init(Resources res) { mMaximumFlingVelocity = ViewConfiguration.getMaximumFlingVelocity(); } - /** - * format a number properly with the given number of digits - * - * @param number the number to format - * @param digits the number of digits - * @return - */ - public static String formatDecimal(double number, int digits) { - - StringBuffer a = new StringBuffer(); - for (int i = 0; i < digits; i++) { - if (i == 0) - a.append("."); - a.append("0"); - } - - DecimalFormat nf = new DecimalFormat("###,###,###,##0" + a.toString()); - String formatted = nf.format(number); - - return formatted; - } - /** * This method converts dp unit to equivalent pixels, depending on device * density. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. - * + * * @param dp A value in dp (density independent pixels) unit. Which we need - * to convert into pixels + * to convert into pixels * @return A float value to represent px equivalent to dp depending on - * device density + * device density */ public static float convertDpToPixel(float dp) { @@ -128,7 +105,7 @@ public static float convertDpToPixel(float dp) { /** * This method converts device specific pixels to density independent * pixels. NEEDS UTILS TO BE INITIALIZED BEFORE USAGE. - * + * * @param px A value in px (pixels) unit. Which we need to convert into db * @return A float value to represent dp equivalent to px value */ @@ -151,7 +128,7 @@ public static float convertPixelsToDp(float px) { /** * calculates the approximate width of a text, depending on a demo text * avoid repeated calls (e.g. inside drawing methods) - * + * * @param paint * @param demoText * @return @@ -200,55 +177,6 @@ public static FSize calcTextSize(Paint paint, String demoText) { return new FSize(r.width(), r.height()); } - // /** - // * returns the appropriate number of format digits for a delta value - // * - // * @param delta - // * @return - // */ - // public static int getFormatDigits(float delta) { - // - // if (delta < 0.1) { - // return 6; - // } else if (delta <= 1) { - // return 4; - // } else if (delta < 4) { - // return 3; - // } else if (delta < 20) { - // return 2; - // } else if (delta < 60) { - // return 1; - // } else { - // return 0; - // } - // } - - /** - * returns the appropriate number of format digits for a legend value - * - * @param step - * @param bonus - additional digits - * @return - */ - public static int getLegendFormatDigits(float step, int bonus) { - - if (step < 0.0000099) { - return 6 + bonus; - } else if (step < 0.000099) { - return 5 + bonus; - } else if (step < 0.00099) { - return 4 + bonus; - } else if (step < 0.0099) { - return 3 + bonus; - } else if (step < 0.099) { - return 2 + bonus; - } else if (step < 0.99) { - return 1 + bonus; - } else { - return 0 + bonus; - } - } - /** * Math.pow(...) is very expensive, so avoid calling it and create it * yourself. @@ -257,27 +185,27 @@ public static int getLegendFormatDigits(float step, int bonus) { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; - /** - * Formats the given number to the given number of decimals, and returns the - * number as a string, maximum 35 characters. - * - * @param number - * @param digitCount - * @param separateThousands set this to true to separate thousands values - * @return - */ - public static String formatNumber(float number, int digitCount, boolean separateThousands) { - return formatNumber(number, digitCount, separateThousands, '.'); - } + /** + * Formats the given number to the given number of decimals, and returns the + * number as a string, maximum 35 characters. If thousands are separated, the separating character is a dot ("."). + * + * @param number + * @param digitCount + * @param separateThousands set this to true to separate thousands values + * @return + */ + public static String formatNumber(float number, int digitCount, boolean separateThousands) { + return formatNumber(number, digitCount, separateThousands, '.'); + } /** * Formats the given number to the given number of decimals, and returns the * number as a string, maximum 35 characters. - * + * * @param number * @param digitCount * @param separateThousands set this to true to separate thousands values - * @param separateChar + * @param separateChar a caracter to be paced between the "thousands" * @return */ public static String formatNumber(float number, int digitCount, boolean separateThousands, char separateChar) { @@ -361,7 +289,7 @@ public static String formatNumber(float number, int digitCount, boolean separate /** * rounds the given number to the next significant number - * + * * @param number * @return */ @@ -376,7 +304,7 @@ public static float roundToNextSignificant(double number) { /** * Returns the appropriate number of decimals to be used for the provided * number. - * + * * @param number * @return */ @@ -388,7 +316,7 @@ public static int getDecimals(float number) { /** * Converts the provided Integer List to an int array. - * + * * @param integers * @return */ @@ -405,7 +333,7 @@ public static int[] convertIntegers(List integers) { /** * Converts the provided String List to a String array. - * + * * @param strings * @return */ @@ -423,7 +351,7 @@ public static String[] convertStrings(List strings) { /** * Replacement for the Math.nextUp(...) method that is only available in * HONEYCOMB and higher. Dat's some seeeeek sheeet. - * + * * @param d * @return */ @@ -440,12 +368,12 @@ public static double nextUp(double d) { /** * Returns the index of the DataSet that contains the closest value on the * y-axis. This is needed for highlighting. This will return -Integer.MAX_VALUE if failure. - * + * * @param valsAtIndex all the values at a specific index * @return */ public static int getClosestDataSetIndex(List valsAtIndex, float val, - AxisDependency axis) { + AxisDependency axis) { int index = -Integer.MAX_VALUE; float distance = Float.MAX_VALUE; @@ -470,14 +398,14 @@ public static int getClosestDataSetIndex(List valsAtIndex, floa /** * Returns the minimum distance from a touch-y-value (in pixels) to the * closest y-value (in pixels) that is displayed in the chart. - * + * * @param valsAtIndex * @param val * @param axis * @return */ public static float getMinimumDistance(List valsAtIndex, float val, - AxisDependency axis) { + AxisDependency axis) { float distance = Float.MAX_VALUE; @@ -487,7 +415,7 @@ public static float getMinimumDistance(List valsAtIndex, float if (sel.dataSet.getAxisDependency() == axis) { - float cdistance = Math.abs((float) sel.val - val); + float cdistance = Math.abs(sel.val - val); if (cdistance < distance) { distance = cdistance; } @@ -500,10 +428,10 @@ public static float getMinimumDistance(List valsAtIndex, float /** * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. - * + * * @param center * @param dist - * @param angle in degrees, converted to radians internally + * @param angle in degrees, converted to radians internally * @return */ public static PointF getPosition(PointF center, float dist, float angle) { @@ -514,7 +442,7 @@ public static PointF getPosition(PointF center, float dist, float angle) { } public static void velocityTrackerPointerUpCleanUpIfNecessary(MotionEvent ev, - VelocityTracker tracker) { + VelocityTracker tracker) { // Check the dot product of current velocities. // If the pointer that left was opposing another velocity vector, clear. @@ -561,7 +489,9 @@ public static int getMaximumFlingVelocity() { return mMaximumFlingVelocity; } - /** returns an angle between 0.f < 360.f (not less than zero, less than 360) */ + /** + * returns an angle between 0.f < 360.f (not less than zero, less than 360) + */ public static float getNormalizedAngle(float angle) { while (angle < 0.f) angle += 360.f; From f2e3e13a14bc87ff0e4ae466ac3ebd95a2f9f8e7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 4 Oct 2015 12:05:20 +0200 Subject: [PATCH 0505/1390] Minor refactorings #1065 --- .../charting/components/ComponentBase.java | 2 +- .../charting/components/LimitLine.java | 65 +--- .../formatter/LargeValueFormatter.java | 18 +- .../charting/formatter/PercentFormatter.java | 11 +- .../charting/renderer/AxisRenderer.java | 1 - .../charting/renderer/XAxisRenderer.java | 10 +- .../XAxisRendererHorizontalBarChart.java | 7 +- .../charting/renderer/YAxisRenderer.java | 7 +- .../YAxisRendererHorizontalBarChart.java | 10 +- .../renderer/YAxisRendererRadarChart.java | 287 +++++++++--------- .../github/mikephil/charting/utils/FSize.java | 1 - .../mikephil/charting/utils/Transformer.java | 121 +++----- .../charting/utils/ViewPortHandler.java | 91 ++++-- 13 files changed, 302 insertions(+), 329 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java index 51841eabdf..713f89dd79 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/ComponentBase.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.utils.Utils; /** - * This class encapsulates everything both Axis and Legend have in common. + * This class encapsulates everything both Axis, Legend and LimitLines have in common. * * @author Philipp Jahoda */ diff --git a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java index 606fce97bf..8fcdee8fc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/LimitLine.java @@ -15,7 +15,7 @@ * * @author Philipp Jahoda */ -public class LimitLine { +public class LimitLine extends ComponentBase { /** limit / maximum (the y-value or xIndex) */ private float mLimit = 0f; @@ -26,21 +26,12 @@ public class LimitLine { /** the color of the limit line */ private int mLineColor = Color.rgb(237, 91, 91); - /** the color of the value-text */ - private int mValueTextColor = Color.BLACK; - - /** the size of the label text */ - private float mTextSize = 13f; - /** the style of the label text */ private Paint.Style mTextStyle = Paint.Style.FILL_AND_STROKE; /** label string that is drawn next to the limit line */ private String mLabel = ""; - /** the typeface used for the labels */ - private Typeface mTypeface = null; - /** the path effect of this LimitLine that makes dashed lines possible */ private DashPathEffect mDashPathEffect = null; @@ -165,24 +156,6 @@ public DashPathEffect getDashPathEffect() { return mDashPathEffect; } - /** - * Sets the color of the value-text that is drawn next to the LimitLine. - * - * @param color - */ - public void setTextColor(int color) { - mValueTextColor = color; - } - - /** - * Returns the color of the value-text that is drawn next to the LimitLine. - * - * @return - */ - public int getTextColor() { - return mValueTextColor; - } - /** * Sets the color of the value-text that is drawn next to the LimitLine. * Default: Paint.Style.FILL_AND_STROKE @@ -239,40 +212,4 @@ public void setLabel(String label) { public String getLabel() { return mLabel; } - - /** - * Sets the size of the label-text. - * - * @param size - */ - public void setTextSize(float size) { - mTextSize = Utils.convertDpToPixel(size); - } - - /** - * Returns the size of the label text. - * - * @return - */ - public float getTextSize() { - return mTextSize; - } - - /** - * returns the Typeface used for the limitline label, returns null if none is set - * - * @return - */ - public Typeface getTypeface() { - return mTypeface; - } - - /** - * Sets a specific Typeface to be used for the limitline label - * - * @param tf - */ - public void setTypeface(Typeface tf) { - mTypeface = tf; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java index 5bd55edfd1..96b4ead74f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/LargeValueFormatter.java @@ -13,13 +13,13 @@ * 2000000 = 2m; 7800000 = 7.8m; 92150000 = 92m; 123200000 = 123m; 9999999 = * 10m; 1000000000 = 1b; Special thanks to Roman Gromov * (https://github.com/romangromov) for this piece of code. - * + * * @author Philipp Jahoda * @author Oleksandr Tyshkovets */ public class LargeValueFormatter implements ValueFormatter, YAxisValueFormatter { - private static String[] SUFFIX = new String[] { + private static String[] SUFFIX = new String[]{ "", "k", "m", "b", "t" }; private static final int MAX_LENGTH = 4; @@ -32,6 +32,7 @@ public LargeValueFormatter() { /** * Creates a formatter that appends a specified text to the result string + * * @param appendix a text that will be appended */ public LargeValueFormatter(String appendix) { @@ -52,7 +53,18 @@ public String getFormattedValue(float value, YAxis yAxis) { } /** - * Set custom suffix to be appended after the values + * Set an appendix text to be added at the end of the formatted value. + * + * @param appendix + */ + public void setAppendix(String appendix) { + this.mText = appendix; + } + + /** + * Set custom suffix to be appended after the values. + * Default suffix: ["", "k", "m", "b", "t"] + * * @param suff new suffix */ public void setSuffix(String[] suff) { diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java index 01011ce59b..6e3535d8b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/PercentFormatter.java @@ -10,7 +10,7 @@ /** * This ValueFormatter is just for convenience and simply puts a "%" sign after * each value. (Recommeded for PieChart) - * + * * @author Philipp Jahoda */ public class PercentFormatter implements ValueFormatter, YAxisValueFormatter { @@ -21,6 +21,15 @@ public PercentFormatter() { mFormat = new DecimalFormat("###,###,##0.0"); } + /** + * Allow a custom decimalformat + * + * @param format + */ + public PercentFormatter(DecimalFormat format) { + this.mFormat = format; + } + // ValueFormatter @Override public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java index 86d4186351..6dac9de21c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/AxisRenderer.java @@ -117,5 +117,4 @@ public Transformer getTransformer() { * @param c */ public abstract void renderLimitLines(Canvas c); - } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 1f1c0d26fd..482c3e766e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -216,6 +216,9 @@ public void renderLimitLines(Canvas c) { LimitLine l = limitLines.get(i); + if(!l.isEnabled()) + continue; + pts[0] = l.getLimit(); pts[2] = l.getLimit(); @@ -246,9 +249,8 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - float xOffset = l.getLineWidth(); - float add = Utils.convertDpToPixel(4f); - float yOffset = add / 2f; + float xOffset = l.getLineWidth() + l.getXOffset(); + float yOffset = Utils.convertDpToPixel(2f) + l.getYOffset(); final LimitLine.LimitLabelPosition position = l.getLabelPosition(); @@ -260,7 +262,7 @@ public void renderLimitLines(Canvas c) { } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { mLimitLinePaint.setTextAlign(Align.RIGHT); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 25a02e7df1..fc64c70a72 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -191,6 +191,9 @@ public void renderLimitLines(Canvas c) { LimitLine l = limitLines.get(i); + if(!l.isEnabled()) + continue; + mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); @@ -219,8 +222,8 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTextSize(l.getTextSize()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + labelLineHeight; + float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); + float yOffset = l.getLineWidth() + labelLineHeight + l.getYOffset(); final LimitLine.LimitLabelPosition position = l.getLabelPosition(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 874740ace5..1d174f430e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -295,6 +295,9 @@ public void renderLimitLines(Canvas c) { LimitLine l = limitLines.get(i); + if(!l.isEnabled()) + continue; + mLimitLinePaint.setStyle(Paint.Style.STROKE); mLimitLinePaint.setColor(l.getLineColor()); mLimitLinePaint.setStrokeWidth(l.getLineWidth()); @@ -324,8 +327,8 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setTextSize(l.getTextSize()); final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - float xOffset = Utils.convertDpToPixel(4f); - float yOffset = l.getLineWidth() + labelLineHeight; + float xOffset = Utils.convertDpToPixel(4f) + l.getXOffset(); + float yOffset = l.getLineWidth() + labelLineHeight + l.getYOffset(); final LimitLine.LimitLabelPosition position = l.getLabelPosition(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 216f545571..e9ff473efc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -197,6 +197,9 @@ public void renderLimitLines(Canvas c) { for (int i = 0; i < limitLines.size(); i++) { LimitLine l = limitLines.get(i); + + if(!l.isEnabled()) + continue; pts[0] = l.getLimit(); pts[2] = l.getLimit(); @@ -229,9 +232,8 @@ public void renderLimitLines(Canvas c) { mLimitLinePaint.setStrokeWidth(0.5f); mLimitLinePaint.setTextSize(l.getTextSize()); - float xOffset = l.getLineWidth(); - float add = Utils.convertDpToPixel(4f); - float yOffset = add / 2f; + float xOffset = l.getLineWidth() + l.getXOffset(); + float yOffset = Utils.convertDpToPixel(2f) + l.getYOffset(); final LimitLine.LimitLabelPosition position = l.getLabelPosition(); @@ -243,7 +245,7 @@ public void renderLimitLines(Canvas c) { } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - add, mLimitLinePaint); + c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { mLimitLinePaint.setTextAlign(Align.RIGHT); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index f54f3b8579..2f1b254f9e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -14,197 +14,200 @@ public class YAxisRendererRadarChart extends YAxisRenderer { - private RadarChart mChart; + private RadarChart mChart; - public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { - super(viewPortHandler, yAxis, null); + public YAxisRendererRadarChart(ViewPortHandler viewPortHandler, YAxis yAxis, RadarChart chart) { + super(viewPortHandler, yAxis, null); - this.mChart = chart; - } - - @Override - public void computeAxis(float yMin, float yMax) { - computeAxisValues(yMin, yMax); - } - - @Override - protected void computeAxisValues(float min, float max) { - float yMin = min; - float yMax = max; - - int labelCount = mYAxis.getLabelCount(); - double range = Math.abs(yMax - yMin); - - if (labelCount == 0 || range <= 0) { - mYAxis.mEntries = new float[] {}; - mYAxis.mEntryCount = 0; - return; - } + this.mChart = chart; + } + + @Override + public void computeAxis(float yMin, float yMax) { + computeAxisValues(yMin, yMax); + } + + @Override + protected void computeAxisValues(float min, float max) { + float yMin = min; + float yMax = max; + + int labelCount = mYAxis.getLabelCount(); + double range = Math.abs(yMax - yMin); + + if (labelCount == 0 || range <= 0) { + mYAxis.mEntries = new float[]{}; + mYAxis.mEntryCount = 0; + return; + } - double rawInterval = range / labelCount; - double interval = Utils.roundToNextSignificant(rawInterval); - double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); - int intervalSigDigit = (int) (interval / intervalMagnitude); - if (intervalSigDigit > 5) { - // Use one order of magnitude higher, to avoid intervals like 0.9 or - // 90 - interval = Math.floor(10 * intervalMagnitude); - } + double rawInterval = range / labelCount; + double interval = Utils.roundToNextSignificant(rawInterval); + double intervalMagnitude = Math.pow(10, (int) Math.log10(interval)); + int intervalSigDigit = (int) (interval / intervalMagnitude); + if (intervalSigDigit > 5) { + // Use one order of magnitude higher, to avoid intervals like 0.9 or + // 90 + interval = Math.floor(10 * intervalMagnitude); + } - // force label count - if (mYAxis.isForceLabelsEnabled()) { + // force label count + if (mYAxis.isForceLabelsEnabled()) { - float step = (float) range / (float) (labelCount-1); - mYAxis.mEntryCount = labelCount; + float step = (float) range / (float) (labelCount - 1); + mYAxis.mEntryCount = labelCount; - if (mYAxis.mEntries.length < labelCount) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[labelCount]; - } + if (mYAxis.mEntries.length < labelCount) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[labelCount]; + } - float v = min; + float v = min; - for (int i = 0; i < labelCount; i++) { - mYAxis.mEntries[i] = v; - v += step; - } + for (int i = 0; i < labelCount; i++) { + mYAxis.mEntries[i] = v; + v += step; + } - // no forced count - } else { + // no forced count + } else { - // if the labels should only show min and max - if (mYAxis.isShowOnlyMinMaxEnabled()) { + // if the labels should only show min and max + if (mYAxis.isShowOnlyMinMaxEnabled()) { - mYAxis.mEntryCount = 2; - mYAxis.mEntries = new float[2]; - mYAxis.mEntries[0] = yMin; - mYAxis.mEntries[1] = yMax; + mYAxis.mEntryCount = 2; + mYAxis.mEntries = new float[2]; + mYAxis.mEntries[0] = yMin; + mYAxis.mEntries[1] = yMax; - } else { + } else { - final double rawCount = yMin / interval; - double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; + final double rawCount = yMin / interval; + double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - if (first < yMin && mYAxis.isStartAtZeroEnabled()) { - // Force the first label to be at the 0 (or smallest negative value) - first = yMin; - } + if (first < yMin && mYAxis.isStartAtZeroEnabled()) { + // Force the first label to be at the 0 (or smallest negative value) + first = yMin; + } - if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) - first = 0.0; + if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) + first = 0.0; - double last = Utils.nextUp(Math.floor(yMax / interval) * interval); + double last = Utils.nextUp(Math.floor(yMax / interval) * interval); - double f; - int i; - int n = 0; - for (f = first; f <= last; f += interval) { - ++n; - } + double f; + int i; + int n = 0; + for (f = first; f <= last; f += interval) { + ++n; + } - if (Float.isNaN(mYAxis.getAxisMaxValue())) - n += 1; + if (Float.isNaN(mYAxis.getAxisMaxValue())) + n += 1; - mYAxis.mEntryCount = n; + mYAxis.mEntryCount = n; - if (mYAxis.mEntries.length < n) { - // Ensure stops contains at least numStops elements. - mYAxis.mEntries = new float[n]; - } + if (mYAxis.mEntries.length < n) { + // Ensure stops contains at least numStops elements. + mYAxis.mEntries = new float[n]; + } - for (f = first, i = 0; i < n; f += interval, ++i) { - mYAxis.mEntries[i] = (float) f; - } - } - } + for (f = first, i = 0; i < n; f += interval, ++i) { + mYAxis.mEntries[i] = (float) f; + } + } + } - if (interval < 1) { - mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); - } else { - mYAxis.mDecimals = 0; - } + if (interval < 1) { + mYAxis.mDecimals = (int) Math.ceil(-Math.log10(interval)); + } else { + mYAxis.mDecimals = 0; + } - if (!mYAxis.isStartAtZeroEnabled() && mYAxis.mEntries[0] < yMin) { - // If startAtZero is disabled, and the first label is lower that the axis minimum, - // Then adjust the axis minimum - mYAxis.mAxisMinimum = mYAxis.mEntries[0]; - } + if (!mYAxis.isStartAtZeroEnabled() && mYAxis.mEntries[0] < yMin) { + // If startAtZero is disabled, and the first label is lower that the axis minimum, + // Then adjust the axis minimum + mYAxis.mAxisMinimum = mYAxis.mEntries[0]; + } - mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; - mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); - } + mYAxis.mAxisMaximum = mYAxis.mEntries[mYAxis.mEntryCount - 1]; + mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); + } - @Override - public void renderAxisLabels(Canvas c) { + @Override + public void renderAxisLabels(Canvas c) { - if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) - return; + if (!mYAxis.isEnabled() || !mYAxis.isDrawLabelsEnabled()) + return; - mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); - mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); - mAxisLabelPaint.setColor(mYAxis.getTextColor()); + mAxisLabelPaint.setTypeface(mYAxis.getTypeface()); + mAxisLabelPaint.setTextSize(mYAxis.getTextSize()); + mAxisLabelPaint.setColor(mYAxis.getTextColor()); - PointF center = mChart.getCenterOffsets(); - float factor = mChart.getFactor(); + PointF center = mChart.getCenterOffsets(); + float factor = mChart.getFactor(); - int labelCount = mYAxis.mEntryCount; + int labelCount = mYAxis.mEntryCount; - for (int j = 0; j < labelCount; j++) { + for (int j = 0; j < labelCount; j++) { - if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) - break; + if (j == labelCount - 1 && mYAxis.isDrawTopYLabelEntryEnabled() == false) + break; - float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; + float r = (mYAxis.mEntries[j] - mYAxis.mAxisMinimum) * factor; - PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); + PointF p = Utils.getPosition(center, r, mChart.getRotationAngle()); - String label = mYAxis.getFormattedLabel(j); + String label = mYAxis.getFormattedLabel(j); - c.drawText(label, p.x + 10, p.y, mAxisLabelPaint); - } - } + c.drawText(label, p.x + 10, p.y, mAxisLabelPaint); + } + } - @Override - public void renderLimitLines(Canvas c) { + @Override + public void renderLimitLines(Canvas c) { - List limitLines = mYAxis.getLimitLines(); + List limitLines = mYAxis.getLimitLines(); - if (limitLines == null) - return; + if (limitLines == null) + return; - float sliceangle = mChart.getSliceAngle(); + float sliceangle = mChart.getSliceAngle(); - // calculate the factor that is needed for transforming the value to - // pixels - float factor = mChart.getFactor(); + // calculate the factor that is needed for transforming the value to + // pixels + float factor = mChart.getFactor(); - PointF center = mChart.getCenterOffsets(); + PointF center = mChart.getCenterOffsets(); - for (int i = 0; i < limitLines.size(); i++) { + for (int i = 0; i < limitLines.size(); i++) { - LimitLine l = limitLines.get(i); + LimitLine l = limitLines.get(i); - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); + if (!l.isEnabled()) + continue; - float r = (l.getLimit() - mChart.getYChartMin()) * factor; + mLimitLinePaint.setColor(l.getLineColor()); + mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - Path limitPath = new Path(); + float r = (l.getLimit() - mChart.getYChartMin()) * factor; - for (int j = 0; j < mChart.getData().getXValCount(); j++) { + Path limitPath = new Path(); - PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); + for (int j = 0; j < mChart.getData().getXValCount(); j++) { - if (j == 0) - limitPath.moveTo(p.x, p.y); - else - limitPath.lineTo(p.x, p.y); - } + PointF p = Utils.getPosition(center, r, sliceangle * j + mChart.getRotationAngle()); - limitPath.close(); + if (j == 0) + limitPath.moveTo(p.x, p.y); + else + limitPath.lineTo(p.x, p.y); + } - c.drawPath(limitPath, mLimitLinePaint); - } - } + limitPath.close(); + + c.drawPath(limitPath, mLimitLinePaint); + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/FSize.java b/MPChartLib/src/com/github/mikephil/charting/utils/FSize.java index 498da226b7..185e05bf5d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/FSize.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/FSize.java @@ -16,7 +16,6 @@ public FSize(final float width, final float height) { this.height = height; } - @Override public boolean equals(final Object obj) { if (obj == null) { diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index cf8f5b2c4c..cd936ffc9e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -14,15 +14,19 @@ /** * Transformer class that contains all matrices and is responsible for * transforming values into pixels on the screen and backwards. - * + * * @author Philipp Jahoda */ public class Transformer { - /** matrix to map the values to the screen pixels */ + /** + * matrix to map the values to the screen pixels + */ protected Matrix mMatrixValueToPx = new Matrix(); - /** matrix for handling the different offsets of the chart */ + /** + * matrix for handling the different offsets of the chart + */ protected Matrix mMatrixOffset = new Matrix(); protected ViewPortHandler mViewPortHandler; @@ -34,8 +38,11 @@ public Transformer(ViewPortHandler viewPortHandler) { /** * Prepares the matrix that transforms values to pixels. Calculates the * scale factors from the charts size and offsets. - * - * @param chart + * + * @param xChartMin + * @param deltaX + * @param deltaY + * @param yChartMin */ public void prepareMatrixValuePx(float xChartMin, float deltaX, float deltaY, float yChartMin) { @@ -48,24 +55,9 @@ public void prepareMatrixValuePx(float xChartMin, float deltaX, float deltaY, fl mMatrixValueToPx.postScale(scaleX, -scaleY); } - // /** - // * Prepares the transformation matrix with the specified scales. - // * - // * @param chart - // * @param scaleX - // * @param scaleY - // */ - // public void prepareMatrixValuePx(ChartInterface chart, float scaleX, - // float scaleY) { - // - // mMatrixValueToPx.reset(); - // mMatrixValueToPx.postTranslate(0, -chart.getYChartMin()); - // mMatrixValueToPx.postScale(scaleX, -scaleY); - // } - /** * Prepares the matrix that contains all offsets. - * + * * @param inverted */ public void prepareMatrixOffset(boolean inverted) { @@ -94,12 +86,12 @@ public void prepareMatrixOffset(boolean inverted) { /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the SCATTERCHART. - * + * * @param entries * @return */ public float[] generateTransformedValuesScatter(List entries, - float phaseY) { + float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -126,7 +118,7 @@ public float[] generateTransformedValuesScatter(List entries, * @return */ public float[] generateTransformedValuesBubble(List entries, - float phaseX, float phaseY, int from, int to) { + float phaseX, float phaseY, int from, int to) { final int count = (int) Math.ceil(to - from) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; @@ -146,18 +138,18 @@ public float[] generateTransformedValuesBubble(List entries, return valuePoints; } - + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the LINECHART. - * + * * @param entries * @return */ public float[] generateTransformedValuesLine(List entries, - float phaseX, float phaseY, int from, int to) { + float phaseX, float phaseY, int from, int to) { - final int count = (int)Math.ceil((to - from) * phaseX) * 2; + final int count = (int) Math.ceil((to - from) * phaseX) * 2; float[] valuePoints = new float[count]; @@ -175,18 +167,18 @@ public float[] generateTransformedValuesLine(List entries, return valuePoints; } - + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the CANDLESTICKCHART. - * + * * @param entries * @return */ public float[] generateTransformedValuesCandle(List entries, - float phaseX, float phaseY, int from, int to) { + float phaseX, float phaseY, int from, int to) { - final int count = (int)Math.ceil((to - from) * phaseX) * 2; + final int count = (int) Math.ceil((to - from) * phaseX) * 2; float[] valuePoints = new float[count]; @@ -208,13 +200,13 @@ public float[] generateTransformedValuesCandle(List entries, /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. - * + * * @param entries * @param dataSet the dataset index * @return */ public float[] generateTransformedValuesBarChart(List entries, - int dataSet, BarData bd, float phaseY) { + int dataSet, BarData bd, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -239,17 +231,17 @@ public float[] generateTransformedValuesBarChart(List entries, return valuePoints; } - + /** * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. - * + * * @param entries * @param dataSet the dataset index * @return */ public float[] generateTransformedValuesHorizontalBarChart(List entries, - int dataSet, BarData bd, float phaseY) { + int dataSet, BarData bd, float phaseY) { float[] valuePoints = new float[entries.size() * 2]; @@ -263,7 +255,7 @@ public float[] generateTransformedValuesHorizontalBarChart(List // calculate the x-position, depending on datasetcount float x = i + i * (setCount - 1) + dataSet + space * i - + space / 2f ; + + space / 2f; float y = e.getVal(); valuePoints[j] = y * phaseY; @@ -278,7 +270,7 @@ public float[] generateTransformedValuesHorizontalBarChart(List /** * transform a path with all the given matrices VERY IMPORTANT: keep order * to value-touch-offset - * + * * @param path */ public void pathValueToPixel(Path path) { @@ -290,7 +282,7 @@ public void pathValueToPixel(Path path) { /** * Transforms multiple paths will all matrices. - * + * * @param paths */ public void pathValuesToPixel(List paths) { @@ -303,7 +295,7 @@ public void pathValuesToPixel(List paths) { /** * Transform an array of points with all matrices. VERY IMPORTANT: Keep * matrix order "value-touch-offset" when transforming. - * + * * @param pts */ public void pointValuesToPixel(float[] pts) { @@ -315,7 +307,7 @@ public void pointValuesToPixel(float[] pts) { /** * Transform a rectangle with all matrices. - * + * * @param r */ public void rectValueToPixel(RectF r) { @@ -327,7 +319,7 @@ public void rectValueToPixel(RectF r) { /** * Transform a rectangle with all matrices with potential animation phases. - * + * * @param r * @param phaseY */ @@ -346,7 +338,6 @@ public void rectValueToPixel(RectF r, float phaseY) { * Transform a rectangle with all matrices with potential animation phases. * * @param r - */ public void rectValueToPixelHorizontal(RectF r) { @@ -354,10 +345,10 @@ public void rectValueToPixelHorizontal(RectF r) { mViewPortHandler.getMatrixTouch().mapRect(r); mMatrixOffset.mapRect(r); } - + /** * Transform a rectangle with all matrices with potential animation phases. - * + * * @param r * @param phaseY */ @@ -374,7 +365,7 @@ public void rectValueToPixelHorizontal(RectF r, float phaseY) { /** * transforms multiple rects with all matrices - * + * * @param rects */ public void rectValuesToPixel(List rects) { @@ -388,7 +379,7 @@ public void rectValuesToPixel(List rects) { /** * Transforms the given array of touch positions (pixels) (x, y, x, y, ...) * into values on the chart. - * + * * @param pixels */ public void pixelsToValue(float[] pixels) { @@ -411,7 +402,7 @@ public void pixelsToValue(float[] pixels) { * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). - * + * * @param x * @param y * @return @@ -431,33 +422,16 @@ public PointD getValuesByTouchPoint(float x, float y) { return new PointD(xTouchVal, yTouchVal); } - // /** - // * transforms the given rect objects with the touch matrix only - // * - // * @param paths - // */ - // public void transformRectsTouch(List rects) { - // for (int i = 0; i < rects.size(); i++) { - // mMatrixTouch.mapRect(rects.get(i)); - // } - // } - // - // /** - // * transforms the given path objects with the touch matrix only - // * - // * @param paths - // */ - // public void transformPathsTouch(List paths) { - // for (int i = 0; i < paths.size(); i++) { - // paths.get(i).transform(mMatrixTouch); - // } - // } - public Matrix getValueMatrix() { return mMatrixValueToPx; } + public Matrix getOffsetMatrix() { + return mMatrixOffset; + } + private Matrix mMBuffer1 = new Matrix(); + public Matrix getValueToPixelMatrix() { mMBuffer1.set(mMatrixValueToPx); mMBuffer1.postConcat(mViewPortHandler.mMatrixTouch); @@ -466,12 +440,9 @@ public Matrix getValueToPixelMatrix() { } private Matrix mMBuffer2 = new Matrix(); + public Matrix getPixelToValueMatrix() { getValueToPixelMatrix().invert(mMBuffer2); return mMBuffer2; } - - public Matrix getOffsetMatrix() { - return mMatrixOffset; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index 44ae1001c4..8840e70fa3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -6,43 +6,74 @@ import android.graphics.RectF; import android.view.View; +/** + * Class that contains information about the charts current viewport settings, including offsets, scale & translation levels, ... + * + * @author Philipp Jahoda + */ public class ViewPortHandler { - /** matrix used for touch events */ + /** + * matrix used for touch events + */ protected final Matrix mMatrixTouch = new Matrix(); - /** this rectangle defines the area in which graph values can be drawn */ + /** + * this rectangle defines the area in which graph values can be drawn + */ protected RectF mContentRect = new RectF(); protected float mChartWidth = 0f; protected float mChartHeight = 0f; - /** minimum scale value on the y-axis */ + /** + * minimum scale value on the y-axis + */ private float mMinScaleY = 1f; - /** maximum scale value on the y-axis */ + /** + * maximum scale value on the y-axis + */ private float mMaxScaleY = Float.MAX_VALUE; - /** minimum scale value on the x-axis */ + /** + * minimum scale value on the x-axis + */ private float mMinScaleX = 1f; - /** maximum scale value on the x-axis */ + /** + * maximum scale value on the x-axis + */ private float mMaxScaleX = Float.MAX_VALUE; - /** contains the current scale factor of the x-axis */ + /** + * contains the current scale factor of the x-axis + */ private float mScaleX = 1f; - /** contains the current scale factor of the y-axis */ + /** + * contains the current scale factor of the y-axis + */ private float mScaleY = 1f; + /** + * current translation (drag distance) on the x-axis + */ private float mTransX = 0f; + /** + * current translation (drag distance) on the y-axis + */ private float mTransY = 0f; - /** offset that allows the chart to be dragged over its bounds on the x-axis */ + /** + * offset that allows the chart to be dragged over its bounds on the x-axis + */ private float mTransOffsetX = 0f; - /** offset that allows the chart to be dragged over its bounds on the x-axis */ + /** + * offset that allows the chart to be dragged over its bounds on the x-axis + */ private float mTransOffsetY = 0f; public ViewPortHandler() { @@ -51,7 +82,7 @@ public ViewPortHandler() { /** * Sets the width and height of the chart. - * + * * @param width * @param height */ @@ -78,7 +109,7 @@ public boolean hasChartDimens() { } public void restrainViewPort(float offsetLeft, float offsetTop, float offsetRight, - float offsetBottom) { + float offsetBottom) { mContentRect.set(offsetLeft, offsetTop, mChartWidth - offsetRight, mChartHeight - offsetBottom); } @@ -147,7 +178,7 @@ public float getChartWidth() { /** * Zooms in by 1.4f, x and y are the coordinates (in pixels) of the zoom * center. - * + * * @param x * @param y */ @@ -178,7 +209,7 @@ public Matrix zoomOut(float x, float y) { /** * Zooms in or out by the given scale factor. x and y are the coordinates * (in pixels) of the zoom center. - * + * * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in * @param x @@ -201,7 +232,7 @@ public Matrix zoom(float scaleX, float scaleY, float x, float y) { * bounds. */ public Matrix fitScreen() { - + mMinScaleX = 1f; mMinScaleY = 1f; @@ -228,7 +259,7 @@ public Matrix fitScreen() { * in the chart. Centering the viewport outside the bounds of the chart is * not possible. Makes most sense in combination with the * setScaleMinima(...) method. - * + * * @param transformedPts the position to center view viewport to * @param view * @return save @@ -250,7 +281,7 @@ public synchronized void centerViewPort(final float[] transformedPts, final View /** * call this method to refresh the graph with a given matrix - * + * * @param newMatrix * @return */ @@ -270,7 +301,7 @@ public Matrix refresh(Matrix newMatrix, View chart, boolean invalidate) { /** * limits the maximum scale and X translation of the given matrix - * + * * @param matrix */ public void limitTransAndScale(Matrix matrix, RectF content) { @@ -331,7 +362,7 @@ public void setMaximumScaleX(float xScale) { limitTransAndScale(mMatrixTouch, mContentRect); } - + public void setMinMaxScaleX(float minScaleX, float maxScaleX) { if (minScaleX < 1f) @@ -362,7 +393,7 @@ public void setMaximumScaleY(float yScale) { /** * Returns the charts-touch matrix used for translation and scale on touch. - * + * * @return */ public Matrix getMatrixTouch() { @@ -372,7 +403,9 @@ public Matrix getMatrixTouch() { /** * ################ ################ ################ ################ */ - /** BELOW METHODS FOR BOUNDS CHECK */ + /** + * BELOW METHODS FOR BOUNDS CHECK + */ public boolean isInBoundsX(float x) { if (isInBoundsLeft(x) && isInBoundsRight(x)) @@ -400,7 +433,7 @@ public boolean isInBoundsLeft(float x) { } public boolean isInBoundsRight(float x) { - x = (float)((int)(x * 100.f)) / 100.f; + x = (float) ((int) (x * 100.f)) / 100.f; return mContentRect.right >= x ? true : false; } @@ -409,7 +442,7 @@ public boolean isInBoundsTop(float y) { } public boolean isInBoundsBottom(float y) { - y = (float)((int)(y * 100.f)) / 100.f; + y = (float) ((int) (y * 100.f)) / 100.f; return mContentRect.bottom >= y ? true : false; } @@ -437,7 +470,7 @@ public float getTransY() { /** * if the chart is fully zoomed out, return true - * + * * @return */ public boolean isFullyZoomedOut() { @@ -450,7 +483,7 @@ public boolean isFullyZoomedOut() { /** * Returns true if the chart is fully zoomed out on it's y-axis (vertical). - * + * * @return */ public boolean isFullyZoomedOutY() { @@ -463,7 +496,7 @@ public boolean isFullyZoomedOutY() { /** * Returns true if the chart is fully zoomed out on it's x-axis * (horizontal). - * + * * @return */ public boolean isFullyZoomedOutX() { @@ -476,7 +509,7 @@ public boolean isFullyZoomedOutX() { /** * Set an offset in dp that allows the user to drag the chart over it's * bounds on the x-axis. - * + * * @param offset */ public void setDragOffsetX(float offset) { @@ -486,7 +519,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's * bounds on the y-axis. - * + * * @param offset */ public void setDragOffsetY(float offset) { @@ -495,7 +528,7 @@ public void setDragOffsetY(float offset) { /** * Returns true if both drag offsets (x and y) are zero or smaller. - * + * * @return */ public boolean hasNoDragOffset() { From 0e9495261bb21ac8d7bd081c4759a8a062aef134 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 4 Oct 2015 18:15:14 +0200 Subject: [PATCH 0506/1390] Allow callbacks on touch-start and end (#1069) --- .../mpchartexample/LineChartActivity1.java | 11 +++++ .../fragments/BarChartFrag.java | 10 +++++ .../listener/BarLineChartTouchListener.java | 1 + .../charting/listener/ChartTouchListener.java | 40 +++++++++++++++-- .../listener/OnChartGestureListener.java | 43 ++++++++++++------- .../listener/PieRadarChartTouchListener.java | 1 + 6 files changed, 87 insertions(+), 19 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 281fcd06f4..bd42baf26b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -364,6 +364,17 @@ private void setData(int count, float range) { mChart.setData(data); } + @Override + public void onChartGestureStart(MotionEvent me) { + Log.i("Gesture", "START"); + } + + @Override + public void onChartGestureEnd(MotionEvent me) { + Log.i("Gesture", "END"); + mChart.highlightValues(null); + } + @Override public void onChartLongPressed(MotionEvent me) { Log.i("LongPress", "Chart longpressed."); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index dcaace51f9..3702795f5e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -66,6 +66,16 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa return v; } + @Override + public void onChartGestureStart(MotionEvent me) { + Log.i("Gesture", "START"); + } + + @Override + public void onChartGestureEnd(MotionEvent me) { + Log.i("Gesture", "END"); + } + @Override public void onChartLongPressed(MotionEvent me) { Log.i("LongPress", "Chart longpressed."); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 18d3ee44a7..e80e16be36 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -61,6 +61,7 @@ public BarLineChartTouchListener(BarLineChartBase> extends GestureDete protected static final int POST_ZOOM = 5; protected static final int ROTATE = 6; - /** integer field that holds the current touch-state */ + /** + * integer field that holds the current touch-state + */ protected int mTouchMode = NONE; - /** the last highlighted object (via touch) */ + /** + * the last highlighted object (via touch) + */ protected Highlight mLastHighlighted; - /** the gesturedetector used for detecting taps and longpresses, ... */ + /** + * the gesturedetector used for detecting taps and longpresses, ... + */ protected GestureDetector mGestureDetector; - /** the chart the listener represents */ + /** + * the chart the listener represents + */ protected T mChart; public ChartTouchListener(T chart) { @@ -38,8 +47,31 @@ public ChartTouchListener(T chart) { mGestureDetector = new GestureDetector(chart.getContext(), this); } + @Override + public boolean onTouch(View v, MotionEvent event) { + + OnChartGestureListener l = mChart.getOnChartGestureListener(); + + if (l != null) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + l.onChartGestureStart(event); + break; + case MotionEvent.ACTION_CANCEL: + l.onChartGestureEnd(event); + break; + case MotionEvent.ACTION_UP: + l.onChartGestureEnd(event); + break; + } + } + + return false; + } + /** * Sets the last value that was highlighted via touch. + * * @param high */ public void setLastHighlighted(Highlight high) { diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java index 9674b2c7b7..f984395b19 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -4,35 +4,49 @@ /** * Listener for callbacks when doing gestures on the chart. - * + * * @author Philipp Jahoda */ public interface OnChartGestureListener { + /** + * Callbacks when a touch-gesture has started on the chart (ACTION_DOWN) + * + * @param me + */ + void onChartGestureStart(MotionEvent me); + + /** + * Callbacks when a touch-gesture has ended on the chart (ACTION_UP, ACTION_CANCEL) + * + * @param me + */ + void onChartGestureEnd(MotionEvent me); + /** * Callbacks when the chart is longpressed. - * + * * @param me */ void onChartLongPressed(MotionEvent me); /** * Callbacks when the chart is double-tapped. - * + * * @param me */ void onChartDoubleTapped(MotionEvent me); /** * Callbacks when the chart is single-tapped. - * + * * @param me */ void onChartSingleTapped(MotionEvent me); /** * Callbacks then a fling gesture is made on the chart. - * + * * @param me1 * @param me2 * @param velocityX @@ -42,20 +56,19 @@ public interface OnChartGestureListener { /** * Callbacks when the chart is scaled / zoomed via pinch zoom gesture. - * + * * @param me * @param scaleX scalefactor on the x-axis * @param scaleY scalefactor on the y-axis */ void onChartScale(MotionEvent me, float scaleX, float scaleY); - /** - * Callbacks when the chart is moved / translated via drag gesture. - * - * @param me - * @param dX translation distance on the x-axis - * @param dY translation distance on the y-axis - */ - void onChartTranslate(MotionEvent me, float dX, float dY); - + /** + * Callbacks when the chart is moved / translated via drag gesture. + * + * @param me + * @param dX translation distance on the x-axis + * @param dY translation distance on the y-axis + */ + void onChartTranslate(MotionEvent me, float dX, float dY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 3df80403a6..f7b92f5932 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -41,6 +41,7 @@ public PieRadarChartTouchListener(PieRadarChartBase chart) { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { + super.onTouch(v, event); if (mGestureDetector.onTouchEvent(event)) return true; From 314a9d810430ac0299d61dfd72c08cc62d6dcc23 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 4 Oct 2015 20:18:39 +0200 Subject: [PATCH 0507/1390] Improvements to gesture start-end callbacks. --- .../mpchartexample/LineChartActivity1.java | 11 ++-- .../fragments/BarChartFrag.java | 6 +- .../listener/BarLineChartTouchListener.java | 56 +++++++++++++++---- .../charting/listener/ChartTouchListener.java | 56 +++++++++++++------ .../listener/OnChartGestureListener.java | 6 +- .../listener/PieRadarChartTouchListener.java | 13 ++++- 6 files changed, 111 insertions(+), 37 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index bd42baf26b..24551f0fc7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -29,6 +29,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; @@ -365,14 +366,16 @@ private void setData(int count, float range) { } @Override - public void onChartGestureStart(MotionEvent me) { + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "START"); } @Override - public void onChartGestureEnd(MotionEvent me) { - Log.i("Gesture", "END"); - mChart.highlightValues(null); + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { + Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); + + if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) + mChart.highlightValues(null); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index 3702795f5e..c338026740 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; @@ -67,13 +68,14 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa } @Override - public void onChartGestureStart(MotionEvent me) { + public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "START"); } @Override - public void onChartGestureEnd(MotionEvent me) { + public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "END"); + mChart.highlightValues(null); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index e80e16be36..443a3495e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -61,7 +61,6 @@ public BarLineChartTouchListener(BarLineChartBase 5f) { + if (mChart.hasNoDragOffset()) { - if (!mChart.isFullyZoomedOut() && mChart.isDragEnabled()) + if (!mChart.isFullyZoomedOut() && mChart.isDragEnabled()) { mTouchMode = DRAG; - else { + } else { + + mLastGesture = ChartGesture.DRAG; + if (mChart.isHighlightPerDragEnabled()) performHighlightDrag(event); } } else if (mChart.isDragEnabled()) { + mLastGesture = ChartGesture.DRAG; mTouchMode = DRAG; } } @@ -201,6 +207,8 @@ public boolean onTouch(View v, MotionEvent event) { mVelocityTracker = null; } + endAction(event); + break; case MotionEvent.ACTION_POINTER_UP: Utils.velocityTrackerPointerUpCleanUpIfNecessary(event, mVelocityTracker); @@ -211,7 +219,7 @@ public boolean onTouch(View v, MotionEvent event) { case MotionEvent.ACTION_CANCEL: mTouchMode = NONE; - + endAction(event); break; } @@ -247,6 +255,8 @@ private void saveTouchStart(MotionEvent event) { */ private void performDrag(MotionEvent event) { + mLastGesture = ChartGesture.DRAG; + mMatrix.set(mSavedMatrix); OnChartGestureListener l = mChart.getOnChartGestureListener(); @@ -301,6 +311,8 @@ private void performZoom(MotionEvent event) { // mode if (mTouchMode == PINCH_ZOOM) { + mLastGesture = ChartGesture.PINCH_ZOOM; + float scale = totalDist / mSavedDist; // total scale boolean isZoomingOut = (scale < 1); @@ -322,6 +334,8 @@ private void performZoom(MotionEvent event) { } else if (mTouchMode == X_ZOOM && mChart.isScaleXEnabled()) { + mLastGesture = ChartGesture.X_ZOOM; + float xDist = getXDist(event); float scaleX = xDist / mSavedXDist; // x-axis scale @@ -341,6 +355,8 @@ private void performZoom(MotionEvent event) { } else if (mTouchMode == Y_ZOOM && mChart.isScaleYEnabled()) { + mLastGesture = ChartGesture.Y_ZOOM; + float yDist = getYDist(event); float scaleY = yDist / mSavedYDist; // y-axis scale @@ -486,6 +502,8 @@ public Matrix getMatrix() { @Override public boolean onDoubleTap(MotionEvent e) { + mLastGesture = ChartGesture.DOUBLE_TAP; + OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { @@ -511,6 +529,8 @@ public boolean onDoubleTap(MotionEvent e) { @Override public void onLongPress(MotionEvent e) { + mLastGesture = ChartGesture.LONG_PRESS; + OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { @@ -524,11 +544,7 @@ public boolean onSingleTapUp(MotionEvent e) { performHighlight(e); - return super.onSingleTapUp(e); - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent e) { + mLastGesture = ChartGesture.SINGLE_TAP; OnChartGestureListener l = mChart.getOnChartGestureListener(); @@ -536,16 +552,34 @@ public boolean onSingleTapConfirmed(MotionEvent e) { l.onChartSingleTapped(e); } - return super.onSingleTapConfirmed(e); + return super.onSingleTapUp(e); } +// @Override +// public boolean onSingleTapConfirmed(MotionEvent e) { +// +// mLastGesture = ChartGesture.SINGLE_TAP; +// +// OnChartGestureListener l = mChart.getOnChartGestureListener(); +// +// if (l != null) { +// l.onChartSingleTapped(e); +// l.onChartGestureEnd(e, mLastGesture); +// } +// +// return super.onSingleTapConfirmed(e); +// } + @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + mLastGesture = ChartGesture.FLING; + OnChartGestureListener l = mChart.getOnChartGestureListener(); - if (l != null) + if (l != null) { l.onChartFling(e1, e2, velocityX, velocityY); + } return super.onFling(e1, e2, velocityX, velocityY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java index 03c8cba32c..f5aadcf060 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -12,6 +12,15 @@ */ public abstract class ChartTouchListener> extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { + public enum ChartGesture { + NONE, DRAG, X_ZOOM, Y_ZOOM, PINCH_ZOOM, ROTATE, SINGLE_TAP, DOUBLE_TAP, LONG_PRESS, FLING + } + + /** + * the last touch gesture that has been performed + **/ + protected ChartGesture mLastGesture = ChartGesture.NONE; + // states protected static final int NONE = 0; protected static final int DRAG = 1; @@ -47,26 +56,30 @@ public ChartTouchListener(T chart) { mGestureDetector = new GestureDetector(chart.getContext(), this); } - @Override - public boolean onTouch(View v, MotionEvent event) { + /** + * Calls the OnChartGestureListener to do the start callback + * + * @param me + */ + public void startAction(MotionEvent me) { OnChartGestureListener l = mChart.getOnChartGestureListener(); - if (l != null) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - l.onChartGestureStart(event); - break; - case MotionEvent.ACTION_CANCEL: - l.onChartGestureEnd(event); - break; - case MotionEvent.ACTION_UP: - l.onChartGestureEnd(event); - break; - } - } - - return false; + if (l != null) + l.onChartGestureStart(me, mLastGesture); + } + + /** + * Calls the OnChartGestureListener to do the end callback + * + * @param me + */ + public void endAction(MotionEvent me) { + + OnChartGestureListener l = mChart.getOnChartGestureListener(); + + if (l != null) + l.onChartGestureEnd(me, mLastGesture); } /** @@ -87,6 +100,15 @@ public int getTouchMode() { return mTouchMode; } + /** + * Returns the last gesture that has been performed on the chart. + * + * @return + */ + public ChartGesture getLastGesture() { + return mLastGesture; + } + /** * returns the distance between two points * diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java index f984395b19..a17cdde941 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/OnChartGestureListener.java @@ -13,15 +13,17 @@ public interface OnChartGestureListener { * Callbacks when a touch-gesture has started on the chart (ACTION_DOWN) * * @param me + * @param lastPerformedGesture */ - void onChartGestureStart(MotionEvent me); + void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture); /** * Callbacks when a touch-gesture has ended on the chart (ACTION_UP, ACTION_CANCEL) * * @param me + * @param lastPerformedGesture */ - void onChartGestureEnd(MotionEvent me); + void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture); /** * Callbacks when the chart is longpressed. diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index f7b92f5932..b3b6d586b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -41,7 +41,6 @@ public PieRadarChartTouchListener(PieRadarChartBase chart) { @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouch(View v, MotionEvent event) { - super.onTouch(v, event); if (mGestureDetector.onTouchEvent(event)) return true; @@ -56,6 +55,8 @@ public boolean onTouch(View v, MotionEvent event) { case MotionEvent.ACTION_DOWN: + startAction(event); + stopDeceleration(); resetVelocity(); @@ -76,6 +77,7 @@ public boolean onTouch(View v, MotionEvent event) { if (mTouchMode == NONE && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) > Utils.convertDpToPixel(8f)) { + mLastGesture = ChartGesture.ROTATE; mTouchMode = ROTATE; mChart.disableScroll(); } else if (mTouchMode == ROTATE) { @@ -83,6 +85,8 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) mChart.invalidate(); } + endAction(event); + break; case MotionEvent.ACTION_UP: @@ -104,6 +108,8 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) mChart.enableScroll(); mTouchMode = NONE; + endAction(event); + break; } } @@ -113,6 +119,9 @@ && distance(x, mTouchStartPoint.x, y, mTouchStartPoint.y) @Override public void onLongPress(MotionEvent me) { + + mLastGesture = ChartGesture.LONG_PRESS; + OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { @@ -128,6 +137,8 @@ public boolean onSingleTapConfirmed(MotionEvent e) { @Override public boolean onSingleTapUp(MotionEvent e) { + mLastGesture = ChartGesture.SINGLE_TAP; + OnChartGestureListener l = mChart.getOnChartGestureListener(); if (l != null) { From 92ea5b3892b559c9649e01efb4ea90fe071ae46d Mon Sep 17 00:00:00 2001 From: Christian De Angelis Date: Mon, 5 Oct 2015 13:43:39 -0700 Subject: [PATCH 0508/1390] Fix disappearing line when zooming into LineChart --- .../charting/renderer/LineChartRenderer.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 913ed47fba..086555af53 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -138,8 +138,10 @@ protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int maxx = Math.min(Math.max( + minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -289,8 +291,10 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int maxx = Math.min(Math.max( + minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); int range = (maxx - minx) * 4 - 4; @@ -430,8 +434,10 @@ public void drawValues(Canvas c) { Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int maxx = Math.min(Math.max( + minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); float[] positions = trans.generateTransformedValuesLine( entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -485,8 +491,10 @@ protected void drawCircles(Canvas c) { Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int diff = (entryFrom == entryTo) ? 1 : 0; + int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int maxx = Math.min(Math.max( + minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); CircleBuffer buffer = mCircleBuffers[i]; buffer.setPhases(phaseX, phaseY); From cd04e50cb42e9de748138dafb8c591b3fa8f3219 Mon Sep 17 00:00:00 2001 From: George Lin Date: Tue, 6 Oct 2015 13:36:14 +0800 Subject: [PATCH 0509/1390] Release Bitmap in LineChartRenderer and PieChartRenderer to avoid OOM issues --- .../github/mikephil/charting/charts/LineChart.java | 6 ++++++ .../com/github/mikephil/charting/charts/PieChart.java | 6 ++++++ .../mikephil/charting/renderer/LineChartRenderer.java | 11 +++++++++++ .../mikephil/charting/renderer/PieChartRenderer.java | 11 +++++++++++ 4 files changed, 34 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index e04859fe50..ff632a2483 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -46,4 +46,10 @@ protected void calcMinMax() { public LineData getLineData() { return mData; } + + @Override protected void onDetachedFromWindow() { + // releases the bitmap in the renderer to avoid oom error + ((LineChartRenderer) mRenderer).releaseBitmap(); + super.onDetachedFromWindow(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 554d114236..ae8634aef0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -203,6 +203,12 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { return new float[]{x, y}; } + @Override protected void onDetachedFromWindow() { + // releases the bitmap in the renderer to avoid oom error + ((PieChartRenderer) mRenderer).releaseBitmap(); + super.onDetachedFromWindow(); + } + /** * calculates the needed angles for the chart slices */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 913ed47fba..92d935bd7e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.CircleBuffer; import com.github.mikephil.charting.buffer.LineBuffer; +import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; @@ -101,6 +102,16 @@ public void drawData(Canvas c) { c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } + /** + * Releases bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. + */ + public void releaseBitmap() { + if (mDrawBitmap != null) { + mDrawBitmap.recycle(); + mDrawBitmap = null; + } + } + protected void drawDataSet(Canvas c, LineDataSet dataSet) { List entries = dataSet.getYVals(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 5766bd3371..154754e400 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -14,6 +14,7 @@ import android.text.TextPaint; import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; @@ -123,6 +124,16 @@ public void drawData(Canvas c) { } } + /** + * Releases bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. + */ + public void releaseBitmap() { + if (mDrawBitmap != null) { + mDrawBitmap.recycle(); + mDrawBitmap = null; + } + } + protected void drawDataSet(Canvas c, PieDataSet dataSet) { float angle = mChart.getRotationAngle(); From 764ed2fd2791dfbcd82b9544ea52ead9e18b260e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 6 Oct 2015 09:11:51 +0200 Subject: [PATCH 0510/1390] Update docs. --- .../charting/charts/BarLineChartBase.java | 199 ++++++++++-------- 1 file changed, 109 insertions(+), 90 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 70c54ca7e4..6dc9067abb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -38,17 +38,21 @@ /** * Base-class of LineChart, BarChart, ScatterChart and CandleStickChart. - * + * * @author Philipp Jahoda */ @SuppressLint("RtlHardcoded") public abstract class BarLineChartBase>> extends Chart implements BarLineScatterCandleBubbleDataProvider { - /** the maximum number of entried to which values will be drawn */ + /** + * the maximum number of entried to which values will be drawn + */ protected int mMaxVisibleCount = 100; - /** flag that indicates if auto scaling on the y axis is enabled */ + /** + * flag that indicates if auto scaling on the y axis is enabled + */ private boolean mAutoScaleMinMaxEnabled = false; private Integer mAutoScaleLastLowestVisibleXIndex = null; private Integer mAutoScaleLastHighestVisibleXIndex = null; @@ -60,7 +64,9 @@ public abstract class BarLineChartBase= 0.0) { + } else if (minLeft >= 0.0) { // We have positive values only, stay in the positive zone mAxisLeft.mAxisMinimum = 0.f; mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } - else { + } else { // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) mAxisLeft.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft)); mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); } - } - else { + } else { // Use the values as they are mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); @@ -390,19 +407,16 @@ else if (minLeft >= 0.0) { // If the values are all negative, let's stay in the negative zone mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); mAxisRight.mAxisMaximum = 0.f; - } - else if (minRight >= 0.f) { + } else if (minRight >= 0.f) { // We have positive values only, stay in the positive zone mAxisRight.mAxisMinimum = 0.f; mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); - } - else { + } else { // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); } - } - else { + } else { mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight); mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight); } @@ -558,15 +572,15 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { int setCount = mData.getDataSetCount(); int i = e.getXIndex(); - if(this instanceof HorizontalBarChart) { + if (this instanceof HorizontalBarChart) { // calculate the x-position, depending on datasetcount - float y = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f ; + float y = i + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; yPos = y; BarEntry entry = (BarEntry) e; - if(entry.getVals() != null) { + if (entry.getVals() != null) { xPos = highlight.getRange().to; } else { xPos = e.getVal(); @@ -580,7 +594,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { xPos = x; BarEntry entry = (BarEntry) e; - if(entry.getVals() != null) { + if (entry.getVals() != null) { yPos = highlight.getRange().to; } else { yPos = e.getVal(); @@ -593,7 +607,7 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { } // position of the marker depends on selected value index and value - float[] pts = new float[] { + float[] pts = new float[]{ xPos, yPos }; @@ -693,7 +707,7 @@ public void zoomOut() { /** * Zooms in or out by the given scale factor. x and y are the coordinates * (in pixels) of the zoom center. - * + * * @param scaleX if < 1f --> zoom out, if > 1f --> zoom in * @param scaleY if < 1f --> zoom out, if > 1f --> zoom in * @param x @@ -728,7 +742,7 @@ public void fitScreen() { /** * Sets the minimum scale factor value to which can be zoomed out. 1f = * fitScreen - * + * * @param scaleX * @param scaleY */ @@ -742,7 +756,7 @@ public void setScaleMinima(float scaleX, float scaleY) { * visible at once (no further zooming out allowed). If this is e.g. set to * 10, no more than 10 values on the x-axis can be viewed at once without * scrolling. - * + * * @param maxXRange The maximum visible range of x-values. */ public void setVisibleXRangeMaximum(float maxXRange) { @@ -755,7 +769,7 @@ public void setVisibleXRangeMaximum(float maxXRange) { * visible at once (no further zooming in allowed). If this is e.g. set to * 10, no more than 10 values on the x-axis can be viewed at once without * scrolling. - * + * * @param minXRange The minimum visible range of x-values. */ public void setVisibleXRangeMinimum(float minXRange) { @@ -768,7 +782,7 @@ public void setVisibleXRangeMinimum(float minXRange) { * pinching and zooming. e.g. minRange=10, maxRange=100 no less than 10 * values and no more that 100 values can be viewed at once without * scrolling - * + * * @param minXRange * @param maxXRange */ @@ -781,9 +795,9 @@ public void setVisibleXRange(float minXRange, float maxXRange) { /** * Sets the size of the area (range on the y-axis) that should be maximum * visible at once. - * + * * @param maxYRange the maximum visible range on the y-axis - * @param axis - the axis for which this limit should apply + * @param axis - the axis for which this limit should apply */ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { float yScale = getDeltaY(axis) / maxYRange; @@ -793,7 +807,7 @@ public void setVisibleYRangeMaximum(float maxYRange, AxisDependency axis) { /** * Moves the left side of the current viewport to the specified x-index. * This also refreshes the chart by calling invalidate(). - * + * * @param xIndex */ public void moveViewToX(float xIndex) { @@ -811,9 +825,9 @@ public void moveViewToX(float xIndex) { /** * Centers the viewport to the specified y-value on the y-axis. * This also refreshes the chart by calling invalidate(). - * + * * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the y-axis */ public void moveViewToY(float yValue, AxisDependency axis) { @@ -834,10 +848,10 @@ public void moveViewToY(float yValue, AxisDependency axis) { * x-index on the x-axis, and center the viewport to the specified y-value * on the y-axis. * This also refreshes the chart by calling invalidate(). - * + * * @param xIndex * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the y-axis */ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { @@ -860,7 +874,7 @@ public void moveViewTo(float xIndex, float yValue, AxisDependency axis) { * * @param xIndex * @param yValue - * @param axis - which axis should be used as a reference for the y-axis + * @param axis - which axis should be used as a reference for the y-axis */ public void centerViewTo(int xIndex, float yValue, AxisDependency axis) { @@ -878,7 +892,9 @@ public void centerViewTo(int xIndex, float yValue, AxisDependency axis) { } } - /** flag that indicates if a custom viewport offset has been set */ + /** + * flag that indicates if a custom viewport offset has been set + */ private boolean mCustomViewPortEnabled = false; /** @@ -887,14 +903,14 @@ public void centerViewTo(int xIndex, float yValue, AxisDependency axis) { * automatically calculating it's offsets. Use resetViewPortOffsets() to * undo this. ONLY USE THIS WHEN YOU KNOW WHAT YOU ARE DOING, else use * setExtraOffsets(...). - * + * * @param left * @param top * @param right * @param bottom */ public void setViewPortOffsets(final float left, final float top, - final float right, final float bottom) { + final float right, final float bottom) { mCustomViewPortEnabled = true; post(new Runnable() { @@ -925,7 +941,7 @@ public void resetViewPortOffsets() { /** * Returns the delta-y value (y-value range) of the specified axis. - * + * * @param axis * @return */ @@ -938,7 +954,7 @@ public float getDeltaY(AxisDependency axis) { /** * Sets the OnDrawListener - * + * * @param drawListener */ public void setOnDrawListener(OnDrawListener drawListener) { @@ -947,7 +963,7 @@ public void setOnDrawListener(OnDrawListener drawListener) { /** * Gets the OnDrawListener. May be null. - * + * * @return */ public OnDrawListener getDrawListener() { @@ -957,7 +973,7 @@ public OnDrawListener getDrawListener() { /** * Returns the position (in pixels) the provided Entry has inside the chart * view or null, if the provided Entry is null. - * + * * @param e * @return */ @@ -966,7 +982,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { if (e == null) return null; - float[] vals = new float[] { + float[] vals = new float[]{ e.getXIndex(), e.getVal() }; @@ -978,7 +994,7 @@ public PointF getPosition(Entry e, AxisDependency axis) { /** * sets the number of maximum visible drawn values on the chart only active * when setDrawValues() is enabled - * + * * @param count */ public void setMaxVisibleValueCount(int count) { @@ -992,7 +1008,7 @@ public int getMaxVisibleCount() { /** * Set this to true to allow highlighting per dragging over the chart * surface when it is fully zoomed out. Default: true - * + * * @param enabled */ public void setHighlightPerDragEnabled(boolean enabled) { @@ -1006,7 +1022,7 @@ public boolean isHighlightPerDragEnabled() { /** * Sets the color for the background of the chart-drawing area (everything * behind the grid lines). - * + * * @param color */ public void setGridBackgroundColor(int color) { @@ -1016,7 +1032,7 @@ public void setGridBackgroundColor(int color) { /** * Set this to true to enable dragging (moving the chart with the finger) * for the chart (this does not effect scaling). - * + * * @param enabled */ public void setDragEnabled(boolean enabled) { @@ -1025,7 +1041,7 @@ public void setDragEnabled(boolean enabled) { /** * Returns true if dragging is enabled for the chart, false if not. - * + * * @return */ public boolean isDragEnabled() { @@ -1035,7 +1051,7 @@ public boolean isDragEnabled() { /** * Set this to true to enable scaling (zooming in and out by gesture) for * the chart (this does not effect dragging) on both X- and Y-Axis. - * + * * @param enabled */ public void setScaleEnabled(boolean enabled) { @@ -1062,7 +1078,7 @@ public boolean isScaleYEnabled() { /** * Set this to true to enable zooming in by double-tap on the chart. * Default: enabled - * + * * @param enabled */ public void setDoubleTapToZoomEnabled(boolean enabled) { @@ -1071,7 +1087,7 @@ public void setDoubleTapToZoomEnabled(boolean enabled) { /** * Returns true if zooming via double-tap is enabled false if not. - * + * * @return */ public boolean isDoubleTapToZoomEnabled() { @@ -1080,7 +1096,7 @@ public boolean isDoubleTapToZoomEnabled() { /** * set this to true to draw the grid background, false if not - * + * * @param enabled */ public void setDrawGridBackground(boolean enabled) { @@ -1090,7 +1106,7 @@ public void setDrawGridBackground(boolean enabled) { /** * Sets drawing the borders rectangle to true. If this is enabled, there is * no point drawing the axis-lines of x- and y-axis. - * + * * @param enabled */ public void setDrawBorders(boolean enabled) { @@ -1099,7 +1115,7 @@ public void setDrawBorders(boolean enabled) { /** * Sets the width of the border lines in dp. - * + * * @param width */ public void setBorderWidth(float width) { @@ -1108,7 +1124,7 @@ public void setBorderWidth(float width) { /** * Sets the color of the chart border lines. - * + * * @param color */ public void setBorderColor(int color) { @@ -1119,7 +1135,7 @@ public void setBorderColor(int color) { * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or * CandleStick-Chart. - * + * * @param x * @param y * @return @@ -1138,7 +1154,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { * (encapsulated in a PointD). This method transforms pixel coordinates to * coordinates / values in the chart. This is the opposite method to * getPixelsForValues(...). - * + * * @param x * @param y * @return @@ -1161,14 +1177,14 @@ public PointD getValuesByTouchPoint(float x, float y, AxisDependency axis) { /** * Transforms the given chart values into pixels. This is the opposite * method to getValuesByTouchPoint(...). - * + * * @param x * @param y * @return */ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { - float[] pts = new float[] { + float[] pts = new float[]{ x, y }; @@ -1180,7 +1196,7 @@ public PointD getPixelsForValues(float x, float y, AxisDependency axis) { /** * returns the y-value at the given touch position (must not necessarily be * a value contained in one of the datasets) - * + * * @param x * @param y * @return @@ -1191,7 +1207,7 @@ public float getYValueByTouchPoint(float x, float y, AxisDependency axis) { /** * returns the Entry object displayed at the touched position of the chart - * + * * @param x * @param y * @return @@ -1206,7 +1222,7 @@ public Entry getEntryByTouchPoint(float x, float y) { /** * returns the DataSet object displayed at the touched position of the chart - * + * * @param x * @param y * @return @@ -1222,12 +1238,12 @@ public BarLineScatterCandleBubbleDataSet getDataSetByTouchPoint /** * Returns the lowest x-index (value on the x-axis) that is still visible on * the chart. - * + * * @return */ @Override public int getLowestVisibleXIndex() { - float[] pts = new float[] { + float[] pts = new float[]{ mViewPortHandler.contentLeft(), mViewPortHandler.contentBottom() }; getTransformer(AxisDependency.LEFT).pixelsToValue(pts); @@ -1237,12 +1253,12 @@ public int getLowestVisibleXIndex() { /** * Returns the highest x-index (value on the x-axis) that is still visible * on the chart. - * + * * @return */ @Override public int getHighestVisibleXIndex() { - float[] pts = new float[] { + float[] pts = new float[]{ mViewPortHandler.contentRight(), mViewPortHandler.contentBottom() }; getTransformer(AxisDependency.LEFT).pixelsToValue(pts); @@ -1271,7 +1287,7 @@ public float getScaleY() { /** * if the chart is fully zoomed out, return true - * + * * @return */ public boolean isFullyZoomedOut() { @@ -1281,7 +1297,7 @@ public boolean isFullyZoomedOut() { /** * Returns the left y-axis object. In the horizontal bar-chart, this is the * top axis. - * + * * @return */ public YAxis getAxisLeft() { @@ -1291,7 +1307,7 @@ public YAxis getAxisLeft() { /** * Returns the right y-axis object. In the horizontal bar-chart, this is the * bottom axis. - * + * * @return */ public YAxis getAxisRight() { @@ -1301,7 +1317,7 @@ public YAxis getAxisRight() { /** * Returns the y-axis object to the corresponding AxisDependency. In the * horizontal bar-chart, LEFT == top, RIGHT == BOTTOM - * + * * @param axis * @return */ @@ -1321,7 +1337,7 @@ public boolean isInverted(AxisDependency axis) { * Returns the object representing all x-labels, this method can be used to * acquire the XAxis object and modify it (e.g. change the position of the * labels) - * + * * @return */ public XAxis getXAxis() { @@ -1331,7 +1347,7 @@ public XAxis getXAxis() { /** * Enables data filtering for the chart data, filtering will use the user * customized Approximator handed over to this method. - * + * * @param a */ public void enableFiltering(Approximator a) { @@ -1348,7 +1364,7 @@ public void disableFiltering() { /** * returns true if data filtering is enabled, false if not - * + * * @return */ public boolean isFilteringEnabled() { @@ -1356,9 +1372,9 @@ public boolean isFilteringEnabled() { } /** - * if set to true, both x and y axis can be scaled with 2 fingers, if false, + * If set to true, both x and y axis can be scaled simultaneously with 2 fingers, if false, * x and y axis can be scaled separately. default: false - * + * * @param enabled */ public void setPinchZoom(boolean enabled) { @@ -1367,7 +1383,7 @@ public void setPinchZoom(boolean enabled) { /** * returns true if pinch-zoom is enabled, false if not - * + * * @return */ public boolean isPinchZoomEnabled() { @@ -1377,7 +1393,7 @@ public boolean isPinchZoomEnabled() { /** * Set an offset in dp that allows the user to drag the chart over it's * bounds on the x-axis. - * + * * @param offset */ public void setDragOffsetX(float offset) { @@ -1387,7 +1403,7 @@ public void setDragOffsetX(float offset) { /** * Set an offset in dp that allows the user to drag the chart over it's * bounds on the y-axis. - * + * * @param offset */ public void setDragOffsetY(float offset) { @@ -1396,7 +1412,7 @@ public void setDragOffsetY(float offset) { /** * Returns true if both drag offsets (x and y) are zero or smaller. - * + * * @return */ public boolean hasNoDragOffset() { @@ -1409,6 +1425,7 @@ public XAxisRenderer getRendererXAxis() { /** * Sets a custom XAxisRenderer and overrides the existing (default) one. + * * @param xAxisRenderer */ public void setXAxisRenderer(XAxisRenderer xAxisRenderer) { @@ -1421,6 +1438,7 @@ public YAxisRenderer getRendererLeftYAxis() { /** * Sets a custom axis renderer for the left axis and overwrites the existing one. + * * @param rendererLeftYAxis */ public void setRendererLeftYAxis(YAxisRenderer rendererLeftYAxis) { @@ -1433,6 +1451,7 @@ public YAxisRenderer getRendererRightYAxis() { /** * Sets a custom axis renderer for the right acis and overwrites the existing one. + * * @param rendererRightYAxis */ public void setRendererRightYAxis(YAxisRenderer rendererRightYAxis) { @@ -1449,7 +1468,7 @@ public float getYChartMin() { /** * Returns true if either the left or the right or both axes are inverted. - * + * * @return */ public boolean isAnyAxisInverted() { @@ -1463,18 +1482,18 @@ public boolean isAnyAxisInverted() { /** * Flag that indicates if auto scaling on the y axis is enabled. This is * especially interesting for charts displaying financial data. - * + * * @param enabled the y axis automatically adjusts to the min and max y - * values of the current x axis range whenever the viewport - * changes + * values of the current x axis range whenever the viewport + * changes */ public void setAutoScaleMinMaxEnabled(boolean enabled) { mAutoScaleMinMaxEnabled = enabled; } /** - * @default false * @return true if auto scaling on the y axis is enabled. + * @default false */ public boolean isAutoScaleMinMaxEnabled() { return mAutoScaleMinMaxEnabled; From eae7df48a06cb977138af22b7406918d6b50c1e6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 6 Oct 2015 17:12:08 +0200 Subject: [PATCH 0511/1390] Add docs. --- .../com/github/mikephil/charting/renderer/LineChartRenderer.java | 1 + 1 file changed, 1 insertion(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 16cad40b72..ad62a0980a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -357,6 +357,7 @@ protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries /** * Draws the provided path in filled mode with the provided color and alpha. + * Special thanks to Angelo Suzuki (https://github.com/tinsukE) for this. * * @param c * @param filledPath From 0e379d31c1e277f46135f9bdaf907cee0455138a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 6 Oct 2015 17:37:59 +0200 Subject: [PATCH 0512/1390] Fix #1066 --- .../MultiLineChartActivity.java | 10 +++- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/Chart.java | 31 ++++++------ .../mikephil/charting/charts/PieChart.java | 14 +++--- .../mikephil/charting/charts/RadarChart.java | 2 +- .../listener/PieRadarChartTouchListener.java | 50 ++++++++----------- 6 files changed, 54 insertions(+), 55 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 95f5a3cbcb..81d1505fcf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -54,8 +54,14 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setDescription(""); - - // mChart.setStartAtZero(true); + mChart.setDrawBorders(false); + + mChart.getAxisLeft().setDrawAxisLine(false); + mChart.getAxisLeft().setDrawGridLines(false); + mChart.getAxisRight().setDrawAxisLine(false); + mChart.getAxisRight().setDrawGridLines(false); + mChart.getXAxis().setDrawAxisLine(false); + mChart.getXAxis().setDrawGridLines(false); // enable value highlighting mChart.setHighlightEnabled(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 6dc9067abb..713ed0fc62 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -257,7 +257,7 @@ protected void onDraw(Canvas canvas) { // if highlighting is enabled if (valuesToHighlight()) - mRenderer.drawHighlighted(canvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHighlight); // Removes clipping rectangle canvas.restoreToCount(clipRestoreCount); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f2c86c5160..5191d8c67f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -299,7 +299,7 @@ public void setData(T data) { public void clear() { mData = null; mDataNotSet = true; - mIndicesToHightlight = null; + mIndicesToHighlight = null; invalidate(); } @@ -441,7 +441,7 @@ protected void drawDescription(Canvas c) { * array of Highlight objects that reference the highlighted slices in the * chart */ - protected Highlight[] mIndicesToHightlight; + protected Highlight[] mIndicesToHighlight; /** * Returns the array of currently highlighted values. This might a null or @@ -450,7 +450,7 @@ protected void drawDescription(Canvas c) { * @return */ public Highlight[] getHighlighted() { - return mIndicesToHightlight; + return mIndicesToHighlight; } /** @@ -461,8 +461,8 @@ public Highlight[] getHighlighted() { * @return */ public boolean valuesToHighlight() { - return mIndicesToHightlight == null || mIndicesToHightlight.length <= 0 - || mIndicesToHightlight[0] == null ? false + return mIndicesToHighlight == null || mIndicesToHighlight.length <= 0 + || mIndicesToHighlight[0] == null ? false : true; } @@ -477,7 +477,7 @@ public boolean valuesToHighlight() { public void highlightValues(Highlight[] highs) { // set the indices to highlight - mIndicesToHightlight = highs; + mIndicesToHighlight = highs; if(highs == null || highs.length == 0) mChartTouchListener.setLastHighlighted(null); @@ -518,7 +518,7 @@ public void highlightTouch(Highlight high) { Entry e = null; if (high == null) - mIndicesToHightlight = null; + mIndicesToHighlight = null; else { if (mLogEnabled) @@ -526,20 +526,17 @@ public void highlightTouch(Highlight high) { e = mData.getEntryForHighlight(high); if (e == null || e.getXIndex() != high.getXIndex()) { - mIndicesToHightlight = null; + mIndicesToHighlight = null; high = null; } else { // set the indices to highlight - mIndicesToHightlight = new Highlight[] { + mIndicesToHighlight = new Highlight[] { high }; } } - // redraw the chart - invalidate(); - if (mSelectionListener != null) { if (!valuesToHighlight()) @@ -549,6 +546,8 @@ public void highlightTouch(Highlight high) { mSelectionListener.onValueSelected(e, high.getDataSetIndex(), high); } } + // redraw the chart + invalidate(); } /** @@ -581,18 +580,18 @@ protected void drawMarkers(Canvas canvas) { if (mMarkerView == null || !mDrawMarkerViews || !valuesToHighlight()) return; - for (int i = 0; i < mIndicesToHightlight.length; i++) { + for (int i = 0; i < mIndicesToHighlight.length; i++) { - Highlight highlight = mIndicesToHightlight[i]; + Highlight highlight = mIndicesToHighlight[i]; int xIndex = highlight.getXIndex(); int dataSetIndex = highlight.getDataSetIndex(); if (xIndex <= mDeltaX && xIndex <= mDeltaX * mAnimator.getPhaseX()) { - Entry e = mData.getEntryForHighlight(mIndicesToHightlight[i]); + Entry e = mData.getEntryForHighlight(mIndicesToHighlight[i]); // make sure entry not null - if (e == null || e.getXIndex() != mIndicesToHightlight[i].getXIndex()) + if (e == null || e.getXIndex() != mIndicesToHighlight[i].getXIndex()) continue; float[] pos = getMarkerPosition(e, highlight); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 554d114236..96f76a4e88 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -119,7 +119,7 @@ protected void onDraw(Canvas canvas) { mRenderer.drawData(canvas); if (valuesToHighlight()) - mRenderer.drawHighlighted(canvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHighlight); mRenderer.drawExtras(canvas); @@ -250,11 +250,11 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { if (!valuesToHighlight() || dataSetIndex < 0) return false; - for (int i = 0; i < mIndicesToHightlight.length; i++) + for (int i = 0; i < mIndicesToHighlight.length; i++) // check if the xvalue for the given dataset needs highlight - if (mIndicesToHightlight[i].getXIndex() == xIndex - && mIndicesToHightlight[i].getDataSetIndex() == dataSetIndex) + if (mIndicesToHighlight[i].getXIndex() == xIndex + && mIndicesToHighlight[i].getDataSetIndex() == dataSetIndex) return true; return false; @@ -467,7 +467,7 @@ public void setCenterTextTypeface(Typeface t) { /** * Sets the size of the center text of the PieChart in dp. * - * @param size + * @param sizeDp */ public void setCenterTextSize(float sizeDp) { ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize( @@ -477,7 +477,7 @@ public void setCenterTextSize(float sizeDp) { /** * Sets the size of the center text of the PieChart in pixels. * - * @param size + * @param sizePixels */ public void setCenterTextSizePixels(float sizePixels) { ((PieChartRenderer) mRenderer).getPaintCenterText().setTextSize(sizePixels); @@ -496,7 +496,7 @@ public void setCenterTextColor(int color) { * sets the radius of the hole in the center of the piechart in percent of * the maximum radius (max = the radius of the whole chart), default 50% * - * @param size + * @param percent */ public void setHoleRadius(final float percent) { mHoleRadiusPercent = percent; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 077116cb7c..7de9699def 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -196,7 +196,7 @@ protected void onDraw(Canvas canvas) { mRenderer.drawData(canvas); if (valuesToHighlight()) - mRenderer.drawHighlighted(canvas, mIndicesToHightlight); + mRenderer.drawHighlighted(canvas, mIndicesToHighlight); mYAxisRenderer.renderAxisLabels(canvas); diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index b3b6d586b4..75f168e4d2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -19,14 +19,16 @@ /** * Touchlistener for the PieChart. - * + * * @author Philipp Jahoda */ public class PieRadarChartTouchListener extends ChartTouchListener> { private PointF mTouchStartPoint = new PointF(); - /** the angle where the dragging started */ + /** + * the angle where the dragging started + */ private float mStartAngle = 0f; private ArrayList _velocitySamples = new ArrayList(); @@ -151,7 +153,12 @@ public boolean onSingleTapUp(MotionEvent e) { if (distance > mChart.getRadius()) { // if no slice was touched, highlight nothing - mChart.highlightValues(null); + + if (mLastHighlighted == null) + mChart.highlightValues(null); // no listener callback + else + mChart.highlightTouch(null); // listener callback + mLastHighlighted = null; } else { @@ -218,16 +225,12 @@ private void sampleVelocity(float touchLocationX, float touchLocationY) { _velocitySamples.add(new AngularVelocitySample(currentTime, mChart.getAngleForPoint(touchLocationX, touchLocationY))); // Remove samples older than our sample time - 1 seconds - for (int i = 0, count = _velocitySamples.size(); i < count - 2; i++) - { - if (currentTime - _velocitySamples.get(i).time > 1000) - { + for (int i = 0, count = _velocitySamples.size(); i < count - 2; i++) { + if (currentTime - _velocitySamples.get(i).time > 1000) { _velocitySamples.remove(0); i--; count--; - } - else - { + } else { break; } } @@ -243,37 +246,30 @@ private float calculateVelocity() { // Look for a sample that's closest to the latest sample, but not the same, so we can deduce the direction AngularVelocitySample beforeLastSample = firstSample; - for (int i = _velocitySamples.size() - 1; i >= 0; i--) - { + for (int i = _velocitySamples.size() - 1; i >= 0; i--) { beforeLastSample = _velocitySamples.get(i); - if (beforeLastSample.angle != lastSample.angle) - { + if (beforeLastSample.angle != lastSample.angle) { break; } } // Calculate the sampling time float timeDelta = (lastSample.time - firstSample.time) / 1000.f; - if (timeDelta == 0.f) - { + if (timeDelta == 0.f) { timeDelta = 0.1f; } // Calculate clockwise/ccw by choosing two values that should be closest to each other, // so if the angles are two far from each other we know they are inverted "for sure" boolean clockwise = lastSample.angle >= beforeLastSample.angle; - if (Math.abs(lastSample.angle - beforeLastSample.angle) > 270.0) - { + if (Math.abs(lastSample.angle - beforeLastSample.angle) > 270.0) { clockwise = !clockwise; } // Now if the "gesture" is over a too big of an angle - then we know the angles are inverted, and we need to move them closer to each other from both sides of the 360.0 wrapping point - if (lastSample.angle - firstSample.angle > 180.0) - { + if (lastSample.angle - firstSample.angle > 180.0) { firstSample.angle += 360.0; - } - else if (firstSample.angle - lastSample.angle > 180.0) - { + } else if (firstSample.angle - lastSample.angle > 180.0) { lastSample.angle += 360.0; } @@ -281,8 +277,7 @@ else if (firstSample.angle - lastSample.angle > 180.0) float velocity = Math.abs((lastSample.angle - firstSample.angle) / timeDelta); // Direction? - if (!clockwise) - { + if (!clockwise) { velocity = -velocity; } @@ -327,7 +322,7 @@ public void computeScroll() { mDecelerationAngularVelocity *= mChart.getDragDecelerationFrictionCoef(); - final float timeInterval = (float)(currentTime - mDecelerationLastTime) / 1000.f; + final float timeInterval = (float) (currentTime - mDecelerationLastTime) / 1000.f; mChart.setRotationAngle(mChart.getRotationAngle() + mDecelerationAngularVelocity * timeInterval); @@ -344,8 +339,7 @@ private class AngularVelocitySample { public long time; public float angle; - public AngularVelocitySample(long time, float angle) - { + public AngularVelocitySample(long time, float angle) { this.time = time; this.angle = angle; } From 4c06674012d41ebb260ad4931ffe43c9d4fac67d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 6 Oct 2015 19:47:28 +0200 Subject: [PATCH 0513/1390] Minor adjustments to PR --- .../mikephil/charting/charts/LineChart.java | 7 +++++-- .../mikephil/charting/charts/PieChart.java | 17 ++++++++++------ .../charting/renderer/LineChartRenderer.java | 20 +++++++++---------- .../charting/renderer/PieChartRenderer.java | 20 +++++++++---------- .../charting/renderer/XAxisRenderer.java | 2 +- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index ff632a2483..55cac759e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -47,9 +47,12 @@ public LineData getLineData() { return mData; } - @Override protected void onDetachedFromWindow() { + @Override + protected void onDetachedFromWindow() { // releases the bitmap in the renderer to avoid oom error - ((LineChartRenderer) mRenderer).releaseBitmap(); + if(mRenderer != null && mRenderer instanceof LineChartRenderer) { + ((LineChartRenderer) mRenderer).releaseBitmap(); + } super.onDetachedFromWindow(); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 9b373dbc73..4866009606 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -203,12 +203,6 @@ protected float[] getMarkerPosition(Entry e, Highlight highlight) { return new float[]{x, y}; } - @Override protected void onDetachedFromWindow() { - // releases the bitmap in the renderer to avoid oom error - ((PieChartRenderer) mRenderer).releaseBitmap(); - super.onDetachedFromWindow(); - } - /** * calculates the needed angles for the chart slices */ @@ -637,4 +631,15 @@ public void setCenterTextRadiusPercent(float percent) { public float getCenterTextRadiusPercent() { return mCenterTextRadiusPercent; } + + + @Override + protected void onDetachedFromWindow() { + // releases the bitmap in the renderer to avoid oom error + if(mRenderer != null && mRenderer instanceof PieChartRenderer) { + ((PieChartRenderer) mRenderer).releaseBitmap(); + } + super.onDetachedFromWindow(); + } + } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 67bf108aab..147229cb82 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -104,16 +104,6 @@ public void drawData(Canvas c) { c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } - /** - * Releases bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. - */ - public void releaseBitmap() { - if (mDrawBitmap != null) { - mDrawBitmap.recycle(); - mDrawBitmap = null; - } - } - protected void drawDataSet(Canvas c, LineDataSet dataSet) { List entries = dataSet.getYVals(); @@ -585,4 +575,14 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { drawHighlightLines(c, pts, set); } } + + /** + * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. + */ + public void releaseBitmap() { + if (mDrawBitmap != null) { + mDrawBitmap.recycle(); + mDrawBitmap = null; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 154754e400..66e3621c5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -124,16 +124,6 @@ public void drawData(Canvas c) { } } - /** - * Releases bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. - */ - public void releaseBitmap() { - if (mDrawBitmap != null) { - mDrawBitmap.recycle(); - mDrawBitmap = null; - } - } - protected void drawDataSet(Canvas c, PieDataSet dataSet) { float angle = mChart.getRotationAngle(); @@ -488,4 +478,14 @@ protected void drawRoundedSlices(Canvas c) { angle += newangle * mAnimator.getPhaseX(); } } + + /** + * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. + */ + public void releaseBitmap() { + if (mDrawBitmap != null) { + mDrawBitmap.recycle(); + mDrawBitmap = null; + } + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 482c3e766e..fce5d7a42f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -41,7 +41,7 @@ public void computeAxis(float xValAverageLength, List xValues) { + mXAxis.getSpaceBetweenLabels()); for (int i = 0; i < max; i++) { - a.append("h"); + a.append('h'); } mXAxis.mLabelWidth = Utils.calcTextWidth(mAxisLabelPaint, a.toString()); From 01916b5a72ecb3a9168f2fff5c787da4fc9de3a2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 7 Oct 2015 21:45:18 +0200 Subject: [PATCH 0514/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 365fe8da2d..7106188228 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Remember: *It's all about the looks.* An **iOS** version of this library is now available, go check it out: [**ios-charts**](https://github.com/danielgindi/ios-charts) -Are you using this library? Add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/edit/master/Projects_using_MPAndroidChart.txt). +Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). Donations ----- From a277152d98334a03d99927fdcaec4e67b3becce4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 7 Oct 2015 21:46:04 +0200 Subject: [PATCH 0515/1390] Moved references and performance to wiki. --- Projects_using_MPAndroidChart.txt | 49 ------------------------------ performance.xlsx | Bin 42313 -> 0 bytes 2 files changed, 49 deletions(-) delete mode 100644 Projects_using_MPAndroidChart.txt delete mode 100644 performance.xlsx diff --git a/Projects_using_MPAndroidChart.txt b/Projects_using_MPAndroidChart.txt deleted file mode 100644 index ca64fb9c96..0000000000 --- a/Projects_using_MPAndroidChart.txt +++ /dev/null @@ -1,49 +0,0 @@ -References - -Blood Pressure Companion -https://play.google.com/store/apps/details?id=de.medando.bloodpressurecompanion - -Smoke Free - Stop smoking help -https://play.google.com/store/apps/details?id=com.portablepixels.smokefree - -Drivvo - Vehicle Management -https://play.google.com/store/apps/details?id=br.com.ctncardoso.ctncar - -Phone Addiction -https://play.google.com/store/apps/details?id=com.tutorialsface.phoneaddiction - -AS Sales Management -https://play.google.com/store/apps/details?id=com.armsoft.mtrade - -Notification Analyser -https://play.google.com/store/apps/details?id=com.tierep.notificationanalyser - -Bluetooth Terminal/Graphics -https://play.google.com/store/apps/details?id=com.emrctn.BluetoothGraphics - -HI - Health & Fitness Tracker - All-in-one Diet, Health & Fitness Tracker -https://play.google.com/store/apps/details?id=com.droidinfinity.healthplus - -БИТ.Лидер -https://play.google.com/store/apps/details?id=com.firstbit.bitlider - -My Expenses -https://play.google.com/store/apps/details?id=org.totschnig.myexpenses - -H-Files -https://play.google.com/store/apps/details?id=com.hconnect.hfiles&hl=en - -Яндекс Метрика для Android -https://play.google.com/store/apps/details?id=ru.vdmodule.androidmetrix - -Poker Manager -https://play.google.com/store/apps/details?id=com.pokermanagerpro - -Speaker Recognition -https://github.com/C-piace-il-C/Speaker_Recognition - -ExpenseDroid - Expense Manager -https://play.google.com/store/apps/details?id=com.tphoneix.avi.myapplication - -Live Tracking -https://play.google.com/store/apps/details?id=com.aorbegozo005.livetrack diff --git a/performance.xlsx b/performance.xlsx deleted file mode 100644 index 041d4fea4e748ac1f5efd0b4ca5f7707c6c2f3ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42313 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 L0+UbPA`lM%4?J+K From 9dde506afb4e74fa57110922a7a939932935b573 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 7 Oct 2015 22:48:03 +0200 Subject: [PATCH 0516/1390] Fix IOOB exception --- .../src/com/github/mikephil/charting/data/CandleDataSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index cbbc98c55b..67b41efe69 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -87,8 +87,8 @@ protected void calcMinMax(int start, int end) { mLastStart = start; mLastEnd = endValue; - mYMin = mYVals.get(start).getLow(); - mYMax = mYVals.get(start).getHigh(); + mYMin = start < mYVals.size() ? mYVals.get(start).getLow() : Float.MAX_VALUE; + mYMax = start < mYVals.size() ? mYVals.get(start).getHigh() : -Float.MAX_VALUE; for (int i = start + 1; i <= endValue; i++) { From 7e4151e86efdf5c933675ebe2f8d88e541fd78d6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 7 Oct 2015 22:51:45 +0200 Subject: [PATCH 0517/1390] Additional fix --- .../com/github/mikephil/charting/data/CandleDataSet.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 67b41efe69..3a7c4041ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -87,10 +87,10 @@ protected void calcMinMax(int start, int end) { mLastStart = start; mLastEnd = endValue; - mYMin = start < mYVals.size() ? mYVals.get(start).getLow() : Float.MAX_VALUE; - mYMax = start < mYVals.size() ? mYVals.get(start).getHigh() : -Float.MAX_VALUE; + mYMin = Float.MAX_VALUE; + mYMax = -Float.MAX_VALUE; - for (int i = start + 1; i <= endValue; i++) { + for (int i = start; i <= endValue; i++) { CandleEntry e = entries.get(i); From 78441499b82639f988cfbae423e9db1d9ad2fcf9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 8 Oct 2015 12:26:12 +0300 Subject: [PATCH 0518/1390] Make the XAxisRenderer more flexible It is now possible to overwrite drawing the line or label of the LimitLine --- .../charting/renderer/XAxisRenderer.java | 103 ++++++++++-------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index fce5d7a42f..7eb6fb5ad5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -112,7 +112,7 @@ public void renderAxisLine(Canvas c) { /** * draws the x-labels on the specified y-position - * + * * @param pos */ protected void drawLabels(Canvas c, float pos) { @@ -209,8 +209,7 @@ public void renderLimitLines(Canvas c) { if (limitLines == null || limitLines.size() <= 0) return; - float[] pts = new float[4]; - Path limitLinePath = new Path(); + float[] position = new float[2]; for (int i = 0; i < limitLines.size(); i++) { @@ -219,61 +218,75 @@ public void renderLimitLines(Canvas c) { if(!l.isEnabled()) continue; - pts[0] = l.getLimit(); - pts[2] = l.getLimit(); + position[0] = l.getLimit(); + position[1] = 0.f; - mTrans.pointValuesToPixel(pts); + mTrans.pointValuesToPixel(position); - pts[1] = mViewPortHandler.contentTop(); - pts[3] = mViewPortHandler.contentBottom(); + renderLimitLineLine(c, l, position); + renderLimitLineLabel(c, l, position, 2.f + l.getYOffset()); + } + } - limitLinePath.moveTo(pts[0], pts[1]); - limitLinePath.lineTo(pts[2], pts[3]); + float[] mLimitLineSegmentsBuffer = new float[4]; + private Path mLimitLinePath = new Path(); - mLimitLinePaint.setStyle(Paint.Style.STROKE); - mLimitLinePaint.setColor(l.getLineColor()); - mLimitLinePaint.setStrokeWidth(l.getLineWidth()); - mLimitLinePaint.setPathEffect(l.getDashPathEffect()); + public void renderLimitLineLine(Canvas c, LimitLine limitLine, float[] position) + { + mLimitLineSegmentsBuffer[0] = position[0]; + mLimitLineSegmentsBuffer[1] = mViewPortHandler.contentTop(); + mLimitLineSegmentsBuffer[2] = position[0]; + mLimitLineSegmentsBuffer[3] = mViewPortHandler.contentBottom(); - c.drawPath(limitLinePath, mLimitLinePaint); - limitLinePath.reset(); + mLimitLinePath.reset(); + mLimitLinePath.moveTo(mLimitLineSegmentsBuffer[0], mLimitLineSegmentsBuffer[1]); + mLimitLinePath.lineTo(mLimitLineSegmentsBuffer[2], mLimitLineSegmentsBuffer[3]); - String label = l.getLabel(); + mLimitLinePaint.setStyle(Paint.Style.STROKE); + mLimitLinePaint.setColor(limitLine.getLineColor()); + mLimitLinePaint.setStrokeWidth(limitLine.getLineWidth()); + mLimitLinePaint.setPathEffect(limitLine.getDashPathEffect()); - // if drawing the limit-value label is enabled - if (label != null && !label.equals("")) { + c.drawPath(mLimitLinePath, mLimitLinePaint); + } - mLimitLinePaint.setStyle(l.getTextStyle()); - mLimitLinePaint.setPathEffect(null); - mLimitLinePaint.setColor(l.getTextColor()); - mLimitLinePaint.setStrokeWidth(0.5f); - mLimitLinePaint.setTextSize(l.getTextSize()); + public void renderLimitLineLabel(Canvas c, LimitLine limitLine, float[] position, float yOffset) + { + String label = limitLine.getLabel(); - float xOffset = l.getLineWidth() + l.getXOffset(); - float yOffset = Utils.convertDpToPixel(2f) + l.getYOffset(); + // if drawing the limit-value label is enabled + if (label != null && !label.equals("")) { - final LimitLine.LimitLabelPosition position = l.getLabelPosition(); + mLimitLinePaint.setStyle(limitLine.getTextStyle()); + mLimitLinePaint.setPathEffect(null); + mLimitLinePaint.setColor(limitLine.getTextColor()); + mLimitLinePaint.setStrokeWidth(0.5f); + mLimitLinePaint.setTextSize(limitLine.getTextSize()); - if (position == LimitLine.LimitLabelPosition.RIGHT_TOP) { + float xOffset = limitLine.getLineWidth() + limitLine.getXOffset(); - final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); - } else if (position == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + final LimitLine.LimitLabelPosition labelPosition = limitLine.getLabelPosition(); - mLimitLinePaint.setTextAlign(Align.LEFT); - c.drawText(label, pts[0] + xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); - } else if (position == LimitLine.LimitLabelPosition.LEFT_TOP) { + if (labelPosition == LimitLine.LimitLabelPosition.RIGHT_TOP) { - mLimitLinePaint.setTextAlign(Align.RIGHT); - final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); - c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); - } else { + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, position[0] + xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + } else if (labelPosition == LimitLine.LimitLabelPosition.RIGHT_BOTTOM) { + + mLimitLinePaint.setTextAlign(Align.LEFT); + c.drawText(label, position[0] + xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); + } else if (labelPosition == LimitLine.LimitLabelPosition.LEFT_TOP) { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + final float labelLineHeight = Utils.calcTextHeight(mLimitLinePaint, label); + c.drawText(label, position[0] - xOffset, mViewPortHandler.contentTop() + yOffset + labelLineHeight, mLimitLinePaint); + } else { + + mLimitLinePaint.setTextAlign(Align.RIGHT); + c.drawText(label, position[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); + } + } + } - mLimitLinePaint.setTextAlign(Align.RIGHT); - c.drawText(label, pts[0] - xOffset, mViewPortHandler.contentBottom() - yOffset, mLimitLinePaint); - } - } - } - } } From d1d590d48e290d81bfd4ffcc88d8c03ceb1e80c2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 9 Oct 2015 18:46:36 +0200 Subject: [PATCH 0519/1390] Fix PieChart offset issue #1092 --- .../mpchartexample/PieChartActivity.java | 1 + .../mikephil/charting/charts/PieChart.java | 21 ++++++------------- .../charting/charts/PieRadarChartBase.java | 7 ++----- 3 files changed, 9 insertions(+), 20 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 468f71e79a..43ade52662 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -217,6 +217,7 @@ private void setData(int count, float range) { colors.add(ColorTemplate.getHoloBlue()); dataSet.setColors(colors); + //dataSet.setSelectionShift(0f); PieData data = new PieData(xVals, dataSet); data.setValueFormatter(new PercentFormatter()); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 4866009606..e86a38bfe3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -143,25 +143,16 @@ public void calculateOffsets() { float diameter = getDiameter(); float radius = diameter / 2f; - PointF c = getCenterOffsets(); + PointF c = getCenter(); - final List dataSets = mData.getDataSets(); - - float maxShift = 0.f; - for (int i = 0; i < dataSets.size(); i++) { - final float shift = dataSets.get(i).getSelectionShift(); - if (shift > maxShift) - maxShift = shift; - } - - final float halfMaxShift = maxShift / 2.f; + float shift = mData.getDataSet().getSelectionShift(); // create the circle box that will contain the pie-chart (the bounds of // the pie-chart) - mCircleBox.set(c.x - radius + halfMaxShift, - c.y - radius + halfMaxShift, - c.x + radius - halfMaxShift, - c.y + radius - halfMaxShift); + mCircleBox.set(c.x - radius + shift, + c.y - radius + shift, + c.x + radius - shift, + c.y + radius - shift); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 1acc57aef9..c5ff63c7e8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -42,9 +42,6 @@ public abstract class PieRadarChartBase Date: Fri, 9 Oct 2015 18:53:27 +0200 Subject: [PATCH 0520/1390] Additional fix --- .../listviewitems/PieChartItem.java | 1 + .../notimportant/MainActivity.java | 36 +++++++------------ .../mikephil/charting/charts/PieChart.java | 2 +- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index a8e02c325d..f65c02e506 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -57,6 +57,7 @@ public View getView(int position, View convertView, Context c) { holder.chart.setCenterTextTypeface(mTf); holder.chart.setCenterTextSize(18f); holder.chart.setUsePercentValues(true); + holder.chart.setExtraOffsets(5, 10, 50, 10); mChartData.setValueFormatter(new PercentFormatter()); mChartData.setValueTypeface(mTf); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index c4d4599bde..f22a2ed3f7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -86,8 +86,6 @@ protected void onCreate(Bundle savedInstanceState) { "A line chart with multiple DataSet objects. One color per DataSet.")); objects.add(new ContentItem("Multiple Bars Chart", "A bar chart with multiple DataSet objects. One multiple colors per DataSet.")); - objects.add(new ContentItem("Draw Chart", - "Demonstration of drawing values into the chart per touch-gesture. With callbacks.")); objects.add(new ContentItem( "Charts in ViewPager Fragments", "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the chart.")); @@ -195,64 +193,54 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 13: - // i = new Intent(this, DrawChartActivity.class); - // startActivity(i); - - AlertDialog.Builder b = new AlertDialog.Builder(this); - b.setTitle("Feature not available"); - b.setMessage("Due to recent changes to the data model of the library, this feature is temporarily not available."); - b.setPositiveButton("OK", null); - b.create().show(); - break; - case 14: i = new Intent(this, SimpleChartDemo.class); startActivity(i); break; - case 15: + case 14: i = new Intent(this, ListViewBarChartActivity.class); startActivity(i); break; - case 16: + case 15: i = new Intent(this, ListViewMultiChartActivity.class); startActivity(i); break; - case 17: + case 16: i = new Intent(this, InvertedLineChartActivity.class); startActivity(i); break; - case 18: + case 17: i = new Intent(this, CandleStickChartActivity.class); startActivity(i); break; - case 19: + case 18: i = new Intent(this, CubicLineChartActivity.class); startActivity(i); break; - case 20: + case 19: i = new Intent(this, RadarChartActivitry.class); startActivity(i); break; - case 21: + case 20: i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 22: + case 21: i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; - case 23: + case 22: i = new Intent(this, DynamicalAddingActivity.class); startActivity(i); break; - case 24: + case 23: i = new Intent(this, PerformanceLineChart.class); startActivity(i); break; - case 25: + case 24: i = new Intent(this, BarChartActivitySinus.class); startActivity(i); break; - case 26: + case 25: i = new Intent(this, ScrollViewActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index e86a38bfe3..51956848a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -143,7 +143,7 @@ public void calculateOffsets() { float diameter = getDiameter(); float radius = diameter / 2f; - PointF c = getCenter(); + PointF c = getCenterOffsets(); float shift = mData.getDataSet().getSelectionShift(); From d15f2533368e78ef4c92afc1af0f6487dc8b6e96 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 10 Oct 2015 18:11:48 +0200 Subject: [PATCH 0521/1390] Work on supporting SpannableString for PieChart center text (#993). --- .../mpchartexample/PieChartActivity.java | 63 ++----- .../mikephil/charting/charts/PieChart.java | 48 +++-- .../charting/renderer/PieChartRenderer.java | 168 +++++++++--------- 3 files changed, 126 insertions(+), 153 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 43ade52662..8392f186d8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -4,6 +4,10 @@ import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; +import android.text.style.StyleSpan; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -58,12 +62,14 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (PieChart) findViewById(R.id.chart1); mChart.setUsePercentValues(true); mChart.setDescription(""); - + mChart.setExtraOffsets(5, 10, 5, 5); + mChart.setDragDecelerationFrictionCoef(0.95f); tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); mChart.setCenterTextTypeface(Typeface.createFromAsset(getAssets(), "OpenSans-Light.ttf")); + mChart.setCenterText(generateCenterSpannableText()); mChart.setDrawHoleEnabled(true); mChart.setHoleColorTransparent(true); @@ -86,8 +92,6 @@ protected void onCreate(Bundle savedInstanceState) { // add a selection listener mChart.setOnChartValueSelectedListener(this); - mChart.setCenterText("MPAndroidChart\nby Philipp Jahoda"); - setData(3, 100); mChart.animateY(1500, Easing.EasingOption.EaseInOutQuad); @@ -232,6 +236,17 @@ private void setData(int count, float range) { mChart.invalidate(); } + private SpannableString generateCenterSpannableText() { + + SpannableString s = new SpannableString("MPAndroidChart developed by Philipp Jahoda"); + s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); +// s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); +// s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); +// s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); +// s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); + return s; + } + @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { @@ -258,46 +273,4 @@ public void onStopTrackingTouch(SeekBar seekBar) { // TODO Auto-generated method stub } - - // private void removeLastEntry() { - // - // PieData data = mChart.getDataOriginal(); - // - // if (data != null) { - // - // PieDataSet set = data.getDataSet(); - // - // if (set != null) { - // - // Entry e = set.getEntryForXIndex(set.getEntryCount() - 1); - // - // data.removeEntry(e, 0); - // // or remove by index - // // mData.removeEntry(xIndex, dataSetIndex); - // - // mChart.notifyDataSetChanged(); - // mChart.invalidate(); - // } - // } - // } - // - // private void addEntry() { - // - // PieData data = mChart.getDataOriginal(); - // - // if (data != null) { - // - // PieDataSet set = data.getDataSet(); - // // set.addEntry(...); - // - // data.addEntry(new Entry((float) (Math.random() * 25) + 20f, - // set.getEntryCount()), 0); - // - // // let the chart know it's data has changed - // mChart.notifyDataSetChanged(); - // - // // redraw the chart - // mChart.invalidate(); - // } - // } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 51956848a8..adeb6954bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -9,6 +9,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; +import android.text.SpannableString; import android.util.AttributeSet; import com.github.mikephil.charting.data.DataSet; @@ -65,10 +66,9 @@ public class PieChart extends PieRadarChartBase { private boolean mDrawRoundedSlices = false; /** - * variable for the text that is drawn in the center of the pie-chart. If - * this value is null, the default is "Total Value\n + getYValueSum()" + * variable for the text that is drawn in the center of the pie-chart */ - private String mCenterText = ""; + private SpannableString mCenterText = new SpannableString(""); /** * indicates the size of the hole in the center of the piechart, default: @@ -86,8 +86,6 @@ public class PieChart extends PieRadarChartBase { */ private boolean mDrawCenterText = true; - private boolean mCenterTextWordWrapEnabled = false; - private float mCenterTextRadiusPercent = 1.f; public PieChart(Context context) { @@ -373,13 +371,25 @@ public boolean isDrawHoleEnabled() { } /** - * sets the text that is displayed in the center of the pie-chart. By - * default, the text is "Total Value + sumofallvalues" + * Sets the text SpannableString that is displayed in the center of the PieChart. + * + * @param text + */ + public void setCenterText(SpannableString text) { + + if (text == null) + mCenterText = new SpannableString(""); + else + mCenterText = text; + } + + /** + * Sets the text String that is displayed in the center of the PieChart. * * @param text */ public void setCenterText(String text) { - mCenterText = text; + setCenterText(new SpannableString(text)); } /** @@ -387,7 +397,7 @@ public void setCenterText(String text) { * * @return */ - public String getCenterText() { + public SpannableString getCenterText() { return mCenterText; } @@ -589,24 +599,6 @@ public boolean isUsePercentValuesEnabled() { return mUsePercentValues; } - /** - * should the center text be word wrapped? - * note that word wrapping takes a toll on performance - * if word wrapping is disabled, newlines are still respected - */ - public void setCenterTextWordWrapEnabled(boolean enabled) { - mCenterTextWordWrapEnabled = enabled; - } - - /** - * should the center text be word wrapped? - * note that word wrapping takes a toll on performance - * if word wrapping is disabled, newlines are still respected - */ - public boolean isCenterTextWordWrapEnabled() { - return mCenterTextWordWrapEnabled; - } - /** * the rectangular radius of the bounding box for the center text, as a percentage of the pie hole * default 1.f (100%) @@ -627,7 +619,7 @@ public float getCenterTextRadiusPercent() { @Override protected void onDetachedFromWindow() { // releases the bitmap in the renderer to avoid oom error - if(mRenderer != null && mRenderer instanceof PieChartRenderer) { + if (mRenderer != null && mRenderer instanceof PieChartRenderer) { ((PieChartRenderer) mRenderer).releaseBitmap(); } super.onDetachedFromWindow(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 66e3621c5a..9dfdb556e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -10,8 +10,10 @@ import android.graphics.PointF; import android.graphics.RectF; import android.text.Layout; +import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; +import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; @@ -44,17 +46,19 @@ public class PieChartRenderer extends DataRenderer { private TextPaint mCenterTextPaint; private StaticLayout mCenterTextLayout; - private String mCenterTextLastValue; + private SpannableString mCenterTextLastValue; private RectF mCenterTextLastBounds = new RectF(); - private RectF[] mRectBuffer = { new RectF(), new RectF(), new RectF() }; + private RectF[] mRectBuffer = {new RectF(), new RectF(), new RectF()}; - /** Bitmap for drawing the center hole */ + /** + * Bitmap for drawing the center hole + */ protected Bitmap mDrawBitmap; protected Canvas mBitmapCanvas; public PieChartRenderer(PieChart chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -92,7 +96,6 @@ public TextPaint getPaintCenterText() { @Override public void initBuffers() { // TODO Auto-generated method stub - } @Override @@ -210,7 +213,7 @@ public void drawValues(Canvas c) { * mAnimator.getPhaseY())) + center.x); float y = (float) (r * Math.sin(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) - * mAnimator.getPhaseY())) + center.y); + * mAnimator.getPhaseY())) + center.y); float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() / data.getYValueSum() * 100f : entry.getVal(); @@ -290,87 +293,92 @@ protected void drawHole(Canvas c) { */ protected void drawCenterText(Canvas c) { - String centerText = mChart.getCenterText(); + SpannableString centerText = mChart.getCenterText(); if (mChart.isDrawCenterTextEnabled() && centerText != null) { PointF center = mChart.getCenterCircleBox(); - if (mChart.isCenterTextWordWrapEnabled()) { - - float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); - - RectF holeRect = mRectBuffer[0]; - holeRect.left = center.x - innerRadius; - holeRect.top = center.y - innerRadius; - holeRect.right = center.x + innerRadius; - holeRect.bottom = center.y + innerRadius; - RectF boundingRect = mRectBuffer[1]; - boundingRect.set(holeRect); - - float radiusPercent = mChart.getCenterTextRadiusPercent(); - if (radiusPercent > 0.0) { - boundingRect.inset((boundingRect.width() - boundingRect.width() * radiusPercent) / 2.f, - (boundingRect.height() - boundingRect.height() * radiusPercent) / 2.f); - } - - if (!centerText.equals(mCenterTextLastValue) || !boundingRect.equals(mCenterTextLastBounds)) { - - // Next time we won't recalculate StaticLayout... - mCenterTextLastBounds.set(boundingRect); - mCenterTextLastValue = centerText; - - // If width is 0, it will crash. Always have a minimum of 1 - mCenterTextLayout = new StaticLayout(centerText, 0, centerText.length(), - mCenterTextPaint, - (int)Math.max(Math.ceil(mCenterTextLastBounds.width()), 1.f), - Layout.Alignment.ALIGN_NORMAL, 1.f, 0.f, false); - } - - // I wish we could make an ellipse clipping path on Android to clip to the hole... - // If we ever find out how, this is the place to add it, based on holeRect - - //float layoutWidth = Utils.getStaticLayoutMaxWidth(mCenterTextLayout); - float layoutHeight = mCenterTextLayout.getHeight(); + float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius(); - c.save(); - c.translate(boundingRect.centerX(), boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); - mCenterTextLayout.draw(c); - c.restore(); + RectF holeRect = mRectBuffer[0]; + holeRect.left = center.x - innerRadius; + holeRect.top = center.y - innerRadius; + holeRect.right = center.x + innerRadius; + holeRect.bottom = center.y + innerRadius; + RectF boundingRect = mRectBuffer[1]; + boundingRect.set(holeRect); - } else { - - // get all lines from the text - String[] lines = centerText.split("\n"); - - float maxlineheight = 0f; - - // calc the maximum line height - for (String line : lines) { - float curHeight = Utils.calcTextHeight(mCenterTextPaint, line); - if (curHeight > maxlineheight) - maxlineheight = curHeight; - } - - float linespacing = maxlineheight * 0.25f; - - float totalheight = maxlineheight * lines.length - linespacing * (lines.length - 1); - - int cnt = lines.length; + float radiusPercent = mChart.getCenterTextRadiusPercent(); + if (radiusPercent > 0.0) { + boundingRect.inset((boundingRect.width() - boundingRect.width() * radiusPercent) / 2.f, + (boundingRect.height() - boundingRect.height() * radiusPercent) / 2.f); + } - float y = center.y; + if (!centerText.equals(mCenterTextLastValue) || !boundingRect.equals(mCenterTextLastBounds)) { - for (int i = 0; i < lines.length; i++) { + // Next time we won't recalculate StaticLayout... + mCenterTextLastBounds.set(boundingRect); + mCenterTextLastValue = centerText; - String line = lines[lines.length - i - 1]; + float width = mCenterTextLastBounds.width(); - c.drawText(line, center.x, y - + maxlineheight * cnt - totalheight / 2f, - mCenterTextPaint); - cnt--; - y -= linespacing; - } + // If width is 0, it will crash. Always have a minimum of 1 + mCenterTextLayout = new StaticLayout(centerText, 0, centerText.length(), + mCenterTextPaint, + (int) Math.max(Math.ceil(width), 1.f), + Layout.Alignment.ALIGN_NORMAL, 1.f, 0.f, false); } + + // I wish we could make an ellipse clipping path on Android to clip to the hole... + // If we ever find out how, this is the place to add it, based on holeRect + + //float layoutWidth = Utils.getStaticLayoutMaxWidth(mCenterTextLayout); + float layoutHeight = mCenterTextLayout.getHeight(); + + c.save(); + c.translate(boundingRect.centerX(), boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); + mCenterTextLayout.draw(c); + c.restore(); + +// } +// +// else { +// +// +// // get all lines from the text +// String[] lines = centerText.toString().split("\n"); +// +// float maxlineheight = 0f; +// +// // calc the maximum line height +// for (String line : lines) { +// float curHeight = Utils.calcTextHeight(mCenterTextPaint, line); +// if (curHeight > maxlineheight) +// maxlineheight = curHeight; +// } +// +// float linespacing = maxlineheight * 0.25f; +// +// float totalheight = maxlineheight * lines.length - linespacing * (lines.length - 1); +// +// int cnt = lines.length; +// +// float y = center.y; +// +// for (int i = 0; i < lines.length; i++) { +// +// String line = lines[lines.length - i - 1]; +// +// +// +// c.drawText(line, center.x, y +// + maxlineheight * cnt - totalheight / 2f, +// mCenterTextPaint); +// cnt--; +// y -= linespacing; +// } +// } } } @@ -412,7 +420,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { /** * Make the box containing current arc larger equally in every * dimension, to preserve shape of arc. Code provided by: - * + * * @link https://github.com/wogg */ RectF highlighted = new RectF(circleBox.left - shift, @@ -432,7 +440,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { /** * This gives all pie-slices a rounded edge. - * + * * @param c */ protected void drawRoundedSlices(Canvas c) { @@ -444,7 +452,7 @@ protected void drawRoundedSlices(Canvas c) { if (!dataSet.isVisible()) return; - + PointF center = mChart.getCenterCircleBox(); float r = mChart.getRadius(); @@ -466,10 +474,10 @@ protected void drawRoundedSlices(Canvas c) { float x = (float) ((r - circleRadius) * Math.cos(Math.toRadians((angle + newangle) - * mAnimator.getPhaseY())) + center.x); + * mAnimator.getPhaseY())) + center.x); float y = (float) ((r - circleRadius) * Math.sin(Math.toRadians((angle + newangle) - * mAnimator.getPhaseY())) + center.y); + * mAnimator.getPhaseY())) + center.y); mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawCircle(x, y, circleRadius, mRenderPaint); From 70e2c3899ba54527720c8d616484313237efb702 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 11 Oct 2015 16:34:50 +0200 Subject: [PATCH 0522/1390] Fix SpannableString PieChart center text issues (#993). --- .../xxmassdeveloper/mpchartexample/PieChartActivity.java | 8 ++++---- .../mikephil/charting/renderer/PieChartRenderer.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 8392f186d8..93f2b3e5ec 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -240,10 +240,10 @@ private SpannableString generateCenterSpannableText() { SpannableString s = new SpannableString("MPAndroidChart developed by Philipp Jahoda"); s.setSpan(new RelativeSizeSpan(1.7f), 0, 14, 0); -// s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); -// s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); -// s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); -// s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); + s.setSpan(new StyleSpan(Typeface.NORMAL), 14, s.length() - 15, 0); + s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); + s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); + s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); return s; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 9dfdb556e6..46884a018b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -74,7 +74,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f)); - mCenterTextPaint.setTextAlign(Align.CENTER); + //mCenterTextPaint.setTextAlign(Align.CENTER); mValuePaint.setTextSize(Utils.convertDpToPixel(13f)); mValuePaint.setColor(Color.WHITE); @@ -327,7 +327,7 @@ protected void drawCenterText(Canvas c) { mCenterTextLayout = new StaticLayout(centerText, 0, centerText.length(), mCenterTextPaint, (int) Math.max(Math.ceil(width), 1.f), - Layout.Alignment.ALIGN_NORMAL, 1.f, 0.f, false); + Layout.Alignment.ALIGN_CENTER, 1.f, 0.f, false); } // I wish we could make an ellipse clipping path on Android to clip to the hole... @@ -337,7 +337,7 @@ protected void drawCenterText(Canvas c) { float layoutHeight = mCenterTextLayout.getHeight(); c.save(); - c.translate(boundingRect.centerX(), boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); + c.translate(boundingRect.left, boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f); mCenterTextLayout.draw(c); c.restore(); From 280cb5c648bcb615067957c7855cf4b63e31f6b0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 11 Oct 2015 16:47:55 +0200 Subject: [PATCH 0523/1390] Improve example --- .../CubicLineChartActivity.java | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 6b663c95ed..22fb3409cc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -21,6 +21,8 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.LineDataProvider; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -54,7 +56,8 @@ protected void onCreate(Bundle savedInstanceState) { mSeekBarX.setOnSeekBarChangeListener(this); mChart = (LineChart) findViewById(R.id.chart1); - // if enabled, the chart will always start at zero on the y-axis + mChart.setViewPortOffsets(0, 20, 0, 0); + mChart.setBackgroundColor(Color.rgb(104, 241, 175)); // no description text mChart.setDescription(""); @@ -77,13 +80,16 @@ protected void onCreate(Bundle savedInstanceState) { tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); XAxis x = mChart.getXAxis(); - x.setTypeface(tf); x.setEnabled(false); YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); - y.setLabelCount(5, false); - y.setEnabled(false); + y.setLabelCount(6, false); + y.setStartAtZero(false); + y.setTextColor(Color.WHITE); + y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); + y.setDrawGridLines(false); + y.setAxisLineColor(Color.WHITE); mChart.getAxisRight().setEnabled(false); @@ -270,12 +276,20 @@ private void setData(int count, float range) { set1.setCubicIntensity(0.2f); //set1.setDrawFilled(true); set1.setDrawCircles(false); - set1.setLineWidth(2f); - set1.setCircleSize(5f); + set1.setLineWidth(1.8f); + set1.setCircleSize(4f); + set1.setCircleColor(Color.WHITE); set1.setHighLightColor(Color.rgb(244, 117, 117)); - set1.setColor(Color.rgb(104, 241, 175)); - set1.setFillColor(ColorTemplate.getHoloBlue()); + set1.setColor(Color.WHITE); + set1.setFillColor(Color.WHITE); + set1.setFillAlpha(100); set1.setDrawHorizontalHighlightIndicator(false); + set1.setFillFormatter(new FillFormatter() { + @Override + public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + return -10; + } + }); // create a data object with the datasets LineData data = new LineData(xVals, set1); From 1eae8e050ec6efc77c94084e3bcf5b654f5bc283 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 11 Oct 2015 19:23:16 +0200 Subject: [PATCH 0524/1390] Improvements on piechart. --- .../mpchartexample/PieChartActivity.java | 11 +++++----- .../fragments/PieChartFrag.java | 17 ++++++++++++--- .../fragments/SimpleFragment.java | 2 +- .../listviewitems/PieChartItem.java | 21 +++++++++++++++++-- .../charting/renderer/PieChartRenderer.java | 16 +++++++------- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 93f2b3e5ec..a5ff3955dc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -94,7 +94,7 @@ protected void onCreate(Bundle savedInstanceState) { setData(3, 100); - mChart.animateY(1500, Easing.EasingOption.EaseInOutQuad); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuad); // mChart.spin(2000, 0, 360); Legend l = mChart.getLegend(); @@ -153,15 +153,15 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; case R.id.animateX: { - mChart.animateX(1800); + mChart.animateX(1400); break; } case R.id.animateY: { - mChart.animateY(1800); + mChart.animateY(1400); break; } case R.id.animateXY: { - mChart.animateXY(1800, 1800); + mChart.animateXY(1400, 1400); break; } } @@ -196,7 +196,7 @@ private void setData(int count, float range) { xVals.add(mParties[i % mParties.length]); PieDataSet dataSet = new PieDataSet(yVals1, "Election Results"); - dataSet.setSliceSpace(3f); + dataSet.setSliceSpace(2f); dataSet.setSelectionShift(5f); // add a lot of colors @@ -244,6 +244,7 @@ private SpannableString generateCenterSpannableText() { s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, s.length() - 15, 0); s.setSpan(new RelativeSizeSpan(.8f), 14, s.length() - 15, 0); s.setSpan(new StyleSpan(Typeface.ITALIC), s.length() - 14, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), s.length() - 14, s.length(), 0); return s; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java index b06ab32b84..ae7ca9f19c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/PieChartFrag.java @@ -1,7 +1,11 @@ package com.xxmassdeveloper.mpchartexample.fragments; +import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.app.Fragment; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,12 +34,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa Typeface tf = Typeface.createFromAsset(getActivity().getAssets(), "OpenSans-Light.ttf"); mChart.setCenterTextTypeface(tf); - mChart.setCenterText("Revenues"); - mChart.setCenterTextSize(22f); + mChart.setCenterText(generateCenterText()); + mChart.setCenterTextSize(10f); mChart.setCenterTextTypeface(tf); // radius of the center hole in percent of maximum radius - mChart.setHoleRadius(45f); + mChart.setHoleRadius(45f); mChart.setTransparentCircleRadius(50f); Legend l = mChart.getLegend(); @@ -45,4 +49,11 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa return v; } + + private SpannableString generateCenterText() { + SpannableString s = new SpannableString("Revenues\nQuarters 2015"); + s.setSpan(new RelativeSizeSpan(2f), 0, 8, 0); + s.setSpan(new ForegroundColorSpan(Color.GRAY), 8, s.length(), 0); + return s; + } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index ce9a49b719..386f699fe3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -113,7 +113,7 @@ protected PieData generatePieData() { entries1.add(new Entry((float) (Math.random() * 60) + 40, i)); } - PieDataSet ds1 = new PieDataSet(entries1, "Quarterly Revenues 2014"); + PieDataSet ds1 = new PieDataSet(entries1, "Quarterly Revenues 2015"); ds1.setColors(ColorTemplate.VORDIPLOM_COLORS); ds1.setSliceSpace(2f); ds1.setValueTextColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index f65c02e506..fb09474b56 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -4,6 +4,9 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.text.style.RelativeSizeSpan; import android.view.LayoutInflater; import android.view.View; @@ -13,16 +16,19 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.formatter.PercentFormatter; +import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.R; public class PieChartItem extends ChartItem { private Typeface mTf; + private SpannableString mCenterText; public PieChartItem(ChartData cd, Context c) { super(cd); mTf = Typeface.createFromAsset(c.getAssets(), "OpenSans-Regular.ttf"); + mCenterText = generateCenterText(); } @Override @@ -53,9 +59,9 @@ public View getView(int position, View convertView, Context c) { holder.chart.setDescription(""); holder.chart.setHoleRadius(52f); holder.chart.setTransparentCircleRadius(57f); - holder.chart.setCenterText("MPChart\nAndroid"); + holder.chart.setCenterText(mCenterText); holder.chart.setCenterTextTypeface(mTf); - holder.chart.setCenterTextSize(18f); + holder.chart.setCenterTextSize(9f); holder.chart.setUsePercentValues(true); holder.chart.setExtraOffsets(5, 10, 50, 10); @@ -78,6 +84,17 @@ public View getView(int position, View convertView, Context c) { return convertView; } + private SpannableString generateCenterText() { + SpannableString s = new SpannableString("MPAndroidChart\ncreated by\nPhilipp Jahoda"); + s.setSpan(new RelativeSizeSpan(1.6f), 0, 14, 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.VORDIPLOM_COLORS[0]), 0, 14, 0); + s.setSpan(new RelativeSizeSpan(.9f), 14, 25, 0); + s.setSpan(new ForegroundColorSpan(Color.GRAY), 14, 25, 0); + s.setSpan(new RelativeSizeSpan(1.4f), 25, s.length(), 0); + s.setSpan(new ForegroundColorSpan(ColorTemplate.getHoloBlue()), 25, s.length(), 0); + return s; + } + private static class ViewHolder { PieChart chart; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 46884a018b..2b4fdb488c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -69,7 +69,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator, mTransparentCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTransparentCirclePaint.setColor(Color.WHITE); mTransparentCirclePaint.setStyle(Style.FILL); - mTransparentCirclePaint.setAlpha(100); + mTransparentCirclePaint.setAlpha(105); mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); mCenterTextPaint.setColor(Color.BLACK); @@ -266,19 +266,19 @@ protected void drawHole(Canvas c) { PointF center = mChart.getCenterCircleBox(); - if (transparentCircleRadius > holeRadius && mAnimator.getPhaseX() >= 1f - && mAnimator.getPhaseY() >= 1f) { + // only draw the circle if it can be seen (not covered by the hole) + if (transparentCircleRadius > holeRadius) { - //int color = mTransparentCirclePaint.getColor(); - - // make transparent - //mTransparentCirclePaint.setColor(color & 0x60FFFFFF); + // get original alpha + int alpha = mTransparentCirclePaint.getAlpha(); + mTransparentCirclePaint.setAlpha((int) ((float) alpha * mAnimator.getPhaseX() * mAnimator.getPhaseY())); // draw the transparent-circle mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * transparentCircleRadius, mTransparentCirclePaint); - //mTransparentCirclePaint.setColor(color); + // reset alpha + mTransparentCirclePaint.setAlpha(alpha); } // draw the hole-circle From e3a7b0969b97f4014122a6dce275c20928f14088 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 11 Oct 2015 19:24:06 +0200 Subject: [PATCH 0525/1390] Update version. --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 18a347ea17..639694e26a 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="45" + android:versionName="2.1.5" > Date: Sun, 11 Oct 2015 19:39:01 +0200 Subject: [PATCH 0526/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7106188228..f17b4585aa 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.4' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.5' } ``` @@ -160,7 +160,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.4 + v2.1.5 ``` @@ -180,7 +180,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/-SNAPSHOT/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From a2ecebca0caaba0c2262f7a154e05a3734fc0d77 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 11 Oct 2015 23:13:40 +0200 Subject: [PATCH 0527/1390] add javadoc link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f17b4585aa..324132ec7b 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/-SNAPSHOT/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.5/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) @@ -180,7 +180,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/-SNAPSHOT/javadoc/). +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.5/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From a7898f191a1ad3a8ae91f8b48cf577892980c061 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 13 Oct 2015 20:56:34 +0300 Subject: [PATCH 0528/1390] Allow getting/settings minOffset of the charts, instead of zeroing them out totally --- .../charting/charts/BarLineChartBase.java | 10 ++++++++++ .../charting/charts/PieRadarChartBase.java | 17 +++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 713ed0fc62..3a89c2aada 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -1131,6 +1131,16 @@ public void setBorderColor(int color) { mBorderPaint.setColor(color); } + /** Gets the minimum offset (padding) around the chart, defaults to 10.f */ + public float getMinOffset() { + return mMinOffset; + } + + /** Sets the minimum offset (padding) around the chart, defaults to 10.f */ + public void setMinOffset(float minOffset) { + mMinOffset = minOffset; + } + /** * Returns the Highlight object (contains x-index and DataSet index) of the * selected value at the given touch point inside the Line-, Scatter-, or diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index c5ff63c7e8..881ea65f91 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -42,6 +42,9 @@ public abstract class PieRadarChartBase Date: Tue, 13 Oct 2015 20:15:18 +0200 Subject: [PATCH 0529/1390] Minor changes --- .../com/xxmassdeveloper/mpchartexample/PieChartActivity.java | 4 ++-- settings.gradle | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index a5ff3955dc..5874f82684 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -76,11 +76,11 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setTransparentCircleColor(Color.WHITE); mChart.setTransparentCircleAlpha(110); - + mChart.setHoleRadius(58f); mChart.setTransparentCircleRadius(61f); - mChart.setDrawCenterText(true); + mChart.setDrawCenterText(true); mChart.setRotationAngle(0); // enable rotation of the chart by touch diff --git a/settings.gradle b/settings.gradle index 0d770eb38c..6d793f8d10 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,5 @@ include 'MPChartLib' +//include 'MPAndroidChart-Realm' include 'MPChartExample' + From 47b78b4308bacdd6e4e85b4e2fbfcc3c7adbeaf4 Mon Sep 17 00:00:00 2001 From: Christopher Roberts Date: Thu, 15 Oct 2015 00:45:11 -0400 Subject: [PATCH 0530/1390] Make Entry class Parcelable. As an Entry object may contain arbitrary data (in the form of a single object), I took the route of checking if that object is also parcelable and parceling it if so. If the object is not parcelable, then an Exception is thrown. --- .../github/mikephil/charting/data/Entry.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/Entry.java b/MPChartLib/src/com/github/mikephil/charting/data/Entry.java index e57852ea33..35052fbcb5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/Entry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/Entry.java @@ -1,13 +1,17 @@ package com.github.mikephil.charting.data; +import android.os.Parcel; +import android.os.ParcelFormatException; +import android.os.Parcelable; + /** * Class representing one entry in the chart. Might contain multiple values. * Might only contain a single value depending on the used constructor. * * @author Philipp Jahoda */ -public class Entry { +public class Entry implements Parcelable { /** the actual value */ private float mVal = 0f; @@ -142,4 +146,43 @@ public boolean equalTo(Entry e) { public String toString() { return "Entry, xIndex: " + mXIndex + " val (sum): " + getVal(); } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeFloat(this.mVal); + dest.writeInt(this.mXIndex); + if (mData != null) { + if (mData instanceof Parcelable) { + dest.writeInt(1); + dest.writeParcelable((Parcelable) this.mData, flags); + } else { + throw new ParcelFormatException("Cannot parcel an Entry with non-parcelable data"); + } + } else { + dest.writeInt(0); + } + } + + protected Entry(Parcel in) { + this.mVal = in.readFloat(); + this.mXIndex = in.readInt(); + if (in.readInt() == 1) { + this.mData = in.readParcelable(Object.class.getClassLoader()); + } + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public Entry createFromParcel(Parcel source) { + return new Entry(source); + } + + public Entry[] newArray(int size) { + return new Entry[size]; + } + }; } From c91507525b73ad7af4e8f3148c6d1d2c7ace9b55 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 15 Oct 2015 16:24:39 +0200 Subject: [PATCH 0531/1390] Remove chart.setHighlightEnabled(...) method because it led to confusions when no data was set (issue #1110). --- .../mpchartexample/AnotherBarActivity.java | 10 ++--- .../mpchartexample/BarChartActivity.java | 14 ++----- .../BarChartActivityMultiDataset.java | 9 ++-- .../mpchartexample/BarChartActivitySinus.java | 9 ++-- .../mpchartexample/BubbleChartActivity.java | 10 ++--- .../CandleStickChartActivity.java | 9 ++-- .../CubicLineChartActivity.java | 12 ++---- .../mpchartexample/DrawChartActivity.java | 17 ++------ .../HorizontalBarChartActivity.java | 9 ++-- .../InvertedLineChartActivity.java | 16 ++----- .../mpchartexample/LineChartActivity1.java | 12 ++---- .../mpchartexample/LineChartActivity2.java | 12 ++---- .../MultiLineChartActivity.java | 12 ++---- .../mpchartexample/PerformanceLineChart.java | 7 ---- .../mpchartexample/RadarChartActivitry.java | 9 ++-- .../RealtimeLineChartActivity.java | 3 -- .../mpchartexample/ScatterChartActivity.java | 10 ++--- .../mpchartexample/StackedBarActivity.java | 9 ++-- .../StackedBarActivityNegative.java | 9 ++-- .../fragments/BarChartFrag.java | 2 - .../fragments/ComplexityFragment.java | 6 +-- .../fragments/ScatterChartFrag.java | 1 - .../fragments/SineCosineFragment.java | 7 +--- .../mikephil/charting/charts/Chart.java | 42 +++++++++---------- 24 files changed, 92 insertions(+), 164 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 2fe3723091..0cf9982ef1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -104,11 +104,11 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index be899270db..9ade72efbb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -76,11 +76,6 @@ protected void onCreate(Bundle savedInstanceState) { // scaling can now only be done on x- and y-axis separately mChart.setPinchZoom(false); - // draw shadows for each bar that show the maximum value - // mChart.setDrawBarShadow(true); - - // mChart.setDrawXLabels(false); - mChart.setDrawGridBackground(false); // mChart.setDrawYLabels(false); @@ -149,11 +144,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 398d00373f..910e4839ee 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -135,11 +135,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleHighlightArrow: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 5e53f2b147..1a29182e85 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -130,11 +130,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 4a1a84d95e..690bc6528c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -66,7 +66,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setTouchEnabled(true); - mChart.setHighlightEnabled(true); // enable scaling and dragging mChart.setDragEnabled(true); @@ -116,11 +115,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 384983f42b..5ea63dab91 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -101,11 +101,10 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 22fb3409cc..1d476c9c24 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -62,9 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.setDescription(""); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); @@ -122,11 +119,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleFilled: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 62b9d2386b..7e66ecbb06 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -47,14 +47,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setOnChartValueSelectedListener(this); mChart.setOnDrawListener(this); - // enable drawing with the finger - // mChart.setDrawingEnabled(true); - - // mChart.setLineWidth(5f); - // mChart.setCircleSize(5f); - - mChart.setHighlightEnabled(true); - // if disabled, drawn datasets with the finger will not be automatically // finished // mChart.setAutoFinish(true); @@ -119,11 +111,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleStartzero: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 4df4497da1..83ea2be4e9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -141,11 +141,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index c4ee0ae5da..e943222ead 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -62,9 +62,6 @@ protected void onCreate(Bundle savedInstanceState) { // no description text mChart.setDescription(""); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); @@ -84,10 +81,6 @@ protected void onCreate(Bundle savedInstanceState) { // set the marker to the chart mChart.setMarkerView(mv); - - // enable/disable highlight indicators (the lines that indicate the - // highlighted Entry) - mChart.setHighlightEnabled(false); XAxis xl = mChart.getXAxis(); xl.setAvoidFirstLastClipping(true); @@ -136,11 +129,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleFilled: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 24551f0fc7..a7ee98a6bd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -72,9 +72,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); @@ -186,11 +183,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleFilled: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 6cce635b44..fa2681e9e4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -66,9 +66,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); @@ -146,11 +143,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleFilled: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 81d1505fcf..d6bd2e3aa3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -63,9 +63,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getXAxis().setDrawAxisLine(false); mChart.getXAxis().setDrawGridLines(false); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); @@ -115,11 +112,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleFilled: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java index fa8a393d09..9a195cb4b4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PerformanceLineChart.java @@ -45,9 +45,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); - // disable value highlighting - mChart.setHighlightEnabled(false); - // enable touch gestures mChart.setTouchEnabled(true); @@ -57,10 +54,6 @@ protected void onCreate(Bundle savedInstanceState) { // if disabled, scaling can be done on x- and y-axis separately mChart.setPinchZoom(false); - - // enable/disable highlight indicators (the lines that indicate the - // highlighted Entry) - mChart.setHighlightEnabled(false); mChart.getAxisLeft().setDrawGridLines(false); mChart.getAxisRight().setEnabled(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 9660723760..143bdaf6ed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -90,11 +90,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionToggleRotate: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 286bd4182b..afa181cd0e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -43,9 +43,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDescription(""); mChart.setNoDataTextDescription("You need to provide data for the chart."); - // enable value highlighting - mChart.setHighlightEnabled(true); - // enable touch gestures mChart.setTouchEnabled(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 989ed1b806..c33a77ce11 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -65,7 +65,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawGridBackground(false); mChart.setTouchEnabled(true); - mChart.setHighlightEnabled(true); // enable scaling and dragging mChart.setDragEnabled(true); @@ -109,11 +108,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index 8ed71e49e9..a62e55ecd3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -112,11 +112,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 89acfc268e..3fa58437c1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -126,11 +126,10 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleHighlight: { - if (mChart.isHighlightEnabled()) - mChart.setHighlightEnabled(false); - else - mChart.setHighlightEnabled(true); - mChart.invalidate(); + if(mChart.getData() != null) { + mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); + mChart.invalidate(); + } break; } case R.id.actionTogglePinch: { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java index c338026740..98e368a4db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/BarChartFrag.java @@ -39,8 +39,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view); mChart.setMarkerView(mv); - - mChart.setHighlightEnabled(false); mChart.setDrawGridBackground(false); mChart.setDrawBarShadow(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java index c4fdd7580f..98b904b2b7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ComplexityFragment.java @@ -28,16 +28,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart = (LineChart) v.findViewById(R.id.lineChart1); mChart.setDescription(""); - - mChart.setHighlightEnabled(false); + mChart.setDrawGridBackground(false); mChart.setData(getComplexity()); mChart.animateX(3000); -// mChart.setScaleMinima(3f, 3f); -// mChart.centerViewPort(300, 0); - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); Legend l = mChart.getLegend(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java index 3e07869555..a93038c1e2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/ScatterChartFrag.java @@ -36,7 +36,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart.setMarkerView(mv); - mChart.setHighlightEnabled(false); mChart.setDrawGridBackground(false); mChart.setData(generateScatterData(6, 10000, 200)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index ec783286cb..b2e2cda033 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -28,17 +28,12 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa mChart = (LineChart) v.findViewById(R.id.lineChart1); mChart.setDescription(""); -// mChart.setCircleSize(5f); - - mChart.setHighlightEnabled(false); + mChart.setDrawGridBackground(false); mChart.setData(generateLineData()); mChart.animateX(3000); -// mChart.setScaleMinima(3f, 3f); -// mChart.centerViewPort(300, 0); - Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),"OpenSans-Light.ttf"); Legend l = mChart.getLegend(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 5191d8c67f..6b202b3980 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -875,27 +875,27 @@ public void setOnChartGestureListener(OnChartGestureListener l) { public OnChartGestureListener getOnChartGestureListener() { return mGestureListener; } - - /** - * If set to true, value highlighting is enabled for all underlying data of - * the chart which means that all values can be highlighted programmatically - * or by touch gesture. - * - * @param enabled - */ - public void setHighlightEnabled(boolean enabled) { - if (mData != null) - mData.setHighlightEnabled(enabled); - } - - /** - * Returns true if highlighting of values is enabled, false if not - * - * @return - */ - public boolean isHighlightEnabled() { - return mData == null ? true : mData.isHighlightEnabled(); - } +// +// /** +// * If set to true, value highlighting is enabled for all underlying data of +// * the chart which means that all values can be highlighted programmatically +// * or by touch gesture. +// * +// * @param enabled +// */ +// public void setHighlightEnabled(boolean enabled) { +// if (mData != null) +// mData.setHighlightEnabled(enabled); +// } +// +// /** +// * Returns true if highlighting of values is enabled, false if not +// * +// * @return +// */ +// public boolean isHighlightEnabled() { +// return mData == null ? true : mData.isHighlightEnabled(); +// } /** * returns the current y-max value across all DataSets From 1fdb1827204db3398f1c4adf259ebc7f2add3ece Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 15 Oct 2015 18:13:32 +0200 Subject: [PATCH 0532/1390] Fix #924 --- .../src/com/github/mikephil/charting/charts/Chart.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 6b202b3980..bf350dbb74 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -479,8 +479,11 @@ public void highlightValues(Highlight[] highs) { // set the indices to highlight mIndicesToHighlight = highs; - if(highs == null || highs.length == 0) + if(highs == null || highs.length <= 0 || highs[0] == null) { mChartTouchListener.setLastHighlighted(null); + } else { + mChartTouchListener.setLastHighlighted(highs[0]); + } // redraw the chart invalidate(); From 18e3b07b9d3e28e9324146a74633cf42a8a1a326 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 15 Oct 2015 18:16:03 +0200 Subject: [PATCH 0533/1390] Add new highlighting method. --- .../mikephil/charting/charts/Chart.java | 201 ++++++++++++------ 1 file changed, 135 insertions(+), 66 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index bf350dbb74..074976aa9f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -65,7 +65,9 @@ public abstract class Chart mJobs = new ArrayList(); /** * Adds a job to be executed after the chart-view is setup (after * onSizeChanged(...) is called). - * + * * @param job */ public void addJob(Runnable job) { @@ -1525,7 +1594,7 @@ public void clearAllJobs() { /** * Returns all jobs that are scheduled to be executed after * onSizeChanged(...). - * + * * @return */ public ArrayList getJobs() { @@ -1580,7 +1649,7 @@ protected void onSizeChanged(int w, int h, int oldw, int oldh) { /** * Setting this to true will set the layer-type HARDWARE for the view, false * will set layer-type SOFTWARE. - * + * * @param enabled */ public void setHardwareAccelerationEnabled(boolean enabled) { From 5cbc6b7245d6ff37972c9468daca2cda4620df51 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 16 Oct 2015 12:05:49 +0200 Subject: [PATCH 0534/1390] Allow disabling tap-highlight while still being able to highlight programatically or via drag. --- .../mpchartexample/LineChartActivity1.java | 3 ++- .../mpchartexample/PieChartActivity.java | 1 + .../com/github/mikephil/charting/charts/Chart.java | 13 +++++++++++++ .../listener/BarLineChartTouchListener.java | 8 ++++++-- .../listener/PieRadarChartTouchListener.java | 4 ++++ 5 files changed, 26 insertions(+), 3 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index a7ee98a6bd..c75ed1d967 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -370,8 +370,9 @@ public void onChartGestureStart(MotionEvent me, ChartTouchListener.ChartGesture public void onChartGestureEnd(MotionEvent me, ChartTouchListener.ChartGesture lastPerformedGesture) { Log.i("Gesture", "END, lastGesture: " + lastPerformedGesture); + // un-highlight values after the gesture is finished and no single-tap if(lastPerformedGesture != ChartTouchListener.ChartGesture.SINGLE_TAP) - mChart.highlightValues(null); + mChart.highlightValues(null); // or highlightTouch(null) for callback to onNothingSelected(...) } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 5874f82684..69fd7d9508 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -85,6 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setRotationAngle(0); // enable rotation of the chart by touch mChart.setRotationEnabled(true); + mChart.setHighLightPerTapEnabled(false); // mChart.setUnit(" €"); // mChart.setDrawUnitsInChart(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 074976aa9f..7638636fda 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -76,6 +76,11 @@ public abstract class Chart Date: Fri, 16 Oct 2015 12:06:24 +0200 Subject: [PATCH 0535/1390] Remove unused variable --- .../src/com/github/mikephil/charting/charts/Chart.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 7638636fda..17034de5c1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -121,11 +121,6 @@ public abstract class Chart Date: Fri, 16 Oct 2015 12:07:12 +0200 Subject: [PATCH 0536/1390] Add docs --- .../src/com/github/mikephil/charting/data/ChartData.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index ff60bbfde7..d615347880 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -963,7 +963,8 @@ public void setDrawValues(boolean enabled) { /** * Enables / disables highlighting values for all DataSets this data object - * contains. + * contains. If set to true, this means that values can + * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { for (DataSet set : mDataSets) { From 2e475b8d7dd81570959f5d13ca7808505d6d825a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 16 Oct 2015 14:30:48 +0200 Subject: [PATCH 0537/1390] Improve touch-listener code style --- .../StackedBarActivityNegative.java | 2 +- .../listener/BarLineChartTouchListener.java | 22 +++---------------- .../charting/listener/ChartTouchListener.java | 17 ++++++++++++++ .../listener/PieRadarChartTouchListener.java | 11 +--------- 4 files changed, 22 insertions(+), 30 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 3fa58437c1..45a672ba11 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -209,7 +209,7 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { @Override public void onNothingSelected() { // TODO Auto-generated method stub - + Log.i("NOTING SELECTED", ""); } private class CustomFormatter implements ValueFormatter, YAxisValueFormatter { diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 0a74bec20e..4430cc619c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -372,24 +372,6 @@ private void performZoom(MotionEvent event) { } } - /** - * Perform a highlight operation. - * - * @param e - */ - private void performHighlight(MotionEvent e) { - - Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); - - if (h == null || h.equalTo(mLastHighlighted)) { - mChart.highlightTouch(null); - mLastHighlighted = null; - } else { - mLastHighlighted = h; - mChart.highlightTouch(h); - } - } - /** * Highlights upon dragging, generates callbacks for the selection-listener. * @@ -554,7 +536,9 @@ public boolean onSingleTapUp(MotionEvent e) { return false; } - performHighlight(e); + + Highlight h = mChart.getHighlightByTouchPoint(e.getX(), e.getY()); + performHighlight(h, e); return super.onSingleTapUp(e); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java index f5aadcf060..eef16c8460 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/ChartTouchListener.java @@ -109,6 +109,23 @@ public ChartGesture getLastGesture() { return mLastGesture; } + + /** + * Perform a highlight operation. + * + * @param e + */ + protected void performHighlight(Highlight h, MotionEvent e) { + + if (h == null || h.equalTo(mLastHighlighted)) { + mChart.highlightTouch(null); + mLastHighlighted = null; + } else { + mLastHighlighted = h; + mChart.highlightTouch(h); + } + } + /** * returns the distance between two points * diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 1657d1a1a7..50c61a4194 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -201,16 +201,7 @@ public boolean onSingleTapUp(MotionEvent e) { mLastHighlighted = null; } else { Highlight h = new Highlight(index, dataSetIndex); - - if (h.equalTo(mLastHighlighted)) { - - mChart.highlightTouch(null); - mLastHighlighted = null; - } else { - - mChart.highlightTouch(h); - mLastHighlighted = h; - } + performHighlight(h, e); } } } From 5190f8198c23d100b77bc95ca61ef651808812f7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 16 Oct 2015 17:05:15 +0200 Subject: [PATCH 0538/1390] Code cleanup, documentation. --- .../mpchartexample/PieChartActivity.java | 2 +- .../github/mikephil/charting/charts/Chart.java | 15 +++++++++++++-- .../listener/BarLineChartTouchListener.java | 2 +- .../listener/PieRadarChartTouchListener.java | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 69fd7d9508..72a84b937b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -85,7 +85,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setRotationAngle(0); // enable rotation of the chart by touch mChart.setRotationEnabled(true); - mChart.setHighLightPerTapEnabled(false); + mChart.setHighlightPerTapEnabled(true); // mChart.setUnit(" €"); // mChart.setDrawUnitsInChart(true); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 17034de5c1..a5eec88939 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -495,11 +495,22 @@ public Highlight[] getHighlighted() { return mIndicesToHighlight; } - public boolean isHighLightPerTapEnabled() { + /** + * Returns true if values can be highlighted via tap gesture, false if not. + * + * @return + */ + public boolean isHighlightPerTapEnabled() { return mHighLightPerTapEnabled; } - public void setHighLightPerTapEnabled(boolean enabled) { + /** + * Set this to false to prevent values from being highlighted by tap gesture. + * Values can still be highlighted via drag or programmatically. Default: true + * + * @param enabled + */ + public void setHighlightPerTapEnabled(boolean enabled) { mHighLightPerTapEnabled = enabled; } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 4430cc619c..8a6f3d4a81 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -532,7 +532,7 @@ public boolean onSingleTapUp(MotionEvent e) { l.onChartSingleTapped(e); } - if(!mChart.isHighLightPerTapEnabled()) { + if(!mChart.isHighlightPerTapEnabled()) { return false; } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 50c61a4194..9163c823d8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -147,7 +147,7 @@ public boolean onSingleTapUp(MotionEvent e) { l.onChartSingleTapped(e); } - if(!mChart.isHighLightPerTapEnabled()) { + if(!mChart.isHighlightPerTapEnabled()) { return false; } From 8065d17016b3d0f3e2406e27705233d7980d1a7c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 19 Oct 2015 14:20:30 +0200 Subject: [PATCH 0539/1390] Critical fix in radarchart (issue #1121) --- .../src/com/github/mikephil/charting/charts/RadarChart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 7de9699def..c619cad9a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -60,7 +60,7 @@ public class RadarChart extends PieRadarChartBase { /** * modulus that determines how many labels and web-lines are skipped before the next is drawn */ - private int mSkipWebLineCount = 1; + private int mSkipWebLineCount = 0; /** * the object reprsenting the y-axis labels From 83e8911290a32cee478d19b89e559b823c6f4c18 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 11:00:44 +0200 Subject: [PATCH 0540/1390] Work on creating interfaces for realm --- .../CubicLineChartActivity.java | 3 +- .../mpchartexample/RealmDatabaseActivity.java | 111 ++++++++++++++++++ .../custom/MyFillFormatter.java | 2 +- .../mikephil/charting/charts/BarChart.java | 4 +- .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/BubbleChart.java | 2 +- .../charting/charts/CandleStickChart.java | 2 +- .../mikephil/charting/charts/Chart.java | 2 +- .../charting/charts/CombinedChart.java | 10 +- .../mikephil/charting/charts/LineChart.java | 2 +- .../charting/charts/ScatterChart.java | 2 +- .../mikephil/charting/data/ChartData.java | 32 +---- .../charting/data/realm/RealmLineData.java | 33 ++++++ .../charting/data/realm/RealmLineDataSet.java | 9 ++ .../formatter/DefaultFillFormatter.java | 2 +- .../charting/formatter/FillFormatter.java | 3 +- .../charting/highlight/BarHighlighter.java | 2 +- .../charting/highlight/ChartHighlighter.java | 2 +- .../highlight/CombinedHighlighter.java | 2 +- .../highlight/HorizontalBarHighlighter.java | 2 +- .../data/IBarLineScatterCandleBubbleData.java | 10 ++ .../datainterfaces/data/IChartData.java | 44 +++++++ .../datainterfaces/data/ILineData.java | 9 ++ .../IBarLineScatterCandleBubbleDataSet.java | 7 ++ .../datainterfaces/datasets/IDataSet.java | 7 ++ .../datainterfaces/datasets/ILineDataSet.java | 8 ++ .../datasets/ILineRadarDataSet.java | 7 ++ .../ILineScatterCandleRadarDataSet.java | 7 ++ .../{ => dataprovider}/BarDataProvider.java | 2 +- ...arLineScatterCandleBubbleDataProvider.java | 2 +- .../BubbleDataProvider.java | 2 +- .../CandleDataProvider.java | 2 +- .../{ => dataprovider}/ChartInterface.java | 2 +- .../{ => dataprovider}/LineDataProvider.java | 2 +- .../ScatterDataProvider.java | 2 +- .../charting/renderer/BarChartRenderer.java | 2 +- .../renderer/BubbleChartRenderer.java | 2 +- .../renderer/CandleStickChartRenderer.java | 3 +- .../renderer/CombinedChartRenderer.java | 2 +- .../renderer/HorizontalBarChartRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 2 +- .../mikephil/charting/renderer/Renderer.java | 2 +- .../renderer/ScatterChartRenderer.java | 2 +- 43 files changed, 293 insertions(+), 66 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/BarDataProvider.java (82%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/BarLineScatterCandleBubbleDataProvider.java (89%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/BubbleDataProvider.java (73%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/CandleDataProvider.java (73%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/ChartInterface.java (92%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/LineDataProvider.java (81%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{ => dataprovider}/ScatterDataProvider.java (74%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 1d476c9c24..2432180f1e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -22,8 +22,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.LineDataProvider; -import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java new file mode 100644 index 0000000000..c92b71d0ce --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -0,0 +1,111 @@ +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.realm.RealmLineData; +import com.github.mikephil.charting.data.realm.RealmLineDataSet; +import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; + +import java.util.ArrayList; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivity extends DemoBase { + + private LineChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_linechart_noseekbar); + + mChart = (LineChart) findViewById(R.id.chart1); + mChart.setDrawGridBackground(false); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable touch gestures + mChart.setTouchEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(true); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines + leftAxis.setAxisMaxValue(220f); + leftAxis.setAxisMinValue(-50f); + leftAxis.setStartAtZero(false); + leftAxis.enableGridDashedLine(10f, 10f, 0f); + + mChart.getAxisRight().setEnabled(false); + + // add data + setData(45, 100); + + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } + + private void setData(int count, float range) { + + ArrayList xVals = new ArrayList(); + for (int i = 0; i < count; i++) { + xVals.add((i) + ""); + } + + ArrayList yVals = new ArrayList(); + + for (int i = 0; i < count; i++) { + + float mult = (range + 1); + float val = (float) (Math.random() * mult) + 3;// + (float) + // ((mult * + // 0.1) / 10); + yVals.add(new Entry(val, i)); + } + + // create a dataset and give it a type + RealmLineDataSet set1 = new RealmLineDataSet(); + + // set the line to be drawn like this "- - - - - -" + set1.enableDashedLine(10f, 5f, 0f); + set1.enableDashedHighlightLine(10f, 5f, 0f); + set1.setColor(Color.BLACK); + set1.setCircleColor(Color.BLACK); + set1.setLineWidth(1f); + set1.setCircleSize(3f); + set1.setDrawCircleHole(false); + set1.setValueTextSize(9f); + set1.setFillAlpha(65); + set1.setFillColor(Color.BLACK); +// set1.setDrawFilled(true); + // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), + // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set1); // add the datasets + + // create a data object with the datasets + RealmLineData data = new RealmLineData(); + + // set data + mChart.setData(data); + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index de96237cc5..248f7f5bed 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -1,7 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.formatter.FillFormatter; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index f118c145b4..35bdd81f8a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -9,11 +9,9 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 3a89c2aada..782f5a86e9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -25,7 +25,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java index 6e61689740..fd99ab45e9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -6,7 +6,7 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleDataSet; -import com.github.mikephil.charting.interfaces.BubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.renderer.BubbleChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index f8d1deb139..12f8dad9fd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -5,7 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.interfaces.CandleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.renderer.CandleStickChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index a5eec88939..f4b165ff6e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -34,7 +34,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.ChartHighlighter; -import com.github.mikephil.charting.interfaces.ChartInterface; +import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 9c4be80cf2..8f432611b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -12,11 +12,11 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; -import com.github.mikephil.charting.interfaces.BarDataProvider; -import com.github.mikephil.charting.interfaces.BubbleDataProvider; -import com.github.mikephil.charting.interfaces.CandleDataProvider; -import com.github.mikephil.charting.interfaces.LineDataProvider; -import com.github.mikephil.charting.interfaces.ScatterDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.renderer.CombinedChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 55cac759e8..c354217a04 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -5,7 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java index 0a9303f173..773d280fae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/ScatterChart.java @@ -5,7 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.interfaces.ScatterDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.renderer.ScatterChartRenderer; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index d615347880..bb6002c365 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.interfaces.datainterfaces.data.IChartData; import java.util.ArrayList; import java.util.Arrays; @@ -18,7 +19,7 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> { +public abstract class ChartData> implements IChartData { /** * maximum y-value in the y-value array across all axes @@ -406,12 +407,7 @@ public float getYValueSum() { return mYValueSum; } - /** - * Returns the total number of y-values across all DataSet objects the this - * object represents. - * - * @return - */ + @Override public int getYValCount() { return mYValCount; } @@ -445,11 +441,7 @@ public void removeXValue(int index) { mXVals.remove(index); } - /** - * Returns an the array of DataSets this object holds. - * - * @return - */ + @Override public List getDataSets() { return mDataSets; } @@ -540,12 +532,7 @@ public T getDataSetByLabel(String label, boolean ignorecase) { return mDataSets.get(index); } - /** - * Returns the DataSet object at the given index. - * - * @param index - * @return - */ + @Override public T getDataSetByIndex(int index) { if (mDataSets == null || index < 0 || index >= mDataSets.size()) @@ -834,15 +821,8 @@ public int[] getColors() { return colors; } - /** - * Returns the index of the provided DataSet inside the DataSets array of - * this data object. Returns -1 if the DataSet was not found. - * - * @param dataSet - * @return - */ + @Override public int getIndexOfDataSet(T dataSet) { - for (int i = 0; i < mDataSets.size(); i++) { if (mDataSets.get(i) == dataSet) return i; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java new file mode 100644 index 0000000000..344b211543 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java @@ -0,0 +1,33 @@ +package com.github.mikephil.charting.data.realm; + +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.data.ILineData; + +import java.util.List; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmLineData implements ILineData { + + + @Override + public List getDataSets() { + return null; + } + + @Override + public LineDataSet getDataSetByIndex(int index) { + return null; + } + + @Override + public int getIndexOfDataSet(LineDataSet dataSet) { + return 0; + } + + @Override + public int getYValCount() { + return 0; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java new file mode 100644 index 0000000000..5e5a41a9d2 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.data.realm; + +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmLineDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index 20ba8fdda4..ac1345a022 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -3,7 +3,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** * Default formatter that calculates the position of the filled line. diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java index 424874a199..fccb6b61a6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java @@ -1,8 +1,7 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** * Interface for providing a custom logic to where the filling line of a LineDataSet diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 07e476acd6..9f575c3dec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -3,7 +3,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** * Created by Philipp Jahoda on 22/07/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index c4070d066b..f010d3a5b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -5,7 +5,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java index bb335256ea..d0f2ceea4d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -3,7 +3,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index f6343615b6..3e814f6a2c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** * Created by Philipp Jahoda on 22/07/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java new file mode 100644 index 0000000000..70830c6c83 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java @@ -0,0 +1,10 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.data; + +import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.data.Entry; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface IBarLineScatterCandleBubbleData> extends IChartData { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java new file mode 100644 index 0000000000..e53e83f880 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java @@ -0,0 +1,44 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.data; + +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface IChartData> { + + /** + * Returns an the array of DataSets this object holds. + * + * @return + */ + List getDataSets(); + + /** + * Returns the DataSet object at the given index. + * + * @param index + * @return + */ + T getDataSetByIndex(int index); + + /** + * Returns the index of the provided DataSet inside the DataSets array of + * this data object. Returns -1 if the DataSet was not found. + * + * @param dataSet + * @return + */ + int getIndexOfDataSet(T dataSet); + + /** + * Returns the total number of y-values across all DataSet objects the this + * object represents. + * + * @return + */ + int getYValCount(); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java new file mode 100644 index 0000000000..049e0f1fc1 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.data; + +import com.github.mikephil.charting.data.LineDataSet; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface ILineData extends IBarLineScatterCandleBubbleData { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java new file mode 100644 index 0000000000..e389fa0725 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +/** + * Created by philipp on 21/10/15. + */ +public interface IBarLineScatterCandleBubbleDataSet extends IDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java new file mode 100644 index 0000000000..704fb7e93c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface IDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java new file mode 100644 index 0000000000..9d2198496c --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java @@ -0,0 +1,8 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +/** + * Created by Philpp Jahoda on 21/10/15. + */ +public interface ILineDataSet extends ILineRadarDataSet { + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java new file mode 100644 index 0000000000..f6a0873858 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface ILineRadarDataSet extends ILineScatterCandleRadarDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java new file mode 100644 index 0000000000..10f4e94908 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public interface ILineScatterCandleRadarDataSet extends IBarLineScatterCandleBubbleDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java similarity index 82% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java index 3de8ee3e48..2f0675fc4a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.data.BarData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java similarity index 89% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java index 41dd8c4c6a..faab82a265 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BarLineScatterCandleBubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BarLineScatterCandleBubbleDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java similarity index 73% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java index 2d1847af6d..82ee30ad7c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/BubbleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/BubbleDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.data.BubbleData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java similarity index 73% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java index 67b58f2462..357403f98a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/CandleDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/CandleDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.data.CandleData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java similarity index 92% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java index 216e9a6cef..5d060cb8a0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ChartInterface.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import android.graphics.PointF; import android.graphics.RectF; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java similarity index 81% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java index ef4866ef77..5c23ac27b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/LineDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/LineDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.LineData; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java similarity index 74% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java index 07aedbd47d..b58d5af95d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/ScatterDataProvider.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/dataprovider/ScatterDataProvider.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces; +package com.github.mikephil.charting.interfaces.dataprovider; import com.github.mikephil.charting.data.ScatterData; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index ce6036a8c1..2440850f34 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index dae2f1a7d0..b4d1efaeaf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.BubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 460f983975..d233429b38 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -10,8 +10,7 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.CandleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 596200b994..5bb4e432a0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.charts.CombinedChart; import com.github.mikephil.charting.charts.CombinedChart.DrawOrder; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 850464bea2..c684ae4f4f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -10,7 +10,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.BarDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.formatter.ValueFormatter; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 147229cb82..bb86402091 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -14,7 +14,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.LineDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java index dd1975e213..9e66d32329 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/Renderer.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.renderer; -import com.github.mikephil.charting.interfaces.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index a51c2aad91..794567d0e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.interfaces.ScatterDataProvider; +import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; From 1482f9331e6d47c2e255be1cb95b3e91133aabc0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 14:53:53 +0200 Subject: [PATCH 0541/1390] Major refactorings and implementation if line interface --- .../mpchartexample/RealmDatabaseActivity.java | 3 +- .../data/BarLineScatterCandleBubbleData.java | 6 +- .../mikephil/charting/data/BaseDataSet.java | 80 +++++++++ .../mikephil/charting/data/ChartData.java | 21 +-- .../mikephil/charting/data/DataSet.java | 153 +++--------------- .../mikephil/charting/data/LineData.java | 16 +- .../mikephil/charting/data/LineDataSet.java | 3 +- .../charting/data/realm/RealmLineData.java | 10 +- .../charting/data/realm/RealmLineDataSet.java | 59 ++++++- .../data/IBarLineScatterCandleBubbleData.java | 3 +- .../datainterfaces/data/IChartData.java | 3 +- .../datainterfaces/data/ILineData.java | 4 +- .../IBarLineScatterCandleBubbleDataSet.java | 4 +- .../datainterfaces/datasets/IDataSet.java | 92 ++++++++++- .../datainterfaces/datasets/ILineDataSet.java | 4 +- .../datasets/ILineRadarDataSet.java | 4 +- .../ILineScatterCandleRadarDataSet.java | 4 +- 17 files changed, 301 insertions(+), 168 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index c92b71d0ce..255613bdbe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.RealmLineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -103,7 +104,7 @@ private void setData(int count, float range) { dataSets.add(set1); // add the datasets // create a data object with the datasets - RealmLineData data = new RealmLineData(); + LineData data = new LineData(null, dataSets); // set data mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 884140f378..5fb3db1070 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; + import java.util.List; /** @@ -8,8 +10,8 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleBubbleData> - extends ChartData { +public abstract class BarLineScatterCandleBubbleData> + extends ChartData { public BarLineScatterCandleBubbleData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java new file mode 100644 index 0000000000..e42c2212e6 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -0,0 +1,80 @@ +package com.github.mikephil.charting.data; + +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; + +import java.util.List; + +/** + * Created by philipp on 21/10/15. + */ +public abstract class BaseDataSet implements IDataSet { + + /** + * maximum y-value in the y-value array + */ + protected float mYMax = 0.0f; + + /** + * the minimum y-value in the y-value array + */ + protected float mYMin = 0.0f; + + /** + * the last start value used for calcMinMax + */ + protected int mLastStart = 0; + + /** + * the last end value used for calcMinMax + */ + protected int mLastEnd = 0; + + + /** + * calc minimum and maximum y value + */ + protected void calcMinMax(List values, int start, int end) { + + if(values == null) + return; + + final int yValCount = values.size(); + + if (yValCount == 0) + return; + + int endValue; + + if (end == 0 || end >= yValCount) + endValue = yValCount - 1; + else + endValue = end; + + mLastStart = start; + mLastEnd = endValue; + + mYMin = Float.MAX_VALUE; + mYMax = -Float.MAX_VALUE; + + for (int i = start; i <= endValue; i++) { + + T e = values.get(i); + + if (e != null && !Float.isNaN(e.getVal())) { + + if (e.getVal() < mYMin) + mYMin = e.getVal(); + + if (e.getVal() > mYMax) + mYMax = e.getVal(); + } + } + + if (mYMin == Float.MAX_VALUE) { + mYMin = 0.f; + mYMax = 0.f; + } + } + + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index bb6002c365..a24f890f55 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.data.IChartData; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.ArrayList; import java.util.Arrays; @@ -19,7 +20,7 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> implements IChartData { +public abstract class ChartData> implements IChartData { /** * maximum y-value in the y-value array across all axes @@ -249,7 +250,7 @@ public void calcMinMax(int start, int end) { mLeftAxisMax = firstLeft.getYMax(); mLeftAxisMin = firstLeft.getYMin(); - for (DataSet dataSet : mDataSets) { + for (IDataSet dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.LEFT) { if (dataSet.getYMin() < mLeftAxisMin) mLeftAxisMin = dataSet.getYMin(); @@ -268,7 +269,7 @@ public void calcMinMax(int start, int end) { mRightAxisMax = firstRight.getYMax(); mRightAxisMin = firstRight.getYMin(); - for (DataSet dataSet : mDataSets) { + for (IDataSet dataSet : mDataSets) { if (dataSet.getAxisDependency() == AxisDependency.RIGHT) { if (dataSet.getYMin() < mRightAxisMin) mRightAxisMin = dataSet.getYMin(); @@ -887,7 +888,7 @@ public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueFormatter(f); } } @@ -900,7 +901,7 @@ public void setValueFormatter(ValueFormatter f) { * @param color */ public void setValueTextColor(int color) { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTextColor(color); } } @@ -912,7 +913,7 @@ public void setValueTextColor(int color) { * @param tf */ public void setValueTypeface(Typeface tf) { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTypeface(tf); } } @@ -924,7 +925,7 @@ public void setValueTypeface(Typeface tf) { * @param size */ public void setValueTextSize(float size) { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTextSize(size); } } @@ -936,7 +937,7 @@ public void setValueTextSize(float size) { * @param enabled */ public void setDrawValues(boolean enabled) { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setDrawValues(enabled); } } @@ -947,7 +948,7 @@ public void setDrawValues(boolean enabled) { * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setHighlightEnabled(enabled); } } @@ -959,7 +960,7 @@ public void setHighlightEnabled(boolean enabled) { * @return */ public boolean isHighlightEnabled() { - for (DataSet set : mDataSets) { + for (IDataSet set : mDataSets) { if (!set.isHighlightEnabled()) return false; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index a90562b5ff..278f55c452 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -6,6 +6,7 @@ import android.graphics.Typeface; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.utils.Utils; @@ -22,12 +23,7 @@ * * @author Philipp Jahoda */ -public abstract class DataSet { - - /** - * List representing all colors that are used for this DataSet - */ - protected List mColors = null; +public abstract class DataSet extends BaseDataSet { /** * the entries that this dataset represents / holds together @@ -35,30 +31,15 @@ public abstract class DataSet { protected List mYVals = null; /** - * maximum y-value in the y-value array - */ - protected float mYMax = 0.0f; - - /** - * the minimum y-value in the y-value array + * List representing all colors that are used for this DataSet */ - protected float mYMin = 0.0f; + protected List mColors = null; /** * the total sum of all y-values */ private float mYValueSum = 0f; - /** - * the last start value used for calcMinMax - */ - protected int mLastStart = 0; - - /** - * the last end value used for calcMinMax - */ - protected int mLastEnd = 0; - /** * label that describes the DataSet or the data the DataSet represents */ @@ -125,7 +106,7 @@ public DataSet(List yVals, String label) { // default color mColors.add(Color.rgb(140, 234, 255)); - calcMinMax(mLastStart, mLastEnd); + calcMinMax(mYVals, mLastStart, mLastEnd); calcYValueSum(); } @@ -133,52 +114,10 @@ public DataSet(List yVals, String label) { * Use this method to tell the data set that the underlying data has changed */ public void notifyDataSetChanged() { - calcMinMax(mLastStart, mLastEnd); + calcMinMax(mYVals, mLastStart, mLastEnd); calcYValueSum(); } - /** - * calc minimum and maximum y value - */ - protected void calcMinMax(int start, int end) { - final int yValCount = mYVals.size(); - - if (yValCount == 0) - return; - - int endValue; - - if (end == 0 || end >= yValCount) - endValue = yValCount - 1; - else - endValue = end; - - mLastStart = start; - mLastEnd = endValue; - - mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - - for (int i = start; i <= endValue; i++) { - - Entry e = mYVals.get(i); - - if (e != null && !Float.isNaN(e.getVal())) { - - if (e.getVal() < mYMin) - mYMin = e.getVal(); - - if (e.getVal() > mYMax) - mYMax = e.getVal(); - } - } - - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - } - /** * calculates the sum of all y-values */ @@ -202,11 +141,7 @@ public float getAverage() { return (float) getYValueSum() / (float) getValueCount(); } - /** - * returns the number of y-values this DataSet represents - * - * @return - */ + @Override public int getEntryCount() { return mYVals.size(); } @@ -230,16 +165,7 @@ public float getYValForXIndex(int xIndex) { return Float.NaN; } - /** - * Returns the first Entry object found at the given xIndex with binary - * search. If the no Entry at the specified x-index is found, this method - * returns the index at the closest x-index. Returns null if no Entry object - * at that index. INFORMATION: This method does calculations at runtime. Do - * not over-use in performance critical situations. - * - * @param x - * @return - */ + @Override public T getEntryForXIndex(int x) { int index = getEntryIndex(x); @@ -328,38 +254,22 @@ public List getEntriesForXIndex(int x) { return entries; } - /** - * returns the DataSets Entry array - * - * @return - */ + @Override public List getYVals() { return mYVals; } - /** - * gets the sum of all y-values - * - * @return - */ + @Override public float getYValueSum() { return mYValueSum; } - /** - * returns the minimum y-value this DataSet holds - * - * @return - */ + @Override public float getYMin() { return mYMin; } - /** - * returns the maximum y-value this DataSet holds - * - * @return - */ + @Override public float getYMax() { return mYMax; } @@ -430,11 +340,7 @@ public void setLabel(String label) { mLabel = label; } - /** - * Returns the label string that describes the DataSet. - * - * @return - */ + @Override public String getLabel() { return mLabel; } @@ -459,11 +365,7 @@ public boolean isVisible() { return mVisible; } - /** - * Returns the axis this DataSet should be plotted against. - * - * @return - */ + @Override public AxisDependency getAxisDependency() { return mAxisDependency; } @@ -598,7 +500,7 @@ public boolean removeEntry(T e) { float val = e.getVal(); mYValueSum -= val; - calcMinMax(mLastStart, mLastEnd); + calcMinMax(mYVals, mLastStart, mLastEnd); } return removed; @@ -633,7 +535,7 @@ public boolean removeFirst() { float val = entry.getVal(); mYValueSum -= val; - calcMinMax(mLastStart, mLastEnd); + calcMinMax(mYVals, mLastStart, mLastEnd); } return removed; @@ -659,7 +561,7 @@ public boolean removeLast() { float val = entry.getVal(); mYValueSum -= val; - calcMinMax(mLastStart, mLastEnd); + calcMinMax(mYVals, mLastStart, mLastEnd); } return removed; @@ -736,11 +638,7 @@ public void setColor(int color) { mColors.add(color); } - /** - * returns all the colors that are set for this DataSet - * - * @return - */ + @Override public List getColors() { return mColors; } @@ -783,11 +681,7 @@ public void setHighlightEnabled(boolean enabled) { mHighlightEnabled = enabled; } - /** - * returns true if highlighting of values is enabled, false if not - * - * @return - */ + @Override public boolean isHighlightEnabled() { return mHighlightEnabled; } @@ -896,14 +790,7 @@ public float getValueTextSize() { return mValueTextSize; } - /** - * Checks if this DataSet contains the specified Entry. Returns true if so, - * false if not. NOTE: Performance is pretty bad on this one, do not - * over-use in performance critical situations. - * - * @param e - * @return - */ + @Override public boolean contains(Entry e) { for (Entry entry : mYVals) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 245319d07f..a411fda37c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; + import java.util.ArrayList; import java.util.List; @@ -9,7 +11,7 @@ * * @author Philipp Jahoda */ -public class LineData extends BarLineScatterCandleBubbleData { +public class LineData extends BarLineScatterCandleBubbleData { public LineData() { super(); @@ -23,24 +25,24 @@ public LineData(String[] xVals) { super(xVals); } - public LineData(List xVals, List dataSets) { + public LineData(List xVals, List dataSets) { super(xVals, dataSets); } - public LineData(String[] xVals, List dataSets) { + public LineData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public LineData(List xVals, LineDataSet dataSet) { + public LineData(List xVals, ILineDataSet dataSet) { super(xVals, toList(dataSet)); } - public LineData(String[] xVals, LineDataSet dataSet) { + public LineData(String[] xVals, ILineDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(LineDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(ILineDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index fdbd15d6ab..a7df7ba0e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.DashPathEffect; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -13,7 +14,7 @@ import java.util.ArrayList; import java.util.List; -public class LineDataSet extends LineRadarDataSet { +public class LineDataSet extends LineRadarDataSet implements ILineDataSet { /** List representing all colors that are used for the circles */ private List mCircleColors = null; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java index 344b211543..f0e4f9fce1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java @@ -1,7 +1,9 @@ package com.github.mikephil.charting.data.realm; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.data.ILineData; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.List; @@ -12,22 +14,22 @@ public class RealmLineData implements ILineData { @Override - public List getDataSets() { + public List getDataSets() { return null; } @Override - public LineDataSet getDataSetByIndex(int index) { + public IDataSet getDataSetByIndex(int index) { return null; } @Override - public int getIndexOfDataSet(LineDataSet dataSet) { + public int getYValCount() { return 0; } @Override - public int getYValCount() { + public int getIndexOfDataSet(IDataSet dataSet) { return 0; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 5e5a41a9d2..0150d1f907 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -1,9 +1,66 @@ package com.github.mikephil.charting.data.realm; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BaseDataSet; +import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import java.util.List; + /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet { +public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { + + + @Override + public String getLabel() { + return null; + } + + @Override + public List getYVals() { + return null; + } + + @Override + public float getYMin() { + return 0; + } + + @Override + public float getYMax() { + return 0; + } + + @Override + public float getYValueSum() { + return 0; + } + + @Override + public int getEntryCount() { + return 0; + } + + @Override + public YAxis.AxisDependency getAxisDependency() { + return null; + } + + @Override + public List getColors() { + return null; + } + + @Override + public Entry getEntryForXIndex(int x) { + return null; + } + + @Override + public boolean contains(Entry e) { + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java index 70830c6c83..9f28994f80 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java @@ -2,9 +2,10 @@ import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; /** * Created by Philipp Jahoda on 21/10/15. */ -public interface IBarLineScatterCandleBubbleData> extends IChartData { +public interface IBarLineScatterCandleBubbleData> extends IChartData { } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java index e53e83f880..e44dc312be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java @@ -2,13 +2,14 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.List; /** * Created by Philipp Jahoda on 21/10/15. */ -public interface IChartData> { +public interface IChartData> { /** * Returns an the array of DataSets this object holds. diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java index 049e0f1fc1..713af78fd1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java @@ -1,9 +1,9 @@ package com.github.mikephil.charting.interfaces.datainterfaces.data; -import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; /** * Created by Philipp Jahoda on 21/10/15. */ -public interface ILineData extends IBarLineScatterCandleBubbleData { +public interface ILineData extends IBarLineScatterCandleBubbleData { } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java index e389fa0725..a1a488158d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java @@ -1,7 +1,9 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.data.Entry; + /** * Created by philipp on 21/10/15. */ -public interface IBarLineScatterCandleBubbleDataSet extends IDataSet { +public interface IBarLineScatterCandleBubbleDataSet extends IDataSet { } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index 704fb7e93c..ca57116ca4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -1,7 +1,97 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + /** * Created by Philipp Jahoda on 21/10/15. */ -public interface IDataSet { +public interface IDataSet { + + /** + * Returns the label string that describes the DataSet. + * + * @return + */ + String getLabel(); + + /** + * returns the DataSets Entry array + * + * @return + */ + List getYVals(); + + /** + * returns the minimum y-value this DataSet holds + * + * @return + */ + float getYMin(); + + /** + * returns the maximum y-value this DataSet holds + * + * @return + */ + float getYMax(); + + /** + * gets the sum of all y-values + * + * @return + */ + float getYValueSum(); + + /** + * returns the number of y-values this DataSet represents -> yvals.size() + * + * @return + */ + int getEntryCount(); + + /** + * Returns the axis this DataSet should be plotted against. + * + * @return + */ + YAxis.AxisDependency getAxisDependency(); + + /** + * returns all the colors that are set for this DataSet + * + * @return + */ + List getColors(); + + /** + * Returns the first Entry object found at the given xIndex with binary + * search. If the no Entry at the specified x-index is found, this method + * returns the index at the closest x-index. Returns null if no Entry object + * at that index. INFORMATION: This method does calculations at runtime. Do + * not over-use in performance critical situations. + * + * @param x + * @return + */ + T getEntryForXIndex(int x); + + /** + * Checks if this DataSet contains the specified Entry. Returns true if so, + * false if not. NOTE: Performance is pretty bad on this one, do not + * over-use in performance critical situations. + * + * @param e + * @return + */ + boolean contains(Entry e); + + /** + * returns true if highlighting of values is enabled, false if not + * + * @return + */ + boolean isHighlightEnabled(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java index 9d2198496c..a5f674b250 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java @@ -1,8 +1,10 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.data.Entry; + /** * Created by Philpp Jahoda on 21/10/15. */ -public interface ILineDataSet extends ILineRadarDataSet { +public interface ILineDataSet extends ILineRadarDataSet { } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java index f6a0873858..71e67b4d13 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java @@ -1,7 +1,9 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.data.Entry; + /** * Created by Philipp Jahoda on 21/10/15. */ -public interface ILineRadarDataSet extends ILineScatterCandleRadarDataSet { +public interface ILineRadarDataSet extends ILineScatterCandleRadarDataSet { } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java index 10f4e94908..852a3ac0ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java @@ -1,7 +1,9 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.data.Entry; + /** * Created by Philipp Jahoda on 21/10/15. */ -public interface ILineScatterCandleRadarDataSet extends IBarLineScatterCandleBubbleDataSet { +public interface ILineScatterCandleRadarDataSet extends IBarLineScatterCandleBubbleDataSet { } From f264c813d7120d6e76e03a4d5525bf2be9617468 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 14:58:18 +0200 Subject: [PATCH 0542/1390] Remove y-value-sum from DataSets as it is not needed --- .../mikephil/charting/data/ChartData.java | 58 ++----------------- .../mikephil/charting/data/DataSet.java | 42 -------------- .../datainterfaces/datasets/IDataSet.java | 7 --- 3 files changed, 6 insertions(+), 101 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index a24f890f55..e7063b0964 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -40,11 +40,6 @@ public abstract class ChartData> implements protected float mRightAxisMin = 0.0f; - /** - * the total sum of all y-values - */ - private float mYValueSum = 0f; - /** * total number of y-values across all DataSet objects */ @@ -154,7 +149,6 @@ protected void init() { checkLegal(); calcMinMax(mLastStart, mLastEnd); - calcYValueSum(); calcYValueCount(); calcXValAverageLength(); @@ -228,13 +222,14 @@ public void calcMinMax(int start, int end) { for (int i = 0; i < mDataSets.size(); i++) { - mDataSets.get(i).calcMinMax(start, end); + T set = mDataSets.get(i); + set.calcMinMax(set.getYVals(), start, end); - if (mDataSets.get(i).getYMin() < mYMin) - mYMin = mDataSets.get(i).getYMin(); + if (set.getYMin() < mYMin) + mYMin = set.getYMin(); - if (mDataSets.get(i).getYMax() > mYMax) - mYMax = mDataSets.get(i).getYMax(); + if (set.getYMax() > mYMax) + mYMax = set.getYMax(); } if (mYMin == Float.MAX_VALUE) { @@ -285,21 +280,6 @@ public void calcMinMax(int start, int end) { } } - /** - * calculates the sum of all y-values in all datasets - */ - protected void calcYValueSum() { - - mYValueSum = 0; - - if (mDataSets == null) - return; - - for (int i = 0; i < mDataSets.size(); i++) { - mYValueSum += Math.abs(mDataSets.get(i).getYValueSum()); - } - } - /** * Calculates the total number of y-values across all DataSets the ChartData * represents. @@ -335,15 +315,6 @@ public int getDataSetCount() { return mDataSets.size(); } - /** - * Returns the average value across all entries in this Data object - * (all entries from the DataSets this data object holds) - * @return - */ - public float getAverage() { - return (float ) getYValueSum() / (float) getYValCount(); - } - /** * Returns the smallest y-value the data object contains. * @@ -398,16 +369,6 @@ public float getXValAverageLength() { return mXValAverageLength; } - /** - * Returns the total y-value sum across all DataSet objects the this object - * represents. - * - * @return - */ - public float getYValueSum() { - return mYValueSum; - } - @Override public int getYValCount() { return mYValCount; @@ -553,7 +514,6 @@ public void addDataSet(T d) { return; mYValCount += d.getEntryCount(); - mYValueSum += d.getYValueSum(); if (mDataSets.size() <= 0) { @@ -630,7 +590,6 @@ public boolean removeDataSet(T d) { if (removed) { mYValCount -= d.getEntryCount(); - mYValueSum -= d.getYValueSum(); calcMinMax(mLastStart, mLastEnd); } @@ -702,7 +661,6 @@ public void addEntry(Entry e, int dataSetIndex) { } mYValCount += 1; - mYValueSum += val; handleEmptyAxis(getFirstLeft(), getFirstRight()); @@ -729,11 +687,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { boolean removed = mDataSets.get(dataSetIndex).removeEntry(e.getXIndex()); if (removed) { - - float val = e.getVal(); - mYValCount -= 1; - mYValueSum -= val; calcMinMax(mLastStart, mLastEnd); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 278f55c452..c3d43ecafa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -35,11 +35,6 @@ public abstract class DataSet extends BaseDataSet { */ protected List mColors = null; - /** - * the total sum of all y-values - */ - private float mYValueSum = 0f; - /** * label that describes the DataSet or the data the DataSet represents */ @@ -107,7 +102,6 @@ public DataSet(List yVals, String label) { mColors.add(Color.rgb(140, 234, 255)); calcMinMax(mYVals, mLastStart, mLastEnd); - calcYValueSum(); } /** @@ -115,21 +109,6 @@ public DataSet(List yVals, String label) { */ public void notifyDataSetChanged() { calcMinMax(mYVals, mLastStart, mLastEnd); - calcYValueSum(); - } - - /** - * calculates the sum of all y-values - */ - private void calcYValueSum() { - - mYValueSum = 0; - - for (int i = 0; i < mYVals.size(); i++) { - Entry e = mYVals.get(i); - if (e != null) - mYValueSum += Math.abs(e.getVal()); - } } /** @@ -259,11 +238,6 @@ public List getYVals() { return mYVals; } - @Override - public float getYValueSum() { - return mYValueSum; - } - @Override public float getYMin() { return mYMin; @@ -430,8 +404,6 @@ public void addEntry(Entry e) { mYMin = val; } - mYValueSum += val; - // add the entry mYVals.add((T) e); } @@ -466,8 +438,6 @@ public void addEntryOrdered(Entry e) { mYMin = val; } - mYValueSum += val; - if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) { int closestIndex = getEntryIndex(e.getXIndex()); if (mYVals.get(closestIndex).getXIndex() < e.getXIndex()) @@ -496,10 +466,6 @@ public boolean removeEntry(T e) { boolean removed = mYVals.remove(e); if (removed) { - - float val = e.getVal(); - mYValueSum -= val; - calcMinMax(mYVals, mLastStart, mLastEnd); } @@ -531,10 +497,6 @@ public boolean removeFirst() { boolean removed = entry != null; if (removed) { - - float val = entry.getVal(); - mYValueSum -= val; - calcMinMax(mYVals, mLastStart, mLastEnd); } @@ -557,10 +519,6 @@ public boolean removeLast() { boolean removed = entry != null; if (removed) { - - float val = entry.getVal(); - mYValueSum -= val; - calcMinMax(mYVals, mLastStart, mLastEnd); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index ca57116ca4..f1a881ba55 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -38,13 +38,6 @@ public interface IDataSet { */ float getYMax(); - /** - * gets the sum of all y-values - * - * @return - */ - float getYValueSum(); - /** * returns the number of y-values this DataSet represents -> yvals.size() * From a38b9f5daf1227cd607028bb78e1a6f297934957 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 16:47:37 +0200 Subject: [PATCH 0543/1390] More refactoring due to interfaces --- .../charting/charts/BarLineChartBase.java | 5 +- .../mikephil/charting/charts/Chart.java | 17 +- .../data/BarLineScatterCandleBubbleData.java | 2 +- .../mikephil/charting/data/BaseDataSet.java | 148 +++++++++++++- .../mikephil/charting/data/ChartData.java | 22 +- .../mikephil/charting/data/DataSet.java | 192 ------------------ .../charting/data/realm/RealmLineDataSet.java | 5 - .../datainterfaces/datasets/IDataSet.java | 85 ++++++++ .../listener/BarLineChartTouchListener.java | 8 +- .../charting/renderer/DataRenderer.java | 3 +- .../charting/renderer/LineChartRenderer.java | 23 ++- .../LineScatterCandleRadarRenderer.java | 3 +- 12 files changed, 268 insertions(+), 245 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 782f5a86e9..d51496fcf3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -25,6 +25,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; @@ -42,7 +43,7 @@ * @author Philipp Jahoda */ @SuppressLint("RtlHardcoded") -public abstract class BarLineChartBase>> +public abstract class BarLineChartBase>> extends Chart implements BarLineScatterCandleBubbleDataProvider { /** @@ -1237,7 +1238,7 @@ public Entry getEntryByTouchPoint(float x, float y) { * @param y * @return */ - public BarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float y) { + public IBarLineScatterCandleBubbleDataSet getDataSetByTouchPoint(float x, float y) { Highlight h = getHighlightByTouchPoint(x, y); if (h != null) { return mData.getDataSetByIndex(h.getDataSetIndex()); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f4b165ff6e..9681ae5da7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -34,6 +34,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.ChartHighlighter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; @@ -59,7 +60,7 @@ * @author Philipp Jahoda */ @SuppressLint("NewApi") -public abstract class Chart>> extends +public abstract class Chart>> extends ViewGroup implements ChartInterface { @@ -316,7 +317,7 @@ public void setData(T data) { // calculate how many digits are needed calculateFormatter(data.getYMin(), data.getYMax()); - for (DataSet set : mData.getDataSets()) { + for (IDataSet set : mData.getDataSets()) { if (set.needsDefaultFormatter()) set.setValueFormatter(mDefaultFormatter); } @@ -1398,7 +1399,7 @@ public List getEntriesAtIndex(int xIndex) { for (int i = 0; i < mData.getDataSetCount(); i++) { - DataSet set = mData.getDataSetByIndex(i); + IDataSet set = mData.getDataSetByIndex(i); Entry e = set.getEntryForXIndex(xIndex); @@ -1419,16 +1420,6 @@ public T getData() { return mData; } - /** - * returns the percentage the given value has of the total y-value sum - * - * @param val - * @return - */ - public float getPercentOfTotal(float val) { - return val / mData.getYValueSum() * 100f; - } - /** * Returns the ViewPortHandler of the chart that is responsible for the * content area of the chart and its offsets and dimensions. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 5fb3db1070..8f6da8aeb2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -11,7 +11,7 @@ * @author Philipp Jahoda */ public abstract class BarLineScatterCandleBubbleData> - extends ChartData { + extends ChartData { public BarLineScatterCandleBubbleData() { super(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index e42c2212e6..1851e57330 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -1,7 +1,14 @@ package com.github.mikephil.charting.data; +import android.graphics.Color; +import android.graphics.Typeface; + +import com.github.mikephil.charting.formatter.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; import java.util.List; /** @@ -29,13 +36,41 @@ public abstract class BaseDataSet implements IDataSet { */ protected int mLastEnd = 0; + /** + * if true, value highlightning is enabled + */ + protected boolean mHighlightEnabled = true; + + /** + * custom formatter that is used instead of the auto-formatter if set + */ + protected transient ValueFormatter mValueFormatter; + + /** + * the color used for the value-text + */ + protected int mValueColor = Color.BLACK; + + /** + * the typeface used for the value text + */ + protected Typeface mValueTypeface; + + /** + * if true, y-values are drawn on the chart + */ + protected boolean mDrawValues = true; /** - * calc minimum and maximum y value + * the size of the value-text labels */ - protected void calcMinMax(List values, int start, int end) { + protected float mValueTextSize = 17f; - if(values == null) + + @Override + public void calcMinMax(List values, int start, int end) { + + if (values == null) return; final int yValCount = values.size(); @@ -76,5 +111,112 @@ protected void calcMinMax(List values, int start, int end) { } } + @Override + public void setHighlightEnabled(boolean enabled) { + mHighlightEnabled = enabled; + } + + @Override + public boolean isHighlightEnabled() { + return mHighlightEnabled; + } + + @Override + public void addEntry(T e) { + + if (e == null) + return; + + float val = e.getVal(); + + List yVals = getYVals(); + if (yVals == null) { + yVals = new ArrayList(); + } + + if (yVals.size() == 0) { + mYMax = val; + mYMin = val; + } else { + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; + } + + // add the entry + yVals.add(e); + } + @Override + public boolean removeEntry(T e) { + + if (e == null) + return false; + + List yVals = getYVals(); + + if (yVals == null) + return false; + + // remove the entry + boolean removed = yVals.remove(e); + + if (removed) { + calcMinMax(yVals, mLastStart, mLastEnd); + } + + return removed; + } + + /** + * Removes the Entry object that has the given xIndex from the DataSet. + * Returns true if an Entry was removed, false if no Entry could be removed. + * + * @param xIndex + */ + public boolean removeEntry(int xIndex) { + + T e = getEntryForXIndex(xIndex); + return removeEntry(e); + } + + @Override + public boolean needsDefaultFormatter() { + if (mValueFormatter == null) + return true; + if (mValueFormatter instanceof DefaultValueFormatter) + return true; + + return false; + } + + @Override + public void setValueFormatter(ValueFormatter f) { + + if (f == null) + return; + else + mValueFormatter = f; + } + + @Override + public void setValueTextColor(int color) { + mValueColor = color; + } + + @Override + public void setValueTypeface(Typeface tf) { + mValueTypeface = tf; + } + + @Override + public void setValueTextSize(float size) { + mValueTextSize = Utils.convertDpToPixel(size); + } + + @Override + public void setDrawValues(boolean enabled) { + this.mDrawValues = enabled; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index e7063b0964..1f80e4c13a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -20,7 +20,7 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> implements IChartData { +public abstract class ChartData> { /** * maximum y-value in the y-value array across all axes @@ -369,7 +369,6 @@ public float getXValAverageLength() { return mXValAverageLength; } - @Override public int getYValCount() { return mYValCount; } @@ -403,7 +402,6 @@ public void removeXValue(int index) { mXVals.remove(index); } - @Override public List getDataSets() { return mDataSets; } @@ -494,7 +492,6 @@ public T getDataSetByLabel(String label, boolean ignorecase) { return mDataSets.get(index); } - @Override public T getDataSetByIndex(int index) { if (mDataSets == null || index < 0 || index >= mDataSets.size()) @@ -684,7 +681,7 @@ public boolean removeEntry(Entry e, int dataSetIndex) { return false; // remove the entry from the dataset - boolean removed = mDataSets.get(dataSetIndex).removeEntry(e.getXIndex()); + boolean removed = mDataSets.get(dataSetIndex).removeEntry(e); if (removed) { mYValCount -= 1; @@ -776,7 +773,6 @@ public int[] getColors() { return colors; } - @Override public int getIndexOfDataSet(T dataSet) { for (int i = 0; i < mDataSets.size(); i++) { if (mDataSets.get(i) == dataSet) @@ -842,7 +838,7 @@ public void setValueFormatter(ValueFormatter f) { if (f == null) return; else { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueFormatter(f); } } @@ -855,7 +851,7 @@ public void setValueFormatter(ValueFormatter f) { * @param color */ public void setValueTextColor(int color) { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTextColor(color); } } @@ -867,7 +863,7 @@ public void setValueTextColor(int color) { * @param tf */ public void setValueTypeface(Typeface tf) { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTypeface(tf); } } @@ -879,7 +875,7 @@ public void setValueTypeface(Typeface tf) { * @param size */ public void setValueTextSize(float size) { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setValueTextSize(size); } } @@ -891,7 +887,7 @@ public void setValueTextSize(float size) { * @param enabled */ public void setDrawValues(boolean enabled) { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setDrawValues(enabled); } } @@ -902,7 +898,7 @@ public void setDrawValues(boolean enabled) { * be highlighted programmatically or by touch gesture. */ public void setHighlightEnabled(boolean enabled) { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { set.setHighlightEnabled(enabled); } } @@ -914,7 +910,7 @@ public void setHighlightEnabled(boolean enabled) { * @return */ public boolean isHighlightEnabled() { - for (IDataSet set : mDataSets) { + for (IDataSet set : mDataSets) { if (!set.isHighlightEnabled()) return false; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index c3d43ecafa..59559febde 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -45,40 +45,11 @@ public abstract class DataSet extends BaseDataSet { */ private boolean mVisible = true; - /** - * if true, y-values are drawn on the chart - */ - protected boolean mDrawValues = true; - - /** - * the color used for the value-text - */ - private int mValueColor = Color.BLACK; - - /** - * the size of the value-text labels - */ - private float mValueTextSize = 17f; - - /** - * the typeface used for the value text - */ - private Typeface mValueTypeface; - - /** - * custom formatter that is used instead of the auto-formatter if set - */ - protected transient ValueFormatter mValueFormatter; - /** * this specifies which axis this DataSet should be plotted against */ protected AxisDependency mAxisDependency = AxisDependency.LEFT; - /** - * if true, value highlightning is enabled - */ - protected boolean mHighlightEnabled = true; /** * Creates a new DataSet object with the given values it represents. Also, a @@ -111,15 +82,6 @@ public void notifyDataSetChanged() { calcMinMax(mYVals, mLastStart, mLastEnd); } - /** - * Returns the average value across all entries in this DataSet. - * - * @return - */ - public float getAverage() { - return (float) getYValueSum() / (float) getValueCount(); - } - @Override public int getEntryCount() { return mYVals.size(); @@ -354,17 +316,6 @@ public void setAxisDependency(AxisDependency dependency) { mAxisDependency = dependency; } - /** - * set this to true to draw y-values on the chart NOTE (for bar and - * linechart): if "maxvisiblecount" is reached, no values will be drawn even - * if this is enabled - * - * @param enabled - */ - public void setDrawValues(boolean enabled) { - this.mDrawValues = enabled; - } - /** * returns true if y-value drawing is enabled, false if not * @@ -374,40 +325,6 @@ public boolean isDrawValuesEnabled() { return mDrawValues; } - /** - * Adds an Entry to the DataSet dynamically. - * Entries are added to the end of the list. - * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. - * - * @param e - */ - @SuppressWarnings("unchecked") - public void addEntry(Entry e) { - - if (e == null) - return; - - float val = e.getVal(); - - if (mYVals == null) { - mYVals = new ArrayList(); - } - - if (mYVals.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } - - // add the entry - mYVals.add((T) e); - } - /** * Adds an Entry to the DataSet dynamically. * Entries are added to their appropriate index respective to it's x-index. @@ -449,41 +366,6 @@ public void addEntryOrdered(Entry e) { mYVals.add((T) e); } - /** - * Removes an Entry from the DataSets entries array. This will also - * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could - * be removed. - * - * @param e - */ - public boolean removeEntry(T e) { - - if (e == null) - return false; - - // remove the entry - boolean removed = mYVals.remove(e); - - if (removed) { - calcMinMax(mYVals, mLastStart, mLastEnd); - } - - return removed; - } - - /** - * Removes the Entry object that has the given xIndex from the DataSet. - * Returns true if an Entry was removed, false if no Entry could be removed. - * - * @param xIndex - */ - public boolean removeEntry(int xIndex) { - - T e = getEntryForXIndex(xIndex); - return removeEntry(e); - } - /** * Removes the first Entry (at index 0) of this DataSet from the entries array. * Returns true if successful, false if not. @@ -629,21 +511,6 @@ public void resetColors() { mColors = new ArrayList(); } - /** - * If set to true, value highlighting is enabled which means that values can - * be highlighted programmatically or by touch gesture. - * - * @param enabled - */ - public void setHighlightEnabled(boolean enabled) { - mHighlightEnabled = enabled; - } - - @Override - public boolean isHighlightEnabled() { - return mHighlightEnabled; - } - /** * Returns the position of the provided entry in the DataSets Entry array. * Returns -1 if doesn't exist. @@ -661,23 +528,6 @@ public int getEntryPosition(Entry e) { return -1; } - /** - * Sets the formatter to be used for drawing the values inside the chart. If - * no formatter is set, the chart will automatically determine a reasonable - * formatting (concerning decimals) for all the values that are drawn inside - * the chart. Use chart.getDefaultValueFormatter() to use the formatter - * calculated by the chart. - * - * @param f - */ - public void setValueFormatter(ValueFormatter f) { - - if (f == null) - return; - else - mValueFormatter = f; - } - /** * Returns the formatter used for drawing the values inside the chart. * @@ -689,56 +539,14 @@ public ValueFormatter getValueFormatter() { return mValueFormatter; } - /** - * If this component has no ValueFormatter or is only equipped with the - * default one (no custom set), return true. - * - * @return - */ - public boolean needsDefaultFormatter() { - if (mValueFormatter == null) - return true; - if (mValueFormatter instanceof DefaultValueFormatter) - return true; - - return false; - } - - /** - * Sets the color the value-labels of this DataSet should have. - * - * @param color - */ - public void setValueTextColor(int color) { - mValueColor = color; - } - public int getValueTextColor() { return mValueColor; } - /** - * Sets a Typeface for the value-labels of this DataSet. - * - * @param tf - */ - public void setValueTypeface(Typeface tf) { - mValueTypeface = tf; - } - public Typeface getValueTypeface() { return mValueTypeface; } - /** - * Sets the text-size of the value-labels of this DataSet in dp. - * - * @param size - */ - public void setValueTextSize(float size) { - mValueTextSize = Utils.convertDpToPixel(size); - } - /** * Returns the text-size of the labels that are displayed above the values. * diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 0150d1f907..81d5f5a32b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -34,11 +34,6 @@ public float getYMax() { return 0; } - @Override - public float getYValueSum() { - return 0; - } - @Override public int getEntryCount() { return 0; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index f1a881ba55..0bdcf881ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -1,7 +1,10 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import android.graphics.Typeface; + import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.List; @@ -59,6 +62,11 @@ public interface IDataSet { */ List getColors(); + /** + * calc minimum and maximum y value + */ + void calcMinMax(List values, int start, int end); + /** * Returns the first Entry object found at the given xIndex with binary * search. If the no Entry at the specified x-index is found, this method @@ -87,4 +95,81 @@ public interface IDataSet { * @return */ boolean isHighlightEnabled(); + + /** + * If set to true, value highlighting is enabled which means that values can + * be highlighted programmatically or by touch gesture. + * + * @param enabled + */ + void setHighlightEnabled(boolean enabled); + + /** + * Adds an Entry to the DataSet dynamically. + * Entries are added to the end of the list. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. + * + * @param e + */ + void addEntry(T e); + + /** + * Removes an Entry from the DataSets entries array. This will also + * recalculate the current minimum and maximum values of the DataSet and the + * value-sum. Returns true if an Entry was removed, false if no Entry could + * be removed. + * + * @param e + */ + boolean removeEntry(T e); + + /** + * If this component has no ValueFormatter or is only equipped with the + * default one (no custom set), return true. + * + * @return + */ + boolean needsDefaultFormatter(); + + /** + * Sets the formatter to be used for drawing the values inside the chart. If + * no formatter is set, the chart will automatically determine a reasonable + * formatting (concerning decimals) for all the values that are drawn inside + * the chart. Use chart.getDefaultValueFormatter() to use the formatter + * calculated by the chart. + * + * @param f + */ + void setValueFormatter(ValueFormatter f); + + /** + * Sets the color the value-labels of this DataSet should have. + * + * @param color + */ + void setValueTextColor(int color); + + /** + * Sets a Typeface for the value-labels of this DataSet. + * + * @param tf + */ + void setValueTypeface(Typeface tf); + + /** + * Sets the text-size of the value-labels of this DataSet in dp. + * + * @param size + */ + void setValueTextSize(float size); + + /** + * set this to true to draw y-values on the chart NOTE (for bar and + * linechart): if "maxvisiblecount" is reached, no values will be drawn even + * if this is enabled + * + * @param enabled + */ + void setDrawValues(boolean enabled); } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 8a6f3d4a81..d214374228 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -17,6 +17,8 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -26,7 +28,7 @@ * * @author Philipp Jahoda */ -public class BarLineChartTouchListener extends ChartTouchListener>>> { +public class BarLineChartTouchListener extends ChartTouchListener>>> { /** the original touch-matrix from the chart */ private Matrix mMatrix = new Matrix(); @@ -44,7 +46,7 @@ public class BarLineChartTouchListener extends ChartTouchListener mClosestDataSetToTouch; + private IDataSet mClosestDataSetToTouch; /** used for tracking velocity of dragging */ private VelocityTracker mVelocityTracker; @@ -53,7 +55,7 @@ public class BarLineChartTouchListener extends ChartTouchListener>> chart, Matrix touchMatrix) { + public BarLineChartTouchListener(BarLineChartBase>> chart, Matrix touchMatrix) { super(chart); this.mMatrix = touchMatrix; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 87daddac45..202249bb2c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -100,7 +101,7 @@ public Paint getPaintRender() { * * @param set */ - protected void applyValueTextStyle(DataSet set) { + protected void applyValueTextStyle(IDataSet set) { mValuePaint.setColor(set.getValueTextColor()); mValuePaint.setTypeface(set.getValueTypeface()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index bb86402091..dff567b086 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -14,6 +14,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -67,7 +68,7 @@ public void initBuffers() { mCircleBuffers = new CircleBuffer[lineData.getDataSetCount()]; for (int i = 0; i < mLineBuffers.length; i++) { - LineDataSet set = lineData.getDataSetByIndex(i); + ILineDataSet set = lineData.getDataSetByIndex(i); mLineBuffers[i] = new LineBuffer(set.getEntryCount() * 4 - 4); mCircleBuffers[i] = new CircleBuffer(set.getEntryCount() * 2); } @@ -95,7 +96,7 @@ public void drawData(Canvas c) { LineData lineData = mChart.getLineData(); - for (LineDataSet set : lineData.getDataSets()) { + for (ILineDataSet set : lineData.getDataSets()) { if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); @@ -104,7 +105,7 @@ public void drawData(Canvas c) { c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } - protected void drawDataSet(Canvas c, LineDataSet dataSet) { + protected void drawDataSet(Canvas c, ILineDataSet dataSet) { List entries = dataSet.getYVals(); @@ -134,7 +135,7 @@ protected void drawDataSet(Canvas c, LineDataSet dataSet) { * @param dataSet * @param entries */ - protected void drawCubic(Canvas c, LineDataSet dataSet, List entries) { + protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -264,7 +265,7 @@ protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transfo * @param dataSet * @param entries */ - protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { + protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); @@ -343,7 +344,7 @@ protected void drawLinear(Canvas c, LineDataSet dataSet, List entries) { } } - protected void drawLinearFill(Canvas c, LineDataSet dataSet, List entries, int minx, + protected void drawLinearFill(Canvas c, ILineDataSet dataSet, List entries, int minx, int maxx, Transformer trans) { @@ -414,11 +415,11 @@ public void drawValues(Canvas c) { if (mChart.getLineData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - List dataSets = mChart.getLineData().getDataSets(); + List dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - LineDataSet dataSet = dataSets.get(i); + ILineDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -479,11 +480,11 @@ protected void drawCircles(Canvas c) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - List dataSets = mChart.getLineData().getDataSets(); + List dataSets = mChart.getLineData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - LineDataSet dataSet = dataSets.get(i); + ILineDataSet dataSet = dataSets.get(i); if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled()) continue; @@ -545,7 +546,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { - LineDataSet set = mChart.getLineData().getDataSetByIndex(indices[i] + ILineDataSet set = mChart.getLineData().getDataSetByIndex(indices[i] .getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index bc5ebd063e..2f5189e44e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.LineScatterCandleRadarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineScatterCandleRadarDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; /** @@ -28,7 +29,7 @@ public LineScatterCandleRadarRenderer(ChartAnimator animator, ViewPortHandler vi * @param pts the transformed x- and y-position of the lines * @param set the currently drawn dataset */ - protected void drawHighlightLines(Canvas c, float[] pts, LineScatterCandleRadarDataSet set) { + protected void drawHighlightLines(Canvas c, float[] pts, ILineScatterCandleRadarDataSet set) { // set color and stroke-width mHighlightPaint.setColor(set.getHighLightColor()); From 7de07205eff46026913a9a65399070f3a0fc9852 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 17:00:31 +0200 Subject: [PATCH 0544/1390] More refactoring, introducing base interface --- .../mpchartexample/RealmDatabaseActivity.java | 21 +++++++------- .../data/BarLineScatterCandleBubbleData.java | 1 + .../mikephil/charting/data/ChartData.java | 2 +- .../datainterfaces/datasets/IBaseDataSet.java | 29 +++++++++++++++++++ .../datainterfaces/datasets/IDataSet.java | 22 +------------- 5 files changed, 42 insertions(+), 33 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 255613bdbe..8a0a75e605 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -10,7 +10,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.RealmLineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -86,16 +85,16 @@ private void setData(int count, float range) { RealmLineDataSet set1 = new RealmLineDataSet(); // set the line to be drawn like this "- - - - - -" - set1.enableDashedLine(10f, 5f, 0f); - set1.enableDashedHighlightLine(10f, 5f, 0f); - set1.setColor(Color.BLACK); - set1.setCircleColor(Color.BLACK); - set1.setLineWidth(1f); - set1.setCircleSize(3f); - set1.setDrawCircleHole(false); - set1.setValueTextSize(9f); - set1.setFillAlpha(65); - set1.setFillColor(Color.BLACK); +// set1.enableDashedLine(10f, 5f, 0f); +// set1.enableDashedHighlightLine(10f, 5f, 0f); +// set1.setColor(Color.BLACK); +// set1.setCircleColor(Color.BLACK); +// set1.setLineWidth(1f); +// set1.setCircleSize(3f); +// set1.setDrawCircleHole(false); +// set1.setValueTextSize(9f); +// set1.setFillAlpha(65); +// set1.setFillColor(Color.BLACK); // set1.setDrawFilled(true); // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 8f6da8aeb2..1962545701 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.data; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 1f80e4c13a..4254233d5f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -20,7 +20,7 @@ * * @author Philipp Jahoda */ -public abstract class ChartData> { +public abstract class ChartData> { /** * maximum y-value in the y-value array across all axes diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java new file mode 100644 index 0000000000..46b4999e4b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java @@ -0,0 +1,29 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.Entry; + +/** + * Created by philipp on 21/10/15. + */ +public interface IBaseDataSet { + + /** + * Adds an Entry to the DataSet dynamically. + * Entries are added to the end of the list. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. + * + * @param e + */ + void addEntry(T e); + + /** + * Removes an Entry from the DataSets entries array. This will also + * recalculate the current minimum and maximum values of the DataSet and the + * value-sum. Returns true if an Entry was removed, false if no Entry could + * be removed. + * + * @param e + */ + boolean removeEntry(T e); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index 0bdcf881ec..dd1818595a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -11,7 +11,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public interface IDataSet { +public interface IDataSet extends IBaseDataSet { /** * Returns the label string that describes the DataSet. @@ -104,26 +104,6 @@ public interface IDataSet { */ void setHighlightEnabled(boolean enabled); - /** - * Adds an Entry to the DataSet dynamically. - * Entries are added to the end of the list. - * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. - * - * @param e - */ - void addEntry(T e); - - /** - * Removes an Entry from the DataSets entries array. This will also - * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could - * be removed. - * - * @param e - */ - boolean removeEntry(T e); - /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. From 0307b7d76fc71957efe3588a0a2504ce9c52b864 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 17:13:54 +0200 Subject: [PATCH 0545/1390] Interface improvements, get rid of IBaseDataSet --- .../mikephil/charting/data/BaseDataSet.java | 1 + .../mikephil/charting/data/ChartData.java | 24 +++++++++------ .../datainterfaces/datasets/IBaseDataSet.java | 29 ------------------- .../datainterfaces/datasets/IDataSet.java | 22 +++++++++++++- 4 files changed, 37 insertions(+), 39 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 1851e57330..eba52650b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBaseDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 4254233d5f..1c8f5c7e1f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.data.IChartData; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBaseDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.ArrayList; @@ -622,7 +623,7 @@ public void addEntry(Entry e, int dataSetIndex) { if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { float val = e.getVal(); - T set = mDataSets.get(dataSetIndex); + IDataSet set = mDataSets.get(dataSetIndex); if (mYValCount == 0) { mYMin = val; @@ -680,16 +681,21 @@ public boolean removeEntry(Entry e, int dataSetIndex) { if (e == null || dataSetIndex >= mDataSets.size()) return false; - // remove the entry from the dataset - boolean removed = mDataSets.get(dataSetIndex).removeEntry(e); + IDataSet set = mDataSets.get(dataSetIndex); - if (removed) { - mYValCount -= 1; + if(set != null) { + // remove the entry from the dataset + boolean removed = set.removeEntry(e); - calcMinMax(mLastStart, mLastEnd); - } + if (removed) { + mYValCount -= 1; - return removed; + calcMinMax(mLastStart, mLastEnd); + } + + return removed; + } else + return false; } /** @@ -706,7 +712,7 @@ public boolean removeEntry(int xIndex, int dataSetIndex) { if (dataSetIndex >= mDataSets.size()) return false; - T dataSet = mDataSets.get(dataSetIndex); + IDataSet dataSet = mDataSets.get(dataSetIndex); Entry e = dataSet.getEntryForXIndex(xIndex); if (e == null || e.getXIndex() != xIndex) diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java deleted file mode 100644 index 46b4999e4b..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBaseDataSet.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; - -import com.github.mikephil.charting.data.Entry; - -/** - * Created by philipp on 21/10/15. - */ -public interface IBaseDataSet { - - /** - * Adds an Entry to the DataSet dynamically. - * Entries are added to the end of the list. - * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. - * - * @param e - */ - void addEntry(T e); - - /** - * Removes an Entry from the DataSets entries array. This will also - * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could - * be removed. - * - * @param e - */ - boolean removeEntry(T e); -} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index dd1818595a..0bdcf881ec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -11,7 +11,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public interface IDataSet extends IBaseDataSet { +public interface IDataSet { /** * Returns the label string that describes the DataSet. @@ -104,6 +104,26 @@ public interface IDataSet extends IBaseDataSet { */ void setHighlightEnabled(boolean enabled); + /** + * Adds an Entry to the DataSet dynamically. + * Entries are added to the end of the list. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. + * + * @param e + */ + void addEntry(T e); + + /** + * Removes an Entry from the DataSets entries array. This will also + * recalculate the current minimum and maximum values of the DataSet and the + * value-sum. Returns true if an Entry was removed, false if no Entry could + * be removed. + * + * @param e + */ + boolean removeEntry(T e); + /** * If this component has no ValueFormatter or is only equipped with the * default one (no custom set), return true. From 0d6dc4e44d87824a2530b308329c9db05df8e284 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 21 Oct 2015 17:29:15 +0200 Subject: [PATCH 0546/1390] Further implementation of interfaces --- .../mikephil/charting/charts/BarChart.java | 3 ++- .../mikephil/charting/data/BarData.java | 16 ++++++------ .../mikephil/charting/data/BarDataSet.java | 7 +++--- .../BarLineScatterCandleBubbleDataSet.java | 2 +- .../mikephil/charting/data/BubbleData.java | 18 +++++++------ .../mikephil/charting/data/BubbleDataSet.java | 25 ++++++++----------- .../mikephil/charting/data/CandleData.java | 16 ++++++------ .../mikephil/charting/data/CandleDataSet.java | 15 ++++++----- .../mikephil/charting/data/ScatterData.java | 18 +++++++------ .../charting/data/ScatterDataSet.java | 9 +++---- .../datainterfaces/datasets/IBarDataSet.java | 9 +++++++ .../datasets/IBubbleDataSet.java | 18 +++++++++++++ .../datasets/ICandleDataSet.java | 9 +++++++ .../datasets/IScatterDataSet.java | 16 ++++++++++++ 14 files changed, 117 insertions(+), 64 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 35bdd81f8a..26782e2f36 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; @@ -106,7 +107,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { */ public RectF getBarBounds(BarEntry e) { - BarDataSet set = mData.getDataSetForEntry(e); + IBarDataSet set = mData.getDataSetForEntry(e); if (set == null) return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 5da2ea5718..4af86eae6c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; + import java.util.ArrayList; import java.util.List; @@ -9,7 +11,7 @@ * * @author Philipp Jahoda */ -public class BarData extends BarLineScatterCandleBubbleData { +public class BarData extends BarLineScatterCandleBubbleData { /** the space that is left between groups of bars */ private float mGroupSpace = 0.8f; @@ -31,24 +33,24 @@ public BarData(String[] xVals) { super(xVals); } - public BarData(List xVals, List dataSets) { + public BarData(List xVals, List dataSets) { super(xVals, dataSets); } - public BarData(String[] xVals, List dataSets) { + public BarData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public BarData(List xVals, BarDataSet dataSet) { + public BarData(List xVals, IBarDataSet dataSet) { super(xVals, toList(dataSet)); } - public BarData(String[] xVals, BarDataSet dataSet) { + public BarData(String[] xVals, IBarDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(BarDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(IBarDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index e339964e96..013fb39249 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -100,8 +100,9 @@ private void calcStackSize(List yVals) { } @Override - protected void calcMinMax(int start, int end) { - final int yValCount = mYVals.size(); + public void calcMinMax(List values, int start, int end) { + + final int yValCount = values.size(); if (yValCount == 0) return; @@ -121,7 +122,7 @@ protected void calcMinMax(int start, int end) { for (int i = start; i <= endValue; i++) { - BarEntry e = mYVals.get(i); + BarEntry e = values.get(i); if (e != null && !Float.isNaN(e.getVal())) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index d7499b4b96..d8dac4dd23 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -10,7 +10,7 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleBubbleDataSet extends DataSet { +public abstract class BarLineScatterCandleBubbleDataSet extends DataSet{ /** default highlight color */ protected int mHighLightColor = Color.rgb(255, 187, 115); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index 67cd2e1bfd..ae349558cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -1,10 +1,12 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; + import java.util.ArrayList; import java.util.List; -public class BubbleData extends BarLineScatterCandleBubbleData { +public class BubbleData extends BarLineScatterCandleBubbleData { public BubbleData() { super(); @@ -18,24 +20,24 @@ public BubbleData(String[] xVals) { super(xVals); } - public BubbleData(List xVals, List dataSets) { + public BubbleData(List xVals, List dataSets) { super(xVals, dataSets); } - public BubbleData(String[] xVals, List dataSets) { + public BubbleData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public BubbleData(List xVals, BubbleDataSet dataSet) { + public BubbleData(List xVals, IBubbleDataSet dataSet) { super(xVals, toList(dataSet)); } - public BubbleData(String[] xVals, BubbleDataSet dataSet) { + public BubbleData(String[] xVals, IBubbleDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(BubbleDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(IBubbleDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } @@ -47,7 +49,7 @@ private static List toList(BubbleDataSet dataSet) { * @param width */ public void setHighlightCircleWidth(float width) { - for (BubbleDataSet set : mDataSets) { + for (IBubbleDataSet set : mDataSets) { set.setHighlightCircleWidth(width); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 759b7307fb..317fee4e89 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -3,12 +3,14 @@ import android.graphics.Color; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; -public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet { +public class BubbleDataSet extends BarLineScatterCandleBubbleDataSet implements IBubbleDataSet { // NOTE: Do not initialize these, as the calcMinMax is called by the super, // and the initializers are called after that and can reset the values @@ -22,12 +24,7 @@ public BubbleDataSet(List yVals, String label) { super(yVals, label); } - /** - * Sets the width of the circle that surrounds the bubble when highlighted, - * in dp. - * - * @param width - */ + @Override public void setHighlightCircleWidth(float width) { mHighlightCircleWidth = Utils.convertDpToPixel(width); } @@ -46,30 +43,28 @@ public void setColor(int color, int alpha) { } @Override - protected void calcMinMax(int start, int end) { - if (mYVals.size() == 0) + public void calcMinMax(List values, int start, int end) { + if (values.size() == 0) return; - final List entries = getYVals(); - int endValue; if (end == 0) - endValue = mYVals.size() - 1; + endValue = values.size() - 1; else endValue = end; mLastStart = start; mLastEnd = endValue; - mYMin = yMin(entries.get(start)); - mYMax = yMax(entries.get(start)); + mYMin = yMin(values.get(start)); + mYMax = yMax(values.get(start)); // need chart width to guess this properly for (int i = start; i <= endValue; i++) { - final BubbleEntry entry = entries.get(i); + final BubbleEntry entry = values.get(i); final float ymin = yMin(entry); final float ymax = yMax(entry); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index 4794207d14..821993718f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -1,9 +1,11 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; + import java.util.ArrayList; import java.util.List; -public class CandleData extends BarLineScatterCandleBubbleData { +public class CandleData extends BarLineScatterCandleBubbleData { public CandleData() { super(); @@ -17,24 +19,24 @@ public CandleData(String[] xVals) { super(xVals); } - public CandleData(List xVals, List dataSets) { + public CandleData(List xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(String[] xVals, List dataSets) { + public CandleData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public CandleData(List xVals, CandleDataSet dataSet) { + public CandleData(List xVals, ICandleDataSet dataSet) { super(xVals, toList(dataSet)); } - public CandleData(String[] xVals, CandleDataSet dataSet) { + public CandleData(String[] xVals, ICandleDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(CandleDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(ICandleDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 3a7c4041ab..ad9f3913b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -3,6 +3,7 @@ import android.graphics.Paint; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; @@ -14,7 +15,7 @@ * * @author Philipp Jahoda */ -public class CandleDataSet extends LineScatterCandleRadarDataSet { +public class CandleDataSet extends LineScatterCandleRadarDataSet implements ICandleDataSet { /** the width of the shadow of the candle */ private float mShadowWidth = 3f; @@ -69,18 +70,16 @@ public DataSet copy() { } @Override - protected void calcMinMax(int start, int end) { + public void calcMinMax(List values, int start, int end) { // super.calcMinMax(); - if (mYVals.size() == 0) + if (values.size() == 0) return; - List entries = mYVals; - int endValue; - if (end == 0 || end >= mYVals.size()) - endValue = mYVals.size() - 1; + if (end == 0 || end >= values.size()) + endValue = values.size() - 1; else endValue = end; @@ -92,7 +91,7 @@ protected void calcMinMax(int start, int end) { for (int i = start; i <= endValue; i++) { - CandleEntry e = entries.get(i); + CandleEntry e = values.get(i); if (e.getLow() < mYMin) mYMin = e.getLow(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index faf7066add..a9fed8ebba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -1,10 +1,12 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; + import java.util.ArrayList; import java.util.List; -public class ScatterData extends BarLineScatterCandleBubbleData { +public class ScatterData extends BarLineScatterCandleBubbleData { public ScatterData() { super(); @@ -18,24 +20,24 @@ public ScatterData(String[] xVals) { super(xVals); } - public ScatterData(List xVals, List dataSets) { + public ScatterData(List xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(String[] xVals, List dataSets) { + public ScatterData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public ScatterData(List xVals, ScatterDataSet dataSet) { + public ScatterData(List xVals, IScatterDataSet dataSet) { super(xVals, toList(dataSet)); } - public ScatterData(String[] xVals, ScatterDataSet dataSet) { + public ScatterData(String[] xVals, IScatterDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(ScatterDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(IScatterDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } @@ -49,7 +51,7 @@ public float getGreatestShapeSize() { float max = 0f; - for (ScatterDataSet set : mDataSets) { + for (IScatterDataSet set : mDataSets) { float size = set.getScatterShapeSize(); if (size > max) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index f8c6f2ffe8..6ae85a8210 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -4,12 +4,13 @@ import android.graphics.Path; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; -public class ScatterDataSet extends LineScatterCandleRadarDataSet { +public class ScatterDataSet extends LineScatterCandleRadarDataSet implements IScatterDataSet { /** the size the scattershape will have, in screen pixels */ private float mShapeSize = 15f; @@ -61,11 +62,7 @@ public void setScatterShapeSize(float size) { mShapeSize = Utils.convertDpToPixel(size); } - /** - * returns the currently set scatter shape size - * - * @return - */ + @Override public float getScatterShapeSize() { return mShapeSize; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java new file mode 100644 index 0000000000..0d3ff7100f --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.BarEntry; + +/** + * Created by philipp on 21/10/15. + */ +public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java new file mode 100644 index 0000000000..0715a06ea5 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java @@ -0,0 +1,18 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.utils.Utils; + +/** + * Created by philipp on 21/10/15. + */ +public interface IBubbleDataSet extends IBarLineScatterCandleBubbleDataSet { + + /** + * Sets the width of the circle that surrounds the bubble when highlighted, + * in dp. + * + * @param width + */ + void setHighlightCircleWidth(float width); +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java new file mode 100644 index 0000000000..6c6c1e47e9 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java @@ -0,0 +1,9 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.CandleEntry; + +/** + * Created by philipp on 21/10/15. + */ +public interface ICandleDataSet extends IBarLineScatterCandleBubbleDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java new file mode 100644 index 0000000000..6605f3af77 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java @@ -0,0 +1,16 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.Entry; + +/** + * Created by philipp on 21/10/15. + */ +public interface IScatterDataSet extends IBarLineScatterCandleBubbleDataSet { + + /** + * returns the currently set scatter shape size + * + * @return + */ + float getScatterShapeSize(); +} From 9b655d186acfa776b51f078ed6e525bb12e9bf50 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 10:18:52 +0200 Subject: [PATCH 0547/1390] Implement ILineDataInterface --- .../mikephil/charting/charts/Chart.java | 2 +- .../BarLineScatterCandleBubbleDataSet.java | 10 +- .../mikephil/charting/data/BaseDataSet.java | 114 +++++++++++- .../mikephil/charting/data/DataSet.java | 167 +----------------- .../mikephil/charting/data/LineDataSet.java | 54 ++---- .../charting/data/LineRadarDataSet.java | 28 +-- .../data/LineScatterCandleRadarDataSet.java | 11 +- .../IBarLineScatterCandleBubbleDataSet.java | 15 ++ .../datainterfaces/datasets/IDataSet.java | 99 ++++++++++- .../datainterfaces/datasets/ILineDataSet.java | 66 +++++++ .../datasets/ILineRadarDataSet.java | 29 +++ .../ILineScatterCandleRadarDataSet.java | 26 +++ .../charting/renderer/DataRenderer.java | 2 +- .../charting/renderer/LineChartRenderer.java | 2 +- .../github/mikephil/charting/utils/Utils.java | 17 ++ 15 files changed, 390 insertions(+), 252 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 9681ae5da7..9e2646ad1d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -318,7 +318,7 @@ public void setData(T data) { calculateFormatter(data.getYMin(), data.getYMax()); for (IDataSet set : mData.getDataSets()) { - if (set.needsDefaultFormatter()) + if (Utils.needsDefaultFormatter(set.getValueFormatter())) set.setValueFormatter(mDefaultFormatter); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index d8dac4dd23..15424909a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -3,6 +3,8 @@ import android.graphics.Color; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; + import java.util.List; /** @@ -10,7 +12,7 @@ * * @author Philipp Jahoda */ -public abstract class BarLineScatterCandleBubbleDataSet extends DataSet{ +public abstract class BarLineScatterCandleBubbleDataSet extends DataSet implements IBarLineScatterCandleBubbleDataSet { /** default highlight color */ protected int mHighLightColor = Color.rgb(255, 187, 115); @@ -30,11 +32,7 @@ public void setHighLightColor(int color) { mHighLightColor = color; } - /** - * Returns the color that is used for drawing the highlight indicators. - * - * @return - */ + @Override public int getHighLightColor() { return mHighLightColor; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index eba52650b5..29a747e380 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -5,7 +5,6 @@ import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBaseDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; @@ -13,7 +12,9 @@ import java.util.List; /** - * Created by philipp on 21/10/15. + * Created by Philipp Jahoda on 21/10/15. + * This is the base dataset of all DataSets. It's purpose is to implement critical methods + * provided by the IDataSet interface. */ public abstract class BaseDataSet implements IDataSet { @@ -67,6 +68,11 @@ public abstract class BaseDataSet implements IDataSet { */ protected float mValueTextSize = 17f; + /** + * flag that indicates if the DataSet is visible or not + */ + protected boolean mVisible = true; + @Override public void calcMinMax(List values, int start, int end) { @@ -183,13 +189,16 @@ public boolean removeEntry(int xIndex) { } @Override - public boolean needsDefaultFormatter() { - if (mValueFormatter == null) - return true; - if (mValueFormatter instanceof DefaultValueFormatter) - return true; + public int getEntryPosition(T e) { + + List values = getYVals(); + + for (int i = 0; i < values.size(); i++) { + if (e.equalTo(values.get(i))) + return i; + } - return false; + return -1; } @Override @@ -201,6 +210,13 @@ public void setValueFormatter(ValueFormatter f) { mValueFormatter = f; } + @Override + public ValueFormatter getValueFormatter() { + if (mValueFormatter == null) + return new DefaultValueFormatter(1); + return mValueFormatter; + } + @Override public void setValueTextColor(int color) { mValueColor = color; @@ -216,8 +232,90 @@ public void setValueTextSize(float size) { mValueTextSize = Utils.convertDpToPixel(size); } + @Override + public int getValueTextColor() { + return mValueColor; + } + + @Override + public Typeface getValueTypeface() { + return mValueTypeface; + } + + @Override + public float getValueTextSize() { + return mValueTextSize; + } + @Override public void setDrawValues(boolean enabled) { this.mDrawValues = enabled; } + + @Override + public boolean isDrawValuesEnabled() { + return mDrawValues; + } + + @Override + public void setVisible(boolean visible) { + mVisible = visible; + } + + @Override + public boolean isVisible() { + return mVisible; + } + + @Override + public T getEntryForXIndex(int x) { + + List values = getYVals(); + + int index = getEntryIndex(x); + if (index > -1) + return values.get(index); + return null; + } + + @Override + public int getEntryIndex(int x) { + + List values = getYVals(); + + int low = 0; + int high = values.size() - 1; + int closest = -1; + + while (low <= high) { + int m = (high + low) / 2; + + if (x == values.get(m).getXIndex()) { + while (m > 0 && values.get(m - 1).getXIndex() == x) + m--; + + return m; + } + + if (x > values.get(m).getXIndex()) + low = m + 1; + else + high = m - 1; + + closest = m; + } + + return closest; + } + + @Override + public float getYValForXIndex(int xIndex) { + + Entry e = getEntryForXIndex(xIndex); + + if (e != null && e.getXIndex() == xIndex) + return e.getVal(); + else + return Float.NaN; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 59559febde..e6baeb4e25 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -40,11 +40,6 @@ public abstract class DataSet extends BaseDataSet { */ private String mLabel = "DataSet"; - /** - * flag that indicates if the DataSet is visible or not - */ - private boolean mVisible = true; - /** * this specifies which axis this DataSet should be plotted against */ @@ -87,71 +82,6 @@ public int getEntryCount() { return mYVals.size(); } - /** - * Returns the value of the Entry object at the given xIndex. Returns - * Float.NaN if no value is at the given x-index. INFORMATION: This method - * does calculations at runtime. Do not over-use in performance critical - * situations. - * - * @param xIndex - * @return - */ - public float getYValForXIndex(int xIndex) { - - Entry e = getEntryForXIndex(xIndex); - - if (e != null && e.getXIndex() == xIndex) - return e.getVal(); - else - return Float.NaN; - } - - @Override - public T getEntryForXIndex(int x) { - - int index = getEntryIndex(x); - if (index > -1) - return mYVals.get(index); - return null; - } - - /** - * Returns the first Entry index found at the given xIndex with binary - * search. If the no Entry at the specified x-index is found, this method - * returns the index at the closest x-index. Returns -1 if no Entry object - * at that index. INFORMATION: This method does calculations at runtime. Do - * not over-use in performance critical situations. - * - * @param x - * @return - */ - public int getEntryIndex(int x) { - - int low = 0; - int high = mYVals.size() - 1; - int closest = -1; - - while (low <= high) { - int m = (high + low) / 2; - - if (x == mYVals.get(m).getXIndex()) { - while (m > 0 && mYVals.get(m - 1).getXIndex() == x) - m--; - - return m; - } - - if (x > mYVals.get(m).getXIndex()) - low = m + 1; - else - high = m - 1; - - closest = m; - } - - return closest; - } - /** * Returns all Entry objects at the given xIndex. INFORMATION: This method * does calculations at runtime. Do not over-use in performance critical @@ -281,26 +211,6 @@ public String getLabel() { return mLabel; } - /** - * Set the visibility of this DataSet. If not visible, the DataSet will not - * be drawn to the chart upon refreshing it. - * - * @param visible - */ - public void setVisible(boolean visible) { - mVisible = visible; - } - - /** - * Returns true if this DataSet is visible inside the chart, or false if it - * is currently hidden. - * - * @return - */ - public boolean isVisible() { - return mVisible; - } - @Override public AxisDependency getAxisDependency() { return mAxisDependency; @@ -316,15 +226,6 @@ public void setAxisDependency(AxisDependency dependency) { mAxisDependency = dependency; } - /** - * returns true if y-value drawing is enabled, false if not - * - * @return - */ - public boolean isDrawValuesEnabled() { - return mDrawValues; - } - /** * Adds an Entry to the DataSet dynamically. * Entries are added to their appropriate index respective to it's x-index. @@ -483,27 +384,16 @@ public List getColors() { return mColors; } - /** - * Returns the color at the given index of the DataSet's color array. - * Performs a IndexOutOfBounds check by modulus. - * - * @param index - * @return - */ - public int getColor(int index) { - return mColors.get(index % mColors.size()); - } - - /** - * Returns the first color (index 0) of the colors-array this DataSet - * contains. - * - * @return - */ + @Override public int getColor() { return mColors.get(0); } + @Override + public int getColor(int index) { + return mColors.get(index % mColors.size()); + } + /** * Resets all colors of this DataSet and recreates the colors array. */ @@ -511,51 +401,6 @@ public void resetColors() { mColors = new ArrayList(); } - /** - * Returns the position of the provided entry in the DataSets Entry array. - * Returns -1 if doesn't exist. - * - * @param e - * @return - */ - public int getEntryPosition(Entry e) { - - for (int i = 0; i < mYVals.size(); i++) { - if (e.equalTo(mYVals.get(i))) - return i; - } - - return -1; - } - - /** - * Returns the formatter used for drawing the values inside the chart. - * - * @return - */ - public ValueFormatter getValueFormatter() { - if (mValueFormatter == null) - return new DefaultValueFormatter(1); - return mValueFormatter; - } - - public int getValueTextColor() { - return mValueColor; - } - - public Typeface getValueTypeface() { - return mValueTypeface; - } - - /** - * Returns the text-size of the labels that are displayed above the values. - * - * @return - */ - public float getValueTextSize() { - return mValueTextSize; - } - @Override public boolean contains(Entry e) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index a7df7ba0e0..b7d0557aac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -93,11 +93,7 @@ public void setCubicIntensity(float intensity) { mCubicIntensity = intensity; } - /** - * Returns the intensity of the cubic lines (the effect intensity). - * - * @return - */ + @Override public float getCubicIntensity() { return mCubicIntensity; } @@ -112,9 +108,7 @@ public void setCircleSize(float size) { mCircleSize = Utils.convertDpToPixel(size); } - /** - * returns the circlesize - */ + @Override public float getCircleSize() { return mCircleSize; } @@ -141,20 +135,12 @@ public void disableDashedLine() { mDashPathEffect = null; } - /** - * Returns true if the dashed-line effect is enabled, false if not. - * - * @return - */ + @Override public boolean isDashedLineEnabled() { return mDashPathEffect == null ? false : true; } - /** - * returns the DashPathEffect that is set for this DataSet - * - * @return - */ + @Override public DashPathEffect getDashPathEffect() { return mDashPathEffect; } @@ -169,11 +155,7 @@ public void setDrawCircles(boolean enabled) { this.mDrawCircles = enabled; } - /** - * returns true if drawing circles for this DataSet is enabled, false if not - * - * @return - */ + @Override public boolean isDrawCirclesEnabled() { return mDrawCircles; } @@ -188,11 +170,7 @@ public void setDrawCubic(boolean enabled) { mDrawCubic = enabled; } - /** - * returns true if drawing cubic lines is enabled, false if not. - * - * @return - */ + @Override public boolean isDrawCubicEnabled() { return mDrawCubic; } @@ -208,13 +186,7 @@ public List getCircleColors() { return mCircleColors; } - /** - * Returns the color at the given index of the DataSet's circle-color array. - * Performs a IndexOutOfBounds check by modulus. - * - * @param index - * @return - */ + @Override public int getCircleColor(int index) { return mCircleColors.get(index % mCircleColors.size()); } @@ -293,11 +265,7 @@ public void setCircleColorHole(int color) { mCircleColorHole = color; } - /** - * Returns the color of the inner circle. - * - * @return - */ + @Override public int getCircleHoleColor() { return mCircleColorHole; } @@ -311,6 +279,7 @@ public void setDrawCircleHole(boolean enabled) { mDrawCircleHole = enabled; } + @Override public boolean isDrawCircleHoleEnabled() { return mDrawCircleHole; } @@ -329,10 +298,7 @@ public void setFillFormatter(FillFormatter formatter) { mFillFormatter = formatter; } - /** - * Returns the FillFormatter that is set for this DataSet. - * @return - */ + @Override public FillFormatter getFillFormatter() { return mFillFormatter; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 1328122017..9efb327933 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -3,6 +3,7 @@ import android.graphics.Color; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineRadarDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.List; @@ -12,7 +13,7 @@ * * @author Philipp Jahoda */ -public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet { +public abstract class LineRadarDataSet extends LineScatterCandleRadarDataSet implements ILineRadarDataSet { /** the color that is used for filling the line surface */ private int mFillColor = Color.rgb(140, 234, 255); @@ -31,11 +32,7 @@ public LineRadarDataSet(List yVals, String label) { super(yVals, label); } - /** - * returns the color that is used for filling the line surface - * - * @return - */ + @Override public int getFillColor() { return mFillColor; } @@ -49,12 +46,7 @@ public void setFillColor(int color) { mFillColor = color; } - /** - * returns the alpha value that is used for filling the line surface, - * default: 85 - * - * @return - */ + @Override public int getFillAlpha() { return mFillAlpha; } @@ -84,11 +76,7 @@ public void setLineWidth(float width) { mLineWidth = Utils.convertDpToPixel(width); } - /** - * returns the width of the drawn chart line - * - * @return - */ + @Override public float getLineWidth() { return mLineWidth; } @@ -104,11 +92,7 @@ public void setDrawFilled(boolean filled) { mDrawFilled = filled; } - /** - * returns true if filled drawing is enabled, false if not - * - * @return - */ + @Override public boolean isDrawFilledEnabled() { return mDrawFilled; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index 5c0b7f86af..3b9ad6529f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -2,6 +2,7 @@ import android.graphics.DashPathEffect; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineScatterCandleRadarDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.List; @@ -9,7 +10,7 @@ /** * Created by Philipp Jahoda on 11/07/15. */ -public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleBubbleDataSet { +public abstract class LineScatterCandleRadarDataSet extends BarLineScatterCandleBubbleDataSet implements ILineScatterCandleRadarDataSet { protected boolean mDrawVerticalHighlightIndicator = true; protected boolean mDrawHorizontalHighlightIndicator = true; @@ -51,10 +52,12 @@ public void setDrawHighlightIndicators(boolean enabled) { setDrawHorizontalHighlightIndicator(enabled); } + @Override public boolean isVerticalHighlightIndicatorEnabled() { return mDrawVerticalHighlightIndicator; } + @Override public boolean isHorizontalHighlightIndicatorEnabled() { return mDrawHorizontalHighlightIndicator; } @@ -67,10 +70,7 @@ public void setHighlightLineWidth(float width) { mHighlightLineWidth = Utils.convertDpToPixel(width); } - /** - * Returns the line-width in which highlight lines are to be drawn. - * @return - */ + @Override public float getHighlightLineWidth() { return mHighlightLineWidth; } @@ -105,6 +105,7 @@ public boolean isDashedHighlightLineEnabled() { return mHighlightDashPathEffect == null ? false : true; } + @Override public DashPathEffect getDashPathEffectHighlight() { return mHighlightDashPathEffect; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java index a1a488158d..d2eeabd812 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java @@ -6,4 +6,19 @@ * Created by philipp on 21/10/15. */ public interface IBarLineScatterCandleBubbleDataSet extends IDataSet { + + /** + * Returns the color that is used for drawing the highlight indicators. + * + * @return + */ + int getHighLightColor(); + + /** + * Returns true if the dashed-line effect is enabled, false if not. + * If the DashPathEffect object is null, also return false here. + * + * @return + */ + boolean isDashedLineEnabled(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index 0bdcf881ec..87e16dfebc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.List; @@ -62,6 +63,23 @@ public interface IDataSet { */ List getColors(); + /** + * Returns the first color (index 0) of the colors-array this DataSet + * contains. This is only used for performance reasons when only one color is in the colors array (size == 1) + * + * @return + */ + int getColor(); + + /** + * Returns the color at the given index of the DataSet's color array. + * Performs a IndexOutOfBounds check by modulus. + * + * @param index + * @return + */ + int getColor(int index); + /** * calc minimum and maximum y value */ @@ -79,6 +97,29 @@ public interface IDataSet { */ T getEntryForXIndex(int x); + /** + * Returns the first Entry index found at the given xIndex with binary + * search. If the no Entry at the specified x-index is found, this method + * returns the index at the closest x-index. Returns -1 if no Entry object + * at that index. INFORMATION: This method does calculations at runtime. Do + * not over-use in performance critical situations. + * + * @param x + * @return + */ + int getEntryIndex(int x); + + /** + * Returns the value of the Entry object at the given xIndex. Returns + * Float.NaN if no value is at the given x-index. INFORMATION: This method + * does calculations at runtime. Do not over-use in performance critical + * situations. + * + * @param xIndex + * @return + */ + float getYValForXIndex(int xIndex); + /** * Checks if this DataSet contains the specified Entry. Returns true if so, * false if not. NOTE: Performance is pretty bad on this one, do not @@ -125,12 +166,13 @@ public interface IDataSet { boolean removeEntry(T e); /** - * If this component has no ValueFormatter or is only equipped with the - * default one (no custom set), return true. + * Returns the position of the provided entry in the DataSets Entry array. + * Returns -1 if doesn't exist. * + * @param e * @return */ - boolean needsDefaultFormatter(); + int getEntryPosition(T e); /** * Sets the formatter to be used for drawing the values inside the chart. If @@ -143,6 +185,13 @@ public interface IDataSet { */ void setValueFormatter(ValueFormatter f); + /** + * Returns the formatter used for drawing the values inside the chart. + * + * @return + */ + ValueFormatter getValueFormatter(); + /** * Sets the color the value-labels of this DataSet should have. * @@ -164,6 +213,27 @@ public interface IDataSet { */ void setValueTextSize(float size); + /** + * Returns the color that is used for drawing the values inside the chart + * + * @return + */ + int getValueTextColor(); + + /** + * Returns the typeface that is used for drawing the values inside the chart + * + * @return + */ + Typeface getValueTypeface(); + + /** + * Returns the text size that is used for drawing the values inside the chart + * + * @return + */ + float getValueTextSize(); + /** * set this to true to draw y-values on the chart NOTE (for bar and * linechart): if "maxvisiblecount" is reached, no values will be drawn even @@ -172,4 +242,27 @@ public interface IDataSet { * @param enabled */ void setDrawValues(boolean enabled); + + /** + * Returns true if y-value drawing is enabled, false if not + * + * @return + */ + boolean isDrawValuesEnabled(); + + /** + * Set the visibility of this DataSet. If not visible, the DataSet will not + * be drawn to the chart upon refreshing it. + * + * @param visible + */ + void setVisible(boolean visible); + + /** + * Returns true if this DataSet is visible inside the chart, or false if it + * is currently hidden. + * + * @return + */ + boolean isVisible(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java index a5f674b250..21a079a9a0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java @@ -1,10 +1,76 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import android.graphics.DashPathEffect; + import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.FillFormatter; /** * Created by Philpp Jahoda on 21/10/15. */ public interface ILineDataSet extends ILineRadarDataSet { + /** + * Returns the intensity of the cubic lines (the effect intensity). + * Max = 1f = very cubic, Min = 0.05f = low cubic effect, Default: 0.2f + * + * @return + */ + float getCubicIntensity(); + + /** + * Returns true if drawing cubic lines is enabled, false if not. + * + * @return + */ + boolean isDrawCubicEnabled(); + + /** + * Returns the size of the drawn circles. + */ + float getCircleSize(); + + /** + * Returns the color at the given index of the DataSet's circle-color array. + * Performs a IndexOutOfBounds check by modulus. + * + * @param index + * @return + */ + int getCircleColor(int index); + + /** + * Returns true if drawing circles for this DataSet is enabled, false if not + * + * @return + */ + boolean isDrawCirclesEnabled(); + + /** + * Returns the color of the inner circle (the circle-hole). + * + * @return + */ + int getCircleHoleColor(); + + /** + * Returns true if drawing the circle-holes is enabled, false if not. + * + * @return + */ + boolean isDrawCircleHoleEnabled(); + + /** + * Returns the DashPathEffect that is set for this DataSet + * + * @return + */ + DashPathEffect getDashPathEffect(); + + /** + * Returns the FillFormatter that is set for this DataSet. + * + * @return + */ + FillFormatter getFillFormatter(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java index 71e67b4d13..210d6ada82 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java @@ -6,4 +6,33 @@ * Created by Philipp Jahoda on 21/10/15. */ public interface ILineRadarDataSet extends ILineScatterCandleRadarDataSet { + + /** + * Returns the color that is used for filling the line surface area. + * + * @return + */ + int getFillColor(); + + /** + * Returns the alpha value that is used for filling the line surface, + * default: 85 + * + * @return + */ + int getFillAlpha(); + + /** + * Returns the stroke-width of the drawn line + * + * @return + */ + float getLineWidth(); + + /** + * Returns true if filled drawing is enabled, false if not + * + * @return + */ + boolean isDrawFilledEnabled(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java index 852a3ac0ab..a88fe2c593 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java @@ -1,9 +1,35 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import android.graphics.DashPathEffect; + import com.github.mikephil.charting.data.Entry; /** * Created by Philipp Jahoda on 21/10/15. */ public interface ILineScatterCandleRadarDataSet extends IBarLineScatterCandleBubbleDataSet { + + /** + * Returns true if vertical highlight indicator lines are enabled (drawn) + * @return + */ + boolean isVerticalHighlightIndicatorEnabled(); + + /** + * Returns true if vertical highlight indicator lines are enabled (drawn) + * @return + */ + boolean isHorizontalHighlightIndicatorEnabled(); + + /** + * Returns the line-width in which highlight lines are to be drawn. + * @return + */ + float getHighlightLineWidth(); + + /** + * Returns the DashPathEffect that should be used for the highlight indicators. + * @return + */ + DashPathEffect getDashPathEffectHighlight(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 202249bb2c..81e54fb35f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -101,7 +101,7 @@ public Paint getPaintRender() { * * @param set */ - protected void applyValueTextStyle(IDataSet set) { + protected void applyValueTextStyle(IDataSet set) { mValuePaint.setColor(set.getValueTextColor()); mValuePaint.setTypeface(set.getValueTypeface()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index dff567b086..8d4a583937 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -240,7 +240,7 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { mRenderPaint.setPathEffect(null); } - protected void drawCubicFill(Canvas c, LineDataSet dataSet, Path spline, Transformer trans, + protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transformer trans, int from, int to) { if (to - from <= 1) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 8f86e36d72..5075e5d933 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -16,6 +16,8 @@ import android.view.ViewConfiguration; import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.formatter.DefaultValueFormatter; +import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.List; @@ -425,6 +427,21 @@ public static float getMinimumDistance(List valsAtIndex, float return distance; } + /** + * If this component has no ValueFormatter or is only equipped with the + * default one (no custom set), return true. + * + * @return + */ + public static boolean needsDefaultFormatter(ValueFormatter formatter) { + if (formatter == null) + return true; + if (formatter instanceof DefaultValueFormatter) + return true; + + return false; + } + /** * Calculates the position around a center point, depending on the distance * from the center, and the angle of the position around the center. From 48a713affccf89d2671d48cc65466f1f3baa8916 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 10:19:32 +0200 Subject: [PATCH 0548/1390] Update FillFormatter with new interface --- .../github/mikephil/charting/formatter/FillFormatter.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java index fccb6b61a6..1862865e5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java @@ -1,6 +1,6 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** @@ -15,9 +15,9 @@ public interface FillFormatter { * Returns the vertical (y-axis) position where the filled-line of the * LineDataSet should end. * - * @param dataSet the LineDataSet that is currently drawn + * @param dataSet the ILineDataSet that is currently drawn * @param dataProvider * @return */ - float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider); + float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider); } From 6f8158041d1fef4c6174208625a1ad9904fde348 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 10:58:28 +0200 Subject: [PATCH 0549/1390] Library cleanup and fix final compile errors --- .../mpchartexample/AnotherBarActivity.java | 6 +- .../mpchartexample/RealmDatabaseActivity.java | 2 +- .../mikephil/charting/charts/BubbleChart.java | 3 +- .../charting/charts/CombinedChart.java | 23 ++-- .../charting/charts/HorizontalBarChart.java | 4 +- .../mikephil/charting/data/BarDataSet.java | 37 ++---- .../mikephil/charting/data/BubbleDataSet.java | 4 + .../mikephil/charting/data/CandleDataSet.java | 51 ++------- .../mikephil/charting/data/ChartData.java | 6 +- .../mikephil/charting/data/CombinedData.java | 4 +- .../mikephil/charting/data/DataSet.java | 9 -- .../mikephil/charting/data/PieData.java | 13 +++ .../charting/data/ScatterDataSet.java | 8 +- .../charting/data/realm/RealmLineDataSet.java | 107 +++++++++++++++++- .../formatter/DefaultFillFormatter.java | 4 +- .../charting/highlight/BarHighlighter.java | 5 +- .../charting/highlight/ChartHighlighter.java | 3 +- .../highlight/CombinedHighlighter.java | 3 +- .../highlight/HorizontalBarHighlighter.java | 4 +- .../datainterfaces/datasets/IBarDataSet.java | 38 +++++++ .../IBarLineScatterCandleBubbleDataSet.java | 8 -- .../datasets/IBubbleDataSet.java | 12 ++ .../datasets/ICandleDataSet.java | 61 +++++++++- .../datainterfaces/datasets/ILineDataSet.java | 10 +- .../ILineScatterCandleRadarDataSet.java | 2 +- .../datasets/IScatterDataSet.java | 12 +- .../charting/renderer/BarChartRenderer.java | 15 +-- .../renderer/BubbleChartRenderer.java | 25 ++-- .../renderer/CandleStickChartRenderer.java | 56 ++------- .../renderer/HorizontalBarChartRenderer.java | 11 +- .../charting/renderer/LegendRenderer.java | 3 +- .../renderer/ScatterChartRenderer.java | 16 +-- .../charting/utils/SelectionDetail.java | 5 +- 33 files changed, 358 insertions(+), 212 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 0cf9982ef1..47aadc68fd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -19,6 +19,8 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -97,7 +99,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); @@ -201,7 +203,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setColors(ColorTemplate.VORDIPLOM_COLORS); set1.setDrawValues(false); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); BarData data = new BarData(xVals, dataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 8a0a75e605..4cb022367e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -103,7 +103,7 @@ private void setData(int count, float range) { dataSets.add(set1); // add the datasets // create a data object with the datasets - LineData data = new LineData(null, dataSets); + LineData data = new LineData(); // set data mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java index fd99ab45e9..a478b50788 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -6,6 +6,7 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.renderer.BubbleChartRenderer; @@ -49,7 +50,7 @@ protected void calcMinMax() { mXChartMax = (float) mData.getXValCount() - 0.5f; if (mRenderer != null) { - for (BubbleDataSet set : mData.getDataSets()) { + for (IBubbleDataSet set : mData.getDataSets()) { final float xmin = set.getXMin(); final float xmax = set.getXMax(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 8f432611b5..c180bf5071 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; @@ -22,13 +23,15 @@ /** * This chart class allows the combination of lines, bars, scatter and candle * data all displayed in one chart area. - * + * * @author Philipp Jahoda */ public class CombinedChart extends BarLineChartBase implements LineDataProvider, BarDataProvider, ScatterDataProvider, CandleDataProvider, BubbleDataProvider { - /** flag that enables or disables the highlighting arrow */ + /** + * flag that enables or disables the highlighting arrow + */ private boolean mDrawHighlightArrow = false; /** @@ -43,7 +46,7 @@ public class CombinedChart extends BarLineChartBase implements Lin */ private boolean mDrawBarShadow = false; - protected DrawOrder[] mDrawOrder = new DrawOrder[] { + protected DrawOrder[] mDrawOrder = new DrawOrder[]{ DrawOrder.BAR, DrawOrder.BUBBLE, DrawOrder.LINE, DrawOrder.CANDLE, DrawOrder.SCATTER }; @@ -80,14 +83,14 @@ protected void init() { @Override protected void calcMinMax() { super.calcMinMax(); - + if (getBarData() != null || getCandleData() != null || getBubbleData() != null) { mXChartMin = -0.5f; mXChartMax = mData.getXVals().size() - 0.5f; if (getBubbleData() != null) { - for (BubbleDataSet set : getBubbleData().getDataSets()) { + for (IBubbleDataSet set : getBubbleData().getDataSets()) { final float xmin = set.getXMin(); final float xmax = set.getXMax(); @@ -165,7 +168,7 @@ public boolean isDrawHighlightArrowEnabled() { /** * set this to true to draw the highlightning arrow - * + * * @param enabled */ public void setDrawHighlightArrow(boolean enabled) { @@ -175,7 +178,7 @@ public void setDrawHighlightArrow(boolean enabled) { /** * If set to true, all values are drawn above their bars, instead of below * their top. - * + * * @param enabled */ public void setDrawValueAboveBar(boolean enabled) { @@ -186,7 +189,7 @@ public void setDrawValueAboveBar(boolean enabled) { /** * If set to true, a grey area is drawn behind each bar that indicates the * maximum value. Enabling his will reduce performance by about 50%. - * + * * @param enabled */ public void setDrawBarShadow(boolean enabled) { @@ -195,7 +198,7 @@ public void setDrawBarShadow(boolean enabled) { /** * Returns the currently set draw order. - * + * * @return */ public DrawOrder[] getDrawOrder() { @@ -207,7 +210,7 @@ public DrawOrder[] getDrawOrder() { * earlier you place them in the provided array, the further they will be in * the background. e.g. if you provide new DrawOrer[] { DrawOrder.BAR, * DrawOrder.LINE }, the bars will be drawn behind the lines. - * + * * @param order */ public void setDrawOrder(DrawOrder[] order) { diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 021a5b8257..0c10faba45 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -10,11 +10,11 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.HorizontalBarHighlighter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; @@ -172,7 +172,7 @@ protected void calcModulus() { @Override public RectF getBarBounds(BarEntry e) { - BarDataSet set = mData.getDataSetForEntry(e); + IBarDataSet set = mData.getDataSetForEntry(e); if (set == null) return null; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index 013fb39249..036a43b62f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -3,10 +3,12 @@ import android.graphics.Color; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; + import java.util.ArrayList; import java.util.List; -public class BarDataSet extends BarLineScatterCandleBubbleDataSet { +public class BarDataSet extends BarLineScatterCandleBubbleDataSet implements IBarDataSet { /** space indicator between the bars 0.1f == 10 % */ private float mBarSpace = 0.15f; @@ -150,21 +152,12 @@ public void calcMinMax(List values, int start, int end) { } } - /** - * Returns the maximum number of bars that can be stacked upon another in - * this DataSet. - * - * @return - */ + @Override public int getStackSize() { return mStackSize; } - /** - * Returns true if this DataSet is stacked (stacksize > 1) or not. - * - * @return - */ + @Override public boolean isStacked() { return mStackSize > 1 ? true : false; } @@ -188,11 +181,7 @@ public float getBarSpacePercent() { return mBarSpace * 100f; } - /** - * returns the space between bars as the actual value (0 - 1.0f) - * - * @return - */ + @Override public float getBarSpace() { return mBarSpace; } @@ -217,12 +206,7 @@ public void setBarShadowColor(int color) { mBarShadowColor = color; } - /** - * Returns the color used for drawing the bar-shadows. The bar shadows is a - * surface behind the bar that indicates the maximum value. - * - * @return - */ + @Override public int getBarShadowColor() { return mBarShadowColor; } @@ -237,12 +221,7 @@ public void setHighLightAlpha(int alpha) { mHighLightAlpha = alpha; } - /** - * Returns the alpha value (transparency) that is used for drawing the - * highlight indicator. - * - * @return - */ + @Override public int getHighLightAlpha() { return mHighLightAlpha; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 317fee4e89..8fd141187c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -29,6 +29,7 @@ public void setHighlightCircleWidth(float width) { mHighlightCircleWidth = Utils.convertDpToPixel(width); } + @Override public float getHighlightCircleWidth() { return mHighlightCircleWidth; } @@ -117,14 +118,17 @@ public DataSet copy() { return copied; } + @Override public float getXMax() { return mXMax; } + @Override public float getXMin() { return mXMin; } + @Override public float getMaxSize() { return mMaxSize; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index ad9f3913b9..45fc704c12 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -117,30 +117,21 @@ public void setBodySpace(float space) { mBodySpace = space; } - /** - * Returns the space that is left out on the left and right side of each - * candle. - * - * @return - */ + @Override public float getBodySpace() { return mBodySpace; } /** * Sets the width of the candle-shadow-line in pixels. Default 3f. - * + * * @param width */ public void setShadowWidth(float width) { mShadowWidth = Utils.convertDpToPixel(width); } - /** - * Returns the width of the candle-shadow-line in pixels. - * - * @return - */ + @Override public float getShadowWidth() { return mShadowWidth; } @@ -167,11 +158,7 @@ public void setDecreasingColor(int color) { mDecreasingColor = color; } - /** - * Returns the decreasing color. - * - * @return - */ + @Override public int getDecreasingColor() { return mDecreasingColor; } @@ -186,20 +173,12 @@ public void setIncreasingColor(int color) { mIncreasingColor = color; } - /** - * Returns the increasing color. - * - * @return - */ + @Override public int getIncreasingColor() { return mIncreasingColor; } - /** - * Returns paint style when open > close - * - * @return - */ + @Override public Paint.Style getDecreasingPaintStyle() { return mDecreasingPaintStyle; } @@ -213,11 +192,7 @@ public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { this.mDecreasingPaintStyle = decreasingPaintStyle; } - /** - * Returns paint style when open <= close - * - * @return - */ + @Override public Paint.Style getIncreasingPaintStyle() { return mIncreasingPaintStyle; } @@ -231,11 +206,7 @@ public void setIncreasingPaintStyle(Paint.Style paintStyle) { this.mIncreasingPaintStyle = paintStyle; } - /** - * Returns shadow color for all entries - * - * @return - */ + @Override public int getShadowColor() { return mShadowColor; } @@ -249,11 +220,7 @@ public void setShadowColor(int shadowColor) { this.mShadowColor = shadowColor; } - /** - * Is the shadow color same as the candle color? - * - * @return - */ + @Override public boolean getShadowColorSameAsCandle() { return mShadowColorSameAsCandle; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 1c8f5c7e1f..661796e5b1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -5,10 +5,8 @@ import android.util.Log; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.data.IChartData; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBaseDataSet; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import java.util.ArrayList; @@ -223,7 +221,7 @@ public void calcMinMax(int start, int end) { for (int i = 0; i < mDataSets.size(); i++) { - T set = mDataSets.get(i); + IDataSet set = mDataSets.get(i); set.calcMinMax(set.getYVals(), start, end); if (set.getYMin() < mYMin) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index 62374172b7..b71d066cce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,6 +1,8 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; + import java.util.ArrayList; import java.util.List; @@ -10,7 +12,7 @@ * * @author Philipp Jahoda */ -public class CombinedData extends BarLineScatterCandleBubbleData> { +public class CombinedData extends BarLineScatterCandleBubbleData> { private LineData mLineData; private BarData mBarData; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index e6baeb4e25..8fb49d251b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -140,15 +140,6 @@ public float getYMax() { return mYMax; } - /** - * Returns the number of entries this DataSet holds. - * - * @return - */ - public int getValueCount() { - return mYVals.size(); - } - /** * The xIndex of an Entry object is provided. This method returns the actual * index in the Entry array of the DataSet. IMPORTANT: This method does diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 49af93de1b..5bf01aa6dd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.data; +import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.List; @@ -71,4 +72,16 @@ public PieDataSet getDataSetByLabel(String label, boolean ignorecase) { return ignorecase ? label.equalsIgnoreCase(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null : label.equals(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null; } + + public float getYValueSum() { + + float sum = 0; + + List values = getDataSet().getYVals(); + + for(Entry e : values) + sum += e.getVal(); + + return sum; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index 6ae85a8210..a699ba4fe3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -71,18 +71,14 @@ public float getScatterShapeSize() { * Sets the shape that is drawn on the position where the values are at. If * "CUSTOM" is chosen, you need to call setCustomScatterShape(...) and * provide a path object that is drawn as the custom scattershape. - * + * * @param shape */ public void setScatterShape(ScatterShape shape) { mScatterShape = shape; } - /** - * returns all the different scattershapes the chart uses - * - * @return - */ + @Override public ScatterShape getScatterShape() { return mScatterShape; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 81d5f5a32b..a702697742 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -1,9 +1,12 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.DashPathEffect; + import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import java.util.List; @@ -14,6 +17,101 @@ public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { + @Override + public float getCubicIntensity() { + return 0; + } + + @Override + public boolean isDrawCubicEnabled() { + return false; + } + + @Override + public float getCircleSize() { + return 0; + } + + @Override + public int getCircleColor(int index) { + return 0; + } + + @Override + public boolean isDrawCirclesEnabled() { + return false; + } + + @Override + public int getCircleHoleColor() { + return 0; + } + + @Override + public boolean isDrawCircleHoleEnabled() { + return false; + } + + @Override + public DashPathEffect getDashPathEffect() { + return null; + } + + @Override + public boolean isDashedLineEnabled() { + return false; + } + + @Override + public FillFormatter getFillFormatter() { + return null; + } + + @Override + public int getFillColor() { + return 0; + } + + @Override + public int getFillAlpha() { + return 0; + } + + @Override + public float getLineWidth() { + return 0; + } + + @Override + public boolean isDrawFilledEnabled() { + return false; + } + + @Override + public boolean isVerticalHighlightIndicatorEnabled() { + return false; + } + + @Override + public boolean isHorizontalHighlightIndicatorEnabled() { + return false; + } + + @Override + public float getHighlightLineWidth() { + return 0; + } + + @Override + public DashPathEffect getDashPathEffectHighlight() { + return null; + } + + @Override + public int getHighLightColor() { + return 0; + } + @Override public String getLabel() { return null; @@ -50,8 +148,13 @@ public List getColors() { } @Override - public Entry getEntryForXIndex(int x) { - return null; + public int getColor() { + return 0; + } + + @Override + public int getColor(int index) { + return 0; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index ac1345a022..9e007e43b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** @@ -13,7 +13,7 @@ public class DefaultFillFormatter implements FillFormatter { @Override - public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { float fillMin = 0f; float chartMaxY = dataProvider.getYChartMax(); diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 9f575c3dec..8316960d29 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** @@ -23,7 +24,7 @@ public Highlight getHighlight(float x, float y) { return h; else { - BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + IBarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); if (set.isStacked()) { @@ -95,7 +96,7 @@ else if (dataSetIndex >= setCount) * @param yValue * @return */ - protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xIndex, int dataSetIndex, double yValue) { + protected Highlight getStackedHighlight(Highlight old, IBarDataSet set, int xIndex, int dataSetIndex, double yValue) { BarEntry entry = set.getEntryForXIndex(xIndex); diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index f010d3a5b0..dbb874474c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -5,6 +5,7 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; @@ -95,7 +96,7 @@ protected List getSelectionDetailsAtIndex(int xIndex) { for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { - DataSet dataSet = mChart.getData().getDataSetByIndex(i); + IDataSet dataSet = mChart.getData().getDataSetByIndex(i); // dont include datasets that cannot be highlighted if (!dataSet.isHighlightEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java index d0f2ceea4d..05aceccbed 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; @@ -40,7 +41,7 @@ protected List getSelectionDetailsAtIndex(int xIndex) { for(int j = 0; j < dataObjects.get(i).getDataSetCount(); j++) { - DataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); + IDataSet dataSet = dataObjects.get(i).getDataSetByIndex(j); // dont include datasets that cannot be highlighted if (!dataSet.isHighlightEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 3e814f6a2c..1225c4619c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** @@ -22,7 +22,7 @@ public Highlight getHighlight(float x, float y) { return h; else { - BarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); + IBarDataSet set = mChart.getBarData().getDataSetByIndex(h.getDataSetIndex()); if (set.isStacked()) { diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java index 0d3ff7100f..84a2a8d2d5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java @@ -6,4 +6,42 @@ * Created by philipp on 21/10/15. */ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { + + /** + * Returns the space between bars as the actual value (0 - 1.0f) + * + * @return + */ + float getBarSpace(); + + /** + * Returns true if this DataSet is stacked (stacksize > 1) or not. + * + * @return + */ + boolean isStacked(); + + /** + * Returns the maximum number of bars that can be stacked upon another in + * this DataSet. + * + * @return + */ + int getStackSize(); + + /** + * Returns the color used for drawing the bar-shadows. The bar shadows is a + * surface behind the bar that indicates the maximum value. + * + * @return + */ + int getBarShadowColor(); + + /** + * Returns the alpha value (transparency) that is used for drawing the + * highlight indicator. + * + * @return + */ + int getHighLightAlpha(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java index d2eeabd812..21dfb564ce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java @@ -13,12 +13,4 @@ public interface IBarLineScatterCandleBubbleDataSet extends IDa * @return */ int getHighLightColor(); - - /** - * Returns true if the dashed-line effect is enabled, false if not. - * If the DashPathEffect object is null, also return false here. - * - * @return - */ - boolean isDashedLineEnabled(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java index 0715a06ea5..58b6b3af43 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java @@ -15,4 +15,16 @@ public interface IBubbleDataSet extends IBarLineScatterCandleBubbleDataSet { +public interface ICandleDataSet extends ILineScatterCandleRadarDataSet { + + /** + * Returns the space that is left out on the left and right side of each + * candle. + * + * @return + */ + float getBodySpace(); + + /** + * Returns the width of the candle-shadow-line in pixels. + * + * @return + */ + float getShadowWidth(); + + /** + * Returns shadow color for all entries + * + * @return + */ + public int getShadowColor(); + + /** + * Returns the decreasing color. + * + * @return + */ + int getDecreasingColor(); + + /** + * Returns the increasing color. + * + * @return + */ + int getIncreasingColor(); + + /** + * Returns paint style when open > close + * + * @return + */ + Paint.Style getDecreasingPaintStyle(); + + /** + * Returns paint style when open <= close + * + * @return + */ + Paint.Style getIncreasingPaintStyle(); + + /** + * Is the shadow color same as the candle color? + * + * @return + */ + boolean getShadowColorSameAsCandle(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java index 21a079a9a0..327e742d20 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java @@ -61,12 +61,20 @@ public interface ILineDataSet extends ILineRadarDataSet { boolean isDrawCircleHoleEnabled(); /** - * Returns the DashPathEffect that is set for this DataSet + * Returns the DashPathEffect that is used for drawing the lines. * * @return */ DashPathEffect getDashPathEffect(); + /** + * Returns true if the dashed-line effect is enabled, false if not. + * If the DashPathEffect object is null, also return false here. + * + * @return + */ + boolean isDashedLineEnabled(); + /** * Returns the FillFormatter that is set for this DataSet. * diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java index a88fe2c593..3eca8c274a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java @@ -28,7 +28,7 @@ public interface ILineScatterCandleRadarDataSet extends IBarLin float getHighlightLineWidth(); /** - * Returns the DashPathEffect that should be used for the highlight indicators. + * Returns the DashPathEffect that is used for highlighting. * @return */ DashPathEffect getDashPathEffectHighlight(); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java index 6605f3af77..b62e4f59c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java @@ -1,16 +1,24 @@ package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; /** * Created by philipp on 21/10/15. */ -public interface IScatterDataSet extends IBarLineScatterCandleBubbleDataSet { +public interface IScatterDataSet extends ILineScatterCandleRadarDataSet { /** - * returns the currently set scatter shape size + * Returns the currently set scatter shape size * * @return */ float getScatterShapeSize(); + + /** + * Returns all the different scattershapes the chart uses + * + * @return + */ + ScatterChart.ScatterShape getScatterShape(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 2440850f34..549c39299f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; @@ -54,8 +55,8 @@ public void initBuffers() { mBarBuffers = new BarBuffer[barData.getDataSetCount()]; for (int i = 0; i < mBarBuffers.length; i++) { - BarDataSet set = barData.getDataSetByIndex(i); - mBarBuffers[i] = new BarBuffer(set.getValueCount() * 4 * set.getStackSize(), + IBarDataSet set = barData.getDataSetByIndex(i); + mBarBuffers[i] = new BarBuffer(set.getEntryCount() * 4 * set.getStackSize(), barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } @@ -68,7 +69,7 @@ public void drawData(Canvas c) { for (int i = 0; i < barData.getDataSetCount(); i++) { - BarDataSet set = barData.getDataSetByIndex(i); + IBarDataSet set = barData.getDataSetByIndex(i); if (set.isVisible() && set.getEntryCount() > 0) { drawDataSet(c, set, i); @@ -76,7 +77,7 @@ public void drawData(Canvas c) { } } - protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { + protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -175,7 +176,7 @@ public void drawValues(Canvas c) { // if values are drawn if (passesCheck()) { - List dataSets = mChart.getBarData().getDataSets(); + List dataSets = mChart.getBarData().getDataSets(); final float valueOffsetPlus = Utils.convertDpToPixel(4.5f); float posOffset = 0f; @@ -184,7 +185,7 @@ public void drawValues(Canvas c) { for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { - BarDataSet dataSet = dataSets.get(i); + IBarDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -313,7 +314,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int index = h.getXIndex(); int dataSetIndex = h.getDataSetIndex(); - BarDataSet set = mChart.getBarData().getDataSetByIndex(dataSetIndex); + IBarDataSet set = mChart.getBarData().getDataSetByIndex(dataSetIndex); if (set == null || !set.isHighlightEnabled()) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index b4d1efaeaf..bc615a6a10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -10,8 +10,9 @@ import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -47,7 +48,7 @@ public void drawData(Canvas c) { BubbleData bubbleData = mChart.getBubbleData(); - for (BubbleDataSet set : bubbleData.getDataSets()) { + for (IBubbleDataSet set : bubbleData.getDataSets()) { if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); @@ -63,7 +64,7 @@ protected float getShapeSize(float entrySize, float maxSize, float reference) { return shapeSize; } - protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { + protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -72,8 +73,8 @@ protected void drawDataSet(Canvas c, BubbleDataSet dataSet) { List entries = dataSet.getYVals(); - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); + BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); @@ -127,13 +128,13 @@ public void drawValues(Canvas c) { if (bubbleData.getYValCount() < (int) (Math.ceil((float) (mChart.getMaxVisibleCount()) * mViewPortHandler.getScaleX()))) { - final List dataSets = bubbleData.getDataSets(); + final List dataSets = bubbleData.getDataSets(); float lineHeight = Utils.calcTextHeight(mValuePaint, "1"); for (int i = 0; i < dataSets.size(); i++) { - BubbleDataSet dataSet = dataSets.get(i); + IBubbleDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -153,8 +154,8 @@ public void drawValues(Canvas c) { final List entries = dataSet.getYVals(); - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); + BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = dataSet.getEntryPosition(entryFrom); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); @@ -199,13 +200,13 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (Highlight indice : indices) { - BubbleDataSet dataSet = bubbleData.getDataSetByIndex(indice.getDataSetIndex()); + IBubbleDataSet dataSet = bubbleData.getDataSetByIndex(indice.getDataSetIndex()); if (dataSet == null || !dataSet.isHighlightEnabled()) continue; - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); - Entry entryTo = dataSet.getEntryForXIndex(mMaxX); + BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); + BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = dataSet.getEntryPosition(entryFrom); int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index d233429b38..454547d854 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; @@ -39,9 +40,9 @@ public void initBuffers() { mBodyBuffers = new CandleBodyBuffer[candleData.getDataSetCount()]; for (int i = 0; i < mShadowBuffers.length; i++) { - CandleDataSet set = candleData.getDataSetByIndex(i); - mShadowBuffers[i] = new CandleShadowBuffer(set.getValueCount() * 4); - mBodyBuffers[i] = new CandleBodyBuffer(set.getValueCount() * 4); + ICandleDataSet set = candleData.getDataSetByIndex(i); + mShadowBuffers[i] = new CandleShadowBuffer(set.getEntryCount() * 4); + mBodyBuffers[i] = new CandleBodyBuffer(set.getEntryCount() * 4); } } @@ -50,14 +51,14 @@ public void drawData(Canvas c) { CandleData candleData = mChart.getCandleData(); - for (CandleDataSet set : candleData.getDataSets()) { + for (ICandleDataSet set : candleData.getDataSets()) { if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } - protected void drawDataSet(Canvas c, CandleDataSet dataSet) { + protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -177,45 +178,6 @@ else if (e.getOpen() < e.getClose()) } } - // /** - // * Transforms the values of an entry in order to draw the candle-body. - // * - // * @param bodyPoints - // * @param e - // * @param bodySpace - // */ - // private void transformBody(float[] bodyPoints, CandleEntry e, float - // bodySpace, Transformer trans) { - // - // float phase = mAnimator.getPhaseY(); - // - // bodyPoints[0] = e.getXIndex() - 0.5f + bodySpace; - // bodyPoints[1] = e.getClose() * phase; - // bodyPoints[2] = e.getXIndex() + 0.5f - bodySpace; - // bodyPoints[3] = e.getOpen() * phase; - // - // trans.pointValuesToPixel(bodyPoints); - // } - // - // /** - // * Transforms the values of an entry in order to draw the candle-shadow. - // * - // * @param shadowPoints - // * @param e - // */ - // private void transformShadow(float[] shadowPoints, CandleEntry e, - // Transformer trans) { - // - // float phase = mAnimator.getPhaseY(); - // - // shadowPoints[0] = e.getXIndex(); - // shadowPoints[1] = e.getHigh() * phase; - // shadowPoints[2] = e.getXIndex(); - // shadowPoints[3] = e.getLow() * phase; - // - // trans.pointValuesToPixel(shadowPoints); - // } - @Override public void drawValues(Canvas c) { @@ -223,11 +185,11 @@ public void drawValues(Canvas c) { if (mChart.getCandleData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - List dataSets = mChart.getCandleData().getDataSets(); + List dataSets = mChart.getCandleData().getDataSets(); for (int i = 0; i < dataSets.size(); i++) { - CandleDataSet dataSet = dataSets.get(i); + ICandleDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -278,7 +240,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { int xIndex = indices[i].getXIndex(); // get the // x-position - CandleDataSet set = mChart.getCandleData().getDataSetByIndex( + ICandleDataSet set = mChart.getCandleData().getDataSetByIndex( indices[i].getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index c684ae4f4f..1df0791923 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -10,10 +10,11 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.formatter.ValueFormatter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; @@ -39,8 +40,8 @@ public void initBuffers() { mBarBuffers = new HorizontalBarBuffer[barData.getDataSetCount()]; for (int i = 0; i < mBarBuffers.length; i++) { - BarDataSet set = barData.getDataSetByIndex(i); - mBarBuffers[i] = new HorizontalBarBuffer(set.getValueCount() * 4 * set.getStackSize(), + IBarDataSet set = barData.getDataSetByIndex(i); + mBarBuffers[i] = new HorizontalBarBuffer(set.getEntryCount() * 4 * set.getStackSize(), barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } @@ -96,7 +97,7 @@ public void drawValues(Canvas c) { // if values are drawn if (passesCheck()) { - List dataSets = mChart.getBarData().getDataSets(); + List dataSets = mChart.getBarData().getDataSets(); final float valueOffsetPlus = Utils.convertDpToPixel(5f); float posOffset = 0f; @@ -105,7 +106,7 @@ public void drawValues(Canvas c) { for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { - BarDataSet dataSet = dataSets.get(i); + IBarDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 9d87300347..9d7d8286e1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; @@ -85,7 +86,7 @@ public void computeLegend(ChartData data) { // loop for building up the colors and labels used in the legend for (int i = 0; i < data.getDataSetCount(); i++) { - DataSet dataSet = data.getDataSetByIndex(i); + IDataSet dataSet = data.getDataSetByIndex(i); List clrs = dataSet.getColors(); int entryCount = dataSet.getEntryCount(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 794567d0e1..efb7f813ed 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -10,9 +10,9 @@ import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; -import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -41,7 +41,7 @@ public void initBuffers() { mScatterBuffers = new ScatterBuffer[scatterData.getDataSetCount()]; for (int i = 0; i < mScatterBuffers.length; i++) { - ScatterDataSet set = scatterData.getDataSetByIndex(i); + IScatterDataSet set = scatterData.getDataSetByIndex(i); mScatterBuffers[i] = new ScatterBuffer(set.getEntryCount() * 2); } } @@ -51,14 +51,14 @@ public void drawData(Canvas c) { ScatterData scatterData = mChart.getScatterData(); - for (ScatterDataSet set : scatterData.getDataSets()) { + for (IScatterDataSet set : scatterData.getDataSets()) { if (set.isVisible()) drawDataSet(c, set); } } - protected void drawDataSet(Canvas c, ScatterDataSet dataSet) { + protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -203,11 +203,11 @@ public void drawValues(Canvas c) { if (mChart.getScatterData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX()) { - List dataSets = mChart.getScatterData().getDataSets(); + List dataSets = mChart.getScatterData().getDataSets(); for (int i = 0; i < mChart.getScatterData().getDataSetCount(); i++) { - ScatterDataSet dataSet = dataSets.get(i); + IScatterDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -251,7 +251,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { - ScatterDataSet set = mChart.getScatterData().getDataSetByIndex(indices[i] + IScatterDataSet set = mChart.getScatterData().getDataSetByIndex(indices[i] .getDataSetIndex()); if (set == null || !set.isHighlightEnabled()) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java index 20e9feb3f2..9d518855fa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.utils; import com.github.mikephil.charting.data.DataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; /** * Class that encapsulates information of a value that has been @@ -14,9 +15,9 @@ public class SelectionDetail { public float val; public int dataSetIndex; - public DataSet dataSet; + public IDataSet dataSet; - public SelectionDetail(float val, int dataSetIndex, DataSet set) { + public SelectionDetail(float val, int dataSetIndex, IDataSet set) { this.val = val; this.dataSetIndex = dataSetIndex; this.dataSet = set; From 3455343555cf52c13021c3818fee2b850bd1dadd Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 11:18:46 +0200 Subject: [PATCH 0550/1390] Example adjustments due to changes in library --- .../mpchartexample/BarChartActivity.java | 11 ++++--- .../BarChartActivityMultiDataset.java | 10 +++--- .../mpchartexample/BarChartActivitySinus.java | 3 +- .../mpchartexample/BubbleChartActivity.java | 9 ++--- .../CandleStickChartActivity.java | 6 ++-- .../mpchartexample/CombinedChartActivity.java | 5 +-- .../CubicLineChartActivity.java | 27 ++++++++++----- .../mpchartexample/DrawChartActivity.java | 12 +++++-- .../DynamicalAddingActivity.java | 5 +-- .../HorizontalBarChartActivity.java | 14 ++++++-- .../InvertedLineChartActivity.java | 24 +++++++++++--- .../mpchartexample/LineChartActivity1.java | 31 ++++++++++++----- .../mpchartexample/LineChartActivity2.java | 30 ++++++++++++----- .../LineChartActivityColored.java | 3 +- .../ListViewBarChartActivity.java | 3 +- .../ListViewMultiChartActivity.java | 3 +- .../MultiLineChartActivity.java | 33 ++++++++++++------- .../RealtimeLineChartActivity.java | 3 +- .../mpchartexample/ScatterChartActivity.java | 15 ++++++--- .../mpchartexample/StackedBarActivity.java | 17 +++++++--- .../StackedBarActivityNegative.java | 10 +++++- .../custom/MyFillFormatter.java | 6 ++-- .../fragments/SimpleFragment.java | 11 ++++--- 23 files changed, 202 insertions(+), 89 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 9ade72efbb..0736149c82 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -27,13 +27,14 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -137,7 +138,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); @@ -257,7 +258,7 @@ private void setData(int count, float range) { BarDataSet set1 = new BarDataSet(yVals1, "DataSet"); set1.setBarSpacePercent(35f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); BarData data = new BarData(xVals, dataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index 910e4839ee..ae9428980b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -20,11 +20,11 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.listener.OnChartValueSelectedListener; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.LargeValueFormatter; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -114,7 +114,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); @@ -219,7 +219,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { BarDataSet set3 = new BarDataSet(yVals3, "Company C"); set3.setColor(Color.rgb(242, 247, 158)); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); dataSets.add(set2); dataSets.add(set3); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 1a29182e85..c57568f15d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -25,6 +25,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.FileUtils; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -123,7 +124,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IBarDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 690bc6528c..70a27cbfb8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -20,13 +20,14 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -108,7 +109,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); @@ -225,7 +226,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set3.setColor(ColorTemplate.COLORFUL_COLORS[2], 130); set3.setDrawValues(true); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets dataSets.add(set2); dataSets.add(set3); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 5ea63dab91..87515c1f0a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -122,9 +123,8 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleMakeShadowSameColorAsCandle: { - for (CandleDataSet set : mChart.getData().getDataSets()) - { - set.setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); + for (ICandleDataSet set : mChart.getData().getDataSets()) { + //TODO: set.setShadowColorSameAsCandle(!set.getShadowColorSameAsCandle()); } mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 3d98460374..1ce9acb4ea 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -28,6 +28,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -198,7 +199,7 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleLineValues: { - for (DataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : mChart.getData().getDataSets()) { if (set instanceof LineDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } @@ -207,7 +208,7 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleBarValues: { - for (DataSet set : mChart.getData().getDataSets()) { + for (IDataSet set : mChart.getData().getDataSets()) { if (set instanceof BarDataSet) set.setDrawValues(!set.isDrawValuesEnabled()); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 2432180f1e..2237009000 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -15,17 +15,19 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class CubicLineChartActivity extends DemoBase implements OnSeekBarChangeListener { @@ -111,7 +113,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); @@ -126,10 +128,13 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; + if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -139,10 +144,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCirclesEnabled()) set.setDrawCircles(false); else @@ -152,10 +159,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCubicEnabled()) set.setDrawCubic(false); else @@ -281,7 +290,7 @@ private void setData(int count, float range) { set1.setDrawHorizontalHighlightIndicator(false); set1.setFillFormatter(new FillFormatter() { @Override - public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { return -10; } }); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 7e66ecbb06..96cca2c363 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -16,12 +16,14 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; /** * This Activity demonstrates drawing into the Chart with the finger. Both line, @@ -84,7 +86,7 @@ private void initWithDummyData() { set1.setLineWidth(3f); set1.setCircleSize(5f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets // create a data object with the datasets @@ -104,8 +106,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index ea0d2f73a1..31f46c04b0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -13,6 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; @@ -52,7 +53,7 @@ private void addEntry() { if(data != null) { - LineDataSet set = data.getDataSetByIndex(0); + ILineDataSet set = data.getDataSetByIndex(0); // set.addEntry(...); // can be called as well if (set == null) { @@ -85,7 +86,7 @@ private void removeLastEntry() { if(data != null) { - LineDataSet set = data.getDataSetByIndex(0); + ILineDataSet set = data.getDataSetByIndex(0); if (set != null) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 83ea2be4e9..c165f5ff08 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -26,14 +26,18 @@ import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -134,8 +138,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + IBarDataSet set = (BarDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -247,7 +257,7 @@ private void setData(int count, float range) { BarDataSet set1 = new BarDataSet(yVals1, "DataSet 1"); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); BarData data = new BarData(xVals, dataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index e943222ead..a543b709bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -16,18 +16,22 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class InvertedLineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -122,8 +126,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -137,10 +147,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -150,10 +162,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCirclesEnabled()) set.setDrawCircles(false); else diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index c75ed1d967..8e912eaad2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -22,13 +22,13 @@ import com.github.mikephil.charting.components.LimitLine.LimitLabelPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; @@ -36,6 +36,7 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class LineChartActivity1 extends DemoBase implements OnSeekBarChangeListener, OnChartGestureListener, OnChartValueSelectedListener { @@ -176,8 +177,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -191,10 +198,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -204,10 +213,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCirclesEnabled()) set.setDrawCircles(false); else @@ -217,10 +228,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCubicEnabled()) set.setDrawCubic(false); else @@ -351,7 +364,7 @@ private void setData(int count, float range) { // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets // create a data object with the datasets diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index fa2681e9e4..82635a0566 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -26,6 +26,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; @@ -33,6 +34,7 @@ import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class LineChartActivity2 extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -136,8 +138,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -151,10 +159,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -164,10 +174,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCirclesEnabled()) set.setDrawCircles(false); else @@ -177,10 +189,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCubic: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCubicEnabled()) set.setDrawCubic(false); else @@ -317,7 +331,7 @@ private void setData(int count, float range) { set2.setHighLightColor(Color.rgb(244, 117, 117)); //set2.setFillFormatter(new MyFillFormatter(900f)); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set2); dataSets.add(set1); // add the datasets diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index c66ba99b40..6f21471269 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -11,6 +11,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -118,7 +119,7 @@ private LineData getData(int count, float range) { set1.setHighLightColor(Color.WHITE); set1.setDrawValues(false); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets // create a data object with the datasets diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index d314c3166f..71a474eb2a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -20,6 +20,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -140,7 +141,7 @@ private BarData generateData(int cnt) { d.setColors(ColorTemplate.VORDIPLOM_COLORS); d.setBarShadowColor(Color.rgb(203, 203, 203)); - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); sets.add(d); BarData cd = new BarData(getMonths(), sets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 4a47000f90..74779c0c5d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.listviewitems.BarChartItem; import com.xxmassdeveloper.mpchartexample.listviewitems.ChartItem; @@ -120,7 +121,7 @@ private LineData generateDataLine(int cnt) { d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setDrawValues(false); - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); sets.add(d1); sets.add(d2); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index d6bd2e3aa3..2ec667e244 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -13,18 +13,19 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class MultiLineChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -91,8 +92,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -119,10 +126,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -132,10 +141,12 @@ public boolean onOptionsItemSelected(MenuItem item) { break; } case R.id.actionToggleCircles: { - ArrayList sets = (ArrayList) mChart.getData() + List sets = mChart.getData() .getDataSets(); - for (LineDataSet set : sets) { + for (ILineDataSet iSet : sets) { + + LineDataSet set = (LineDataSet) iSet; if (set.isDrawCirclesEnabled()) set.setDrawCircles(false); else @@ -204,7 +215,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { xVals.add((i) + ""); } - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); for (int z = 0; z < 3; z++) { @@ -226,9 +237,9 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { } // make the first DataSet dashed - dataSets.get(0).enableDashedLine(10, 10, 0); - dataSets.get(0).setColors(ColorTemplate.VORDIPLOM_COLORS); - dataSets.get(0).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); + ((LineDataSet) dataSets.get(0)).enableDashedLine(10, 10, 0); + ((LineDataSet) dataSets.get(0)).setColors(ColorTemplate.VORDIPLOM_COLORS); + ((LineDataSet) dataSets.get(0)).setCircleColors(ColorTemplate.VORDIPLOM_COLORS); LineData data = new LineData(xVals, dataSets); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index afa181cd0e..52ef71151d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; @@ -130,7 +131,7 @@ private void addEntry() { if (data != null) { - LineDataSet set = data.getDataSetByIndex(0); + ILineDataSet set = data.getDataSetByIndex(0); // set.addEntry(...); // can be called as well if (set == null) { diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index c33a77ce11..af471c83a8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -17,18 +17,19 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import java.util.List; public class ScatterChartActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { @@ -101,8 +102,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (IScatterDataSet iSet : sets) { + + ScatterDataSet set = (ScatterDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -213,7 +220,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set2.setScatterShapeSize(8f); set3.setScatterShapeSize(8f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets dataSets.add(set2); dataSets.add(set3); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index a62e55ecd3..f30c6e4915 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -1,7 +1,5 @@ package com.xxmassdeveloper.mpchartexample; -import java.util.ArrayList; - import android.os.Bundle; import android.util.Log; import android.view.Menu; @@ -21,17 +19,20 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import java.util.ArrayList; +import java.util.List; + public class StackedBarActivity extends DemoBase implements OnSeekBarChangeListener, OnChartValueSelectedListener { private BarChart mChart; @@ -105,8 +106,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + BarDataSet set = (BarDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; @@ -208,7 +215,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { set1.setColors(getColors()); set1.setStackLabels(new String[] { "Births", "Divorces", "Marriages" }); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set1); BarData data = new BarData(xVals, dataSets); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 45a672ba11..0f7fd3e155 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -22,6 +22,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; @@ -31,6 +32,7 @@ import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.List; public class StackedBarActivityNegative extends DemoBase implements OnChartValueSelectedListener { @@ -119,8 +121,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + List sets = mChart.getData() + .getDataSets(); + + for (IBarDataSet iSet : sets) { + + BarDataSet set = (BarDataSet) iSet; set.setDrawValues(!set.isDrawValuesEnabled()); + } mChart.invalidate(); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index 248f7f5bed..1f330dfd76 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -1,8 +1,8 @@ package com.xxmassdeveloper.mpchartexample.custom; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.formatter.FillFormatter; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** * Created by Philipp Jahoda on 12/09/15. @@ -16,7 +16,7 @@ public MyFillFormatter(float fillpos) { } @Override - public float getFillLinePosition(LineDataSet dataSet, LineDataProvider dataProvider) { + public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProvider) { // your logic could be here return mFillPos; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 386f699fe3..d789d7952e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -21,6 +21,9 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FileUtils; @@ -42,7 +45,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa protected BarData generateBarData(int dataSets, float range, int count) { - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); for(int i = 0; i < dataSets; i++) { @@ -66,7 +69,7 @@ protected BarData generateBarData(int dataSets, float range, int count) { protected ScatterData generateScatterData(int dataSets, float range, int count) { - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); ScatterShape[] shapes = ScatterChart.getAllPossibleShapes(); @@ -132,7 +135,7 @@ protected LineData generateLineData() { // DataSet ds3 = new DataSet(nsquare, "O(n\u00B2)"); // DataSet ds4 = new DataSet(nthree, "O(n\u00B3)"); - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "sine.txt"), "Sine function"); LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "cosine.txt"), "Cosine function"); @@ -164,7 +167,7 @@ protected LineData generateLineData() { protected LineData getComplexity() { - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); LineDataSet ds1 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "n.txt"), "O(n)"); LineDataSet ds2 = new LineDataSet(FileUtils.loadEntriesFromAssets(getActivity().getAssets(), "nlogn.txt"), "O(nlogn)"); From 063b395b8cb8a81ead186cdae44863f73cce685a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 11:21:09 +0200 Subject: [PATCH 0551/1390] Realm example cleanup --- .../mpchartexample/RealmDatabaseActivity.java | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 4cb022367e..b2cdebd2bb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -1,6 +1,5 @@ package com.xxmassdeveloper.mpchartexample; -import android.graphics.Color; import android.graphics.Typeface; import android.os.Bundle; import android.view.WindowManager; @@ -11,6 +10,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; @@ -75,35 +75,17 @@ private void setData(int count, float range) { for (int i = 0; i < count; i++) { float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3;// + (float) - // ((mult * - // 0.1) / 10); + float val = (float) (Math.random() * mult) + 3; yVals.add(new Entry(val, i)); } - // create a dataset and give it a type - RealmLineDataSet set1 = new RealmLineDataSet(); - - // set the line to be drawn like this "- - - - - -" -// set1.enableDashedLine(10f, 5f, 0f); -// set1.enableDashedHighlightLine(10f, 5f, 0f); -// set1.setColor(Color.BLACK); -// set1.setCircleColor(Color.BLACK); -// set1.setLineWidth(1f); -// set1.setCircleSize(3f); -// set1.setDrawCircleHole(false); -// set1.setValueTextSize(9f); -// set1.setFillAlpha(65); -// set1.setFillColor(Color.BLACK); -// set1.setDrawFilled(true); - // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), - // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); - - ArrayList dataSets = new ArrayList(); - dataSets.add(set1); // add the datasets - - // create a data object with the datasets - LineData data = new LineData(); + RealmLineDataSet set = new RealmLineDataSet(); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + LineData data = new LineData(xVals, dataSets); // set data mChart.setData(data); From aab951a5e0660af7a5f59ecd9d969250d88e8f56 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 11:24:18 +0200 Subject: [PATCH 0552/1390] Add Realm optional dependency --- MPChartLib/build.gradle | 7 +++++++ .../mikephil/charting/data/realm/RealmLineDataSet.java | 3 +++ 2 files changed, 10 insertions(+) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index da9ce3afe1..6c92f5d7df 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -31,10 +31,17 @@ android { } } +repositories { + maven { + url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' + } +} + dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' //compile 'com.nineoldandroids:library:2.4.+' + provided 'io.realm:realm-android:0.84.0-SNAPSHOT' // optional dependency to realm-database API } android.libraryVariants.all { variant -> diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index a702697742..fac7c6791a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -16,6 +16,9 @@ */ public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { + public RealmLineDataSet() { + + } @Override public float getCubicIntensity() { From 01b5826e7332b71cb3e5a953c0162f673b560af6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 11:25:25 +0200 Subject: [PATCH 0553/1390] Remove RealmLineData - no longer needed --- .../charting/data/realm/RealmLineData.java | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java deleted file mode 100644 index f0e4f9fce1..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineData.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.github.mikephil.charting.data.realm; - -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.data.ILineData; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; - -import java.util.List; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public class RealmLineData implements ILineData { - - - @Override - public List getDataSets() { - return null; - } - - @Override - public IDataSet getDataSetByIndex(int index) { - return null; - } - - @Override - public int getYValCount() { - return 0; - } - - @Override - public int getIndexOfDataSet(IDataSet dataSet) { - return 0; - } -} From 71cef8509bdde1f04665f1992680a25fc1c49db7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 13:59:09 +0200 Subject: [PATCH 0554/1390] Setup example for realm --- MPChartExample/AndroidManifest.xml | 2 +- MPChartExample/build.gradle | 5 ++- .../mpchartexample/RealmDatabaseActivity.java | 9 ++++- .../mpchartexample/custom/RealmDemoData.java | 26 +++++++++++++++ .../notimportant/MainActivity.java | 33 +++++++++++++++++++ 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 639694e26a..6d413a0f34 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -26,7 +26,6 @@ - @@ -46,6 +45,7 @@ + diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index ac6eda10af..d19d76d7e6 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -39,7 +39,6 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:1.3.1' - // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -47,11 +46,15 @@ buildscript { repositories { maven { url "https://jitpack.io" } + maven { // this is for realm-db + url 'http://oss.jfrog.org/artifactory/oss-snapshot-local' + } } dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.0.0' + compile 'io.realm:realm-android:0.84.0-SNAPSHOT' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index b2cdebd2bb..3332625964 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -11,10 +11,15 @@ import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; +import io.realm.Realm; +import io.realm.RealmObject; +import io.realm.RealmResults; + /** * Created by Philipp Jahoda on 21/10/15. */ @@ -79,7 +84,9 @@ private void setData(int count, float range) { yVals.add(new Entry(val, i)); } - RealmLineDataSet set = new RealmLineDataSet(); + RealmResults result = Realm.getDefaultInstance().allObjects(RealmDemoData.class); + + RealmLineDataSet set = new RealmLineDataSet(result); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java new file mode 100644 index 0000000000..be91ae4db4 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -0,0 +1,26 @@ +package com.xxmassdeveloper.mpchartexample.custom; + + +import io.realm.RealmObject; + +public class RealmDemoData extends RealmObject { + + private float value; + private int xIndex; + + public float getValue() { + return value; + } + + public void setValue(float value) { + this.value = value; + } + + public int getxIndex() { + return xIndex; + } + + public void setxIndex(int xIndex) { + this.xIndex = xIndex; + } +} \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index f22a2ed3f7..0b111045bb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -41,16 +41,20 @@ import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; +import com.xxmassdeveloper.mpchartexample.RealmDatabaseActivity; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; import java.util.ArrayList; import java.util.List; +import io.realm.Realm; + public class MainActivity extends Activity implements OnItemClickListener { @Override @@ -63,6 +67,28 @@ protected void onCreate(Bundle savedInstanceState) { // initialize the utilities Utils.init(this); +// Realm realm = Realm.getInstance(this); +// +// realm.beginTransaction(); +// +// RealmDemoData d1 = realm.createObject(RealmDemoData.class); +// d1.setValue(10f); +// d1.setxIndex(0); +// RealmDemoData d2 = realm.createObject(RealmDemoData.class); +// d1.setValue(20f); +// d1.setxIndex(1); +// RealmDemoData d3 = realm.createObject(RealmDemoData.class); +// d1.setValue(30f); +// d1.setxIndex(2); +// RealmDemoData d4 = realm.createObject(RealmDemoData.class); +// d1.setValue(40f); +// d1.setxIndex(3); +// RealmDemoData d5 = realm.createObject(RealmDemoData.class); +// d1.setValue(50f); +// d1.setxIndex(4); +// +// realm.commitTransaction(); + ArrayList objects = new ArrayList(); objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); @@ -125,6 +151,9 @@ protected void onCreate(Bundle savedInstanceState) { objects.add(new ContentItem( "Chart in ScrollView", "This demonstrates how to use a chart inside a ScrollView.")); + objects.add(new ContentItem( + "Realm.io Database", + "This demonstrates how to use this library with Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -244,6 +273,10 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, ScrollViewActivity.class); startActivity(i); break; + case 26: + i = new Intent(this, RealmDatabaseActivity.class); + startActivity(i); + break; } overridePendingTransition(R.anim.move_right_in_activity, R.anim.move_left_out_activity); From 496f1b143a629af89554deacc19a51870dbb6b35 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 14:04:34 +0200 Subject: [PATCH 0555/1390] Minor changes on BaseDataSet --- .../mikephil/charting/data/BaseDataSet.java | 23 ++++++++ .../mikephil/charting/data/DataSet.java | 21 ------- .../charting/data/realm/RealmLineDataSet.java | 58 +++++++++---------- 3 files changed, 49 insertions(+), 53 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 29a747e380..c4580e9acf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -73,6 +73,16 @@ public abstract class BaseDataSet implements IDataSet { */ protected boolean mVisible = true; + @Override + public float getYMin() { + return mYMin; + } + + @Override + public float getYMax() { + return mYMax; + } + @Override public void calcMinMax(List values, int start, int end) { @@ -318,4 +328,17 @@ public float getYValForXIndex(int xIndex) { else return Float.NaN; } + + @Override + public boolean contains(Entry e) { + + List values = getYVals(); + + for (Entry entry : values) { + if (entry.equals(e)) + return true; + } + + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 8fb49d251b..6395572ded 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -130,16 +130,6 @@ public List getYVals() { return mYVals; } - @Override - public float getYMin() { - return mYMin; - } - - @Override - public float getYMax() { - return mYMax; - } - /** * The xIndex of an Entry object is provided. This method returns the actual * index in the Entry array of the DataSet. IMPORTANT: This method does @@ -392,17 +382,6 @@ public void resetColors() { mColors = new ArrayList(); } - @Override - public boolean contains(Entry e) { - - for (Entry entry : mYVals) { - if (entry.equals(e)) - return true; - } - - return false; - } - /** * Removes all values from this DataSet and recalculates min and max value. */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index fac7c6791a..e71c94c9ba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -1,14 +1,17 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.Color; import android.graphics.DashPathEffect; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import java.util.ArrayList; import java.util.List; /** @@ -16,13 +19,19 @@ */ public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { + private List mColors = new ArrayList<>(); + + private List mValues = new ArrayList<>(); + public RealmLineDataSet() { + mColors.add(Color.WHITE); + } @Override public float getCubicIntensity() { - return 0; + return .2f; } @Override @@ -32,22 +41,22 @@ public boolean isDrawCubicEnabled() { @Override public float getCircleSize() { - return 0; + return 5f; } @Override public int getCircleColor(int index) { - return 0; + return Color.WHITE; } @Override public boolean isDrawCirclesEnabled() { - return false; + return true; } @Override public int getCircleHoleColor() { - return 0; + return Color.WHITE; } @Override @@ -67,22 +76,22 @@ public boolean isDashedLineEnabled() { @Override public FillFormatter getFillFormatter() { - return null; + return new DefaultFillFormatter(); } @Override public int getFillColor() { - return 0; + return Color.WHITE; } @Override public int getFillAlpha() { - return 0; + return 100; } @Override public float getLineWidth() { - return 0; + return 3f; } @Override @@ -112,56 +121,41 @@ public DashPathEffect getDashPathEffectHighlight() { @Override public int getHighLightColor() { - return 0; + return Color.WHITE; } @Override public String getLabel() { - return null; + return "Realm Data"; } @Override public List getYVals() { - return null; - } - - @Override - public float getYMin() { - return 0; - } - - @Override - public float getYMax() { - return 0; + return mValues; } @Override public int getEntryCount() { - return 0; + return mValues.size(); } @Override public YAxis.AxisDependency getAxisDependency() { - return null; + return YAxis.AxisDependency.LEFT; } @Override public List getColors() { - return null; + return mColors; } @Override public int getColor() { - return 0; + return mColors.get(0); } @Override public int getColor(int index) { - return 0; - } - - @Override - public boolean contains(Entry e) { - return false; + return mColors.get(index % mColors.size()); } } From a0f901c63a2ce2d9fda01466fdcf9f4b3c262989 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 14:14:52 +0200 Subject: [PATCH 0556/1390] More work on RealmLineDataSet --- .../mikephil/charting/data/realm/RealmLineDataSet.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index e71c94c9ba..d6c3c04204 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -14,18 +14,20 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { +public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { private List mColors = new ArrayList<>(); private List mValues = new ArrayList<>(); - public RealmLineDataSet() { + public RealmLineDataSet(RealmResults result) { mColors.add(Color.WHITE); - } From f26a20652a8118314bcb2bbfee0ac5aa9054a1e8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 22 Oct 2015 14:22:22 +0200 Subject: [PATCH 0557/1390] Minor changes --- .../mpchartexample/RealmDatabaseActivity.java | 11 +---------- .../mpchartexample/custom/RealmDemoData.java | 2 ++ 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 3332625964..89a98abbc4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -75,18 +75,9 @@ private void setData(int count, float range) { xVals.add((i) + ""); } - ArrayList yVals = new ArrayList(); - - for (int i = 0; i < count; i++) { - - float mult = (range + 1); - float val = (float) (Math.random() * mult) + 3; - yVals.add(new Entry(val, i)); - } - RealmResults result = Realm.getDefaultInstance().allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result); + RealmLineDataSet set = new RealmLineDataSet(result); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index be91ae4db4..cebf645081 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -8,6 +8,8 @@ public class RealmDemoData extends RealmObject { private float value; private int xIndex; + // ofc there could me more fields here... + public float getValue() { return value; } From 38ea630a7ba4eb210bf89b23baa0982c137e263c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 23 Oct 2015 00:15:46 +0200 Subject: [PATCH 0558/1390] Worked on example and realm data plotting --- .../mpchartexample/RealmDatabaseActivity.java | 57 ++++++++++++++++--- .../mpchartexample/custom/RealmDemoData.java | 20 +++++++ .../notimportant/MainActivity.java | 26 --------- .../charting/data/realm/RealmLineDataSet.java | 30 +++++++--- 4 files changed, 90 insertions(+), 43 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 89a98abbc4..d1fa1bca0c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -17,7 +17,9 @@ import java.util.ArrayList; import io.realm.Realm; +import io.realm.RealmConfiguration; import io.realm.RealmObject; +import io.realm.RealmQuery; import io.realm.RealmResults; /** @@ -49,7 +51,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setScaleEnabled(true); // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(true); + mChart.setPinchZoom(false); Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); @@ -58,26 +60,63 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); leftAxis.setStartAtZero(false); - leftAxis.enableGridDashedLine(10f, 10f, 0f); + leftAxis.setTypeface(tf); + + mChart.getXAxis().setTypeface(tf); mChart.getAxisRight().setEnabled(false); + // write some demo-data into the realm.io database + writeToDB(400); + // add data - setData(45, 100); + setData(); mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); } - private void setData(int count, float range) { + private void writeToDB(int objectCount) { + + RealmConfiguration config = new RealmConfiguration.Builder(this) + .name("myrealm.realm") + .build(); + + Realm.deleteRealm(config); + + Realm.setDefaultConfiguration(config); + + Realm realm = Realm.getInstance(config); + + realm.beginTransaction(); + + realm.clear(RealmDemoData.class); + + for(int i = 0; i < objectCount; i++) { + + RealmDemoData d = new RealmDemoData(30f + (float) (Math.random() * 100.0), i); + realm.copyToRealm(d); + } + + realm.commitTransaction(); + realm.close(); + } + + private void setData() { + + RealmConfiguration config = new RealmConfiguration.Builder(this) + .name("myrealm.realm") + .build(); + + Realm realm = Realm.getInstance(config); + RealmResults result = realm.allObjects(RealmDemoData.class); ArrayList xVals = new ArrayList(); - for (int i = 0; i < count; i++) { + for (int i = 0; i < result.size(); i++) { xVals.add((i) + ""); } - RealmResults result = Realm.getDefaultInstance().allObjects(RealmDemoData.class); - - RealmLineDataSet set = new RealmLineDataSet(result); + RealmLineDataSet set = new RealmLineDataSet(result, "value", "xIndex"); + set.setValueTextSize(9f); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset @@ -87,5 +126,7 @@ private void setData(int count, float range) { // set data mChart.setData(data); + + realm.close(); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index cebf645081..9673c298c8 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -2,14 +2,26 @@ import io.realm.RealmObject; +import io.realm.annotations.Ignore; public class RealmDemoData extends RealmObject { private float value; private int xIndex; + private String someStringField; + // ofc there could me more fields here... + public RealmDemoData() { + + } + + public RealmDemoData(float value, int xIndex) { + this.value = value; + this.xIndex = xIndex; + } + public float getValue() { return value; } @@ -25,4 +37,12 @@ public int getxIndex() { public void setxIndex(int xIndex) { this.xIndex = xIndex; } + + public String getSomeStringField() { + return someStringField; + } + + public void setSomeStringField(String someStringField) { + this.someStringField = someStringField; + } } \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 0b111045bb..eb011ebc2f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -2,7 +2,6 @@ package com.xxmassdeveloper.mpchartexample.notimportant; import android.app.Activity; -import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.net.Uri; @@ -47,14 +46,11 @@ import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivity; import com.xxmassdeveloper.mpchartexample.StackedBarActivityNegative; -import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.fragments.SimpleChartDemo; import java.util.ArrayList; import java.util.List; -import io.realm.Realm; - public class MainActivity extends Activity implements OnItemClickListener { @Override @@ -67,28 +63,6 @@ protected void onCreate(Bundle savedInstanceState) { // initialize the utilities Utils.init(this); -// Realm realm = Realm.getInstance(this); -// -// realm.beginTransaction(); -// -// RealmDemoData d1 = realm.createObject(RealmDemoData.class); -// d1.setValue(10f); -// d1.setxIndex(0); -// RealmDemoData d2 = realm.createObject(RealmDemoData.class); -// d1.setValue(20f); -// d1.setxIndex(1); -// RealmDemoData d3 = realm.createObject(RealmDemoData.class); -// d1.setValue(30f); -// d1.setxIndex(2); -// RealmDemoData d4 = realm.createObject(RealmDemoData.class); -// d1.setValue(40f); -// d1.setxIndex(3); -// RealmDemoData d5 = realm.createObject(RealmDemoData.class); -// d1.setValue(50f); -// d1.setxIndex(4); -// -// realm.commitTransaction(); - ArrayList objects = new ArrayList(); objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index d6c3c04204..a38a0a9228 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -16,6 +16,7 @@ import io.realm.RealmObject; import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 21/10/15. @@ -23,12 +24,23 @@ public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { private List mColors = new ArrayList<>(); - private List mValues = new ArrayList<>(); - public RealmLineDataSet(RealmResults result) { - mColors.add(Color.WHITE); - + private FillFormatter mFillFormatter = new DefaultFillFormatter(); + + public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { + mColors.add(Color.BLACK); + + result.sort(xIndexField, true); + + for(T object : result) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + + mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + } + + //calcMinMax(mValues, mLastStart, mLastEnd); } @Override @@ -43,12 +55,12 @@ public boolean isDrawCubicEnabled() { @Override public float getCircleSize() { - return 5f; + return 8f; } @Override public int getCircleColor(int index) { - return Color.WHITE; + return Color.BLACK; } @Override @@ -58,7 +70,7 @@ public boolean isDrawCirclesEnabled() { @Override public int getCircleHoleColor() { - return Color.WHITE; + return Color.BLACK; } @Override @@ -78,7 +90,7 @@ public boolean isDashedLineEnabled() { @Override public FillFormatter getFillFormatter() { - return new DefaultFillFormatter(); + return mFillFormatter; } @Override @@ -93,7 +105,7 @@ public int getFillAlpha() { @Override public float getLineWidth() { - return 3f; + return 4f; } @Override From 5f5950b4414fc6294f333870deda0341ea0dd9fc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 23 Oct 2015 13:58:43 +0200 Subject: [PATCH 0559/1390] Fix issue #1136 --- .../mpchartexample/custom/MyMarkerView.java | 4 +- .../custom/StackedBarsMarkerView.java | 4 +- .../charting/components/MarkerView.java | 127 +++++++++--------- 3 files changed, 67 insertions(+), 68 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java index 836e7befb6..4198d14f1c 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyMarkerView.java @@ -43,13 +43,13 @@ public void refreshContent(Entry e, Highlight highlight) { } @Override - public int getXOffset() { + public int getXOffset(float xpos) { // this will center the marker-view horizontally return -(getWidth() / 2); } @Override - public int getYOffset() { + public int getYOffset(float ypos) { // this will cause the marker-view to be above the selected value return -getHeight(); } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java index 3b3b5e186e..9be2f30acb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/StackedBarsMarkerView.java @@ -50,13 +50,13 @@ public void refreshContent(Entry e, Highlight highlight) { } @Override - public int getXOffset() { + public int getXOffset(float xpos) { // this will center the marker-view horizontally return -(getWidth() / 2); } @Override - public int getYOffset() { + public int getYOffset(float ypos) { // this will cause the marker-view to be above the selected value return -getHeight(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java index 7a65b7e236..523376c786 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/MarkerView.java @@ -17,78 +17,77 @@ */ public abstract class MarkerView extends RelativeLayout { - /** - * Constructor. Sets up the MarkerView with a custom layout resource. - * - * @param context - * @param layoutResource - * the layout resource to use for the MarkerView - */ - public MarkerView(Context context, int layoutResource) { - super(context); - setupLayoutResource(layoutResource); - } + /** + * Constructor. Sets up the MarkerView with a custom layout resource. + * + * @param context + * @param layoutResource the layout resource to use for the MarkerView + */ + public MarkerView(Context context, int layoutResource) { + super(context); + setupLayoutResource(layoutResource); + } - /** - * Sets the layout resource for a custom MarkerView. - * - * @param layoutResource - */ - private void setupLayoutResource(int layoutResource) { + /** + * Sets the layout resource for a custom MarkerView. + * + * @param layoutResource + */ + private void setupLayoutResource(int layoutResource) { - View inflated = LayoutInflater.from(getContext()).inflate(layoutResource, this); + View inflated = LayoutInflater.from(getContext()).inflate(layoutResource, this); - inflated.setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); - inflated.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + inflated.setLayoutParams(new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)); + inflated.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - // measure(getWidth(), getHeight()); - inflated.layout(0, 0, inflated.getMeasuredWidth(), inflated.getMeasuredHeight()); - } + // measure(getWidth(), getHeight()); + inflated.layout(0, 0, inflated.getMeasuredWidth(), inflated.getMeasuredHeight()); + } - /** - * Draws the MarkerView on the given position on the screen with the given Canvas object. - * - * @param canvas - * @param posx - * @param posy - */ - public void draw(Canvas canvas, float posx, float posy) { + /** + * Draws the MarkerView on the given position on the screen with the given Canvas object. + * + * @param canvas + * @param posx + * @param posy + */ + public void draw(Canvas canvas, float posx, float posy) { - // take offsets into consideration - posx += getXOffset(); - posy += getYOffset(); + // take offsets into consideration + posx += getXOffset(posx); + posy += getYOffset(posy); - // translate to the correct position and draw - canvas.translate(posx, posy); - draw(canvas); - canvas.translate(-posx, -posy); - } + // translate to the correct position and draw + canvas.translate(posx, posy); + draw(canvas); + canvas.translate(-posx, -posy); + } - /** - * This method enables a specified custom MarkerView to update it's content everytime the MarkerView is redrawn. - * - * @param e - * The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or - * CandleEntry, simply cast it at runtime. - * @param highlight - * the highlight object contains information about the highlighted value such as it's dataset-index, the - * selected range or stack-index (only stacked bar entries). - */ - public abstract void refreshContent(Entry e, Highlight highlight); + /** + * This method enables a specified custom MarkerView to update it's content everytime the MarkerView is redrawn. + * + * @param e The Entry the MarkerView belongs to. This can also be any subclass of Entry, like BarEntry or + * CandleEntry, simply cast it at runtime. + * @param highlight the highlight object contains information about the highlighted value such as it's dataset-index, the + * selected range or stack-index (only stacked bar entries). + */ + public abstract void refreshContent(Entry e, Highlight highlight); - /** - * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / - * 2) you will center the MarkerView horizontally. - * - * @return - */ - public abstract int getXOffset(); + /** + * Use this to return the desired offset you wish the MarkerView to have on the x-axis. By returning -(getWidth() / + * 2) you will center the MarkerView horizontally. + * + * @param xpos the position on the x-axis in pixels where the marker is drawn + * @return + */ + public abstract int getXOffset(float xpos); - /** - * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning - * -getHeight() you will cause the MarkerView to be above the selected value. - * - * @return - */ - public abstract int getYOffset(); + /** + * Use this to return the desired position offset you wish the MarkerView to have on the y-axis. By returning + * -getHeight() you will cause the MarkerView to be above the selected value. + * + * @param ypos the position on the y-axis in pixels where the marker is drawn + * @return + */ + public abstract int getYOffset(float ypos); } From 58845ebd7d4c88db0cfec572eb6b1f9c0fd9590c Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 23 Oct 2015 15:02:46 +0300 Subject: [PATCH 0560/1390] Fixed a potential crash in CombinedChart with lineData and only one x-value Deployed same deltaX fix as in LineChart --- .../com/github/mikephil/charting/charts/CombinedChart.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index 9c4be80cf2..f74fee2f10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -102,6 +102,10 @@ protected void calcMinMax() { } mDeltaX = Math.abs(mXChartMax - mXChartMin); + + if (mDeltaX == 0.f && getLineData() != null && getLineData().getYValCount() > 0) { + mDeltaX = 1.f; + } } @Override From 25336b88dc7783ba839d76b5ff656fe107d60c32 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 23 Oct 2015 15:05:10 +0300 Subject: [PATCH 0561/1390] Fixed potential crash when line data is empty --- .../github/mikephil/charting/renderer/LineChartRenderer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 147229cb82..725fea540e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -485,7 +485,8 @@ protected void drawCircles(Canvas c) { LineDataSet dataSet = dataSets.get(i); - if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled()) + if (!dataSet.isVisible() || !dataSet.isDrawCirclesEnabled() || + dataSet.getEntryCount() == 0) continue; mCirclePaintInner.setColor(dataSet.getCircleHoleColor()); From 9a3d2ad1caff9ae6c0da8f28037ac49330b74cb6 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 23 Oct 2015 15:12:36 +0300 Subject: [PATCH 0562/1390] Moved highlightTouch logic to highlightValue & deprecated highlightTouch --- .../mikephil/charting/charts/Chart.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index a5eec88939..5745b32dff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -572,14 +572,12 @@ public void highlightValue(int xIndex, int dataSetIndex) { /** * Highlights the values represented by the provided Highlight object + * This DOES NOT generate a callback to the OnChartValueSelectedListener. * * @param highlight contains information about which entry should be highlighted */ public void highlightValue(Highlight highlight) { - if (highlight == null) - highlightValues(null); - else - highlightValues(new Highlight[]{highlight}); + highlightValue(highlight); } /** @@ -587,9 +585,10 @@ public void highlightValue(Highlight highlight) { * highlightValues(...), this generates a callback to the * OnChartValueSelectedListener. * - * @param high + * @param high - the highlight object + * @param callListener - call the listener */ - public void highlightTouch(Highlight high) { + public void highlightValue(Highlight high, boolean callListener) { Entry e = null; @@ -612,7 +611,7 @@ public void highlightTouch(Highlight high) { } } - if (mSelectionListener != null) { + if (callListener && mSelectionListener != null) { if (!valuesToHighlight()) mSelectionListener.onNothingSelected(); @@ -625,6 +624,14 @@ public void highlightTouch(Highlight high) { invalidate(); } + /** + * Deprecated. Calls highlightValue(high, true) + */ + @Deprecated + public void highlightTouch(Highlight high) { + highlightValue(high, true); + } + /** * Set a new (e.g. custom) ChartTouchListener NOTE: make sure to * setTouchEnabled(true); if you need touch gestures on the chart From 0298122d206fa65fa1d4c61586ede1043f616a01 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 23 Oct 2015 15:16:14 +0300 Subject: [PATCH 0563/1390] Fixed the avoidFirstLastClipping feature --- .../charting/renderer/XAxisRendererBarChart.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 1a1d304be3..a9d0c07ec0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -60,15 +60,16 @@ protected void drawLabels(Canvas c, float pos) { if (i == mXAxis.getValues().size() - 1) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); - if (width > mViewPortHandler.offsetRight() * 2 - && position[0] + width > mViewPortHandler.getChartWidth()) - position[0] -= width / 2; + if (position[0] + width / 2.f > mViewPortHandler.contentRight()) + position[0] = mViewPortHandler.contentRight() - (width / 2.f); // avoid clipping of the first } else if (i == 0) { float width = Utils.calcTextWidth(mAxisLabelPaint, label); - position[0] += width / 2; + + if (position[0] - width / 2.f < mViewPortHandler.contentLeft()) + position[0] = mViewPortHandler.contentLeft() + (width / 2.f); } } From 548381bcf5dd58c6cfd17ef2249468a52504dca1 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 23 Oct 2015 16:49:12 +0300 Subject: [PATCH 0564/1390] Fix missing argument causing an overflow loop --- MPChartLib/src/com/github/mikephil/charting/charts/Chart.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 5745b32dff..f79aa065d4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -577,7 +577,7 @@ public void highlightValue(int xIndex, int dataSetIndex) { * @param highlight contains information about which entry should be highlighted */ public void highlightValue(Highlight highlight) { - highlightValue(highlight); + highlightValue(highlight, false); } /** From 8490f80d38a7dccd7e02ab012ebbef6aa02e7e18 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Tue, 27 Oct 2015 22:30:57 +0200 Subject: [PATCH 0565/1390] Implemented support for rotated labels on the x-axis --- .../charting/charts/BarLineChartBase.java | 10 +- .../charting/charts/HorizontalBarChart.java | 5 +- .../charting/charts/PieRadarChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 4 +- .../mikephil/charting/components/XAxis.java | 44 ++++++++- .../charting/renderer/XAxisRenderer.java | 62 +++++++++---- .../renderer/XAxisRendererBarChart.java | 7 +- .../XAxisRendererHorizontalBarChart.java | 55 +++++++---- .../renderer/XAxisRendererRadarChart.java | 8 +- .../github/mikephil/charting/utils/Utils.java | 92 +++++++++++++++++++ 10 files changed, 235 insertions(+), 54 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 3a89c2aada..a528c282f1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -489,7 +489,7 @@ public void calculateOffsets() { if (mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled()) { - float xlabelheight = mXAxis.mLabelHeight * 2f; + float xlabelheight = mXAxis.mLabelRotatedHeight + mXAxis.getYOffset(); // offsets for x-labels if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { @@ -545,14 +545,16 @@ protected void calcModulus() { mViewPortHandler.getMatrixTouch().getValues(values); mXAxis.mAxisLabelModulus = (int) Math - .ceil((mData.getXValCount() * mXAxis.mLabelWidth) + .ceil((mData.getXValCount() * mXAxis.mLabelRotatedWidth) / (mViewPortHandler.contentWidth() * values[Matrix.MSCALE_X])); } if (mLogEnabled) - Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + ", x-axis label width: " - + mXAxis.mLabelWidth + ", content width: " + mViewPortHandler.contentWidth()); + Log.i(LOG_TAG, "X-Axis modulus: " + mXAxis.mAxisLabelModulus + + ", x-axis label width: " + mXAxis.mLabelWidth + + ", x-axis label rotated width: " + mXAxis.mLabelRotatedWidth + + ", content width: " + mViewPortHandler.contentWidth()); if (mXAxis.mAxisLabelModulus < 1) mXAxis.mAxisLabelModulus = 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 021a5b8257..9e3b0f1acf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -108,7 +108,7 @@ public void calculateOffsets() { offsetBottom += mAxisRight.getRequiredHeightSpace(mAxisRendererRight.getPaintAxisLabels()); } - float xlabelwidth = mXAxis.mLabelWidth; + float xlabelwidth = mXAxis.mLabelRotatedWidth; if (mXAxis.isEnabled()) { @@ -162,7 +162,8 @@ protected void calcModulus() { float[] values = new float[9]; mViewPortHandler.getMatrixTouch().getValues(values); - mXAxis.mAxisLabelModulus = (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelHeight) + mXAxis.mAxisLabelModulus = + (int) Math.ceil((mData.getXValCount() * mXAxis.mLabelRotatedHeight) / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); if (mXAxis.mAxisLabelModulus < 1) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 881ea65f91..3abbc7d81c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -218,7 +218,7 @@ public void calculateOffsets() { XAxis x = ((RadarChart) this).getXAxis(); if (x.isEnabled() && x.isDrawLabelsEnabled()) { - minOffset = Math.max(minOffset, x.mLabelWidth); + minOffset = Math.max(minOffset, x.mLabelRotatedWidth); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index c619cad9a2..6a92830c94 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -377,7 +377,9 @@ protected float getRequiredLegendOffset() { @Override protected float getRequiredBaseOffset() { - return mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled() ? mXAxis.mLabelWidth : Utils.convertDpToPixel(10f); + return mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled() ? + mXAxis.mLabelRotatedWidth : + Utils.convertDpToPixel(10f); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 40172a5999..0578967cb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.formatter.DefaultXAxisValueFormatter; import com.github.mikephil.charting.formatter.XAxisValueFormatter; +import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; @@ -20,17 +21,34 @@ public class XAxis extends AxisBase { protected List mValues = new ArrayList(); /** - * width of the x-axis labels in pixels - this is calculated by the - * calcTextWidth() method of the utils + * width of the x-axis labels in pixels - this is automatically + * calculated by the computeAxis() methods in the renderers */ public int mLabelWidth = 1; /** - * height of the x-axis labels in pixels - this is calculated by the - * calcTextHeight() method of the utils + * height of the x-axis labels in pixels - this is automatically + * calculated by the computeAxis() methods in the renderers */ public int mLabelHeight = 1; + /** + * width of the (rotated) x-axis labels in pixels - this is automatically + * calculated by the computeAxis() methods in the renderers + */ + public int mLabelRotatedWidth = 1; + + /** + * height of the (rotated) x-axis labels in pixels - this is automatically + * calculated by the computeAxis() methods in the renderers + */ + public int mLabelRotatedHeight = 1; + + /** + * This is the angle for drawing the X axis labels (in degrees) + */ + protected float mLabelRotationAngle = 0.f; + /** * the space that should be left out (in characters) between the x-axis * labels @@ -78,6 +96,8 @@ public enum XAxisPosition { public XAxis() { super(); + + mYOffset = Utils.convertDpToPixel(4.f); } /** @@ -96,6 +116,22 @@ public void setPosition(XAxisPosition pos) { mPosition = pos; } + /** + * returns the angle for drawing the X axis labels (in degrees) + */ + public float getLabelRotationAngle() { + return mLabelRotationAngle; + } + + /** + * sets the angle for drawing the X axis labels (in degrees) + * + * @param angle the angle in degrees + */ + public void setLabelRotationAngle(float angle) { + mLabelRotationAngle = angle; + } + /** * Sets the space (in characters) that should be left out between the x-axis * labels, default 4. This only applies if the number of labels that will be diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 7eb6fb5ad5..51109ca237 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -6,10 +6,13 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.PointF; +import android.util.Size; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -35,17 +38,30 @@ public void computeAxis(float xValAverageLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); - StringBuffer a = new StringBuffer(); + StringBuilder widthText = new StringBuilder(); - int max = (int) Math.round(xValAverageLength + int max = Math.round(xValAverageLength + mXAxis.getSpaceBetweenLabels()); for (int i = 0; i < max; i++) { - a.append('h'); + widthText.append('h'); } - mXAxis.mLabelWidth = Utils.calcTextWidth(mAxisLabelPaint, a.toString()); - mXAxis.mLabelHeight = Utils.calcTextHeight(mAxisLabelPaint, "Q"); + final FSize labelSize = Utils.calcTextSize(mAxisLabelPaint, widthText.toString()); + + final float labelWidth = labelSize.width; + final float labelHeight = Utils.calcTextHeight(mAxisLabelPaint, "Q"); + + final FSize labelRotatedSize = Utils.getSizeOfRotatedRectangleByDegrees( + labelWidth, + labelHeight, + mXAxis.getLabelRotationAngle()); + + mXAxis.mLabelWidth = Math.round(labelWidth); + mXAxis.mLabelHeight = Math.round(labelHeight); + mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width); + mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); + mXAxis.setValues(xValues); } @@ -55,7 +71,7 @@ public void renderAxisLabels(Canvas c) { if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; - float yoffset = Utils.convertDpToPixel(4f); + float yoffset = mXAxis.getYOffset(); mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); @@ -63,24 +79,30 @@ public void renderAxisLabels(Canvas c) { if (mXAxis.getPosition() == XAxisPosition.TOP) { - drawLabels(c, mViewPortHandler.offsetTop() - yoffset); + drawLabels(c, mViewPortHandler.contentTop() - yoffset, + new PointF(0.5f, 1.0f)); - } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { - drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.5f); + drawLabels(c, mViewPortHandler.contentTop() + yoffset + mXAxis.mLabelRotatedHeight, + new PointF(0.5f, 1.0f)); - } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - drawLabels(c, mViewPortHandler.contentBottom() - yoffset); + drawLabels(c, mViewPortHandler.contentBottom() + yoffset, + new PointF(0.5f, 0.0f)); - } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { - drawLabels(c, mViewPortHandler.offsetTop() + yoffset + mXAxis.mLabelHeight); + drawLabels(c, mViewPortHandler.contentBottom() - yoffset - mXAxis.mLabelRotatedHeight, + new PointF(0.5f, 0.0f)); } else { // BOTH SIDED - drawLabels(c, mViewPortHandler.offsetTop() - yoffset); - drawLabels(c, mViewPortHandler.contentBottom() + mXAxis.mLabelHeight + yoffset * 1.6f); + drawLabels(c, mViewPortHandler.contentTop() - yoffset, + new PointF(0.5f, 1.0f)); + drawLabels(c, mViewPortHandler.contentBottom() + yoffset, + new PointF(0.5f, 0.0f)); } } @@ -115,7 +137,9 @@ public void renderAxisLine(Canvas c) { * * @param pos */ - protected void drawLabels(Canvas c, float pos) { + protected void drawLabels(Canvas c, float pos, PointF anchor) { + + final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { @@ -150,14 +174,14 @@ protected void drawLabels(Canvas c, float pos) { } } - drawLabel(c, label, i, position[0], pos); + drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); } } } - protected void drawLabel(Canvas c, String label, int xIndex, float x, float y) { + protected void drawLabel(Canvas c, String label, int xIndex, float x, float y, PointF anchor, float angleDegrees) { String formattedLabel = mXAxis.getValueFormatter().getXValue(label, xIndex, mViewPortHandler); - c.drawText(formattedLabel, x, y, mAxisLabelPaint); + Utils.drawText(c, formattedLabel, x, y, mAxisLabelPaint, anchor, angleDegrees); } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index a9d0c07ec0..c869bec352 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -2,6 +2,7 @@ package com.github.mikephil.charting.renderer; import android.graphics.Canvas; +import android.graphics.PointF; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.XAxis; @@ -27,7 +28,9 @@ public XAxisRendererBarChart(ViewPortHandler viewPortHandler, XAxis xAxis, Trans * @param pos */ @Override - protected void drawLabels(Canvas c, float pos) { + protected void drawLabels(Canvas c, float pos, PointF anchor) { + + final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { @@ -73,7 +76,7 @@ protected void drawLabels(Canvas c, float pos) { } } - drawLabel(c, label, i, position[0], pos); + drawLabel(c, label, i, position[0], pos, anchor, labelRotationAngleDegrees); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index fc64c70a72..e862263520 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -5,12 +5,14 @@ import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Path; +import android.graphics.PointF; import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.components.LimitLine; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -32,8 +34,21 @@ public void computeAxis(float xValAverageLength, List xValues) { mXAxis.setValues(xValues); String longest = mXAxis.getLongestLabel(); - mXAxis.mLabelWidth = (int) (Utils.calcTextWidth(mAxisLabelPaint, longest) + mXAxis.getXOffset() * 3.5f); - mXAxis.mLabelHeight = Utils.calcTextHeight(mAxisLabelPaint, longest); + + final FSize labelSize = Utils.calcTextSize(mAxisLabelPaint, longest); + + final float labelWidth = (int)(labelSize.width + mXAxis.getXOffset() * 3.5f); + final float labelHeight = labelSize.height; + + final FSize labelRotatedSize = Utils.getSizeOfRotatedRectangleByDegrees( + labelSize.width, + labelHeight, + mXAxis.getLabelRotationAngle()); + + mXAxis.mLabelWidth = Math.round(labelWidth); + mXAxis.mLabelHeight = Math.round(labelHeight); + mXAxis.mLabelRotatedWidth = (int)(labelRotatedSize.width + mXAxis.getXOffset() * 3.5f); + mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); } @Override @@ -50,30 +65,30 @@ public void renderAxisLabels(Canvas c) { if (mXAxis.getPosition() == XAxisPosition.TOP) { - mAxisLabelPaint.setTextAlign(Align.LEFT); - drawLabels(c, mViewPortHandler.contentRight() + xoffset); + drawLabels(c, mViewPortHandler.contentRight() + xoffset, + new PointF(0.0f, 0.5f)); - } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { + } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - drawLabels(c, mViewPortHandler.contentLeft() - xoffset); + drawLabels(c, mViewPortHandler.contentRight() - xoffset, + new PointF(1.0f, 0.5f)); - } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { - mAxisLabelPaint.setTextAlign(Align.LEFT); - drawLabels(c, mViewPortHandler.contentLeft() + xoffset); + drawLabels(c, mViewPortHandler.contentLeft() - xoffset, + new PointF(1.0f, 0.5f)); - } else if (mXAxis.getPosition() == XAxisPosition.TOP_INSIDE) { + } else if (mXAxis.getPosition() == XAxisPosition.BOTTOM_INSIDE) { - mAxisLabelPaint.setTextAlign(Align.RIGHT); - drawLabels(c, mViewPortHandler.contentRight() - xoffset); + drawLabels(c, mViewPortHandler.contentLeft() + xoffset, + new PointF(0.0f, 0.5f)); } else { // BOTH SIDED - mAxisLabelPaint.setTextAlign(Align.RIGHT); - drawLabels(c, mViewPortHandler.contentLeft() - xoffset); - mAxisLabelPaint.setTextAlign(Align.LEFT); - drawLabels(c, mViewPortHandler.contentRight() + xoffset); + drawLabels(c, mViewPortHandler.contentRight() + xoffset, + new PointF(0.0f, 0.5f)); + drawLabels(c, mViewPortHandler.contentLeft() - xoffset, + new PointF(1.0f, 0.5f)); } } @@ -83,7 +98,9 @@ public void renderAxisLabels(Canvas c) { * @param pos */ @Override - protected void drawLabels(Canvas c, float pos) { + protected void drawLabels(Canvas c, float pos, PointF anchor) { + + final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); // pre allocate to save performance (dont allocate in loop) float[] position = new float[] { @@ -108,7 +125,7 @@ protected void drawLabels(Canvas c, float pos) { if (mViewPortHandler.isInBoundsY(position[1])) { String label = mXAxis.getValues().get(i); - drawLabel(c, label, i, pos, position[1] + mXAxis.mLabelHeight / 2f); + drawLabel(c, label, i, pos, position[1], anchor, labelRotationAngleDegrees); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java index b5a9ebc594..50a2fc7dd4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererRadarChart.java @@ -25,6 +25,9 @@ public void renderAxisLabels(Canvas c) { if (!mXAxis.isEnabled() || !mXAxis.isDrawLabelsEnabled()) return; + final float labelRotationAngleDegrees = mXAxis.getLabelRotationAngle(); + final PointF drawLabelAnchor = new PointF(0.5f, 0.0f); + mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); mAxisLabelPaint.setColor(mXAxis.getTextColor()); @@ -44,9 +47,10 @@ public void renderAxisLabels(Canvas c) { float angle = (sliceangle * i + mChart.getRotationAngle()) % 360f; PointF p = Utils.getPosition(center, mChart.getYRange() * factor - + mXAxis.mLabelWidth / 2f, angle); + + mXAxis.mLabelRotatedWidth / 2f, angle); - drawLabel(c, label, i, p.x, p.y + mXAxis.mLabelHeight / 2f); + drawLabel(c, label, i, p.x, p.y - mXAxis.mLabelRotatedHeight / 2.f, + drawLabelAnchor, labelRotationAngleDegrees); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index 8f86e36d72..df3aa1ec38 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; +import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PointF; import android.graphics.Rect; @@ -32,6 +33,8 @@ public abstract class Utils { private static DisplayMetrics mMetrics; private static int mMinimumFlingVelocity = 50; private static int mMaximumFlingVelocity = 8000; + public final static double DEG2RAD = (Math.PI / 180.0); + public final static float FDEG2RAD = ((float)Math.PI / 180.f); /** * initialize method, called inside the Chart.init() method. @@ -498,4 +501,93 @@ public static float getNormalizedAngle(float angle) { return angle % 360.f; } + + private static Rect mDrawTextRectBuffer = new Rect(); + + public static void drawText(Canvas c, String text, float x, float y, Paint paint, PointF anchor, float angleDegrees) { + + float drawOffsetX = 0.f; + float drawOffsetY = 0.f; + + paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); + + // Android sometimes has pre-padding + drawOffsetX -= mDrawTextRectBuffer.left; + + // Android sets the top = - (lineheight), and we want to normalize it to the center + drawOffsetY -= mDrawTextRectBuffer.top; + + // To have a consistent point of reference, we always draw left-aligned + Paint.Align originalTextAlign = paint.getTextAlign(); + paint.setTextAlign(Paint.Align.LEFT); + + if (angleDegrees != 0.f) { + + // Move the text drawing rect in a way that it always rotates around its center + drawOffsetX -= mDrawTextRectBuffer.width() * 0.5f; + drawOffsetY -= mDrawTextRectBuffer.height() * 0.5f; + + float translateX = x; + float translateY = y; + + // Move the "outer" rect relative to the anchor, assuming its centered + if (anchor.x != 0.5f || anchor.y != 0.5f) { + final FSize rotatedSize = getSizeOfRotatedRectangleByDegrees( + mDrawTextRectBuffer.width(), + mDrawTextRectBuffer.height(), + angleDegrees); + + translateX -= rotatedSize.width * (anchor.x - 0.5f); + translateY -= rotatedSize.height * (anchor.y - 0.5f); + } + + c.save(); + c.translate(translateX, translateY); + c.rotate(angleDegrees); + + c.drawText(text, drawOffsetX, drawOffsetY, paint); + + c.restore(); + } + else { + if (anchor.x != 0.f || anchor.y != 0.f) { + + drawOffsetX -= mDrawTextRectBuffer.width() * anchor.x; + drawOffsetY -= mDrawTextRectBuffer.height() * anchor.y; + } + + drawOffsetX += x; + drawOffsetY += y; + + c.drawText(text, drawOffsetX, drawOffsetY, paint); + } + + paint.setTextAlign(originalTextAlign); + } + + public static FSize getSizeOfRotatedRectangleByDegrees(FSize rectangleSize, float degrees) + { + final float radians = degrees * FDEG2RAD; + return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); + } + + public static FSize getSizeOfRotatedRectangleByRadians(FSize rectangleSize, float radians) + { + return getSizeOfRotatedRectangleByRadians(rectangleSize.width, rectangleSize.height, radians); + } + + public static FSize getSizeOfRotatedRectangleByDegrees(float rectangleWidth, float rectangleHeight, float degrees) + { + final float radians = degrees * FDEG2RAD; + return getSizeOfRotatedRectangleByRadians(rectangleWidth, rectangleHeight, radians); + } + + public static FSize getSizeOfRotatedRectangleByRadians(float rectangleWidth, float rectangleHeight, float radians) + { + return new FSize( + Math.abs(rectangleWidth * (float)Math.cos(radians)) + Math.abs(rectangleHeight * (float)Math.sin(radians)), + Math.abs(rectangleWidth * (float)Math.sin(radians)) + Math.abs(rectangleHeight * (float)Math.cos(radians)) + ); + } + } From 72bd6d904e9bc90411ff16b05cebf66f42a2356d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 28 Oct 2015 00:14:42 +0100 Subject: [PATCH 0566/1390] Delete data interfaces --- .../data/IBarLineScatterCandleBubbleData.java | 11 ----- .../datainterfaces/data/IChartData.java | 45 ------------------- .../datainterfaces/data/ILineData.java | 9 ---- 3 files changed, 65 deletions(-) delete mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java delete mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java deleted file mode 100644 index 9f28994f80..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IBarLineScatterCandleBubbleData.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.data; - -import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public interface IBarLineScatterCandleBubbleData> extends IChartData { -} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java deleted file mode 100644 index e44dc312be..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/IChartData.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.data; - -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; - -import java.util.List; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public interface IChartData> { - - /** - * Returns an the array of DataSets this object holds. - * - * @return - */ - List getDataSets(); - - /** - * Returns the DataSet object at the given index. - * - * @param index - * @return - */ - T getDataSetByIndex(int index); - - /** - * Returns the index of the provided DataSet inside the DataSets array of - * this data object. Returns -1 if the DataSet was not found. - * - * @param dataSet - * @return - */ - int getIndexOfDataSet(T dataSet); - - /** - * Returns the total number of y-values across all DataSet objects the this - * object represents. - * - * @return - */ - int getYValCount(); -} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java deleted file mode 100644 index 713af78fd1..0000000000 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/data/ILineData.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.data; - -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; - -/** - * Created by Philipp Jahoda on 21/10/15. - */ -public interface ILineData extends IBarLineScatterCandleBubbleData { -} From 94b13d4200ba69aab6c4e3e2a2948f8415b0bd82 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 30 Oct 2015 17:20:41 +0100 Subject: [PATCH 0567/1390] Did some refactoring on interfaces and abstract data classes --- .../mikephil/charting/data/BaseDataSet.java | 237 +++++----------- .../mikephil/charting/data/DataSet.java | 255 +++++++++++++----- .../charting/data/realm/RealmLineDataSet.java | 70 +++-- .../datainterfaces/datasets/IDataSet.java | 127 +++++---- 4 files changed, 364 insertions(+), 325 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index c4580e9acf..c126d7f235 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -3,6 +3,7 @@ import android.graphics.Color; import android.graphics.Typeface; +import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; @@ -19,14 +20,19 @@ public abstract class BaseDataSet implements IDataSet { /** - * maximum y-value in the y-value array + * List representing all colors that are used for this DataSet */ - protected float mYMax = 0.0f; + protected List mColors = null; /** - * the minimum y-value in the y-value array + * label that describes the DataSet or the data the DataSet represents */ - protected float mYMin = 0.0f; + private String mLabel = "DataSet"; + + /** + * this specifies which axis this DataSet should be plotted against + */ + protected YAxis.AxisDependency mAxisDependency = YAxis.AxisDependency.LEFT; /** * the last start value used for calcMinMax @@ -73,142 +79,73 @@ public abstract class BaseDataSet implements IDataSet { */ protected boolean mVisible = true; - @Override - public float getYMin() { - return mYMin; - } + /** + * Default constructor. + */ + public BaseDataSet() { - @Override - public float getYMax() { - return mYMax; } + /** + * Constructor with label. + * + * @param label + */ + public BaseDataSet(String label) { + this.mLabel = label; + } - @Override - public void calcMinMax(List values, int start, int end) { - - if (values == null) - return; - - final int yValCount = values.size(); - - if (yValCount == 0) - return; - - int endValue; - - if (end == 0 || end >= yValCount) - endValue = yValCount - 1; - else - endValue = end; - - mLastStart = start; - mLastEnd = endValue; - - mYMin = Float.MAX_VALUE; - mYMax = -Float.MAX_VALUE; - - for (int i = start; i <= endValue; i++) { - - T e = values.get(i); - - if (e != null && !Float.isNaN(e.getVal())) { - - if (e.getVal() < mYMin) - mYMin = e.getVal(); + /** + * Use this method to tell the data set that the underlying data has changed + */ + public void notifyDataSetChanged() { + calcMinMax(getYVals(), mLastStart, mLastEnd); + } - if (e.getVal() > mYMax) - mYMax = e.getVal(); - } - } - if (mYMin == Float.MAX_VALUE) { - mYMin = 0.f; - mYMax = 0.f; - } - } + /** + * ###### ###### COLOR RELATED METHODS ##### ###### + */ @Override - public void setHighlightEnabled(boolean enabled) { - mHighlightEnabled = enabled; + public List getColors() { + return mColors; } @Override - public boolean isHighlightEnabled() { - return mHighlightEnabled; + public int getColor() { + return mColors.get(0); } @Override - public void addEntry(T e) { - - if (e == null) - return; - - float val = e.getVal(); - - List yVals = getYVals(); - if (yVals == null) { - yVals = new ArrayList(); - } - - if (yVals.size() == 0) { - mYMax = val; - mYMin = val; - } else { - if (mYMax < val) - mYMax = val; - if (mYMin > val) - mYMin = val; - } - - // add the entry - yVals.add(e); + public int getColor(int index) { + return mColors.get(index % mColors.size()); } - @Override - public boolean removeEntry(T e) { - - if (e == null) - return false; - - List yVals = getYVals(); - - if (yVals == null) - return false; - - // remove the entry - boolean removed = yVals.remove(e); - - if (removed) { - calcMinMax(yVals, mLastStart, mLastEnd); - } - - return removed; - } + /** ###### ###### OTHER STYLING RELATED METHODS ##### ###### */ /** - * Removes the Entry object that has the given xIndex from the DataSet. - * Returns true if an Entry was removed, false if no Entry could be removed. + * Sets the label string that describes the DataSet. * - * @param xIndex + * @return */ - public boolean removeEntry(int xIndex) { - - T e = getEntryForXIndex(xIndex); - return removeEntry(e); + public void setLabel(String label) { + mLabel = label; } @Override - public int getEntryPosition(T e) { - - List values = getYVals(); + public String getLabel() { + return mLabel; + } - for (int i = 0; i < values.size(); i++) { - if (e.equalTo(values.get(i))) - return i; - } + @Override + public void setHighlightEnabled(boolean enabled) { + mHighlightEnabled = enabled; + } - return -1; + @Override + public boolean isHighlightEnabled() { + return mHighlightEnabled; } @Override @@ -278,67 +215,17 @@ public boolean isVisible() { } @Override - public T getEntryForXIndex(int x) { - - List values = getYVals(); - - int index = getEntryIndex(x); - if (index > -1) - return values.get(index); - return null; - } - - @Override - public int getEntryIndex(int x) { - - List values = getYVals(); - - int low = 0; - int high = values.size() - 1; - int closest = -1; - - while (low <= high) { - int m = (high + low) / 2; - - if (x == values.get(m).getXIndex()) { - while (m > 0 && values.get(m - 1).getXIndex() == x) - m--; - - return m; - } - - if (x > values.get(m).getXIndex()) - low = m + 1; - else - high = m - 1; - - closest = m; - } - - return closest; + public YAxis.AxisDependency getAxisDependency() { + return mAxisDependency; } - @Override - public float getYValForXIndex(int xIndex) { - - Entry e = getEntryForXIndex(xIndex); - - if (e != null && e.getXIndex() == xIndex) - return e.getVal(); - else - return Float.NaN; - } - - @Override - public boolean contains(Entry e) { - - List values = getYVals(); - - for (Entry entry : values) { - if (entry.equals(e)) - return true; - } - - return false; + /** + * Set the y-axis this DataSet should be plotted against (either LEFT or + * RIGHT). Default: LEFT + * + * @param dependency + */ + public void setAxisDependency(YAxis.AxisDependency dependency) { + mAxisDependency = dependency; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 6395572ded..144a109df6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -3,14 +3,9 @@ import android.content.Context; import android.graphics.Color; -import android.graphics.Typeface; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; -import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.ArrayList; import java.util.List; @@ -31,19 +26,14 @@ public abstract class DataSet extends BaseDataSet { protected List mYVals = null; /** - * List representing all colors that are used for this DataSet + * maximum y-value in the y-value array */ - protected List mColors = null; + protected float mYMax = 0.0f; /** - * label that describes the DataSet or the data the DataSet represents + * the minimum y-value in the y-value array */ - private String mLabel = "DataSet"; - - /** - * this specifies which axis this DataSet should be plotted against - */ - protected AxisDependency mAxisDependency = AxisDependency.LEFT; + protected float mYMin = 0.0f; /** @@ -55,8 +45,7 @@ public abstract class DataSet extends BaseDataSet { * @param label */ public DataSet(List yVals, String label) { - - this.mLabel = label; + super(label); this.mYVals = yVals; if (mYVals == null) @@ -70,11 +59,48 @@ public DataSet(List yVals, String label) { calcMinMax(mYVals, mLastStart, mLastEnd); } - /** - * Use this method to tell the data set that the underlying data has changed - */ - public void notifyDataSetChanged() { - calcMinMax(mYVals, mLastStart, mLastEnd); + @Override + public void calcMinMax(List values, int start, int end) { + + if (values == null) + return; + + final int yValCount = values.size(); + + if (yValCount == 0) + return; + + int endValue; + + if (end == 0 || end >= yValCount) + endValue = yValCount - 1; + else + endValue = end; + + mLastStart = start; + mLastEnd = endValue; + + mYMin = Float.MAX_VALUE; + mYMax = -Float.MAX_VALUE; + + for (int i = start; i <= endValue; i++) { + + T e = values.get(i); + + if (e != null && !Float.isNaN(e.getVal())) { + + if (e.getVal() < mYMin) + mYMin = e.getVal(); + + if (e.getVal() > mYMax) + mYMax = e.getVal(); + } + } + + if (mYMin == Float.MAX_VALUE) { + mYMin = 0.f; + mYMax = 0.f; + } } @Override @@ -174,37 +200,18 @@ public String toString() { */ public String toSimpleString() { StringBuffer buffer = new StringBuffer(); - buffer.append("DataSet, label: " + (mLabel == null ? "" : mLabel) + ", entries: " + mYVals.size() + "\n"); + buffer.append("DataSet, label: " + (getLabel() == null ? "" : getLabel()) + ", entries: " + mYVals.size() + "\n"); return buffer.toString(); } - /** - * Sets the label string that describes the DataSet. - * - * @return - */ - public void setLabel(String label) { - mLabel = label; - } - @Override - public String getLabel() { - return mLabel; + public float getYMin() { + return mYMin; } @Override - public AxisDependency getAxisDependency() { - return mAxisDependency; - } - - /** - * Set the y-axis this DataSet should be plotted against (either LEFT or - * RIGHT). Default: LEFT - * - * @param dependency - */ - public void setAxisDependency(AxisDependency dependency) { - mAxisDependency = dependency; + public float getYMax() { + return mYMax; } /** @@ -360,21 +367,6 @@ public void setColor(int color) { mColors.add(color); } - @Override - public List getColors() { - return mColors; - } - - @Override - public int getColor() { - return mColors.get(0); - } - - @Override - public int getColor(int index) { - return mColors.get(index % mColors.size()); - } - /** * Resets all colors of this DataSet and recreates the colors array. */ @@ -391,4 +383,147 @@ public void clear() { mLastEnd = 0; notifyDataSetChanged(); } + + @Override + public void addEntry(T e) { + + if (e == null) + return; + + float val = e.getVal(); + + List yVals = getYVals(); + if (yVals == null) { + yVals = new ArrayList(); + } + + if (yVals.size() == 0) { + mYMax = val; + mYMin = val; + } else { + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; + } + + // add the entry + yVals.add(e); + } + + @Override + public boolean removeEntry(T e) { + + if (e == null) + return false; + + List yVals = getYVals(); + + if (yVals == null) + return false; + + // remove the entry + boolean removed = yVals.remove(e); + + if (removed) { + calcMinMax(yVals, mLastStart, mLastEnd); + } + + return removed; + } + + /** + * Removes the Entry object that has the given xIndex from the DataSet. + * Returns true if an Entry was removed, false if no Entry could be removed. + * + * @param xIndex + */ + public boolean removeEntry(int xIndex) { + + T e = getEntryForXIndex(xIndex); + return removeEntry(e); + } + + /** + * Checks if this DataSet contains the specified Entry. Returns true if so, + * false if not. NOTE: Performance is pretty bad on this one, do not + * over-use in performance critical situations. + * + * @param e + * @return + */ + public boolean contains(Entry e) { + + List values = getYVals(); + + for (Entry entry : values) { + if (entry.equals(e)) + return true; + } + + return false; + } + + @Override + public int getEntryPosition(Entry e) { + + for (int i = 0; i < mYVals.size(); i++) { + if (e.equalTo(mYVals.get(i))) + return i; + } + + return -1; + } + + @Override + public T getEntryForXIndex(int x) { + + List values = getYVals(); + + int index = getEntryIndex(x); + if (index > -1) + return values.get(index); + return null; + } + + @Override + public int getEntryIndex(int x) { + + List values = getYVals(); + + int low = 0; + int high = values.size() - 1; + int closest = -1; + + while (low <= high) { + int m = (high + low) / 2; + + if (x == values.get(m).getXIndex()) { + while (m > 0 && values.get(m - 1).getXIndex() == x) + m--; + + return m; + } + + if (x > values.get(m).getXIndex()) + low = m + 1; + else + high = m - 1; + + closest = m; + } + + return closest; + } + + @Override + public float getYValForXIndex(int xIndex) { + + Entry e = getEntryForXIndex(xIndex); + + if (e != null && e.getXIndex() == xIndex) + return e.getVal(); + else + return Float.NaN; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index a38a0a9228..304636545c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; @@ -29,6 +30,7 @@ public class RealmLineDataSet extends BaseDataSet private FillFormatter mFillFormatter = new DefaultFillFormatter(); public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { + super(""); mColors.add(Color.BLACK); result.sort(xIndexField, true); @@ -40,12 +42,12 @@ public RealmLineDataSet(RealmResults result, String yValuesField, String xInd mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); } - //calcMinMax(mValues, mLastStart, mLastEnd); + calcMinMax(mValues, mLastStart, mLastEnd); } @Override public float getCubicIntensity() { - return .2f; + return 0; } @Override @@ -55,22 +57,22 @@ public boolean isDrawCubicEnabled() { @Override public float getCircleSize() { - return 8f; + return 0; } @Override public int getCircleColor(int index) { - return Color.BLACK; + return 0; } @Override public boolean isDrawCirclesEnabled() { - return true; + return false; } @Override public int getCircleHoleColor() { - return Color.BLACK; + return 0; } @Override @@ -90,22 +92,22 @@ public boolean isDashedLineEnabled() { @Override public FillFormatter getFillFormatter() { - return mFillFormatter; + return null; } @Override public int getFillColor() { - return Color.WHITE; + return 0; } @Override public int getFillAlpha() { - return 100; + return 0; } @Override public float getLineWidth() { - return 4f; + return 0; } @Override @@ -135,41 +137,61 @@ public DashPathEffect getDashPathEffectHighlight() { @Override public int getHighLightColor() { - return Color.WHITE; + return 0; } @Override - public String getLabel() { - return "Realm Data"; + public List getYVals() { + return null; } @Override - public List getYVals() { - return mValues; + public float getYMin() { + return 0; + } + + @Override + public float getYMax() { + return 0; } @Override public int getEntryCount() { - return mValues.size(); + return 0; } @Override - public YAxis.AxisDependency getAxisDependency() { - return YAxis.AxisDependency.LEFT; + public void calcMinMax(List values, int start, int end) { + } @Override - public List getColors() { - return mColors; + public Entry getEntryForXIndex(int x) { + return null; } @Override - public int getColor() { - return mColors.get(0); + public int getEntryIndex(int x) { + return 0; } @Override - public int getColor(int index) { - return mColors.get(index % mColors.size()); + public int getEntryPosition(Entry e) { + return 0; + } + + @Override + public float getYValForXIndex(int xIndex) { + return 0; + } + + @Override + public void addEntry(Entry e) { + + } + + @Override + public boolean removeEntry(Entry e) { + return false; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index 87e16dfebc..5d7e6f0cb9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -4,7 +4,6 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import java.util.List; @@ -14,12 +13,7 @@ */ public interface IDataSet { - /** - * Returns the label string that describes the DataSet. - * - * @return - */ - String getLabel(); + /** ###### ###### DATA RELATED METHODS ###### ###### */ /** * returns the DataSets Entry array @@ -43,45 +37,15 @@ public interface IDataSet { float getYMax(); /** - * returns the number of y-values this DataSet represents -> yvals.size() + * Returns the number of y-values this DataSet represents -> the size of the y-values array + * -> yvals.size() * * @return */ int getEntryCount(); /** - * Returns the axis this DataSet should be plotted against. - * - * @return - */ - YAxis.AxisDependency getAxisDependency(); - - /** - * returns all the colors that are set for this DataSet - * - * @return - */ - List getColors(); - - /** - * Returns the first color (index 0) of the colors-array this DataSet - * contains. This is only used for performance reasons when only one color is in the colors array (size == 1) - * - * @return - */ - int getColor(); - - /** - * Returns the color at the given index of the DataSet's color array. - * Performs a IndexOutOfBounds check by modulus. - * - * @param index - * @return - */ - int getColor(int index); - - /** - * calc minimum and maximum y value + * Calculates the minimum and maximum y value (mYMin, mYMax) */ void calcMinMax(List values, int start, int end); @@ -109,6 +73,15 @@ public interface IDataSet { */ int getEntryIndex(int x); + /** + * Returns the position of the provided entry in the DataSets Entry array. + * Returns -1 if doesn't exist. + * + * @param e + * @return + */ + int getEntryPosition(T e); + /** * Returns the value of the Entry object at the given xIndex. Returns * Float.NaN if no value is at the given x-index. INFORMATION: This method @@ -121,58 +94,80 @@ public interface IDataSet { float getYValForXIndex(int xIndex); /** - * Checks if this DataSet contains the specified Entry. Returns true if so, - * false if not. NOTE: Performance is pretty bad on this one, do not - * over-use in performance critical situations. + * Adds an Entry to the DataSet dynamically. + * Entries are added to the end of the list. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. * * @param e + */ + void addEntry(T e); + + /** + * Removes an Entry from the DataSets entries array. This will also + * recalculate the current minimum and maximum values of the DataSet and the + * value-sum. Returns true if an Entry was removed, false if no Entry could + * be removed. + * + * @param e + */ + boolean removeEntry(T e); + + + /** ###### ###### STYLING RELATED (& OTHER) METHODS ###### ###### */ + + /** + * Returns the label string that describes the DataSet. + * * @return */ - boolean contains(Entry e); + String getLabel(); /** - * returns true if highlighting of values is enabled, false if not + * Returns the axis this DataSet should be plotted against. * * @return */ - boolean isHighlightEnabled(); + YAxis.AxisDependency getAxisDependency(); /** - * If set to true, value highlighting is enabled which means that values can - * be highlighted programmatically or by touch gesture. + * returns all the colors that are set for this DataSet * - * @param enabled + * @return */ - void setHighlightEnabled(boolean enabled); + List getColors(); /** - * Adds an Entry to the DataSet dynamically. - * Entries are added to the end of the list. - * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. + * Returns the first color (index 0) of the colors-array this DataSet + * contains. This is only used for performance reasons when only one color is in the colors array (size == 1) * - * @param e + * @return */ - void addEntry(T e); + int getColor(); /** - * Removes an Entry from the DataSets entries array. This will also - * recalculate the current minimum and maximum values of the DataSet and the - * value-sum. Returns true if an Entry was removed, false if no Entry could - * be removed. + * Returns the color at the given index of the DataSet's color array. + * Performs a IndexOutOfBounds check by modulus. * - * @param e + * @param index + * @return */ - boolean removeEntry(T e); + int getColor(int index); /** - * Returns the position of the provided entry in the DataSets Entry array. - * Returns -1 if doesn't exist. + * returns true if highlighting of values is enabled, false if not * - * @param e * @return */ - int getEntryPosition(T e); + boolean isHighlightEnabled(); + + /** + * If set to true, value highlighting is enabled which means that values can + * be highlighted programmatically or by touch gesture. + * + * @param enabled + */ + void setHighlightEnabled(boolean enabled); /** * Sets the formatter to be used for drawing the values inside the chart. If From 16ffc975f94f79f55b5af56fe80951ed3c58a402 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 30 Oct 2015 17:21:02 +0100 Subject: [PATCH 0568/1390] Remove contains(...) method from data object --- .../mikephil/charting/data/ChartData.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 661796e5b1..22754058a5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -930,23 +930,23 @@ public void clearValues() { notifyDataChanged(); } - /** - * Checks if this data object contains the specified Entry. Returns true if - * so, false if not. NOTE: Performance is pretty bad on this one, do not - * over-use in performance critical situations. - * - * @param e - * @return - */ - public boolean contains(Entry e) { - - for (T set : mDataSets) { - if (set.contains(e)) - return true; - } - - return false; - } +// /** +// * Checks if this data object contains the specified Entry. Returns true if +// * so, false if not. NOTE: Performance is pretty bad on this one, do not +// * over-use in performance critical situations. +// * +// * @param e +// * @return +// */ +// public boolean contains(Entry e) { +// +// for (T set : mDataSets) { +// if (set.contains(e)) +// return true; +// } +// +// return false; +// } /** * Checks if this data object contains the specified DataSet. Returns true From dd3bd71027e349e90771d96fdb2d462b074be45e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 2 Nov 2015 14:52:10 +0100 Subject: [PATCH 0569/1390] Fix #1168 --- .../com/github/mikephil/charting/highlight/BarHighlighter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 07e476acd6..a85f488681 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -131,7 +131,7 @@ protected int getClosestStackIndex(Range[] ranges, float value) { stackIndex++; } - int length = ranges.length - 1; + int length = Math.max(ranges.length - 1, 0); return (value > ranges[length].to) ? length : 0; // From af0c5acffbf0dbee912703241df3d8b0f09f85c0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 2 Nov 2015 20:31:37 +0100 Subject: [PATCH 0570/1390] Update version --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 639694e26a..34125b0286 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="46" + android:versionName="2.1.6" > Date: Mon, 2 Nov 2015 20:33:56 +0100 Subject: [PATCH 0571/1390] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 324132ec7b..6c0f46ed53 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.5/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.6/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) @@ -145,7 +145,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.5' + compile 'com.github.PhilJay:MPAndroidChart:v2.1.6' } ``` @@ -160,7 +160,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.5 + v2.1.6 ``` @@ -180,7 +180,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.5/javadoc/). +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.6/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From f8d8f4ce6c42d0fc481d9ea46dc6ba1c7954b39a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:43:19 +0100 Subject: [PATCH 0572/1390] Add IPieDataSet & IRadarDataSet, add getStackLabels to IBarDataSet --- .../mikephil/charting/data/BarDataSet.java | 6 +---- .../mikephil/charting/data/PieDataSet.java | 19 ++++---------- .../mikephil/charting/data/RadarDataSet.java | 4 ++- .../datainterfaces/datasets/IBarDataSet.java | 9 +++++++ .../datainterfaces/datasets/IPieDataSet.java | 26 +++++++++++++++++++ .../datasets/IRadarDataSet.java | 11 ++++++++ .../charting/renderer/LegendRenderer.java | 5 ++-- 7 files changed, 58 insertions(+), 22 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IPieDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index 036a43b62f..d0e8e6ab86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -235,11 +235,7 @@ public void setStackLabels(String[] labels) { mStackLabels = labels; } - /** - * returns the labels used for the different value-stacks - * - * @return - */ + @Override public String[] getStackLabels() { return mStackLabels; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index eb1d979307..acedd40f87 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -1,12 +1,13 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; import java.util.List; -public class PieDataSet extends DataSet { +public class PieDataSet extends DataSet implements IPieDataSet { /** the space in degrees between the chart-slices, default 0f */ private float mSliceSpace = 0f; @@ -38,7 +39,7 @@ public DataSet copy() { /** * sets the space that is left out between the piechart-slices, default: 0° * --> no space, maximum 45, minimum 0 (no space) - * + * * @param degrees */ public void setSliceSpace(float degrees) { @@ -51,12 +52,7 @@ public void setSliceSpace(float degrees) { mSliceSpace = degrees; } - /** - * returns the space that is set to be between the piechart-slices of this - * DataSet, in degrees - * - * @return - */ + @Override public float getSliceSpace() { return mSliceSpace; } @@ -71,12 +67,7 @@ public void setSelectionShift(float shift) { mShift = Utils.convertDpToPixel(shift); } - /** - * returns the distance a highlighted piechart slice is "shifted" away from - * the chart-center - * - * @return - */ + @Override public float getSelectionShift() { return mShift; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java index 83cf2907c9..354af2ff75 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java @@ -1,10 +1,12 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; + import java.util.ArrayList; import java.util.List; -public class RadarDataSet extends LineRadarDataSet { +public class RadarDataSet extends LineRadarDataSet implements IRadarDataSet { public RadarDataSet(List yVals, String label) { super(yVals, label); diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java index 84a2a8d2d5..11b5b0b39f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java @@ -44,4 +44,13 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet { + + /** + * Returns the space that is set to be between the piechart-slices of this + * DataSet, in degrees. + * + * @return + */ + float getSliceSpace(); + + /** + * Returns the distance a highlighted piechart slice is "shifted" away from + * the chart-center in dp. + * + * @return + */ + float getSelectionShift(); +} + diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java new file mode 100644 index 0000000000..f6246466d4 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java @@ -0,0 +1,11 @@ +package com.github.mikephil.charting.interfaces.datainterfaces.datasets; + +import com.github.mikephil.charting.data.Entry; + +/** + * Created by Philipp Jahoda on 03/11/15. + */ +public interface IRadarDataSet extends ILineRadarDataSet { + + +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 9d7d8286e1..3dc1e3efd2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; @@ -92,9 +93,9 @@ public void computeLegend(ChartData data) { int entryCount = dataSet.getEntryCount(); // if we have a barchart with stacked bars - if (dataSet instanceof BarDataSet && ((BarDataSet) dataSet).isStacked()) { + if (dataSet instanceof IBarDataSet && ((IBarDataSet) dataSet).isStacked()) { - BarDataSet bds = (BarDataSet) dataSet; + IBarDataSet bds = (IBarDataSet) dataSet; String[] sLabels = bds.getStackLabels(); for (int j = 0; j < clrs.size() && j < bds.getStackSize(); j++) { From d687c8ff1846e5325732b54a614a1bec5c621af9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:44:28 +0100 Subject: [PATCH 0573/1390] Add IPieDataSet interface to PieData object --- .../mikephil/charting/data/PieData.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 5bf01aa6dd..6cb55e6bc3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -1,7 +1,8 @@ package com.github.mikephil.charting.data; -import java.nio.channels.FileLock; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; + import java.util.ArrayList; import java.util.List; @@ -10,10 +11,10 @@ * legend labels of the PieChart are created from the x-values array, and not * from the DataSet labels. Each PieData object can only represent one * PieDataSet (multiple PieDataSets inside a single PieChart are not possible). - * + * * @author Philipp Jahoda */ -public class PieData extends ChartData { +public class PieData extends ChartData { public PieData() { super(); @@ -27,26 +28,26 @@ public PieData(String[] xVals) { super(xVals); } - public PieData(List xVals, PieDataSet dataSet) { + public PieData(List xVals, IPieDataSet dataSet) { super(xVals, toList(dataSet)); } - public PieData(String[] xVals, PieDataSet dataSet) { + public PieData(String[] xVals, IPieDataSet dataSet) { super(xVals, toList(dataSet)); } - private static List toList(PieDataSet dataSet) { - List sets = new ArrayList(); + private static List toList(IPieDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } /** * Sets the PieDataSet this data object should represent. - * + * * @param dataSet */ - public void setDataSet(PieDataSet dataSet) { + public void setDataSet(IPieDataSet dataSet) { mDataSets.clear(); mDataSets.add(dataSet); init(); @@ -55,31 +56,36 @@ public void setDataSet(PieDataSet dataSet) { /** * Returns the DataSet this PieData object represents. A PieData object can * only contain one DataSet. - * + * * @return */ - public PieDataSet getDataSet() { + public IPieDataSet getDataSet() { return mDataSets.get(0); } @Override - public PieDataSet getDataSetByIndex(int index) { + public IPieDataSet getDataSetByIndex(int index) { return index == 0 ? getDataSet() : null; } @Override - public PieDataSet getDataSetByLabel(String label, boolean ignorecase) { + public IPieDataSet getDataSetByLabel(String label, boolean ignorecase) { return ignorecase ? label.equalsIgnoreCase(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null : label.equals(mDataSets.get(0).getLabel()) ? mDataSets.get(0) : null; } + /** + * Returns the sum of all values in this PieData object. + * + * @return + */ public float getYValueSum() { float sum = 0; List values = getDataSet().getYVals(); - for(Entry e : values) + for (Entry e : values) sum += e.getVal(); return sum; From a4d1946486c95f67534fdcbd48153a49235f75f6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:45:04 +0100 Subject: [PATCH 0574/1390] Add IRadarDataSet to RadarData object --- .../mikephil/charting/data/RadarData.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 444c13fb05..3374a63135 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -1,46 +1,48 @@ package com.github.mikephil.charting.data; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; + import java.util.ArrayList; import java.util.List; /** * Data container for the RadarChart. - * + * * @author Philipp Jahoda */ -public class RadarData extends ChartData { +public class RadarData extends ChartData { public RadarData() { super(); } - + public RadarData(List xVals) { super(xVals); } - + public RadarData(String[] xVals) { super(xVals); } - - public RadarData(List xVals, List dataSets) { + + public RadarData(List xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(String[] xVals, List dataSets) { + public RadarData(String[] xVals, List dataSets) { super(xVals, dataSets); } - public RadarData(List xVals, RadarDataSet dataSet) { + public RadarData(List xVals, IRadarDataSet dataSet) { super(xVals, toList(dataSet)); } - public RadarData(String[] xVals, RadarDataSet dataSet) { + public RadarData(String[] xVals, IRadarDataSet dataSet) { super(xVals, toList(dataSet)); } - - private static List toList(RadarDataSet dataSet) { - List sets = new ArrayList(); + + private static List toList(IRadarDataSet dataSet) { + List sets = new ArrayList(); sets.add(dataSet); return sets; } From e0c518ecb2940f1678bf89b25770bc80ce6536df Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:50:59 +0100 Subject: [PATCH 0575/1390] Minor refactoring --- .../github/mikephil/charting/data/DataSet.java | 15 ++++++++++----- .../charting/data/realm/RealmLineDataSet.java | 2 +- .../datainterfaces/datasets/IDataSet.java | 18 +++++++++++++----- .../charting/renderer/BubbleChartRenderer.java | 14 ++++++-------- .../charting/renderer/LineChartRenderer.java | 17 ++++++++--------- .../charting/renderer/RadarChartRenderer.java | 2 +- 6 files changed, 39 insertions(+), 29 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 144a109df6..bc290a5926 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -465,7 +465,7 @@ public boolean contains(Entry e) { } @Override - public int getEntryPosition(Entry e) { + public int getEntryIndex(Entry e) { for (int i = 0; i < mYVals.size(); i++) { if (e.equalTo(mYVals.get(i))) @@ -487,7 +487,12 @@ public T getEntryForXIndex(int x) { } @Override - public int getEntryIndex(int x) { + public T getEntryForIndex(int index) { + return mYVals.get(index); + } + + @Override + public int getEntryIndex(int xIndex) { List values = getYVals(); @@ -498,14 +503,14 @@ public int getEntryIndex(int x) { while (low <= high) { int m = (high + low) / 2; - if (x == values.get(m).getXIndex()) { - while (m > 0 && values.get(m - 1).getXIndex() == x) + if (xIndex == values.get(m).getXIndex()) { + while (m > 0 && values.get(m - 1).getXIndex() == xIndex) m--; return m; } - if (x > values.get(m).getXIndex()) + if (xIndex > values.get(m).getXIndex()) low = m + 1; else high = m - 1; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 304636545c..9255f6c53a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -176,7 +176,7 @@ public int getEntryIndex(int x) { } @Override - public int getEntryPosition(Entry e) { + public int getEntryIndex(Entry e) { return 0; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java index 5d7e6f0cb9..3343bd8ebd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java @@ -56,10 +56,18 @@ public interface IDataSet { * at that index. INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param x + * @param xIndex + * @return + */ + T getEntryForXIndex(int xIndex); + + /** + * Returns the Entry object found at the given index (NOT xIndex) in the values array. + * + * @param index * @return */ - T getEntryForXIndex(int x); + T getEntryForIndex(int index); /** * Returns the first Entry index found at the given xIndex with binary @@ -68,10 +76,10 @@ public interface IDataSet { * at that index. INFORMATION: This method does calculations at runtime. Do * not over-use in performance critical situations. * - * @param x + * @param xIndex * @return */ - int getEntryIndex(int x); + int getEntryIndex(int xIndex); /** * Returns the position of the provided entry in the DataSets Entry array. @@ -80,7 +88,7 @@ public interface IDataSet { * @param e * @return */ - int getEntryPosition(T e); + int getEntryIndex(T e); /** * Returns the value of the Entry object at the given xIndex. Returns diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index bc615a6a10..651f558dc1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -7,9 +7,7 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; @@ -76,8 +74,8 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = Math.max(dataSet.getEntryPosition(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, entries.size()); + int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); + int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entries.size()); sizeBuffer[0] = 0f; sizeBuffer[2] = 1f; @@ -157,8 +155,8 @@ public void drawValues(Canvas c) { BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) .generateTransformedValuesBubble(entries, phaseX, phaseY, minx, maxx); @@ -208,8 +206,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); - int minx = dataSet.getEntryPosition(entryFrom); - int maxx = Math.min(dataSet.getEntryPosition(entryTo) + 1, dataSet.getEntryCount()); + int minx = dataSet.getEntryIndex(entryFrom); + int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); final BubbleEntry entry = (BubbleEntry) bubbleData.getEntryForHighlight(indice); if (entry == null || entry.getXIndex() != indice.getXIndex()) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 006c23b679..6f76009624 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -13,7 +13,6 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.highlight.Highlight; @@ -143,9 +142,9 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -289,9 +288,9 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); int range = (maxx - minx) * 4 - 4; @@ -441,9 +440,9 @@ public void drawValues(Canvas c) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); float[] positions = trans.generateTransformedValuesLine( entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); @@ -499,9 +498,9 @@ protected void drawCircles(Canvas c) { Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; - int minx = Math.max(dataSet.getEntryPosition(entryFrom) - diff, 0); + int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryPosition(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); CircleBuffer buffer = mCircleBuffers[i]; buffer.setPhases(phaseX, phaseY); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 70e1c6bc55..336315da49 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -229,7 +229,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (e == null || e.getXIndex() != xIndex) continue; - int j = set.getEntryPosition(e); + int j = set.getEntryIndex(e); float y = (e.getVal() - mChart.getYChartMin()); if (Float.isNaN(y)) From 642d6480462b5b8d0b1316da40a18e83568b9d43 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:54:41 +0100 Subject: [PATCH 0576/1390] Fix compile errors in PieChart & RadarChart --- .../src/com/github/mikephil/charting/charts/PieChart.java | 7 ++++--- .../github/mikephil/charting/charts/PieRadarChartBase.java | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index adeb6954bf..9a3b42bfe3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -17,6 +17,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; @@ -200,13 +201,13 @@ private void calcAngles() { mDrawAngles = new float[mData.getYValCount()]; mAbsoluteAngles = new float[mData.getYValCount()]; - List dataSets = mData.getDataSets(); + List dataSets = mData.getDataSets(); int cnt = 0; for (int i = 0; i < mData.getDataSetCount(); i++) { - PieDataSet set = dataSets.get(i); + IPieDataSet set = dataSets.get(i); List entries = set.getYVals(); for (int j = 0; j < entries.size(); j++) { @@ -281,7 +282,7 @@ public int getIndexForAngle(float angle) { */ public int getDataSetIndexForIndex(int xIndex) { - List> dataSets = mData.getDataSets(); + List dataSets = mData.getDataSets(); for (int i = 0; i < dataSets.size(); i++) { if (dataSets.get(i).getEntryForXIndex(xIndex) != null) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 3abbc7d81c..68b854827d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -18,6 +18,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; @@ -30,7 +31,7 @@ * * @author Philipp Jahoda */ -public abstract class PieRadarChartBase>> +public abstract class PieRadarChartBase>> extends Chart { /** holds the normalized version of the current rotation angle of the chart */ @@ -451,7 +452,7 @@ public List getSelectionDetailsAtIndex(int xIndex) { for (int i = 0; i < mData.getDataSetCount(); i++) { - DataSet dataSet = mData.getDataSetByIndex(i); + IDataSet dataSet = mData.getDataSetByIndex(i); // extract all y-values from all DataSets at the given x-index final float yVal = dataSet.getYValForXIndex(xIndex); From 3a451e238bb8f741630125bea19e0a638a8a0ce3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 21:58:54 +0100 Subject: [PATCH 0577/1390] Fix compile errors in Pie- and RadarChartRenderer --- .../github/mikephil/charting/data/DataSet.java | 1 - .../charting/data/realm/RealmLineDataSet.java | 9 +++++++-- .../charting/renderer/PieChartRenderer.java | 17 ++++++++--------- .../charting/renderer/RadarChartRenderer.java | 10 +++++----- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index bc290a5926..c8eb3467bb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -4,7 +4,6 @@ import android.content.Context; import android.graphics.Color; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.utils.ColorTemplate; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 9255f6c53a..8a8801837c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -166,12 +166,17 @@ public void calcMinMax(List values, int start, int end) { } @Override - public Entry getEntryForXIndex(int x) { + public Entry getEntryForXIndex(int xIndex) { return null; } @Override - public int getEntryIndex(int x) { + public Entry getEntryForIndex(int index) { + return null; + } + + @Override + public int getEntryIndex(int xIndex) { return 0; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 2b4fdb488c..16bc158fa7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -13,17 +13,16 @@ import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; -import android.util.Log; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; -import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; import java.util.List; @@ -120,14 +119,14 @@ public void drawData(Canvas c) { PieData pieData = mChart.getData(); - for (PieDataSet set : pieData.getDataSets()) { + for (IPieDataSet set : pieData.getDataSets()) { if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } - protected void drawDataSet(Canvas c, PieDataSet dataSet) { + protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = mChart.getRotationAngle(); @@ -179,14 +178,14 @@ public void drawValues(Canvas c) { r -= off; // offset to keep things inside the chart PieData data = mChart.getData(); - List dataSets = data.getDataSets(); + List dataSets = data.getDataSets(); boolean drawXVals = mChart.isDrawSliceTextEnabled(); int cnt = 0; for (int i = 0; i < dataSets.size(); i++) { - PieDataSet dataSet = dataSets.get(i); + IPieDataSet dataSet = dataSets.get(i); if (!dataSet.isDrawValuesEnabled() && !drawXVals) continue; @@ -398,7 +397,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex >= drawAngles.length) continue; - PieDataSet set = mChart.getData() + IPieDataSet set = mChart.getData() .getDataSetByIndex(indices[i] .getDataSetIndex()); @@ -448,7 +447,7 @@ protected void drawRoundedSlices(Canvas c) { if (!mChart.isDrawRoundedSlicesEnabled()) return; - PieDataSet dataSet = mChart.getData().getDataSet(); + IPieDataSet dataSet = mChart.getData().getDataSet(); if (!dataSet.isVisible()) return; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 336315da49..1db9358f10 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.charts.RadarChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; -import com.github.mikephil.charting.data.RadarDataSet; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -56,14 +56,14 @@ public void drawData(Canvas c) { RadarData radarData = mChart.getData(); - for (RadarDataSet set : radarData.getDataSets()) { + for (IRadarDataSet set : radarData.getDataSets()) { if (set.isVisible() && set.getEntryCount() > 0) drawDataSet(c, set); } } - protected void drawDataSet(Canvas c, RadarDataSet dataSet) { + protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { float sliceangle = mChart.getSliceAngle(); @@ -131,7 +131,7 @@ public void drawValues(Canvas c) { for (int i = 0; i < mChart.getData().getDataSetCount(); i++) { - RadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); + IRadarDataSet dataSet = mChart.getData().getDataSetByIndex(i); if (!dataSet.isDrawValuesEnabled() || dataSet.getEntryCount() == 0) continue; @@ -215,7 +215,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { - RadarDataSet set = mChart.getData() + IRadarDataSet set = mChart.getData() .getDataSetByIndex(indices[i] .getDataSetIndex()); From 98f375f9f94907c9a4ec8e275a33f7956a8b0728 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 22:01:57 +0100 Subject: [PATCH 0578/1390] Fix compile errors in example project --- .../mpchartexample/PieChartActivity.java | 3 ++- .../mpchartexample/RadarChartActivitry.java | 15 ++++++++------- .../mikephil/charting/data/LineRadarDataSet.java | 8 +------- .../charting/data/realm/RealmLineDataSet.java | 5 +++++ .../datasets/ILineRadarDataSet.java | 9 +++++++++ 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 72a84b937b..90c2fdc37f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -24,6 +24,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; @@ -116,7 +117,7 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 143bdaf6ed..2c6a2e0656 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -14,10 +14,11 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -83,14 +84,14 @@ public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.actionToggleValues: { - for (DataSet set : mChart.getData().getDataSets()) + for (IDataSet set : mChart.getData().getDataSets()) set.setDrawValues(!set.isDrawValuesEnabled()); mChart.invalidate(); break; } case R.id.actionToggleHighlight: { - if(mChart.getData() != null) { + if (mChart.getData() != null) { mChart.getData().setHighlightEnabled(!mChart.getData().isHighlightEnabled()); mChart.invalidate(); } @@ -106,10 +107,10 @@ public boolean onOptionsItemSelected(MenuItem item) { } case R.id.actionToggleFilled: { - ArrayList sets = (ArrayList) mChart.getData() + ArrayList sets = (ArrayList) mChart.getData() .getDataSets(); - for (RadarDataSet set : sets) { + for (IRadarDataSet set : sets) { if (set.isDrawFilledEnabled()) set.setDrawFilled(false); else @@ -147,7 +148,7 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } - private String[] mParties = new String[] { + private String[] mParties = new String[]{ "Party A", "Party B", "Party C", "Party D", "Party E", "Party F", "Party G", "Party H", "Party I" }; @@ -186,7 +187,7 @@ public void setData() { set2.setDrawFilled(true); set2.setLineWidth(2f); - ArrayList sets = new ArrayList(); + ArrayList sets = new ArrayList(); sets.add(set1); sets.add(set2); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index 9efb327933..f1c496c182 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -81,13 +81,7 @@ public float getLineWidth() { return mLineWidth; } - /** - * Set to true if the DataSet should be drawn filled (surface), and not just - * as a line, disabling this will give great performance boost! default: - * false - * - * @param filled - */ + @Override public void setDrawFilled(boolean filled) { mDrawFilled = filled; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 8a8801837c..07501a4bbc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -115,6 +115,11 @@ public boolean isDrawFilledEnabled() { return false; } + @Override + public void setDrawFilled(boolean enabled) { + + } + @Override public boolean isVerticalHighlightIndicatorEnabled() { return false; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java index 210d6ada82..fed9ac71bf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java @@ -35,4 +35,13 @@ public interface ILineRadarDataSet extends ILineScatterCandleRa * @return */ boolean isDrawFilledEnabled(); + + /** + * Set to true if the DataSet should be drawn filled (surface), and not just + * as a line, disabling this will give great performance boost! default: + * false + * + * @param enabled + */ + void setDrawFilled(boolean enabled); } From a57104e6afe4224237352c04f27f7cff0a3f5700 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 3 Nov 2015 22:09:35 +0100 Subject: [PATCH 0579/1390] Move data interfaces to different package --- .../xxmassdeveloper/mpchartexample/AnotherBarActivity.java | 5 ++--- .../xxmassdeveloper/mpchartexample/BarChartActivity.java | 4 ++-- .../mpchartexample/BarChartActivityMultiDataset.java | 2 +- .../mpchartexample/BarChartActivitySinus.java | 3 +-- .../mpchartexample/BubbleChartActivity.java | 4 ++-- .../mpchartexample/CandleStickChartActivity.java | 2 +- .../mpchartexample/CombinedChartActivity.java | 3 +-- .../mpchartexample/CubicLineChartActivity.java | 4 ++-- .../xxmassdeveloper/mpchartexample/DrawChartActivity.java | 2 +- .../mpchartexample/DynamicalAddingActivity.java | 2 +- .../mpchartexample/HorizontalBarChartActivity.java | 6 +----- .../mpchartexample/InvertedLineChartActivity.java | 5 +---- .../xxmassdeveloper/mpchartexample/LineChartActivity1.java | 2 +- .../xxmassdeveloper/mpchartexample/LineChartActivity2.java | 4 +--- .../mpchartexample/LineChartActivityColored.java | 2 +- .../mpchartexample/ListViewBarChartActivity.java | 2 +- .../mpchartexample/ListViewMultiChartActivity.java | 2 +- .../mpchartexample/MultiLineChartActivity.java | 2 +- .../xxmassdeveloper/mpchartexample/PieChartActivity.java | 3 +-- .../mpchartexample/RadarChartActivitry.java | 4 ++-- .../mpchartexample/RealmDatabaseActivity.java | 5 +---- .../mpchartexample/RealtimeLineChartActivity.java | 2 +- .../mpchartexample/ScatterChartActivity.java | 2 +- .../xxmassdeveloper/mpchartexample/StackedBarActivity.java | 2 +- .../mpchartexample/StackedBarActivityNegative.java | 3 +-- .../mpchartexample/custom/MyFillFormatter.java | 2 +- .../mpchartexample/fragments/SimpleFragment.java | 6 +++--- .../src/com/github/mikephil/charting/charts/BarChart.java | 3 +-- .../github/mikephil/charting/charts/BarLineChartBase.java | 3 +-- .../com/github/mikephil/charting/charts/BubbleChart.java | 3 +-- .../src/com/github/mikephil/charting/charts/Chart.java | 3 +-- .../com/github/mikephil/charting/charts/CombinedChart.java | 3 +-- .../mikephil/charting/charts/HorizontalBarChart.java | 2 +- .../src/com/github/mikephil/charting/charts/PieChart.java | 4 +--- .../github/mikephil/charting/charts/PieRadarChartBase.java | 3 +-- .../src/com/github/mikephil/charting/data/BarData.java | 2 +- .../src/com/github/mikephil/charting/data/BarDataSet.java | 2 +- .../charting/data/BarLineScatterCandleBubbleData.java | 3 +-- .../charting/data/BarLineScatterCandleBubbleDataSet.java | 2 +- .../src/com/github/mikephil/charting/data/BaseDataSet.java | 3 +-- .../src/com/github/mikephil/charting/data/BubbleData.java | 2 +- .../com/github/mikephil/charting/data/BubbleDataSet.java | 3 +-- .../src/com/github/mikephil/charting/data/CandleData.java | 2 +- .../com/github/mikephil/charting/data/CandleDataSet.java | 2 +- .../src/com/github/mikephil/charting/data/ChartData.java | 2 +- .../com/github/mikephil/charting/data/CombinedData.java | 2 +- .../src/com/github/mikephil/charting/data/LineData.java | 2 +- .../src/com/github/mikephil/charting/data/LineDataSet.java | 2 +- .../github/mikephil/charting/data/LineRadarDataSet.java | 2 +- .../charting/data/LineScatterCandleRadarDataSet.java | 2 +- .../src/com/github/mikephil/charting/data/PieData.java | 2 +- .../src/com/github/mikephil/charting/data/PieDataSet.java | 2 +- .../src/com/github/mikephil/charting/data/RadarData.java | 2 +- .../com/github/mikephil/charting/data/RadarDataSet.java | 2 +- .../src/com/github/mikephil/charting/data/ScatterData.java | 2 +- .../com/github/mikephil/charting/data/ScatterDataSet.java | 2 +- .../mikephil/charting/data/realm/RealmLineDataSet.java | 5 +---- .../mikephil/charting/formatter/DefaultFillFormatter.java | 2 +- .../github/mikephil/charting/formatter/FillFormatter.java | 2 +- .../github/mikephil/charting/highlight/BarHighlighter.java | 3 +-- .../mikephil/charting/highlight/ChartHighlighter.java | 3 +-- .../mikephil/charting/highlight/CombinedHighlighter.java | 3 +-- .../charting/highlight/HorizontalBarHighlighter.java | 2 +- .../{datainterfaces => }/datasets/IBarDataSet.java | 2 +- .../datasets/IBarLineScatterCandleBubbleDataSet.java | 2 +- .../{datainterfaces => }/datasets/IBubbleDataSet.java | 3 +-- .../{datainterfaces => }/datasets/ICandleDataSet.java | 2 +- .../interfaces/{datainterfaces => }/datasets/IDataSet.java | 2 +- .../{datainterfaces => }/datasets/ILineDataSet.java | 2 +- .../{datainterfaces => }/datasets/ILineRadarDataSet.java | 2 +- .../datasets/ILineScatterCandleRadarDataSet.java | 2 +- .../{datainterfaces => }/datasets/IPieDataSet.java | 2 +- .../{datainterfaces => }/datasets/IRadarDataSet.java | 2 +- .../{datainterfaces => }/datasets/IScatterDataSet.java | 2 +- .../charting/listener/BarLineChartTouchListener.java | 6 ++---- .../mikephil/charting/renderer/BarChartRenderer.java | 3 +-- .../mikephil/charting/renderer/BubbleChartRenderer.java | 2 +- .../charting/renderer/CandleStickChartRenderer.java | 3 +-- .../github/mikephil/charting/renderer/DataRenderer.java | 3 +-- .../charting/renderer/HorizontalBarChartRenderer.java | 2 +- .../github/mikephil/charting/renderer/LegendRenderer.java | 7 ++----- .../mikephil/charting/renderer/LineChartRenderer.java | 2 +- .../charting/renderer/LineScatterCandleRadarRenderer.java | 3 +-- .../mikephil/charting/renderer/PieChartRenderer.java | 2 +- .../mikephil/charting/renderer/RadarChartRenderer.java | 2 +- .../mikephil/charting/renderer/ScatterChartRenderer.java | 2 +- .../github/mikephil/charting/utils/SelectionDetail.java | 3 +-- 87 files changed, 96 insertions(+), 141 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IBarDataSet.java (94%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IBarLineScatterCandleBubbleDataSet.java (81%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IBubbleDataSet.java (82%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/ICandleDataSet.java (94%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IDataSet.java (98%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/ILineDataSet.java (96%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/ILineRadarDataSet.java (93%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/ILineScatterCandleRadarDataSet.java (92%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IPieDataSet.java (87%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IRadarDataSet.java (69%) rename MPChartLib/src/com/github/mikephil/charting/interfaces/{datainterfaces => }/datasets/IScatterDataSet.java (87%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 47aadc68fd..244cac2b4f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -16,11 +16,10 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 0736149c82..81056b9a5b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -32,8 +32,8 @@ import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.YAxisValueFormatter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyYAxisValueFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index ae9428980b..d3fe246c76 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -23,7 +23,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.LargeValueFormatter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index c57568f15d..745f1f441d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -22,10 +22,9 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.FileUtils; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index 70a27cbfb8..f47e1e2a47 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -24,8 +24,8 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 87515c1f0a..414530a9c3 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -20,7 +20,7 @@ import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 1ce9acb4ea..4a7444a14f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -22,13 +22,12 @@ import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.CombinedData; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 2237009000..3f2192139e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -21,8 +21,8 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 96cca2c363..18eacb72ad 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -16,7 +16,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 31f46c04b0..52b08e68bf 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index c165f5ff08..05c181fefe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -24,16 +24,12 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index a543b709bc..f4a5acc383 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -16,15 +16,12 @@ import com.github.mikephil.charting.components.Legend.LegendForm; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.BarDataSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 8e912eaad2..913d37216d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -28,7 +28,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 82635a0566..b2e777c7f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -20,17 +20,15 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.components.YAxis.AxisDependency; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; -import com.xxmassdeveloper.mpchartexample.custom.MyFillFormatter; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 6f21471269..3d6d8a4cd4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import java.util.ArrayList; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java index 71a474eb2a..e1c69086bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewBarChartActivity.java @@ -20,7 +20,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index 74779c0c5d..dfa137abb1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -18,7 +18,7 @@ import com.github.mikephil.charting.data.LineDataSet; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.listviewitems.BarChartItem; import com.xxmassdeveloper.mpchartexample.listviewitems.ChartItem; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 2ec667e244..651616f912 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -19,7 +19,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java index 90c2fdc37f..cedd8e7628 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/PieChartActivity.java @@ -20,11 +20,10 @@ import com.github.mikephil.charting.charts.PieChart; import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.Legend.LegendPosition; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 2c6a2e0656..f38804ddb1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -17,8 +17,8 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.data.RadarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyMarkerView; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index d1fa1bca0c..ca7dfaef82 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -7,10 +7,9 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -18,8 +17,6 @@ import io.realm.Realm; import io.realm.RealmConfiguration; -import io.realm.RealmObject; -import io.realm.RealmQuery; import io.realm.RealmResults; /** diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 52ef71151d..8c4d1b9120 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -19,7 +19,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.LineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index af471c83a8..02a7760873 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -23,7 +23,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index f30c6e4915..ea106e4de2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -23,7 +23,7 @@ import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.utils.ColorTemplate; import com.xxmassdeveloper.mpchartexample.custom.MyValueFormatter; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 0f7fd3e155..17625a8ede 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -18,11 +18,10 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.data.filter.Approximator.ApproximatorType; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.listener.OnChartValueSelectedListener; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.formatter.ValueFormatter; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java index 1f330dfd76..2ca92f61eb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/MyFillFormatter.java @@ -1,7 +1,7 @@ package com.xxmassdeveloper.mpchartexample.custom; import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index d789d7952e..10865174a1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -21,9 +21,9 @@ import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.data.ScatterDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FileUtils; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 26782e2f36..177a62905b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -7,11 +7,10 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.highlight.BarHighlighter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.renderer.BarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererBarChart; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 02d7942449..3c1374d914 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -21,11 +21,10 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; -import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java index a478b50788..fe7942f0a2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -5,8 +5,7 @@ import android.util.AttributeSet; import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.BubbleDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.renderer.BubbleChartRenderer; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index de0bd36a97..5967d64ec0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -31,10 +31,9 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.components.MarkerView; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.ChartHighlighter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface; import com.github.mikephil.charting.listener.ChartTouchListener; import com.github.mikephil.charting.listener.OnChartGestureListener; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index fa2ed990e4..b946e6470a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -6,13 +6,12 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BubbleData; -import com.github.mikephil.charting.data.BubbleDataSet; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CombinedData; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.CombinedHighlighter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index f1335cb1ef..e87a11bef1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -14,7 +14,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.highlight.HorizontalBarHighlighter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 9a3b42bfe3..b6098f8f0d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -12,12 +12,10 @@ import android.text.SpannableString; import android.util.AttributeSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieData; -import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.renderer.PieChartRenderer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java index 68b854827d..198af5216c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieRadarChartBase.java @@ -16,9 +16,8 @@ import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.listener.PieRadarChartTouchListener; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 4af86eae6c..43b6e88e86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index d0e8e6ab86..d5f8b7dd00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -3,7 +3,7 @@ import android.graphics.Color; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java index 1962545701..84dc3df67e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleData.java @@ -1,8 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java index 15424909a1..fba8216c3d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarLineScatterCandleBubbleDataSet.java @@ -3,7 +3,7 @@ import android.graphics.Color; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index c126d7f235..241f928b34 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -6,10 +6,9 @@ import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; -import java.util.ArrayList; import java.util.List; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index ae349558cb..53945ac0e5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index 8fd141187c..aea8fade57 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -3,8 +3,7 @@ import android.graphics.Color; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index 821993718f..a1c797b4fa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -1,6 +1,6 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 45fc704c12..6275ddd19d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -3,7 +3,7 @@ import android.graphics.Paint; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 22754058a5..c1f5ed6a78 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -7,7 +7,7 @@ import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import java.util.ArrayList; import java.util.Arrays; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java index b71d066cce..2d7982265d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CombinedData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index a411fda37c..9adb07b60d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index b7d0557aac..8d760ef753 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -5,7 +5,7 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java index f1c496c182..718aecc4f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineRadarDataSet.java @@ -3,7 +3,7 @@ import android.graphics.Color; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineRadarDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java index 3b9ad6529f..90a0a43fb3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineScatterCandleRadarDataSet.java @@ -2,7 +2,7 @@ import android.graphics.DashPathEffect; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineScatterCandleRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineScatterCandleRadarDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 6cb55e6bc3..c2cf7fc7d3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java index acedd40f87..2fe974b76b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieDataSet.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 3374a63135..48494d3d65 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java index 354af2ff75..189ac032a9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarDataSet.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index a9fed8ebba..99422dd916 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.data; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java index a699ba4fe3..874cc2ffb3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterDataSet.java @@ -4,7 +4,7 @@ import android.graphics.Path; import com.github.mikephil.charting.charts.ScatterChart.ScatterShape; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 07501a4bbc..2fc8790e34 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -3,14 +3,11 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BaseDataSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import java.util.ArrayList; import java.util.List; diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index 9e007e43b0..e0fc63addf 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -2,7 +2,7 @@ import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java index 1862865e5a..66895d77e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/FillFormatter.java @@ -1,6 +1,6 @@ package com.github.mikephil.charting.formatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index 09dd9595f9..2dff191ca9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -1,9 +1,8 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java index dbb874474c..04ee9bec11 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/ChartHighlighter.java @@ -4,8 +4,7 @@ import java.util.List; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java index 05aceccbed..25ffb1f334 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/CombinedHighlighter.java @@ -2,8 +2,7 @@ import com.github.mikephil.charting.data.ChartData; import com.github.mikephil.charting.data.CombinedData; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.SelectionDetail; diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java index 1225c4619c..1930409a1b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/HorizontalBarHighlighter.java @@ -1,7 +1,7 @@ package com.github.mikephil.charting.highlight; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java similarity index 94% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index 11b5b0b39f..47801c0881 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.BarEntry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java similarity index 81% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java index 21dfb564ce..0f9454b2cd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarLineScatterCandleBubbleDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java similarity index 82% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java index 58b6b3af43..2764b56d1d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBubbleDataSet.java @@ -1,7 +1,6 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.BubbleEntry; -import com.github.mikephil.charting.utils.Utils; /** * Created by philipp on 21/10/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java similarity index 94% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java index be60a02e91..8f2b96c96d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ICandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ICandleDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import android.graphics.Paint; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 3343bd8ebd..91797519ff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import android.graphics.Typeface; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java similarity index 96% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 327e742d20..03e2bd3a6f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java similarity index 93% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java index fed9ac71bf..62252cec6d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineRadarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java similarity index 92% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java index 3eca8c274a..9ab6802556 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/ILineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineScatterCandleRadarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java similarity index 87% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IPieDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java index f4908982e6..f431d21a18 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IPieDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java similarity index 69% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java index f6246466d4..22ea37dc72 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IRadarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java similarity index 87% rename from MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java index b62e4f59c4..e1d9904919 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datainterfaces/datasets/IScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IScatterDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.interfaces.datainterfaces.datasets; +package com.github.mikephil.charting.interfaces.datasets; import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index d214374228..6de33f84c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -13,12 +13,10 @@ import com.github.mikephil.charting.charts.BarLineChartBase; import com.github.mikephil.charting.charts.HorizontalBarChart; import com.github.mikephil.charting.data.BarLineScatterCandleBubbleData; -import com.github.mikephil.charting.data.BarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarLineScatterCandleBubbleDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 549c39299f..a069a47841 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -11,9 +11,8 @@ import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 651f558dc1..8c774e65f7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -9,7 +9,7 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 454547d854..55916227c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -8,9 +8,8 @@ import com.github.mikephil.charting.buffer.CandleBodyBuffer; import com.github.mikephil.charting.buffer.CandleShadowBuffer; import com.github.mikephil.charting.data.CandleData; -import com.github.mikephil.charting.data.CandleDataSet; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.highlight.Highlight; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java index 81e54fb35f..ec963ddccd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/DataRenderer.java @@ -8,10 +8,9 @@ import android.graphics.Paint.Style; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.DataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 1df0791923..077d7f27de 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 3dc1e3efd2..0b96988fe8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -7,13 +7,10 @@ import android.graphics.Typeface; import com.github.mikephil.charting.components.Legend; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.PieDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 6f76009624..4990ff4954 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -13,7 +13,7 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java index 2f5189e44e..c262953aa3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineScatterCandleRadarRenderer.java @@ -4,8 +4,7 @@ import android.graphics.Path; import com.github.mikephil.charting.animation.ChartAnimator; -import com.github.mikephil.charting.data.LineScatterCandleRadarDataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.ILineScatterCandleRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineScatterCandleRadarDataSet; import com.github.mikephil.charting.utils.ViewPortHandler; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 16bc158fa7..5fc2177acd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -21,7 +21,7 @@ import com.github.mikephil.charting.data.PieData; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 1db9358f10..0252051f86 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -12,7 +12,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.RadarData; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IRadarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index efb7f813ed..6006b0f67e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -11,7 +11,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java index 9d518855fa..1704eefeb8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/SelectionDetail.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.utils; -import com.github.mikephil.charting.data.DataSet; -import com.github.mikephil.charting.interfaces.datainterfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IDataSet; /** * Class that encapsulates information of a value that has been From 20141a0499078db2bd930e739cad54f3a0b42d0d Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:10:28 +0100 Subject: [PATCH 0580/1390] Remove getYVals() method LineRenderer --- .../charting/buffer/AbstractBuffer.java | 4 +- .../charting/buffer/CircleBuffer.java | 9 +- .../mikephil/charting/buffer/LineBuffer.java | 11 +-- .../mikephil/charting/data/DataSet.java | 6 +- .../interfaces/datasets/IDataSet.java | 7 -- .../charting/renderer/LineChartRenderer.java | 95 +++++++++---------- .../mikephil/charting/utils/Transformer.java | 7 +- 7 files changed, 67 insertions(+), 72 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java index 3089c0bde6..958d12afba 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/AbstractBuffer.java @@ -85,7 +85,7 @@ public void setPhases(float phaseX, float phaseY) { * Builds up the buffer with the provided data and resets the buffer-index * after feed-completion. This needs to run FAST. * - * @param entries + * @param data */ - public abstract void feed(List entries); + public abstract void feed(T data); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java index 1b37525942..2e8f753af7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CircleBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import java.util.List; - -public class CircleBuffer extends AbstractBuffer { +public class CircleBuffer extends AbstractBuffer { public CircleBuffer(int size) { super(size); @@ -17,13 +16,13 @@ protected void addCircle(float x, float y) { } @Override - public void feed(List entries) { + public void feed(ILineDataSet data) { int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); for (int i = mFrom; i < size; i++) { - Entry e = entries.get(i); + Entry e = data.getEntryForIndex(i); addCircle(e.getXIndex(), e.getVal() * phaseY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java index 173ac166f3..723124f72d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/LineBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import java.util.List; - -public class LineBuffer extends AbstractBuffer { +public class LineBuffer extends AbstractBuffer { public LineBuffer(int size) { super((size < 4) ? 4 : size); @@ -41,15 +40,15 @@ public void lineTo(float x, float y) { } @Override - public void feed(List entries) { - moveTo(entries.get(mFrom).getXIndex(), entries.get(mFrom).getVal() * phaseY); + public void feed(ILineDataSet data) { + moveTo(data.getEntryForIndex(mFrom).getXIndex(), data.getEntryForIndex(mFrom).getVal() * phaseY); int size = (int) Math.ceil((mTo - mFrom) * phaseX + mFrom); int from = mFrom + 1; for (int i = from; i < size; i++) { - Entry e = entries.get(i); + Entry e = data.getEntryForIndex(i); lineTo(e.getXIndex(), e.getVal() * phaseY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index c8eb3467bb..ba0c84a7ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -150,7 +150,11 @@ public List getEntriesForXIndex(int x) { return entries; } - @Override + /** + * Returns the array of y-values that this DataSet represents. + * + * @return + */ public List getYVals() { return mYVals; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 91797519ff..c47c2cce99 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -15,13 +15,6 @@ public interface IDataSet { /** ###### ###### DATA RELATED METHODS ###### ###### */ - /** - * returns the DataSets Entry array - * - * @return - */ - List getYVals(); - /** * returns the minimum y-value this DataSet holds * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 4990ff4954..ebcadb3276 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -13,9 +13,9 @@ import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -106,9 +106,7 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, ILineDataSet dataSet) { - List entries = dataSet.getYVals(); - - if (entries.size() < 1) + if (dataSet.getEntryCount() < 1) return; mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); @@ -117,11 +115,11 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { // if drawing cubic lines is enabled if (dataSet.isDrawCubicEnabled()) { - drawCubic(c, dataSet, entries); + drawCubic(c, dataSet); // draw normal (straight) lines } else { - drawLinear(c, dataSet, entries); + drawLinear(c, dataSet); } mRenderPaint.setPathEffect(null); @@ -132,19 +130,20 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { * * @param c * @param dataSet - * @param entries */ - protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { + protected void drawCubic(Canvas c, ILineDataSet dataSet) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); + int entryCount = dataSet.getEntryCount(); + Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); @@ -162,10 +161,10 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { float curDx = 0f; float curDy = 0f; - Entry prevPrev = entries.get(minx); - Entry prev = entries.get(minx); - Entry cur = entries.get(minx); - Entry next = entries.get(minx + 1); + Entry prevPrev = dataSet.getEntryForIndex(minx); + Entry prev = prevPrev; + Entry cur = prev; + Entry next = dataSet.getEntryForIndex(minx + 1); // let the spline start cubicPath.moveTo(cur.getXIndex(), cur.getVal() * phaseY); @@ -181,12 +180,12 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { cur.getXIndex() - curDx, (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); - for (int j = minx + 1, count = Math.min(size, entries.size() - 1); j < count; j++) { + for (int j = minx + 1, count = Math.min(size, entryCount - 1); j < count; j++) { - prevPrev = entries.get(j == 1 ? 0 : j - 2); - prev = entries.get(j - 1); - cur = entries.get(j); - next = entries.get(j + 1); + prevPrev = dataSet.getEntryForIndex(j == 1 ? 0 : j - 2); + prev = dataSet.getEntryForIndex(j - 1); + cur = dataSet.getEntryForIndex(j); + next = dataSet.getEntryForIndex(j + 1); prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; prevDy = (cur.getVal() - prevPrev.getVal()) * intensity; @@ -198,12 +197,12 @@ protected void drawCubic(Canvas c, ILineDataSet dataSet, List entries) { (cur.getVal() - curDy) * phaseY, cur.getXIndex(), cur.getVal() * phaseY); } - if (size > entries.size() - 1) { + if (size > entryCount - 1) { - prevPrev = entries.get((entries.size() >= 3) ? entries.size() - 3 - : entries.size() - 2); - prev = entries.get(entries.size() - 2); - cur = entries.get(entries.size() - 1); + prevPrev = dataSet.getEntryForIndex((entryCount >= 3) ? entryCount - 3 + : entryCount - 2); + prev = dataSet.getEntryForIndex(entryCount - 2); + cur = dataSet.getEntryForIndex(entryCount - 1); next = cur; prevDx = (cur.getXIndex() - prevPrev.getXIndex()) * intensity; @@ -262,9 +261,10 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf * * @param c * @param dataSet - * @param entries */ - protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { + protected void drawLinear(Canvas c, ILineDataSet dataSet) { + + int entryCount = dataSet.getEntryCount(); int dataSetIndex = mChart.getLineData().getIndexOfDataSet(dataSet); @@ -290,7 +290,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), entryCount); int range = (maxx - minx) * 4 - 4; @@ -298,7 +298,7 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { buffer.setPhases(phaseX, phaseY); buffer.limitFrom(minx); buffer.limitTo(maxx); - buffer.feed(entries); + buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); @@ -338,18 +338,17 @@ protected void drawLinear(Canvas c, ILineDataSet dataSet, List entries) { mRenderPaint.setPathEffect(null); // if drawing filled is enabled - if (dataSet.isDrawFilledEnabled() && entries.size() > 0) { - drawLinearFill(c, dataSet, entries, minx, maxx, trans); + if (dataSet.isDrawFilledEnabled() && entryCount > 0) { + drawLinearFill(c, dataSet, minx, maxx, trans); } } - protected void drawLinearFill(Canvas c, ILineDataSet dataSet, List entries, int minx, + protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, int maxx, Transformer trans) { Path filled = generateFilledPath( - entries, - dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart), minx, maxx); + dataSet, minx, maxx); trans.pathValueToPixel(filled); @@ -377,31 +376,34 @@ protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fill /** * Generates the path that is used for filled drawing. * - * @param entries + * @param dataSet * @return */ - private Path generateFilledPath(List entries, float fillMin, int from, int to) { + private Path generateFilledPath(ILineDataSet dataSet, int from, int to) { + float fillMin = dataSet.getFillFormatter().getFillLinePosition(dataSet, mChart); float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); Path filled = new Path(); - filled.moveTo(entries.get(from).getXIndex(), fillMin); - filled.lineTo(entries.get(from).getXIndex(), entries.get(from).getVal() * phaseY); + Entry entry = dataSet.getEntryForIndex(from); + + filled.moveTo(entry.getXIndex(), fillMin); + filled.lineTo(entry.getXIndex(), entry.getVal() * phaseY); // create a new path for (int x = from + 1, count = (int) Math.ceil((to - from) * phaseX + from); x < count; x++) { - Entry e = entries.get(x); + Entry e = dataSet.getEntryForIndex(x); filled.lineTo(e.getXIndex(), e.getVal() * phaseY); } // close up filled.lineTo( - entries.get( + dataSet.getEntryForIndex( Math.max( Math.min((int) Math.ceil((to - from) * phaseX + from) - 1, - entries.size() - 1), 0)).getXIndex(), fillMin); + dataSet.getEntryCount() - 1), 0)).getXIndex(), fillMin); filled.close(); @@ -434,18 +436,16 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; - List entries = dataSet.getYVals(); - Entry entryFrom = dataSet.getEntryForXIndex(mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), dataSet.getEntryCount()); float[] positions = trans.generateTransformedValuesLine( - entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); + dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); for (int j = 0; j < positions.length; j += 2) { @@ -458,7 +458,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - Entry entry = entries.get(j / 2 + minx); + Entry entry = dataSet.getEntryForIndex(j / 2 + minx); drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, x, y - valOffset); @@ -492,7 +492,6 @@ protected void drawCircles(Canvas c) { mCirclePaintInner.setColor(dataSet.getCircleHoleColor()); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - List entries = dataSet.getYVals(); Entry entryFrom = dataSet.getEntryForXIndex((mMinX < 0) ? 0 : mMinX); Entry entryTo = dataSet.getEntryForXIndex(mMaxX); @@ -500,13 +499,13 @@ protected void drawCircles(Canvas c) { int diff = (entryFrom == entryTo) ? 1 : 0; int minx = Math.max(dataSet.getEntryIndex(entryFrom) - diff, 0); int maxx = Math.min(Math.max( - minx + 2, dataSet.getEntryIndex(entryTo) + 1), entries.size()); + minx + 2, dataSet.getEntryIndex(entryTo) + 1), dataSet.getEntryCount()); CircleBuffer buffer = mCircleBuffers[i]; buffer.setPhases(phaseX, phaseY); buffer.limitFrom(minx); buffer.limitTo(maxx); - buffer.feed(entries); + buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index cd936ffc9e..d53e74b6b0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import java.util.List; @@ -143,10 +144,10 @@ public float[] generateTransformedValuesBubble(List entries, * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the LINECHART. * - * @param entries + * @param data * @return */ - public float[] generateTransformedValuesLine(List entries, + public float[] generateTransformedValuesLine(ILineDataSet data, float phaseX, float phaseY, int from, int to) { final int count = (int) Math.ceil((to - from) * phaseX) * 2; @@ -155,7 +156,7 @@ public float[] generateTransformedValuesLine(List entries, for (int j = 0; j < count; j += 2) { - Entry e = entries.get(j / 2 + from); + Entry e = data.getEntryForIndex(j / 2 + from); if (e != null) { valuePoints[j] = e.getXIndex(); From 41e52e791f36d46b394a0f1c5cf85150ca6b9df3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:14:27 +0100 Subject: [PATCH 0581/1390] Remove getYVals() method BarRenderer --- .../mikephil/charting/buffer/BarBuffer.java | 11 +++++----- .../charting/renderer/BarChartRenderer.java | 20 ++++++++----------- .../mikephil/charting/utils/Transformer.java | 17 +++++++++------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java index 7387231698..3d8f114121 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/BarBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import java.util.List; - -public class BarBuffer extends AbstractBuffer { +public class BarBuffer extends AbstractBuffer { protected float mBarSpace = 0f; protected float mGroupSpace = 0f; @@ -42,9 +41,9 @@ protected void addBar(float left, float top, float right, float bottom) { } @Override - public void feed(List entries) { + public void feed(IBarDataSet data) { - float size = entries.size() * phaseX; + float size = data.getEntryCount() * phaseX; int dataSetOffset = (mDataSetCount - 1); float barSpaceHalf = mBarSpace / 2f; @@ -53,7 +52,7 @@ public void feed(List entries) { for (int i = 0; i < size; i++) { - BarEntry e = entries.get(i); + BarEntry e = data.getEntryForIndex(i); // calculate the x-position, depending on datasetcount float x = e.getXIndex() + e.getXIndex() * dataSetOffset + mDataSetIndex diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index a069a47841..ee8048fb09 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -12,9 +12,9 @@ import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarEntry; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -85,8 +85,6 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - List entries = dataSet.getYVals(); - // initialize the buffer BarBuffer buffer = mBarBuffers[index]; buffer.setPhases(phaseX, phaseY); @@ -94,7 +92,7 @@ protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); - buffer.feed(entries); + buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); @@ -207,9 +205,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - List entries = dataSet.getYVals(); - - float[] valuePoints = getTransformedValues(trans, entries, i); + float[] valuePoints = getTransformedValues(trans, dataSet, i); // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -223,7 +219,7 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) continue; - BarEntry entry = entries.get(j / 2); + BarEntry entry = dataSet.getEntryForIndex(j / 2); float val = entry.getVal(); drawValue(c, dataSet.getValueFormatter(), val, entry, i, valuePoints[j], @@ -235,7 +231,7 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - BarEntry entry = entries.get(j / 2); + BarEntry entry = dataSet.getEntryForIndex(j / 2); float[] vals = entry.getVals(); @@ -384,9 +380,9 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - public float[] getTransformedValues(Transformer trans, List entries, + public float[] getTransformedValues(Transformer trans, IBarDataSet data, int dataSetIndex) { - return trans.generateTransformedValuesBarChart(entries, dataSetIndex, + return trans.generateTransformedValuesBarChart(data, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index d53e74b6b0..00fc0d02a6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -8,6 +8,7 @@ import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import java.util.List; @@ -202,25 +203,27 @@ public float[] generateTransformedValuesCandle(List entries, * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. * - * @param entries - * @param dataSet the dataset index + * @param data + * @param dataSetIndex the dataset index + * @param bd + * @param phaseY * @return */ - public float[] generateTransformedValuesBarChart(List entries, - int dataSet, BarData bd, float phaseY) { + public float[] generateTransformedValuesBarChart(IBarDataSet data, + int dataSetIndex, BarData bd, float phaseY) { - float[] valuePoints = new float[entries.size() * 2]; + float[] valuePoints = new float[data.getEntryCount() * 2]; int setCount = bd.getDataSetCount(); float space = bd.getGroupSpace(); for (int j = 0; j < valuePoints.length; j += 2) { - Entry e = entries.get(j / 2); + Entry e = data.getEntryForIndex(j / 2); int i = e.getXIndex(); // calculate the x-position, depending on datasetcount - float x = e.getXIndex() + i * (setCount - 1) + dataSet + space * i + float x = e.getXIndex() + i * (setCount - 1) + dataSetIndex + space * i + space / 2f; float y = e.getVal(); From 088d0ad6f347c85f29dbe654b7929b48d72e64fe Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:16:22 +0100 Subject: [PATCH 0582/1390] Remove getYVals() method HorizontalBarRenderer --- .../renderer/HorizontalBarChartRenderer.java | 14 ++++++-------- .../mikephil/charting/utils/Transformer.java | 8 ++++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 077d7f27de..45fb1b1fb8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -65,7 +65,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { buffer.setDataSet(index); buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency())); - buffer.feed(entries); + buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); @@ -121,9 +121,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - List entries = dataSet.getYVals(); - - float[] valuePoints = getTransformedValues(trans, entries, i); + float[] valuePoints = getTransformedValues(trans, dataSet, i); // if only single values are drawn (sum) if (!dataSet.isStacked()) { @@ -139,7 +137,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) continue; - BarEntry e = entries.get(j / 2); + BarEntry e = dataSet.getEntryForIndex(j / 2); float val = e.getVal(); String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler); @@ -162,7 +160,7 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - BarEntry e = entries.get(j / 2); + BarEntry e = dataSet.getEntryForIndex(j / 2); float[] vals = e.getVals(); @@ -278,9 +276,9 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHa } @Override - public float[] getTransformedValues(Transformer trans, List entries, + public float[] getTransformedValues(Transformer trans, IBarDataSet data, int dataSetIndex) { - return trans.generateTransformedValuesHorizontalBarChart(entries, dataSetIndex, + return trans.generateTransformedValuesHorizontalBarChart(data, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); } diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 00fc0d02a6..41e9136f39 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -240,21 +240,21 @@ public float[] generateTransformedValuesBarChart(IBarDataSet data, * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BARCHART. * - * @param entries + * @param data * @param dataSet the dataset index * @return */ - public float[] generateTransformedValuesHorizontalBarChart(List entries, + public float[] generateTransformedValuesHorizontalBarChart(IBarDataSet data, int dataSet, BarData bd, float phaseY) { - float[] valuePoints = new float[entries.size() * 2]; + float[] valuePoints = new float[data.getEntryCount() * 2]; int setCount = bd.getDataSetCount(); float space = bd.getGroupSpace(); for (int j = 0; j < valuePoints.length; j += 2) { - Entry e = entries.get(j / 2); + Entry e = data.getEntryForIndex(j / 2); int i = e.getXIndex(); // calculate the x-position, depending on datasetcount From 6e66acb7a083705791dcb1a5bcdab8e8a7f9e16e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:18:32 +0100 Subject: [PATCH 0583/1390] Remove getYVals() method ScatterRenderer --- .../charting/buffer/ScatterBuffer.java | 11 +++++------ .../renderer/ScatterChartRenderer.java | 18 +++++++----------- .../mikephil/charting/utils/Transformer.java | 9 +++++---- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java index 11dcb66779..68ac437ac1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/ScatterBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; -import java.util.List; - -public class ScatterBuffer extends AbstractBuffer { +public class ScatterBuffer extends AbstractBuffer { public ScatterBuffer(int size) { super(size); @@ -17,13 +16,13 @@ protected void addForm(float x, float y) { } @Override - public void feed(List entries) { + public void feed(IScatterDataSet data) { - float size = entries.size() * phaseX; + float size = data.getEntryCount() * phaseX; for (int i = 0; i < size; i++) { - Entry e = entries.get(i); + Entry e = data.getEntryForIndex(i); addForm(e.getXIndex(), e.getVal() * phaseY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java index 6006b0f67e..2d9e051a01 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/ScatterChartRenderer.java @@ -11,8 +11,8 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.ScatterData; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -26,7 +26,7 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer { protected ScatterBuffer[] mScatterBuffers; public ScatterChartRenderer(ScatterDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -65,8 +65,6 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - List entries = dataSet.getYVals(); - float shapeHalf = dataSet.getScatterShapeSize() / 2f; ScatterShape shape = dataSet.getScatterShape(); @@ -74,7 +72,7 @@ protected void drawDataSet(Canvas c, IScatterDataSet dataSet) { ScatterBuffer buffer = mScatterBuffers[mChart.getScatterData().getIndexOfDataSet( dataSet)]; buffer.setPhases(phaseX, phaseY); - buffer.feed(entries); + buffer.feed(dataSet); trans.pointValuesToPixel(buffer.buffer); @@ -215,10 +213,8 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - List entries = dataSet.getYVals(); - float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) - .generateTransformedValuesScatter(entries, + .generateTransformedValuesScatter(dataSet, mAnimator.getPhaseY()); float shapeSize = dataSet.getScatterShapeSize(); @@ -233,7 +229,7 @@ public void drawValues(Canvas c) { || !mViewPortHandler.isInBoundsY(positions[j + 1]))) continue; - Entry entry = entries.get(j / 2); + Entry entry = dataSet.getEntryForIndex(j / 2); drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, positions[j], positions[j + 1] - shapeSize); @@ -258,7 +254,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; int xIndex = indices[i].getXIndex(); // get the - // x-position + // x-position if (xIndex > mChart.getXChartMax() * mAnimator.getPhaseX()) @@ -270,7 +266,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float y = yVal * mAnimator.getPhaseY(); - float[] pts = new float[] { + float[] pts = new float[]{ xIndex, y }; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 41e9136f39..119365ddb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -10,6 +10,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import java.util.List; @@ -89,17 +90,17 @@ public void prepareMatrixOffset(boolean inverted) { * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the SCATTERCHART. * - * @param entries + * @param data * @return */ - public float[] generateTransformedValuesScatter(List entries, + public float[] generateTransformedValuesScatter(IScatterDataSet data, float phaseY) { - float[] valuePoints = new float[entries.size() * 2]; + float[] valuePoints = new float[data.getEntryCount() * 2]; for (int j = 0; j < valuePoints.length; j += 2) { - Entry e = entries.get(j / 2); + Entry e = data.getEntryForIndex(j / 2); if (e != null) { valuePoints[j] = e.getXIndex(); From 20fa3ce17bcf52f273115496310570751c3958e3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:22:34 +0100 Subject: [PATCH 0584/1390] Remove getYVals() method Candle- & BubbleRenderer --- .../charting/buffer/CandleBodyBuffer.java | 9 +++-- .../charting/buffer/CandleShadowBuffer.java | 9 +++-- .../renderer/BubbleChartRenderer.java | 20 +++++------ .../renderer/CandleStickChartRenderer.java | 34 ++++++++----------- .../mikephil/charting/utils/Transformer.java | 14 ++++---- 5 files changed, 39 insertions(+), 47 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java index 46164a0add..d40c35ddce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleBodyBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import java.util.List; - -public class CandleBodyBuffer extends AbstractBuffer { +public class CandleBodyBuffer extends AbstractBuffer { private float mBodySpace = 0f; @@ -26,13 +25,13 @@ private void addBody(float left, float top, float right, float bottom) { } @Override - public void feed(List entries) { + public void feed(ICandleDataSet data) { int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); for (int i = mFrom; i < size; i++) { - CandleEntry e = entries.get(i); + CandleEntry e = data.getEntryForIndex(i); addBody(e.getXIndex() - 0.5f + mBodySpace, e.getClose() * phaseY, e.getXIndex() + 0.5f - mBodySpace, e.getOpen() * phaseY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java index 85b1766d66..2c413d66b4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/CandleShadowBuffer.java @@ -2,10 +2,9 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; -import java.util.List; - -public class CandleShadowBuffer extends AbstractBuffer { +public class CandleShadowBuffer extends AbstractBuffer { public CandleShadowBuffer(int size) { super(size); @@ -20,13 +19,13 @@ private void addShadow(float x1, float y1, float x2, float y2) { } @Override - public void feed(List entries) { + public void feed(ICandleDataSet data) { int size = (int)Math.ceil((mTo - mFrom) * phaseX + mFrom); for (int i = mFrom; i < size; i++) { - CandleEntry e = entries.get(i); + CandleEntry e = data.getEntryForIndex(i); addShadow(e.getXIndex(), e.getHigh() * phaseY, e.getXIndex(), e.getLow() * phaseY); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java index 8c774e65f7..509fd337f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BubbleChartRenderer.java @@ -9,8 +9,8 @@ import com.github.mikephil.charting.data.BubbleData; import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.highlight.Highlight; -import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -26,7 +26,7 @@ public class BubbleChartRenderer extends DataRenderer { protected BubbleDataProvider mChart; public BubbleChartRenderer(BubbleDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; @@ -69,13 +69,11 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - List entries = dataSet.getYVals(); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); int minx = Math.max(dataSet.getEntryIndex(entryFrom), 0); - int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, entries.size()); + int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); sizeBuffer[0] = 0f; sizeBuffer[2] = 1f; @@ -89,7 +87,7 @@ protected void drawDataSet(Canvas c, IBubbleDataSet dataSet) { for (int j = minx; j < maxx; j++) { - final BubbleEntry entry = entries.get(j); + final BubbleEntry entry = dataSet.getEntryForIndex(j); pointBuffer[0] = (float) (entry.getXIndex() - minx) * phaseX + (float) minx; pointBuffer[1] = (float) (entry.getVal()) * phaseY; @@ -150,8 +148,6 @@ public void drawValues(Canvas c) { mValuePaint.setColor(valueTextColor); - final List entries = dataSet.getYVals(); - BubbleEntry entryFrom = dataSet.getEntryForXIndex(mMinX); BubbleEntry entryTo = dataSet.getEntryForXIndex(mMaxX); @@ -159,7 +155,7 @@ public void drawValues(Canvas c) { int maxx = Math.min(dataSet.getEntryIndex(entryTo) + 1, dataSet.getEntryCount()); final float[] positions = mChart.getTransformer(dataSet.getAxisDependency()) - .generateTransformedValuesBubble(entries, phaseX, phaseY, minx, maxx); + .generateTransformedValuesBubble(dataSet, phaseX, phaseY, minx, maxx); for (int j = 0; j < positions.length; j += 2) { @@ -172,7 +168,7 @@ public void drawValues(Canvas c) { if ((!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y))) continue; - BubbleEntry entry = entries.get(j / 2 + minx); + BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x, y + (0.5f * lineHeight)); @@ -214,12 +210,12 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - + sizeBuffer[0] = 0f; sizeBuffer[2] = 1f; trans.pointValuesToPixel(sizeBuffer); - + // calcualte the full width of 1 step on the x-axis final float maxBubbleWidth = Math.abs(sizeBuffer[2] - sizeBuffer[0]); final float maxBubbleHeight = Math.abs(mViewPortHandler.contentBottom() - mViewPortHandler.contentTop()); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java index 55916227c2..2b4838365c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CandleStickChartRenderer.java @@ -9,10 +9,10 @@ import com.github.mikephil.charting.buffer.CandleShadowBuffer; import com.github.mikephil.charting.data.CandleData; import com.github.mikephil.charting.data.CandleEntry; -import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.utils.ColorTemplate; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -27,7 +27,7 @@ public class CandleStickChartRenderer extends LineScatterCandleRadarRenderer { private CandleBodyBuffer[] mBodyBuffers; public CandleStickChartRenderer(CandleDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(animator, viewPortHandler); mChart = chart; } @@ -66,20 +66,18 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet); - List entries = dataSet.getYVals(); - int minx = Math.max(mMinX, 0); - int maxx = Math.min(mMaxX + 1, entries.size()); + int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); int range = (maxx - minx) * 4; - int to = (int)Math.ceil((maxx - minx) * phaseX + minx); + int to = (int) Math.ceil((maxx - minx) * phaseX + minx); CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex]; bodyBuffer.setBodySpace(dataSet.getBodySpace()); bodyBuffer.setPhases(phaseX, phaseY); bodyBuffer.limitFrom(minx); bodyBuffer.limitTo(maxx); - bodyBuffer.feed(entries); + bodyBuffer.feed(dataSet); trans.pointValuesToPixel(bodyBuffer.buffer); @@ -87,7 +85,7 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { shadowBuffer.setPhases(phaseX, phaseY); shadowBuffer.limitFrom(minx); shadowBuffer.limitTo(maxx); - shadowBuffer.feed(entries); + shadowBuffer.feed(dataSet); trans.pointValuesToPixel(shadowBuffer.buffer); @@ -97,7 +95,7 @@ protected void drawDataSet(Canvas c, ICandleDataSet dataSet) { for (int j = 0; j < range; j += 4) { // get the entry - CandleEntry e = entries.get(j / 4 + minx); + CandleEntry e = dataSet.getEntryForIndex(j / 4 + minx); if (!fitsBounds(e.getXIndex(), mMinX, to)) continue; @@ -158,7 +156,7 @@ else if (e.getOpen() < e.getClose()) // draw the body c.drawRect(leftBody, close, rightBody, open, mRenderPaint); - } else if(open < close) { + } else if (open < close) { if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) { mRenderPaint.setColor(dataSet.getColor(j / 4 + minx)); @@ -170,7 +168,7 @@ else if (e.getOpen() < e.getClose()) // draw the body c.drawRect(leftBody, open, rightBody, close, mRenderPaint); } else { // equal values - + mRenderPaint.setColor(dataSet.getShadowColor()); c.drawLine(leftBody, open, rightBody, close, mRenderPaint); } @@ -198,13 +196,11 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); - List entries = dataSet.getYVals(); - int minx = Math.max(mMinX, 0); - int maxx = Math.min(mMaxX + 1, entries.size()); + int maxx = Math.min(mMaxX + 1, dataSet.getEntryCount()); float[] positions = trans.generateTransformedValuesCandle( - entries, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); + dataSet, mAnimator.getPhaseX(), mAnimator.getPhaseY(), minx, maxx); float yOffset = Utils.convertDpToPixel(5f); @@ -219,7 +215,7 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsLeft(x) || !mViewPortHandler.isInBoundsY(y)) continue; - CandleEntry entry = entries.get(j / 2 + minx); + CandleEntry entry = dataSet.getEntryForIndex(j / 2 + minx); drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset); } @@ -237,7 +233,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { for (int i = 0; i < indices.length; i++) { int xIndex = indices[i].getXIndex(); // get the - // x-position + // x-position ICandleDataSet set = mChart.getCandleData().getDataSetByIndex( indices[i].getDataSetIndex()); @@ -258,7 +254,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { float max = mChart.getYChartMax(); - float[] pts = new float[] { + float[] pts = new float[]{ xIndex, y }; diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java index 119365ddb6..344537aa7c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Transformer.java @@ -9,6 +9,8 @@ import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -117,10 +119,10 @@ public float[] generateTransformedValuesScatter(IScatterDataSet data, * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the BUBBLECHART. * - * @param entries + * @param data * @return */ - public float[] generateTransformedValuesBubble(List entries, + public float[] generateTransformedValuesBubble(IBubbleDataSet data, float phaseX, float phaseY, int from, int to) { final int count = (int) Math.ceil(to - from) * 2; // (int) Math.ceil((to - from) * phaseX) * 2; @@ -129,7 +131,7 @@ public float[] generateTransformedValuesBubble(List entries, for (int j = 0; j < count; j += 2) { - Entry e = entries.get(j / 2 + from); + Entry e = data.getEntryForIndex(j / 2 + from); if (e != null) { valuePoints[j] = (float) (e.getXIndex() - from) * phaseX + from; @@ -175,10 +177,10 @@ public float[] generateTransformedValuesLine(ILineDataSet data, * Transforms an List of Entry into a float array containing the x and * y values transformed with all matrices for the CANDLESTICKCHART. * - * @param entries + * @param data * @return */ - public float[] generateTransformedValuesCandle(List entries, + public float[] generateTransformedValuesCandle(ICandleDataSet data, float phaseX, float phaseY, int from, int to) { final int count = (int) Math.ceil((to - from) * phaseX) * 2; @@ -187,7 +189,7 @@ public float[] generateTransformedValuesCandle(List entries, for (int j = 0; j < count; j += 2) { - CandleEntry e = entries.get(j / 2 + from); + CandleEntry e = data.getEntryForIndex(j / 2 + from); if (e != null) { valuePoints[j] = e.getXIndex(); From 293361fba1e8e7d13f027a246312854cf8b66d90 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:37:23 +0100 Subject: [PATCH 0585/1390] Remove laststart & lastend --- .../charting/buffer/HorizontalBarBuffer.java | 11 +- .../mikephil/charting/data/BaseDataSet.java | 22 +- .../mikephil/charting/data/ChartData.java | 29 +-- .../mikephil/charting/data/DataSet.java | 27 +- .../interfaces/datasets/IDataSet.java | 7 +- .../renderer/CombinedChartRenderer.java | 240 +++++++++--------- 6 files changed, 158 insertions(+), 178 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java index 8555206fc9..48d81a566c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java +++ b/MPChartLib/src/com/github/mikephil/charting/buffer/HorizontalBarBuffer.java @@ -2,8 +2,7 @@ package com.github.mikephil.charting.buffer; import com.github.mikephil.charting.data.BarEntry; - -import java.util.List; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; public class HorizontalBarBuffer extends BarBuffer { @@ -12,9 +11,9 @@ public HorizontalBarBuffer(int size, float groupspace, int dataSetCount, boolean } @Override - public void feed(List entries) { + public void feed(IBarDataSet data) { - float size = entries.size() * phaseX; + float size = data.getEntryCount() * phaseX; int dataSetOffset = (mDataSetCount - 1); float barSpaceHalf = mBarSpace / 2f; @@ -23,7 +22,7 @@ public void feed(List entries) { for (int i = 0; i < size; i++) { - BarEntry e = entries.get(i); + BarEntry e = data.getEntryForIndex(i); // calculate the x-position, depending on datasetcount float x = e.getXIndex() + e.getXIndex() * dataSetOffset + mDataSetIndex @@ -63,7 +62,7 @@ public void feed(List entries) { float value = vals[k]; - if(value >= 0f) { + if (value >= 0f) { y = posY; yStart = posY + value; posY = yStart; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 241f928b34..3b79383e5d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -33,15 +33,15 @@ public abstract class BaseDataSet implements IDataSet { */ protected YAxis.AxisDependency mAxisDependency = YAxis.AxisDependency.LEFT; - /** - * the last start value used for calcMinMax - */ - protected int mLastStart = 0; - - /** - * the last end value used for calcMinMax - */ - protected int mLastEnd = 0; +// /** +// * the last start value used for calcMinMax +// */ +// protected int mLastStart = 0; +// +// /** +// * the last end value used for calcMinMax +// */ +// protected int mLastEnd = 0; /** * if true, value highlightning is enabled @@ -95,10 +95,10 @@ public BaseDataSet(String label) { } /** - * Use this method to tell the data set that the underlying data has changed + * Use this method to tell the data set that the underlying data has changed. */ public void notifyDataSetChanged() { - calcMinMax(getYVals(), mLastStart, mLastEnd); + calcMinMax( 0, getEntryCount()-1); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index c1f5ed6a78..0d020adb35 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -44,16 +44,6 @@ public abstract class ChartData> { */ private int mYValCount = 0; - /** - * the last start value used for calcMinMax - */ - protected int mLastStart = 0; - - /** - * the last end value used for calcMinMax - */ - protected int mLastEnd = 0; - /** * contains the average length (in characters) an entry in the x-vals array * has @@ -147,8 +137,8 @@ protected void init() { checkLegal(); - calcMinMax(mLastStart, mLastEnd); calcYValueCount(); + calcMinMax(0, mYValCount); calcXValAverageLength(); } @@ -181,13 +171,11 @@ private void checkLegal() { if (mDataSets == null) return; - if(this instanceof ScatterData) + if (this instanceof ScatterData) return; for (int i = 0; i < mDataSets.size(); i++) { - if (mDataSets.get(i) - .getYVals() - .size() > mXVals.size()) { + if (mDataSets.get(i).getEntryCount() > mXVals.size()) { throw new IllegalArgumentException( "One or more of the DataSet Entry arrays are longer than the x-values array of this ChartData object."); } @@ -213,16 +201,13 @@ public void calcMinMax(int start, int end) { mYMin = 0f; } else { - mLastStart = start; - mLastEnd = end; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; for (int i = 0; i < mDataSets.size(); i++) { IDataSet set = mDataSets.get(i); - set.calcMinMax(set.getYVals(), start, end); + set.calcMinMax(start, end); if (set.getYMin() < mYMin) mYMin = set.getYMin(); @@ -587,7 +572,7 @@ public boolean removeDataSet(T d) { mYValCount -= d.getEntryCount(); - calcMinMax(mLastStart, mLastEnd); + calcMinMax(0, mYValCount); } return removed; @@ -681,14 +666,14 @@ public boolean removeEntry(Entry e, int dataSetIndex) { IDataSet set = mDataSets.get(dataSetIndex); - if(set != null) { + if (set != null) { // remove the entry from the dataset boolean removed = set.removeEntry(e); if (removed) { mYValCount -= 1; - calcMinMax(mLastStart, mLastEnd); + calcMinMax(0, mYValCount); } return removed; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index ba0c84a7ea..9e36d43ee5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -55,16 +55,16 @@ public DataSet(List yVals, String label) { // default color mColors.add(Color.rgb(140, 234, 255)); - calcMinMax(mYVals, mLastStart, mLastEnd); + calcMinMax(0, mYVals.size()); } @Override - public void calcMinMax(List values, int start, int end) { + public void calcMinMax(int start, int end) { - if (values == null) + if (mYVals == null) return; - final int yValCount = values.size(); + final int yValCount = mYVals.size(); if (yValCount == 0) return; @@ -76,15 +76,12 @@ public void calcMinMax(List values, int start, int end) { else endValue = end; - mLastStart = start; - mLastEnd = endValue; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; for (int i = start; i <= endValue; i++) { - T e = values.get(i); + T e = mYVals.get(i); if (e != null && !Float.isNaN(e.getVal())) { @@ -271,7 +268,7 @@ public boolean removeFirst() { boolean removed = entry != null; if (removed) { - calcMinMax(mYVals, mLastStart, mLastEnd); + calcMinMax(0, mYVals.size()); } return removed; @@ -293,7 +290,7 @@ public boolean removeLast() { boolean removed = entry != null; if (removed) { - calcMinMax(mYVals, mLastStart, mLastEnd); + calcMinMax(0, mYVals.size()); } return removed; @@ -382,8 +379,6 @@ public void resetColors() { */ public void clear() { mYVals.clear(); - mLastStart = 0; - mLastEnd = 0; notifyDataSetChanged(); } @@ -420,16 +415,14 @@ public boolean removeEntry(T e) { if (e == null) return false; - List yVals = getYVals(); - - if (yVals == null) + if (mYVals == null) return false; // remove the entry - boolean removed = yVals.remove(e); + boolean removed = mYVals.remove(e); if (removed) { - calcMinMax(yVals, mLastStart, mLastEnd); + calcMinMax(0, mYVals.size()); } return removed; diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index c47c2cce99..2f063bf29f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -38,9 +38,12 @@ public interface IDataSet { int getEntryCount(); /** - * Calculates the minimum and maximum y value (mYMin, mYMax) + * Calculates the minimum and maximum y value (mYMin, mYMax). From the specified starting to ending index. + * + * @param start starting index in your data list + * @param end ending index in your data list */ - void calcMinMax(List values, int start, int end); + void calcMinMax(int start, int end); /** * Returns the first Entry object found at the given xIndex with binary diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java index 5bb4e432a0..6a1b2e518a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/CombinedChartRenderer.java @@ -1,8 +1,5 @@ package com.github.mikephil.charting.renderer; -import java.util.ArrayList; -import java.util.List; - import android.graphics.Canvas; import com.github.mikephil.charting.animation.ChartAnimator; @@ -12,126 +9,129 @@ import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.util.ArrayList; +import java.util.List; + /** * Renderer class that is responsible for rendering multiple different data-types. */ public class CombinedChartRenderer extends DataRenderer { - /** - * all rederers for the different kinds of data this combined-renderer can draw - */ - protected List mRenderers; - - public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { - super(animator, viewPortHandler); - - createRenderers(chart, animator, viewPortHandler); - } - - /** - * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into - * consideration. - * - * @param chart - * @param animator - * @param viewPortHandler - */ - protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { - - mRenderers = new ArrayList(); - - DrawOrder[] orders = chart.getDrawOrder(); - - for (DrawOrder order : orders) { - - switch (order) { - case BAR: - if (chart.getBarData() != null) - mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); - break; - case BUBBLE: - if (chart.getBubbleData() != null) - mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); - break; - case LINE: - if (chart.getLineData() != null) - mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); - break; - case CANDLE: - if (chart.getCandleData() != null) - mRenderers.add(new CandleStickChartRenderer(chart, animator, viewPortHandler)); - break; - case SCATTER: - if (chart.getScatterData() != null) - mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); - break; - } - } - } - - @Override - public void initBuffers() { - - for (DataRenderer renderer : mRenderers) - renderer.initBuffers(); - } - - @Override - public void drawData(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawData(c); - } - - @Override - public void drawValues(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawValues(c); - } - - @Override - public void drawExtras(Canvas c) { - - for (DataRenderer renderer : mRenderers) - renderer.drawExtras(c); - } - - @Override - public void drawHighlighted(Canvas c, Highlight[] indices) { - for (DataRenderer renderer : mRenderers) - renderer.drawHighlighted(c, indices); - } - - @Override - public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { - for (DataRenderer renderer : mRenderers) - renderer.calcXBounds(chart, xAxisModulus); - } - - /** - * Returns the sub-renderer object at the specified index. - * - * @param index - * @return - */ - public DataRenderer getSubRenderer(int index) { - if (index >= mRenderers.size() || index < 0) - return null; - else - return mRenderers.get(index); - } - - /** - * Returns all sub-renderers. - * - * @return - */ - public List getSubRenderers() { - return mRenderers; - } - - public void setSubRenderers(List renderers) { - this.mRenderers = renderers; - } + /** + * all rederers for the different kinds of data this combined-renderer can draw + */ + protected List mRenderers; + + public CombinedChartRenderer(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + + createRenderers(chart, animator, viewPortHandler); + } + + /** + * Creates the renderers needed for this combined-renderer in the required order. Also takes the DrawOrder into + * consideration. + * + * @param chart + * @param animator + * @param viewPortHandler + */ + protected void createRenderers(CombinedChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { + + mRenderers = new ArrayList(); + + DrawOrder[] orders = chart.getDrawOrder(); + + for (DrawOrder order : orders) { + + switch (order) { + case BAR: + if (chart.getBarData() != null) + mRenderers.add(new BarChartRenderer(chart, animator, viewPortHandler)); + break; + case BUBBLE: + if (chart.getBubbleData() != null) + mRenderers.add(new BubbleChartRenderer(chart, animator, viewPortHandler)); + break; + case LINE: + if (chart.getLineData() != null) + mRenderers.add(new LineChartRenderer(chart, animator, viewPortHandler)); + break; + case CANDLE: + if (chart.getCandleData() != null) + mRenderers.add(new CandleStickChartRenderer(chart, animator, viewPortHandler)); + break; + case SCATTER: + if (chart.getScatterData() != null) + mRenderers.add(new ScatterChartRenderer(chart, animator, viewPortHandler)); + break; + } + } + } + + @Override + public void initBuffers() { + + for (DataRenderer renderer : mRenderers) + renderer.initBuffers(); + } + + @Override + public void drawData(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawData(c); + } + + @Override + public void drawValues(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawValues(c); + } + + @Override + public void drawExtras(Canvas c) { + + for (DataRenderer renderer : mRenderers) + renderer.drawExtras(c); + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + for (DataRenderer renderer : mRenderers) + renderer.drawHighlighted(c, indices); + } + + @Override + public void calcXBounds(BarLineScatterCandleBubbleDataProvider chart, int xAxisModulus) { + for (DataRenderer renderer : mRenderers) + renderer.calcXBounds(chart, xAxisModulus); + } + + /** + * Returns the sub-renderer object at the specified index. + * + * @param index + * @return + */ + public DataRenderer getSubRenderer(int index) { + if (index >= mRenderers.size() || index < 0) + return null; + else + return mRenderers.get(index); + } + + /** + * Returns all sub-renderers. + * + * @return + */ + public List getSubRenderers() { + return mRenderers; + } + + public void setSubRenderers(List renderers) { + this.mRenderers = renderers; + } } From d1432aaa8bd9e240dc84ff46e737ad5a4c0dca03 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:48:07 +0100 Subject: [PATCH 0586/1390] Fix calcminmax --- .../mikephil/charting/charts/PieChart.java | 5 +- .../mikephil/charting/data/BarDataSet.java | 40 ++++++----- .../mikephil/charting/data/BubbleDataSet.java | 37 +++++------ .../mikephil/charting/data/CandleDataSet.java | 66 +++++++++++-------- .../mikephil/charting/data/PieData.java | 5 +- .../charting/data/realm/RealmLineDataSet.java | 11 +--- 6 files changed, 87 insertions(+), 77 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index b6098f8f0d..576876b364 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -206,11 +206,10 @@ private void calcAngles() { for (int i = 0; i < mData.getDataSetCount(); i++) { IPieDataSet set = dataSets.get(i); - List entries = set.getYVals(); - for (int j = 0; j < entries.size(); j++) { + for (int j = 0; j < set.getEntryCount(); j++) { - mDrawAngles[cnt] = calcAngle(Math.abs(entries.get(j).getVal())); + mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getVal())); if (cnt == 0) { mAbsoluteAngles[cnt] = mDrawAngles[cnt]; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java index d5f8b7dd00..fb1dccccf8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarDataSet.java @@ -10,7 +10,9 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet implements IBarDataSet { - /** space indicator between the bars 0.1f == 10 % */ + /** + * space indicator between the bars 0.1f == 10 % + */ private float mBarSpace = 0.15f; /** @@ -19,10 +21,14 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl */ private int mStackSize = 1; - /** the color used for drawing the bar shadows */ + /** + * the color used for drawing the bar shadows + */ private int mBarShadowColor = Color.rgb(215, 215, 215); - /** the alpha value used to draw the highlight indicator bar */ + /** + * the alpha value used to draw the highlight indicator bar + */ private int mHighLightAlpha = 120; /** @@ -33,7 +39,7 @@ public class BarDataSet extends BarLineScatterCandleBubbleDataSet impl /** * array of labels used to describe the different values of the stacked bars */ - private String[] mStackLabels = new String[] { + private String[] mStackLabels = new String[]{ "Stack" }; @@ -102,9 +108,12 @@ private void calcStackSize(List yVals) { } @Override - public void calcMinMax(List values, int start, int end) { + public void calcMinMax(int start, int end) { + + if (mYVals == null) + return; - final int yValCount = values.size(); + final int yValCount = mYVals.size(); if (yValCount == 0) return; @@ -116,19 +125,16 @@ public void calcMinMax(List values, int start, int end) { else endValue = end; - mLastStart = start; - mLastEnd = endValue; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; for (int i = start; i <= endValue; i++) { - BarEntry e = values.get(i); + BarEntry e = mYVals.get(i); if (e != null && !Float.isNaN(e.getVal())) { - if(e.getVals() == null) { + if (e.getVals() == null) { if (e.getVal() < mYMin) mYMin = e.getVal(); @@ -165,7 +171,7 @@ public boolean isStacked() { /** * returns the overall entry count, including counting each stack-value * individually - * + * * @return */ public int getEntryCountStacks() { @@ -174,7 +180,7 @@ public int getEntryCountStacks() { /** * returns the space between bars in percent of the whole width of one value - * + * * @return */ public float getBarSpacePercent() { @@ -188,7 +194,7 @@ public float getBarSpace() { /** * sets the space between the bars in percent (0-100) of the total bar width - * + * * @param percent */ public void setBarSpacePercent(float percent) { @@ -199,7 +205,7 @@ public void setBarSpacePercent(float percent) { * Sets the color used for drawing the bar-shadows. The bar shadows is a * surface behind the bar that indicates the maximum value. Don't for get to * use getResources().getColor(...) to set this. Or Color.rgb(...). - * + * * @param color */ public void setBarShadowColor(int color) { @@ -214,7 +220,7 @@ public int getBarShadowColor() { /** * Set the alpha value (transparency) that is used for drawing the highlight * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) - * + * * @param alpha */ public void setHighLightAlpha(int alpha) { @@ -228,7 +234,7 @@ public int getHighLightAlpha() { /** * Sets labels for different values of bar-stacks, in case there are one. - * + * * @param labels */ public void setStackLabels(String[] labels) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java index aea8fade57..df02438ef2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleDataSet.java @@ -35,6 +35,7 @@ public float getHighlightCircleWidth() { /** * Sets a color with a specific alpha value. + * * @param color * @param alpha from 0-255 */ @@ -43,59 +44,55 @@ public void setColor(int color, int alpha) { } @Override - public void calcMinMax(List values, int start, int end) { - if (values.size() == 0) + public void calcMinMax(int start, int end) { + + if (mYVals == null) + return; + + if (mYVals.size() == 0) return; int endValue; if (end == 0) - endValue = values.size() - 1; + endValue = mYVals.size() - 1; else endValue = end; - mLastStart = start; - mLastEnd = endValue; - - mYMin = yMin(values.get(start)); - mYMax = yMax(values.get(start)); + mYMin = yMin(mYVals.get(start)); + mYMax = yMax(mYVals.get(start)); // need chart width to guess this properly for (int i = start; i <= endValue; i++) { - final BubbleEntry entry = values.get(i); - + final BubbleEntry entry = mYVals.get(i); + final float ymin = yMin(entry); final float ymax = yMax(entry); - if (ymin < mYMin) - { + if (ymin < mYMin) { mYMin = ymin; } - if (ymax > mYMax) - { + if (ymax > mYMax) { mYMax = ymax; } final float xmin = xMin(entry); final float xmax = xMax(entry); - if (xmin < mXMin) - { + if (xmin < mXMin) { mXMin = xmin; } - if (xmax > mXMax) - { + if (xmax > mXMax) { mXMax = xmax; } final float size = largestSize(entry); - if (size > mMaxSize) - { + if (size > mMaxSize) { mMaxSize = size; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java index 6275ddd19d..176c4422aa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleDataSet.java @@ -12,30 +12,44 @@ /** * DataSet for the CandleStickChart. - * + * * @author Philipp Jahoda */ public class CandleDataSet extends LineScatterCandleRadarDataSet implements ICandleDataSet { - /** the width of the shadow of the candle */ + /** + * the width of the shadow of the candle + */ private float mShadowWidth = 3f; - /** the space between the candle entries, default 0.1f (10%) */ + /** + * the space between the candle entries, default 0.1f (10%) + */ private float mBodySpace = 0.1f; - /** use candle color for the shadow */ + /** + * use candle color for the shadow + */ private boolean mShadowColorSameAsCandle = false; - /** paint style when open <= close */ + /** + * paint style when open <= close + */ protected Paint.Style mIncreasingPaintStyle = Paint.Style.FILL; - /** paint style when open > close */ + /** + * paint style when open > close + */ protected Paint.Style mDecreasingPaintStyle = Paint.Style.STROKE; - /** color for open <= close */ + /** + * color for open <= close + */ protected int mIncreasingColor = ColorTemplate.COLOR_NONE; - /** color for open > close */ + /** + * color for open > close + */ protected int mDecreasingColor = ColorTemplate.COLOR_NONE; /** @@ -70,28 +84,28 @@ public DataSet copy() { } @Override - public void calcMinMax(List values, int start, int end) { + public void calcMinMax(int start, int end) { // super.calcMinMax(); - if (values.size() == 0) + if (mYVals == null) + return; + + if (mYVals.size() == 0) return; int endValue; - if (end == 0 || end >= values.size()) - endValue = values.size() - 1; + if (end == 0 || end >= mYVals.size()) + endValue = mYVals.size() - 1; else endValue = end; - mLastStart = start; - mLastEnd = endValue; - mYMin = Float.MAX_VALUE; mYMax = -Float.MAX_VALUE; for (int i = start; i <= endValue; i++) { - CandleEntry e = values.get(i); + CandleEntry e = mYVals.get(i); if (e.getLow() < mYMin) mYMin = e.getLow(); @@ -104,7 +118,7 @@ public void calcMinMax(List values, int start, int end) { /** * Sets the space that is left out on the left and right side of each * candle, default 0.1f (10%), max 0.45f, min 0f - * + * * @param space */ public void setBodySpace(float space) { @@ -142,7 +156,7 @@ public float getShadowWidth() { * colors list functionality, because It's wrong to copy paste setColor, * addColor, ... resetColors for each time when we want to add a coloring * options for one of objects - * + * * @author Mesrop */ @@ -150,29 +164,29 @@ public float getShadowWidth() { /** * Sets the one and ONLY color that should be used for this DataSet when - * open > close. + * open > close. * * @param color */ public void setDecreasingColor(int color) { mDecreasingColor = color; } - + @Override public int getDecreasingColor() { return mDecreasingColor; } - + /** * Sets the one and ONLY color that should be used for this DataSet when - * open <= close. + * open <= close. * * @param color */ public void setIncreasingColor(int color) { mIncreasingColor = color; } - + @Override public int getIncreasingColor() { return mIncreasingColor; @@ -185,7 +199,7 @@ public Paint.Style getDecreasingPaintStyle() { /** * Sets paint style when open > close - * + * * @param decreasingPaintStyle */ public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { @@ -199,7 +213,7 @@ public Paint.Style getIncreasingPaintStyle() { /** * Sets paint style when open <= close - * + * * @param paintStyle */ public void setIncreasingPaintStyle(Paint.Style paintStyle) { @@ -213,7 +227,7 @@ public int getShadowColor() { /** * Sets shadow color for all entries - * + * * @param shadowColor */ public void setShadowColor(int shadowColor) { diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index c2cf7fc7d3..06922829a9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -83,10 +83,9 @@ public float getYValueSum() { float sum = 0; - List values = getDataSet().getYVals(); + for (int i = 0; i < getDataSet().getEntryCount(); i++) + sum += getDataSet().getEntryForIndex(i).getVal(); - for (Entry e : values) - sum += e.getVal(); return sum; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 2fc8790e34..accfd4b248 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -32,14 +32,14 @@ public RealmLineDataSet(RealmResults result, String yValuesField, String xInd result.sort(xIndexField, true); - for(T object : result) { + for (T object : result) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); } - calcMinMax(mValues, mLastStart, mLastEnd); + calcMinMax(0, mValues.size()); } @Override @@ -142,11 +142,6 @@ public int getHighLightColor() { return 0; } - @Override - public List getYVals() { - return null; - } - @Override public float getYMin() { return 0; @@ -163,7 +158,7 @@ public int getEntryCount() { } @Override - public void calcMinMax(List values, int start, int end) { + public void calcMinMax(int start, int end) { } From 5b31e14a984d165aab327f8820f6bf5419fb5f3c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 18:50:31 +0100 Subject: [PATCH 0587/1390] Remove getYVals() method from Radar- & PieRenderer --- .../charting/renderer/PieChartRenderer.java | 16 +++++++--------- .../charting/renderer/RadarChartRenderer.java | 14 ++++---------- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 5fc2177acd..d0c71de0cd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -130,15 +130,14 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = mChart.getRotationAngle(); - List entries = dataSet.getYVals(); float[] drawAngles = mChart.getDrawAngles(); - for (int j = 0; j < entries.size(); j++) { + for (int j = 0; j < dataSet.getEntryCount(); j++) { float newangle = drawAngles[j]; float sliceSpace = dataSet.getSliceSpace(); - Entry e = entries.get(j); + Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero if ((Math.abs(e.getVal()) > 0.000001)) { @@ -196,12 +195,12 @@ public void drawValues(Canvas c) { float lineHeight = Utils.calcTextHeight(mValuePaint, "Q") + Utils.convertDpToPixel(4f); - List entries = dataSet.getYVals(); + int entryCount = dataSet.getEntryCount(); for (int j = 0, maxEntry = Math.min( - (int) Math.ceil(entries.size() * mAnimator.getPhaseX()), entries.size()); j < maxEntry; j++) { + (int) Math.ceil(entryCount * mAnimator.getPhaseX()), entryCount); j < maxEntry; j++) { - Entry entry = entries.get(j); + Entry entry = dataSet.getEntryForIndex(j); // offset needed to center the drawn text in the slice float offset = drawAngles[cnt] / 2; @@ -458,15 +457,14 @@ protected void drawRoundedSlices(Canvas c) { // calculate the radius of the "slice-circle" float circleRadius = (r - (r * mChart.getHoleRadius() / 100f)) / 2f; - List entries = dataSet.getYVals(); float[] drawAngles = mChart.getDrawAngles(); float angle = mChart.getRotationAngle(); - for (int j = 0; j < entries.size(); j++) { + for (int j = 0; j < dataSet.getEntryCount(); j++) { float newangle = drawAngles[j]; - Entry e = entries.get(j); + Entry e = dataSet.getEntryForIndex(j); // draw only if the value is greater than zero if ((Math.abs(e.getVal()) > 0.000001)) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 0252051f86..5a9d13dcb9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -16,8 +16,6 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.util.List; - public class RadarChartRenderer extends LineScatterCandleRadarRenderer { protected RadarChart mChart; @@ -73,17 +71,15 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { PointF center = mChart.getCenterOffsets(); - List entries = dataSet.getYVals(); - Path surface = new Path(); boolean hasMovedToPoint = false; - for (int j = 0; j < entries.size(); j++) { + for (int j = 0; j < dataSet.getEntryCount(); j++) { mRenderPaint.setColor(dataSet.getColor(j)); - Entry e = entries.get(j); + Entry e = dataSet.getEntryForIndex(j); PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); @@ -139,11 +135,9 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); - List entries = dataSet.getYVals(); - - for (int j = 0; j < entries.size(); j++) { + for (int j = 0; j < dataSet.getEntryCount(); j++) { - Entry entry = entries.get(j); + Entry entry = dataSet.getEntryForIndex(j); PointF p = Utils.getPosition(center, (entry.getVal() - mChart.getYChartMin()) * factor, sliceangle * j + mChart.getRotationAngle()); From b2f4e26e67997786e145b62cb991685b5504af4f Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 4 Nov 2015 19:04:03 +0100 Subject: [PATCH 0588/1390] Change default minoffset to 15 (instead of 10) --- .../github/mikephil/charting/charts/BarLineChartBase.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index a528c282f1..a9f8039c25 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -103,9 +103,9 @@ public abstract class BarLineChartBase Date: Wed, 4 Nov 2015 13:04:11 -0700 Subject: [PATCH 0589/1390] Added ability to set image format and subdirectory when saving to gallery --- .../mikephil/charting/charts/Chart.java | 61 ++++++++++++++----- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index f79aa065d4..aebe81166a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1532,16 +1532,18 @@ public boolean saveToPath(String title, String pathOnSD) { } /** - * Saves the current state of the chart to the gallery as a JPEG image. The - * filename and compression can be set. 0 == maximum compression, 100 = low + * Saves the current state of the chart to the gallery as an image type. The + * compression must be set for JPEG only. 0 == maximum compression, 100 = low * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE * * @param fileName e.g. "my_image" - * @param quality e.g. 50, min = 0, max = 100 - * @return returns true if saving was successfull, false if not + * @param subFolderPath e.g. "ChartPics" + * @param fileDescription e.g. "Chart details" + * @param format e.g. Bitmap.CompressFormat.PNG + * @param quality e.g. 50, min = 0, max = 100 + * @return returns true if saving was successful, false if not */ - public boolean saveToGallery(String fileName, int quality) { - + public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat format, int quality) { // restrain quality if (quality < 0 || quality > 100) quality = 50; @@ -1549,23 +1551,40 @@ public boolean saveToGallery(String fileName, int quality) { long currentTime = System.currentTimeMillis(); File extBaseDir = Environment.getExternalStorageDirectory(); - File file = new File(extBaseDir.getAbsolutePath() + "/DCIM"); + File file = new File(extBaseDir.getAbsolutePath() + "/DCIM/" + subFolderPath); if (!file.exists()) { if (!file.mkdirs()) { return false; } } + String mimeType = ""; + switch (format) { + case PNG: + mimeType = "image/png"; + if (!fileName.endsWith(".png")) + fileName += ".png"; + break; + case WEBP: + mimeType = "image/webp"; + if (!fileName.endsWith(".webp")) + fileName += ".webp"; + break; + case JPEG: + default: + mimeType = "image/jpeg"; + if (!(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg"))) + fileName += ".jpg"; + break; + } + String filePath = file.getAbsolutePath() + "/" + fileName; FileOutputStream out = null; try { out = new FileOutputStream(filePath); Bitmap b = getChartBitmap(); - - b.compress(Bitmap.CompressFormat.JPEG, quality, out); // control - // the jpeg - // quality + b.compress(format, quality, out); out.flush(); out.close(); @@ -1584,14 +1603,26 @@ public boolean saveToGallery(String fileName, int quality) { values.put(Images.Media.TITLE, fileName); values.put(Images.Media.DISPLAY_NAME, fileName); values.put(Images.Media.DATE_ADDED, currentTime); - values.put(Images.Media.MIME_TYPE, "image/jpeg"); - values.put(Images.Media.DESCRIPTION, "MPAndroidChart-Library Save"); + values.put(Images.Media.MIME_TYPE, mimeType); + values.put(Images.Media.DESCRIPTION, fileDescription); values.put(Images.Media.ORIENTATION, 0); values.put(Images.Media.DATA, filePath); values.put(Images.Media.SIZE, size); - return getContext().getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values) == null - ? false : true; + return getContext().getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values) != null; + } + + /** + * Saves the current state of the chart to the gallery as a JPEG image. The + * filename and compression can be set. 0 == maximum compression, 100 = low + * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE + * + * @param fileName e.g. "my_image" + * @param quality e.g. 50, min = 0, max = 100 + * @return returns true if saving was successful, false if not + */ + public boolean saveToGallery(String fileName, int quality) { + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.JPEG, quality); } /** From b495a7d9ebc278addb2a81695825f1b06202f36a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 5 Nov 2015 10:52:33 +0100 Subject: [PATCH 0590/1390] Fix #1168 --- .../github/mikephil/charting/highlight/BarHighlighter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java index a85f488681..7d001dfe25 100644 --- a/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java +++ b/MPChartLib/src/com/github/mikephil/charting/highlight/BarHighlighter.java @@ -119,7 +119,7 @@ protected Highlight getStackedHighlight(Highlight old, BarDataSet set, int xInde */ protected int getClosestStackIndex(Range[] ranges, float value) { - if (ranges == null) + if (ranges == null || ranges.length == 0) return 0; int stackIndex = 0; @@ -188,7 +188,7 @@ protected Range[] getRanges(BarEntry entry) { float[] values = entry.getVals(); - if (values == null) + if (values == null || values.length == 0) return null; float negRemain = -entry.getNegativeSum(); From 5bc50bd780cd9ca2b4f79229a4f0b3296866a3ed Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 6 Nov 2015 18:37:58 +0100 Subject: [PATCH 0591/1390] Work on realm datasets --- .../mpchartexample/RealmDatabaseActivity.java | 57 ++++--------------- .../mpchartexample/custom/RealmDemoData.java | 14 ++++- .../notimportant/RealmBaseActivity.java | 50 ++++++++++++++++ .../mikephil/charting/data/BaseDataSet.java | 5 ++ .../mikephil/charting/data/DataSet.java | 5 -- .../mikephil/charting/data/LineData.java | 21 +++++++ .../charting/data/realm/RealmLineDataSet.java | 42 ++++++++------ 7 files changed, 125 insertions(+), 69 deletions(-) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index ca7dfaef82..4b777eb2db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -12,6 +12,7 @@ import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; +import com.xxmassdeveloper.mpchartexample.notimportant.RealmBaseActivity; import java.util.ArrayList; @@ -22,7 +23,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmDatabaseActivity extends DemoBase { +public class RealmDatabaseActivity extends RealmBaseActivity { private LineChart mChart; @@ -62,55 +63,22 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getXAxis().setTypeface(tf); mChart.getAxisRight().setEnabled(false); - - // write some demo-data into the realm.io database - writeToDB(400); - - // add data - setData(); - - mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); } - private void writeToDB(int objectCount) { - - RealmConfiguration config = new RealmConfiguration.Builder(this) - .name("myrealm.realm") - .build(); - - Realm.deleteRealm(config); - - Realm.setDefaultConfiguration(config); - - Realm realm = Realm.getInstance(config); - - realm.beginTransaction(); - - realm.clear(RealmDemoData.class); - - for(int i = 0; i < objectCount; i++) { + @Override + protected void onResume() { + super.onResume(); // setup realm - RealmDemoData d = new RealmDemoData(30f + (float) (Math.random() * 100.0), i); - realm.copyToRealm(d); - } + // write some demo-data into the realm.io database + writeToDB(200); - realm.commitTransaction(); - realm.close(); + // add data to the chart + setData(); } private void setData() { - RealmConfiguration config = new RealmConfiguration.Builder(this) - .name("myrealm.realm") - .build(); - - Realm realm = Realm.getInstance(config); - RealmResults result = realm.allObjects(RealmDemoData.class); - - ArrayList xVals = new ArrayList(); - for (int i = 0; i < result.size(); i++) { - xVals.add((i) + ""); - } + RealmResults result = mRealm.allObjects(RealmDemoData.class); RealmLineDataSet set = new RealmLineDataSet(result, "value", "xIndex"); set.setValueTextSize(9f); @@ -119,11 +87,10 @@ private void setData() { dataSets.add(set); // add the dataset // create a data object with the dataset list - LineData data = new LineData(xVals, dataSets); + LineData data = new LineData(result, "xValue", dataSets); // set data mChart.setData(data); - - realm.close(); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); } } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index 9673c298c8..ae8959c3c1 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -2,13 +2,14 @@ import io.realm.RealmObject; -import io.realm.annotations.Ignore; public class RealmDemoData extends RealmObject { private float value; private int xIndex; + private String xValue; + private String someStringField; // ofc there could me more fields here... @@ -17,9 +18,10 @@ public RealmDemoData() { } - public RealmDemoData(float value, int xIndex) { + public RealmDemoData(float value, int xIndex, String xValue) { this.value = value; this.xIndex = xIndex; + this.xValue = xValue; } public float getValue() { @@ -38,6 +40,14 @@ public void setxIndex(int xIndex) { this.xIndex = xIndex; } + public String getxValue() { + return xValue; + } + + public void setxValue(String xValue) { + this.xValue = xValue; + } + public String getSomeStringField() { return someStringField; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java new file mode 100644 index 0000000000..edbbf3a5cd --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java @@ -0,0 +1,50 @@ +package com.xxmassdeveloper.mpchartexample.notimportant; + +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; + +import io.realm.Realm; +import io.realm.RealmConfiguration; + +/** + * Created by Philipp Jahoda on 05/11/15. + */ +public abstract class RealmBaseActivity extends DemoBase { + + protected Realm mRealm; + + @Override + protected void onResume() { + super.onResume(); + + RealmConfiguration config = new RealmConfiguration.Builder(this) + .name("myrealm.realm") + .build(); + + Realm.deleteRealm(config); + + Realm.setDefaultConfiguration(config); + + mRealm = Realm.getInstance(config); + } + + @Override + protected void onPause() { + super.onPause(); + mRealm.close(); + } + + protected void writeToDB(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.clear(RealmDemoData.class); + + for(int i = 0; i < objectCount; i++) { + + RealmDemoData d = new RealmDemoData(30f + (float) (Math.random() * 100.0), i, "" + i); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 3b79383e5d..6015c86631 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -9,6 +9,7 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet; import com.github.mikephil.charting.utils.Utils; +import java.util.ArrayList; import java.util.List; /** @@ -82,7 +83,10 @@ public abstract class BaseDataSet implements IDataSet { * Default constructor. */ public BaseDataSet() { + mColors = new ArrayList<>(); + // default color + mColors.add(Color.rgb(140, 234, 255)); } /** @@ -91,6 +95,7 @@ public BaseDataSet() { * @param label */ public BaseDataSet(String label) { + this(); this.mLabel = label; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 9e36d43ee5..a813657efc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -50,11 +50,6 @@ public DataSet(List yVals, String label) { if (mYVals == null) mYVals = new ArrayList(); - mColors = new ArrayList(); - - // default color - mColors.add(Color.rgb(140, 234, 255)); - calcMinMax(0, mYVals.size()); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 9adb07b60d..3885dc2e5a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -6,6 +6,10 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** * Data object that encapsulates all data associated with a LineChart. * @@ -13,6 +17,10 @@ */ public class LineData extends BarLineScatterCandleBubbleData { + public LineData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public LineData() { super(); } @@ -46,4 +54,17 @@ private static List toList(ILineDataSet dataSet) { sets.add(dataSet); return sets; } + + private static List toXVals(RealmResults result, String xValuesField) { + + List xVals = new ArrayList<>(); + + for (RealmObject object : result) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + xVals.add(dynamicObject.getString(xValuesField)); + } + + return xVals; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index accfd4b248..cca6b3af24 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -21,18 +21,23 @@ */ public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { - private List mColors = new ArrayList<>(); private List mValues = new ArrayList<>(); private FillFormatter mFillFormatter = new DefaultFillFormatter(); + private RealmResults results; + private String yValuesField; + private String xIndexField; + public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { super(""); - mColors.add(Color.BLACK); + this.results = result; + this.yValuesField = yValuesField; + this.xIndexField = xIndexField; - result.sort(xIndexField, true); + results.sort(xIndexField, true); - for (T object : result) { + for (T object : results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); @@ -42,6 +47,7 @@ public RealmLineDataSet(RealmResults result, String yValuesField, String xInd calcMinMax(0, mValues.size()); } + @Override public float getCubicIntensity() { return 0; @@ -54,22 +60,22 @@ public boolean isDrawCubicEnabled() { @Override public float getCircleSize() { - return 0; + return 10; } @Override public int getCircleColor(int index) { - return 0; + return Color.BLACK; } @Override public boolean isDrawCirclesEnabled() { - return false; + return true; } @Override public int getCircleHoleColor() { - return 0; + return Color.BLACK; } @Override @@ -89,7 +95,7 @@ public boolean isDashedLineEnabled() { @Override public FillFormatter getFillFormatter() { - return null; + return mFillFormatter; } @Override @@ -104,7 +110,7 @@ public int getFillAlpha() { @Override public float getLineWidth() { - return 0; + return 5; } @Override @@ -144,17 +150,17 @@ public int getHighLightColor() { @Override public float getYMin() { - return 0; + return results.min(yValuesField).floatValue(); } @Override public float getYMax() { - return 0; + return results.max(yValuesField).floatValue(); } @Override public int getEntryCount() { - return 0; + return results.size(); } @Override @@ -164,12 +170,14 @@ public void calcMinMax(int start, int end) { @Override public Entry getEntryForXIndex(int xIndex) { - return null; + + DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); + return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); } @Override public Entry getEntryForIndex(int index) { - return null; + return mValues.get(index); } @Override @@ -179,12 +187,12 @@ public int getEntryIndex(int xIndex) { @Override public int getEntryIndex(Entry e) { - return 0; + return mValues.indexOf(e); } @Override public float getYValForXIndex(int xIndex) { - return 0; + return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); } @Override From 5aab431cff2ce9352d7dfe4296ba4155424d0560 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 6 Nov 2015 18:53:38 +0100 Subject: [PATCH 0592/1390] Impleme3nt RealmBaseDataSet --- .../charting/data/realm/RealmBaseDataSet.java | 89 +++++++++++++++++++ .../charting/data/realm/RealmLineDataSet.java | 88 ++---------------- 2 files changed, 94 insertions(+), 83 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java new file mode 100644 index 0000000000..fda4f25641 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -0,0 +1,89 @@ +package com.github.mikephil.charting.data.realm; + +import com.github.mikephil.charting.data.BaseDataSet; +import com.github.mikephil.charting.data.Entry; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + +/** + * Created by Philipp Jahoda on 06/11/15. + */ +public abstract class RealmBaseDataSet extends BaseDataSet { + + private RealmResults results; + private String yValuesField; + private String xIndexField; + + public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { + this.results = results; + this.yValuesField = yValuesField; + this.xIndexField = xIndexField; + + this.results.sort(xIndexField, true); + + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + //mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + } + } + + @Override + public float getYMin() { + return results.min(yValuesField).floatValue(); + } + + @Override + public float getYMax() { + return results.max(yValuesField).floatValue(); + } + + @Override + public int getEntryCount() { + return results.size(); + } + + @Override + public void calcMinMax(int start, int end) { + + } + + @Override + public Entry getEntryForXIndex(int xIndex) { + + DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); + return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + } + + @Override + public Entry getEntryForIndex(int index) { + return null; + } + + @Override + public int getEntryIndex(int xIndex) { + return 0; + } + + @Override + public int getEntryIndex(Entry e) { + return 0; + } + + @Override + public float getYValForXIndex(int xIndex) { + return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); + } + + @Override + public void addEntry(Entry e) { + + } + + @Override + public boolean removeEntry(Entry e) { + return false; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index cca6b3af24..d3259af425 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -3,7 +3,6 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -14,43 +13,23 @@ import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends BaseDataSet implements ILineDataSet { +public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { private List mValues = new ArrayList<>(); private FillFormatter mFillFormatter = new DefaultFillFormatter(); - private RealmResults results; - private String yValuesField; - private String xIndexField; - public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { - super(""); - this.results = result; - this.yValuesField = yValuesField; - this.xIndexField = xIndexField; - - results.sort(xIndexField, true); - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - - mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); - } - - calcMinMax(0, mValues.size()); + super(result, yValuesField, xIndexField); } - @Override public float getCubicIntensity() { - return 0; + return 0.2f; } @Override @@ -70,12 +49,12 @@ public int getCircleColor(int index) { @Override public boolean isDrawCirclesEnabled() { - return true; + return false; } @Override public int getCircleHoleColor() { - return Color.BLACK; + return 0; } @Override @@ -147,61 +126,4 @@ public DashPathEffect getDashPathEffectHighlight() { public int getHighLightColor() { return 0; } - - @Override - public float getYMin() { - return results.min(yValuesField).floatValue(); - } - - @Override - public float getYMax() { - return results.max(yValuesField).floatValue(); - } - - @Override - public int getEntryCount() { - return results.size(); - } - - @Override - public void calcMinMax(int start, int end) { - - } - - @Override - public Entry getEntryForXIndex(int xIndex) { - - DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); - return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); - } - - @Override - public Entry getEntryForIndex(int index) { - return mValues.get(index); - } - - @Override - public int getEntryIndex(int xIndex) { - return 0; - } - - @Override - public int getEntryIndex(Entry e) { - return mValues.indexOf(e); - } - - @Override - public float getYValForXIndex(int xIndex) { - return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); - } - - @Override - public void addEntry(Entry e) { - - } - - @Override - public boolean removeEntry(Entry e) { - return false; - } } From 5ca17914f0833ad1505d38c5be1a3446faaa937e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Nov 2015 22:56:23 +0100 Subject: [PATCH 0593/1390] Implement 1st version of RealmLineDataSet --- .../mpchartexample/RealmDatabaseActivity.java | 1 + .../mikephil/charting/data/BaseDataSet.java | 23 +----- .../mikephil/charting/data/DataSet.java | 15 ++-- .../charting/data/realm/RealmBarDataSet.java | 7 ++ .../charting/data/realm/RealmBaseDataSet.java | 75 +++++++++++++++---- .../data/realm/RealmBubbleDataSet.java | 7 ++ .../data/realm/RealmCandleDataSet.java | 7 ++ .../charting/data/realm/RealmLineDataSet.java | 6 +- .../charting/data/realm/RealmPieDataSet.java | 7 ++ .../data/realm/RealmRadarDataSet.java | 7 ++ .../data/realm/RealmScatterDataSet.java | 7 ++ .../interfaces/datasets/IDataSet.java | 15 ++++ 12 files changed, 132 insertions(+), 45 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index 4b777eb2db..ec67827cd7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -7,6 +7,7 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.RealmLineDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 6015c86631..14954b8f3c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -34,16 +34,6 @@ public abstract class BaseDataSet implements IDataSet { */ protected YAxis.AxisDependency mAxisDependency = YAxis.AxisDependency.LEFT; -// /** -// * the last start value used for calcMinMax -// */ -// protected int mLastStart = 0; -// -// /** -// * the last end value used for calcMinMax -// */ -// protected int mLastEnd = 0; - /** * if true, value highlightning is enabled */ @@ -128,11 +118,7 @@ public int getColor(int index) { /** ###### ###### OTHER STYLING RELATED METHODS ##### ###### */ - /** - * Sets the label string that describes the DataSet. - * - * @return - */ + @Override public void setLabel(String label) { mLabel = label; } @@ -223,12 +209,7 @@ public YAxis.AxisDependency getAxisDependency() { return mAxisDependency; } - /** - * Set the y-axis this DataSet should be plotted against (either LEFT or - * RIGHT). Default: LEFT - * - * @param dependency - */ + @Override public void setAxisDependency(YAxis.AxisDependency dependency) { mAxisDependency = dependency; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index a813657efc..a7d11fcd28 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -457,13 +457,14 @@ public boolean contains(Entry e) { @Override public int getEntryIndex(Entry e) { - - for (int i = 0; i < mYVals.size(); i++) { - if (e.equalTo(mYVals.get(i))) - return i; - } - - return -1; + return mYVals.indexOf(e); +// +// for (int i = 0; i < mYVals.size(); i++) { +// if (e.equalTo(mYVals.get(i))) +// return i; +// } +// +// return -1; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java new file mode 100644 index 0000000000..0f1e1ddeea --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmBarDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java index fda4f25641..c5d3f8ed47 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -3,6 +3,9 @@ import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.Entry; +import java.util.ArrayList; +import java.util.List; + import io.realm.RealmObject; import io.realm.RealmResults; import io.realm.dynamic.DynamicRealmObject; @@ -12,37 +15,39 @@ */ public abstract class RealmBaseDataSet extends BaseDataSet { - private RealmResults results; + protected List mValues; private String yValuesField; private String xIndexField; public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { - this.results = results; this.yValuesField = yValuesField; this.xIndexField = xIndexField; + mValues = new ArrayList(); - this.results.sort(xIndexField, true); + results.sort(xIndexField, true); for (T object : results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - //mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); } } @Override public float getYMin() { - return results.min(yValuesField).floatValue(); + //return results.min(yValuesField).floatValue(); + return -50; } @Override public float getYMax() { - return results.max(yValuesField).floatValue(); + //return results.max(yValuesField).floatValue(); + return 200; } @Override public int getEntryCount() { - return results.size(); + return mValues.size(); } @Override @@ -52,29 +57,63 @@ public void calcMinMax(int start, int end) { @Override public Entry getEntryForXIndex(int xIndex) { - - DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); - return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); + //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + int index = getEntryIndex(xIndex); + if (index > -1) + return mValues.get(index); + return null; } @Override public Entry getEntryForIndex(int index) { - return null; + //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); + //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + return mValues.get(index); } @Override public int getEntryIndex(int xIndex) { - return 0; + + int low = 0; + int high = mValues.size() - 1; + int closest = -1; + + while (low <= high) { + int m = (high + low) / 2; + + if (xIndex == mValues.get(m).getXIndex()) { + while (m > 0 && mValues.get(m - 1).getXIndex() == xIndex) + m--; + + return m; + } + + if (xIndex > mValues.get(m).getXIndex()) + low = m + 1; + else + high = m - 1; + + closest = m; + } + + return closest; } @Override public int getEntryIndex(Entry e) { - return 0; + return mValues.indexOf(e); } @Override public float getYValForXIndex(int xIndex) { - return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); + //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); + Entry e = getEntryForXIndex(xIndex); + + if (e != null && e.getXIndex() == xIndex) + return e.getVal(); + else + return Float.NaN; } @Override @@ -86,4 +125,12 @@ public void addEntry(Entry e) { public boolean removeEntry(Entry e) { return false; } + + public String getValuesField() { + return yValuesField; + } + + public String getIndexField() { + return xIndexField; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java new file mode 100644 index 0000000000..8b030d4f28 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmBubbleDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java new file mode 100644 index 0000000000..a245082c5a --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmCandleDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index d3259af425..3695fac8eb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -3,6 +3,7 @@ import android.graphics.Color; import android.graphics.DashPathEffect; +import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -13,13 +14,12 @@ import io.realm.RealmObject; import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { - - private List mValues = new ArrayList<>(); +public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { private FillFormatter mFillFormatter = new DefaultFillFormatter(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java new file mode 100644 index 0000000000..6f8c2b30ae --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmPieDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java new file mode 100644 index 0000000000..b1ca419338 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmRadarDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java new file mode 100644 index 0000000000..f0ef8ed51b --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java @@ -0,0 +1,7 @@ +package com.github.mikephil.charting.data.realm; + +/** + * Created by philipp on 07/11/15. + */ +public class RealmScatterDataSet { +} diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 2f063bf29f..11e5fb0375 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -127,6 +127,13 @@ public interface IDataSet { */ String getLabel(); + /** + * Sets the label string that describes the DataSet. + * + * @param label + */ + void setLabel(String label); + /** * Returns the axis this DataSet should be plotted against. * @@ -134,6 +141,14 @@ public interface IDataSet { */ YAxis.AxisDependency getAxisDependency(); + /** + * Set the y-axis this DataSet should be plotted against (either LEFT or + * RIGHT). Default: LEFT + * + * @param dependency + */ + void setAxisDependency(YAxis.AxisDependency dependency); + /** * returns all the colors that are set for this DataSet * From 9399db9ec77560669dc598379fd88a2b0014ad8e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Nov 2015 23:00:25 +0100 Subject: [PATCH 0594/1390] Change void addEntry(...) to boolean addEntry(...) --- .../src/com/github/mikephil/charting/data/ChartData.java | 8 +++++--- .../src/com/github/mikephil/charting/data/DataSet.java | 5 +++-- .../mikephil/charting/data/realm/RealmBaseDataSet.java | 4 ++-- .../mikephil/charting/interfaces/datasets/IDataSet.java | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 0d020adb35..a25d4eea0e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -605,8 +605,12 @@ public void addEntry(Entry e, int dataSetIndex) { if (mDataSets.size() > dataSetIndex && dataSetIndex >= 0) { - float val = e.getVal(); IDataSet set = mDataSets.get(dataSetIndex); + // add the entry to the dataset + if(!set.addEntry(e)) + return; + + float val = e.getVal(); if (mYValCount == 0) { mYMin = val; @@ -645,8 +649,6 @@ public void addEntry(Entry e, int dataSetIndex) { handleEmptyAxis(getFirstLeft(), getFirstRight()); - // add the entry to the dataset - set.addEntry(e); } else { Log.e("addEntry", "Cannot add Entry because dataSetIndex too high or too low."); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index a7d11fcd28..d4f4dbd110 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -378,10 +378,10 @@ public void clear() { } @Override - public void addEntry(T e) { + public boolean addEntry(T e) { if (e == null) - return; + return false; float val = e.getVal(); @@ -402,6 +402,7 @@ public void addEntry(T e) { // add the entry yVals.add(e); + return true; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java index c5d3f8ed47..d077e89003 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -117,8 +117,8 @@ public float getYValForXIndex(int xIndex) { } @Override - public void addEntry(Entry e) { - + public boolean addEntry(Entry e) { + return false; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 11e5fb0375..088942cff8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -105,7 +105,7 @@ public interface IDataSet { * * @param e */ - void addEntry(T e); + boolean addEntry(T e); /** * Removes an Entry from the DataSets entries array. This will also From 29fdf185cf31e3a1ff88f298c00ff0d66ca1cef6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Nov 2015 23:15:22 +0100 Subject: [PATCH 0595/1390] Implement 1st version of RealmBarDataSet --- .../charting/data/realm/RealmBarDataSet.java | 58 ++++++++++++++++++- .../charting/data/realm/RealmBaseDataSet.java | 40 +++++++------ .../charting/data/realm/RealmLineDataSet.java | 8 ++- 3 files changed, 86 insertions(+), 20 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java index 0f1e1ddeea..911813ca42 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java @@ -1,7 +1,61 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.Color; + +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmBarDataSet { +public class RealmBarDataSet extends RealmBaseDataSet implements IBarDataSet { + + public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { + super(results, yValuesField, xIndexField); + + for (T object : this.results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new BarEntry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + } + } + + @Override + public float getBarSpace() { + return 0; + } + + @Override + public boolean isStacked() { + return false; + } + + @Override + public int getStackSize() { + return 0; + } + + @Override + public int getBarShadowColor() { + return Color.BLACK; + } + + @Override + public int getHighLightAlpha() { + return 0; + } + + @Override + public String[] getStackLabels() { + return new String[0]; + } + + @Override + public int getHighLightColor() { + return 0; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java index d077e89003..e02514888d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -8,29 +8,35 @@ import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 06/11/15. */ -public abstract class RealmBaseDataSet extends BaseDataSet { +public abstract class RealmBaseDataSet extends BaseDataSet { + + /** + * a list of queried realm objects + */ + protected RealmResults results; + + protected List mValues; - protected List mValues; private String yValuesField; private String xIndexField; + /** + * Constructor that takes the realm RealmResults, sorts & stores them. + * + * @param results + * @param yValuesField + * @param xIndexField + */ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { + this.results = results; this.yValuesField = yValuesField; this.xIndexField = xIndexField; - mValues = new ArrayList(); - - results.sort(xIndexField, true); - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); - } + mValues = new ArrayList(); + this.results.sort(xIndexField, true); } @Override @@ -56,7 +62,7 @@ public void calcMinMax(int start, int end) { } @Override - public Entry getEntryForXIndex(int xIndex) { + public S getEntryForXIndex(int xIndex) { //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); int index = getEntryIndex(xIndex); @@ -66,7 +72,7 @@ public Entry getEntryForXIndex(int xIndex) { } @Override - public Entry getEntryForIndex(int index) { + public S getEntryForIndex(int index) { //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); return mValues.get(index); @@ -101,7 +107,7 @@ public int getEntryIndex(int xIndex) { } @Override - public int getEntryIndex(Entry e) { + public int getEntryIndex(S e) { return mValues.indexOf(e); } @@ -117,12 +123,12 @@ public float getYValForXIndex(int xIndex) { } @Override - public boolean addEntry(Entry e) { + public boolean addEntry(S e) { return false; } @Override - public boolean removeEntry(Entry e) { + public boolean removeEntry(S e) { return false; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 3695fac8eb..1c33825453 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -19,12 +19,18 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { +public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { private FillFormatter mFillFormatter = new DefaultFillFormatter(); public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); + + for (T object : this.results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + } } @Override From 0c729ac64c28e4e6801ac92065621733d431ab6a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Nov 2015 23:18:04 +0100 Subject: [PATCH 0596/1390] Add realm x-values support for BarData --- .../github/mikephil/charting/data/BarData.java | 8 ++++++++ .../mikephil/charting/data/ChartData.java | 17 +++++++++++++++++ .../github/mikephil/charting/data/LineData.java | 14 -------------- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java index 43b6e88e86..01db783ba6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarData.java @@ -2,10 +2,14 @@ package com.github.mikephil.charting.data; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + /** * Data object that represents all data for the BarChart. * @@ -21,6 +25,10 @@ public class BarData extends BarLineScatterCandleBubbleData { // */ // private float mMaximumBarWidth = 100f; + public BarData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public BarData() { super(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index a25d4eea0e..4c973208e0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -13,6 +13,10 @@ import java.util.Arrays; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** * Class that holds all relevant data that represents the chart. That involves * at least one (or more) DataSets, and an array of x-values. @@ -951,4 +955,17 @@ public boolean contains(T dataSet) { return false; } + + protected static List toXVals(RealmResults result, String xValuesField) { + + List xVals = new ArrayList<>(); + + for (RealmObject object : result) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + xVals.add(dynamicObject.getString(xValuesField)); + } + + return xVals; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java index 3885dc2e5a..9cc964fd2f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineData.java @@ -8,7 +8,6 @@ import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Data object that encapsulates all data associated with a LineChart. @@ -54,17 +53,4 @@ private static List toList(ILineDataSet dataSet) { sets.add(dataSet); return sets; } - - private static List toXVals(RealmResults result, String xValuesField) { - - List xVals = new ArrayList<>(); - - for (RealmObject object : result) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - xVals.add(dynamicObject.getString(xValuesField)); - } - - return xVals; - } } From faa02b87eaf3108482a31c1f6c37a92c9f64216c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 7 Nov 2015 23:25:38 +0100 Subject: [PATCH 0597/1390] Test RealmBarDataSet, fix stack-size issue --- .../mpchartexample/RealmDatabaseActivity.java | 16 ++++++++++------ .../github/mikephil/charting/data/ChartData.java | 9 ++++++++- .../charting/data/realm/RealmBarDataSet.java | 2 +- .../interfaces/datasets/IBarDataSet.java | 2 +- .../charting/renderer/BarChartRenderer.java | 2 +- .../renderer/HorizontalBarChartRenderer.java | 2 +- 6 files changed, 22 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index ec67827cd7..ed7df429f9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -5,11 +5,15 @@ import android.view.WindowManager; import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.RealmBarDataSet; import com.github.mikephil.charting.data.realm.RealmLineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; @@ -26,16 +30,16 @@ */ public class RealmDatabaseActivity extends RealmBaseActivity { - private LineChart mChart; + private BarChart mChart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_linechart_noseekbar); + setContentView(R.layout.activity_barchart); - mChart = (LineChart) findViewById(R.id.chart1); + mChart = (BarChart) findViewById(R.id.chart1); mChart.setDrawGridBackground(false); // no description text @@ -81,14 +85,14 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmLineDataSet set = new RealmLineDataSet(result, "value", "xIndex"); + RealmBarDataSet set = new RealmBarDataSet(result, "value", "xIndex"); set.setValueTextSize(9f); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset // create a data object with the dataset list - LineData data = new LineData(result, "xValue", dataSets); + BarData data = new BarData(result, "xValue", dataSets); // set data mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 4c973208e0..fc47d1253d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -611,7 +611,7 @@ public void addEntry(Entry e, int dataSetIndex) { IDataSet set = mDataSets.get(dataSetIndex); // add the entry to the dataset - if(!set.addEntry(e)) + if (!set.addEntry(e)) return; float val = e.getVal(); @@ -956,6 +956,13 @@ public boolean contains(T dataSet) { return false; } + /** + * Transforms the given Realm-ResultSet into a String array by using the provided xValuesField. + * + * @param result + * @param xValuesField + * @return + */ protected static List toXVals(RealmResults result, String xValuesField) { List xVals = new ArrayList<>(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java index 911813ca42..cf8b6122db 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java @@ -51,7 +51,7 @@ public int getHighLightAlpha() { @Override public String[] getStackLabels() { - return new String[0]; + return null; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java index 47801c0881..bc3bb9b3ea 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IBarDataSet.java @@ -23,7 +23,7 @@ public interface IBarDataSet extends IBarLineScatterCandleBubbleDataSet 1 for stacked bars. * * @return */ diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index ee8048fb09..d4ae8eb422 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -55,7 +55,7 @@ public void initBuffers() { for (int i = 0; i < mBarBuffers.length; i++) { IBarDataSet set = barData.getDataSetByIndex(i); - mBarBuffers[i] = new BarBuffer(set.getEntryCount() * 4 * set.getStackSize(), + mBarBuffers[i] = new BarBuffer(set.getEntryCount() * 4 * (set.isStacked() ? set.getStackSize() : 1), barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 45fb1b1fb8..09de5fd413 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -41,7 +41,7 @@ public void initBuffers() { for (int i = 0; i < mBarBuffers.length; i++) { IBarDataSet set = barData.getDataSetByIndex(i); - mBarBuffers[i] = new HorizontalBarBuffer(set.getEntryCount() * 4 * set.getStackSize(), + mBarBuffers[i] = new HorizontalBarBuffer(set.getEntryCount() * 4 * (set.isStacked() ? set.getStackSize() : 1), barData.getGroupSpace(), barData.getDataSetCount(), set.isStacked()); } From af541451d822876cbbf1e48f0051f636a92cc622 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 11:42:38 +0100 Subject: [PATCH 0598/1390] Implement all RealmDataSets --- .../charting/data/realm/RealmBarDataSet.java | 12 +- .../charting/data/realm/RealmBaseDataSet.java | 41 ++++--- .../data/realm/RealmBubbleDataSet.java | 67 +++++++++++- .../data/realm/RealmCandleDataSet.java | 103 +++++++++++++++++- .../charting/data/realm/RealmLineDataSet.java | 12 +- .../charting/data/realm/RealmPieDataSet.java | 35 +++++- .../data/realm/RealmRadarDataSet.java | 77 ++++++++++++- .../data/realm/RealmScatterDataSet.java | 63 ++++++++++- 8 files changed, 377 insertions(+), 33 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java index cf8b6122db..96abdd9ae7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java @@ -16,11 +16,15 @@ public class RealmBarDataSet extends RealmBaseDataSet results, String yValuesField, String xIndexField) { super(results, yValuesField, xIndexField); + } + + @Override + public void build(RealmResults results) { - for (T object : this.results) { + for (T object : results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new BarEntry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + mValues.add(new BarEntry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); } } @@ -46,7 +50,7 @@ public int getBarShadowColor() { @Override public int getHighLightAlpha() { - return 0; + return 120; } @Override @@ -56,6 +60,6 @@ public String[] getStackLabels() { @Override public int getHighLightColor() { - return 0; + return Color.BLACK; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java index e02514888d..7e5b9bb296 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -21,8 +21,8 @@ public abstract class RealmBaseDataSet e protected List mValues; - private String yValuesField; - private String xIndexField; + protected String mValuesField; + protected String mIndexField; /** * Constructor that takes the realm RealmResults, sorts & stores them. @@ -33,21 +33,28 @@ public abstract class RealmBaseDataSet e */ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIndexField) { this.results = results; - this.yValuesField = yValuesField; - this.xIndexField = xIndexField; + this.mValuesField = yValuesField; + this.mIndexField = xIndexField; mValues = new ArrayList(); - this.results.sort(xIndexField, true); + this.results.sort(mIndexField, true); + + build(this.results); } + /** + * Rebuilds the DataSet based on the given RealmResults. + */ + public abstract void build(RealmResults results); + @Override public float getYMin() { - //return results.min(yValuesField).floatValue(); + //return results.min(mValuesField).floatValue(); return -50; } @Override public float getYMax() { - //return results.max(yValuesField).floatValue(); + //return results.max(mValuesField).floatValue(); return 200; } @@ -63,8 +70,8 @@ public void calcMinMax(int start, int end) { @Override public S getEntryForXIndex(int xIndex) { - //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(xIndexField, xIndex).findFirst()); - //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + //DynamicRealmObject o = new DynamicRealmObject(results.where().equalTo(mIndexField, xIndex).findFirst()); + //return new Entry(o.getFloat(mValuesField), o.getInt(mIndexField)); int index = getEntryIndex(xIndex); if (index > -1) return mValues.get(index); @@ -74,7 +81,7 @@ public S getEntryForXIndex(int xIndex) { @Override public S getEntryForIndex(int index) { //DynamicRealmObject o = new DynamicRealmObject(results.get(index)); - //return new Entry(o.getFloat(yValuesField), o.getInt(xIndexField)); + //return new Entry(o.getFloat(mValuesField), o.getInt(mIndexField)); return mValues.get(index); } @@ -113,7 +120,7 @@ public int getEntryIndex(S e) { @Override public float getYValForXIndex(int xIndex) { - //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(xIndexField, xIndex).findFirst()).getFloat(yValuesField); + //return new DynamicRealmObject(results.where().greaterThanOrEqualTo(mIndexField, xIndex).findFirst()).getFloat(mValuesField); Entry e = getEntryForXIndex(xIndex); if (e != null && e.getXIndex() == xIndex) @@ -133,10 +140,18 @@ public boolean removeEntry(S e) { } public String getValuesField() { - return yValuesField; + return mValuesField; + } + + public void setValuesField(String yValuesField) { + this.mValuesField = yValuesField; } public String getIndexField() { - return xIndexField; + return mIndexField; + } + + public void setIndexField(String xIndexField) { + this.mIndexField = xIndexField; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java index 8b030d4f28..e57a9b59f3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java @@ -1,7 +1,70 @@ package com.github.mikephil.charting.data.realm; +import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmBubbleDataSet { +public class RealmBubbleDataSet extends RealmBaseDataSet implements IBubbleDataSet { + + private String mSizeField; + + public RealmBubbleDataSet(RealmResults result, String yValuesField, String xIndexField, String sizeField) { + super(result, yValuesField, xIndexField); + this.mSizeField = sizeField; + } + + @Override + public void build(RealmResults results) { + + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new BubbleEntry(dynamicObject.getInt(mIndexField), dynamicObject.getFloat(mValuesField), dynamicObject.getFloat(mSizeField))); + } + } + + @Override + public void setHighlightCircleWidth(float width) { + + } + + @Override + public float getXMax() { + return 0; + } + + @Override + public float getXMin() { + return 0; + } + + @Override + public float getMaxSize() { + return 0; + } + + @Override + public float getHighlightCircleWidth() { + return 0; + } + + @Override + public int getHighLightColor() { + return 0; + } + + /** + * Returns the database fieldname that stores bubble size. + * + * @return + */ + public String getSizeField() { + return mSizeField; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java index a245082c5a..bba30c9922 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java @@ -1,7 +1,106 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.Color; +import android.graphics.DashPathEffect; +import android.graphics.Paint; + +import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmCandleDataSet { +public class RealmCandleDataSet extends RealmBaseDataSet implements ICandleDataSet { + + private String mHighField; + private String mLowField; + private String mOpenField; + private String mCloseField; + + public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField, String xIndexField) { + super(result, "", xIndexField); + this.mHighField = highField; + this.mLowField = lowField; + this.mOpenField = openField; + this.mCloseField = closeField; + } + + @Override + public void build(RealmResults results) { + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new CandleEntry(dynamicObject.getInt(mIndexField), dynamicObject.getFloat(mHighField), dynamicObject.getFloat(mLowField), + dynamicObject.getFloat(mOpenField), dynamicObject.getFloat(mCloseField))); + } + } + + @Override + public float getBodySpace() { + return 0; + } + + @Override + public float getShadowWidth() { + return 2; + } + + @Override + public int getShadowColor() { + return Color.BLACK; + } + + @Override + public int getDecreasingColor() { + return Color.GREEN; + } + + @Override + public int getIncreasingColor() { + return Color.RED; + } + + @Override + public Paint.Style getDecreasingPaintStyle() { + return null; + } + + @Override + public Paint.Style getIncreasingPaintStyle() { + return null; + } + + @Override + public boolean getShadowColorSameAsCandle() { + return false; + } + + @Override + public boolean isVerticalHighlightIndicatorEnabled() { + return false; + } + + @Override + public boolean isHorizontalHighlightIndicatorEnabled() { + return false; + } + + @Override + public float getHighlightLineWidth() { + return 0; + } + + @Override + public DashPathEffect getDashPathEffectHighlight() { + return null; + } + + @Override + public int getHighLightColor() { + return 0; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 1c33825453..652d13d4f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -3,15 +3,11 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; -import java.util.ArrayList; -import java.util.List; - import io.realm.RealmObject; import io.realm.RealmResults; import io.realm.dynamic.DynamicRealmObject; @@ -25,11 +21,15 @@ public class RealmLineDataSet extends RealmBaseDataSet result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); + } + + @Override + public void build(RealmResults results) { - for (T object : this.results) { + for (T object : results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(yValuesField), dynamicObject.getInt(xIndexField))); + mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java index 6f8c2b30ae..7dc59316f6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java @@ -1,7 +1,38 @@ package com.github.mikephil.charting.data.realm; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmPieDataSet { +public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { + + public RealmPieDataSet(RealmResults result, String yValuesField, String xIndexField) { + super(result, yValuesField, xIndexField); + } + + @Override + public void build(RealmResults results) { + + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); + } + } + + @Override + public float getSliceSpace() { + return 0; + } + + @Override + public float getSelectionShift() { + return 0; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java index b1ca419338..3a3ec82688 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java @@ -1,7 +1,80 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.DashPathEffect; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmRadarDataSet { +public class RealmRadarDataSet extends RealmBaseDataSet implements IRadarDataSet { + + public RealmRadarDataSet(RealmResults result, String yValuesField, String xIndexField) { + super(result, yValuesField, xIndexField); + } + + @Override + public void build(RealmResults results) { + + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); + } + } + + @Override + public int getFillColor() { + return 0; + } + + @Override + public int getFillAlpha() { + return 0; + } + + @Override + public float getLineWidth() { + return 4; + } + + @Override + public boolean isDrawFilledEnabled() { + return false; + } + + @Override + public void setDrawFilled(boolean enabled) { + + } + + @Override + public boolean isVerticalHighlightIndicatorEnabled() { + return false; + } + + @Override + public boolean isHorizontalHighlightIndicatorEnabled() { + return false; + } + + @Override + public float getHighlightLineWidth() { + return 0; + } + + @Override + public DashPathEffect getDashPathEffectHighlight() { + return null; + } + + @Override + public int getHighLightColor() { + return 0; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java index f0ef8ed51b..5e5e96bd69 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java @@ -1,7 +1,66 @@ package com.github.mikephil.charting.data.realm; +import android.graphics.DashPathEffect; + +import com.github.mikephil.charting.charts.ScatterChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmObject; + /** - * Created by philipp on 07/11/15. + * Created by Philipp Jahoda on 07/11/15. */ -public class RealmScatterDataSet { +public class RealmScatterDataSet extends RealmBaseDataSet implements IScatterDataSet { + + public RealmScatterDataSet(RealmResults result, String yValuesField, String xIndexField) { + super(result, yValuesField, xIndexField); + } + + @Override + public void build(RealmResults results) { + + for (T object : results) { + + DynamicRealmObject dynamicObject = new DynamicRealmObject(object); + mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); + } + } + + @Override + public float getScatterShapeSize() { + return 0; + } + + @Override + public ScatterChart.ScatterShape getScatterShape() { + return null; + } + + @Override + public boolean isVerticalHighlightIndicatorEnabled() { + return false; + } + + @Override + public boolean isHorizontalHighlightIndicatorEnabled() { + return false; + } + + @Override + public float getHighlightLineWidth() { + return 0; + } + + @Override + public DashPathEffect getDashPathEffectHighlight() { + return null; + } + + @Override + public int getHighLightColor() { + return 0; + } } From b7e0e40d52a644767fa92cca632f6614491a7f24 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 11:44:06 +0100 Subject: [PATCH 0599/1390] Documentation --- .../mikephil/charting/data/realm/RealmBaseDataSet.java | 10 ++++++++++ .../mikephil/charting/data/realm/RealmPieDataSet.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java index 7e5b9bb296..cf6e913dd4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java @@ -19,9 +19,19 @@ public abstract class RealmBaseDataSet e */ protected RealmResults results; + /** + * a cached list of all data read from the database + */ protected List mValues; + /** + * fieldname of the column that contains the y-values of this dataset + */ protected String mValuesField; + + /** + * fieldname of the column that contains the x-indices of this dataset + */ protected String mIndexField; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java index 7dc59316f6..86eb0f28e6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java @@ -33,6 +33,6 @@ public float getSliceSpace() { @Override public float getSelectionShift() { - return 0; + return 10; } } From 6773bad9d5cb28c4cf7567175071b5b2d1072b98 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 17:32:08 +0100 Subject: [PATCH 0600/1390] Add abstract RealmBarLineScatterCandleBubbleDataSet --- .../charting/data/realm/RealmBarDataSet.java | 6 +-- ...ealmBarLineScatterCandleBubbleDataSet.java | 45 +++++++++++++++++++ .../data/realm/RealmBubbleDataSet.java | 12 +++-- 3 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java index 96abdd9ae7..b873d16f47 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java @@ -12,7 +12,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmBarDataSet extends RealmBaseDataSet implements IBarDataSet { +public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBarDataSet { public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { super(results, yValuesField, xIndexField); @@ -58,8 +58,4 @@ public String[] getStackLabels() { return null; } - @Override - public int getHighLightColor() { - return Color.BLACK; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java new file mode 100644 index 0000000000..1509919e62 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java @@ -0,0 +1,45 @@ +package com.github.mikephil.charting.data.realm; + +import android.graphics.Color; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; + +import io.realm.RealmObject; +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 08/11/15. + */ +public abstract class RealmBarLineScatterCandleBubbleDataSet extends RealmBaseDataSet implements IBarLineScatterCandleBubbleDataSet { + + /** default highlight color */ + protected int mHighLightColor = Color.rgb(255, 187, 115); + + /** + * Constructor that takes the realm RealmResults, sorts & stores them. + * + * @param results + * @param yValuesField + * @param xIndexField + */ + public RealmBarLineScatterCandleBubbleDataSet(RealmResults results, String yValuesField, String xIndexField) { + super(results, yValuesField, xIndexField); + } + + /** + * Sets the color that is used for drawing the highlight indicators. Dont + * forget to resolve the color using getResources().getColor(...) or + * Color.rgb(...). + * + * @param color + */ + public void setHighLightColor(int color) { + mHighLightColor = color; + } + + @Override + public int getHighLightColor() { + return mHighLightColor; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java index e57a9b59f3..38b907654d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java @@ -10,7 +10,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmBubbleDataSet extends RealmBaseDataSet implements IBubbleDataSet { +public class RealmBubbleDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBubbleDataSet { private String mSizeField; @@ -54,9 +54,13 @@ public float getHighlightCircleWidth() { return 0; } - @Override - public int getHighLightColor() { - return 0; + /** + * Sets the database fieldname for the bubble size. + * + * @param sizeField + */ + public void setSizeField(String sizeField) { + this.mSizeField = sizeField; } /** From ee0fd10fc42fed77a178d55899afad911c16a988 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 17:44:03 +0100 Subject: [PATCH 0601/1390] Complete realm model --- .../data/realm/RealmCandleDataSet.java | 28 +---- .../charting/data/realm/RealmLineDataSet.java | 52 +------- .../data/realm/RealmLineRadarDataSet.java | 98 +++++++++++++++ .../RealmLineScatterCandleRadarDataSet.java | 119 ++++++++++++++++++ .../data/realm/RealmRadarDataSet.java | 54 +------- .../data/realm/RealmScatterDataSet.java | 29 +---- 6 files changed, 221 insertions(+), 159 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java index bba30c9922..35178bcb4e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java @@ -1,7 +1,6 @@ package com.github.mikephil.charting.data.realm; import android.graphics.Color; -import android.graphics.DashPathEffect; import android.graphics.Paint; import com.github.mikephil.charting.data.CandleEntry; @@ -14,7 +13,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmCandleDataSet extends RealmBaseDataSet implements ICandleDataSet { +public class RealmCandleDataSet extends RealmLineScatterCandleRadarDataSet implements ICandleDataSet { private String mHighField; private String mLowField; @@ -78,29 +77,4 @@ public Paint.Style getIncreasingPaintStyle() { public boolean getShadowColorSameAsCandle() { return false; } - - @Override - public boolean isVerticalHighlightIndicatorEnabled() { - return false; - } - - @Override - public boolean isHorizontalHighlightIndicatorEnabled() { - return false; - } - - @Override - public float getHighlightLineWidth() { - return 0; - } - - @Override - public DashPathEffect getDashPathEffectHighlight() { - return null; - } - - @Override - public int getHighLightColor() { - return 0; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java index 652d13d4f4..9283713eed 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java @@ -15,7 +15,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmLineDataSet extends RealmBaseDataSet implements ILineDataSet { +public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { private FillFormatter mFillFormatter = new DefaultFillFormatter(); @@ -82,54 +82,4 @@ public boolean isDashedLineEnabled() { public FillFormatter getFillFormatter() { return mFillFormatter; } - - @Override - public int getFillColor() { - return 0; - } - - @Override - public int getFillAlpha() { - return 0; - } - - @Override - public float getLineWidth() { - return 5; - } - - @Override - public boolean isDrawFilledEnabled() { - return false; - } - - @Override - public void setDrawFilled(boolean enabled) { - - } - - @Override - public boolean isVerticalHighlightIndicatorEnabled() { - return false; - } - - @Override - public boolean isHorizontalHighlightIndicatorEnabled() { - return false; - } - - @Override - public float getHighlightLineWidth() { - return 0; - } - - @Override - public DashPathEffect getDashPathEffectHighlight() { - return null; - } - - @Override - public int getHighLightColor() { - return 0; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java new file mode 100644 index 0000000000..f5e42a7600 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java @@ -0,0 +1,98 @@ +package com.github.mikephil.charting.data.realm; + +import android.graphics.Color; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.ILineRadarDataSet; +import com.github.mikephil.charting.utils.Utils; + +import io.realm.RealmObject; +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 08/11/15. + */ +public abstract class RealmLineRadarDataSet extends RealmLineScatterCandleRadarDataSet implements ILineRadarDataSet { + + /** the color that is used for filling the line surface */ + private int mFillColor = Color.rgb(140, 234, 255); + + /** transparency used for filling line surface */ + private int mFillAlpha = 85; + + /** the width of the drawn data lines */ + private float mLineWidth = 2.5f; + + /** if true, the data will also be drawn filled */ + private boolean mDrawFilled = false; + + /** + * Constructor that takes the realm RealmResults, sorts & stores them. + * + * @param results + * @param yValuesField + * @param xIndexField + */ + public RealmLineRadarDataSet(RealmResults results, String yValuesField, String xIndexField) { + super(results, yValuesField, xIndexField); + } + + @Override + public int getFillColor() { + return mFillColor; + } + + /** + * sets the color that is used for filling the line surface + * + * @param color + */ + public void setFillColor(int color) { + mFillColor = color; + } + + @Override + public int getFillAlpha() { + return mFillAlpha; + } + + /** + * sets the alpha value (transparency) that is used for filling the line + * surface (0-255), default: 85 + * + * @param alpha + */ + public void setFillAlpha(int alpha) { + mFillAlpha = alpha; + } + + /** + * set the line width of the chart (min = 0.2f, max = 10f); default 1f NOTE: + * thinner line == better performance, thicker line == worse performance + * + * @param width + */ + public void setLineWidth(float width) { + + if (width < 0.2f) + width = 0.2f; + if (width > 10.0f) + width = 10.0f; + mLineWidth = Utils.convertDpToPixel(width); + } + + @Override + public float getLineWidth() { + return mLineWidth; + } + + @Override + public void setDrawFilled(boolean filled) { + mDrawFilled = filled; + } + + @Override + public boolean isDrawFilledEnabled() { + return mDrawFilled; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java new file mode 100644 index 0000000000..a7b032fe8f --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java @@ -0,0 +1,119 @@ +package com.github.mikephil.charting.data.realm; + +import android.graphics.DashPathEffect; + +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.interfaces.datasets.ILineScatterCandleRadarDataSet; +import com.github.mikephil.charting.utils.Utils; + +import io.realm.RealmObject; +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 08/11/15. + */ +public abstract class RealmLineScatterCandleRadarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements ILineScatterCandleRadarDataSet { + + protected boolean mDrawVerticalHighlightIndicator = true; + protected boolean mDrawHorizontalHighlightIndicator = true; + + /** the width of the highlight indicator lines */ + protected float mHighlightLineWidth = 0.5f; + + /** the path effect for dashed highlight-lines */ + protected DashPathEffect mHighlightDashPathEffect = null; + + /** + * Constructor that takes the realm RealmResults, sorts & stores them. + * + * @param results + * @param yValuesField + * @param xIndexField + */ + public RealmLineScatterCandleRadarDataSet(RealmResults results, String yValuesField, String xIndexField) { + super(results, yValuesField, xIndexField); + } + + /** + * Enables / disables the horizontal highlight-indicator. If disabled, the indicator is not drawn. + * @param enabled + */ + public void setDrawHorizontalHighlightIndicator(boolean enabled) { + this.mDrawHorizontalHighlightIndicator = enabled; + } + + /** + * Enables / disables the vertical highlight-indicator. If disabled, the indicator is not drawn. + * @param enabled + */ + public void setDrawVerticalHighlightIndicator(boolean enabled) { + this.mDrawVerticalHighlightIndicator = enabled; + } + + /** + * Enables / disables both vertical and horizontal highlight-indicators. + * @param enabled + */ + public void setDrawHighlightIndicators(boolean enabled) { + setDrawVerticalHighlightIndicator(enabled); + setDrawHorizontalHighlightIndicator(enabled); + } + + @Override + public boolean isVerticalHighlightIndicatorEnabled() { + return mDrawVerticalHighlightIndicator; + } + + @Override + public boolean isHorizontalHighlightIndicatorEnabled() { + return mDrawHorizontalHighlightIndicator; + } + + /** + * Sets the width of the highlight line in dp. + * @param width + */ + public void setHighlightLineWidth(float width) { + mHighlightLineWidth = Utils.convertDpToPixel(width); + } + + @Override + public float getHighlightLineWidth() { + return mHighlightLineWidth; + } + + /** + * Enables the highlight-line to be drawn in dashed mode, e.g. like this "- - - - - -" + * + * @param lineLength the length of the line pieces + * @param spaceLength the length of space inbetween the line-pieces + * @param phase offset, in degrees (normally, use 0) + */ + public void enableDashedHighlightLine(float lineLength, float spaceLength, float phase) { + mHighlightDashPathEffect = new DashPathEffect(new float[] { + lineLength, spaceLength + }, phase); + } + + /** + * Disables the highlight-line to be drawn in dashed mode. + */ + public void disableDashedHighlightLine() { + mHighlightDashPathEffect = null; + } + + /** + * Returns true if the dashed-line effect is enabled for highlight lines, false if not. + * Default: disabled + * + * @return + */ + public boolean isDashedHighlightLineEnabled() { + return mHighlightDashPathEffect == null ? false : true; + } + + @Override + public DashPathEffect getDashPathEffectHighlight() { + return mHighlightDashPathEffect; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java index 3a3ec82688..408635750f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java @@ -1,7 +1,5 @@ package com.github.mikephil.charting.data.realm; -import android.graphics.DashPathEffect; - import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; @@ -12,7 +10,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmRadarDataSet extends RealmBaseDataSet implements IRadarDataSet { +public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { public RealmRadarDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); @@ -27,54 +25,4 @@ public void build(RealmResults results) { mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); } } - - @Override - public int getFillColor() { - return 0; - } - - @Override - public int getFillAlpha() { - return 0; - } - - @Override - public float getLineWidth() { - return 4; - } - - @Override - public boolean isDrawFilledEnabled() { - return false; - } - - @Override - public void setDrawFilled(boolean enabled) { - - } - - @Override - public boolean isVerticalHighlightIndicatorEnabled() { - return false; - } - - @Override - public boolean isHorizontalHighlightIndicatorEnabled() { - return false; - } - - @Override - public float getHighlightLineWidth() { - return 0; - } - - @Override - public DashPathEffect getDashPathEffectHighlight() { - return null; - } - - @Override - public int getHighLightColor() { - return 0; - } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java index 5e5e96bd69..3e211d19b3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java @@ -1,7 +1,5 @@ package com.github.mikephil.charting.data.realm; -import android.graphics.DashPathEffect; - import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; @@ -13,7 +11,7 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmScatterDataSet extends RealmBaseDataSet implements IScatterDataSet { +public class RealmScatterDataSet extends RealmLineScatterCandleRadarDataSet implements IScatterDataSet { public RealmScatterDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); @@ -38,29 +36,4 @@ public float getScatterShapeSize() { public ScatterChart.ScatterShape getScatterShape() { return null; } - - @Override - public boolean isVerticalHighlightIndicatorEnabled() { - return false; - } - - @Override - public boolean isHorizontalHighlightIndicatorEnabled() { - return false; - } - - @Override - public float getHighlightLineWidth() { - return 0; - } - - @Override - public DashPathEffect getDashPathEffectHighlight() { - return null; - } - - @Override - public int getHighLightColor() { - return 0; - } } From 691ce133b8d160c78b241b047b993529c3d1261e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 17:45:07 +0100 Subject: [PATCH 0602/1390] Package refactoring --- .../mpchartexample/RealmDatabaseActivity.java | 10 +--------- .../RealmBarLineScatterCandleBubbleDataSet.java | 2 +- .../data/realm/{ => base}/RealmBaseDataSet.java | 2 +- .../data/realm/{ => base}/RealmLineRadarDataSet.java | 2 +- .../{ => base}/RealmLineScatterCandleRadarDataSet.java | 2 +- .../realm/{ => implementation}/RealmBarDataSet.java | 3 ++- .../realm/{ => implementation}/RealmBubbleDataSet.java | 3 ++- .../realm/{ => implementation}/RealmCandleDataSet.java | 3 ++- .../realm/{ => implementation}/RealmLineDataSet.java | 3 ++- .../realm/{ => implementation}/RealmPieDataSet.java | 3 ++- .../realm/{ => implementation}/RealmRadarDataSet.java | 3 ++- .../{ => implementation}/RealmScatterDataSet.java | 3 ++- 12 files changed, 19 insertions(+), 20 deletions(-) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => base}/RealmBarLineScatterCandleBubbleDataSet.java (96%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => base}/RealmBaseDataSet.java (98%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => base}/RealmLineRadarDataSet.java (97%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => base}/RealmLineScatterCandleRadarDataSet.java (98%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmBarDataSet.java (89%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmBubbleDataSet.java (91%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmCandleDataSet.java (93%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmLineDataSet.java (93%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmPieDataSet.java (88%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmRadarDataSet.java (86%) rename MPChartLib/src/com/github/mikephil/charting/data/realm/{ => implementation}/RealmScatterDataSet.java (87%) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index ed7df429f9..fb002e445b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -6,23 +6,15 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; -import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.Entry; -import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.data.realm.RealmBarDataSet; -import com.github.mikephil.charting.data.realm.RealmLineDataSet; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; -import com.xxmassdeveloper.mpchartexample.notimportant.DemoBase; import com.xxmassdeveloper.mpchartexample.notimportant.RealmBaseActivity; import java.util.ArrayList; -import io.realm.Realm; -import io.realm.RealmConfiguration; import io.realm.RealmResults; /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java similarity index 96% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java index 1509919e62..a8e40345a4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.base; import android.graphics.Color; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index cf6e913dd4..6f7887a9be 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.base; import com.github.mikephil.charting.data.BaseDataSet; import com.github.mikephil.charting.data.Entry; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java similarity index 97% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index f5e42a7600..57b7e1affa 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.base; import android.graphics.Color; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java similarity index 98% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java index a7b032fe8f..8a58351026 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineScatterCandleRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineScatterCandleRadarDataSet.java @@ -1,4 +1,4 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.base; import android.graphics.DashPathEffect; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java similarity index 89% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index b873d16f47..7544e2fd22 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -1,8 +1,9 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import android.graphics.Color; import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import io.realm.RealmObject; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java similarity index 91% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 38b907654d..e017c32fc7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -1,6 +1,7 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.data.BubbleEntry; +import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import io.realm.RealmObject; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java similarity index 93% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 35178bcb4e..7d08aec47f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -1,9 +1,10 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import android.graphics.Color; import android.graphics.Paint; import com.github.mikephil.charting.data.CandleEntry; +import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; import io.realm.RealmObject; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java similarity index 93% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index 9283713eed..7228b7beb0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -1,9 +1,10 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import android.graphics.Color; import android.graphics.DashPathEffect; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java similarity index 88% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 86eb0f28e6..3948be95dd 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -1,6 +1,7 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.realm.base.RealmBaseDataSet; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import io.realm.RealmObject; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java similarity index 86% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 408635750f..ba07a52f37 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -1,6 +1,7 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import io.realm.RealmObject; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java similarity index 87% rename from MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java rename to MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 3e211d19b3..f559cfcec8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -1,7 +1,8 @@ -package com.github.mikephil.charting.data.realm; +package com.github.mikephil.charting.data.realm.implementation; import com.github.mikephil.charting.charts.ScatterChart; import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import io.realm.RealmObject; From c482df559e19b2c92334b4ca8770a1fe76a6f455 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 17:55:37 +0100 Subject: [PATCH 0603/1390] Add necessary styling methods --- .../realm/implementation/RealmBarDataSet.java | 98 ++++++++++- .../implementation/RealmBubbleDataSet.java | 17 +- .../implementation/RealmCandleDataSet.java | 155 ++++++++++++++++-- .../realm/implementation/RealmPieDataSet.java | 36 +++- .../implementation/RealmScatterDataSet.java | 35 +++- 5 files changed, 316 insertions(+), 25 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 7544e2fd22..4209c8258d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -15,6 +15,34 @@ */ public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBarDataSet { + /** + * space indicator between the bars 0.1f == 10 % + */ + private float mBarSpace = 0.15f; + + /** + * the maximum number of bars that are stacked upon each other, this value + * is calculated from the Entries that are added to the DataSet + */ + private int mStackSize = 1; + + /** + * the color used for drawing the bar shadows + */ + private int mBarShadowColor = Color.rgb(215, 215, 215); + + /** + * the alpha value used to draw the highlight indicator bar + */ + private int mHighLightAlpha = 120; + + /** + * array of labels used to describe the different values of the stacked bars + */ + private String[] mStackLabels = new String[]{ + "Stack" + }; + public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { super(results, yValuesField, xIndexField); } @@ -30,33 +58,87 @@ public void build(RealmResults results) { } @Override - public float getBarSpace() { - return 0; + public void calcMinMax(int start, int end) { + + // TODO: implement this + } + + @Override + public int getStackSize() { + return mStackSize; } @Override public boolean isStacked() { - return false; + return mStackSize > 1 ? true : false; + } + + /** + * returns the space between bars in percent of the whole width of one value + * + * @return + */ + public float getBarSpacePercent() { + return mBarSpace * 100f; } @Override - public int getStackSize() { - return 0; + public float getBarSpace() { + return mBarSpace; + } + + /** + * sets the space between the bars in percent (0-100) of the total bar width + * + * @param percent + */ + public void setBarSpacePercent(float percent) { + mBarSpace = percent / 100f; + } + + /** + * Sets the color used for drawing the bar-shadows. The bar shadows is a + * surface behind the bar that indicates the maximum value. Don't for get to + * use getResources().getColor(...) to set this. Or Color.rgb(...). + * + * @param color + */ + public void setBarShadowColor(int color) { + mBarShadowColor = color; } @Override public int getBarShadowColor() { - return Color.BLACK; + return mBarShadowColor; + } + + /** + * Set the alpha value (transparency) that is used for drawing the highlight + * indicator bar. min = 0 (fully transparent), max = 255 (fully opaque) + * + * @param alpha + */ + public void setHighLightAlpha(int alpha) { + mHighLightAlpha = alpha; } @Override public int getHighLightAlpha() { - return 120; + return mHighLightAlpha; + } + + /** + * Sets labels for different values of bar-stacks, in case there are one. + * + * @param labels + */ + public void setStackLabels(String[] labels) { + mStackLabels = labels; } @Override public String[] getStackLabels() { - return null; + return mStackLabels; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index e017c32fc7..7ad64aefd5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; +import com.github.mikephil.charting.utils.Utils; import io.realm.RealmObject; import io.realm.RealmResults; @@ -15,6 +16,12 @@ public class RealmBubbleDataSet extends RealmBarLineScatt private String mSizeField; + protected float mXMax; + protected float mXMin; + protected float mMaxSize; + + private float mHighlightCircleWidth = 2.5f; + public RealmBubbleDataSet(RealmResults result, String yValuesField, String xIndexField, String sizeField) { super(result, yValuesField, xIndexField); this.mSizeField = sizeField; @@ -31,8 +38,9 @@ public void build(RealmResults results) { } @Override - public void setHighlightCircleWidth(float width) { + public void calcMinMax(int start, int end) { + // TODO: implement this } @Override @@ -50,9 +58,14 @@ public float getMaxSize() { return 0; } + @Override + public void setHighlightCircleWidth(float width) { + mHighlightCircleWidth = Utils.convertDpToPixel(width); + } + @Override public float getHighlightCircleWidth() { - return 0; + return mHighlightCircleWidth; } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 7d08aec47f..1f2809d36c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -1,11 +1,12 @@ package com.github.mikephil.charting.data.realm.implementation; -import android.graphics.Color; import android.graphics.Paint; import com.github.mikephil.charting.data.CandleEntry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Utils; import io.realm.RealmObject; import io.realm.RealmResults; @@ -21,6 +22,48 @@ public class RealmCandleDataSet extends RealmLineScatterC private String mOpenField; private String mCloseField; + + /** + * the width of the shadow of the candle + */ + private float mShadowWidth = 3f; + + /** + * the space between the candle entries, default 0.1f (10%) + */ + private float mBodySpace = 0.1f; + + /** + * use candle color for the shadow + */ + private boolean mShadowColorSameAsCandle = false; + + /** + * paint style when open <= close + */ + protected Paint.Style mIncreasingPaintStyle = Paint.Style.FILL; + + /** + * paint style when open > close + */ + protected Paint.Style mDecreasingPaintStyle = Paint.Style.STROKE; + + /** + * color for open <= close + */ + protected int mIncreasingColor = ColorTemplate.COLOR_NONE; + + /** + * color for open > close + */ + protected int mDecreasingColor = ColorTemplate.COLOR_NONE; + + /** + * shadow line color, set -1 for backward compatibility and uses default + * color + */ + protected int mShadowColor = ColorTemplate.COLOR_NONE; + public RealmCandleDataSet(RealmResults result, String highField, String lowField, String openField, String closeField, String xIndexField) { super(result, "", xIndexField); this.mHighField = highField; @@ -39,43 +82,133 @@ public void build(RealmResults results) { } } + @Override + public void calcMinMax(int start, int end) { + + // TODO: implement this + } + + /** + * Sets the space that is left out on the left and right side of each + * candle, default 0.1f (10%), max 0.45f, min 0f + * + * @param space + */ + public void setBodySpace(float space) { + + if (space < 0f) + space = 0f; + if (space > 0.45f) + space = 0.45f; + + mBodySpace = space; + } + @Override public float getBodySpace() { - return 0; + return mBodySpace; + } + + /** + * Sets the width of the candle-shadow-line in pixels. Default 3f. + * + * @param width + */ + public void setShadowWidth(float width) { + mShadowWidth = Utils.convertDpToPixel(width); } @Override public float getShadowWidth() { - return 2; + return mShadowWidth; } - @Override - public int getShadowColor() { - return Color.BLACK; + + /** BELOW THIS COLOR HANDLING */ + + /** + * Sets the one and ONLY color that should be used for this DataSet when + * open > close. + * + * @param color + */ + public void setDecreasingColor(int color) { + mDecreasingColor = color; } @Override public int getDecreasingColor() { - return Color.GREEN; + return mDecreasingColor; + } + + /** + * Sets the one and ONLY color that should be used for this DataSet when + * open <= close. + * + * @param color + */ + public void setIncreasingColor(int color) { + mIncreasingColor = color; } @Override public int getIncreasingColor() { - return Color.RED; + return mIncreasingColor; } @Override public Paint.Style getDecreasingPaintStyle() { - return null; + return mDecreasingPaintStyle; + } + + /** + * Sets paint style when open > close + * + * @param decreasingPaintStyle + */ + public void setDecreasingPaintStyle(Paint.Style decreasingPaintStyle) { + this.mDecreasingPaintStyle = decreasingPaintStyle; } @Override public Paint.Style getIncreasingPaintStyle() { - return null; + return mIncreasingPaintStyle; + } + + /** + * Sets paint style when open <= close + * + * @param paintStyle + */ + public void setIncreasingPaintStyle(Paint.Style paintStyle) { + this.mIncreasingPaintStyle = paintStyle; + } + + @Override + public int getShadowColor() { + return mShadowColor; + } + + /** + * Sets shadow color for all entries + * + * @param shadowColor + */ + public void setShadowColor(int shadowColor) { + this.mShadowColor = shadowColor; } @Override public boolean getShadowColorSameAsCandle() { - return false; + return mShadowColorSameAsCandle; + } + + /** + * Sets shadow color to be the same color as the candle color + * + * @param shadowColorSameAsCandle + */ + public void setShadowColorSameAsCandle(boolean shadowColorSameAsCandle) { + this.mShadowColorSameAsCandle = shadowColorSameAsCandle; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 3948be95dd..cf7a180a00 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -3,6 +3,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmBaseDataSet; import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.utils.Utils; import io.realm.RealmObject; import io.realm.RealmResults; @@ -13,6 +14,12 @@ */ public class RealmPieDataSet extends RealmBaseDataSet implements IPieDataSet { + /** the space in degrees between the chart-slices, default 0f */ + private float mSliceSpace = 0f; + + /** indicates the selection distance of a pie slice */ + private float mShift = 18f; + public RealmPieDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); } @@ -26,14 +33,39 @@ public void build(RealmResults results) { mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); } } + /** + * sets the space that is left out between the piechart-slices, default: 0° + * --> no space, maximum 45, minimum 0 (no space) + * + * @param degrees + */ + public void setSliceSpace(float degrees) { + + if (degrees > 45) + degrees = 45f; + if (degrees < 0) + degrees = 0f; + + mSliceSpace = degrees; + } @Override public float getSliceSpace() { - return 0; + return mSliceSpace; + } + + /** + * sets the distance the highlighted piechart-slice of this DataSet is + * "shifted" away from the center of the chart, default 12f + * + * @param shift + */ + public void setSelectionShift(float shift) { + mShift = Utils.convertDpToPixel(shift); } @Override public float getSelectionShift() { - return 10; + return mShift; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index f559cfcec8..0aa468721a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -4,6 +4,7 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineScatterCandleRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; +import com.github.mikephil.charting.utils.Utils; import io.realm.RealmObject; import io.realm.RealmResults; @@ -14,6 +15,15 @@ */ public class RealmScatterDataSet extends RealmLineScatterCandleRadarDataSet implements IScatterDataSet { + /** the size the scattershape will have, in screen pixels */ + private float mShapeSize = 15f; + + /** + * the type of shape that is set to be drawn where the values are at, + * default ScatterShape.SQUARE + */ + private ScatterChart.ScatterShape mScatterShape = ScatterChart.ScatterShape.SQUARE; + public RealmScatterDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); } @@ -28,13 +38,34 @@ public void build(RealmResults results) { } } + /** + * Sets the size in density pixels the drawn scattershape will have. This + * only applies for non custom shapes. + * + * @param size + */ + public void setScatterShapeSize(float size) { + mShapeSize = Utils.convertDpToPixel(size); + } + @Override public float getScatterShapeSize() { - return 0; + return mShapeSize; + } + + /** + * Sets the shape that is drawn on the position where the values are at. If + * "CUSTOM" is chosen, you need to call setCustomScatterShape(...) and + * provide a path object that is drawn as the custom scattershape. + * + * @param shape + */ + public void setScatterShape(ScatterChart.ScatterShape shape) { + mScatterShape = shape; } @Override public ScatterChart.ScatterShape getScatterShape() { - return null; + return mScatterShape; } } From 58e629fd1f1419adffe12864d7a3ddd062532140 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 18:08:24 +0100 Subject: [PATCH 0604/1390] Add documentation --- .../data/realm/base/RealmBaseDataSet.java | 26 +++++++++++++++++++ .../implementation/RealmCandleDataSet.java | 1 - 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 6f7887a9be..f9cc6ea1f3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -49,6 +49,7 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn this.results.sort(mIndexField, true); build(this.results); + calcMinMax(0, results.size()); } /** @@ -76,6 +77,7 @@ public int getEntryCount() { @Override public void calcMinMax(int start, int end) { + } @Override @@ -149,10 +151,29 @@ public boolean removeEntry(S e) { return false; } + /** + * Returns the List of values that has been extracted from the RealmResults + * using the provided fieldnames. + * + * @return + */ + public List getValues() { + return mValues; + } + + public RealmResults getResults() { + return results; + } + public String getValuesField() { return mValuesField; } + /** + * Sets the field name that is used for getting the y-values out of the RealmResultSet. + * + * @param yValuesField + */ public void setValuesField(String yValuesField) { this.mValuesField = yValuesField; } @@ -161,6 +182,11 @@ public String getIndexField() { return mIndexField; } + /** + * Sets the field name that is used for getting the x-indices out of the RealmResultSet. + * + * @param xIndexField + */ public void setIndexField(String xIndexField) { this.mIndexField = xIndexField; } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 1f2809d36c..dcc190f326 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -22,7 +22,6 @@ public class RealmCandleDataSet extends RealmLineScatterC private String mOpenField; private String mCloseField; - /** * the width of the shadow of the candle */ From 60dcf5bd1d8b2a36b44f881c84be6572cd952f7a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 18:09:59 +0100 Subject: [PATCH 0605/1390] Move color related methods to BaseDataSet --- .../mikephil/charting/data/BaseDataSet.java | 84 ++++++++++++++++++- .../mikephil/charting/data/DataSet.java | 83 ------------------ 2 files changed, 83 insertions(+), 84 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 14954b8f3c..e1f5ff0222 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.data; +import android.content.Context; import android.graphics.Color; import android.graphics.Typeface; @@ -7,6 +8,7 @@ import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.ValueFormatter; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; import java.util.ArrayList; @@ -98,7 +100,7 @@ public void notifyDataSetChanged() { /** - * ###### ###### COLOR RELATED METHODS ##### ###### + * ###### ###### COLOR GETTING RELATED METHODS ##### ###### */ @Override @@ -116,6 +118,86 @@ public int getColor(int index) { return mColors.get(index % mColors.size()); } + /** + * ###### ###### COLOR SETTING RELATED METHODS ##### ###### + */ + + /** + * Sets the colors that should be used fore this DataSet. Colors are reused + * as soon as the number of Entries the DataSet represents is higher than + * the size of the colors array. If you are using colors from the resources, + * make sure that the colors are already prepared (by calling + * getResources().getColor(...)) before adding them to the DataSet. + * + * @param colors + */ + public void setColors(List colors) { + this.mColors = colors; + } + + /** + * Sets the colors that should be used fore this DataSet. Colors are reused + * as soon as the number of Entries the DataSet represents is higher than + * the size of the colors array. If you are using colors from the resources, + * make sure that the colors are already prepared (by calling + * getResources().getColor(...)) before adding them to the DataSet. + * + * @param colors + */ + public void setColors(int[] colors) { + this.mColors = ColorTemplate.createColors(colors); + } + + /** + * Sets the colors that should be used fore this DataSet. Colors are reused + * as soon as the number of Entries the DataSet represents is higher than + * the size of the colors array. You can use + * "new int[] { R.color.red, R.color.green, ... }" to provide colors for + * this method. Internally, the colors are resolved using + * getResources().getColor(...) + * + * @param colors + */ + public void setColors(int[] colors, Context c) { + + List clrs = new ArrayList(); + + for (int color : colors) { + clrs.add(c.getResources().getColor(color)); + } + + mColors = clrs; + } + + /** + * Adds a new color to the colors array of the DataSet. + * + * @param color + */ + public void addColor(int color) { + if (mColors == null) + mColors = new ArrayList(); + mColors.add(color); + } + + /** + * Sets the one and ONLY color that should be used for this DataSet. + * Internally, this recreates the colors array and adds the specified color. + * + * @param color + */ + public void setColor(int color) { + resetColors(); + mColors.add(color); + } + + /** + * Resets all colors of this DataSet and recreates the colors array. + */ + public void resetColors() { + mColors = new ArrayList(); + } + /** ###### ###### OTHER STYLING RELATED METHODS ##### ###### */ @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index d4f4dbd110..4c61ab1ade 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -1,11 +1,6 @@ package com.github.mikephil.charting.data; -import android.content.Context; -import android.graphics.Color; - -import com.github.mikephil.charting.utils.ColorTemplate; - import java.util.ArrayList; import java.util.List; @@ -291,84 +286,6 @@ public boolean removeLast() { return removed; } - /** BELOW THIS COLOR HANDLING */ - - /** - * Sets the colors that should be used fore this DataSet. Colors are reused - * as soon as the number of Entries the DataSet represents is higher than - * the size of the colors array. If you are using colors from the resources, - * make sure that the colors are already prepared (by calling - * getResources().getColor(...)) before adding them to the DataSet. - * - * @param colors - */ - public void setColors(List colors) { - this.mColors = colors; - } - - /** - * Sets the colors that should be used fore this DataSet. Colors are reused - * as soon as the number of Entries the DataSet represents is higher than - * the size of the colors array. If you are using colors from the resources, - * make sure that the colors are already prepared (by calling - * getResources().getColor(...)) before adding them to the DataSet. - * - * @param colors - */ - public void setColors(int[] colors) { - this.mColors = ColorTemplate.createColors(colors); - } - - /** - * Sets the colors that should be used fore this DataSet. Colors are reused - * as soon as the number of Entries the DataSet represents is higher than - * the size of the colors array. You can use - * "new int[] { R.color.red, R.color.green, ... }" to provide colors for - * this method. Internally, the colors are resolved using - * getResources().getColor(...) - * - * @param colors - */ - public void setColors(int[] colors, Context c) { - - List clrs = new ArrayList(); - - for (int color : colors) { - clrs.add(c.getResources().getColor(color)); - } - - mColors = clrs; - } - - /** - * Adds a new color to the colors array of the DataSet. - * - * @param color - */ - public void addColor(int color) { - if (mColors == null) - mColors = new ArrayList(); - mColors.add(color); - } - - /** - * Sets the one and ONLY color that should be used for this DataSet. - * Internally, this recreates the colors array and adds the specified color. - * - * @param color - */ - public void setColor(int color) { - resetColors(); - mColors.add(color); - } - - /** - * Resets all colors of this DataSet and recreates the colors array. - */ - public void resetColors() { - mColors = new ArrayList(); - } - /** * Removes all values from this DataSet and recalculates min and max value. */ From 566e8018a0b18f160a6c361a5c8ba98994c37d62 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 18:15:36 +0100 Subject: [PATCH 0606/1390] Add cler method --- .../charting/data/realm/base/RealmBaseDataSet.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index f9cc6ea1f3..6cbcacce85 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -161,6 +161,14 @@ public List getValues() { return mValues; } + /** + * Clears all values from the DataSet. + */ + public void clearValues() { + mValues.clear(); + notifyDataSetChanged(); + } + public RealmResults getResults() { return results; } From 3f942bf0039f257bd789899d0df5deb3aa5bc7e6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 8 Nov 2015 18:24:06 +0100 Subject: [PATCH 0607/1390] Work on realm-linedataset example --- .../mpchartexample/RealmDatabaseActivity.java | 19 +- .../implementation/RealmLineDataSet.java | 243 ++++++++++++++++-- 2 files changed, 240 insertions(+), 22 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java index fb002e445b..c821e8377d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java @@ -6,10 +6,14 @@ import com.github.mikephil.charting.animation.Easing; import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.LineChart; import com.github.mikephil.charting.components.YAxis; import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import com.xxmassdeveloper.mpchartexample.notimportant.RealmBaseActivity; @@ -22,16 +26,16 @@ */ public class RealmDatabaseActivity extends RealmBaseActivity { - private BarChart mChart; + private LineChart mChart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); - setContentView(R.layout.activity_barchart); + setContentView(R.layout.activity_linechart_noseekbar); - mChart = (BarChart) findViewById(R.id.chart1); + mChart = (LineChart) findViewById(R.id.chart1); mChart.setDrawGridBackground(false); // no description text @@ -77,14 +81,17 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBarDataSet set = new RealmBarDataSet(result, "value", "xIndex"); + RealmLineDataSet set = new RealmLineDataSet(result, "value", "xIndex"); set.setValueTextSize(9f); + set.setDrawCubic(false); + set.setLabel("Realm LineDataSet"); + set.setDrawCircleHole(false); - ArrayList dataSets = new ArrayList(); + ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset // create a data object with the dataset list - BarData data = new BarData(result, "xValue", dataSets); + LineData data = new LineData(result, "xValue", dataSets); // set data mChart.setData(data); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index 7228b7beb0..f36f8a213b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -1,5 +1,6 @@ package com.github.mikephil.charting.data.realm.implementation; +import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; @@ -8,6 +9,11 @@ import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.github.mikephil.charting.utils.Utils; + +import java.util.ArrayList; +import java.util.List; import io.realm.RealmObject; import io.realm.RealmResults; @@ -18,10 +24,38 @@ */ public class RealmLineDataSet extends RealmLineRadarDataSet implements ILineDataSet { + /** List representing all colors that are used for the circles */ + private List mCircleColors = null; + + /** the color of the inner circles */ + private int mCircleColorHole = Color.WHITE; + + /** the radius of the circle-shaped value indicators */ + private float mCircleSize = 8f; + + /** sets the intensity of the cubic lines */ + private float mCubicIntensity = 0.2f; + + /** the path effect of this DataSet that makes dashed lines possible */ + private DashPathEffect mDashPathEffect = null; + + /** formatter for customizing the position of the fill-line */ private FillFormatter mFillFormatter = new DefaultFillFormatter(); + /** if true, drawing circles is enabled */ + private boolean mDrawCircles = true; + + /** if true, cubic lines are drawn instead of linear */ + private boolean mDrawCubic = false; + + private boolean mDrawCircleHole = true; + public RealmLineDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); + mCircleColors = new ArrayList(); + + // default color + mCircleColors.add(Color.rgb(140, 234, 255)); } @Override @@ -34,49 +68,226 @@ public void build(RealmResults results) { } } + + /** + * Sets the intensity for cubic lines (if enabled). Max = 1f = very cubic, + * Min = 0.05f = low cubic effect, Default: 0.2f + * + * @param intensity + */ + public void setCubicIntensity(float intensity) { + + if (intensity > 1f) + intensity = 1f; + if (intensity < 0.05f) + intensity = 0.05f; + + mCubicIntensity = intensity; + } + @Override public float getCubicIntensity() { - return 0.2f; + return mCubicIntensity; } - @Override - public boolean isDrawCubicEnabled() { - return false; + /** + * sets the size (radius) of the circle shpaed value indicators, default + * size = 4f + * + * @param size + */ + public void setCircleSize(float size) { + mCircleSize = Utils.convertDpToPixel(size); } @Override public float getCircleSize() { - return 10; + return mCircleSize; + } + + /** + * Enables the line to be drawn in dashed mode, e.g. like this + * "- - - - - -". THIS ONLY WORKS IF HARDWARE-ACCELERATION IS TURNED OFF. + * Keep in mind that hardware acceleration boosts performance. + * + * @param lineLength the length of the line pieces + * @param spaceLength the length of space in between the pieces + * @param phase offset, in degrees (normally, use 0) + */ + public void enableDashedLine(float lineLength, float spaceLength, float phase) { + mDashPathEffect = new DashPathEffect(new float[] { + lineLength, spaceLength + }, phase); + } + + /** + * Disables the line to be drawn in dashed mode. + */ + public void disableDashedLine() { + mDashPathEffect = null; } @Override - public int getCircleColor(int index) { - return Color.BLACK; + public boolean isDashedLineEnabled() { + return mDashPathEffect == null ? false : true; + } + + @Override + public DashPathEffect getDashPathEffect() { + return mDashPathEffect; + } + + /** + * set this to true to enable the drawing of circle indicators for this + * DataSet, default true + * + * @param enabled + */ + public void setDrawCircles(boolean enabled) { + this.mDrawCircles = enabled; } @Override public boolean isDrawCirclesEnabled() { - return false; + return mDrawCircles; + } + + /** + * If set to true, the linechart lines are drawn in cubic-style instead of + * linear. This affects performance! Default: false + * + * @param enabled + */ + public void setDrawCubic(boolean enabled) { + mDrawCubic = enabled; } @Override - public int getCircleHoleColor() { - return 0; + public boolean isDrawCubicEnabled() { + return mDrawCubic; + } + + /** ALL CODE BELOW RELATED TO CIRCLE-COLORS */ + + /** + * returns all colors specified for the circles + * + * @return + */ + public List getCircleColors() { + return mCircleColors; } @Override - public boolean isDrawCircleHoleEnabled() { - return false; + public int getCircleColor(int index) { + return mCircleColors.get(index % mCircleColors.size()); + } + + /** + * Sets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. Make sure that the colors + * are already prepared (by calling getResources().getColor(...)) before + * adding them to the DataSet. + * + * @param colors + */ + public void setCircleColors(List colors) { + mCircleColors = colors; + } + + /** + * Sets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. Make sure that the colors + * are already prepared (by calling getResources().getColor(...)) before + * adding them to the DataSet. + * + * @param colors + */ + public void setCircleColors(int[] colors) { + this.mCircleColors = ColorTemplate.createColors(colors); + } + + /** + * ets the colors that should be used for the circles of this DataSet. + * Colors are reused as soon as the number of Entries the DataSet represents + * is higher than the size of the colors array. You can use + * "new String[] { R.color.red, R.color.green, ... }" to provide colors for + * this method. Internally, the colors are resolved using + * getResources().getColor(...) + * + * @param colors + */ + public void setCircleColors(int[] colors, Context c) { + + List clrs = new ArrayList(); + + for (int color : colors) { + clrs.add(c.getResources().getColor(color)); + } + + mCircleColors = clrs; + } + + /** + * Sets the one and ONLY color that should be used for this DataSet. + * Internally, this recreates the colors array and adds the specified color. + * + * @param color + */ + public void setCircleColor(int color) { + resetCircleColors(); + mCircleColors.add(color); + } + + /** + * resets the circle-colors array and creates a new one + */ + public void resetCircleColors() { + mCircleColors = new ArrayList(); + } + + /** + * Sets the color of the inner circle of the line-circles. + * + * @param color + */ + public void setCircleColorHole(int color) { + mCircleColorHole = color; } @Override - public DashPathEffect getDashPathEffect() { - return null; + public int getCircleHoleColor() { + return mCircleColorHole; + } + + /** + * Set this to true to allow drawing a hole in each data circle. + * + * @param enabled + */ + public void setDrawCircleHole(boolean enabled) { + mDrawCircleHole = enabled; } @Override - public boolean isDashedLineEnabled() { - return false; + public boolean isDrawCircleHoleEnabled() { + return mDrawCircleHole; + } + + /** + * Sets a custom FillFormatter to the chart that handles the position of the + * filled-line for each DataSet. Set this to null to use the default logic. + * + * @param formatter + */ + public void setFillFormatter(FillFormatter formatter) { + + if (formatter == null) + mFillFormatter = new DefaultFillFormatter(); + else + mFillFormatter = formatter; } @Override From 00574b75a56e2d98765c44860f7935c30163a5eb Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 9 Nov 2015 11:21:57 +0100 Subject: [PATCH 0608/1390] Update gradle dependency --- MPChartLib/build.gradle | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 6c92f5d7df..5e647e4a64 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -40,8 +40,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' - //compile 'com.nineoldandroids:library:2.4.+' - provided 'io.realm:realm-android:0.84.0-SNAPSHOT' // optional dependency to realm-database API + provided 'io.realm:realm-android:0.84.1-SNAPSHOT' // "optional" dependency to realm-database API } android.libraryVariants.all { variant -> From d8a898f114f85120881a14f522e7efc1b8cdfe06 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 9 Nov 2015 12:10:28 +0100 Subject: [PATCH 0609/1390] Work on implementing realm stacked-bars support --- MPChartExample/AndroidManifest.xml | 3 +- .../layout/activity_barchart_noseekbar.xml | 11 +++ .../RealmDatabaseActivityBar.java | 88 +++++++++++++++++++ ...ty.java => RealmDatabaseActivityLine.java} | 31 +------ .../mpchartexample/custom/RealmDemoData.java | 27 ++++++ .../mpchartexample/custom/RealmFloat.java | 27 ++++++ .../notimportant/MainActivity.java | 14 ++- .../notimportant/RealmBaseActivity.java | 57 ++++++++++++ .../realm/implementation/RealmBarDataSet.java | 28 +++++- 9 files changed, 250 insertions(+), 36 deletions(-) create mode 100644 MPChartExample/res/layout/activity_barchart_noseekbar.xml create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java rename MPChartExample/src/com/xxmassdeveloper/mpchartexample/{RealmDatabaseActivity.java => RealmDatabaseActivityLine.java} (69%) create mode 100644 MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 94759bd9ba..b3c50efd38 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -45,7 +45,8 @@ - + + diff --git a/MPChartExample/res/layout/activity_barchart_noseekbar.xml b/MPChartExample/res/layout/activity_barchart_noseekbar.xml new file mode 100644 index 0000000000..5180e07b78 --- /dev/null +++ b/MPChartExample/res/layout/activity_barchart_noseekbar.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java new file mode 100644 index 0000000000..f1fd98a0dc --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java @@ -0,0 +1,88 @@ +package com.xxmassdeveloper.mpchartexample; + +import android.graphics.Typeface; +import android.os.Bundle; +import android.view.WindowManager; + +import com.github.mikephil.charting.animation.Easing; +import com.github.mikephil.charting.charts.BarChart; +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.BarData; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.realm.implementation.RealmBarDataSet; +import com.github.mikephil.charting.data.realm.implementation.RealmLineDataSet; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; +import com.github.mikephil.charting.utils.ColorTemplate; +import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; +import com.xxmassdeveloper.mpchartexample.notimportant.RealmBaseActivity; + +import java.util.ArrayList; + +import io.realm.RealmResults; + +/** + * Created by Philipp Jahoda on 21/10/15. + */ +public class RealmDatabaseActivityBar extends RealmBaseActivity { + + private BarChart mChart; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, + WindowManager.LayoutParams.FLAG_FULLSCREEN); + setContentView(R.layout.activity_barchart_noseekbar); + + mChart = (BarChart) findViewById(R.id.chart1); + setup(mChart); + } + + @Override + protected void onResume() { + super.onResume(); // setup realm + + // write some demo-data into the realm.io database + writeToDBStack(200); + + // add data to the chart + setData(); + } + + private void setData() { + + RealmResults result = mRealm.allObjects(RealmDemoData.class); + + RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); + set.setValueTextSize(9f); + set.setColors(getColors(set.getStackSize())); + set.setLabel("Realm BarDataSet"); + set.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); + + System.out.println("Stacksize: " + set.getStackSize()); + + ArrayList dataSets = new ArrayList(); + dataSets.add(set); // add the dataset + + // create a data object with the dataset list + BarData data = new BarData(result, "xValue", dataSets); + + // set data + mChart.setData(data); + mChart.animateY(1400, Easing.EasingOption.EaseInOutQuart); + } + + private int[] getColors(int stacksize) { + + // have as many colors as stack-values per entry + int[] colors = new int[stacksize]; + + for (int i = 0; i < stacksize; i++) { + colors[i] = ColorTemplate.VORDIPLOM_COLORS[i]; + } + + return colors; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityLine.java similarity index 69% rename from MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java rename to MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityLine.java index c821e8377d..52820f594b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityLine.java @@ -24,7 +24,7 @@ /** * Created by Philipp Jahoda on 21/10/15. */ -public class RealmDatabaseActivity extends RealmBaseActivity { +public class RealmDatabaseActivityLine extends RealmBaseActivity { private LineChart mChart; @@ -36,34 +36,7 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_linechart_noseekbar); mChart = (LineChart) findViewById(R.id.chart1); - mChart.setDrawGridBackground(false); - - // no description text - mChart.setDescription(""); - mChart.setNoDataTextDescription("You need to provide data for the chart."); - - // enable touch gestures - mChart.setTouchEnabled(true); - - // enable scaling and dragging - mChart.setDragEnabled(true); - mChart.setScaleEnabled(true); - - // if disabled, scaling can be done on x- and y-axis separately - mChart.setPinchZoom(false); - - Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); - - YAxis leftAxis = mChart.getAxisLeft(); - leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setAxisMaxValue(220f); - leftAxis.setAxisMinValue(-50f); - leftAxis.setStartAtZero(false); - leftAxis.setTypeface(tf); - - mChart.getXAxis().setTypeface(tf); - - mChart.getAxisRight().setEnabled(false); + setup(mChart); } @Override diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index ae8959c3c1..15a5817b6f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -1,11 +1,13 @@ package com.xxmassdeveloper.mpchartexample.custom; +import io.realm.RealmList; import io.realm.RealmObject; public class RealmDemoData extends RealmObject { private float value; + private RealmList stackValues; private int xIndex; private String xValue; @@ -24,6 +26,23 @@ public RealmDemoData(float value, int xIndex, String xValue) { this.xValue = xValue; } + /** + * Constructor for stacked bars. + * + * @param stackValues + * @param xIndex + * @param xValue + */ + public RealmDemoData(float[] stackValues, int xIndex, String xValue) { + this.xIndex = xIndex; + this.xValue = xValue; + this.stackValues = new RealmList<>(); + + for(float val : stackValues) { + this.stackValues.add(new RealmFloat(val)); + } + } + public float getValue() { return value; } @@ -32,6 +51,14 @@ public void setValue(float value) { this.value = value; } + public RealmList getStackValues() { + return stackValues; + } + + public void setStackValues(RealmList stackValues) { + this.stackValues = stackValues; + } + public int getxIndex() { return xIndex; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java new file mode 100644 index 0000000000..3752935b70 --- /dev/null +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -0,0 +1,27 @@ +package com.xxmassdeveloper.mpchartexample.custom; + +import io.realm.RealmObject; + +/** + * Created by Philipp Jahoda on 09/11/15. + */ +public class RealmFloat extends RealmObject { + + private float value; + + public RealmFloat() { + + } + + public RealmFloat(float value) { + this.value = value; + } + + public float getValue() { + return value; + } + + public void setValue(float value) { + this.value = value; + } +} diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index eb011ebc2f..4982b61e34 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -40,7 +40,8 @@ import com.xxmassdeveloper.mpchartexample.PieChartActivity; import com.xxmassdeveloper.mpchartexample.R; import com.xxmassdeveloper.mpchartexample.RadarChartActivitry; -import com.xxmassdeveloper.mpchartexample.RealmDatabaseActivity; +import com.xxmassdeveloper.mpchartexample.RealmDatabaseActivityBar; +import com.xxmassdeveloper.mpchartexample.RealmDatabaseActivityLine; import com.xxmassdeveloper.mpchartexample.RealtimeLineChartActivity; import com.xxmassdeveloper.mpchartexample.ScatterChartActivity; import com.xxmassdeveloper.mpchartexample.ScrollViewActivity; @@ -126,7 +127,10 @@ protected void onCreate(Bundle savedInstanceState) { "Chart in ScrollView", "This demonstrates how to use a chart inside a ScrollView.")); objects.add(new ContentItem( - "Realm.io Database", + "Realm.io Database LineChart", + "This demonstrates how to use this library with Realm.io mobile database.")); + objects.add(new ContentItem( + "Realm.io Database BarChart", "This demonstrates how to use this library with Realm.io mobile database.")); MyAdapter adapter = new MyAdapter(this, objects); @@ -248,7 +252,11 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 26: - i = new Intent(this, RealmDatabaseActivity.class); + i = new Intent(this, RealmDatabaseActivityLine.class); + startActivity(i); + break; + case 27: + i = new Intent(this, RealmDatabaseActivityBar.class); startActivity(i); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java index edbbf3a5cd..5737959a88 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/RealmBaseActivity.java @@ -1,5 +1,10 @@ package com.xxmassdeveloper.mpchartexample.notimportant; +import android.graphics.Typeface; + +import com.github.mikephil.charting.charts.BarLineChartBase; +import com.github.mikephil.charting.charts.Chart; +import com.github.mikephil.charting.components.YAxis; import com.xxmassdeveloper.mpchartexample.custom.RealmDemoData; import io.realm.Realm; @@ -12,6 +17,38 @@ public abstract class RealmBaseActivity extends DemoBase { protected Realm mRealm; + protected void setup(BarLineChartBase mChart) { + + mChart.setDrawGridBackground(false); + + // no description text + mChart.setDescription(""); + mChart.setNoDataTextDescription("You need to provide data for the chart."); + + // enable touch gestures + mChart.setTouchEnabled(true); + + // enable scaling and dragging + mChart.setDragEnabled(true); + mChart.setScaleEnabled(true); + + // if disabled, scaling can be done on x- and y-axis separately + mChart.setPinchZoom(false); + + Typeface tf = Typeface.createFromAsset(getAssets(), "OpenSans-Regular.ttf"); + + YAxis leftAxis = mChart.getAxisLeft(); + leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines + leftAxis.setAxisMaxValue(220f); + leftAxis.setAxisMinValue(-50f); + leftAxis.setStartAtZero(false); + leftAxis.setTypeface(tf); + + mChart.getXAxis().setTypeface(tf); + + mChart.getAxisRight().setEnabled(false); + } + @Override protected void onResume() { super.onResume(); @@ -47,4 +84,24 @@ protected void writeToDB(int objectCount) { mRealm.commitTransaction(); } + + protected void writeToDBStack(int objectCount) { + + mRealm.beginTransaction(); + + mRealm.clear(RealmDemoData.class); + + for(int i = 0; i < objectCount; i++) { + + float val1 = 20f + (float) (Math.random() * 50.0); + float val2 = 20f + (float) (Math.random() * 50.0); + float val3 = 20f + (float) (Math.random() * 50.0); + float [] stack = new float[] {val1, val2, val3}; + + RealmDemoData d = new RealmDemoData(stack, i, "" + i); + mRealm.copyToRealm(d); + } + + mRealm.commitTransaction(); + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 4209c8258d..85858b6865 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -6,8 +6,10 @@ import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import io.realm.RealmList; import io.realm.RealmObject; import io.realm.RealmResults; +import io.realm.dynamic.DynamicRealmList; import io.realm.dynamic.DynamicRealmObject; /** @@ -50,10 +52,30 @@ public RealmBarDataSet(RealmResults results, String yValuesField, String xInd @Override public void build(RealmResults results) { - for (T object : results) { + for (T realmObject : results) { - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new BarEntry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); + DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); + + try { + + float value = dynamicObject.getFloat(mValuesField); + mValues.add(new BarEntry(value, dynamicObject.getInt(mIndexField))); + + } catch(IllegalArgumentException e) { + + DynamicRealmList list = dynamicObject.getList(mValuesField); + float [] values = new float[list.size()]; + + int i = 0; + for(DynamicRealmObject o : list) { + values[i] = o.getFloat("value"); + System.out.println("Value: " + values[i]); + i++; + } + mValues.add(new BarEntry(values, dynamicObject.getInt(mIndexField))); + + mStackSize = Math.max(mStackSize, values.length); + } } } From aa2418767364f8aa394264fa598779b21c57256e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 9 Nov 2015 16:50:31 +0100 Subject: [PATCH 0610/1390] Work on supporting stacked entries via realm --- .../RealmDatabaseActivityBar.java | 6 +++--- .../data/realm/base/RealmBaseDataSet.java | 2 +- .../realm/implementation/RealmBarDataSet.java | 20 +++++++++++++++---- .../charting/renderer/LegendRenderer.java | 6 +++--- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java index f1fd98a0dc..d7bda334f9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java @@ -45,7 +45,7 @@ protected void onResume() { super.onResume(); // setup realm // write some demo-data into the realm.io database - writeToDBStack(200); + writeToDBStack(4); // add data to the chart setData(); @@ -56,12 +56,12 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); + System.out.println("Act: " + set.getStackSize()); set.setValueTextSize(9f); set.setColors(getColors(set.getStackSize())); set.setLabel("Realm BarDataSet"); set.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); - - System.out.println("Stacksize: " + set.getStackSize()); + System.out.println("Act: " + set.getStackSize()); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 6cbcacce85..01f387e00a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -45,7 +45,7 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn this.results = results; this.mValuesField = yValuesField; this.mIndexField = xIndexField; - mValues = new ArrayList(); + this.mValues = new ArrayList(); this.results.sort(mIndexField, true); build(this.results); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 85858b6865..6914202cda 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -6,7 +6,6 @@ import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; -import io.realm.RealmList; import io.realm.RealmObject; import io.realm.RealmResults; import io.realm.dynamic.DynamicRealmList; @@ -47,6 +46,8 @@ public class RealmBarDataSet extends RealmBarLineScatterC public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { super(results, yValuesField, xIndexField); + mHighLightColor = Color.rgb(0, 0, 0); + calcStackSize(); } @Override @@ -69,14 +70,14 @@ public void build(RealmResults results) { int i = 0; for(DynamicRealmObject o : list) { values[i] = o.getFloat("value"); - System.out.println("Value: " + values[i]); i++; } - mValues.add(new BarEntry(values, dynamicObject.getInt(mIndexField))); - mStackSize = Math.max(mStackSize, values.length); + mValues.add(new BarEntry(values, dynamicObject.getInt(mIndexField))); } } + + calcStackSize(); } @Override @@ -85,6 +86,17 @@ public void calcMinMax(int start, int end) { // TODO: implement this } + private void calcStackSize() { + + for (int i = 0; i < mValues.size(); i++) { + + float[] vals = mValues.get(i).getVals(); + + if (vals != null && vals.length > mStackSize) + mStackSize = vals.length; + } + } + @Override public int getStackSize() { return mStackSize; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java index 0b96988fe8..467de05975 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LegendRenderer.java @@ -8,9 +8,9 @@ import com.github.mikephil.charting.components.Legend; import com.github.mikephil.charting.data.ChartData; -import com.github.mikephil.charting.data.PieDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.datasets.IDataSet; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.FSize; import com.github.mikephil.charting.utils.Utils; @@ -107,10 +107,10 @@ public void computeLegend(ChartData data) { labels.add(bds.getLabel()); } - } else if (dataSet instanceof PieDataSet) { + } else if (dataSet instanceof IPieDataSet) { List xVals = data.getXVals(); - PieDataSet pds = (PieDataSet) dataSet; + IPieDataSet pds = (IPieDataSet) dataSet; for (int j = 0; j < clrs.size() && j < entryCount && j < xVals.size(); j++) { From f4421699bde4e943b60a6ab536305c4fb1aeab90 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 9 Nov 2015 16:57:18 +0100 Subject: [PATCH 0611/1390] Bugfixing concerning stacked bars --- .../RealmDatabaseActivityBar.java | 7 ++-- .../mpchartexample/custom/RealmFloat.java | 14 ++++---- .../realm/implementation/RealmBarDataSet.java | 34 +++++++++++++++---- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java index d7bda334f9..8e98eb12b5 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealmDatabaseActivityBar.java @@ -45,7 +45,7 @@ protected void onResume() { super.onResume(); // setup realm // write some demo-data into the realm.io database - writeToDBStack(4); + writeToDBStack(200); // add data to the chart setData(); @@ -55,13 +55,12 @@ private void setData() { RealmResults result = mRealm.allObjects(RealmDemoData.class); - RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); - System.out.println("Act: " + set.getStackSize()); + //RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex"); // normal entries + RealmBarDataSet set = new RealmBarDataSet(result, "stackValues", "xIndex", "floatValue"); // stacked entries set.setValueTextSize(9f); set.setColors(getColors(set.getStackSize())); set.setLabel("Realm BarDataSet"); set.setStackLabels(new String[]{"Births", "Divorces", "Marriages"}); - System.out.println("Act: " + set.getStackSize()); ArrayList dataSets = new ArrayList(); dataSets.add(set); // add the dataset diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java index 3752935b70..15b027b3ff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -7,21 +7,21 @@ */ public class RealmFloat extends RealmObject { - private float value; + private float floatValue; public RealmFloat() { } - public RealmFloat(float value) { - this.value = value; + public RealmFloat(float floatValue) { + this.floatValue = floatValue; } - public float getValue() { - return value; + public float getFloatValue() { + return floatValue; } - public void setValue(float value) { - this.value = value; + public void setFloatValue(float value) { + this.floatValue = value; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 6914202cda..eb12410eb7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -16,6 +16,8 @@ */ public class RealmBarDataSet extends RealmBarLineScatterCandleBubbleDataSet implements IBarDataSet { + private String mStackValueFieldName; + /** * space indicator between the bars 0.1f == 10 % */ @@ -47,12 +49,25 @@ public class RealmBarDataSet extends RealmBarLineScatterC public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField) { super(results, yValuesField, xIndexField); mHighLightColor = Color.rgb(0, 0, 0); - calcStackSize(); + buildData(this.results); } - @Override - public void build(RealmResults results) { + /** + * Constructor for supporting stacked values. + * + * @param results + * @param yValuesField + * @param xIndexField + * @param stackValueFieldName + */ + public RealmBarDataSet(RealmResults results, String yValuesField, String xIndexField, String stackValueFieldName) { + super(results, yValuesField, xIndexField); + this.mStackValueFieldName = stackValueFieldName; + mHighLightColor = Color.rgb(0, 0, 0); + buildData(this.results); + } + private void buildData(RealmResults results) { for (T realmObject : results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); @@ -62,14 +77,14 @@ public void build(RealmResults results) { float value = dynamicObject.getFloat(mValuesField); mValues.add(new BarEntry(value, dynamicObject.getInt(mIndexField))); - } catch(IllegalArgumentException e) { + } catch (IllegalArgumentException e) { DynamicRealmList list = dynamicObject.getList(mValuesField); - float [] values = new float[list.size()]; + float[] values = new float[list.size()]; int i = 0; - for(DynamicRealmObject o : list) { - values[i] = o.getFloat("value"); + for (DynamicRealmObject o : list) { + values[i] = o.getFloat(mStackValueFieldName); i++; } @@ -80,6 +95,11 @@ public void build(RealmResults results) { calcStackSize(); } + @Override + public void build(RealmResults results) { + // TODO: make this cleaner + } + @Override public void calcMinMax(int start, int end) { From 78aa0b034c22f17a11ff52bceb0c55d8193dd818 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 10 Nov 2015 13:02:52 +0100 Subject: [PATCH 0612/1390] Implement constructors to support realm-xvalues --- .../src/com/github/mikephil/charting/data/BubbleData.java | 7 +++++++ .../src/com/github/mikephil/charting/data/CandleData.java | 7 +++++++ .../src/com/github/mikephil/charting/data/PieData.java | 7 +++++++ .../src/com/github/mikephil/charting/data/RadarData.java | 7 +++++++ .../src/com/github/mikephil/charting/data/ScatterData.java | 7 +++++++ 5 files changed, 35 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java index 53945ac0e5..ae38135b3f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BubbleData.java @@ -6,8 +6,15 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + public class BubbleData extends BarLineScatterCandleBubbleData { + public BubbleData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public BubbleData() { super(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java index a1c797b4fa..ad1a036d06 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/CandleData.java @@ -5,8 +5,15 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + public class CandleData extends BarLineScatterCandleBubbleData { + public CandleData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public CandleData() { super(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 06922829a9..1f150d1d49 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -6,6 +6,9 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + /** * A PieData object can only represent one DataSet. Unlike all other charts, the * legend labels of the PieChart are created from the x-values array, and not @@ -16,6 +19,10 @@ */ public class PieData extends ChartData { + public PieData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public PieData() { super(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java index 48494d3d65..e1237bb5b9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/RadarData.java @@ -6,6 +6,9 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + /** * Data container for the RadarChart. * @@ -13,6 +16,10 @@ */ public class RadarData extends ChartData { + public RadarData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public RadarData() { super(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java index 99422dd916..eb0c9d9489 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ScatterData.java @@ -6,8 +6,15 @@ import java.util.ArrayList; import java.util.List; +import io.realm.RealmObject; +import io.realm.RealmResults; + public class ScatterData extends BarLineScatterCandleBubbleData { + public ScatterData(RealmResults result, String xValuesField, List dataSets) { + super(toXVals(result, xValuesField), dataSets); + } + public ScatterData() { super(); } From 67c4d41939e337b850260db95f5a4208805c2064 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 16 Nov 2015 10:47:07 +0100 Subject: [PATCH 0613/1390] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 6c0f46ed53..03e15abeb9 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ Remember: *It's all about the looks.* ![alt tag](https://raw.github.com/PhilJay/MPChart/master/design/feature_graphic.png) -**MPAndroidChart** is a powerful & easy to use chart library for Android, supporting line-, bar-, scatter-, candlestick-, bubble-, pie- and radarcharts (spider web), as well as scaling, dragging (panning), selecting and animations. Works on **Android 2.2 (API level 8)** and upwards. +**MPAndroidChart** is a powerful & easy to use chart library for Android, supporting line-, bar-, scatter-, candlestick-, bubble-, pie- and radarcharts (spider web), as well as scaling, dragging (panning), selecting and animations. Works on **Android 2.2 (API level 8)** and upwards. -An **iOS** version of this library is now available, go check it out: [**ios-charts**](https://github.com/danielgindi/ios-charts) +This library allows **cross-platform** development between Android and iOS as an iOS version of this library is also available: [**ios-charts**](https://github.com/danielgindi/ios-charts) Are you using this library? Let me know about it and I will add your project to the [**references**](https://github.com/PhilJay/MPAndroidChart/wiki/References). @@ -134,9 +134,9 @@ Features Usage ======= -In order to use the library, there are 4 options: +In order to use the library, there are 4 different options: -**1. Gradle dependency** +**1. Gradle dependency** (recommended) - Add the following to your `build.gradle`: ```gradle @@ -170,9 +170,9 @@ dependencies { - Start using the library **4. clone whole repository** - - Open your **commandline-input** and navigate to your desired destination folder (where you want to put the library) - - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library project as well as the example project) - - Import the library folder (`MPChartLib`) into Android Studio or your Eclipse workspace + - Open your **commandline-input** and navigate to the desired destination folder on your machine (where you want to place the library) + - Use the command `git clone https://github.com/PhilJay/MPAndroidChart.git` to download the full MPAndroidChart repository to your computer (this includes the folder of the library as well as the folder of the example project) + - Import the library folder (`MPChartLib`) into Android Studio (recommended) or your Eclipse workspace - Add it as a reference to your project: - [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) - [managing projects from Android Studio](https://developer.android.com/sdk/installing/create-project.html) From 6b2bfddfda8af002b4dd2f90a3a6f5fbdd4f2bb9 Mon Sep 17 00:00:00 2001 From: Brad Barnhill Date: Thu, 19 Nov 2015 22:06:47 -0600 Subject: [PATCH 0614/1390] upgrade dependencies (gradle plugin 1.5.0, appcompat 23.1.1, build tools 23.0.2, gradle 2.9, android-maven plugin 1.3), remove unnecessary version definitions in manifest, auto generated wrapper files --- MPChartExample/build.gradle | 6 +++--- MPChartLib/AndroidManifest.xml | 9 +-------- MPChartLib/build.gradle | 5 +++-- build.gradle | 8 ++++++-- gradle/wrapper/gradle-wrapper.jar | Bin 49896 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++-- gradlew | 10 +++------- 7 files changed, 18 insertions(+), 24 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 580d094378..ab8765d829 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -2,7 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion 23 - buildToolsVersion '23.0.1' + buildToolsVersion '23.0.2' defaultConfig { minSdkVersion 8 targetSdkVersion 23 @@ -38,7 +38,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:1.3.1' + classpath 'com.android.tools.build:gradle:1.5.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -52,6 +52,6 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project - compile 'com.android.support:appcompat-v7:23.0.0' + compile 'com.android.support:appcompat-v7:23.1.1' //compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' } diff --git a/MPChartLib/AndroidManifest.xml b/MPChartLib/AndroidManifest.xml index bda2ca4cb0..d75f87c7e2 100644 --- a/MPChartLib/AndroidManifest.xml +++ b/MPChartLib/AndroidManifest.xml @@ -1,12 +1,5 @@ - - - + no space, maximum 45, minimum 0 (no space) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 9b9d2856ab..3df67095fe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -11,8 +11,28 @@ /** * Created by Philipp Jahoda on 07/11/15. */ -public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { +public class RealmRadarDataSet extends RealmLineRadarDataSet implements IRadarDataSet { + /** + * Constructor for creating a RadarDataSet with realm data. + * + * @param result the queried results from the realm database + * @param yValuesField the name of the field in your data object that represents the y-value + */ + public RealmRadarDataSet(RealmResults result, String yValuesField) { + super(result, yValuesField); + + build(this.results); + calcMinMax(0, results.size()); + } + + /** + * Constructor for creating a RadarDataSet with realm data. + * + * @param result the queried results from the realm database + * @param yValuesField the name of the field in your data object that represents the y-value + * @param xIndexField the name of the field in your data object that represents the x-index + */ public RealmRadarDataSet(RealmResults result, String yValuesField, String xIndexField) { super(result, yValuesField, xIndexField); @@ -22,11 +42,6 @@ public RealmRadarDataSet(RealmResults result, String yValuesField, String xIn @Override public void build(RealmResults results) { - - for (T object : results) { - - DynamicRealmObject dynamicObject = new DynamicRealmObject(object); - mValues.add(new Entry(dynamicObject.getFloat(mValuesField), dynamicObject.getInt(mIndexField))); - } + super.build(results); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 80634eb0c9..30beb750f4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -28,7 +28,7 @@ public class RealmScatterDataSet extends RealmLineScatter /** - * Constructor for creating a LineDataSet with realm data. + * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database * @param yValuesField the name of the field in your data object that represents the y-value @@ -41,7 +41,7 @@ public RealmScatterDataSet(RealmResults result, String yValuesField) { } /** - * Constructor for creating a LineDataSet with realm data. + * Constructor for creating a ScatterDataSet with realm data. * * @param result the queried results from the realm database * @param yValuesField the name of the field in your data object that represents the y-value From 59620060da844046f32a93855766d94f3e5b3b2a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 25 Dec 2015 16:48:30 +0100 Subject: [PATCH 0650/1390] Add documentation --- .../charting/data/realm/base/RealmBaseDataSet.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 0917580f6e..a0a62ad103 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -68,7 +68,7 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn this.mValues = new ArrayList(); if (mIndexField != null) ; - this.results.sort(mIndexField, true); + this.results.sort(mIndexField, true); } /** @@ -281,6 +281,11 @@ public RealmResults getResults() { return results; } + /** + * Returns the fieldname that represents the "y-values" in the realm-data. + * + * @return + */ public String getValuesField() { return mValuesField; } @@ -294,6 +299,11 @@ public void setValuesField(String yValuesField) { this.mValuesField = yValuesField; } + /** + * Returns the fieldname that represents the "x-index" in the realm-data. + * + * @return + */ public String getIndexField() { return mIndexField; } From b65086f7df8259b86f04ca6d27860d3d4b0d9927 Mon Sep 17 00:00:00 2001 From: Mike Monteith Date: Mon, 28 Dec 2015 10:21:40 +0000 Subject: [PATCH 0651/1390] Fixes #1258 --- .../com/github/mikephil/charting/renderer/PieChartRenderer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index eb2669f97b..c183add9c2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -246,7 +246,7 @@ public void drawValues(Canvas c) { public void drawExtras(Canvas c) { // drawCircles(c); drawHole(c); - c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); + c.drawBitmap(mDrawBitmap, 0, 0, null); drawCenterText(c); } From c2fbd7ccf1c1c401ff6688d40d4bf876a12c9563 Mon Sep 17 00:00:00 2001 From: Mike Monteith Date: Wed, 30 Dec 2015 20:18:52 +0000 Subject: [PATCH 0652/1390] Pie animation should be applied after rotationAngle --- .../charting/renderer/PieChartRenderer.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index c183add9c2..5f27b407b5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -128,7 +128,8 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, IPieDataSet dataSet) { - float angle = mChart.getRotationAngle(); + float angle = 0; + float rotationAngle = mChart.getRotationAngle(); float[] drawAngles = mChart.getDrawAngles(); @@ -147,7 +148,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawArc(mChart.getCircleBox(), - (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), + rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), (newangle - sliceSpace / 2f) * mAnimator.getPhaseY(), true, mRenderPaint); } @@ -205,13 +206,14 @@ public void drawValues(Canvas c) { // offset needed to center the drawn text in the slice float offset = drawAngles[cnt] / 2; + float angle = (absoluteAngles[cnt] - offset) * mAnimator.getPhaseY(); // calculate the text position float x = (float) (r - * Math.cos(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) - * mAnimator.getPhaseY())) + center.x); + * Math.cos(Math.toRadians(rotationAngle) + Math.toRadians(angle)) + + center.x); float y = (float) (r - * Math.sin(Math.toRadians((rotationAngle + absoluteAngles[cnt] - offset) - * mAnimator.getPhaseY())) + center.y); + * Math.sin(Math.toRadians(rotationAngle) + Math.toRadians(angle)) + + center.y); float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() / data.getYValueSum() * 100f : entry.getVal(); From 4807eca1457cfe2947574de12227d9b917262a7e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 3 Jan 2016 20:37:06 +0200 Subject: [PATCH 0653/1390] Fixes y-offset when rendering rotate-able text --- .../github/mikephil/charting/utils/Utils.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index e9047b07fa..d4c36767a4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -520,19 +520,26 @@ public static float getNormalizedAngle(float angle) { } private static Rect mDrawTextRectBuffer = new Rect(); + private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics(); - public static void drawText(Canvas c, String text, float x, float y, Paint paint, PointF anchor, float angleDegrees) { + public static void drawText(Canvas c, String text, float x, float y, + Paint paint, + PointF anchor, float angleDegrees) { float drawOffsetX = 0.f; float drawOffsetY = 0.f; + final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer); + paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; - // Android sets the top = - (lineheight), and we want to normalize it to the center - drawOffsetY -= mDrawTextRectBuffer.top; + // Android does not snap the bounds to line boundaries, + // and draws from bottom to top. + // And we want to normalize it. + drawOffsetY += lineHeight; // To have a consistent point of reference, we always draw left-aligned Paint.Align originalTextAlign = paint.getTextAlign(); @@ -542,7 +549,7 @@ public static void drawText(Canvas c, String text, float x, float y, Paint paint // Move the text drawing rect in a way that it always rotates around its center drawOffsetX -= mDrawTextRectBuffer.width() * 0.5f; - drawOffsetY -= mDrawTextRectBuffer.height() * 0.5f; + drawOffsetY -= lineHeight * 0.5f; float translateX = x; float translateY = y; @@ -551,7 +558,7 @@ public static void drawText(Canvas c, String text, float x, float y, Paint paint if (anchor.x != 0.5f || anchor.y != 0.5f) { final FSize rotatedSize = getSizeOfRotatedRectangleByDegrees( mDrawTextRectBuffer.width(), - mDrawTextRectBuffer.height(), + lineHeight, angleDegrees); translateX -= rotatedSize.width * (anchor.x - 0.5f); @@ -570,7 +577,7 @@ public static void drawText(Canvas c, String text, float x, float y, Paint paint if (anchor.x != 0.f || anchor.y != 0.f) { drawOffsetX -= mDrawTextRectBuffer.width() * anchor.x; - drawOffsetY -= mDrawTextRectBuffer.height() * anchor.y; + drawOffsetY -= lineHeight * anchor.y; } drawOffsetX += x; From 3074744db7bb1fccbaac17f4737742c5e27ad465 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 3 Jan 2016 21:00:57 +0200 Subject: [PATCH 0654/1390] Preparations for rotated multiline text --- .../github/mikephil/charting/utils/Utils.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index d4c36767a4..d389012d96 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -9,6 +9,9 @@ import android.graphics.PointF; import android.graphics.Rect; import android.os.Build; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; @@ -589,6 +592,99 @@ public static void drawText(Canvas c, String text, float x, float y, paint.setTextAlign(originalTextAlign); } + public static void drawMultilineText(Canvas c, StaticLayout textLayout, + float x, float y, + TextPaint paint, + PointF anchor, float angleDegrees) { + + float drawOffsetX = 0.f; + float drawOffsetY = 0.f; + float drawWidth; + float drawHeight; + + final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer); + + drawWidth = textLayout.getWidth(); + drawHeight = textLayout.getLineCount() * lineHeight; + + // Android sometimes has pre-padding + drawOffsetX -= mDrawTextRectBuffer.left; + + // Android does not snap the bounds to line boundaries, + // and draws from bottom to top. + // And we want to normalize it. + drawOffsetY += drawHeight; + + // To have a consistent point of reference, we always draw left-aligned + Paint.Align originalTextAlign = paint.getTextAlign(); + paint.setTextAlign(Paint.Align.LEFT); + + if (angleDegrees != 0.f) { + + // Move the text drawing rect in a way that it always rotates around its center + drawOffsetX -= drawWidth * 0.5f; + drawOffsetY -= drawHeight * 0.5f; + + float translateX = x; + float translateY = y; + + // Move the "outer" rect relative to the anchor, assuming its centered + if (anchor.x != 0.5f || anchor.y != 0.5f) { + final FSize rotatedSize = getSizeOfRotatedRectangleByDegrees( + drawWidth, + drawHeight, + angleDegrees); + + translateX -= rotatedSize.width * (anchor.x - 0.5f); + translateY -= rotatedSize.height * (anchor.y - 0.5f); + } + + c.save(); + c.translate(translateX, translateY); + c.rotate(angleDegrees); + + c.translate(drawOffsetX, drawOffsetY); + textLayout.draw(c); + + c.restore(); + } + else { + if (anchor.x != 0.f || anchor.y != 0.f) { + + drawOffsetX -= drawWidth * anchor.x; + drawOffsetY -= drawHeight * anchor.y; + } + + drawOffsetX += x; + drawOffsetY += y; + + c.save(); + + c.translate(drawOffsetX, drawOffsetY); + textLayout.draw(c); + + c.restore(); + } + + paint.setTextAlign(originalTextAlign); + } + + public static void drawMultilineText(Canvas c, String text, + float x, float y, + TextPaint paint, + FSize constrainedToSize, + PointF anchor, float angleDegrees) { + + StaticLayout textLayout = new StaticLayout( + text, 0, text.length(), + paint, + (int) Math.max(Math.ceil(constrainedToSize.width), 1.f), + Layout.Alignment.ALIGN_NORMAL, 1.f, 0.f, false); + + + drawMultilineText(c, textLayout, x, y, paint, anchor, angleDegrees); + } + public static FSize getSizeOfRotatedRectangleByDegrees(FSize rectangleSize, float degrees) { final float radians = degrees * FDEG2RAD; From d33c1b1558b8e7cd4f54c544256a0ce0f9cb6bd6 Mon Sep 17 00:00:00 2001 From: Matias Hernandez Date: Mon, 4 Jan 2016 18:47:53 -0300 Subject: [PATCH 0655/1390] Remove PieChart.setCenterText() overloads. Replaced them by a single method receiving CharSequence. --- .../mikephil/charting/charts/PieChart.java | 21 +++++-------------- .../charting/renderer/PieChartRenderer.java | 5 ++--- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index a206685e91..ebafd89b0a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -9,7 +9,6 @@ import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.Typeface; -import android.text.SpannableString; import android.util.AttributeSet; import com.github.mikephil.charting.data.Entry; @@ -67,7 +66,7 @@ public class PieChart extends PieRadarChartBase { /** * variable for the text that is drawn in the center of the pie-chart */ - private SpannableString mCenterText = new SpannableString(""); + private CharSequence mCenterText = ""; /** * indicates the size of the hole in the center of the piechart, default: @@ -371,33 +370,23 @@ public boolean isDrawHoleEnabled() { } /** - * Sets the text SpannableString that is displayed in the center of the PieChart. + * Sets the text String that is displayed in the center of the PieChart. * * @param text */ - public void setCenterText(SpannableString text) { - + public void setCenterText(CharSequence text) { if (text == null) - mCenterText = new SpannableString(""); + mCenterText = ""; else mCenterText = text; } - /** - * Sets the text String that is displayed in the center of the PieChart. - * - * @param text - */ - public void setCenterText(String text) { - setCenterText(new SpannableString(text)); - } - /** * returns the text that is drawn in the center of the pie-chart * * @return */ - public SpannableString getCenterText() { + public CharSequence getCenterText() { return mCenterText; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index c183add9c2..b4ceb7dcce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -10,7 +10,6 @@ import android.graphics.PointF; import android.graphics.RectF; import android.text.Layout; -import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; @@ -45,7 +44,7 @@ public class PieChartRenderer extends DataRenderer { private TextPaint mCenterTextPaint; private StaticLayout mCenterTextLayout; - private SpannableString mCenterTextLastValue; + private CharSequence mCenterTextLastValue; private RectF mCenterTextLastBounds = new RectF(); private RectF[] mRectBuffer = {new RectF(), new RectF(), new RectF()}; @@ -291,7 +290,7 @@ protected void drawHole(Canvas c) { */ protected void drawCenterText(Canvas c) { - SpannableString centerText = mChart.getCenterText(); + CharSequence centerText = mChart.getCenterText(); if (mChart.isDrawCenterTextEnabled() && centerText != null) { From 2fc56c5fc7ca8e5a22d5a0dcda59418c6c1aa5a4 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 Jan 2016 14:17:48 +0100 Subject: [PATCH 0656/1390] Improve example --- .../mpchartexample/listviewitems/PieChartItem.java | 2 +- .../xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java index fb09474b56..f803eb8072 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/listviewitems/PieChartItem.java @@ -79,7 +79,7 @@ public View getView(int position, View convertView, Context c) { // do not forget to refresh the chart // holder.chart.invalidate(); - holder.chart.animateXY(900, 900); + holder.chart.animateY(900); return convertView; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java index d9532f3e7b..7066d8167b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmWikiExample.java @@ -39,6 +39,9 @@ protected void onCreate(Bundle savedInstanceState) { setup(lineChart); setup(barChart); + lineChart.setExtraBottomOffset(5f); + barChart.setExtraBottomOffset(5f); + lineChart.getAxisLeft().setDrawGridLines(false); lineChart.getXAxis().setDrawGridLines(false); barChart.getAxisLeft().setDrawGridLines(false); From c44761016e4ab34e347561539aa7515404840992 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 5 Jan 2016 14:20:54 +0100 Subject: [PATCH 0657/1390] Update version and sdk --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index b6e15fc91a..906001d44c 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,12 +1,12 @@ + android:targetSdkVersion="23" /> Date: Fri, 8 Jan 2016 15:54:10 +0200 Subject: [PATCH 0658/1390] That's too many toRadians calls just for adding numbers --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 295ee9d3ca..932bc7da84 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -208,10 +208,10 @@ public void drawValues(Canvas c) { float angle = (absoluteAngles[cnt] - offset) * mAnimator.getPhaseY(); // calculate the text position float x = (float) (r - * Math.cos(Math.toRadians(rotationAngle) + Math.toRadians(angle)) + * Math.cos(Math.toRadians(rotationAngle + angle)) + center.x); float y = (float) (r - * Math.sin(Math.toRadians(rotationAngle) + Math.toRadians(angle)) + * Math.sin(Math.toRadians(rotationAngle + angle)) + center.y); float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() From a7dda129ffb63fb9f6ca7066e4e6cf66c8e294a9 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Jan 2016 15:56:15 +0200 Subject: [PATCH 0659/1390] Renamed variables to be more consistent --- .../charting/renderer/PieChartRenderer.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 932bc7da84..249cb5180c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -134,7 +134,7 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { for (int j = 0; j < dataSet.getEntryCount(); j++) { - float newangle = drawAngles[j]; + float sliceAngle = drawAngles[j]; float sliceSpace = dataSet.getSliceSpace(); Entry e = dataSet.getEntryForIndex(j); @@ -148,12 +148,12 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawArc(mChart.getCircleBox(), rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), - (newangle - sliceSpace / 2f) * mAnimator.getPhaseY(), + (sliceAngle - sliceSpace / 2f) * mAnimator.getPhaseY(), true, mRenderPaint); } } - angle += newangle * mAnimator.getPhaseX(); + angle += sliceAngle * mAnimator.getPhaseX(); } } @@ -413,7 +413,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { angle *= mAnimator.getPhaseX(); - float sliceDegrees = drawAngles[xIndex]; + float sliceAngle = drawAngles[xIndex]; float shift = set.getSelectionShift(); RectF circleBox = mChart.getCircleBox(); @@ -433,7 +433,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // redefine the rect that contains the arc so that the // highlighted pie is not cut off - mBitmapCanvas.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceDegrees + mBitmapCanvas.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceAngle * mAnimator.getPhaseY() - set.getSliceSpace() / 2f, true, mRenderPaint); } @@ -465,7 +465,7 @@ protected void drawRoundedSlices(Canvas c) { for (int j = 0; j < dataSet.getEntryCount(); j++) { - float newangle = drawAngles[j]; + float sliceAngle = drawAngles[j]; Entry e = dataSet.getEntryForIndex(j); @@ -473,17 +473,17 @@ protected void drawRoundedSlices(Canvas c) { if ((Math.abs(e.getVal()) > 0.000001)) { float x = (float) ((r - circleRadius) - * Math.cos(Math.toRadians((angle + newangle) + * Math.cos(Math.toRadians((angle + sliceAngle) * mAnimator.getPhaseY())) + center.x); float y = (float) ((r - circleRadius) - * Math.sin(Math.toRadians((angle + newangle) + * Math.sin(Math.toRadians((angle + sliceAngle) * mAnimator.getPhaseY())) + center.y); mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawCircle(x, y, circleRadius, mRenderPaint); } - angle += newangle * mAnimator.getPhaseX(); + angle += sliceAngle * mAnimator.getPhaseX(); } } From a7b038a43e445b3625692e0b84af3e6f1630c944 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 8 Jan 2016 15:58:09 +0200 Subject: [PATCH 0660/1390] Fixed highlighted pie animation --- .../mikephil/charting/renderer/PieChartRenderer.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 249cb5180c..0b07249cec 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -414,6 +414,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { angle *= mAnimator.getPhaseX(); float sliceAngle = drawAngles[xIndex]; + float sliceSpace = set.getSliceSpace(); float shift = set.getSelectionShift(); RectF circleBox = mChart.getCircleBox(); @@ -433,9 +434,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // redefine the rect that contains the arc so that the // highlighted pie is not cut off - mBitmapCanvas.drawArc(highlighted, angle + set.getSliceSpace() / 2f, sliceAngle - * mAnimator.getPhaseY() - - set.getSliceSpace() / 2f, true, mRenderPaint); + mBitmapCanvas.drawArc(highlighted, + rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), + (sliceAngle - sliceSpace / 2f) * mAnimator.getPhaseY(), + true, mRenderPaint); } } From b2adb97cac3cd48d0f1f20b3a86c9accf285569e Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Jan 2016 08:12:23 +0200 Subject: [PATCH 0661/1390] Make highlighter public for extensibility See also: https://github.com/danielgindi/ios-charts/pull/567 --- .../com/github/mikephil/charting/charts/BarChart.java | 4 ++-- .../mikephil/charting/charts/BarLineChartBase.java | 4 ++-- .../src/com/github/mikephil/charting/charts/Chart.java | 9 +++++++++ .../github/mikephil/charting/charts/CombinedChart.java | 2 +- .../mikephil/charting/charts/HorizontalBarChart.java | 4 ++-- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 41f2da45c4..c2dc39b3c3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -59,7 +59,7 @@ protected void init() { mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); - mHighlighter = new BarHighlighter(this); + setHighlighter(new BarHighlighter(this)); mXChartMin = -0.5f; } @@ -94,7 +94,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } else - return mHighlighter.getHighlight(x, y); + return getHighlighter().getHighlight(x, y); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index eb2b552c28..ff10e087d5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -164,7 +164,7 @@ protected void init() { mXAxisRenderer = new XAxisRenderer(mViewPortHandler, mXAxis, mLeftAxisTransformer); - mHighlighter = new ChartHighlighter(this); + setHighlighter(new ChartHighlighter(this)); mChartTouchListener = new BarLineChartTouchListener(this, mViewPortHandler.getMatrixTouch()); @@ -1158,7 +1158,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } else - return mHighlighter.getHighlight(x, y); + return getHighlighter().getHighlight(x, y); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index a7a97e6152..1f441f6f3e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1445,6 +1445,15 @@ public void setRenderer(DataRenderer renderer) { mRenderer = renderer; } + public ChartHighlighter getHighlighter() { + return mHighlighter; + } + + public void setHighlighter(ChartHighlighter highlighter) { + + mHighlighter = highlighter; + } + @Override public PointF getCenterOfView() { return getCenter(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java index b946e6470a..caa011203a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CombinedChart.java @@ -73,7 +73,7 @@ public CombinedChart(Context context, AttributeSet attrs, int defStyle) { protected void init() { super.init(); - mHighlighter = new CombinedHighlighter(this); + setHighlighter(new CombinedHighlighter(this)); // mRenderer = new CombinedChartRenderer(this, mAnimator, // mViewPortHandler); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 1b1d2dc7d4..6172aa7d8a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -49,7 +49,7 @@ protected void init() { mRightAxisTransformer = new TransformerHorizontalBarChart(mViewPortHandler); mRenderer = new HorizontalBarChartRenderer(this, mAnimator, mViewPortHandler); - mHighlighter = new HorizontalBarHighlighter(this); + setHighlighter(new HorizontalBarHighlighter(this)); mAxisRendererLeft = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisLeft, mLeftAxisTransformer); mAxisRendererRight = new YAxisRendererHorizontalBarChart(mViewPortHandler, mAxisRight, mRightAxisTransformer); @@ -224,7 +224,7 @@ public Highlight getHighlightByTouchPoint(float x, float y) { Log.e(LOG_TAG, "Can't select by touch. No data set."); return null; } else - return mHighlighter.getHighlight(y, x); // switch x and y + return getHighlighter().getHighlight(y, x); // switch x and y } /** From 403b40d573ea2b627f9c9d099883726b0672d011 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Jan 2016 08:22:35 +0200 Subject: [PATCH 0662/1390] Fixes base angle for rotate highlight in pie chart --- .../mikephil/charting/renderer/PieChartRenderer.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 0b07249cec..a53ed9e105 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -407,12 +407,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; if (xIndex == 0) - angle = rotationAngle; + angle = 0.f; else - angle = rotationAngle + absoluteAngles[xIndex - 1]; - - angle *= mAnimator.getPhaseX(); - + angle = absoluteAngles[xIndex - 1] * mAnimator.getPhaseX(); + float sliceAngle = drawAngles[xIndex]; float sliceSpace = set.getSliceSpace(); From cb78d48f3ca0ae7cf0bc1568a4c4161d05f25529 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Sun, 10 Jan 2016 22:47:48 +0200 Subject: [PATCH 0663/1390] Fixes minor docs typo --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index eb2b552c28..efa6e9127f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -769,7 +769,7 @@ public void setVisibleXRangeMaximum(float maxXRange) { /** * Sets the size of the area (range on the x-axis) that should be minimum * visible at once (no further zooming in allowed). If this is e.g. set to - * 10, no more than 10 values on the x-axis can be viewed at once without + * 10, no less than 10 values on the x-axis can be viewed at once without * scrolling. * * @param minXRange The minimum visible range of x-values. From ae7959ff8d396cfd64573d13f493c3301e9cabc1 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 10 Jan 2016 23:08:55 +0100 Subject: [PATCH 0664/1390] Add documentation for setHighlighter(...) method --- .../mikephil/charting/charts/Chart.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 1f441f6f3e..e57bd56d09 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -574,7 +574,7 @@ public void highlightValue(Highlight highlight) { * highlightValues(...), this generates a callback to the * OnChartValueSelectedListener. * - * @param high - the highlight object + * @param high - the highlight object * @param callListener - call the listener */ public void highlightValue(Highlight high, boolean callListener) { @@ -1449,6 +1449,12 @@ public ChartHighlighter getHighlighter() { return mHighlighter; } + /** + * Sets a custom highligher object for the chart that handles / processes + * all highlight touch events performed on the chart-view. + * + * @param highlighter + */ public void setHighlighter(ChartHighlighter highlighter) { mHighlighter = highlighter; @@ -1524,11 +1530,11 @@ public boolean saveToPath(String title, String pathOnSD) { * compression must be set for JPEG only. 0 == maximum compression, 100 = low * compression (high quality). NOTE: Needs permission WRITE_EXTERNAL_STORAGE * - * @param fileName e.g. "my_image" - * @param subFolderPath e.g. "ChartPics" + * @param fileName e.g. "my_image" + * @param subFolderPath e.g. "ChartPics" * @param fileDescription e.g. "Chart details" - * @param format e.g. Bitmap.CompressFormat.PNG - * @param quality e.g. 50, min = 0, max = 100 + * @param format e.g. Bitmap.CompressFormat.PNG + * @param quality e.g. 50, min = 0, max = 100 * @return returns true if saving was successful, false if not */ public boolean saveToGallery(String fileName, String subFolderPath, String fileDescription, Bitmap.CompressFormat format, int quality) { @@ -1552,7 +1558,7 @@ public boolean saveToGallery(String fileName, String subFolderPath, String fileD mimeType = "image/png"; if (!fileName.endsWith(".png")) fileName += ".png"; - break; + break; case WEBP: mimeType = "image/webp"; if (!fileName.endsWith(".webp")) @@ -1610,7 +1616,7 @@ public boolean saveToGallery(String fileName, String subFolderPath, String fileD * @return returns true if saving was successful, false if not */ public boolean saveToGallery(String fileName, int quality) { - return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.JPEG, quality); + return saveToGallery(fileName, "", "MPAndroidChart-Library Save", Bitmap.CompressFormat.JPEG, quality); } /** From d20928ab0c18bf53c20dd1ce172ab836eae50720 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Mon, 11 Jan 2016 22:57:03 +0200 Subject: [PATCH 0665/1390] Minor performance improvement in pie chart On large datasets - this will spare many loops over the data just to sum --- .../mikephil/charting/charts/PieChart.java | 17 +++++++++++++++-- .../charting/renderer/PieChartRenderer.java | 5 ++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index ebafd89b0a..9f7255eb6e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -200,6 +200,8 @@ private void calcAngles() { mDrawAngles = new float[mData.getYValCount()]; mAbsoluteAngles = new float[mData.getYValCount()]; + float yValueSum = mData.getYValueSum(); + List dataSets = mData.getDataSets(); int cnt = 0; @@ -210,7 +212,7 @@ private void calcAngles() { for (int j = 0; j < set.getEntryCount(); j++) { - mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getVal())); + mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getVal()), yValueSum); if (cnt == 0) { mAbsoluteAngles[cnt] = mDrawAngles[cnt]; @@ -255,7 +257,18 @@ public boolean needsHighlight(int xIndex, int dataSetIndex) { * @return */ private float calcAngle(float value) { - return value / mData.getYValueSum() * mMaxAngle; + return calcAngle(value, mData.getYValueSum()); + } + + /** + * calculates the needed angle for a given value + * + * @param value + * @param yValueSum + * @return + */ + private float calcAngle(float value, float yValueSum) { + return value / yValueSum * mMaxAngle; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index a53ed9e105..357c9bf99a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -178,6 +178,9 @@ public void drawValues(Canvas c) { PieData data = mChart.getData(); List dataSets = data.getDataSets(); + + float yValueSum = data.getYValueSum(); + boolean drawXVals = mChart.isDrawSliceTextEnabled(); int cnt = 0; @@ -215,7 +218,7 @@ public void drawValues(Canvas c) { + center.y); float value = mChart.isUsePercentValuesEnabled() ? entry.getVal() - / data.getYValueSum() * 100f : entry.getVal(); + / yValueSum * 100f : entry.getVal(); ValueFormatter formatter = dataSet.getValueFormatter(); From 9379008893a1d559387b5a92976c60642123d0d6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 13 Jan 2016 18:07:17 +0100 Subject: [PATCH 0666/1390] Add documentation --- .../src/com/github/mikephil/charting/data/PieData.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java index 06922829a9..9a3151e6c4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/PieData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/PieData.java @@ -63,6 +63,12 @@ public IPieDataSet getDataSet() { return mDataSets.get(0); } + /** + * The PieData object can only have one DataSet. Use getDataSet() method instead. + * + * @param index + * @return + */ @Override public IPieDataSet getDataSetByIndex(int index) { return index == 0 ? getDataSet() : null; From 989c1ab64c25632d4f882941f9adb71010597de4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Fri, 15 Jan 2016 16:26:34 +0200 Subject: [PATCH 0667/1390] Renamed "circle size" to "circle radius", deprecated set/getCircleSize --- .../mpchartexample/CombinedChartActivity.java | 2 +- .../CubicLineChartActivity.java | 2 +- .../mpchartexample/DrawChartActivity.java | 2 +- .../DynamicalAddingActivity.java | 4 +- .../InvertedLineChartActivity.java | 2 +- .../mpchartexample/LineChartActivity1.java | 2 +- .../mpchartexample/LineChartActivity2.java | 4 +- .../LineChartActivityColored.java | 2 +- .../ListViewMultiChartActivity.java | 4 +- .../MultiLineChartActivity.java | 2 +- .../RealtimeLineChartActivity.java | 2 +- .../fragments/SimpleFragment.java | 8 ++-- .../mikephil/charting/data/LineDataSet.java | 42 +++++++++++++++---- .../implementation/RealmLineDataSet.java | 2 +- .../interfaces/datasets/ILineDataSet.java | 2 +- .../charting/renderer/LineChartRenderer.java | 6 +-- 16 files changed, 56 insertions(+), 32 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java index 4a7444a14f..b2e4c7a4e0 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CombinedChartActivity.java @@ -90,7 +90,7 @@ private LineData generateLineData() { set.setColor(Color.rgb(240, 238, 70)); set.setLineWidth(2.5f); set.setCircleColor(Color.rgb(240, 238, 70)); - set.setCircleSize(5f); + set.setCircleRadius(5f); set.setFillColor(Color.rgb(240, 238, 70)); set.setDrawCubic(true); set.setDrawValues(true); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 3f2192139e..0cf43fe45d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -281,7 +281,7 @@ private void setData(int count, float range) { //set1.setDrawFilled(true); set1.setDrawCircles(false); set1.setLineWidth(1.8f); - set1.setCircleSize(4f); + set1.setCircleRadius(4f); set1.setCircleColor(Color.WHITE); set1.setHighLightColor(Color.rgb(244, 117, 117)); set1.setColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index 18eacb72ad..b1093f2ac6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -84,7 +84,7 @@ private void initWithDummyData() { // create a dataset and give it a type (0) LineDataSet set1 = new LineDataSet(yVals, "DataSet"); set1.setLineWidth(3f); - set1.setCircleSize(5f); + set1.setCircleRadius(5f); ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java index 52b08e68bf..0c19b2032d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DynamicalAddingActivity.java @@ -126,7 +126,7 @@ private void addDataSet() { LineDataSet set = new LineDataSet(yVals, "DataSet " + count); set.setLineWidth(2.5f); - set.setCircleSize(4.5f); + set.setCircleRadius(4.5f); int color = mColors[count % mColors.length]; @@ -209,7 +209,7 @@ private LineDataSet createSet() { LineDataSet set = new LineDataSet(null, "DataSet 1"); set.setLineWidth(2.5f); - set.setCircleSize(4.5f); + set.setCircleRadius(4.5f); set.setColor(Color.rgb(240, 99, 99)); set.setCircleColor(Color.rgb(240, 99, 99)); set.setHighLightColor(Color.rgb(190, 190, 190)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index f4a5acc383..0a0c7b64b4 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -292,7 +292,7 @@ private void setData(int count, float range) { LineDataSet set1 = new LineDataSet(yVals, "DataSet 1"); set1.setLineWidth(1.5f); - set1.setCircleSize(4f); + set1.setCircleRadius(4f); // create a data object with the datasets LineData data = new LineData(xVals, set1); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 913d37216d..074b60c1bc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -355,7 +355,7 @@ private void setData(int count, float range) { set1.setColor(Color.BLACK); set1.setCircleColor(Color.BLACK); set1.setLineWidth(1f); - set1.setCircleSize(3f); + set1.setCircleRadius(3f); set1.setDrawCircleHole(false); set1.setValueTextSize(9f); set1.setFillAlpha(65); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index b2e777c7f2..f69c07b561 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -296,7 +296,7 @@ private void setData(int count, float range) { set1.setColor(ColorTemplate.getHoloBlue()); set1.setCircleColor(Color.WHITE); set1.setLineWidth(2f); - set1.setCircleSize(3f); + set1.setCircleRadius(3f); set1.setFillAlpha(65); set1.setFillColor(ColorTemplate.getHoloBlue()); set1.setHighLightColor(Color.rgb(244, 117, 117)); @@ -322,7 +322,7 @@ private void setData(int count, float range) { set2.setColor(Color.RED); set2.setCircleColor(Color.WHITE); set2.setLineWidth(2f); - set2.setCircleSize(3f); + set2.setCircleRadius(3f); set2.setFillAlpha(65); set2.setFillColor(Color.RED); set2.setDrawCircleHole(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java index 3d6d8a4cd4..5d1e212d78 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivityColored.java @@ -113,7 +113,7 @@ private LineData getData(int count, float range) { // set1.setFillColor(Color.RED); set1.setLineWidth(1.75f); - set1.setCircleSize(3f); + set1.setCircleRadius(3f); set1.setColor(Color.WHITE); set1.setCircleColor(Color.WHITE); set1.setHighLightColor(Color.WHITE); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java index dfa137abb1..ad242e99ec 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ListViewMultiChartActivity.java @@ -103,7 +103,7 @@ private LineData generateDataLine(int cnt) { LineDataSet d1 = new LineDataSet(e1, "New DataSet " + cnt + ", (1)"); d1.setLineWidth(2.5f); - d1.setCircleSize(4.5f); + d1.setCircleRadius(4.5f); d1.setHighLightColor(Color.rgb(244, 117, 117)); d1.setDrawValues(false); @@ -115,7 +115,7 @@ private LineData generateDataLine(int cnt) { LineDataSet d2 = new LineDataSet(e2, "New DataSet " + cnt + ", (2)"); d2.setLineWidth(2.5f); - d2.setCircleSize(4.5f); + d2.setCircleRadius(4.5f); d2.setHighLightColor(Color.rgb(244, 117, 117)); d2.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); d2.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[0]); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index 651616f912..db136ab20d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -228,7 +228,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { LineDataSet d = new LineDataSet(values, "DataSet " + (z + 1)); d.setLineWidth(2.5f); - d.setCircleSize(4f); + d.setCircleRadius(4f); int color = mColors[z % mColors.length]; d.setColor(color); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index 8c4d1b9120..cf6661ba87 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -168,7 +168,7 @@ private LineDataSet createSet() { set.setColor(ColorTemplate.getHoloBlue()); set.setCircleColor(Color.WHITE); set.setLineWidth(2f); - set.setCircleSize(4f); + set.setCircleRadius(4f); set.setFillAlpha(65); set.setFillColor(ColorTemplate.getHoloBlue()); set.setHighLightColor(Color.rgb(244, 117, 117)); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java index 10865174a1..25d103e8ce 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SimpleFragment.java @@ -185,13 +185,13 @@ protected LineData getComplexity() { ds4.setCircleColor(ColorTemplate.VORDIPLOM_COLORS[3]); ds1.setLineWidth(2.5f); - ds1.setCircleSize(3f); + ds1.setCircleRadius(3f); ds2.setLineWidth(2.5f); - ds2.setCircleSize(3f); + ds2.setCircleRadius(3f); ds3.setLineWidth(2.5f); - ds3.setCircleSize(3f); + ds3.setCircleRadius(3f); ds4.setLineWidth(2.5f); - ds4.setCircleSize(3f); + ds4.setCircleRadius(3f); // load DataSets from textfiles in assets folders diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index 8d760ef753..ee72ec01cc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -23,7 +23,7 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet private int mCircleColorHole = Color.WHITE; /** the radius of the circle-shaped value indicators */ - private float mCircleSize = 8f; + private float mCircleRadius = 8f; /** sets the intensity of the cubic lines */ private float mCubicIntensity = 0.2f; @@ -45,7 +45,7 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet public LineDataSet(List yVals, String label) { super(yVals, label); - // mCircleSize = Utils.convertDpToPixel(4f); + // mCircleRadius = Utils.convertDpToPixel(4f); // mLineWidth = Utils.convertDpToPixel(1f); mCircleColors = new ArrayList(); @@ -67,7 +67,7 @@ public DataSet copy() { LineDataSet copied = new LineDataSet(yVals, getLabel()); copied.mColors = mColors; - copied.mCircleSize = mCircleSize; + copied.mCircleRadius = mCircleRadius; copied.mCircleColors = mCircleColors; copied.mDashPathEffect = mDashPathEffect; copied.mDrawCircles = mDrawCircles; @@ -98,19 +98,43 @@ public float getCubicIntensity() { return mCubicIntensity; } + /** - * sets the size (radius) of the circle shpaed value indicators, default - * size = 4f - * + * sets the radius of the drawn circles. + * Default radius = 4f + * + * @param radius + */ + public void setCircleRadius(float radius) { + mCircleRadius = Utils.convertDpToPixel(radius); + } + + @Override + public float getCircleRadius() { + return mCircleRadius; + } + + /** + * sets the size (radius) of the circle shpaed value indicators, + * default size = 4f + * + * This method is deprecated because of unclarity. Use setCircleRadius instead. + * * @param size */ + @Deprecated public void setCircleSize(float size) { - mCircleSize = Utils.convertDpToPixel(size); + setCircleRadius(size); } - @Override + /** + * + * This function is deprecated because of unclarity. Use getCircleRadius instead. + * + */ + @Deprecated public float getCircleSize() { - return mCircleSize; + return getCircleRadius(); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index d0f3cffe81..e56fdb953d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -139,7 +139,7 @@ public void setCircleSize(float size) { } @Override - public float getCircleSize() { + public float getCircleRadius() { return mCircleSize; } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 03e2bd3a6f..22e24fd608 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -28,7 +28,7 @@ public interface ILineDataSet extends ILineRadarDataSet { /** * Returns the size of the drawn circles. */ - float getCircleSize(); + float getCircleRadius(); /** * Returns the color at the given index of the DataSet's circle-color array. diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index fc1ad87e7d..5e079ab6ce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -428,7 +428,7 @@ public void drawValues(Canvas c) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); // make sure the values do not interfear with the circles - int valOffset = (int) (dataSet.getCircleSize() * 1.75f); + int valOffset = (int) (dataSet.getCircleRadius() * 1.75f); if (!dataSet.isDrawCirclesEnabled()) valOffset = valOffset / 2; @@ -506,7 +506,7 @@ protected void drawCircles(Canvas c) { trans.pointValuesToPixel(buffer.buffer); - float halfsize = dataSet.getCircleSize() / 2f; + float halfsize = dataSet.getCircleRadius() / 2f; for (int j = 0, count = (int) Math.ceil((maxx - minx) * phaseX + minx) * 2; j < count; j += 2) { @@ -525,7 +525,7 @@ protected void drawCircles(Canvas c) { mRenderPaint.setColor(circleColor); - c.drawCircle(x, y, dataSet.getCircleSize(), + c.drawCircle(x, y, dataSet.getCircleRadius(), mRenderPaint); if (dataSet.isDrawCircleHoleEnabled() From 0759db03519b7a14b66dba653139a2e3bb000639 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 17 Jan 2016 19:47:04 +0100 Subject: [PATCH 0668/1390] Minor fix --- .../mikephil/charting/data/realm/base/RealmBaseDataSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index a0a62ad103..7660e2ceff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -67,8 +67,8 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn this.mIndexField = xIndexField; this.mValues = new ArrayList(); - if (mIndexField != null) ; - this.results.sort(mIndexField, true); + if (mIndexField != null) + this.results.sort(mIndexField, true); } /** From d1464ce6191e440ca3287246f7dc1827ba2607c8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 10:25:53 +0100 Subject: [PATCH 0669/1390] Optimized default y-offsets of legend and xaxis for better default look --- .../src/com/github/mikephil/charting/components/Legend.java | 2 +- .../src/com/github/mikephil/charting/components/XAxis.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 9990abbe6b..27425accd9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -108,7 +108,7 @@ public Legend() { mTextSize = Utils.convertDpToPixel(10f); mStackSpace = Utils.convertDpToPixel(3f); this.mXOffset = Utils.convertDpToPixel(5f); - this.mYOffset = Utils.convertDpToPixel(7f); + this.mYOffset = Utils.convertDpToPixel(4f); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 0578967cb6..f5c46b536b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -97,7 +97,7 @@ public enum XAxisPosition { public XAxis() { super(); - mYOffset = Utils.convertDpToPixel(4.f); + mYOffset = Utils.convertDpToPixel(1.f); } /** From e1594999a57085046469403a1269dadee2b1c283 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 10:30:53 +0100 Subject: [PATCH 0670/1390] Fix bug in HorizontalBarChartRenderer --- .../renderer/HorizontalBarChartRenderer.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 09de5fd413..fe2178b33b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -8,11 +8,10 @@ import com.github.mikephil.charting.buffer.BarBuffer; import com.github.mikephil.charting.buffer.HorizontalBarBuffer; import com.github.mikephil.charting.data.BarData; -import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; import com.github.mikephil.charting.formatter.ValueFormatter; -import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; @@ -21,13 +20,13 @@ /** * Renderer for the HorizontalBarChart. - * + * * @author Philipp Jahoda */ public class HorizontalBarChartRenderer extends BarChartRenderer { public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, - ViewPortHandler viewPortHandler) { + ViewPortHandler viewPortHandler) { super(chart, animator, viewPortHandler); mValuePaint.setTextAlign(Align.LEFT); @@ -47,7 +46,8 @@ public void initBuffers() { } } - protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { + @Override + protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) { Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -56,8 +56,6 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { float phaseX = mAnimator.getPhaseX(); float phaseY = mAnimator.getPhaseY(); - List entries = dataSet.getYVals(); - // initialize the buffer BarBuffer buffer = mBarBuffers[index]; buffer.setPhases(phaseX, phaseY); @@ -192,7 +190,7 @@ public void drawValues(Canvas c) { } drawValue(c, formattedValue, valuePoints[j] - + (e.getVal() >= 0 ? posOffset : negOffset), + + (e.getVal() >= 0 ? posOffset : negOffset), valuePoints[j + 1] + halfTextHeight); } else { @@ -263,7 +261,7 @@ protected void drawValue(Canvas c, String valueText, float x, float y) { @Override protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHalf, - Transformer trans) { + Transformer trans) { float top = x - 0.5f + barspaceHalf; float bottom = x + 0.5f - barspaceHalf; @@ -277,7 +275,7 @@ protected void prepareBarHighlight(float x, float y1, float y2, float barspaceHa @Override public float[] getTransformedValues(Transformer trans, IBarDataSet data, - int dataSetIndex) { + int dataSetIndex) { return trans.generateTransformedValuesHorizontalBarChart(data, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); } From 4281ad1674d68d85bf9412a1b42b0f984a0c2c18 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 10:50:03 +0100 Subject: [PATCH 0671/1390] Change back default offset --- .../src/com/github/mikephil/charting/components/XAxis.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index f5c46b536b..2949e9814c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -97,7 +97,7 @@ public enum XAxisPosition { public XAxis() { super(); - mYOffset = Utils.convertDpToPixel(1.f); + mYOffset = Utils.convertDpToPixel(3.f); } /** From d487da7b4205b693203b32cc166e71c19ff0964e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 14:21:11 +0100 Subject: [PATCH 0672/1390] Fixes regarding offsets on x-axis --- .../src/com/github/mikephil/charting/components/XAxis.java | 2 +- .../src/com/github/mikephil/charting/utils/Utils.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 2949e9814c..0578967cb6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -97,7 +97,7 @@ public enum XAxisPosition { public XAxis() { super(); - mYOffset = Utils.convertDpToPixel(3.f); + mYOffset = Utils.convertDpToPixel(4.f); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index d389012d96..b8e6cd7964 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -532,11 +532,11 @@ public static void drawText(Canvas c, String text, float x, float y, float drawOffsetX = 0.f; float drawOffsetY = 0.f; - final float lineHeight = paint.getFontMetrics(mFontMetricsBuffer); - paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); - // Android sometimes has pre-padding + final float lineHeight = mDrawTextRectBuffer.height(); + + // Android sometimes has pre-padding drawOffsetX -= mDrawTextRectBuffer.left; // Android does not snap the bounds to line boundaries, From d01f03105d171608aaf43a87ed63f4716bda39a6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 14:30:07 +0100 Subject: [PATCH 0673/1390] Fixes concerning horizontalbarchart offset --- .../charting/charts/HorizontalBarChart.java | 2 +- .../mikephil/charting/components/YAxis.java | 840 +++++++++--------- 2 files changed, 442 insertions(+), 400 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 6172aa7d8a..f7c4501710 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -82,7 +82,7 @@ public void calculateOffsets() { // It's possible that we do not need this offset anymore as it // is available through the extraOffsets, but changing it can mean // changing default visibility for existing apps. - float yOffset = mLegend.mTextHeightMax * 2.f; + float yOffset = mLegend.mTextHeightMax; offsetBottom += Math.min(mLegend.mNeededHeight + yOffset, mViewPortHandler.getChartHeight() * mLegend.getMaxSizePercent()); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index 0c2365e4e7..c87d64b04e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -12,407 +12,449 @@ * access public variables directly. Be aware that not all features the YLabels class provides are suitable for the * RadarChart. Customizations that affect the value range of the axis need to be applied before setting data for the * chart. - * + * * @author Philipp Jahoda */ public class YAxis extends AxisBase { - /** custom formatter that is used instead of the auto-formatter if set */ - protected YAxisValueFormatter mYAxisValueFormatter; - - /** the actual array of entries */ - public float[] mEntries = new float[] {}; - - /** the number of entries the legend contains */ - public int mEntryCount; - - /** the number of decimal digits to use */ - public int mDecimals; - - /** the number of y-label entries the y-labels should have, default 6 */ - private int mLabelCount = 6; - - /** indicates if the top y-label entry is drawn or not */ - private boolean mDrawTopYLabelEntry = true; - - /** if true, the y-labels show only the minimum and maximum value */ - protected boolean mShowOnlyMinMax = false; - - /** flag that indicates if the axis is inverted or not */ - protected boolean mInverted = false; - - /** if true, the y-label entries will always start at zero */ - protected boolean mStartAtZero = true; - - /** if true, the set number of y-labels will be forced */ - protected boolean mForceLabels = false; - - /** custom minimum value this axis represents */ - protected float mCustomAxisMin = Float.NaN; - - /** custom maximum value this axis represents */ - protected float mCustomAxisMax = Float.NaN; - - /** - * axis space from the largest value to the top in percent of the total axis range - */ - protected float mSpacePercentTop = 10f; - - /** - * axis space from the smallest value to the bottom in percent of the total axis range - */ - protected float mSpacePercentBottom = 10f; - - public float mAxisMaximum = 0f; - public float mAxisMinimum = 0f; - - /** the total range of values this axis covers */ - public float mAxisRange = 0f; - - /** the position of the y-labels relative to the chart */ - private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; - - /** enum for the position of the y-labels relative to the chart */ - public enum YAxisLabelPosition { - OUTSIDE_CHART, INSIDE_CHART - } - - /** the side this axis object represents */ - private AxisDependency mAxisDependency; - - /** - * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. - * - * @author Philipp Jahoda - */ - public enum AxisDependency { - LEFT, RIGHT - } - - public YAxis() { - super(); - this.mAxisDependency = AxisDependency.LEFT; - this.mYOffset = 0f; - } - - public YAxis(AxisDependency position) { - super(); - this.mAxisDependency = position; - this.mYOffset = 0f; - } - - public AxisDependency getAxisDependency() { - return mAxisDependency; - } - - /** - * returns the position of the y-labels - */ - public YAxisLabelPosition getLabelPosition() { - return mPosition; - } - - /** - * sets the position of the y-labels - * - * @param pos - */ - public void setPosition(YAxisLabelPosition pos) { - mPosition = pos; - } - - /** - * returns true if drawing the top y-axis label entry is enabled - * - * @return - */ - public boolean isDrawTopYLabelEntryEnabled() { - return mDrawTopYLabelEntry; - } - - /** - * set this to true to enable drawing the top y-label entry. Disabling this can be helpful when the top y-label and - * left x-label interfere with each other. default: true - * - * @param enabled - */ - public void setDrawTopYLabelEntry(boolean enabled) { - mDrawTopYLabelEntry = enabled; - } - - /** - * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware that this number is not - * fixed (if force == false) and can only be approximated. - * - * @param count - * the number of y-axis labels that sould be displayed - * @param force - * if enabled, the set label count will be forced, meaning that the exact specified count of labels will - * be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values - */ - public void setLabelCount(int count, boolean force) { - - if (count > 25) - count = 25; - if (count < 2) - count = 2; - - mLabelCount = count; - mForceLabels = force; - } - - /** - * Returns the number of label entries the y-axis should have - * - * @return - */ - public int getLabelCount() { - return mLabelCount; - } - - /** - * Returns true if focing the y-label count is enabled. Default: false - * - * @return - */ - public boolean isForceLabelsEnabled() { - return mForceLabels; - } - - /** - * If enabled, the YLabels will only show the minimum and maximum value of the chart. This will ignore/override the - * set label count. - * - * @param enabled - */ - public void setShowOnlyMinMax(boolean enabled) { - mShowOnlyMinMax = enabled; - } - - /** - * Returns true if showing only min and max value is enabled. - * - * @return - */ - public boolean isShowOnlyMinMaxEnabled() { - return mShowOnlyMinMax; - } - - /** - * If this is set to true, the y-axis is inverted which means that low values are on top of the chart, high values - * on bottom. - * - * @param enabled - */ - public void setInverted(boolean enabled) { - mInverted = enabled; - } - - /** - * If this returns true, the y-axis is inverted. - * - * @return - */ - public boolean isInverted() { - return mInverted; - } - - /** - * enable this to force the y-axis labels to always start at zero - * - * @param enabled - */ - public void setStartAtZero(boolean enabled) { - this.mStartAtZero = enabled; - } - - /** - * returns true if the chart is set to start at zero, false otherwise - * - * @return - */ - public boolean isStartAtZeroEnabled() { - return mStartAtZero; - } - - public float getAxisMinValue() { - return mCustomAxisMin; - } - - /** - * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on - * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use - * this method. Otherwise, the axis-minimum value will still be forced to 0. - * - * @param min - */ - public void setAxisMinValue(float min) { - mCustomAxisMin = min; - } - - /** - * By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is - * done automatically. - */ - public void resetAxisMinValue() { - mCustomAxisMin = Float.NaN; - } - - public float getAxisMaxValue() { - return mCustomAxisMax; - } - - /** - * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on - * the provided data. Use resetAxisMaxValue() to undo this. - * - * @param max - */ - public void setAxisMaxValue(float max) { - mCustomAxisMax = max; - } - - /** - * By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is - * done automatically. - */ - public void resetAxisMaxValue() { - mCustomAxisMax = Float.NaN; - } - - /** - * Sets the top axis space in percent of the full range. Default 10f - * - * @param percent - */ - public void setSpaceTop(float percent) { - mSpacePercentTop = percent; - } - - /** - * Returns the top axis space in percent of the full range. Default 10f - * - * @return - */ - public float getSpaceTop() { - return mSpacePercentTop; - } - - /** - * Sets the bottom axis space in percent of the full range. Default 10f - * - * @param percent - */ - public void setSpaceBottom(float percent) { - mSpacePercentBottom = percent; - } - - /** - * Returns the bottom axis space in percent of the full range. Default 10f - * - * @return - */ - public float getSpaceBottom() { - return mSpacePercentBottom; - } - - public float getRequiredWidthSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(); - return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; - } - - public float getRequiredHeightSpace(Paint p) { - - p.setTextSize(mTextSize); - - String label = getLongestLabel(); - return (float) Utils.calcTextHeight(p, label) + Utils.convertDpToPixel(2.5f) * 2f + getYOffset(); - } - - @Override - public String getLongestLabel() { - - String longest = ""; - - for (int i = 0; i < mEntries.length; i++) { - String text = getFormattedLabel(i); - - if (longest.length() < text.length()) - longest = text; - } - - return longest; - } - - /** - * Returns the formatted y-label at the specified index. This will either use the auto-formatter or the custom - * formatter (if one is set). - * - * @param index - * @return - */ - public String getFormattedLabel(int index) { - - if (index < 0 || index >= mEntries.length) - return ""; - else - return getValueFormatter().getFormattedValue(mEntries[index], this); - } - - /** - * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the chart will - * automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside - * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. - * - * @param f - */ - public void setValueFormatter(YAxisValueFormatter f) { - - if (f == null) - mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); - else - mYAxisValueFormatter = f; - } - - /** - * Returns the formatter used for formatting the axis labels. - * - * @return - */ - public YAxisValueFormatter getValueFormatter() { - - if(mYAxisValueFormatter == null) - mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); - - return mYAxisValueFormatter; - } - - /** - * If this component has no YAxisValueFormatter or is only equipped with the default one (no custom set), return true. - * - * @return - */ - public boolean needsDefaultFormatter() { - if (mYAxisValueFormatter == null) - return true; - if (mYAxisValueFormatter instanceof DefaultValueFormatter) - return true; - - return false; - } - - /** - * Returns true if this axis needs horizontal offset, false if no offset is needed. - * - * @return - */ - public boolean needsOffset() { - if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition.OUTSIDE_CHART) - return true; - else - return false; - } + /** + * custom formatter that is used instead of the auto-formatter if set + */ + protected YAxisValueFormatter mYAxisValueFormatter; + + /** + * the actual array of entries + */ + public float[] mEntries = new float[]{}; + + /** + * the number of entries the legend contains + */ + public int mEntryCount; + + /** + * the number of decimal digits to use + */ + public int mDecimals; + + /** + * the number of y-label entries the y-labels should have, default 6 + */ + private int mLabelCount = 6; + + /** + * indicates if the top y-label entry is drawn or not + */ + private boolean mDrawTopYLabelEntry = true; + + /** + * if true, the y-labels show only the minimum and maximum value + */ + protected boolean mShowOnlyMinMax = false; + + /** + * flag that indicates if the axis is inverted or not + */ + protected boolean mInverted = false; + + /** + * if true, the y-label entries will always start at zero + */ + protected boolean mStartAtZero = true; + + /** + * if true, the set number of y-labels will be forced + */ + protected boolean mForceLabels = false; + + /** + * custom minimum value this axis represents + */ + protected float mCustomAxisMin = Float.NaN; + + /** + * custom maximum value this axis represents + */ + protected float mCustomAxisMax = Float.NaN; + + /** + * axis space from the largest value to the top in percent of the total axis range + */ + protected float mSpacePercentTop = 10f; + + /** + * axis space from the smallest value to the bottom in percent of the total axis range + */ + protected float mSpacePercentBottom = 10f; + + public float mAxisMaximum = 0f; + public float mAxisMinimum = 0f; + + /** + * the total range of values this axis covers + */ + public float mAxisRange = 0f; + + /** + * the position of the y-labels relative to the chart + */ + private YAxisLabelPosition mPosition = YAxisLabelPosition.OUTSIDE_CHART; + + /** + * enum for the position of the y-labels relative to the chart + */ + public enum YAxisLabelPosition { + OUTSIDE_CHART, INSIDE_CHART + } + + /** + * the side this axis object represents + */ + private AxisDependency mAxisDependency; + + /** + * Enum that specifies the axis a DataSet should be plotted against, either LEFT or RIGHT. + * + * @author Philipp Jahoda + */ + public enum AxisDependency { + LEFT, RIGHT + } + + public YAxis() { + super(); + this.mAxisDependency = AxisDependency.LEFT; + this.mYOffset = 0f; + } + + public YAxis(AxisDependency position) { + super(); + this.mAxisDependency = position; + this.mYOffset = 0f; + } + + public AxisDependency getAxisDependency() { + return mAxisDependency; + } + + /** + * returns the position of the y-labels + */ + public YAxisLabelPosition getLabelPosition() { + return mPosition; + } + + /** + * sets the position of the y-labels + * + * @param pos + */ + public void setPosition(YAxisLabelPosition pos) { + mPosition = pos; + } + + /** + * returns true if drawing the top y-axis label entry is enabled + * + * @return + */ + public boolean isDrawTopYLabelEntryEnabled() { + return mDrawTopYLabelEntry; + } + + /** + * set this to true to enable drawing the top y-label entry. Disabling this can be helpful when the top y-label and + * left x-label interfere with each other. default: true + * + * @param enabled + */ + public void setDrawTopYLabelEntry(boolean enabled) { + mDrawTopYLabelEntry = enabled; + } + + /** + * sets the number of label entries for the y-axis max = 25, min = 2, default: 6, be aware that this number is not + * fixed (if force == false) and can only be approximated. + * + * @param count the number of y-axis labels that sould be displayed + * @param force if enabled, the set label count will be forced, meaning that the exact specified count of labels will + * be drawn and evenly distributed alongside the axis - this might cause labels to have uneven values + */ + public void setLabelCount(int count, boolean force) { + + if (count > 25) + count = 25; + if (count < 2) + count = 2; + + mLabelCount = count; + mForceLabels = force; + } + + /** + * Returns the number of label entries the y-axis should have + * + * @return + */ + public int getLabelCount() { + return mLabelCount; + } + + /** + * Returns true if focing the y-label count is enabled. Default: false + * + * @return + */ + public boolean isForceLabelsEnabled() { + return mForceLabels; + } + + /** + * If enabled, the YLabels will only show the minimum and maximum value of the chart. This will ignore/override the + * set label count. + * + * @param enabled + */ + public void setShowOnlyMinMax(boolean enabled) { + mShowOnlyMinMax = enabled; + } + + /** + * Returns true if showing only min and max value is enabled. + * + * @return + */ + public boolean isShowOnlyMinMaxEnabled() { + return mShowOnlyMinMax; + } + + /** + * If this is set to true, the y-axis is inverted which means that low values are on top of the chart, high values + * on bottom. + * + * @param enabled + */ + public void setInverted(boolean enabled) { + mInverted = enabled; + } + + /** + * If this returns true, the y-axis is inverted. + * + * @return + */ + public boolean isInverted() { + return mInverted; + } + + /** + * enable this to force the y-axis labels to always start at zero + * + * @param enabled + */ + public void setStartAtZero(boolean enabled) { + this.mStartAtZero = enabled; + } + + /** + * returns true if the chart is set to start at zero, false otherwise + * + * @return + */ + public boolean isStartAtZeroEnabled() { + return mStartAtZero; + } + + public float getAxisMinValue() { + return mCustomAxisMin; + } + + /** + * Set a custom minimum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMinValue() to undo this. Do not forget to call setStartAtZero(false) if you use + * this method. Otherwise, the axis-minimum value will still be forced to 0. + * + * @param min + */ + public void setAxisMinValue(float min) { + mCustomAxisMin = min; + } + + /** + * By calling this method, any custom minimum value that has been previously set is reseted, and the calculation is + * done automatically. + */ + public void resetAxisMinValue() { + mCustomAxisMin = Float.NaN; + } + + public float getAxisMaxValue() { + return mCustomAxisMax; + } + + /** + * Set a custom maximum value for this axis. If set, this value will not be calculated automatically depending on + * the provided data. Use resetAxisMaxValue() to undo this. + * + * @param max + */ + public void setAxisMaxValue(float max) { + mCustomAxisMax = max; + } + + /** + * By calling this method, any custom maximum value that has been previously set is reseted, and the calculation is + * done automatically. + */ + public void resetAxisMaxValue() { + mCustomAxisMax = Float.NaN; + } + + /** + * Sets the top axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceTop(float percent) { + mSpacePercentTop = percent; + } + + /** + * Returns the top axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceTop() { + return mSpacePercentTop; + } + + /** + * Sets the bottom axis space in percent of the full range. Default 10f + * + * @param percent + */ + public void setSpaceBottom(float percent) { + mSpacePercentBottom = percent; + } + + /** + * Returns the bottom axis space in percent of the full range. Default 10f + * + * @return + */ + public float getSpaceBottom() { + return mSpacePercentBottom; + } + + /** + * This is for normal (not horizontal) charts horizontal spacing. + * + * @param p + * @return + */ + public float getRequiredWidthSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(); + return (float) Utils.calcTextWidth(p, label) + getXOffset() * 2f; + } + + /** + * This is for HorizontalBarChart vertical spacing. + * + * @param p + * @return + */ + public float getRequiredHeightSpace(Paint p) { + + p.setTextSize(mTextSize); + + String label = getLongestLabel(); + return (float) Utils.calcTextHeight(p, label) + getYOffset() * 2f; + } + + @Override + public String getLongestLabel() { + + String longest = ""; + + for (int i = 0; i < mEntries.length; i++) { + String text = getFormattedLabel(i); + + if (longest.length() < text.length()) + longest = text; + } + + return longest; + } + + /** + * Returns the formatted y-label at the specified index. This will either use the auto-formatter or the custom + * formatter (if one is set). + * + * @param index + * @return + */ + public String getFormattedLabel(int index) { + + if (index < 0 || index >= mEntries.length) + return ""; + else + return getValueFormatter().getFormattedValue(mEntries[index], this); + } + + /** + * Sets the formatter to be used for formatting the axis labels. If no formatter is set, the chart will + * automatically determine a reasonable formatting (concerning decimals) for all the values that are drawn inside + * the chart. Use chart.getDefaultValueFormatter() to use the formatter calculated by the chart. + * + * @param f + */ + public void setValueFormatter(YAxisValueFormatter f) { + + if (f == null) + mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); + else + mYAxisValueFormatter = f; + } + + /** + * Returns the formatter used for formatting the axis labels. + * + * @return + */ + public YAxisValueFormatter getValueFormatter() { + + if (mYAxisValueFormatter == null) + mYAxisValueFormatter = new DefaultYAxisValueFormatter(mDecimals); + + return mYAxisValueFormatter; + } + + /** + * If this component has no YAxisValueFormatter or is only equipped with the default one (no custom set), return true. + * + * @return + */ + public boolean needsDefaultFormatter() { + if (mYAxisValueFormatter == null) + return true; + if (mYAxisValueFormatter instanceof DefaultValueFormatter) + return true; + + return false; + } + + /** + * Returns true if this axis needs horizontal offset, false if no offset is needed. + * + * @return + */ + public boolean needsOffset() { + if (isEnabled() && isDrawLabelsEnabled() && getLabelPosition() == YAxisLabelPosition.OUTSIDE_CHART) + return true; + else + return false; + } } From 3fa3726f3aec41fec649cfaa74994fa179485496 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 18 Jan 2016 14:36:11 +0100 Subject: [PATCH 0674/1390] Update README.md --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f879468169..151c1a0d39 100644 --- a/README.md +++ b/README.md @@ -70,18 +70,17 @@ Features - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - Dragging / Panning (with touch-gesture) - Combined-Charts (line-, bar-, scatter-, candle-data) - - Dual (separate) Y-Axis - - Finger drawing (draw values into the chart with touch-gesture) + - Dual (separate) Axes + - Customizeable Axes (both x- and y-axis) - Highlighting values (with customizeable popup-views) - - Multiple / Separate Axes - Save chart to SD-Card (as image, or as .txt file) - Predefined color templates - Legends (generated automatically, customizeable) - - Customizeable Axes (both x- and y-axis) - Animations (build up animations, on both x- and y-axis) - Limit lines (providing additional information, maximums, ...) - Fully customizeable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) - Smooth zooming and scrolling for up to 30.000 data points in Line- and BarChart + - Gradle support - Plotting data directly from [**Realm.io**](https://realm.io) mobile database **Chart types:** From 2dee57a0dc64418d648dba9104ffecb5c8667eb3 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Jan 2016 00:00:52 +0100 Subject: [PATCH 0675/1390] Minor fixes --- .../gradle/org.springsource.ide.eclipse.gradle.core.prefs | 4 ++++ .../gradle/org.springsource.ide.eclipse.gradle.core.prefs | 3 +++ MPChartExample/project.properties | 2 +- .../xxmassdeveloper/mpchartexample/custom/RealmDemoData.java | 2 +- .../gradle/org.springsource.ide.eclipse.gradle.core.prefs | 4 ++++ MPChartLib/project.properties | 2 +- .../src/com/github/mikephil/charting/data/BaseDataSet.java | 2 +- 7 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs create mode 100644 MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs create mode 100644 MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs diff --git a/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs new file mode 100644 index 0000000000..9383f623c6 --- /dev/null +++ b/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs @@ -0,0 +1,4 @@ +#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences +#Mon Jan 18 23:02:46 CET 2016 +build.family.org.gradle.tooling.model.eclipse.HierarchicalEclipseProject=;MPChartExample;MPChartLib; +org.springsource.ide.eclipse.gradle.rootprojectloc= diff --git a/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs new file mode 100644 index 0000000000..be975eb2db --- /dev/null +++ b/MPChartExample/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs @@ -0,0 +1,3 @@ +#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences +#Mon Jan 18 23:02:46 CET 2016 +org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index 07fc2a4c2f..b32d807be6 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-22 +target=android-23 android.library.reference.1=../MPChartLib diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java index 503acd9fac..58767447fe 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmDemoData.java @@ -46,7 +46,7 @@ public RealmDemoData(float value, int xIndex, String xValue) { public RealmDemoData(float[] stackValues, int xIndex, String xValue) { this.xIndex = xIndex; this.xValue = xValue; - this.stackValues = new RealmList<>(); + this.stackValues = new RealmList(); for (float val : stackValues) { this.stackValues.add(new RealmFloat(val)); diff --git a/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs b/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs new file mode 100644 index 0000000000..77dc3a2d85 --- /dev/null +++ b/MPChartLib/.settings/gradle/org.springsource.ide.eclipse.gradle.core.prefs @@ -0,0 +1,4 @@ +#org.springsource.ide.eclipse.gradle.core.preferences.GradleProjectPreferences +#Mon Jan 18 23:02:46 CET 2016 +org.springsource.ide.eclipse.gradle.linkedresources= +org.springsource.ide.eclipse.gradle.rootprojectloc=.. diff --git a/MPChartLib/project.properties b/MPChartLib/project.properties index 362a0a3082..b2ef7dccc5 100644 --- a/MPChartLib/project.properties +++ b/MPChartLib/project.properties @@ -11,5 +11,5 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-22 +target=android-23 android.library=true diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 7e62a14f16..74b4d47815 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -75,7 +75,7 @@ public abstract class BaseDataSet implements IDataSet { * Default constructor. */ public BaseDataSet() { - mColors = new ArrayList<>(); + mColors = new ArrayList(); // default color mColors.add(Color.rgb(140, 234, 255)); From 1f1996c4d326758b6b3e8cdfb4adb1dd4124f848 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Jan 2016 00:19:01 +0100 Subject: [PATCH 0676/1390] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 151c1a0d39..8084cba31e 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ repositories { } dependencies { - compile 'com.github.PhilJay:MPAndroidChart:v2.1.6' + compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } ``` @@ -160,7 +160,7 @@ dependencies { com.github.PhilJay MPAndroidChart - v2.1.6 + v2.2.0 ``` @@ -180,7 +180,7 @@ dependencies { Documentation ======= -For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.6/javadoc/). +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.0/javadoc/). Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). From 3bd2110ecb538882f4a95cc0a2064224bc3467be Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Jan 2016 00:19:28 +0100 Subject: [PATCH 0677/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8084cba31e..6bcefbbf98 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ Questions & Issues If you are having questions or problems, you should: - Make sure you are using the latest version of the library. Check the [**release-section**](https://github.com/PhilJay/MPAndroidChart/releases). - - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.1.6/javadoc/) + - Study the [**Documentation-Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki) or the [javadocs](https://jitpack.io/com/github/PhilJay/MPAndroidChart/v2.2.0/javadoc/) - Search or open questions on [**stackoverflow**](https://stackoverflow.com/search?q=mpandroidchart) with the `mpandroidchart` tag - Search [**known issues**](https://github.com/PhilJay/MPAndroidChart/issues) for your problem (open and closed) - Create new issues (please **search known issues before**, do not create duplicate issues) From ff5ddbbd92ed1d79858796d6cd7379f08a1f268a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Jan 2016 00:26:16 +0100 Subject: [PATCH 0678/1390] Fix build gradle --- MPChartExample/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 84c34bc414..cd43c424ab 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -56,5 +56,5 @@ dependencies { compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' compile 'io.realm:realm-android:0.84.0-SNAPSHOT' // dependency for realm-database API (http://realm.io) - //compile 'com.github.PhilJay:MPAndroidChart:v2.1.1' + //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } From b6289be3a9cb725eade44e58ad8392379a702c96 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 19 Jan 2016 22:43:58 +0100 Subject: [PATCH 0679/1390] Did some fixing related to #1381, added more useful methods to interfaces. --- .../mikephil/charting/data/BaseDataSet.java | 46 ++++ .../mikephil/charting/data/DataSet.java | 205 ++++-------------- .../data/realm/base/RealmBaseDataSet.java | 37 +++- .../interfaces/datasets/IDataSet.java | 60 +++++ 4 files changed, 187 insertions(+), 161 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java index 74b4d47815..3c151d783f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BaseDataSet.java @@ -317,4 +317,50 @@ public YAxis.AxisDependency getAxisDependency() { public void setAxisDependency(YAxis.AxisDependency dependency) { mAxisDependency = dependency; } + + + /** ###### ###### DATA RELATED METHODS ###### ###### */ + + @Override + public int getIndexInEntries(int xIndex) { + + for (int i = 0; i < getEntryCount(); i++) { + if (xIndex == getEntryForIndex(i).getXIndex()) + return i; + } + + return -1; + } + + @Override + public boolean removeFirst() { + + T entry = getEntryForIndex(0); + return removeEntry(entry); + } + + @Override + public boolean removeLast() { + + T entry = getEntryForIndex(getEntryCount() - 1); + return removeEntry(entry); + } + + @Override + public boolean removeEntry(int xIndex) { + + T e = getEntryForXIndex(xIndex); + return removeEntry(e); + } + + @Override + public boolean contains(T e) { + + for(int i = 0; i < getEntryCount(); i++) { + if(getEntryForIndex(i).equals(e)) + return true; + } + + return false; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java index 32c47d0dbb..29f5f69c28 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/DataSet.java @@ -94,49 +94,6 @@ public int getEntryCount() { return mYVals.size(); } - /** - * Returns all Entry objects at the given xIndex. INFORMATION: This method - * does calculations at runtime. Do not over-use in performance critical - * situations. - * - * @param x - * @return - */ - public List getEntriesForXIndex(int x) { - - List entries = new ArrayList(); - - int low = 0; - int high = mYVals.size() - 1; - - while (low <= high) { - int m = (high + low) / 2; - T entry = mYVals.get(m); - - if (x == entry.getXIndex()) { - while (m > 0 && mYVals.get(m - 1).getXIndex() == x) - m--; - - high = mYVals.size(); - for (; m < high; m++) { - entry = mYVals.get(m); - if (entry.getXIndex() == x) { - entries.add(entry); - } else { - break; - } - } - } - - if (x > entry.getXIndex()) - low = m + 1; - else - high = m - 1; - } - - return entries; - } - /** * Returns the array of y-values that this DataSet represents. * @@ -146,25 +103,6 @@ public List getYVals() { return mYVals; } - /** - * The xIndex of an Entry object is provided. This method returns the actual - * index in the Entry array of the DataSet. IMPORTANT: This method does - * calculations at runtime, do not over-use in performance critical - * situations. - * - * @param xIndex - * @return - */ - public int getIndexInEntries(int xIndex) { - - for (int i = 0; i < mYVals.size(); i++) { - if (xIndex == mYVals.get(i).getXIndex()) - return i; - } - - return -1; - } - /** * Provides an exact copy of the DataSet this method is used on. * @@ -204,16 +142,8 @@ public float getYMax() { return mYMax; } - /** - * Adds an Entry to the DataSet dynamically. - * Entries are added to their appropriate index respective to it's x-index. - * This will also recalculate the current minimum and maximum - * values of the DataSet and the value-sum. - * - * @param e - */ - @SuppressWarnings("unchecked") - public void addEntryOrdered(Entry e) { + @Override + public void addEntryOrdered(T e) { if (e == null) return; @@ -236,57 +166,14 @@ public void addEntryOrdered(Entry e) { if (mYVals.size() > 0 && mYVals.get(mYVals.size() - 1).getXIndex() > e.getXIndex()) { int closestIndex = getEntryIndex(e.getXIndex(), Rounding.UP); - mYVals.add(closestIndex, (T) e); + mYVals.add(closestIndex, e); return; } - mYVals.add((T) e); - } - - /** - * Removes the first Entry (at index 0) of this DataSet from the entries array. - * Returns true if successful, false if not. - * - * @return - */ - public boolean removeFirst() { - - T entry = mYVals.remove(0); - - boolean removed = entry != null; - - if (removed) { - calcMinMax(0, mYVals.size()); - } - - return removed; - } - - /** - * Removes the last Entry (at index size-1) of this DataSet from the entries array. - * Returns true if successful, false if not. - * - * @return - */ - public boolean removeLast() { - - if (mYVals.size() <= 0) - return false; - - T entry = mYVals.remove(mYVals.size() - 1); - - boolean removed = entry != null; - - if (removed) { - calcMinMax(0, mYVals.size()); - } - - return removed; + mYVals.add(e); } - /** - * Removes all values from this DataSet and recalculates min and max value. - */ + @Override public void clear() { mYVals.clear(); notifyDataSetChanged(); @@ -339,48 +226,9 @@ public boolean removeEntry(T e) { return removed; } - /** - * Removes the Entry object that has the given xIndex from the DataSet. - * Returns true if an Entry was removed, false if no Entry could be removed. - * - * @param xIndex - */ - public boolean removeEntry(int xIndex) { - - T e = getEntryForXIndex(xIndex); - return removeEntry(e); - } - - /** - * Checks if this DataSet contains the specified Entry. Returns true if so, - * false if not. NOTE: Performance is pretty bad on this one, do not - * over-use in performance critical situations. - * - * @param e - * @return - */ - public boolean contains(Entry e) { - - List values = getYVals(); - - for (Entry entry : values) { - if (entry.equals(e)) - return true; - } - - return false; - } - @Override public int getEntryIndex(Entry e) { return mYVals.indexOf(e); -// -// for (int i = 0; i < mYVals.size(); i++) { -// if (e.equalTo(mYVals.get(i))) -// return i; -// } -// -// return -1; } @Override @@ -454,6 +302,49 @@ public float getYValForXIndex(int xIndex) { return Float.NaN; } + /** + * Returns all Entry objects at the given xIndex. INFORMATION: This method + * does calculations at runtime. Do not over-use in performance critical + * situations. + * + * @param xIndex + * @return + */ + public List getEntriesForXIndex(int xIndex) { + + List entries = new ArrayList(); + + int low = 0; + int high = mYVals.size() - 1; + + while (low <= high) { + int m = (high + low) / 2; + T entry = mYVals.get(m); + + if (xIndex == entry.getXIndex()) { + while (m > 0 && mYVals.get(m - 1).getXIndex() == xIndex) + m--; + + high = mYVals.size(); + for (; m < high; m++) { + entry = mYVals.get(m); + if (entry.getXIndex() == xIndex) { + entries.add(entry); + } else { + break; + } + } + } + + if (xIndex > entry.getXIndex()) + low = m + 1; + else + high = m - 1; + } + + return entries; + } + /** * Determines how to round DataSet index values for * {@link DataSet#getEntryIndex(int, Rounding)} DataSet.getEntryIndex()} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 7660e2ceff..6598b02b99 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -259,6 +259,37 @@ public boolean removeEntry(S e) { return removed; } + @Override + public void addEntryOrdered(S e) { + + if (e == null) + return; + + float val = e.getVal(); + + if (mValues == null) { + mValues = new ArrayList(); + } + + if (mValues.size() == 0) { + mYMax = val; + mYMin = val; + } else { + if (mYMax < val) + mYMax = val; + if (mYMin > val) + mYMin = val; + } + + if (mValues.size() > 0 && mValues.get(mValues.size() - 1).getXIndex() > e.getXIndex()) { + int closestIndex = getEntryIndex(e.getXIndex(), DataSet.Rounding.UP); + mValues.add(closestIndex, e); + return; + } + + mValues.add(e); + } + /** * Returns the List of values that has been extracted from the RealmResults * using the provided fieldnames. @@ -269,10 +300,8 @@ public List getValues() { return mValues; } - /** - * Clears all values from the DataSet. - */ - public void clearValues() { + @Override + public void clear() { mValues.clear(); notifyDataSetChanged(); } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java index 0eefef7515..d92bb174e9 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/IDataSet.java @@ -112,6 +112,17 @@ public interface IDataSet { */ float getYValForXIndex(int xIndex); + /** + * This method returns the actual + * index in the Entry array of the DataSet for a given xIndex. IMPORTANT: This method does + * calculations at runtime, do not over-use in performance critical + * situations. + * + * @param xIndex + * @return + */ + int getIndexInEntries(int xIndex); + /** * Adds an Entry to the DataSet dynamically. * Entries are added to the end of the list. @@ -132,6 +143,55 @@ public interface IDataSet { */ boolean removeEntry(T e); + /** + * Adds an Entry to the DataSet dynamically. + * Entries are added to their appropriate index respective to it's x-index. + * This will also recalculate the current minimum and maximum + * values of the DataSet and the value-sum. + * + * @param e + */ + void addEntryOrdered(T e); + + /** + * Removes the first Entry (at index 0) of this DataSet from the entries array. + * Returns true if successful, false if not. + * + * @return + */ + boolean removeFirst(); + + /** + * Removes the last Entry (at index size-1) of this DataSet from the entries array. + * Returns true if successful, false if not. + * + * @return + */ + boolean removeLast(); + + /** + * Removes the Entry object that has the given xIndex from the DataSet. + * Returns true if an Entry was removed, false if no Entry could be removed. + * + * @param xIndex + */ + boolean removeEntry(int xIndex); + + /** + * Checks if this DataSet contains the specified Entry. Returns true if so, + * false if not. NOTE: Performance is pretty bad on this one, do not + * over-use in performance critical situations. + * + * @param entry + * @return + */ + boolean contains(T entry); + + /** + * Removes all values from this DataSet and does all necessary recalculations. + */ + void clear(); + /** ###### ###### STYLING RELATED (& OTHER) METHODS ###### ###### */ From 49621cb4a068ac55f633f503aacc09beaccf31b2 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Jan 2016 00:31:23 +0100 Subject: [PATCH 0680/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6bcefbbf98..a655e591bc 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ No problem, let's talk: [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](ht License ======= -Copyright 2015 Philipp Jahoda +Copyright 2016 Philipp Jahoda Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From aa5730d19f01ba5d37c348b3bdfa17c5e8e66d07 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 20 Jan 2016 18:38:04 +0100 Subject: [PATCH 0681/1390] Introducing WeakReference for Bitmap (issue #1386) --- .../charting/renderer/LineChartRenderer.java | 18 ++++++++++-------- .../charting/renderer/PieChartRenderer.java | 18 ++++++++++-------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5e079ab6ce..1323d01b70 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -19,6 +19,7 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.lang.ref.WeakReference; import java.util.List; public class LineChartRenderer extends LineScatterCandleRadarRenderer { @@ -34,7 +35,7 @@ public class LineChartRenderer extends LineScatterCandleRadarRenderer { * Bitmap object used for drawing the paths (otherwise they are too long if * rendered directly on the canvas) */ - protected Bitmap mDrawBitmap; + protected WeakReference mDrawBitmap; /** * on this canvas, the paths are rendered, it is initialized with the @@ -80,18 +81,18 @@ public void drawData(Canvas c) { int height = (int) mViewPortHandler.getChartHeight(); if (mDrawBitmap == null - || (mDrawBitmap.getWidth() != width) - || (mDrawBitmap.getHeight() != height)) { + || (mDrawBitmap.get().getWidth() != width) + || (mDrawBitmap.get().getHeight() != height)) { if (width > 0 && height > 0) { - mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); - mBitmapCanvas = new Canvas(mDrawBitmap); + mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444)); + mBitmapCanvas = new Canvas(mDrawBitmap.get()); } else return; } - mDrawBitmap.eraseColor(Color.TRANSPARENT); + mDrawBitmap.get().eraseColor(Color.TRANSPARENT); LineData lineData = mChart.getLineData(); @@ -101,7 +102,7 @@ public void drawData(Canvas c) { drawDataSet(c, set); } - c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); + c.drawBitmap(mDrawBitmap.get(), 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, ILineDataSet dataSet) { @@ -578,7 +579,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { */ public void releaseBitmap() { if (mDrawBitmap != null) { - mDrawBitmap.recycle(); + mDrawBitmap.get().recycle(); + mDrawBitmap.clear(); mDrawBitmap = null; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 357c9bf99a..f9dbb0dc9b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -24,6 +24,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; +import java.lang.ref.WeakReference; import java.util.List; public class PieChartRenderer extends DataRenderer { @@ -51,7 +52,7 @@ public class PieChartRenderer extends DataRenderer { /** * Bitmap for drawing the center hole */ - protected Bitmap mDrawBitmap; + protected WeakReference mDrawBitmap; protected Canvas mBitmapCanvas; @@ -103,18 +104,18 @@ public void drawData(Canvas c) { int height = (int) mViewPortHandler.getChartHeight(); if (mDrawBitmap == null - || (mDrawBitmap.getWidth() != width) - || (mDrawBitmap.getHeight() != height)) { + || (mDrawBitmap.get().getWidth() != width) + || (mDrawBitmap.get().getHeight() != height)) { if (width > 0 && height > 0) { - mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); - mBitmapCanvas = new Canvas(mDrawBitmap); + mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444)); + mBitmapCanvas = new Canvas(mDrawBitmap.get()); } else return; } - mDrawBitmap.eraseColor(Color.TRANSPARENT); + mDrawBitmap.get().eraseColor(Color.TRANSPARENT); PieData pieData = mChart.getData(); @@ -250,7 +251,7 @@ public void drawValues(Canvas c) { public void drawExtras(Canvas c) { // drawCircles(c); drawHole(c); - c.drawBitmap(mDrawBitmap, 0, 0, null); + c.drawBitmap(mDrawBitmap.get(), 0, 0, null); drawCenterText(c); } @@ -495,7 +496,8 @@ protected void drawRoundedSlices(Canvas c) { */ public void releaseBitmap() { if (mDrawBitmap != null) { - mDrawBitmap.recycle(); + mDrawBitmap.get().recycle(); + mDrawBitmap.clear(); mDrawBitmap = null; } } From f64cff34d27cb1c7f403c03196acc6af24b1833b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 23 Jan 2016 09:59:56 +0100 Subject: [PATCH 0682/1390] DrawGridBackground now defaults to false --- .../com/github/mikephil/charting/charts/BarLineChartBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 80d4af1a19..acc9249b98 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -98,7 +98,7 @@ public abstract class BarLineChartBase Date: Sat, 23 Jan 2016 10:04:49 +0100 Subject: [PATCH 0683/1390] Documentation changes --- .../charting/charts/BarLineChartBase.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index acc9249b98..c922823194 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -46,7 +46,8 @@ public abstract class BarLineChartBase implements BarLineScatterCandleBubbleDataProvider { /** - * the maximum number of entried to which values will be drawn + * the maximum number of entries to which values will be drawn + * (entry numbers greater than this value will cause value-labels to disappear) */ protected int mMaxVisibleCount = 100; @@ -113,10 +114,13 @@ public abstract class BarLineChartBase Date: Sun, 24 Jan 2016 13:23:52 +0100 Subject: [PATCH 0684/1390] Update to realm 0.87.2 (issue #1397) --- MPChartExample/build.gradle | 3 +-- .../xxmassdeveloper/mpchartexample/custom/RealmFloat.java | 2 +- MPChartLib/build.gradle | 2 +- .../realm/base/RealmBarLineScatterCandleBubbleDataSet.java | 1 - .../mikephil/charting/data/realm/base/RealmBaseDataSet.java | 5 +++-- .../charting/data/realm/base/RealmLineRadarDataSet.java | 2 +- .../mikephil/charting/data/realm/base/RealmUtils.java | 3 +-- .../charting/data/realm/implementation/RealmBarDataSet.java | 6 +++--- .../data/realm/implementation/RealmBubbleDataSet.java | 4 +--- .../data/realm/implementation/RealmCandleDataSet.java | 2 +- .../data/realm/implementation/RealmLineDataSet.java | 2 -- .../charting/data/realm/implementation/RealmPieDataSet.java | 2 +- .../data/realm/implementation/RealmRadarDataSet.java | 2 -- .../data/realm/implementation/RealmScatterDataSet.java | 2 +- 14 files changed, 15 insertions(+), 23 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index cd43c424ab..6528de2b7a 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -25,7 +25,6 @@ android { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } - } lintOptions { @@ -55,6 +54,6 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' - compile 'io.realm:realm-android:0.84.0-SNAPSHOT' // dependency for realm-database API (http://realm.io) + compile 'io.realm:realm-android:0.87.2' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java index 15b027b3ff..18ff37861a 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -21,7 +21,7 @@ public float getFloatValue() { return floatValue; } - public void setFloatValue(float value) { + public void setFloatValue(Float value) { this.floatValue = value; } } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index faf5c0df90..0b979d49ea 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -41,7 +41,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' - provided 'io.realm:realm-android:0.84.1-SNAPSHOT' // "optional" dependency to realm-database API + provided 'io.realm:realm-android:0.87.2' // "optional" dependency to realm-database API } android.libraryVariants.all { variant -> diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java index 096f39dd33..cfff7b8b28 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBarLineScatterCandleBubbleDataSet.java @@ -16,7 +16,6 @@ public abstract class RealmBarLineScatterCandleBubbleDataSet results, String yValuesField) { super(results, yValuesField); } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java index 6598b02b99..02b769e8ac 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmBaseDataSet.java @@ -9,6 +9,7 @@ import io.realm.RealmObject; import io.realm.RealmResults; +import io.realm.Sort; /** * Created by Philipp Jahoda on 06/11/15. @@ -51,7 +52,7 @@ public RealmBaseDataSet(RealmResults results, String yValuesField) { this.mValues = new ArrayList(); if (mIndexField != null) - this.results.sort(mIndexField, true); + this.results.sort(mIndexField, Sort.ASCENDING); } /** @@ -68,7 +69,7 @@ public RealmBaseDataSet(RealmResults results, String yValuesField, String xIn this.mValues = new ArrayList(); if (mIndexField != null) - this.results.sort(mIndexField, true); + this.results.sort(mIndexField, Sort.ASCENDING); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index 945d6840e7..8727319203 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -6,9 +6,9 @@ import com.github.mikephil.charting.interfaces.datasets.ILineRadarDataSet; import com.github.mikephil.charting.utils.Utils; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 08/11/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java index cc1bfd44dc..0327a9a060 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmUtils.java @@ -3,10 +3,9 @@ import java.util.ArrayList; import java.util.List; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; - /** * Created by Philipp Jahoda on 19/12/15. */ diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index 2a2f34b819..ec03de0d2e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -6,10 +6,10 @@ import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBarDataSet; +import io.realm.DynamicRealmObject; +import io.realm.RealmList; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmList; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. @@ -85,7 +85,7 @@ public void build(RealmResults results) { } catch (IllegalArgumentException e) { - DynamicRealmList list = dynamicObject.getList(mValuesField); + RealmList list = dynamicObject.getList(mValuesField); float[] values = new float[list.size()]; int i = 0; diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java index 79184658a7..7a8ae13f08 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBubbleDataSet.java @@ -1,15 +1,13 @@ package com.github.mikephil.charting.data.realm.implementation; -import android.graphics.Color; - import com.github.mikephil.charting.data.BubbleEntry; import com.github.mikephil.charting.data.realm.base.RealmBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet; import com.github.mikephil.charting.utils.Utils; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java index 0a0d93c3f1..0a2f8c03d3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmCandleDataSet.java @@ -8,9 +8,9 @@ import com.github.mikephil.charting.utils.ColorTemplate; import com.github.mikephil.charting.utils.Utils; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index e56fdb953d..b64cef73a1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -4,7 +4,6 @@ import android.graphics.Color; import android.graphics.DashPathEffect; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -17,7 +16,6 @@ import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 21/10/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java index 03c9b0a0a2..c6d9116e66 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmPieDataSet.java @@ -5,9 +5,9 @@ import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; import com.github.mikephil.charting.utils.Utils; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java index 3df67095fe..2c0d8457a8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmRadarDataSet.java @@ -1,12 +1,10 @@ package com.github.mikephil.charting.data.realm.implementation; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.interfaces.datasets.IRadarDataSet; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java index 30beb750f4..1991b59926 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmScatterDataSet.java @@ -6,9 +6,9 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet; import com.github.mikephil.charting.utils.Utils; +import io.realm.DynamicRealmObject; import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 07/11/15. From 420a4448973a604eb92ee660c46606544cc40419 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sun, 24 Jan 2016 13:28:53 +0100 Subject: [PATCH 0685/1390] Add documentation --- .../charting/data/realm/implementation/RealmBarDataSet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java index ec03de0d2e..1b78c278cb 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmBarDataSet.java @@ -78,12 +78,12 @@ public void build(RealmResults results) { DynamicRealmObject dynamicObject = new DynamicRealmObject(realmObject); - try { + try { // normal entry float value = dynamicObject.getFloat(mValuesField); mValues.add(new BarEntry(value, dynamicObject.getInt(mIndexField))); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException e) { // stacked entry RealmList list = dynamicObject.getList(mValuesField); float[] values = new float[list.size()]; From bfae450eb1bb3b4bc48767d03f8f7e31f134f38c Mon Sep 17 00:00:00 2001 From: Andrei Boeru Date: Sun, 24 Jan 2016 18:44:30 +0100 Subject: [PATCH 0686/1390] Fill line chart with a Drawable can be used for gradients, pictures, etc. --- MPChartExample/res/drawable/fade_red.xml | 7 ++++ .../mpchartexample/LineChartActivity1.java | 10 +++--- .../mikephil/charting/data/LineDataSet.java | 33 ++++++++++++++++++ .../implementation/RealmLineDataSet.java | 16 +++++++-- .../interfaces/datasets/ILineDataSet.java | 15 +++++++- .../charting/renderer/LineChartRenderer.java | 30 +++++++++++++++- README.md | 3 ++ screenshots/line_chart_gradient.png | Bin 0 -> 46368 bytes 8 files changed, 105 insertions(+), 9 deletions(-) create mode 100644 MPChartExample/res/drawable/fade_red.xml create mode 100644 screenshots/line_chart_gradient.png diff --git a/MPChartExample/res/drawable/fade_red.xml b/MPChartExample/res/drawable/fade_red.xml new file mode 100644 index 0000000000..54ac10ba03 --- /dev/null +++ b/MPChartExample/res/drawable/fade_red.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 074b60c1bc..f1ad5d47a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -3,7 +3,9 @@ import android.graphics.Color; import android.graphics.Typeface; +import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.support.v4.content.ContextCompat; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -358,11 +360,9 @@ private void setData(int count, float range) { set1.setCircleRadius(3f); set1.setDrawCircleHole(false); set1.setValueTextSize(9f); - set1.setFillAlpha(65); - set1.setFillColor(Color.BLACK); -// set1.setDrawFilled(true); - // set1.setShader(new LinearGradient(0, 0, 0, mChart.getHeight(), - // Color.BLACK, Color.WHITE, Shader.TileMode.MIRROR)); + Drawable drawable = ContextCompat.getDrawable(this, R.drawable.fade_red); + set1.setFillDrawable(drawable); + set1.setDrawFilled(true); ArrayList dataSets = new ArrayList(); dataSets.add(set1); // add the datasets diff --git a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java index ee72ec01cc..ed25c8454a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/LineDataSet.java @@ -4,6 +4,7 @@ import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.utils.ColorTemplate; @@ -42,6 +43,10 @@ public class LineDataSet extends LineRadarDataSet implements ILineDataSet private boolean mDrawCircleHole = true; + /** the drawable to be used for filling the line surface*/ + protected Drawable mFillDrawable; + + public LineDataSet(List yVals, String label) { super(yVals, label); @@ -326,4 +331,32 @@ public void setFillFormatter(FillFormatter formatter) { public FillFormatter getFillFormatter() { return mFillFormatter; } + + + /** + * sets the color that is used for filling the line surface + * disables filling with a drawable + * @param color + */ + @Override + public void setFillColor(int color) { + super.setFillColor(color); + mFillDrawable = null; + } + + /** + * sets the drawable to be used for filling the line surface. The drawable is used + * instead of the solid color + * @param drawable + */ + @Override + public void setFillDrawable(Drawable drawable) { + mFillDrawable = drawable; + } + + @Override + public Drawable getFillDrawable() { + return mFillDrawable; + } + } diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java index e56fdb953d..21483d6070 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/implementation/RealmLineDataSet.java @@ -3,8 +3,8 @@ import android.content.Context; import android.graphics.Color; import android.graphics.DashPathEffect; +import android.graphics.drawable.Drawable; -import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.realm.base.RealmLineRadarDataSet; import com.github.mikephil.charting.formatter.DefaultFillFormatter; import com.github.mikephil.charting.formatter.FillFormatter; @@ -17,7 +17,6 @@ import io.realm.RealmObject; import io.realm.RealmResults; -import io.realm.dynamic.DynamicRealmObject; /** * Created by Philipp Jahoda on 21/10/15. @@ -66,6 +65,8 @@ public class RealmLineDataSet extends RealmLineRadarDataS private boolean mDrawCircleHole = true; + /** the drawable to be used for filling the line surface*/ + protected Drawable mFillDrawable; /** * Constructor for creating a LineDataSet with realm data. @@ -332,4 +333,15 @@ public void setFillFormatter(FillFormatter formatter) { public FillFormatter getFillFormatter() { return mFillFormatter; } + + @Override + public void setFillDrawable(Drawable drawable) { + mFillDrawable = drawable; + } + + @Override + public Drawable getFillDrawable() { + return mFillDrawable; + } + } diff --git a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java index 22e24fd608..561511147e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/interfaces/datasets/ILineDataSet.java @@ -1,6 +1,7 @@ package com.github.mikephil.charting.interfaces.datasets; import android.graphics.DashPathEffect; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.formatter.FillFormatter; @@ -81,4 +82,16 @@ public interface ILineDataSet extends ILineRadarDataSet { * @return */ FillFormatter getFillFormatter(); -} + + + /** + * Sets the drawable to be used for filling + * @param drawable + */ + void setFillDrawable(Drawable drawable); + + /** + * @return the drawable used for filling + */ + Drawable getFillDrawable(); +} \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 5e079ab6ce..7b2a72a04a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -5,6 +5,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.CircleBuffer; @@ -85,7 +86,7 @@ public void drawData(Canvas c) { if (width > 0 && height > 0) { - mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); mBitmapCanvas = new Canvas(mDrawBitmap); } else return; @@ -125,6 +126,22 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } + /** + * Draws the provided path in filled mode with the provided drawable. + */ + protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { + c.save(); + c.clipPath(filledPath); + + drawable.setBounds((int) mViewPortHandler.contentLeft(), + (int) mViewPortHandler.contentTop(), + (int) mViewPortHandler.contentRight(), + (int) mViewPortHandler.contentBottom()); + drawable.draw(c); + + c.restore(); + } + /** * Draws a cubic line. * @@ -252,6 +269,11 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf trans.pathValueToPixel(spline); + final Drawable drawable = dataSet.getFillDrawable(); + if (dataSet.getFillDrawable() != null) { + drawFilledPath(c, spline, drawable); + return; + } drawFilledPath(c, spline, dataSet.getFillColor(), dataSet.getFillAlpha()); } @@ -349,6 +371,12 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, trans.pathValueToPixel(filled); + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { + drawFilledPath(c, filled, drawable); + return; + } + drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); } diff --git a/README.md b/README.md index 151c1a0d39..14cc22bfc3 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,9 @@ Features - **LineChart (cubic lines)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) + - **LineChart (gradient fill)** +![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/line_chart_gradient.png) + - **Combined-Chart (bar- and linechart in this case)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) diff --git a/screenshots/line_chart_gradient.png b/screenshots/line_chart_gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..8c1d8e2483e49eeb477e2648a6da198c955edd12 GIT binary patch literal 46368 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∓e|B&KfEVder|=n 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 Je?Kw{{9iHn_XGd{ literal 0 HcmV?d00001 From 43fa3f2338871229ec5b008b835ce354df00657c Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Jan 2016 13:37:19 +0100 Subject: [PATCH 0687/1390] Fix issue #1401 --- .../com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java index 18ff37861a..15b027b3ff 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/custom/RealmFloat.java @@ -21,7 +21,7 @@ public float getFloatValue() { return floatValue; } - public void setFloatValue(Float value) { + public void setFloatValue(float value) { this.floatValue = value; } } From 981c7b4dc73798bf8877f444d198ba60e46b6a78 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Jan 2016 13:45:08 +0100 Subject: [PATCH 0688/1390] Unbind flag that allows unbinding of drawables to counter memory leaks --- .../mikephil/charting/charts/Chart.java | 46 +++++++++++++++++++ .../charting/renderer/LineChartRenderer.java | 2 +- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index e57bd56d09..cde8f605ee 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -1716,4 +1716,50 @@ public void setHardwareAccelerationEnabled(boolean enabled) { "Cannot enable/disable hardware acceleration for devices below API level 11."); } } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + //Log.i(LOG_TAG, "Detaching..."); + + if(mUnbind) + unbindDrawables(this); + } + + /** + * unbind flag + */ + private boolean mUnbind = false; + + /** + * Unbind all drawables to avoid memory leaks. + * Link: http://stackoverflow.com/a/6779164/1590502 + * + * @param view + */ + private void unbindDrawables(View view) { + + if (view.getBackground() != null) { + view.getBackground().setCallback(null); + } + if (view instanceof ViewGroup) { + for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { + unbindDrawables(((ViewGroup) view).getChildAt(i)); + } + ((ViewGroup) view).removeAllViews(); + } + } + + /** + * Set this to true to enable "unbinding" of drawables. When a View is detached + * from a window. This helps avoid memory leaks. + * Default: false + * Link: http://stackoverflow.com/a/6779164/1590502 + * + * @param enabled + */ + public void setUnbindEnabled(boolean enabled) { + this.mUnbind = enabled; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 00b65a3ded..48d7cb60df 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -87,7 +87,7 @@ public void drawData(Canvas c) { if (width > 0 && height > 0) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)); + mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)); mBitmapCanvas = new Canvas(mDrawBitmap.get()); } else return; From cf3a09d3e083639413b5597b1495563ee27c7f23 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Jan 2016 13:56:28 +0100 Subject: [PATCH 0689/1390] Allow drawables for RadarChart area filling. --- .../mpchartexample/RadarChartActivitry.java | 2 + .../charting/renderer/LineChartRenderer.java | 38 +------------ .../charting/renderer/LineRadarRenderer.java | 56 +++++++++++++++++++ .../charting/renderer/RadarChartRenderer.java | 28 +++++++--- 4 files changed, 79 insertions(+), 45 deletions(-) create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index f38804ddb1..0aee228a52 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -179,11 +179,13 @@ public void setData() { RadarDataSet set1 = new RadarDataSet(yVals1, "Set 1"); set1.setColor(ColorTemplate.VORDIPLOM_COLORS[0]); + set1.setFillColor(ColorTemplate.VORDIPLOM_COLORS[0]); set1.setDrawFilled(true); set1.setLineWidth(2f); RadarDataSet set2 = new RadarDataSet(yVals2, "Set 2"); set2.setColor(ColorTemplate.VORDIPLOM_COLORS[4]); + set2.setFillColor(ColorTemplate.VORDIPLOM_COLORS[4]); set2.setDrawFilled(true); set2.setLineWidth(2f); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 48d7cb60df..da004b0255 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -23,7 +23,7 @@ import java.lang.ref.WeakReference; import java.util.List; -public class LineChartRenderer extends LineScatterCandleRadarRenderer { +public class LineChartRenderer extends LineRadarRenderer { protected LineDataProvider mChart; @@ -127,22 +127,6 @@ protected void drawDataSet(Canvas c, ILineDataSet dataSet) { mRenderPaint.setPathEffect(null); } - /** - * Draws the provided path in filled mode with the provided drawable. - */ - protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { - c.save(); - c.clipPath(filledPath); - - drawable.setBounds((int) mViewPortHandler.contentLeft(), - (int) mViewPortHandler.contentTop(), - (int) mViewPortHandler.contentRight(), - (int) mViewPortHandler.contentBottom()); - drawable.draw(c); - - c.restore(); - } - /** * Draws a cubic line. * @@ -271,7 +255,7 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf trans.pathValueToPixel(spline); final Drawable drawable = dataSet.getFillDrawable(); - if (dataSet.getFillDrawable() != null) { + if (drawable != null) { drawFilledPath(c, spline, drawable); } else { @@ -384,24 +368,6 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, } } - /** - * Draws the provided path in filled mode with the provided color and alpha. - * Special thanks to Angelo Suzuki (https://github.com/tinsukE) for this. - * - * @param c - * @param filledPath - * @param fillColor - * @param fillAlpha - */ - protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) { - c.save(); - c.clipPath(filledPath); - - int color = (fillAlpha << 24) | (fillColor & 0xffffff); - c.drawColor(color); - c.restore(); - } - /** * Generates the path that is used for filled drawing. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java new file mode 100644 index 0000000000..bea77bdad9 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineRadarRenderer.java @@ -0,0 +1,56 @@ +package com.github.mikephil.charting.renderer; + +import android.graphics.Canvas; +import android.graphics.Path; +import android.graphics.drawable.Drawable; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.utils.ViewPortHandler; + +/** + * Created by Philipp Jahoda on 25/01/16. + */ +public abstract class LineRadarRenderer extends LineScatterCandleRadarRenderer { + + public LineRadarRenderer(ChartAnimator animator, ViewPortHandler viewPortHandler) { + super(animator, viewPortHandler); + } + + /** + * Draws the provided path in filled mode with the provided drawable. + * + * @param c + * @param filledPath + * @param drawable + */ + protected void drawFilledPath(Canvas c, Path filledPath, Drawable drawable) { + c.save(); + c.clipPath(filledPath); + + drawable.setBounds((int) mViewPortHandler.contentLeft(), + (int) mViewPortHandler.contentTop(), + (int) mViewPortHandler.contentRight(), + (int) mViewPortHandler.contentBottom()); + drawable.draw(c); + + c.restore(); + } + + /** + * Draws the provided path in filled mode with the provided color and alpha. + * Special thanks to Angelo Suzuki (https://github.com/tinsukE) for this. + * + * @param c + * @param filledPath + * @param fillColor + * @param fillAlpha + */ + protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) { + c.save(); + c.clipPath(filledPath); + + int color = (fillAlpha << 24) | (fillColor & 0xffffff); + c.drawColor(color); + c.restore(); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 5a9d13dcb9..61b3decdb1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PointF; +import android.graphics.drawable.Drawable; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.charts.RadarChart; @@ -16,7 +17,7 @@ import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.utils.ViewPortHandler; -public class RadarChartRenderer extends LineScatterCandleRadarRenderer { +public class RadarChartRenderer extends LineRadarRenderer { protected RadarChart mChart; @@ -96,20 +97,29 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { surface.close(); - // draw filled - if (dataSet.isDrawFilledEnabled()) { - mRenderPaint.setStyle(Paint.Style.FILL); - mRenderPaint.setAlpha(dataSet.getFillAlpha()); - c.drawPath(surface, mRenderPaint); - mRenderPaint.setAlpha(255); - } - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); mRenderPaint.setStyle(Paint.Style.STROKE); // draw the line (only if filled is disabled or alpha is below 255) if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) c.drawPath(surface, mRenderPaint); + + final Drawable drawable = dataSet.getFillDrawable(); + if (drawable != null) { + + drawFilledPath(c, surface, drawable); + } else { + + drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha()); + } +// +// // draw filled +// if (dataSet.isDrawFilledEnabled()) { +// mRenderPaint.setStyle(Paint.Style.FILL); +// mRenderPaint.setAlpha(dataSet.getFillAlpha()); +// c.drawPath(surface, mRenderPaint); +// mRenderPaint.setAlpha(255); +// } } @Override From ca6f24ba1580b68d489c7fef5fbe53e54a674bfc Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Jan 2016 14:34:37 +0100 Subject: [PATCH 0690/1390] Allow to set Bitmap.Config for LineChartRenderer - memory management --- .../charting/renderer/LineChartRenderer.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index da004b0255..7708cfdd93 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -44,6 +44,11 @@ public class LineChartRenderer extends LineRadarRenderer { */ protected Canvas mBitmapCanvas; + /** + * the bitmap configuration to be used + */ + protected Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888; + protected Path cubicPath = new Path(); protected Path cubicFillPath = new Path(); @@ -87,7 +92,7 @@ public void drawData(Canvas c) { if (width > 0 && height > 0) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)); + mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, mBitmapConfig)); mBitmapCanvas = new Canvas(mDrawBitmap.get()); } else return; @@ -571,6 +576,27 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } + /** + * Sets the Bitmap.Config to be used by this renderer. + * Default: Bitmap.Config.ARGB_8888 + * Use Bitmap.Config.ARGB_4444 to consume less memory. + * + * @param config + */ + public void setBitmapConfig(Bitmap.Config config) { + mBitmapConfig = config; + releaseBitmap(); + } + + /** + * Returns the Bitmap.Config that is used by this renderer. + * + * @return + */ + public Bitmap.Config getBitmapConfig() { + return mBitmapConfig; + } + /** * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. */ From e556ffb21e1895141fc8a9e65d49461d81f34f6a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 25 Jan 2016 14:58:50 +0100 Subject: [PATCH 0691/1390] Upgrade to realm 0.87.3 --- MPChartExample/build.gradle | 2 +- MPChartLib/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartExample/build.gradle b/MPChartExample/build.gradle index 6528de2b7a..2bb7897a47 100644 --- a/MPChartExample/build.gradle +++ b/MPChartExample/build.gradle @@ -54,6 +54,6 @@ dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':MPChartLib') // remove this if you only imported the example project compile 'com.android.support:appcompat-v7:23.1.1' - compile 'io.realm:realm-android:0.87.2' // dependency for realm-database API (http://realm.io) + compile 'io.realm:realm-android:0.87.3' // dependency for realm-database API (http://realm.io) //compile 'com.github.PhilJay:MPAndroidChart:v2.2.0' } diff --git a/MPChartLib/build.gradle b/MPChartLib/build.gradle index 0b979d49ea..0b4147476c 100644 --- a/MPChartLib/build.gradle +++ b/MPChartLib/build.gradle @@ -41,7 +41,7 @@ repositories { dependencies { //compile fileTree(dir: 'libs', include: ['*.jar']) //compile 'com.android.support:support-v4:19.+' - provided 'io.realm:realm-android:0.87.2' // "optional" dependency to realm-database API + provided 'io.realm:realm-android:0.87.3' // "optional" dependency to realm-database API } android.libraryVariants.all { variant -> From 95abc4513392803292ae6b5d4002de735b30dce6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 26 Jan 2016 18:23:14 +0100 Subject: [PATCH 0692/1390] New gradient linechart screenshot --- .../mikephil/charting/components/Legend.java | 2 +- .../mikephil/charting/components/XAxis.java | 2 +- screenshots/line_chart_gradient.png | Bin 46368 -> 32296 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java index 27425accd9..3a64b3a622 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/Legend.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/Legend.java @@ -108,7 +108,7 @@ public Legend() { mTextSize = Utils.convertDpToPixel(10f); mStackSpace = Utils.convertDpToPixel(3f); this.mXOffset = Utils.convertDpToPixel(5f); - this.mYOffset = Utils.convertDpToPixel(4f); + this.mYOffset = Utils.convertDpToPixel(4f); // 2 } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index 0578967cb6..a5cc5cb134 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -97,7 +97,7 @@ public enum XAxisPosition { public XAxis() { super(); - mYOffset = Utils.convertDpToPixel(4.f); + mYOffset = Utils.convertDpToPixel(4.f); // -3 } /** diff --git a/screenshots/line_chart_gradient.png b/screenshots/line_chart_gradient.png index 8c1d8e2483e49eeb477e2648a6da198c955edd12..2891dcec5f0871e787f3e2e404bfd7be8292c5e2 100644 GIT binary patch literal 32296 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 Z8WOj=LohiI5-1wlGjaK+#Ylbs{{;w%2}J+^ literal 46368 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∓e|B&KfEVder|=n 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 Je?Kw{{9iHn_XGd{ From 4c4d25b246df1e5a3b9d95ce2a98e5253f0448a6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 26 Jan 2016 18:26:36 +0100 Subject: [PATCH 0693/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b6f3a8214..eeba891e04 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Features ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/cubiclinechart.png) - **LineChart (gradient fill)** -![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/line_chart_gradient.png) +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/line_chart_gradient.png) - **Combined-Chart (bar- and linechart in this case)** ![alt tag](https://raw.github.com/PhilJay/MPChart/master/screenshots/combined_chart.png) From 4f5a32d6676b0a2bdc6552ead94d68cfe1e77c55 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 09:22:03 +0100 Subject: [PATCH 0694/1390] Remove redundant startAtZero from YAxis, now use setAxisMinValue --- MPChartExample/res/menu/bar.xml | 4 -- MPChartExample/res/menu/bubble.xml | 4 -- MPChartExample/res/menu/candle.xml | 4 -- MPChartExample/res/menu/draw.xml | 4 -- MPChartExample/res/menu/line.xml | 4 -- MPChartExample/res/menu/scatter.xml | 4 -- .../mpchartexample/AnotherBarActivity.java | 7 --- .../mpchartexample/BarChartActivity.java | 7 --- .../BarChartActivityMultiDataset.java | 6 -- .../mpchartexample/BarChartActivitySinus.java | 9 --- .../mpchartexample/BubbleChartActivity.java | 10 ---- .../CandleStickChartActivity.java | 7 --- .../CubicLineChartActivity.java | 7 --- .../mpchartexample/DrawChartActivity.java | 6 -- .../HorizontalBarChartActivity.java | 6 -- .../InvertedLineChartActivity.java | 6 -- .../mpchartexample/LineChartActivity1.java | 7 --- .../mpchartexample/LineChartActivity2.java | 8 +-- .../MultiLineChartActivity.java | 6 -- .../mpchartexample/RadarChartActivitry.java | 2 +- .../RealtimeLineChartActivity.java | 1 - .../mpchartexample/ScatterChartActivity.java | 6 -- .../mpchartexample/StackedBarActivity.java | 6 -- .../StackedBarActivityNegative.java | 7 --- .../fragments/SineCosineFragment.java | 1 - .../realm/RealmBaseActivity.java | 1 - .../RealmDatabaseActivityHorizontalBar.java | 2 +- .../charting/charts/BarLineChartBase.java | 57 ++++--------------- .../mikephil/charting/charts/RadarChart.java | 24 ++------ .../mikephil/charting/components/YAxis.java | 30 ++++------ .../formatter/DefaultFillFormatter.java | 27 ++++----- .../charting/renderer/YAxisRenderer.java | 9 ++- .../renderer/YAxisRendererRadarChart.java | 7 +-- 33 files changed, 48 insertions(+), 248 deletions(-) diff --git a/MPChartExample/res/menu/bar.xml b/MPChartExample/res/menu/bar.xml index 6a1920421d..a65c8730e8 100644 --- a/MPChartExample/res/menu/bar.xml +++ b/MPChartExample/res/menu/bar.xml @@ -25,10 +25,6 @@ android:id="@+id/animateXY" android:title="Animate XY"> - - diff --git a/MPChartExample/res/menu/bubble.xml b/MPChartExample/res/menu/bubble.xml index 146a06e397..a100c5085d 100644 --- a/MPChartExample/res/menu/bubble.xml +++ b/MPChartExample/res/menu/bubble.xml @@ -9,10 +9,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/res/menu/candle.xml b/MPChartExample/res/menu/candle.xml index bb947aa221..cdf1c4e4dd 100644 --- a/MPChartExample/res/menu/candle.xml +++ b/MPChartExample/res/menu/candle.xml @@ -5,10 +5,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/res/menu/draw.xml b/MPChartExample/res/menu/draw.xml index 3f133dae22..3965a75607 100644 --- a/MPChartExample/res/menu/draw.xml +++ b/MPChartExample/res/menu/draw.xml @@ -17,10 +17,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/res/menu/line.xml b/MPChartExample/res/menu/line.xml index 16f488afac..5d248a4145 100644 --- a/MPChartExample/res/menu/line.xml +++ b/MPChartExample/res/menu/line.xml @@ -21,10 +21,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/res/menu/scatter.xml b/MPChartExample/res/menu/scatter.xml index 146a06e397..a100c5085d 100644 --- a/MPChartExample/res/menu/scatter.xml +++ b/MPChartExample/res/menu/scatter.xml @@ -9,10 +9,6 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> - - diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java index 244cac2b4f..edf3409c01 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/AnotherBarActivity.java @@ -134,13 +134,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index 81056b9a5b..0f9bf47e13 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -173,13 +173,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.notifyDataSetChanged(); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java index d3fe246c76..92046405dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivityMultiDataset.java @@ -149,12 +149,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java index 745f1f441d..a84281e9d6 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivitySinus.java @@ -87,7 +87,6 @@ protected void onCreate(Bundle savedInstanceState) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(mTf); leftAxis.setLabelCount(6, false); - leftAxis.setStartAtZero(false); leftAxis.setAxisMinValue(-2.5f); leftAxis.setAxisMaxValue(2.5f); @@ -95,7 +94,6 @@ protected void onCreate(Bundle savedInstanceState) { rightAxis.setDrawGridLines(false); rightAxis.setTypeface(mTf); rightAxis.setLabelCount(6, false); - rightAxis.setStartAtZero(false); rightAxis.setAxisMinValue(-2.5f); rightAxis.setAxisMaxValue(2.5f); @@ -158,13 +156,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.notifyDataSetChanged(); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(1500); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java index f47e1e2a47..fa6568f8f2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BubbleChartActivity.java @@ -75,9 +75,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setMaxVisibleValueCount(200); mChart.setPinchZoom(true); - mChart.getAxisLeft().setStartAtZero(false); - mChart.getAxisRight().setStartAtZero(false); - mSeekBarX.setProgress(5); mSeekBarY.setProgress(50); @@ -88,7 +85,6 @@ protected void onCreate(Bundle savedInstanceState) { YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setSpaceTop(30f); - yl.setStartAtZero(false); yl.setSpaceBottom(30f); mChart.getAxisRight().setEnabled(false); @@ -136,12 +132,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java index 414530a9c3..bb597073eb 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CandleStickChartActivity.java @@ -70,7 +70,6 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setLabelCount(7, false); leftAxis.setDrawGridLines(false); leftAxis.setDrawAxisLine(false); - leftAxis.setStartAtZero(false); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setEnabled(false); @@ -130,12 +129,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 0cf43fe45d..48731d868e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -83,7 +83,6 @@ protected void onCreate(Bundle savedInstanceState) { YAxis y = mChart.getAxisLeft(); y.setTypeface(tf); y.setLabelCount(6, false); - y.setStartAtZero(false); y.setTextColor(Color.WHITE); y.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART); y.setDrawGridLines(false); @@ -173,12 +172,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java index b1093f2ac6..d12b3ecbd7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/DrawChartActivity.java @@ -125,12 +125,6 @@ public boolean onOptionsItemSelected(MenuItem item) { } break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 05c181fefe..a23fb51432 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -175,12 +175,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java index 0a0c7b64b4..36c0a5f3dd 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/InvertedLineChartActivity.java @@ -173,12 +173,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f1ad5d47a2..e7cf5734d9 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -130,7 +130,6 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.addLimitLine(ll2); leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); - leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); @@ -244,12 +243,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index f69c07b561..8808646e9b 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -114,13 +114,13 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setTypeface(tf); leftAxis.setTextColor(ColorTemplate.getHoloBlue()); leftAxis.setAxisMaxValue(200f); + leftAxis.setAxisMinValue(0f); leftAxis.setDrawGridLines(true); YAxis rightAxis = mChart.getAxisRight(); rightAxis.setTypeface(tf); rightAxis.setTextColor(Color.RED); rightAxis.setAxisMaxValue(900); - rightAxis.setStartAtZero(false); rightAxis.setAxisMinValue(-200); rightAxis.setDrawGridLines(false); } @@ -201,12 +201,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionTogglePinch: { if (mChart.isPinchZoomEnabled()) mChart.setPinchZoom(false); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java index db136ab20d..5ff37be451 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/MultiLineChartActivity.java @@ -168,12 +168,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionSave: { // mChart.saveToGallery("title"+System.currentTimeMillis()); mChart.saveToPath("title" + System.currentTimeMillis(), ""); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 0aee228a52..941eefe106 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -64,7 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { yAxis.setTypeface(tf); yAxis.setLabelCount(5, false); yAxis.setTextSize(9f); - yAxis.setStartAtZero(true); + yAxis.setAxisMinValue(0f); Legend l = mChart.getLegend(); l.setPosition(LegendPosition.RIGHT_OF_CHART); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java index cf6661ba87..a1f31d1043 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RealtimeLineChartActivity.java @@ -88,7 +88,6 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setTextColor(Color.WHITE); leftAxis.setAxisMaxValue(100f); leftAxis.setAxisMinValue(0f); - leftAxis.setStartAtZero(false); leftAxis.setDrawGridLines(true); YAxis rightAxis = mChart.getAxisRight(); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java index 02a7760873..120db36ebc 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/ScatterChartActivity.java @@ -135,12 +135,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.notifyDataSetChanged(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.actionToggleFilter: { Approximator a = new Approximator(ApproximatorType.DOUGLAS_PEUCKER, 25); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index ea106e4de2..9a65c5913d 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -147,12 +147,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java index 17625a8ede..7d8bd37d48 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivityNegative.java @@ -59,7 +59,6 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValueAboveBar(true); mChart.getAxisLeft().setEnabled(false); - mChart.getAxisRight().setStartAtZero(false); mChart.getAxisRight().setAxisMaxValue(25f); mChart.getAxisRight().setAxisMinValue(-25f); mChart.getAxisRight().setLabelCount(7, false); @@ -161,12 +160,6 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } - case R.id.actionToggleStartzero: { - mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); - mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); - mChart.invalidate(); - break; - } case R.id.animateX: { mChart.animateX(3000); break; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java index b2e2cda033..418a856f5f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/fragments/SineCosineFragment.java @@ -41,7 +41,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa YAxis leftAxis = mChart.getAxisLeft(); leftAxis.setTypeface(tf); - leftAxis.setStartAtZero(false); leftAxis.setAxisMaxValue(1.2f); leftAxis.setAxisMinValue(-1.2f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java index 351fb1c0c9..09bcc59e1e 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmBaseActivity.java @@ -60,7 +60,6 @@ protected void setup(Chart chart) { YAxis leftAxis = mChart.getAxisLeft(); leftAxis.removeAllLimitLines(); // reset all limit lines to avoid overlapping lines - leftAxis.setStartAtZero(false); leftAxis.setTypeface(mTf); leftAxis.setTextSize(8f); leftAxis.setTextColor(Color.DKGRAY); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java index f7a286bfe7..7a2ef39c18 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/realm/RealmDatabaseActivityHorizontalBar.java @@ -34,7 +34,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (HorizontalBarChart) findViewById(R.id.chart1); setup(mChart); - mChart.getAxisLeft().setStartAtZero(true); + mChart.getAxisLeft().setAxisMinValue(0f); mChart.setDrawValueAboveBar(false); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c922823194..de1bd99510 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -24,14 +24,14 @@ import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.data.filter.Approximator; import com.github.mikephil.charting.highlight.ChartHighlighter; -import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; +import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.interfaces.dataprovider.BarLineScatterCandleBubbleDataProvider; +import com.github.mikephil.charting.interfaces.datasets.IBarLineScatterCandleBubbleDataSet; import com.github.mikephil.charting.jobs.MoveViewJob; import com.github.mikephil.charting.listener.BarLineChartTouchListener; import com.github.mikephil.charting.listener.OnDrawListener; import com.github.mikephil.charting.renderer.XAxisRenderer; import com.github.mikephil.charting.renderer.YAxisRenderer; -import com.github.mikephil.charting.highlight.Highlight; import com.github.mikephil.charting.utils.PointD; import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.Utils; @@ -360,20 +360,18 @@ protected void calcMinMax() { float minRight = mData.getYMin(AxisDependency.RIGHT); float maxRight = mData.getYMax(AxisDependency.RIGHT); - float leftRange = Math.abs(maxLeft - (mAxisLeft.isStartAtZeroEnabled() ? 0 : minLeft)); - float rightRange = Math.abs(maxRight - (mAxisRight.isStartAtZeroEnabled() ? 0 : minRight)); + float leftRange = Math.abs(maxLeft - minLeft); + float rightRange = Math.abs(maxRight - minRight); // in case all values are equal if (leftRange == 0f) { maxLeft = maxLeft + 1f; - if (!mAxisLeft.isStartAtZeroEnabled()) - minLeft = minLeft - 1f; + minLeft = minLeft - 1f; } if (rightRange == 0f) { maxRight = maxRight + 1f; - if (!mAxisRight.isStartAtZeroEnabled()) - minRight = minRight - 1f; + minRight = minRight - 1f; } float topSpaceLeft = leftRange / 100f * mAxisLeft.getSpaceTop(); @@ -385,45 +383,12 @@ protected void calcMinMax() { mDeltaX = Math.abs(mXChartMax - mXChartMin); // Consider sticking one of the edges of the axis to zero (0.0) + // Use the values as they are + mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); + mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); - if (mAxisLeft.isStartAtZeroEnabled()) { - if (minLeft < 0.f && maxLeft < 0.f) { - // If the values are all negative, let's stay in the negative zone - mAxisLeft.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft)); - mAxisLeft.mAxisMaximum = 0.f; - } else if (minLeft >= 0.0) { - // We have positive values only, stay in the positive zone - mAxisLeft.mAxisMinimum = 0.f; - mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } else { - // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) - mAxisLeft.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft)); - mAxisLeft.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } - } else { - // Use the values as they are - mAxisLeft.mAxisMinimum = !Float.isNaN(mAxisLeft.getAxisMinValue()) ? mAxisLeft.getAxisMinValue() : (minLeft - bottomSpaceLeft); - mAxisLeft.mAxisMaximum = !Float.isNaN(mAxisLeft.getAxisMaxValue()) ? mAxisLeft.getAxisMaxValue() : (maxLeft + topSpaceLeft); - } - - if (mAxisRight.isStartAtZeroEnabled()) { - if (minRight < 0.f && maxRight < 0.f) { - // If the values are all negative, let's stay in the negative zone - mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); - mAxisRight.mAxisMaximum = 0.f; - } else if (minRight >= 0.f) { - // We have positive values only, stay in the positive zone - mAxisRight.mAxisMinimum = 0.f; - mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); - } else { - // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) - mAxisRight.mAxisMinimum = Math.min(0.f, !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight)); - mAxisRight.mAxisMaximum = Math.max(0.f, !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight)); - } - } else { - mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight); - mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight); - } + mAxisRight.mAxisMinimum = !Float.isNaN(mAxisRight.getAxisMinValue()) ? mAxisRight.getAxisMinValue() : (minRight - bottomSpaceRight); + mAxisRight.mAxisMaximum = !Float.isNaN(mAxisRight.getAxisMaxValue()) ? mAxisRight.getAxisMaxValue() : (maxRight + topSpaceRight); mAxisLeft.mAxisRange = Math.abs(mAxisLeft.mAxisMaximum - mAxisLeft.mAxisMinimum); mAxisRight.mAxisRange = Math.abs(mAxisRight.mAxisMaximum - mAxisRight.mAxisMinimum); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 41451092a2..7d7e31243c 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -113,7 +113,7 @@ protected void calcMinMax() { mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - float leftRange = Math.abs(maxLeft - (mYAxis.isStartAtZeroEnabled() ? 0 : minLeft)); + float leftRange = Math.abs(maxLeft - minLeft); float topSpaceLeft = leftRange / 100f * mYAxis.getSpaceTop(); float bottomSpaceLeft = leftRange / 100f * mYAxis.getSpaceBottom(); @@ -121,25 +121,9 @@ protected void calcMinMax() { mXChartMax = mData.getXVals().size() - 1; mDeltaX = Math.abs(mXChartMax - mXChartMin); - if (mYAxis.isStartAtZeroEnabled()) { - if (minLeft < 0.f && maxLeft < 0.f) { - // If the values are all negative, let's stay in the negative zone - mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); - mYAxis.mAxisMaximum = 0.f; - } else if (minLeft >= 0.0) { - // We have positive values only, stay in the positive zone - mYAxis.mAxisMinimum = 0.f; - mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } else { - // Stick the minimum to 0.0 or less, and maximum to 0.0 or more (startAtZero for negative/positive at the same time) - mYAxis.mAxisMinimum = Math.min(0.f, !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft)); - mYAxis.mAxisMaximum = Math.max(0.f, !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft)); - } - } else { - // Use the values as they are - mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft); - mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft); - } + // Use the values as they are + mYAxis.mAxisMinimum = !Float.isNaN(mYAxis.getAxisMinValue()) ? mYAxis.getAxisMinValue() : (minLeft - bottomSpaceLeft); + mYAxis.mAxisMaximum = !Float.isNaN(mYAxis.getAxisMaxValue()) ? mYAxis.getAxisMaxValue() : (maxLeft + topSpaceLeft); mYAxis.mAxisRange = Math.abs(mYAxis.mAxisMaximum - mYAxis.mAxisMinimum); } diff --git a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java index c87d64b04e..0570765a44 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/YAxis.java @@ -4,8 +4,8 @@ import com.github.mikephil.charting.formatter.DefaultValueFormatter; import com.github.mikephil.charting.formatter.DefaultYAxisValueFormatter; -import com.github.mikephil.charting.utils.Utils; import com.github.mikephil.charting.formatter.YAxisValueFormatter; +import com.github.mikephil.charting.utils.Utils; /** * Class representing the y-axis labels settings and its entries. Only use the setter methods to modify it. Do not @@ -57,11 +57,6 @@ public class YAxis extends AxisBase { */ protected boolean mInverted = false; - /** - * if true, the y-label entries will always start at zero - */ - protected boolean mStartAtZero = true; - /** * if true, the set number of y-labels will be forced */ @@ -70,7 +65,7 @@ public class YAxis extends AxisBase { /** * custom minimum value this axis represents */ - protected float mCustomAxisMin = Float.NaN; + protected float mCustomAxisMin = 0f; /** * custom maximum value this axis represents @@ -248,21 +243,16 @@ public boolean isInverted() { } /** - * enable this to force the y-axis labels to always start at zero + * Use setAxisMinValue(...) instead. * - * @param enabled + * @param startAtZero */ - public void setStartAtZero(boolean enabled) { - this.mStartAtZero = enabled; - } - - /** - * returns true if the chart is set to start at zero, false otherwise - * - * @return - */ - public boolean isStartAtZeroEnabled() { - return mStartAtZero; + @Deprecated + public void setStartAtZero(boolean startAtZero) { + if (startAtZero) + setAxisMinValue(0f); + else + resetAxisMinValue(); } public float getAxisMinValue() { diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java index e0fc63addf..54e9cca8b3 100644 --- a/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/DefaultFillFormatter.java @@ -2,8 +2,8 @@ import com.github.mikephil.charting.data.LineData; -import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; /** * Default formatter that calculates the position of the filled line. @@ -25,23 +25,18 @@ public float getFillLinePosition(ILineDataSet dataSet, LineDataProvider dataProv fillMin = 0f; } else { - if (!dataProvider.getAxis(dataSet.getAxisDependency()).isStartAtZeroEnabled()) { - - float max, min; + float max, min; - if (data.getYMax() > 0) - max = 0f; - else - max = chartMaxY; - if (data.getYMin() < 0) - min = 0f; - else - min = chartMinY; + if (data.getYMax() > 0) + max = 0f; + else + max = chartMaxY; + if (data.getYMin() < 0) + min = 0f; + else + min = chartMinY; - fillMin = dataSet.getYMin() >= 0 ? min : max; - } else { - fillMin = 0f; - } + fillMin = dataSet.getYMin() >= 0 ? min : max; } return fillMin; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index 1d174f430e..e4652eab35 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -136,7 +136,14 @@ protected void computeAxisValues(float min, float max) { mYAxis.mEntries = new float[n]; } - for (f = first, i = 0; i < n; f += interval, ++i) { + f = first; + Double d = new Double(f); + + // check negative zero + mYAxis.mEntries[0] = (float) (d.equals(-0.0) ? Math.abs(f) : f); + f += interval; + + for (i = 1; i < n; f += interval, ++i) { mYAxis.mEntries[i] = (float) f; } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java index 2f1b254f9e..1dbefe08ae 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererRadarChart.java @@ -85,11 +85,6 @@ protected void computeAxisValues(float min, float max) { final double rawCount = yMin / interval; double first = rawCount < 0.0 ? Math.floor(rawCount) * interval : Math.ceil(rawCount) * interval; - if (first < yMin && mYAxis.isStartAtZeroEnabled()) { - // Force the first label to be at the 0 (or smallest negative value) - first = yMin; - } - if (first == 0.0) // Fix for IEEE negative zero case (Where value == -0.0, and 0.0 == -0.0) first = 0.0; @@ -124,7 +119,7 @@ protected void computeAxisValues(float min, float max) { mYAxis.mDecimals = 0; } - if (!mYAxis.isStartAtZeroEnabled() && mYAxis.mEntries[0] < yMin) { + if (mYAxis.mEntries[0] < yMin) { // If startAtZero is disabled, and the first label is lower that the axis minimum, // Then adjust the axis minimum mYAxis.mAxisMinimum = mYAxis.mEntries[0]; From 7b1239ccf248a3ea06b7f4abd1015185c9fd0347 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 12:28:26 +0100 Subject: [PATCH 0695/1390] Fix double tap issue with listener #1411 --- .../mikephil/charting/listener/BarLineChartTouchListener.java | 1 - 1 file changed, 1 deletion(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java index 6de33f84c4..34771283c6 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/BarLineChartTouchListener.java @@ -490,7 +490,6 @@ public boolean onDoubleTap(MotionEvent e) { if (l != null) { l.onChartDoubleTapped(e); - return super.onDoubleTap(e); } // check if double-tap zooming is enabled From 9137956ec197866206545c2e965fe77dea0faaaf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 15:35:16 +0100 Subject: [PATCH 0696/1390] Minor bugfixing or recent additions --- .../data/realm/base/RealmLineRadarDataSet.java | 1 + .../charting/renderer/RadarChartRenderer.java | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java index d55f1bccd0..f8ea4df17d 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/realm/base/RealmLineRadarDataSet.java @@ -83,6 +83,7 @@ public int getFillColor() { */ public void setFillColor(int color) { mFillColor = color; + mFillDrawable = null; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 61b3decdb1..255e737a6f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -97,13 +97,6 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { surface.close(); - mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); - mRenderPaint.setStyle(Paint.Style.STROKE); - - // draw the line (only if filled is disabled or alpha is below 255) - if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) - c.drawPath(surface, mRenderPaint); - final Drawable drawable = dataSet.getFillDrawable(); if (drawable != null) { @@ -112,6 +105,13 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { drawFilledPath(c, surface, dataSet.getFillColor(), dataSet.getFillAlpha()); } + + mRenderPaint.setStrokeWidth(dataSet.getLineWidth()); + mRenderPaint.setStyle(Paint.Style.STROKE); + + // draw the line (only if filled is disabled or alpha is below 255) + if (!dataSet.isDrawFilledEnabled() || dataSet.getFillAlpha() < 255) + c.drawPath(surface, mRenderPaint); // // // draw filled // if (dataSet.isDrawFilledEnabled()) { From 99c87c4d89c2d1da706355557226231b7cd13101 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 15:52:24 +0100 Subject: [PATCH 0697/1390] Fix 1410 --- .../mpchartexample/LineChartActivity1.java | 1 + .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 2 +- .../mikephil/charting/components/XAxis.java | 10 +------ .../mikephil/charting/data/ChartData.java | 28 +++++++++++-------- .../charting/renderer/XAxisRenderer.java | 18 ++++++++---- 6 files changed, 33 insertions(+), 28 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f1ad5d47a2..80386c8078 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -131,6 +131,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); leftAxis.setStartAtZero(false); + leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c922823194..7647f13cff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -341,7 +341,7 @@ public void notifyDataSetChanged() { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 41451092a2..56bc6e3c9a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -171,7 +171,7 @@ public void notifyDataSetChanged() { // } mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum); - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null && !mLegend.isLegendCustom()) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index a5cc5cb134..7343baaef8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -47,7 +47,7 @@ public class XAxis extends AxisBase { /** * This is the angle for drawing the X axis labels (in degrees) */ - protected float mLabelRotationAngle = 0.f; + protected float mLabelRotationAngle = 0f; /** * the space that should be left out (in characters) between the x-axis @@ -67,14 +67,6 @@ public class XAxis extends AxisBase { * it's auto, if true, then custom. default: false (automatic modulus) */ private boolean mIsAxisModulusCustom = false; - - /** - * the modulus that indicates if a value at a specified index in an - * array(list) for the y-axis-labels is drawn or not. If index % modulus == - * 0 DRAW, else dont draw. THIS IS ONLY FOR HORIZONTAL BARCHART. - */ - public int mYAxisLabelModulus = 1; - /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 4cb96aa423..9040edead5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -45,10 +45,10 @@ public abstract class ChartData> { private int mYValCount = 0; /** - * contains the average length (in characters) an entry in the x-vals array + * contains the maximum length (in characters) an entry in the x-vals array * has */ - private float mXValAverageLength = 0; + private float mXValMaximumLength = 0; /** * holds all x-values the chart represents @@ -139,26 +139,30 @@ protected void init() { calcYValueCount(); calcMinMax(0, mYValCount); - calcXValAverageLength(); + calcXValMaximumLength(); } /** * calculates the average length (in characters) across all x-value strings */ - private void calcXValAverageLength() { + private void calcXValMaximumLength() { if (mXVals.size() <= 0) { - mXValAverageLength = 1; + mXValMaximumLength = 1; return; } - float sum = 1f; + int max = 1; for (int i = 0; i < mXVals.size(); i++) { - sum += mXVals.get(i).length(); + + int length = mXVals.get(i).length(); + + if(length > max) + max = length; } - mXValAverageLength = sum / (float) mXVals.size(); + mXValMaximumLength = max; } /** @@ -343,13 +347,13 @@ public float getYMax(AxisDependency axis) { } /** - * returns the average length (in characters) across all values in the + * returns the maximum length (in characters) across all values in the * x-vals array * * @return */ - public float getXValAverageLength() { - return mXValAverageLength; + public float getXValMaximumLength() { + return mXValMaximumLength; } /** @@ -378,7 +382,7 @@ public List getXVals() { */ public void addXValue(String xVal) { - mXValAverageLength = (mXValAverageLength + xVal.length()) / 2f; + mXValMaximumLength = (mXValMaximumLength + xVal.length()) / 2f; mXVals.add(xVal); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 51109ca237..8c977f300e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -40,10 +40,9 @@ public void computeAxis(float xValAverageLength, List xValues) { StringBuilder widthText = new StringBuilder(); - int max = Math.round(xValAverageLength - + mXAxis.getSpaceBetweenLabels()); + int xValChars = Math.round(xValAverageLength); - for (int i = 0; i < max; i++) { + for (int i = 0; i < xValChars; i++) { widthText.append('h'); } @@ -57,9 +56,18 @@ public void computeAxis(float xValAverageLength, List xValues) { labelHeight, mXAxis.getLabelRotationAngle()); - mXAxis.mLabelWidth = Math.round(labelWidth); + StringBuilder space = new StringBuilder(); + int xValSpaceChars = mXAxis.getSpaceBetweenLabels(); + + for (int i = 0; i < xValSpaceChars; i++) { + space.append('h'); + } + + final FSize spaceSize = Utils.calcTextSize(mAxisLabelPaint, space.toString()); + + mXAxis.mLabelWidth = Math.round(labelWidth + spaceSize.width); mXAxis.mLabelHeight = Math.round(labelHeight); - mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width); + mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width + spaceSize.width); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); mXAxis.setValues(xValues); From 4f8b80b6ccda68499e045678e457a328ec3c5a17 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 15:52:24 +0100 Subject: [PATCH 0698/1390] Fix #1410 --- .../mpchartexample/LineChartActivity1.java | 1 + .../charting/charts/BarLineChartBase.java | 2 +- .../mikephil/charting/charts/RadarChart.java | 2 +- .../mikephil/charting/components/XAxis.java | 10 +------ .../mikephil/charting/data/ChartData.java | 28 +++++++++++-------- .../charting/renderer/XAxisRenderer.java | 18 ++++++++---- 6 files changed, 33 insertions(+), 28 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index f1ad5d47a2..80386c8078 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -131,6 +131,7 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); leftAxis.setStartAtZero(false); + leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index c922823194..7647f13cff 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -341,7 +341,7 @@ public void notifyDataSetChanged() { mAxisRendererLeft.computeAxis(mAxisLeft.mAxisMinimum, mAxisLeft.mAxisMaximum); mAxisRendererRight.computeAxis(mAxisRight.mAxisMinimum, mAxisRight.mAxisMaximum); - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java index 41451092a2..56bc6e3c9a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/RadarChart.java @@ -171,7 +171,7 @@ public void notifyDataSetChanged() { // } mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum); - mXAxisRenderer.computeAxis(mData.getXValAverageLength(), mData.getXVals()); + mXAxisRenderer.computeAxis(mData.getXValMaximumLength(), mData.getXVals()); if (mLegend != null && !mLegend.isLegendCustom()) mLegendRenderer.computeLegend(mData); diff --git a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java index a5cc5cb134..7343baaef8 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/XAxis.java @@ -47,7 +47,7 @@ public class XAxis extends AxisBase { /** * This is the angle for drawing the X axis labels (in degrees) */ - protected float mLabelRotationAngle = 0.f; + protected float mLabelRotationAngle = 0f; /** * the space that should be left out (in characters) between the x-axis @@ -67,14 +67,6 @@ public class XAxis extends AxisBase { * it's auto, if true, then custom. default: false (automatic modulus) */ private boolean mIsAxisModulusCustom = false; - - /** - * the modulus that indicates if a value at a specified index in an - * array(list) for the y-axis-labels is drawn or not. If index % modulus == - * 0 DRAW, else dont draw. THIS IS ONLY FOR HORIZONTAL BARCHART. - */ - public int mYAxisLabelModulus = 1; - /** * if set to true, the chart will avoid that the first and last label entry * in the chart "clip" off the edge of the chart diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 4cb96aa423..9040edead5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -45,10 +45,10 @@ public abstract class ChartData> { private int mYValCount = 0; /** - * contains the average length (in characters) an entry in the x-vals array + * contains the maximum length (in characters) an entry in the x-vals array * has */ - private float mXValAverageLength = 0; + private float mXValMaximumLength = 0; /** * holds all x-values the chart represents @@ -139,26 +139,30 @@ protected void init() { calcYValueCount(); calcMinMax(0, mYValCount); - calcXValAverageLength(); + calcXValMaximumLength(); } /** * calculates the average length (in characters) across all x-value strings */ - private void calcXValAverageLength() { + private void calcXValMaximumLength() { if (mXVals.size() <= 0) { - mXValAverageLength = 1; + mXValMaximumLength = 1; return; } - float sum = 1f; + int max = 1; for (int i = 0; i < mXVals.size(); i++) { - sum += mXVals.get(i).length(); + + int length = mXVals.get(i).length(); + + if(length > max) + max = length; } - mXValAverageLength = sum / (float) mXVals.size(); + mXValMaximumLength = max; } /** @@ -343,13 +347,13 @@ public float getYMax(AxisDependency axis) { } /** - * returns the average length (in characters) across all values in the + * returns the maximum length (in characters) across all values in the * x-vals array * * @return */ - public float getXValAverageLength() { - return mXValAverageLength; + public float getXValMaximumLength() { + return mXValMaximumLength; } /** @@ -378,7 +382,7 @@ public List getXVals() { */ public void addXValue(String xVal) { - mXValAverageLength = (mXValAverageLength + xVal.length()) / 2f; + mXValMaximumLength = (mXValMaximumLength + xVal.length()) / 2f; mXVals.add(xVal); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 51109ca237..8c977f300e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -40,10 +40,9 @@ public void computeAxis(float xValAverageLength, List xValues) { StringBuilder widthText = new StringBuilder(); - int max = Math.round(xValAverageLength - + mXAxis.getSpaceBetweenLabels()); + int xValChars = Math.round(xValAverageLength); - for (int i = 0; i < max; i++) { + for (int i = 0; i < xValChars; i++) { widthText.append('h'); } @@ -57,9 +56,18 @@ public void computeAxis(float xValAverageLength, List xValues) { labelHeight, mXAxis.getLabelRotationAngle()); - mXAxis.mLabelWidth = Math.round(labelWidth); + StringBuilder space = new StringBuilder(); + int xValSpaceChars = mXAxis.getSpaceBetweenLabels(); + + for (int i = 0; i < xValSpaceChars; i++) { + space.append('h'); + } + + final FSize spaceSize = Utils.calcTextSize(mAxisLabelPaint, space.toString()); + + mXAxis.mLabelWidth = Math.round(labelWidth + spaceSize.width); mXAxis.mLabelHeight = Math.round(labelHeight); - mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width); + mXAxis.mLabelRotatedWidth = Math.round(labelRotatedSize.width + spaceSize.width); mXAxis.mLabelRotatedHeight = Math.round(labelRotatedSize.height); mXAxis.setValues(xValues); From 19f1b3b444758b5ba80ae0634f277ba2171dfff8 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Wed, 27 Jan 2016 16:23:24 +0100 Subject: [PATCH 0699/1390] Fixes for recent changes --- .../xxmassdeveloper/mpchartexample/LineChartActivity1.java | 1 - .../src/com/github/mikephil/charting/data/ChartData.java | 4 +++- .../com/github/mikephil/charting/renderer/XAxisRenderer.java | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 80386c8078..f1ad5d47a2 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -131,7 +131,6 @@ protected void onCreate(Bundle savedInstanceState) { leftAxis.setAxisMaxValue(220f); leftAxis.setAxisMinValue(-50f); leftAxis.setStartAtZero(false); - leftAxis.setStartAtZero(false); //leftAxis.setYOffset(20f); leftAxis.enableGridDashedLine(10f, 10f, 0f); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java index 9040edead5..b33f02d641 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/ChartData.java @@ -382,7 +382,9 @@ public List getXVals() { */ public void addXValue(String xVal) { - mXValMaximumLength = (mXValMaximumLength + xVal.length()) / 2f; + if(xVal != null && xVal.length() > mXValMaximumLength) + mXValMaximumLength = xVal.length(); + mXVals.add(xVal); } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 8c977f300e..a0a2bff642 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -33,14 +33,14 @@ public XAxisRenderer(ViewPortHandler viewPortHandler, XAxis xAxis, Transformer t mAxisLabelPaint.setTextSize(Utils.convertDpToPixel(10f)); } - public void computeAxis(float xValAverageLength, List xValues) { + public void computeAxis(float xValMaximumLength, List xValues) { mAxisLabelPaint.setTypeface(mXAxis.getTypeface()); mAxisLabelPaint.setTextSize(mXAxis.getTextSize()); StringBuilder widthText = new StringBuilder(); - int xValChars = Math.round(xValAverageLength); + int xValChars = Math.round(xValMaximumLength); for (int i = 0; i < xValChars; i++) { widthText.append('h'); From 6ee101c5c68fa8029b4b8a5ff8b158cc9e029231 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 10:59:02 +0200 Subject: [PATCH 0700/1390] Support for animating Radar charts --- MPChartExample/res/menu/radar.xml | 12 +++++++ .../mpchartexample/RadarChartActivitry.java | 17 ++++++++++ .../charting/renderer/RadarChartRenderer.java | 33 ++++++++++++++----- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/MPChartExample/res/menu/radar.xml b/MPChartExample/res/menu/radar.xml index cbde056f4f..8dbcf05e9c 100644 --- a/MPChartExample/res/menu/radar.xml +++ b/MPChartExample/res/menu/radar.xml @@ -13,6 +13,18 @@ android:id="@+id/actionToggleHighlight" android:title="Toggle Highlight"> + + + + + + diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 0aee228a52..ba1e21b938 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -56,6 +56,11 @@ protected void onCreate(Bundle savedInstanceState) { setData(); + mChart.animateXY( + 1400, 1400, + Easing.EasingOption.EaseInOutQuad, + Easing.EasingOption.EaseInOutQuad); + XAxis xAxis = mChart.getXAxis(); xAxis.setTypeface(tf); xAxis.setTextSize(9f); @@ -140,6 +145,18 @@ public boolean onOptionsItemSelected(MenuItem item) { mChart.invalidate(); break; } + case R.id.animateX: { + mChart.animateX(1400); + break; + } + case R.id.animateY: { + mChart.animateY(1400); + break; + } + case R.id.animateXY: { + mChart.animateXY(1400, 1400); + break; + } case R.id.actionToggleSpin: { mChart.spin(2000, mChart.getRotationAngle(), mChart.getRotationAngle() + 360, Easing.EasingOption.EaseInCubic); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java index 255e737a6f..f9fde8a72a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/RadarChartRenderer.java @@ -64,6 +64,9 @@ public void drawData(Canvas c) { protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + float sliceangle = mChart.getSliceAngle(); // calculate the factor that is needed for transforming the value to @@ -82,8 +85,10 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { Entry e = dataSet.getEntryForIndex(j); - PointF p = Utils.getPosition(center, (e.getVal() - mChart.getYChartMin()) * factor, - sliceangle * j + mChart.getRotationAngle()); + PointF p = Utils.getPosition( + center, + (e.getVal() - mChart.getYChartMin()) * factor * phaseY, + sliceangle * j * phaseX + mChart.getRotationAngle()); if (Float.isNaN(p.x)) continue; @@ -125,6 +130,9 @@ protected void drawDataSet(Canvas c, IRadarDataSet dataSet) { @Override public void drawValues(Canvas c) { + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + float sliceangle = mChart.getSliceAngle(); // calculate the factor that is needed for transforming the value to @@ -149,8 +157,10 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j); - PointF p = Utils.getPosition(center, (entry.getVal() - mChart.getYChartMin()) * factor, - sliceangle * j + mChart.getRotationAngle()); + PointF p = Utils.getPosition( + center, + (entry.getVal() - mChart.getYChartMin()) * factor * phaseY, + sliceangle * j * phaseX + mChart.getRotationAngle()); drawValue(c, dataSet.getValueFormatter(), entry.getVal(), entry, i, p.x, p.y - yoffset); } @@ -182,8 +192,10 @@ protected void drawWeb(Canvas c) { for (int i = 0; i < mChart.getData().getXValCount(); i += xIncrements) { - PointF p = Utils.getPosition(center, mChart.getYRange() * factor, sliceangle * i - + rotationangle); + PointF p = Utils.getPosition( + center, + mChart.getYRange() * factor, + sliceangle * i + rotationangle); c.drawLine(center.x, center.y, p.x, p.y, mWebPaint); } @@ -212,6 +224,9 @@ protected void drawWeb(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + float sliceangle = mChart.getSliceAngle(); float factor = mChart.getFactor(); @@ -239,8 +254,10 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (Float.isNaN(y)) continue; - PointF p = Utils.getPosition(center, y * factor, - sliceangle * j + mChart.getRotationAngle()); + PointF p = Utils.getPosition( + center, + y * factor * phaseY, + sliceangle * j * phaseX + mChart.getRotationAngle()); float[] pts = new float[]{ p.x, p.y From 21fc088f0dafcdf333bdf40a84ec3c8e0c0a4960 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 11:00:52 +0200 Subject: [PATCH 0701/1390] Minor perf for pie chart --- .../charting/renderer/PieChartRenderer.java | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index f9dbb0dc9b..1bddedb5ab 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -131,6 +131,9 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { float angle = 0; float rotationAngle = mChart.getRotationAngle(); + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + float[] drawAngles = mChart.getDrawAngles(); for (int j = 0; j < dataSet.getEntryCount(); j++) { @@ -148,13 +151,13 @@ protected void drawDataSet(Canvas c, IPieDataSet dataSet) { mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawArc(mChart.getCircleBox(), - rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), - (sliceAngle - sliceSpace / 2f) * mAnimator.getPhaseY(), + rotationAngle + (angle + sliceSpace / 2f) * phaseY, + (sliceAngle - sliceSpace / 2f) * phaseY, true, mRenderPaint); } } - angle += sliceAngle * mAnimator.getPhaseX(); + angle += sliceAngle * phaseX; } } @@ -169,6 +172,9 @@ public void drawValues(Canvas c) { float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + float off = r / 10f * 3.6f; if (mChart.isDrawHoleEnabled()) { @@ -202,14 +208,14 @@ public void drawValues(Canvas c) { int entryCount = dataSet.getEntryCount(); for (int j = 0, maxEntry = Math.min( - (int) Math.ceil(entryCount * mAnimator.getPhaseX()), entryCount); j < maxEntry; j++) { + (int) Math.ceil(entryCount * phaseX), entryCount); j < maxEntry; j++) { Entry entry = dataSet.getEntryForIndex(j); // offset needed to center the drawn text in the slice float offset = drawAngles[cnt] / 2; - float angle = (absoluteAngles[cnt] - offset) * mAnimator.getPhaseY(); + float angle = (absoluteAngles[cnt] - offset) * phaseY; // calculate the text position float x = (float) (r * Math.cos(Math.toRadians(rotationAngle + angle)) @@ -390,8 +396,11 @@ protected void drawCenterText(Canvas c) { @Override public void drawHighlighted(Canvas c, Highlight[] indices) { + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + + float angle; float rotationAngle = mChart.getRotationAngle(); - float angle = 0f; float[] drawAngles = mChart.getDrawAngles(); float[] absoluteAngles = mChart.getAbsoluteAngles(); @@ -413,7 +422,7 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { if (xIndex == 0) angle = 0.f; else - angle = absoluteAngles[xIndex - 1] * mAnimator.getPhaseX(); + angle = absoluteAngles[xIndex - 1] * phaseX; float sliceAngle = drawAngles[xIndex]; float sliceSpace = set.getSliceSpace(); @@ -437,8 +446,8 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { // redefine the rect that contains the arc so that the // highlighted pie is not cut off mBitmapCanvas.drawArc(highlighted, - rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), - (sliceAngle - sliceSpace / 2f) * mAnimator.getPhaseY(), + rotationAngle + (angle + sliceSpace / 2f) * phaseY, + (sliceAngle - sliceSpace / 2f) * phaseY, true, mRenderPaint); } } @@ -458,6 +467,9 @@ protected void drawRoundedSlices(Canvas c) { if (!dataSet.isVisible()) return; + float phaseX = mAnimator.getPhaseX(); + float phaseY = mAnimator.getPhaseY(); + PointF center = mChart.getCenterCircleBox(); float r = mChart.getRadius(); @@ -478,16 +490,16 @@ protected void drawRoundedSlices(Canvas c) { float x = (float) ((r - circleRadius) * Math.cos(Math.toRadians((angle + sliceAngle) - * mAnimator.getPhaseY())) + center.x); + * phaseY)) + center.x); float y = (float) ((r - circleRadius) * Math.sin(Math.toRadians((angle + sliceAngle) - * mAnimator.getPhaseY())) + center.y); + * phaseY)) + center.y); mRenderPaint.setColor(dataSet.getColor(j)); mBitmapCanvas.drawCircle(x, y, circleRadius, mRenderPaint); } - angle += sliceAngle * mAnimator.getPhaseX(); + angle += sliceAngle * phaseX; } } From ae231be56608fb031c36760122852e001a850708 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 11:01:03 +0200 Subject: [PATCH 0702/1390] Added missing spin in menu --- MPChartExample/res/menu/pie.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/res/menu/pie.xml index 3013da3f2c..fd315839a5 100644 --- a/MPChartExample/res/menu/pie.xml +++ b/MPChartExample/res/menu/pie.xml @@ -37,5 +37,9 @@ android:id="@+id/actionSave" android:title="Save to Gallery"> + + \ No newline at end of file From 996948e829d998ea326c0f82beee736d5170e8b2 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 11:41:06 +0200 Subject: [PATCH 0703/1390] Fix pie chart values animation on X axis --- .../charting/renderer/PieChartRenderer.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index 1bddedb5ab..ebfb468585 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -190,7 +190,8 @@ public void drawValues(Canvas c) { boolean drawXVals = mChart.isDrawSliceTextEnabled(); - int cnt = 0; + float angle; + int xIndex = 0; for (int i = 0; i < dataSets.size(); i++) { @@ -212,10 +213,19 @@ public void drawValues(Canvas c) { Entry entry = dataSet.getEntryForIndex(j); + if (xIndex == 0) + angle = 0.f; + else + angle = absoluteAngles[xIndex - 1] * phaseX; + + final float sliceAngle = drawAngles[xIndex]; + final float sliceSpace = dataSet.getSliceSpace(); + // offset needed to center the drawn text in the slice - float offset = drawAngles[cnt] / 2; + final float offset = (sliceAngle - sliceSpace / 2.f) / 2.f; + + angle = angle + offset; - float angle = (absoluteAngles[cnt] - offset) * phaseY; // calculate the text position float x = (float) (r * Math.cos(Math.toRadians(rotationAngle + angle)) @@ -248,7 +258,7 @@ public void drawValues(Canvas c) { drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f); } - cnt++; + xIndex++; } } } From f3bd299ab198bf70b6b03d0a79baa019b55f5de4 Mon Sep 17 00:00:00 2001 From: Daniel Cohen Gindi Date: Thu, 28 Jan 2016 11:41:13 +0200 Subject: [PATCH 0704/1390] These are redundant --- .../github/mikephil/charting/renderer/PieChartRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index ebfb468585..5d094f01ad 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -250,10 +250,10 @@ public void drawValues(Canvas c) { c.drawText(data.getXVals().get(j), x, y + lineHeight, mValuePaint); - } else if (drawXVals && !drawYVals) { + } else if (drawXVals) { if (j < data.getXValCount()) c.drawText(data.getXVals().get(j), x, y + lineHeight / 2f, mValuePaint); - } else if (!drawXVals && drawYVals) { + } else if (drawYVals) { drawValue(c, formatter, value, entry, 0, x, y + lineHeight / 2f); } From 43203db5c007859dc23537a6b905a09563c9e011 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 28 Jan 2016 11:29:00 +0100 Subject: [PATCH 0705/1390] Introducing StackedValueFormatter (#1415) --- .../formatter/StackedValueFormatter.java | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java diff --git a/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java b/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java new file mode 100644 index 0000000000..4240832da4 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/formatter/StackedValueFormatter.java @@ -0,0 +1,71 @@ +package com.github.mikephil.charting.formatter; + +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.text.DecimalFormat; + +/** + * Created by Philipp Jahoda on 28/01/16. + *

    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
    yJqotrCU$G-@ZO~(u>0m0D3(<|EAqAq9o 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%0DJs>E&&>E-Es%w&A6`u=Hqyq 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ᖼqRKrV^G#@QzNizNcs#KEfNaUo?S9ccG$7c zCdp55f7d{A&qBAEs7l~GQ*jz=g$tU@8mU7cTD$*!psZFsuNTe(fJZAKcnQk}#rXT} zG)?wOpx>d@+?7C#)W3^1zE71XRptYtn+r@-rU9d>fVXA5#1!n36>r?@1q)9vt|fFT z=PVy!I#-Y^eK*p(hV;arqT{1TyhO75ox}_Gk`KOt&DRiI(NMEf$iiFbEPe}^DQvdr z0R-ONY%?$&;@MY{?D{V3@F~*OPZkRyLC4QcB5In}-P&T98&Z~~WMJj4txqoExt6a% zzKRx1pN1_^z35Z|!4R^0>jvKj$k2QpG1HiMH=x+`8014FUaaQRj<8w3h!YZscLlCC zwu~XYcKCdVTK7Itya#Jn(eYu377*#sum|<@m+G)|s83j5lWyILT}Si&rE6ljgZFKl z6vp4@SA4F6GkGm8F7mE-z3Ys>v$C>M3dCH0{q<8j#!^_thb#+_5v zvbMHXYNhPjwTrjE{q4c;=6TLwFxb>~_|nKB6iNGF67s#*p|g8jZ}O>Uh)z6)S$?jl zDo3s*X98*1+#%a`8X-nBYq`h-@;=f#fVtxPA=!m}?03=S9CRMJ;ug5_4$R4C(3R)V zbbv{RPVs#4D)RleV3)2TU%C#RT5#?->EQ2qFkXyXGy}s&FdKh^j2>_Ss+kFB(Lv>k zCKWVPGp#4ugqLSc=(D1n`i!4ulekLaE}ZN+%-WwrzKWfFGpdo(_PC@#lOc9yH`z_! zhDirRC!coOFHus`pw$m-{jspFH(28}NDgAVkAqnU?Sk!kgRTwN2`#H}Eq0OGm^8;& zXb8=Q!E}2V-(rniIPr+&5FJN*BQ#z?hBqSF0+>?8;*D5%#U!&U6w8%b||2RgeK z8Le@y=kvuo2i5hYO9bO*klcV|%%|*NA^vEBbBrQk_Kj%OZyWIaVxbhb z)Z*Wrsm+=@Q=&O{e%f{S9MeUJa4jk+*kO^lMrbrwJ0Yoo9R|&Zpd-Xgm%1yOt$`%& z&#>X?rV`$7QnO1I@hY>$xmuocF=98+@e?q0H|LaHi*dAy_h*6Kx962cleF z@gNYY_3pEp_Cxjgz5kyGl}=hq?QxVVfi7FO7dAkOYM+YztPQbtsjp+tQr3-&g6(6b zZYG*}1$Oit>8X!^?PKj2)4PUv?$wy-Td^yjLQNNRgz4-fnSVW)DKuY0Z5ozON_mYG zVTx$}&DiWD<75BL0Vbw{M6*b==vb7-G(}Lw2Ndf~S>9eM00ndaGIg;IHdlzt*UR?f zvdzplaISsFN(x9Dpkz7EIs^>y-0O(v?m^-ukO(_|o^i^8-cSWRRo4hzD z&Gqy~!!gL&A-l1 zj5q!lSngWrl?akPgRH$D89(AKDKk~DYU<>_W=~_|2fQFBJZ3ADUbLBdhrvr2C{&CU z=MsaNL+mNoct2tcGW{l$ZgCl1BJ1Be3brm>L3-1-ArHPES$VDyGK>SNa7g(~0KrDb zp!X!2JOyGAJH45iW9`p%({MZ_^+;o^!-7K3_bT!#6?;yYICS-8#tydTI95geo8a(_u(*HCv{<_;wW*U|Gppq+r zhEmOCA_&-PK$Uo5vqVr>drNv8(&v%!W7zabwD(3xt^$UI2EsRAmu4+NUxWcygpeZH z3ogm=+FX5zTs+Y#*#vY&r0Jw%`PCoW zFwp`geFoK&7-@bM*G1GvqG_V3yNRZ60+Tpbzy3GK2M?mzniE+@Tat4;gOSR`Olyfp zpi4ju^pWf!%H0LfbhgR0)2=eofEX!- zyR$-k*1tWhYvY)Jx$5*N)Q;VEu_FicHY0-?o5#BM*3A98=^)ar3Ct5{=4hD!wzWuU z=ng|2(5c@aPQN1n^9vS?mTSTy`SYmW3Np?4wUJoIBxtK@X$6^xXbTI=`xeqcvy)_N z_mlS@Mx=+v)5z#)G%sAHNU9ZKGm<^ujY*cU!>3&FOzP1A1w%Z>boLN+4=_IU*AUOr z+4qkTBJ$DGc;bdtPUP^$e-s|M8wFyH2=Rg?0Lo`LSk21r>Vh@WBfj)lQe*(zPbDVV_3b2!Z%6YL^8TZk?iD1vz7u4MY~`cabOkZJV6RI{%cBqYv>EtF(MBY8 z17W!B<(L=8UFfrPCi^pL9f=p`{eBLB$(e*tE(9`lCZ+ld_1rcwn+u7;l@*zM4E+%j z#bj5$60W}oSw2a8@Uujxp2qeTNhE@OH=u(R7%s!ib;!)C9Ri)M6qLxwZT{S`b0q3u z*AF9lE81N}<6(6r?zxWaz#Z7>-DKCk9=os$NfjCQT`R=}p34h8u4g}&#w~e!0@?U5 zq|Z2@q_8Ut1BII6eoOVEqD0e3?8WbeECLSktycq;_e%6r)IV$}#b#6mF^j+$S^EG) zOKA6YpaY~kwlB|knC7nKBHwotQh zD*WDG4HA(_D@R3v52|YFUyGG0yVNRh6<9*~ULj~AHMu-msuX~B5iHty5;a4leTmD4)3R5#^#YX+*gi7&JktLtl0N4|_ll~U1nmQU z1y$Qa4pFa7(F-=!ulRT~V5Wg7u&YFCe}>JDV&}dOlFN$U$u8)*b0P1mot?|mKdXK| zY-fOYsoWuFo=ZV>jOM2t^G~IPwjHMQG~iZ`c~Sz1?vyjhWpwxc0H${xnwOi{FYQ`w6QB;Bhq zQ`e#CG4lR{XrZAI&D>0~@D{SwPm>QGp}Y47$+H!xgJm{Hq>D)ofLcuF08#e}Cn_r) z^5K)DCqIN8Jzd-}rUr~mTDN@guD%9w4ttuSI^2=7uI=1&OK0Rj6Nzd?qINrRXbK58 zT6yvjCfP$g{{|$QV|eJ-$yPrGs&w}KIGv?;5YN7nbme2kQMEz3_64G;mtwj%I*moY zfa1l=A_j@~kSx9(J3h+j(0?FX`#jOiE0}u8|C?m-t=PdMzGG_5L*rn&8a|F6GaNuPCWXUX}JAc3( zJ2u0tuU(Mucd^IyjL(z=>>6hDMP&4iVk>uOx{&zpMd2mj_i1WSQ7jwR8(93LLQ<#C z27z16VzdX0L)K8_tt_MZZDC!EJP900r}PUAfq*s$3BLPR*Nc|co(j? zV4?E@I`sg^s#76vNu#9=!N#X#Yr_erVKeR@ioUQN1k94U&@XKoCJkXkPZvduW5+~C zVCHkszYDU30t9F#BJ}1-Z~I>C-kV(ep3Pre`_gV88y~|AKJ7r=Xm8ENvZX@7rbVlY z{@!BE8m+T&qV>f%&PT2Zg5_j`y zz!E2BIxhP1YwLM3K3b95TNijhXP<=b79l6u{Vt?;9pjT9WPI%RG0A>9OW#Gj_$`>^ zlVroEUA5FqquB}6_KBu$K+6E$-y6lfV+TZ2*O4r|73`3~bN>f+d<2OWn0m?oPCWY> zZ2uAR;ZsO7)k?(=K%UyE>N6rM_Jd=Ih>n<8C!bpt(>g7pqRLM#G4qGA(cV|y12tG% z+in9df!f6NrR-+0eWK}?6VJW21a+in?@d=fO}_CJln4_|Bb{qW7G6WtJHV9vBI)Yq zP&OPuAf^V$6n3@AZsO^e6VKcR(j!~{JlXo^ARoBjX@Kq0WVvp-bb}t$+V5BQodhjS z{ywkVT*!{Pxsm8Rj#a6Ev66xtvahNTtj;EtkesNw14>NSTP8wh?>{2yUPF57Z?NO% zAeuqU6v@)NAUp1obm$Eq{{X^4}6oy_96}TZs1mD1+z!9X36N zn5hOhTItAW4K%4-v&z`-0<$4ccgD(OE;RS{Tg@z3Wb-RMaKrM8i0at#QGz-Bf+%db~E#Xp#Ov!Qne)XO6Ex|4%fULX+!@zIVB#=2AxMWY@nLH8IJf zA1PYWI@P#o4>||Y-q%psC@Qv_g;q^aiGXb)XZh{5lFBGU0X^;SwrZMa145|+^>U6o zU{@-=8Xl!y*ZHi~i9-yPZE)rOQ)|Z& zkBty0I%>`GRa$}d2Af7IanX48Zl^6%oF`&>!+ z1nVVm5~_VC^$Rw#iL8vY#5WM=nv{-Y?c;ZrsY&q};;L{Y8UT-z&njUrdYP=YKwE|T zjUie5R^qwWkgnaw_|yjw6C=_gnz<9xy@v6zKOkTG63H%K7csAre4hba#ESj29Xg;>bokOYK6>Wc&i- zqrdCsJ)VQyNg9}Be{uG$m+qqCM{=RnRl@-**aP)=9-(5bRu<=%N<6SFV9BJ-#*QI7 zj12BW(nlS$rdaO+%w@}T`#pqdOrE>l6U`yrmtlMNfZ6Q{a%V5Pc%c4w@wp~S+Xb4O zP4Fio+al;%N2|_uQg$jJ^X>0YNYjigSK@AusFRSTIoV(xWg2$<2=Shjzx&*??A^P> zjo1Av2E&XrGvqqNBwgZ82Wuf8kIB<9YAwbX)Emp~L_l{EY&(}{RevTRQ^@ds%<3OH z;H0>m>Xnu%m=HptdJVd!Yw&w$Ijb#nM$v#0*zUpOQyVp`m1$*GH=!fy_z@WF2eat@ zw?#_l*{;!Zo=dfe&B?ER4J6aZBOk`BJco8?P@RM15Ze6)8m%DO3Ah6jI%HU%)v%dE z+nYPeT3KMLDQ%typ4*hiVDP?Q8(89h7T?;qVPLFI&`r!5I`w5_;|-9_qfv@kKaNiC zW^~U#LFX@bv`3q6dvJ87bA4<3(t=q4T}PJxt8>92gMuAYwcU8Rq-rzx@ag64MJq4m zq=nrR0+!XgIJ-izN1*?4_uEsi0eX%BbB@5`x!#T2b(!zPT-K{t)%!Ub?!=-|G0x#y z7EqaX!LCgU#>LhdZs!69?bIEz`CLv`WnOD0^E9lae*V*Rj*v~jbBRfh|Ec2~j1Qyv zh8yF~1|Zn<2;^%>p%+B10kfn!v1)9|XqLSHD5La0q3McqcwmU8N1RIz7R{WntZz^o zvO4M&W^HHJ_`mM~6I;7ODtqQhY!o=GN%N!#K~^mVwJX6`0>Hh*t<=AvBGb(k} zaEZuHeTc08aPejlHai6fQTGaxg?q817Z{)X3v~1xbYDt$&-aonyxy@Iv;xdjEuvtO z%ZPeclb(1#S^ukOdXi-K_mC{yOT2h5>4^_`cV4A^QMXBT1p%qS_*JqSv_vYw3dL(n z)s~_`3ASjCL9xpD#dcy4NxW9ts=_bSi%y$pu=tpr9fK;-%a0R-e|PwlEF@i`rF$ zh-BAy6Hng+(HtTjvX#FhTl`Cla; zK7mBDO%Ou;IHU=aNc}khxb0e~CbsEXjM=3W4{Qm*lnz8aBwK^^4qcD2|? zwq%XC_<9|qnbX#?xm)?#hkTW2_@J8~GmV{kJ@2-Ali#`BaR%p zpKhmv>D&xyhRp}4X4pK(7Gq|uEywU;&E6OagH4ha(ahn8jl^|PF;X<0Uk(RXEqXJ7)npA3Hm!+_tM2N<)@fk3?(Yfz{e0bjD zy1jELkPe|UjlJRy#z~jt$xjfy@Cfvt!}cCU_Oh6i7NP~~uxLPYMlSx&g7VrhI zNq9X5Iy8Q7dByh$`{I4&_*x)W{k)bohL{!X^!=Fi*JDm>p!*ImdeuKccV7qD_KK5U z*nL@mC3d3_O@6rOT}^^cHh;{6G4k8%RcmccH9~eZF6NZD@BCyKOYK+e{9@x$?-CDfk7$(xXVuRXou_m>)X6pi$6>~yR z?D#n}UniM=qYM7UF{ZM$FOmM?p8} zuN@+bZeni#TQO5Np`)jqj*Q~kyORAxvv)f-(fa4G;}_6;oowwsqN$sRrfwnCzjQia zrHH(=d{+-NXlgU?}~c%)&VQm2a1~_`K1DobWoyV9c4(ofJlN#b~{GPX>5zDX}8{*_12K-IEI~C zAi~7+ZVku#fP=-}jSA6bt;t3=OO|aUl)8?gYdJJq%I_|ncwn-bdJrX$9z{0(8Z-U| zq|ZTq%HzFLYC~bci^Uc>K_wpA+p68`4GZQ*w-l5m)ki>%KIoLsQ;JM$+^ZbGY?=Q}m>pzv@ z7m@KJXuQX(FtJHrvxHUdMpZyPan`UML>dQDjdLv_sx2+zdX13RYppG-m0GZ7>CpO-m3r~bsf|H z7&7=&LC-WaSsry;%{r~RB`9tkw{R_0jqNS^5W$|ZKgJ{%q?Q7ep`Sap_ zscWG!T~{F*KMmOn7>1}_!DOcpyM}5XvFl*h>87j1vJ1>!jLe`ii$;rXT}TIwUjoUs zF2J&5r*-i6?SA%w^EQw#Sicgk{{|=APeOob8nFW;-c2<9vcg>~B3u6=*iqHB&^VXs zqKkgz)Rxx45-(tS*E&noWUu?xqB<^SSId#Bfe~)oofg=M`WCmPcF9%~>Q;303<<#I zcgLCX1~-3NK|uikY%$S-JMYAhEWRBRz1tP3M$eM>AH?Pd3-B0hdKjcjluR)^`3QFH zS?2ab)VYFe^mI9{YEz`UfazWdcH|gC(nXRk*ddypL^^xJ=1&dO&4P8=wo1!?tE-fk zAxSL(*7g9YVoWKvJU?Y?^Q+b+&}KRWz1!xkZdd3rTO8HB;o{BaDyzSEmCf2J!)>cOCKk>(J~t>B=Y3(GjAl8!*Xb*z`Dd_#{?N zV$);9bFU;HJj8hA<3!!7Nao+@=6durnh%g@s^^`8pUwzW!PA{?|~6NapV)o_Phy{9DOZ{|+bU7@jeqkah*gR%K9a>Z)7kw!XueFg@l|*J)pkp;L!`-S3fd2S`)_gw9vB0;eG%XN z9rwTNFlO*1j2=WrUkAGa(L6*8tub*+h+m7*9Y9tAEQ(}DAUz1lUdWdrxd!dt>YkCW za>+P-p5Yari}lZi7Ph;P&pg}r*)G&-J1mv9`uk`4y-VpkUeF^!)v3;p9>RY=zkKOziQ{k z^&CMH(h)=kyLcJ-OBdkTd1QIk(aI$)E2Uv|sjgM0XMiRAmL_RV!DJ*G4u9e0>4Q@N zyFlyJ;!qvl7jV;nzhc3rXuKc0XGDJ8W!SyfA?xGnJ1IN9C(r#Hh@7DB;C^J|e^M!q zNMlbl9fWEeBG2hTRlHV)24~0{|3-d8U8%phw~9*q_+e!Iuds99gT`073dp6hKQ6}k zDjf%wc|}VOpwcn47%^Vz@kc9MB9T`U)7m+pA$p=h#lo1ZeQ9W9mEdwdKqV$0Jj&?U zAA)p=XJ1AgmH~)Fj`5{U z2&vwt*k*ZO-DQ=PyKiG0tYB?9r={+0=Ig8FUXf!fFK5N9W>-<{Xk)X8r_rJw%KZXmyJ`LBH?_^Yt zwu#(%T(nj1^c~_J7kOGpn>pA?!0rl+59%vWaQaEn9A^3!umkeJV?c%-A46p8$W^!zJT;U1N1@W(P(dRel*$KLA)xymXb6P6!ln$ zW*T7%$p@JA4@0zwoxT^HzSqSFc2K$RT*BiTUyQ`}Y?bzRLKXKyKJRSC^?aV$rl7pj zV|w-nvR=HkGx)rtn3;Ln)Goq{y74EK=#^+tA#_M;C`_g`?S>#YYg8DjN|4l|!ch5N z1I~jBf{TDyBCs2fK8d7{yJYZes%ksDR$Uc)NHq8&GPn=B|29l#5jpt{7_Yhtw}}Ff zqPlhK_I2u2#rz~)gP#iO1X}A~oy@P)G>&Swr8K_#WZnrott6bgN#DF;od!gA5xeUq zbm4Mj@FmQ#S#<8*g$~4vqbum}ex&~~BtHf8 zP)QIoU;JE^cvoOt|b=FrnSLGzu}r z_)Ez4^OMEKS?v{r8jK#lt)vz$*)kv6>b@+%cA0gpFMSGq)4Z-4iS%JA8s{-JSoF?{B)1;|mO*FIsmN5j%u@gl4Ob?PC(qoNVQ9Q7oNZ z-$r-ekD!{8t=-S)*ndORBGRqmkHC^v8W)_;K5^`fiQ|houNJ5C&wC1I6U~d|;W_+N zG{!pD{53wCAmTz=B%O_o;)@Y1*@^Gi_WKuOOfU4>+1j`kC;a#^ zBtKNx6B_FDeLqQ-X0*nHRxK?B1DW{OmzR0X<*(j4GC6Fd?kXT28e0Qe0xF>RZjnV0 zDX2^#b{!dhk$m=wVq52z)LKOnBt7UHimXM{V&|_!I&+wlkD_bOH5KIpUGpmFZL~e9 zpOW}(8R7+@HPA(A5Y7D=lNQmjKvZ38YeqxxtNbhyqf>jy_uPVZXWiYKufh0H7(D{X z)u`q#j&nyWGX6TG&p6cQM8mI;_wIzLR~LbjJ#7-bnT_HlGp-_)UQ2MEXqdK^!F7wcX3@stw{t4) zOziCbKGbfIp86;6RmO3M*F!!Zt1?U$;x7&_w{7ouV`MI+De2BkzBW(eXb5 z>0pwj0z}B%9QwKiDgi)U-BaGF=Q9Dl6W6ayib$3Gob6l&NsG4K$n^@u<_VDBj#2}! z6kj~r8@CDAEq>AzL%u@D78kDS*$nkmQ*A%jmtp_cAGUygR?$oJn4GY5!HJprRr?pb0=h51%nU(uSLqSho` z<+R01satQ>|E}iJ69$vbnsdlhv5;rb+l^hi5uM(HMsbmdD41zv^d#_6bk{$-C}-a} zC)yGt8=rRe!G&vz_}QTs^oQ)6HuZTL0M=wr2s8&b&`0otPET;Ip?Bhyj3ywPbdl^R zI(`CruVKsm_bj!>2A@8Mg>hDJywrBL^StG7WTan zVO&g?c-M(V$qEoG^4$0);9Ax0rLBb?EuH)tOs7U163%8ls?Zkm=(Yn{#GssCjN$fB zgvM7O>GPl)Oj6z_YKuAzr(`$D!ke(;W2DO;N7F-$ zPX0OFrFYW3>?i2%{XsBYC(L~G_p!r+1>jtadhi{*B8!B=|6x&6JUupxFy%m#9mtzE z%kQ?9+d0QH+4vY{{e!3-l`U8eacm7+m?R+fX)6OKFuD*z(cnfKTDrUl;%6%U*X77_2%M4#?CI~`=UJ@Z0WvUVCRyAd#AC z@KmcvX^X|JFF>k6Pl!~Pv$g>(?P7ang~Dc#57A@+yXR(f?sBvT zK2P4e%O$Sc=#;bV=Zp7i8Te(Bdw=l5vxm0%+NCKk=FzbH~+3_MEnF#i3 zDAwr*OFr-v1U*$-L8aqVch@j(UhD`NKZ&gVDR#DxPQ429eh?IG|G9Ia##K>C94Ku! z!ZSFi!24XCu(eMbtGPPE(~}=S_WU57J^z4s;msfsCSD>RJVoAr$gS6C)(Ps0DMd3y zrmJVM(dEY18r=)-)m3Qv%WII|7>ZK)MkMp7+Yz-E8AF%mG*AkpuW1z#g35P z)pT~f15J-JJoJBIlD(+iC}Ino{iZ}{c8YxMv)E`FA;VPDoq&w(_-EmW^ud%%C=J`1y4zm2MD)1kU!y;@BLK-Ax_ zy2H+M^Et*;aybkW=geh_@%8|@6133pdr-EuP1a%*G8u)??WLw8=YT#_fS|_Pz6FcS zZ+TM6gudJdCaTW6K)b6p?i$7mlXdE<_Cqwe3GLkIoOUik9#X|(Q>f`7sjY}UQoHAs z8q=hTwWLPwbR%F8iLvQ1#>f5$)43AUxg5x`<7df7PrGxp1nvdQG}-EB$omgr)8mCJ zSq#w(cJwsE!@p7J5xN!*yZ$vsqr*t=rI=(N1h%iZB9q1X9N&!qz+reOReGPob?2uvsJcGse>TVix-7dDwedrL_F7_1*c zh9{k9YLt{z_&~p8asg7=3YS5TYA}-8&^ZY!B2{H^lNKE>IGY65q6*pAc~SKCpfh{X z>AmRG9yE6DBVw~E7?@x;X3DXG`k#RAjUbDc)VWhVHwGP}gHJ>HY>`AoCBPx|;JV@3 z;oC9Ps=_{V1lmO~gWhj#0js>KU0wgDap@}}J;;w?245!cy{ZbFq&cozJzLwrkgl2~jnJIJwGz4{}2~7pA0^&m@c(v$S6}mjbCv^Uf>x)mH!>qj@ zYuC}K*A{bQUtD*VS_k^Z`<<(hW<@|ARwkWFORli0zdXnwK~hQu)uG$Y&i3Yx7T`E#goiJzD*)^3oV_%k$H1sx#>>B=V{Tf_8T zio~<%@EP*q6Ha@>j@_B0bsdm4u3qI7hKl!{{h!U9K1FgB=iIuXbqO%p#6d*@7N!L3 z5-HCosLM$EMUSTIO1P#frXhJB=^P-Mc?HSv32b(Pq;mi>^-}EUAldpCoG5I(MAW<5 zC42dhxdU$}n!k&D<7?RQ3lPoF+4H?fv_!u48PfHykoO-TS$Gr4p7)TR`WwiXNtWJ$ ziI*5Jf2;x|rEVweK}sdC;B9A515E4AV;aUo!HS$PXzRtHi5TrU%<1MaopUnN_{!qL zrl7s%Jo{p=^?O16yEybfskcc>Et%Ig-49*LQ_6`9LCQ&0ND;vJ3!17Y7$RVqo&Q& z*zYyHnUV$O-)Giox0zYCOMC9Z-dpO@d=n#sFJjjJ8nP3pnGKlojQ~u-LR7eSDwcgH z7dMH_CvjmRA>idqw1HLW9NPV;w!+eHua<~a-RN8Tj6iM{{For0v%$; zkDxksz281a(m;;G_5lrAVTyyYM%il?#H7|N<6SDXs^Vr=s^tajQ-`&!_mx1)WK!`F z&5`sFLXJutw*FkKR}>)|4Ht&6J>!&D=ku2wk`WncfZ4dyxK7q<;(5 zfhWdUJC;lXfA+LaDfW|juS%zN!K$W`i3GJb_2~0CGGUCEDRg=XJF^GvE}=8~AnrPS zjC@pUb|}Iv1y{nckRL^cUqgGZDf(hZTqujREwLOV22C-8&mi^`NVj5$1mdgh?hgU5 z*iv1WM&GN)&Z@C^L|YR2KYDeQNlK<qoh2uLe|No4NJ;>r%hl*2yGuHlVD;;Y0qB3tbGtA!%n>(^xVaF zFYYTxOc#=CAbSq-w51Xmwuw|pd#g204NOn4gNGRppFrZ>pcythfk=cD4lNUaSv1EE zpT=%HK-^tm(*A;UA?uT#_zP5GOg!t}E8iep{+|%theY#W*U)SYF}+eJC3Fn)L9x)a zq}Amua4t!qGY6d;DXopqrQm@n@7%KGE`U6mNx#>;Q-SExmPmVNQ7hO}J5x|F9c+4> z^weLGEPgAUz5ft9K7z!1u;W9dCqIZCJ&TDKFr9tGi*IAna$;o<+1giO^+S#ogkomy zB#SsasE+nv9oMJpj+sf+tJ7_h}tZ3Z&!&c}SPBPUpU9FT$8jYj(sO@mk}EK-C3 zmLj$Do(9NTo^R1~kvzK?$3!y(BDmtsr|AJxMch>|ZznD~@k01{BzET+xpP|)DgL{P zOM=y2u#OsWd0W&{Z_%_Phz}G_GMDCZlvclq&x?Od> zX=hj+#99j`>&^laSma7e=uBPMttOaJ7rYBEs@%~Vvr|aCw@S({(s~usf%G_%9dx#$ zX0}$fZqlp8S{QFQ4U_pRuyY5HbqAW5(F&5Tqgmf2Dr$><*NBO$N6oXNg&6Nsv+ZdU z@<1S1vywurCWh`DbZ60I0i8L3ox9AfwLF7t&|n}nsI5?`l@C4*og2{Ps=zg8yU(4o zIX9X=qX=2S)Ux-8w-ptv{O{QvVw{NI=&P9Z4?%helEQ(7P>?MEaa)~YJxzrcYes3^%MuD!YvJ%= z=0Mkw^$%lY7Tdc6=#)Y9r5}IfV7l1k8qDB+V58Ya=>bvdx2^chxOy*m=?G%bXqN+q zvlUbXQw0C&!z*gt@0nf!c*KaT7xQGDpkBOG^}Lh0pN)E8Q*3t1otyCju64==^44{w ztXl6}5E%R7wH1n=p=P?MoDa^JTnBR|6l-N3mF4pLG?u5I6l=?U86*Mzoh$(Zp<25d zut!_<2mS2eNg>$Nv<@hYQV`F4?IMldgRZ%~vt;Tqq1b(OL_HgT3!k z2MqArcS5o3Py?ze7?psNr{AC&qn*o9(_=GX`7_1mS{Iy^2W&b2NvJPWbc z?Ycu+-$!$ZrXku>fECR)sirk_N~TMQ7xFS zCJKq-6IPHHA3)ojOf-W0SiFAEIo&Idp&@%JVB^!sKN@>AU;x&%AZu=AB>-&Zkp8C;vxv^Ule00f@VgT(bUYAmWung& z(K%o7$gK#Oo-fVmTtSKYxSVSuvy~Q`I?a2l<9e~?@?1aT+5eun9!EXpkn>3oqi1zG zIZ?v{y54t+Q!Sqa`&f6ln5b4px5aj!^ucCcFRY)4Of3JX^%@g^GZWSI&>^Rmp0wzu zFcD%KKMI}wU>44JsBdLH&KlK~F0%0fWb`OR^Fbh23FX$V#NvlUEu?*Sbxkj!GkdTo zrhgK%`aCi`<()`+L*p5A{z`Oq zuUiXwhNSBr^+y^Bd#ko@QF)c@2&7NB>c1o|x!K~`vAuH{yY(}E!YR%(5#pt_l3syJ zQgc-hPZ-yC#Hls&XiM@feoI`_e!JQa5&&PJ<#as&GOjvQh&68K{y5+B{Cw_^YA%aj z`}82P`X`V+56M0#!4hd`RRkJ7XiaXj3aCoWpDLqjgi0;xoBu(9p3{3+dp}~P(atTL zi?i4H+|Ao_N5)R55zyi@*DK0FW2Kh}w25v~tL{w_3!+ZIT#*1I57~~D1F(d=ff_^6 zZL%06aZ56wgw9t@kh4~CAkdKrT4D@JQdBt4HTEb3H#=7&*-=*nAgb3rTbLmlCebvR zZ(%_1{i#qBZdWhyotz~JV95thkoO;{iXaqBE=fSG(`GpK1Yn8dh|virqG>vpljm8X zh5RXUESRp-jwxb@@#?2wEZ>rOLp?DREVg?yX82jiUho)iQZiynKub3f`L6LAL$OzB1^-O2 ziYq^;%4RuivkA{es9J(T;GkLT(sm}34$zr*qTO3uEVGSw$d>P}cpl=Hp!xA)57WvZ z35UG3L5#XCPJM6Ui4?20yI)mpO`*=8w47e`M)^Qd(bA@cy{!U@+R%hJ&0MMld(0)K(VQ1l zOJg1gDtiQpZrQE_*zO#<_ZBy2*%&i834`OvaM_6++N=ydLqSDPv7}@oOoAB`&iceU z)I=yTwzr7PU5@saP~(Z+*{pb;KhJ&uUb}IN&k-a|D((^+JqXFQPVh?8EwRY9eJ)Mn zXwv=r9KcXZenJ4F(vT5P_a|T^sNXfN?JTN*|Dc<;uTj&KX|D#=D$Kqv5$Xgq?P^g` zYq2QZqMp(@?U8Li%O}>s>&WVVNAeR8EtF@SG^0%qtd-Vbu4^7>nBRw0>>ydM3+DN6 zYC!wQ+6Q31=hX4-#s#}Ww(pLdthWv-rX>*fjvJ}1L61@8>uYS*rV|FO?RMGH`q`RU zP2F0zO?RervpL-!Z2?0AmlDB&-4Y|F8?yK|i6I(usg6;i@fC=C65@@7lZ?=PS;kv9BT$mEh6&$F7AIh*`o$mm~6oi;;+GcSrl$ zZNihAIqI~hXwsTIYb(eUuAr)7E^YTAerpaj{gTPt_R#1u*OH@a+j@s=>AbTkR^~Cu z)kuC6C&(!^V0JSOXq!cyw!;v<8;#O>zG@)qPS^@4EtbaOCH>6{j)wDO0NAy))%yVR zqyT2o&Q(soE6x*2&k{v{bpDozTH8(>KEGf?hZEJ`Q0cNS)`K@u6_p`y> zv`M@c9>iV9k0aUBr`44^?HzJ~;(;C0FgYJFPdN|amz{p*{|c{5dM>39e9hO3s!a1f ztVp>UQl!0JJ=HN{dL+BPlX&5cW%Wq26ATakI(GQ9V^Bmh#0zhxv-nmga4N#W^fQc3 z{5dxLiYMk-95MMR;<>le-S@*qCC!s=&4-Y$k*3-lZdjS9{#S&g_Nh-4&}x3Q%ga27^^3 z?K?*an;|xZYy;PR5kZt-C4so({ym;Sy9;P<*3pC~cdap46FULahK+8`Or)jS6~+uL zi97~|UxlgHK<8S-ZoM^Od*?E8f|1#?MG$K|kszD#}K2R*LC!|d<+X36&%p3YsM!V4;#tw0w=%BV zXV+Qmed(al<(PcUv9F5rq7DC0pAIe|1Hc!_mCdSen~YK?Yxec#)tb)?b5K11MU?J8%wav{5$&_N(@!y2!q-U*e0* z))$Dj<1XG^Sn)92xY^!4XteK)?sz+Pk7x>J2|Cxp;IlO*bxj=92ZKd6*X0vw)iY^o zo_H--J~_w_u8bF_OA8=h2Y`dN$L2Z@;)6}?lKn!Mh0gU5?Q$*VmvoYrxT4AUNyrX4 zP>xD>CeSRAb^s$Rgapx7;}${0$rd!mpPHdX$PO(3+Ben^MXsRc>ay# z{jZR&d$W-{5 zwULOGD*vUpYE5j;NB^w@np8kc>@H=Q3jJ@AS(w@bHY?m5a#SE24j7L|#Itinl5L9j zi3$pIf=00yBu;{%y!c-`6Cn^M)D}D3dJ9CDaw0lL(!*$X10_DEww&#l%hQydLVby_ zdAzdQE~}RXh++F!+Xq#m+eGcXAzns)(wzDC2lO6$R@|9?(hUxr^sr(OxNyER$A&~9X#oyS|7%OVNO zj>F*dh#eIzUcT+B)HEunX*CdN7?c9kBDLh)uX=kGNIw~^fhd)oDHWAnVq|bX(zyZc z?1OA@Mxb{mMc&#!fMZZF^R1AdfblK*P&-pcpvD(DbXf*ymq}0LJ^>-JxL%r3Qk- z%{Co>+(Mh{DzUA*rZn!ZT02^!g{Q_sXtZ2SbR9%nK``G{FTCeNcAokUa9XvCgx|cG z5(ZFDC41r+j=t!t-yPwNhXkw>sim6Tq6m_2-nU;S_A(yxSy+mRBx?oFm_UlC#6jaRVaZboqjFEd%+Gb5zsvcGv|QHXc6q7 zIJZrWi9t;t$9EtIVN0ojThb8Yl^}61TREhqb+ni zO=myJ;?Qw#j7SF zk4EJ22%VjG45WaD?B-tbwEC=NwXG>SS|%_pf|*hW80u@cb}@;WLb9hJeF05g3R?h7 zF6adePFqLA>a;Y1$}z|^@!Va+b9WXXlOZ2GOuF`I_mgT+%`wwA5zoDvc=|RZ-bFNX zH>P(p`NkKq!zW$EOX6}JhzJtR(%JJKB-xAFKANp#`(Go^*Ge6sYOiaJ(NKUWWzt~5 zu5q^789M>GpI?wPgXX7@!F`C`s5FhJSKzeUG|(F|l~b~!k0cq&PmWr>*3 zCf2JmSAlpl|CN@uDXA4A)B_Y61(-(EPpcJrMN+N66Dit)R28cl=mXVB@1e$;(4tiy zCh}4VRSHd=iC|2`D@3%|?$yU56y%(+J1oK&Yo=Thwyk%Rg3Zz1tI+Xtn8D|;@!kfb zram=+9D}#F!aEjE;J=!?deca#71YcDLxJFCu_}l?8i3fOYio!|f}Oe7iHDZf>f3im zY#nr0Acbfb+Pf3!-&e5bOoK(J4H0n9-nr&(H?e#U+L$K5@MbLT- zxy`6AY{S*SUoz~el5oBQheP!WE|Whqt~G4%Wk_CHIPK*Z_2xHx^YzWwi|}>2b`T*$ z>>A|`RBi7?->j8R1&GMkze0NQFR=tImT_$$9NJLHX)vHTNTH_z}sFq5*%MeY}+V2q#{@pt5lRSfb4A~g65oANihe$R= zvN4*E5SyX^fI)x0dFmW$%5n4TDSgUsmbM*;_f78K6@z4{P^AjS12Ay*)n^!rz`G&=cX>5@l#> zENDN&%V((v!q$8HeLaUZ^@mVs7o`bus)nv$J^-nWPgwn~ir2bGt-N2`yB>H_9gynn z*+N$)+6U6R0B5GSs(pMVI&&|?O9jiavbbqVy8A$4*sLZkKPDp8K5P-3ufMlY8?)Nq zmqRL{<4Tp+ix(G&(>ueW@d0%DEe;IS;U#qch-+UqGidj&;ttV9Yu08e6zP!}Gn7;=yGYzm=fU!G^reE(Iob2Gz zjv1s2=?kuv+Qcp3Z|%p`S8&lLqX&qqo@RLH|L5!grBeba@znJ$+}rqu z)5-|ipZ&gSi`pT{(sv{A0_p0<$p=p$(L(US!@S$WbX7fi9Mz#@Q_i*}=Y01_YvN`{ z$nZ;!T_SN1{%I>-7533LkQJ(6Hl*FwYv=W@%cgF7>ziw+3!_amhDMK#pNrHkZJp?` z_$~yVkwirk_o8^K%>RdM z?fznXa{?qJXb&p+($vE-R}i$P4SilTcZlgA`7zAsK_{}Tq2GhlX|mMYYdpYm(pnNE zPtBxE)T?IJHg1Kb`PELXCFK>%gzSXtw>}GY$)yoTIID4;c{AF*t{8KI^GVbLazz4> z&(qn)Yfz<@8YZGGz*J3FVItsK7YQwKX=!CG1o|XxDjRhdP-y{VbcpTViFR*mIDeem ztGJarR~Pz1Sqps8=D~jJ-iqsN0Z5@ta>>8|4PcB|+HsPf~K-H)f8uLjd;;Yqal9CZIf@m)~{pJF6vKK5i zJHLHrAl`>|ZY-+$Y3)AoR-IPt#IhFRH?nEfTBE+`XxSpAfhDwPC?xO4?qOSyX92v) zexB%`1)oKwA#LWD3dG;f6VO%#jdr7*>kB|XyU2IXnPPz$$zE`=oAhd{-Uo@)1Mz7T zQ`%6+>i2R~Q&h87?Wh1S6aN_0=8dIVW2sE$#B~c8dxCSZFu#!VVb1kUUu-QiTM1fU zY(UFaKl64b%V+amJ2EcfSRAT@BH8jUxnh%Q8%Y<>V_Z=qjzuCJ)Mic#p!ZTt?|QPe z`^o!X!^Cr7rrposEGFZ*S0lZblWsglwtjzMX2aCw*Mgc`qzm*1Z>w%DeX?Q?k2_FbmuWln`uhX#o;I8;2*-6OPi&m72jHTlb>UjDU>2QdWHg7X z3ZBOrSBrLD=4kLb!bkB$TGqG67}2_=tk3@O5-pV~aS+=03DV*kR6EnP4q1fayFL*p zAaVF(S9AA};IAdTPqan2S0u2;4H6&U794NyN&6g!49aS)D_!W^RNV0wh{38u)GT0o zuR@b+ia)dsn_z7?o@k>8A$6hB5-ju>Qc^FFcq06&HK-MU_feGMLGtvfX=)T=U!zm{9V2sbDteW?8zej4*5D0d4Mto zn7E9oMJD2^Vw&gvL<ZKVez&q&_Oy`^n z(Ykg{QSqhDqS(&QcQ!1D?Rwt1ipB2aJZ#tVF3q(w*<@2KNnTyPOacVkmoafjv=p1% zBE6T=+xsKf^a$DNXV7%nwNZE>X_OqGyZ`%HT|LgpXZ{4k20~O5{i^JRRT7f9Hz4r> z`QR}$JqD(;iIt@XxHS6AYnP2Cr3T85&x42yl(Q4XcQl*Nld_3LU9BV(#ELZ`Nk4@0 zSp<_74%J3-NK+=U_N*p2Bhs$pAhiHo8kUq^)xI%nliDgg+gLFg%sL^-Hv+CF*zQKWM@@zkvtnIh_3OEhx_cJv&YoeKKF!@+A- zOzQo~_1@V=4_6WNiM?3o)Hc750NF`MpL10~@y{B9L};RU(Hv6(7=(t_N#*P1_lHlC zl_txf3VedvZ<$~eFn|b{uIpDGeXVdyx-jFq?eT{NVkcHvIw#a|kPSTzR(ZCcmYD)_1!hZe4F?vpcZW z1BZ|SStUb_Z|oI{%2s9Zd6^+F5JIGd_-8Z=p3}?rgTqB@PP7|4|NUU5oy(fXG^qe3 zAMmT6USS(npgH4Lz>7Q37lIYp#C1q~%^#l~A;F*38a;}!O406J=*)K%Egh%NNp|`U zX|gl~lFK2!x@bSo@v00#LhNfBZ3eWe%H|iBPtn@sD3IX3mnN&B^}i(8n+?lgKOQMt zRQ)1eaofdvp?inBmo&e`^EKnxj`=av4$w&+AT%1CVJX+Esv}8Wu}5L!?JE zdl&KiYw6Cvf+(6sZCdKvsn5Xj|3nND??z4Hfsq6X+(8joL5UoTW%Q8SH6jRq1p(bh}-$EMqhpVXbZad=y3WdcE?`$Kx@B!GI`=&iE`5q1WpX zMJ|}i^PIt8u;qp4f4|9h*zO5v8%zIL+x^V8?{cA@)%MJ`@4Vd$`;2R~NIZ#V+Y<&n z*N29Uq6BfiqL8g&re98X|BoRUM#ugDJ33gfPYR`Y&5&ppo&7%yW*5U_?_<3BMP&LK z$ZdVI6i;&2w$b#>kguWXQ6@rC<)NX?5LFshj$ZX>^7AG>XC(GaYxJzwPZ^NdlKQP4 z<+2Rn#S47ZuakxXg{7m0C*l@>7HZLgA}J)*1yMf9Iu?NiF$UEPtK%X7F!(J4LE54M zWCgoOoO6xDfjFZtBvuNVNi)`Mh-~_HZb6|iLUjZ373f^eR#kg9+k@vcm*Q-9C0`F5 z6#UL4sY%lZsYKX)5m2X{7^!7^?7z{K9?9-^k}Q2YNJ2I`%IMI4a=oi&+6&&p`fHWNl?v8VZaMm5r6^*kvLlUzSx*a6m(=q%)_`pO9-+;rw@cI$ zwWe-`To(tO?7=R!_ew}EN9>>kn$IsD5T|1z9aq_Gu#ZB!Q2*}S9C*@-6r*)bm(bm# zK2GKR;}VN?kQtqrKRLA4Zn{i%S5_TvL3sBzTCYXImxVKDgKlvumgy zgGj^WhQ{6325N;n7vGV`oZHb+lF+)|m&*@XoUvqTn2;3VfANxVvW!@!V^OX6|wfcPx4T%ZyKaz}dPN z&Q5B_#B;Bvv*#Zmri5%76HGTq=7-RVS=ReN_4?Mu0J$rcbo8QdB!UC(StEXLHolb{Nr^6FZ zJi%u^^BIyP;nlBxHP>EyE#vW+;c$pKgHYm5gC%D=tj;$GJRRz|6M_8M2B8=7S?%Mi z&c@fwIpt^d4oRBDfAy;alb@Z~j-@Awr(aIzvLC}lvy5N(b?o4Ahcrv%4v~C-B)jPB z`^T8>RpcxGgKX`yh!{j-D6CXf$B5|^%mGJ#GZ;+w0Quk>*z~9qgOxCTsaya&0n&O6 zShOJ^x)nX=(~axd&t=hjsBIur6&N<@+*)3;+F%S+0p#SeR6B-zfJ8k^=OqX++30bn zpAs*EP6F%1S(i$LF(6Tli8_dxa`wx*}c*^lOH*zqB(=9qZCS|5{i zQR+@PE!65Du#!r|unc^0V2>TR3c(f`CT9zPof-I2lnzAmNZPFQghgoIHAe$rPgR>m zY;|B-vhX@g_j2;VW8}kc5OrQcG<74LU2i2_{ur9AAky_JCNx_`^C6fHCb^uba}{C-g*Wv6|%L@Vn;6&0g!0| z2L)Y2wU6osBGI-dWoKK^IJdhw2bo5@w?p?)Wb|0&3MK`3r)?It9w0tpJ9%dU0npw5*hROJU>uIi01n)T_P{=miAqm;eCE+#NUjEr{PnvE@6&KZh*Zy%9!_BH2NZ znTll~Lc``#G-#7-07rge>{US}C_=OW5Hy8Dyp|a)G#M&pmj-+ksc{y{@vF;aK?4-1 zHC7etq{Zc<2B3ss7$J42W+xPC>-fNufcDYkD(uYLDrKDu9NVd8j?t3b01Mxbto(PU z%MdRGtK0_~g%-d{Xj+{6XJQMESm7qx!g8o-&6Mj}3pbV;yCh#mdv~BS-&!!QHqKZ` z-RV2zv}ap#IXZO@05)# z=|EE7ElF#wbyBs|`7S=LB{)JmFNN-HPLHnzoV-x^-PY$)(0mzmi1;F@70MX`iZbCq z86-bJ)Y*%P_hLu8@cE>guM;iYOK11@0+!LSKL9&om@Q!P=ZH*Hf`%%-qfX@FY`cym zFF~Sd#PkaATUz#PO-^M}l+F*i*070V(?!Z(g`8%1QO`8x5`O(c8X0}6xZf0cagvxsz2iCoo7bELCGXZO32WFO-r z{{>zDTe8s$j!K%J0_Kn?Ld-6(gF@HCRLO#w#g31n`8q05i`5yPKvt2Y*Bw^0q8_?m zh#O3c9UA=tg&!7)R*h<)n+Q*8_?_!UagD&HI5?yESCY)V9!Yi~bcx3Y$yYx^-hb2` zw5CTibu-cIok+Zdk%ZXhShYxgi1hfMVePO0wk9@rxzm-|^$y~>S7G7>up{!}lca0+ zq2m`S%d_(HYY-r8c43#4@Ybl_QviQ+HlQO4L9`6UfUQflS(>heW>JPQ5 zWia76A|0f2Imxc?ChtGY`1l`V$1jj2t{Rany%Rfll63q9BuWT%2imKq^?v2LfMx4t zJh_lx>}GLdAUh8ENg(m;R{ZL_6#dBt)4P^r@okvS<%pTVj-DbPKLhzNNbOXN6VHz3 z>F$0H@$4OR^D)`#3!tfEU3rO{+6|<0fX=S(AfCM&n;rqpF;h1>d-cIVB#MfF$`^&3 zu(KktLl{2;ovVu09KF;BAMybtSHbkXFg{pIV4=wrX(5zrds{|3gC_(A8|qDd`+;~y z=u!tSo9A&um0Md}VS=;UvHLW+(j`{g?INKg=-vpO8z6nOxOWN0Gf+3sru=D;sWm{} zy6v#1VG+zyJ;`qN>et=4sJH2Opn70S-vDl!iM+I(bJB9o1uT&oyU0Hiv~I@Qbj;CG ze`f&k5=_0^>1*xS%h}v&?+&bHnDzew=`&#F1K>kyd5J$>wQGtxkE`}0!PtiiX)R7u zHLc9Rnpsm9i%z`~o&64Xo@o&my_j6tbPQ9kh4e6N{53?qFz%e3<$+tQXCvI$BO3g^ z)U|lDsq@r0=<1}9zl5czsL0DZLGBvlK*|~k#+=g+# zB&gjWTe}Y(K2E&wR-)NEC@ta}MFeQFk0$?~IyOxEFYVYXK3xUvbgw9i$n%`{zyJOG z#&7%vANtUTn3|g6(4j+EYs=P|Znw*c6DN4@d*91%{^oD;UElRx+Mj$^Vc;{zY~06+ipKhHJST*D9l@DDQ{kNNP2Kg_@Q7yp8r zZn}xrzV@}maoh^HoNYDz!Y1*u4HJO^;&Yy+nI|un0m7*~SCd@e3r2-%dRHYBXPic!6l~9qj7nPD!PklCORaqRZ** z`989hzrn739*JgA=^))Jz;r7#zg`X0X0oRe2G`Pden{epHtpnG8h63wCyFG9APLx% zcIj6VYVmEoWlFK2W8&F+95panAnSh(Y)U-)Dx%Iy7$5s1(v2@;%nYV?9r5hlXuj%@ zcN4n{K99n%S_(@&=@QS}L1*tjM(rwg_!tuJCtkQ0Np>?l{9A>^Vs+V837~}bYK?+r zD?g)xhs3zbfNpHdb4d^02pl{tQ^tEKOszzYDq-U+ST%TRLyy{KJD}!vgxzzFtn&_ z`Mz4n?TYCZIx<5{=K!LYxqVgqeU&?o5s8UrUO_zf%0|H?9CYUzlPtWIc>eWd>t7{Z z{vfC!n!15JJzlg58c%3>5)W$`jtC=6{yfS{9OF*27r}j%0aIw_W|(;cvhkVXJd5gZ zd`SOpoORmB@|x~mVH#htfvPz!1raCA5MPnHZUf!WcBm)K>U&4jK8*rnh<2kh-vVZ- zNC>N>@chR&bBvwj0LXL!xSA@ls?q<0J@1XZ`fZ-2C9L0G)RIJ%?_IUWw6<0Tpt!I1 zqV>gABMJq6BF&#|Hu;D5qSBspOumEPB06D3)>$N4dlRX(ziQ^%5zG=hnG2Tdrnv8! zdX+0wt-T*fpGQqMte|_zaagsMw*IQdSr)7oX#v!vieaQxk3&4+=MhL3?Y#n>c{?O8 zaet=iY4^oNze6?yEX^D`{U*qcAfvBCv_!xv5eeO({QV-$J9krUpini}o68!AGTE2n z$Ci5TFqCR@^9ZgbI=RxdP<5_=e2ufwW4cuGJF&xHtp!JjFR0`Twxq|f=}|OWZEh0H zFx|_Mco%kj2+daM?*4~}7-o_uG5I0KTBQ>-K)WK%5Y5)e$uK%3@||#`Zaygl zpX@n9eokf<7a|_mvK2!VMXao>@GHOaD`Z*5Fa6Rl@$0|->r72e1xRlcMLhiQ!~EK> z{Te^<6F{Jn zH{5j7P5l1v|30_eati=I`lCO}J@?$hul?GuaoJ^;aqYF&vc7&PRA#^Vy10nAb%4Rd znpbVX+z2mGEtwl_!H;5+{eZ=e4Rr_(Te zlJUx?5F$)xzq2GO=+hz{Of-ibKVMX0t)rm_!Kqhunz+p9CWROuCyy4L-UfDO$6g}D zj*x7*0uKUuUQ1tmkZ}1SO4G{*QN-q`=@QT0jYJC!5B&z&>Zc%Ip?lz8knDOp(c+sJ zuYJY^))J%XNk&J08{7W^!?edZ&6uBCa_d5pBCb?d6-xFI&AkC7Wpw1XNSFVHsQXg7 z2mbFw(=R9LyaYRbzCgR9iW1)zv8tp3VV+%3mpc+%t zGicK-ocx*i38O`=yO^WtTgZoxp!o)-a|O}#oy9gDp>{;nxeUw0~-cJL5H(@w|4TOeU8++=QYBtKRB z=Zj@x1ne3_3+U{(A?XW{9&{kM#Gy_^6DF-zqBJ*;G-W|)a!S;7mK8vuX#H%Z&A~XJ zv2WgpqG570Va|v;+hCbSr(OlUyIf+cW48D3638tYAArs+$oL@#oIs;O93*EV!9JL@ z^9AiGf%t+{AcOZK1i$YIeyV@Q*L1M7P0V*Qbi=!<)FBbx1fK5*m#Ms0|R zi05eJwR@Bxi8O_?>#ZmhZA6-ZnMHedp|juV7*Te>b~}9R_}SLI8s@(jP91S;LgIia z)xdQ9gt$ewO-nJ>$|*-R1QEl2PieHC`1?cx`)>_mGNIOXsP%FS6*y;Ii=~}=7j$lg zy#FGax5=3^M92tO8iC`cCqGcSb-FfnOi~_vl^#?|)O|_u_dU9Mf0$_c7Q}Q}TwEhP z`B&r{p94~axN?eA7js~`g>zrja)W7DNKmO-Vj6&W#>HlwZW%C{wA=j5&-@Ix-g+y~ zJ@*_x_j5lNEb0kk`@Zkv+H0@iwvRT(!iDnVa6`EdjICDo(}cxA7HaHE!oe z-=aFgQ19Wcs-aS+rq@Kon!d1pfF}rD?BF1Fe3)$gb4a`kqA3SF0YaxZxCN8!Ms42- zP9^&=YB2c*;%OdLO79NzA&MY9f#w5Dyay#GA3sYpeJiGWIW|4)D34-j)6exld28QC2BjNPRZEQvn)FV;wOO@l8ukG)i5w6)JV-u#oOu3qfRe3# z7Bh1zoyE7K`6@O$4%tcKJ^z4s_AZ8peiO}(6>U>~Mx!lxhxg6d(8bPv7iR5GAUjl2 zo7*6hvIV;Audk|qm58)wIUBUT)vAQ*Yubc#c)wjP6le@d2I^}Gs0Nx1s&!)t>uC2= zFGpwIR`mGGg_$!QKyocQbvH74&K{YT$F9AgH!I-dpClC^C0FL1q9KcJ_H;6C+HB`-j90VbRBB>W8XWbCfDaUF=u~7D z(dpMau~bb9)*mnOJ4PVyqsdFq#UIA3yw8E9jUSU1!D9`%O6ML#jqXAH`JF5u43i#s3Z z-#+ za=!AFuV8IB5J{3S8jX13i6`jy`&@I)HO$V=maaOzUXQ!)zMC{nSzTSF{yjEbPG=D9 zJ6jExb6Uce$g?iwGdFuyU4{5Ueb?YwSQofQdlB0&tbt8cr>U2fH))9ziOL@{#Q|c( zS8;X;wiHA&*Hsb~qN|GFl0(-E90!W}<-3~L(cqt@k3VCFgTS6$Vt~eUEmwj?t2#P1pqcZUR-vO z(}>AVkj%fDDESWT`eCvYe+zmHF&)$v3AD2pLUaV_5oG!{Bw9o@#YD42@nxtTkqsVq zs@)PnYlDsVojlOQeLq`P?;HU~%HUWh>x8^?{n@Vl(Y9C4;Z49qg{w+S6>pMaPretG z0=uKmr)YWt($!*YioSR|WOVd>bQZtOwS3IpiE2)^@d)GNe+>C?#LNOYsws898v$&# ziW$2^yi({l0hzZ1ZoGiO1-Zq%M7xSLWw(6pobBDS9cSF8bE#uDPSU9Xk{Y6_S_3J9 zAf-BYY`#Xa>pSVp-;3S&GIsPNkb6L5$fQzhG0AQqCz`p7soo8RMPb(g%P0PrZ1uhZ zoQwhxZE~(cgtcQNKUoCD#={VHetfr3MsjC*as|x14c0#7oQq`IZ6guXTKB!EDezB{ zd(VEjVibn$a7|@!yecfAE|OGdXvuyE&hv_~Ahn!OXzL{}9&6XosaLrwx^#=XM$dSM zY#F?j2#NPY=V~N78d$jpb6Nh=0e=;>8}A$lTc0*#*NA5|+OU`Ps-Ws61Czu~{iJ## zYF?|3w;Hf&=nm&=JV*^ZE9bIi8y&cUG=#_{upq8%;_FPNBJqm%q0vHP-CW4Mc-q)b zhhXNgbKi~WT#Ige46-Bc+#{-zFK=Q3B^e1@l>&Jeza0tx&!C+lHklLaVxI2J*qLvI z?oCB2p}x58kkh`3LQZlGI{R*9?Jq#rQ91!YKY=Wah^L)I2uyf_@S$=Y4VInM&pOpW z=f`I)o5^|R?ZHWmIe}=bUqmR+TgRdh>B98u(WyHeD`H|3e~xkTMV-sZ&FU2o+FEc$o&C=2maU3%m zjmWZ$g@pyKz4lttG;IYm@;v9%sZ)pu`}XZCpQEaDyIpR)@kT@>`2EvfyDcilJLTxI znV!IQZmKgqtG+n4^O>i6)^>l_Gifu32r34NmLPk+pl%v3XlYo{v{a^w^-%@Q} z$Si{T(q#(ck_ubFvr`4D@>qA=nW%(M)OCg^&F{`!e3V5T71>)bN({so!K z)1ljfMd*7K%9hHGYDk%$I7Sq9vx4yuYNFAH=ME29X47Q}XdLsuf^?S1);>$N{uQS` z1Etf8h>)**oP6!Gs9i0_Fb--YE)h2#g}wO1g(x3p8lAcaF|(~8Rogi2)ERe9b1Clo z1T@@w1+GRZn2`JHsW>87JH*6$iRWI2+6{(Bexnjv^v<282uF;>3)ta7(i4APsM>ew zUG{&Yv-CY^wnDb{xq{hJRUWJ0x&Wl@pknpa?&u47Uv5vp>ymrhyAxyAk&TZ)ehM** z6<|6^XuY7(?HO@=RhcgWVpbqw(Vbn4Z}`k#Tu?u==%_jTiJs_`)HtgW*zS{VitM~w-1A-;2l zRt%nEA6OJKai8*ljA{>1bvD$U zj!H&psd-WqSnRrM&7OWOcKQv)U6-BJ*j$Qp=~`^#f^jM}JM@<8%A=gPqruOQC-GCE zai%Gnuc6Y#pxDt<*lZo?>__5VC>bhorLiQHbd%I`f%<7YVTSny1!GW~7vIkmu7(#b zmpl^yc1{eFwgr%7*`^7Vh>&F&X_^wpF`Z7QyfCe`BuT=|%uH~J`tNV8CCf5IgkG-~ z{Jk-T+1c5KQ0$o&TBp-#uvzM$%2ooW^RWm!SJb!D>0pc@Ns{tAZ3XbzY7lxpAk(=% zb8FUw29jBn+rU1CW&@Cz2Ft7E5^V^LN=V67ni>_pc2pe4?oc+CD2mMkL)OLpRZIYzpe&VFoX8e)McIj2g_R^~96ONk-tAjuSV95b_QJl1PmEOGleV8wdBbnCR@iu5wHToXR+&FCLbRno_`h5>|2n< zH=?5lAX|5VH-!_CMi9*q^{xgp3+b~E?}q4dOy@Fk`$3(9RtWBX7*L&gRePJT+@i_ljqnvlIsGGHO#yG>vnB@z#Z1M)QM(1XX&o)4!15Sa}G+2XwpTZxcIE$I9$j(x>$x-?=zI&3fZ6y6Hd`f^ zg+PFEQq@zu?^uX+S4D8|{*cyeA5<|(j2MFvA&%qfwwko{P?wDLtCEu>rrsv$-+>M| zjak7?--*t@8|hx>Kwsi>wt(Ie`^3y5@okvw3*_Tt#n?#$_$ceAJ~hOcChc58DU))z zA+(Iu31}SdE0L-zzdo)-Mu>@`LQ6}Dqo@)zoXoDOW1#pzvain|(h_@A6J&grNo`F8 zB8rpq+-?H$RSVbcL$yT70d(#bY`2Hx?;&aip0?WdS66Id(~f}z z$7z`K;2IYg3Bw;WZaQyi3)-S56rB;cxmbJCD5-2gokYyRijvXV<^Rrq^6K2bU z4?cL>0oiW0$%S}U9LFp#FP9+HMEB)vo^_$V-`TK}F66j|EjdMWpq7PnosOIU+1Nxl zPdx%_$d&NbH$=r%a9VzX0`XRqD2|I3F(ool0M7YJD0M2L-_abrr?hlu263&F6*#M1 z*7c=~4?lsL8H994=hBi8={i&PI8%BYAuH{T8~v$1K%~@KahfK!UX95Kz}XE@i%I%$ z^f^H2Exnmtm%jsF#7Xk;NlY{a z2zj&(?q(uE&F5Zz@uxSG5KXI@(ChcD}!b~L9nV7#3!|6tOPKI zAZx+ytAmqT+!-RnqPNy(F$}|9;8VVI;I(&&2jqBnuvgh~tqx-{VEN=TC`Vicb+e%2 zERutrxH~qROKTRH%?~qe*Aa%LNTIX^ic-|p?1;G6VfSv=UUu^23G!?e0j77|$<*9y zok98RJ;bxGa)NKtC7yo`QTIyLj(vi)L-!FU^F?4gV%i>Nabd)8u+H(L$B248L@d)h z$gYJqGs+T99bZA>QNbdkwo@!h#E?Zcjy#IWOi7EbkMDL=?=I|IDr)8--%C8Yfhl_* zz2pg$x!|m$sKy3_u2xgr`l%v;>zIim*4EaFswvpaR`-Q}S4`M_)GE8JhK-ZYWq>i7 z4_MD`WYoC@J(eOoQV74wIo}~$m@Fqqs5xeI6$?B_WK!qgQhEbTa9;89q@tiv(!4`& zEnn@Z?qL@C?9}HX6wa-fcAllG2qrSDuC5eSRzq&{nqN}gflQjDBC91c(f>4#T|#hM zQjZ~O@kMaQmVi+x_N;2brmXO0#>ZC>^KjvqB|8!)pYFbDJXbAhrks;fekEpf6Xd&z zS!c>TK_Vv#R)KLEazuzp%4&6%ret}>U@&xNqn!X+8Q82S`sAhN%*bBJz+O+zEOf3x zyL;UwoKZ=?K2bh;YY(3tYSgmUj_JrHw@=aUAHHV$j9GcsrL-CdtQgk zyp7|BKME2vd&N76I~`VD_zG)BUtng>tB89`oILRrYysHVyid|K%ufx8XJBPzh0*FU zOw>G%5_J9doy`}Y$?5ylu!o;=Az4?R@=H^9uyO!)=6-7Z&OeKi2jKmU9Q7DQ3R z`uaLw{pwds#>LqTinW%0zkdmMWuMleLwzkH2Jm#CP`mt^hB0ACKpvOV` zjsfAd5D@fG)|1|bYdf2fdHusX%5(BOg95Fz)|Qp;HfzaEgPTA&wD@e^`_!vqqC+xf zSvNN@9%QJV+HsjNOF}F|M;>5|A;S`teWJ)_cEYsS2scOB{aX&w!E|mwP{tcyL!^u9 z2s=K`!rs>+-Rl@Y%WnXNClvUu#&IB{Hu@lUXADG@8DEV@f5Po^j3pu7Fsi zvSIe`ttiULvlLYrk6fiM{Gqz2pSCJ#D4|gD#3=<4Z0B~?qPH?mccG(|0+5#-K99N> zb0gj8Av)XixexX=DT`D?LtppYr71V8neL>O+Ahfx~ zn7rI>Qj>G9_PsBTtu5+A6Ad#L7v`NS7{vFop1us*PZ3?^#V!D^#AFDuv2+-bPZUL3 zbCAG?lYBJ5<^raRrNekUMk2?A&Qch!ejZ)8f$nAhPjuB{qABL~y%`-n&c^YNljCdM3|!3i6q5o6Xd^tXN7(ljmG zf6uBV$ET~b{c|f-o$+|g?CdPJ-+ntYGc$bQ3t!--n{Hxy+S$TA@x&8+<};t+&O7fc zXryrD$PuzEV}5>~xw$!Ryzxe^y6P&v^rbIx=+Ge!9B{&pgTa6ge(;0r-MhE^v&}x+ zMCW8?W`^5uzx}i=Ia>jSHm%Q|BQ^ePUrCa1{P=OMyz)w3@rqZJ8ZKu`HQwp(x1Hm9 z_Rn-{H6Ja(vPH6kj!K9JJJ)^KTax#3%xW$BWvfML%jNz&G7(3P9zoS|*<}aF(k$pj z4($9&OC0ecy`rzOE<{@sb;G+DAafOzsXMuH*ISB;O1ATJDKXeFc96iz)6Nyc#BH%Z zV!YmN3H#713V|tt7_WYqkC1qQ&Sn39_TDsDlC!+`{5_dj%UOF% z|7J7O+Qx5Oi|+?`8glu;-FP!sQ9JU>=<*looc%a-P9cpe@ps<>L>xJM1fsc^E)}%< z0y1+Mo^+XCJj4t)pxqaNqXdgL0WdoQjl+j9;S3_pZ0}7kt3m?oDq5hfEw;?ZW!Y*X zR6876xQ=V~+ze57@^VLNU{;9Eejl{H9>1O6bAF{j>6vRYD`pQ|XCtjLvY#AAA)ZK_ zQOdH*n$pWj2GYA0Q>Sy*(yB1G>q%FT;1Ig&L5??1#sLO1F?qh_JLw0Q3m4Jz&sYjb zsr98O&D}xm;MERN3!13-96EFebOFJ~M32&W{>#pmwGn@TnV0<^gy%m?_ssvxtfwqo zb2sAcvK3s>GDeq>=sD*1-N^A9|1;6*lZZb@?ZACtTFm&*bL8?vc(uLho{JX;0gN?d z@%O^Q_u)dMkJ~<#&uSJZ3UV}y^l_MjAmD}P zp9g`12M!WOhQ7U~DI`%rhiIYNM2PW}?B{6nMs)YPIqKKqAXYDn(RkL?UiPSS5byk- zLg#7lXM5yoQqkvDoM{0UBuhQ_X+uiOFS5>i6%*$}*Jyc5#aiNu7y>Wg^y$+maA5xd z+rln|Is3)Ua$Pb>fW}MPvs~Qz++!New?`IbWDg6Ela{%v`#mIj5nm!&tv2m;hlR!Y*anMGnX%YB!7-$MB_=q6if#Gy z0Ff{z5|GL2=84O?nD0@p#dKbST=>6{@ZS-0K3UlD@@$&?o`L5TAMIX+o;{7W!WfT* zp2g1sSdxK@M{{`d0-fiWt*>zO*cCC9froI6sQs^WUg%Ii_->Bg@V{DnZRJ~ZU;GpH z%%8>Ie-eMr!}FIobnpNgilq~dWr|;0Lc1@pZ|^*N=dVO@82uy*m`DzgIOaY;Lj0We1vXz9>3cm=)M5W>rnr4O!N}9 znOEY^y^3h{n>HicU7~*AK{Q$>eCcCI_X0t9nqc8>O!q~?&OhPRkK@hX0~!)7KStPX z#h_*}5`IKhCDIRcr4UfiKD23?WcLV&!kT3x>_^=yl~&OjF9fm}KCX5Q5L1(TbvZ5`wJA3{3cKrVg)iO%J5m|S~W6S8Ja+iu*dtn94X zpNV3*W>T>s#OA=>d6 zinoB6J`P&kUGKQT?F&D*`lNjZe}QQEtF*f>;LqNI*L)eKdy4M4&k(IX zj%p{qH}2_oX*)xdS+ss42>}c!cecS$V-Ksp2lo6VX7!7B%b!D{mu%@jPSsSI}Q#Axl83)U`@(bvN*96xA{XOU>WMy!`yw)xGw(MXzYQl?`7O#F?T;2o_e6|SfgEO98Gy&5`mD?0NAOOtI;^%*%w?KEtK#z7N*PuwEq=PTCw!V0)mg)t$4 zg9|4PA+Zucv=r;^5YbvL*q`OC@{D7GTDCIr3s!O=X`pVREj|&!f!Gf3PIPU9;ssp` z;AW$7)m2yV^FROd+;PVp)a&)Mv?UBf>h(IWdChD1=tn=wBab}73opFDjW^!N%{Sl7 zTi)^(f*?qL{_SsnJ10+`PU zD`~Y_F<9XGN?Mb0@C|-ubO(2BW0#FlI8K=b92}Zfv99?BpTg?`w#frPT6nA$g zXesV)L5jO;f#UA&#oe{IyK8X^mg4sEy&qXwN!Cho=g#bN&dk|+&tS7zNcB~k{7E~> zebXyk3XlvAiSSIncaf@gD6$;8C%2Vqx^-y!gLgy7I#A0z-|@&)iAM%(S^NCC%a}K3 z;Ui50+i*eCp;|=z{7JOW!SEN}g=7&<;q(Ip5KZGHduM&J_&?gq{W{<>`m?S!mV}1N z3A4u1+L`HZRYt+ve%vR2vih>61t7MTpntu#c?{q-c>Z=Y8)p)}rv~>j6vlR~b{AH! z%(K;cr&I0)F;f<^nx~i4CcH&MxT&nZCIHPjO@(9=^c`dTy~!*q6c`q9sV#>drD6DR zzEra5Rl8tn;9XNSA7TMORK>;kk#u?HRlf8k6Cz^3^!F$0aIY#jZLG>BUY&6&Tk0?%B z!HKcq=IULUM>_E@57j&kGut=7_Ohf_41BqcKw~9>0J;rSHc4B zE>qiBo0lhj^`{)U^ex%B>Gc66^}(eqWxQwMBX-x8P9M$|+_}JN zcKZ`H7oRzn{?--w%BYouPW#5ba4#JvL|J%K#Lb3CaGbq`vRy<@oBOPv*Ww?3(@YC8FR$k zK_O!146)q1(!n~*z74t)<#s9BikK1KtSJtX#AmAafU2DSO4TXKm<3PJ~kgofX4lU3j7A#3hK_l;lLi_4pvivvc9b5b4ycWquLCD z&{D~^=WoS#*k`=fta&9HI?|T0t5f%cp_Lz&j9TW~@3BC(YFc(s8M9zSSh@8Y4{WX6 zwx|kXjd1&-jJ`o3sSb@+cd|T}o2j&N%#XT3BlC2I0#%DR_X2;|#qSaiW9i%l+j%WK z-%>Z!Y)wN%!ozYqKkuzx%^wdq*QIrP%rV=3zgCLWxT8eR`8kYW)x!Z7NSd=rkcN8N zn}*@ZS?+syvF}65%g3nc!;0N5fgL&djwm8vBa4Y<$Dj3-YWXAmzR?YwPQ;?!rgfm;(Zl6`CBVW6)& zq&|+ABo*751vp=2zsWt`dmh^wzVMeLEbn(U)f`Ueue@()`}W4S7+ci;z6yYB=V^RZJKnLTt^Sg_ ztVNLyLP%_jKDQQ2GXyC8GNZHRU?}MJa3tRPVi(4J{K(n9z5N+Roc$;joGP%~;;@Y! zQY?ejOGRZp24NF(5u&(XZGVFtR#{Jcijp9b#&B_Qxma&zJQTWg6`+??DqApda>Ceo zP^(Ii!eC}*R;gWSKdY#mpV8CRU0)R6y1d|9!go&Bu+^UGK`l&EUTBy$oKAPX*NHD_-&8h+OiM?gArX3}|C^mQGDgE5k*MT{Cj1%-mncE6Q(^O6E zk2Qlf-ypj5MNWQCjX@Xf25+w_{FCpCL-7c@o65$@UR&KNk>Tyh{02BIzXpTOHH1hGN2?Zivi-Hys2!fKeV5RjS=C$z zwb4c)1b7)b+>Bm*!A1ZNlUC5oNZ|`tejJ@5CGZslb1&k>zWwW5_ONok(Iyl>Iuk!$ z*K}Xbh99o5*iXK^NG?liZ?**0qIMG9Ksv;X%}3^kYgSHm5+%{5W`O7u83NHmh~j>A>ch#J;v z6=UBx>Ah)@ z*H~89{Yqw7-`Rs%P3lV~f??0d^^gxE5vNl6>K5C>*g{m?7fFx0)(Zl6zc@WSj}3-BKA(d<;36`n=FyLm^AD z&;`qWoN(C7ShoO`yBZnxSQxdCmQ3WuyxL}e%8$jFN(aY9aCbAE+oeb3n+#7i4D&InmLfSLN0*I zF2#eRx8=(~U@zX?Lu`|-mHC6J*6ccl`6UW^_m{1!wI8T{@(kQ*GZ&`|Ged&&kr-%2 z6uGqB%z|SilkA~ZdF}#E4i>L|(79-h4~0`&BY140?_xyaWL?8>dYZrEJY4d0#{8Z@no&}?>KD|ayEO4OuKVWf zbo=G65kh(r2ED}GwG!()fz!Nmmk;C}#yPqRpBgc1f0JqbM#zn*7McA*(Ey?)T-zj7P^Z~9dj8ArJVpb3|c%*E&l_eHK zdzM1VcF8oRz_w^RfNq2c34B84$;qLoTcUuK0ZP1Zq@j)#5WTLA@{y|ImB9qD*W96#0rg&}}mXkjaV6L7fO+6Ro#CmGv9$l0@)7&!qBM~->`cEf=7kRM4k}aI&`=va=L*U; zEyBT?oIW1+ZZiGlm#DFA(m~$HlYmZK-~Ym1bp`NgJ48&fmO^CN-$jLE6UcoUuSm`) z^&kdyIdz8d#!Yt-BJ_qgk;UcEu-XUx(vx~dKy-7$)`uSefuMQua#b;-@PN@>LUcJ3 z6%sUk&W|K#lS!6)X4iZUydBr%i?y+wK?}~Jlt|@EzF!Sr&igo&8>iWZgWV|n^a!6h zM);P9BGn@4Ve1BnXKgeQ5?zq#)furrje1uECL#l>kT(NkBCy`-fCI8~`lEegn}!Cw z6}jCO<|qLHtTjNv%WnMu5u&@5bx3lKrmH){mqh(L38cAUj*p~Ttf$0Dycfux7~JWd ztJb{tOD$8$Va@wHAVg@i#B;U{A*U1Xb&IDcg@fV(J7=i{L=tmua%Zx^A-#>EP7OPj z(&o!UWy}P}S)$yyzgge3C9cLG(>a+K^!)XqG(wwU+DrBz?^FyF!Cb_%VdP+EKTUnz zO2}FLWVMeo>x+}_BKu;CTPGwGl8*NykQ~;M+ez6#g|!YUHG4E+BS;({qq?a z%ts)KB6m%Taa!q?T7`&#Gq9WgYw5h9)bWlfS6?A zANSl;Y+RxO<=*a>;g|@xUb#aE6U01xhav0z=4=@ zOTN6neYQTxqCmHH$%W5mGuEjU6@_D`{N-*Wz+K2T`8n$3HH+MPj6>d7`A!v2e8I|E z)W!%=M=Sdek9Rhjx_97~Gl(u?e+S5A`5oj0H+(N2wOvuA@+o$S905#Zc9Yj-$akU z@DsPtoJ?9+U9o_+mDL~$%SKJA(`n~a1isRB-e-;1-1H^XmR0hYEHElhOf@=0B1OWc z3C{^&%CIMuasP?-V&Y7WRW@DVQ@O8EP2+ICxa+0J^*wpV#VkN+t|Qh|1Z4X9=E=De zUiIE+caE7CtRdO+i|vZ0v{@_Bfz?qW{vd0XE4(Nu>Z!PW)Li`X_dvvY*by_E&r2yo zB~MXn%Zwo*5%%1wknMITk3+-G+?T>e&%a1k|2|6rLF?8LM&J|gZ?^F~wSme^aB_8M zuM@Mo=nUWkO4U*Y(fDhp+Vf?*PxWvuTyq9jQq!%o_q=;&grb6n>$D=O$olQKUwN(; z(#>j|Rltul*da7t0#+*U1HU7zbvzLxu`6M7l0slkI&mYtcYhzaX^b%Bt&vq``)gNj{6wK8HEG${!WtX9 zU1b}FBjIEcju_|ei^M|9kEMbQGP!8m&I0cg<{acgC=!wAjvX84cWdrj4zSI0HVBg& z?@MBrYs73v;3_Z)(}=%>tzDS(Mc&$>2rORNTW+fa#>6NDB1??4&T-mX7?d&dah?I) zGAw6j3FA8hi21=g`7cbE7t_+b2IQ@i+a6KVqb7L~NzWKJw?kAcc1802!eiPdn+)(y zs;4@v1*`Iy*7+{A(pkL4TzUh!?bUF7%i9yHDltA+Fa1gf49_mMl4wi%gcu%I5jIyd za;&&v$D=ttaeC#?qrsX7zkehNYn1_{xmFmcSqv<0qeyj5J>o*n2$v0-{E<;mDMQ%? zh1V`f2$C6ESEySxq}Dz8O{e?jkN4&uGbW9{s~2>%;X7Hx^I=!CHM#4G>C6y^6Texm zA7{=SL=t^o7!^?iK?!{DQ1gviiVuv>Qe@3lXYEX|oPhvYyaVH+RHio`*?P$ydx`rF zoB7WAYsq&p{IL3orii~?SeuQq6?_JMjFBqL7uDD>n!F09?^-E>+PO3Y%(3sM>l)VH zWAjp_A{NC^3*SX{3CZQ5!~7fjhk(rcb8}lOX1Y0iY$qe2h)>q^%Io{qEnPK9T~yu1 z;r06KcSi9p5Jf|8Z1Z6_h+40m@Z9PjaonP-Q3pqh?O^r|Il<#4AbZYhtxenLgA(=Vne>O;IAEg;_O>3u$I;;8EpD2~VCB)1Qrtpf$wX zr@Ax-7fhiG=M5=tBxQXB?%x4r2c|_|`9jxTj0)U8|5=bm z5~adbKY`c(eOA?OnV`-*sJ~P)`%_366Jf|QEQW%T{xP8gPSX?jdiH5W&ygqN+s`q} zkY7c*E8GFR3F$FJ7y)=vpv6(Js(=YS_M5H9;$LGb^TR<>;r!Ffs|skx6a0RJd*lk~ z9~HUAQN!NUr#B|_bAV9t-fJ$EKuxAxu{tvDoNre{Y#hdqE@t8@ zgISV5!;s5o_UmJ2q?isq%3mQAPcQlF3p6P>=h*C@_w)+cm#UBNO6i^dRpeHC&RH}$ zp>&+n7Pz~;b~|1?nCSz$a~SQt6c}uvxF^`Dg7(Ga*tO3~mUK@IWG@v>s;f6AYTN!H zxpo}t{H#cdrav&2+6l zvT@kiRD9qphcB}pQ)7mp-9)N&N<|j0pim22X^xvE;|%Y`r`q9@2lIa~#(hn*>xb#W zqNr1P6y6w1N-XczoQEt{DyZ{I7;s8Wnw&g{yc}6@@?5Ohs)DTdJjtd;4PuW%gv0=k zH+%uGt}T;op%{&a%(8)z*zslXE|gUiu~UW(MIAM4DS<(V^CXJ2$|J$b97}MjEUHHn z-pC+AF~6b=!glbB$r)dej(T@po;}a3G&Dp+t9aI z@KQa3M2TAQE(e7P>VGWF)}*xT-{;__e<_HWjfG|cJpwzB$9)^jmY4LKO5TvJ#DKj! zgj?&*gOT?}XtXpY8ew3UJwB8MKvbzs9E{7k>d?|vENlTkK^jbQlCdwb_!~boyhTX$kZ<+Ne91t;gl?Q|1RvZ^lk{qgshIC7XVoGjqdv zfqfa1JH;vZoqmA=IED@z+aW>b!XDJV=ee0{Un!c>lQ)^j`VuxqUD%oSXI0+SBYTGX zmu4=eUDR3`9eSlc3i`L1Ro=}OdioYt z{!b}Y)ul7wqg94m8vCBaP+yo-5c7<7iYCHCB%* zGrK_4-J+>1=F6d{@7gx%i>7oDM)~nB>_BR~@-u$PGdNY#k-jz)`m}`6`FtBkbjwRI z;8jcza#~9a6WLhT@Tylg#6M_CbGW$&5p(!VL@>m@D4h_bAeU*&EnBYZBFr0`_FEcC zM@Ar$uiBPm;@?smT;sLo_5BdnOasVuv}sLnzYd-T^zX;3|K~Yag~sk{R3fe)!fXx5G$Vhw!^wo>)SpmYql6M`G@9EVhuCC8TPsRL_-GuG8tHH7>q zMaC?J+f^1{vI4Lc;|BZE8$eg1r5kb{5g-9O+m0nK-ap}+mmOZt0@O8CIAl2=kZL$S zB|yAziBHZ%)ie|v(1&fVr1~4AnJmBUuGI=(Z!Fqby|i{EXi<|XR1`klLz>gh2}jl2 z2jC{z7pWu_^o;KO3M`Y>4!6Tu7ZK+~`xB)s7z~j#H$PIkei-@sMzUxE9GgHJW8XZ; z9;LkXr$9ItAX>+=mkX;Wkbps{>AQHBOYa^M2w2aoh&X>HBNg9=YjTIs7@tl;uoW_V zGMrRpke-bJ?M(xF#`)%THP*iiRPaJOdAl^|JluV72kjolq?H!ESm=fF)Wi$z!#H+$ zGjq{0q_b8E-tB!ZTMUf(8-OlHG_DT;;#sZYZxx;(EtNm&VdnXUL(Qo|S<3!VjuVHV z`iPB2MWQ91Gv>nPN|V2K{}ou*n@==_8T-KR|IC85oS}{`e-4q=|4{#Hwd%+MOVpMqxWVtJ8>8N4Wrd~f;t+ad=TvCV zon(=y@)^hCm5LeLP;u;zOs7gBY@{6-zGk>rmLw@e`&&Y6V64X@!I(Tu;Z5Zuk==fT6n=YcspnPlwi zWwIw)GhF+d&2(Z26F}AhxtpCcdj^j#5lU1Yri?}C*Ii9Nx*jgAl!EXYYl8E0e?c1? zFy%Xv+<6pndh}gv?M@AA<5&M;+~oK?oi$G}hq>N`ieLo&mmpawTPKZ}t)B0=BYX;J zOvU9mI26H~li<-wSG=qSS@GIdLXTTZ5YeSp@~ue8wm|WYpKR={9Ka8$T=Rdme_5Pe zTM-ArIN#KgzvfmuN{9)E-_guuq*_YgASsqB>7nYBSfQE4990D>+TOWl&@3hBRF)#K zT+yh9N?4E#wdDKy#LJua+lNS={0XRY-A`}Zo9;Bf8ZB`oqlLBa%(=JS)SywTFST5o z=bz~v6H$9nfk~Q&KGw5AlKNS}Z_A9}Tdb`h7syjjpsy)~2h)i^O7Yo&)Nb>~A@<uu~iIlcP`Tkz$ z!E$Z-kPAk)Fs-t5zlsafyncT1_Y7xLv;LTTKE#2TrsEJgr6z;1CMejmn*)MTsOsCG z^n-B8Yv2#*ut}Zac;@k3rwPGGV8(1q^Hb*!3-zW@rT}DXQ8-;Hw0v#l3Ib}!Z3H=J zrC(}h;&jr}(+Pb?X?-jHse~??#37I08 zpl<%Rckxu~c;jGlm(cdD`qDV^H}rE(8dz0~*+nCPujHtGS@F{iCQ;wPk1u#@a?hr) zgHWfW5$vmqvkt|IN8Q~k zai9?rr-vmEJ4dqzHJ!bDf-_KCzE~W!58x6*iKxv*K0kjg(iC8EU5dBkP+c2iW5AnP z8Qrb#P*bg(Vpn_t5KXI(P1_0l$qR}3;^#&the)!nh$#evw)tlxN_lSS!Z*Z)RaHza z@GxAb``?wzmsWqYwOq(db$zxp3V9A!alqSKQeOBru|K{(;eXyTXNcNUY-iPj`O8p> z#UJ_Z9xBylE=B+;SS5xYzmcE&X-#Os=P2~>S{yN8rhcO>(a4#C31h~jzP_IYE$;Ja z^+0qy+8y?9au*G1_OkA@$pr5rgTbr;E_*4Pw4yydfxnms)7~B>v~Aqx-#z_n+GGdw zBrV`@17KpNC0ub4^1_yTbp#x+aaav$XDoe^FqQW0v+F&EY$e{P7agEJ$j`1C5VbNR z=xqK(V^|Lg6t{_3oL2TPYw;9FnhpmIPpCMc8oV<#JRhbPwp^xjE7=<$RvDkc0Hj=I z6`us-!?Z4DN>f}gT=RZr2+j?8NH|ghuH)bm1&g@USLP|sPn$VFIXR|i$Q6|0{|ARd;4UTHTvGe}w zIhj&Db$~iW)8_D~;p3ioE5oE8kovpI9mVq9zu14X;p^$q=cKG=`0;orqP6s*^o2WE zxP)d~nou~;Qn{0O@wdu`hX%zwXY@SdMFI21bG_2&jaS2AsK07+{JJAK7mD^Z<%Q zawc4>60Sh-S5T_9MMt3}@iB%?DRk?x8@2-I22!00xW(++VsHHUaF~HBP!4gh&i@|P zI7@O-gyyDT*T&~5iX6Rp!HQHabj=!o9i7edToL!uP4j28)~F@ zHC4K4lI*AAd6UmtKtluRZW@6HsL9?>HY29KrB>znfB0NSAu(t1B4})#l$|HN70GTJ z`}`gvfs9l95{*LX&FOT#jF8&-Y4xCq_7={}B3lnwky+U)|4*i;bRIUwO;^xGtl_DJ zPl4!?f6|Xfn`%9la|C`iqjf{-I|x5aH+qFb2*;)#L{VtlFMhSN$O!3^!L z#cCJyouP=P^agi=5YmLhe(@xE^|FQzIUF^7y z=}`CE?wz~&Wq2^(9UMMo@`}Gv)A(W_7{!K_RYCFqT*bMjAbh%I*Bk8?RPm-jWyx+G zDMH-U(Jb+9FUG1@VRT|?TbZhx)XDQ%TT~xbneH?_y@?jTnf4W`;}0et{qD(PS2Of^ ztTHhT?`PTtC}}jo*wPHaQ?;Y);wOF6&_PN~Zd7*wF(Ss;Ls?R-%2;4fPNG#d2Pl{- zOjgmyD?=Iv4HdYn_jPN`#A4I(_$oj%#*QAVKAQjCkZY9;9!JnvKrBKw0zr#y3uh21 z-guh98DURUNm}aGhy5r@N!h{9y{G!(_}YiwDgICRI>w@26S4&4*gVH!bvI>l)s1F! zUR-!`CbQlePxj{!3ZLyp3)Exh>@%~~8y}aEb)#;n1qzS(@p=5G<4k~$apJiEliqHh z%UMM?(jB8+mJ$fxwI|j!H}IODZTQUk&Lu@FvE^*=RtWX6vZJrQUL=YtZVwKWbk;6W z$F3$-A1QHbq~KOmEHK#e)v#$SY!_X(6UDlR7?KXy;o1p`oeOTbZ`mYT%{v3L&jsxB zfYoln}@bLW|9`SRL!IcXotUH69K$tN6L>GC<9?gZVVs|u%`r?(Id*v*OEu7_GU%4=l9Hf9 zN-eK-Z1U<}BYrRoBake-JZjP?4&W9~b2g=2 zHkc>#*1dZLJJYH`yWUJd=}PUR0~mC(wcUWt2p^uZ0wWZ^;ha;exrA08eNrWPjZf}a z`Q}%~_w@;GqAEH=f-x2gBpb|-8$SH@m!2w4mTaj|X;#YFZohDdCU0BO=RMjTBYKEA zqmyj%ER*R^(HT7{gjk@k(pHKpSJ8^iRGtQ8l(AZ`vaegY-|;aeLB&MhY>QS0dlX-2 zHk%wM5fH?yTv$XF8Ef|27P@#y?gOF@XT6aBETjf&r=j1d+|>W8lq*QSGNz{e`VO}^ zXb00`gIa46V*2iHrSCA~1q$2}ZPZ7uRs1Q;_Pf1wjg(FyJX-Ct>O&_%I8L?o0y*Y9 z9~{$WaBcm?Na~+y^aB?8K%$3ZZrfOQxHrV+SI<0v_YC=N8#lgB0VjD169Kj5} z*o460Os2q{nae>e#Lt-WIM?pGpclTVIpa*Tio&!~lHh*wCyN$m6iCFf_+I_BsPyk9 za(4}(R@Ni@+><0OvG<)xF<9ziLBDBfmay=VUaTr2ZZAkGBFyPCHh(na zaQ@DAZupz>25*zFa%qmxs39B?NnpbWAM1kd<5vsP>t>#ki}vB}w72M9r@TDpfsTTq z^axA`zQA4Q>zcts(Hr3ItB1oM&#=mS5?Uh+B0)$acOO3IVtdA*q5Tb3wc|g_xu3it z{2{Kn(c%xm`u8(CdKmQk(-8m-MdAxn#pcg%-=BT8TNCZ zs850)d)^YCLM-(cp4_w#VJ$RkCxcve$ks&LH|EywG?oiDKe)%^IgGQNf%@PWSJq}E zm6aBf=^eDW%KST=6QP*UnUI>n#WP&G`4(J&Ct|MqHTJCct0MRH=X{eKh(f)tC;<`R zrQel8cN^D-zownW1noxviE3hZQBIphb=Y(lCSj}iv6HqJOviVsb@Aq(RIa_EOF1s0%vj zA#2B)UuQdu3ig-7&T6uP+m4Bk z)3KY?n`@}zatG6~oOTCDRIu{EJnMwg=*<-_NwN4d=9e)MPxzrTBeC_+EoDzfS<%wv z-|xPCE=_}x9vs4QQV^pi`xgZk=3gmFt8}tH~bgMes-2Y-oyGLrQZ1 z@~}~$FW}nm4Y;{L+eX@N^1CTBP|q)Nby!%TH^<9s|V>O zF#dnd9y@Njv{*EBZhd_uUCgwpd9?ltf#ckG)byC^$N%tpP?|hZuF*`+SVNAO(TO8D zI|@+bH9gEvX7WNmoPJN_H010$^%O;cIj5h->k%~fiyf(I(Ea$)^Z$AzT=Oe@Bd#WI zQnte|@I|e@3R{E5SA%w#HqBp*4eCX@7Nb%JL!c2S+#)Y8&_>-%5wDXl?Kvo-3aZ)& z#bpOgAusF%nbPHVkQKWeA~M&Rs&GegKZ0YGZL(!=B_FdO<-d5bsNtLBHYnZ3mVDwt z4~cdF>5SB-ajZPcbrOt1B8UA8lb!2IfE3V(J5g-ioqM%Zyj0zpzO|ybT6I2jSgy&x z8G0|3FB}6;uq@qZb!f6i*a~~7Y^#x31BRVBKgwP;2E_Ng6{m1KEv1_o#Vw_ zQ7QY9g$t$?f;|#4)s1KKO)%F&(x9|)zDe}m-Dw%KsI=h#5LpNI65Tx%-C;o@!Rt`^ z)JW~64!3)@@9%Ak%p;e|>dsv{eksJg_7 zU5iI*d+R1n=~#MZvvavhfa>=1AK)du4|W zdrP#>F_US}jX?S2#)ZnXHD|qxRfTlzFzT#IJ^2IS@*|KmCqt5GrPNL+mmhCGM<_0g zmBJFCz)pO6zrhVgXnM`rZ-2-hE+|OMXhQ6bB-y66 z%1d}g4-45Y*#$)cT4Oo8DBBi&HYdiaWn6?eX?ucW`mAkw%JX5~a@PF)Zn;nYIT^P5 z&Qfh$YK)?y;}c?d9H620a3W*h2CeKL|3K7|{wq~Ajodf$F?ytL0RYZx?WuKtRa_D` z-uEnYfBb!<5i)1-2wV=Qt@u(!xD+aDv0PeAkMq(@30k9HG!6-K2>@1GA0qjyh} zE!_dMr=8#3#M!d87S@g@H(TT`-5s$?!X-njI)T3@yR&&n_DuJF$ZSxFmYohM&V4C} zqGjKG`En67rL6j0B3xe;hi1PpgW-Hv$yt4F&nDV6-C_ct>j8jd(|YSQt09#+?Kkzs zCnqF5l^bZzm*|9U6{bfiov;01=12!2Uosz5s?S6H`qzmqw_5!DEsET`pK#5^LG0KN z_+hWRlv4}fu26{qSqKl4j~c+UPCz?gocXx0>F^6L1g3h-wggO*HC}9EcgVUJMVKBJ zk-dNa8dq8G_ai*#2wLM_jXT&nmO9PpbXeo2-mql4379I=o>mn5r2|S~Uwg-T3~<@h zjeRp~HFj^o+J!SHqe&KYLaYoOOuTA?xhN}UI8>4r6M{!C`7KgVb&y!jMs_ghd;)wW zThl$V_QKb;r&(`BsOS_-jj&bR4)snv*@J<*jVZG~K+Gwjv$kzrW#e*nK^K!?4e7R4 z3y*eTjcSU|Jx=*-&#UBPj84FN=GLw5I_kYxa(EJdvrgLWW39XZC=SWwzUQ#nwcbp` zA_*%uI5SNB>M>p;lxJ?q|Ky{Jp`41E5jw+Jt#P@rM%sq`BToE&9^91x7v2JKtNDjT z{Pu1nM5ibG<9tfzbzSq=MbuVU{;vu_u=L`A__mjNnkVPE;2A%>SFB2Q&Quqe4(E*g zN@(0`q&dyDdc%8$ozUcPO&%*FD9`6H`R|9avGl6oRr*5QgYVoDZ?NX?Q+1AHQlNAV>$*FV2Sa=J z9)GT&{lrfLkmYr#)b1fAzcpcUcuI%7Ek1KrzT$>?KixKcR#GNe>ciT4+asuRsThU2 z7M;_Ra=&D9@0=|nuHy_Wdx9CLxl-Dgpw{L<$aBuFkJx+Y+AGdX?PPrGX-V4Fpk5!d+mswG zA0?FqKhu1I@F-35Js0LP(bJ~pP%_&-)M+0JrvpmF46@lt+8PD=(*pboAwBHqL%gT#oM`H2h&XXp+m-;+0>n9qQ{XwPeHwZ^oOd8UBv}Qm0#*APp z%d-1dNAA zGTF(0xH)Y<)n}nfG7RBeal%lk@jDyBhdnljapSq5jh9HZGcEp6K5`?vIQr}l9-kgy zw27Nr^VM+s@c8Si@6L>&jt)I+Oq=4qBetyo3fS&wK1Se-|MH<~dYW%Kw%#>ro2dhG zjxYGD>YcNx7xrC5Dwz1hmSt5u5-Mv@c%E#c`N9gITs4M<>tnx&(!d9n`!k<3hg8J; zC2e+>P2d4w)kFLWeQ(e-K^^#9dUKI{6T6=Zy})49x*(_&l1qAY@q=4iH7DnEexm40 zpxv<>$pN@jB|N(4Ps&+ra-EFe+rEhqKbrpw#6l?Z9b5K0nB*A$$v%gZdPn@w*ip1)^{;PEUM~eY9uu7o{>9V`r-;3{Kn?N zsw)`W)Pr1IEAfcw$^J&k5*Btsq9tj4t0v_#!|F#qX+Da2eHudb=$F98={ z=(H$QjBSBGisv^r67osmeeZK``mr22zM-OvW0C^{_gll*b-)QDbg32VNV8^9{HLs; z$<;{I(^mJ8i^HbTbdEd+)mz{7gK4@eEdmbX_!&a(^h?cUi+OM3%m?R9NJ%VUzJ54O zx8j#5U>@J7D^Ts&Z3u*ji+uOLP4c}CAuC?{;e5R-u9PP-b@e)Zbv?;Bb6tSu7eN;p zQAqdD*>eRE5Q!7M$G-~rc=5U&qviLyrDkMgeBIi4Bl++B-UpxFkpwE4h(as!zgjVK zh^KP1;Tp*n8#^lNyNfz(+O?mih}fFVWI=RIdBNA##V5{iO5-*~ z2$XWKv;a2^oK~?Rgg9zs{@`kS1Q6LmeNgtW+iV+#Dl9beQ%CrD{#8NJ@V&Z$Od^nP0Ne$DPq}-ur3Z z;~rk`=>H|g|C?03k5RqG*4Dou1n}9?8h8Od8yVlC8K(WZ>Smzyc(2NrmYC&cu_K!umo8j}_^}~c=Qb?ZAuL0WobU6Z zxL^x2fLZoOq*J2m=3q6aJ+~ZcKv+8KC_j#BO5?tX6j| z5TA*1ZN-<2Os97FqbbdTZra}&NDQ_I0Fc2-A>&}D3kx0NIHIwfhHZx;$gcUeiFYe4 z1Tw))S$?$~uA`O;H@u7q3m9kd3#w6@v@4}jTFij2xL#cugekw7i*ER_nS`+Xh7L9 zwg&Lr@*{t{qFoF|Kvuwy6R}0{8{;D-t8K&_2g!4l6MuMig?x%k7(Ut0cwVZz(U_|U z6?`~!R;qtX^GPG)JW5bL|+^FQmF_9Mc3(1uLeLO)n2bBg9+CqOjdZ6#ppw_4f!F`Z9Pl(447 z^om1`)17`=0zJWj!N{7un*M^*#UUh6y0VVk)D-0`1nRW>ja}DJ_92iU0{Oz9ip02n z7k^|rfra$^pHX8fI~p6!A*Y14?XuL!>xAxdARVo@!P#g*aT6KOp)cWcS}UG+fbX4~ zlos4O(~_1cEN1vm8@+#DScs0)CJO3hRW`tn3$_ZLZbJNG+7}L=+#BG->P=c2dkCeD z6`!kOo&7>og!FHA#y%k04|_vV*#d5n5R^VlGlDF@qJ>j*X$*)?={|%%?EAV;cI8Dd z13q!@6#94tmosSTJHbMk;P1VN!~jBw9J(+9-8;9yLKZ5PxE}_?*|vWE8Q8W&Ad8GE zzF2S2AlZ>ofl@$Pn_KFsqF$^h~8FIwD-ZQ_K-?352A(;6^M# zLkxSnG_D^$lTwPv2YPnqyF=YQ1oh&jcqssxL}W>B&a9;o)8{Sv4wh4XP4de+wlMLt z{p!|NxQu3?6DdbstGV@6_2ECsPMW1C8h`w@VHj&hwo=qce3%VE>ozypHE{LaozvxE zv0rfY_?^=PSbW7zA6Vw;;T|c(y0M)R`cY9~?J-vT+Szd6#dh|MHCD57XnY(ILa*T> zjQMx2g3T@{I1vO5zx?`27pZMv@byb@vNbI`17si}LJah57vyteFnB}woU^59Ap%B6 zKjnFuzg!EU?L2&19&$K+P#S<_McXc$;20OBod-zg=2qU+#T2;@x1FsZjt@O&pZ=?d z7+Rp=r**(L#$kSTn4q{^L4}t;kN}rvrWou%DTdNT!|+WC(WexHGOVh5gw>C=Oyx5A zSvYE(DPdx4i=f$*QVY!I4wA!ZE{L+ahm`q(HxTpX z#1iU-U`6oo0!BQ3-CD06p2klT-r|(th!|OLNAqF+;VoN;Xb|EYG3|NGHEbMRpjr9% z+7W3~LAvBDF4bTxxVgz~^MYX2wzz*+l zv3P>H353$I0do79{Zb`2G~PHP(s{bQZY}v)DLs5TM{wjnn(f)ySt{h{=!!4$F5Nvf zt6IpYXl{42-38x_&+SZI_l+y&ijSd$bGngpSBj^cq6gM3g^>JFyzdEYkeVuHd8A@C z>gj}hg6T*x%rW;X7nI{G^Xvz}WcyVJArJC^q`rYOQ3bA=@<=fLmZTY)y1AujRxa_X zsGP=+UHpGg6ug1!I#(?lYrj{{vxR+d1CMik>?O0i<+5|+#&VplEN+0pGiF|18B0q` z-$KZ~S6*ZcuF?AlLvW*67i9(vSXbgeXm3oKRx(9{Tx^rAdFPp>88Rda3j5qwy5{w^8BQ-aCb7^oCOjs_N#D$;T8kTeBBF*U zO?zy$`w-ks(i7(Yg^fsM-&#}UkS|h=5PXWQ;yxz7^&-A?O9X!d8+MFE`O8JiUn<&9 zn}1In->imdY#AU~v%eR+xk^FJK=q-mUrH1ewD?BL?m*xyrs2|InTSKP0rF1<^(uu3 zvsJi#yZiw3=NhNW!TF6s?C~HXN-G8)B#>+lLeb3HABkJ|!Ly(^dMx_kg-Rxp4M5A9 zvh2Xf5Xv14$z9FSjQC4unIfaFS$gCLHa0uxUh=( ztDdUltvKz(RjZFF?iyMi|1^t3Q`AP4 zHO7YOBNGOx_l}8D*NW$?9B=ldp<+pe1?q(BaN54%<&X#qN!R2X;b}}d zA>Wr=z*t0AxNxdmyMhp$57DE#9I<+E=5(HZ@Pnwtb-IK08YWnZHbC|pZf=a(D@2kS z>Bxj!a=3pXmI{Z@=e5TRdGB2RvC$uI_FV-?L|)crZm$Q>z?Hqvm0Vfh)Kh?YeyNZd z>x#wFdBM^1@zR?oL+TY8@RSztH`nJ^iAzQ>oka9^*Xn8TqMSrsqJhz zmDYZQH!iP7qta9HjtecY9zuU_Jb+BP&ooONsSmLx_?Xgji{n9{#9#P#zP}Wa1{@8j z3M$w#HhpMb_TSf(Jj`kHa$qKyf3vNX<8@9xY$~eS3FhRO)RpT;cS~JC;*;0!4Kf5v z@wNND64erI&7X4kVb&6U>NqrMf8OX`gt5rDkR>7WqejiVtfo@y9=d{IB#!LZ;L011 z>}gcyaW-585}Jkj^WN6-ZvOM4$>wtk{?E{Da%$?Y7b)56F1*(eqhY^{=<^)*>lNe! z*8iNN{!1Z8(|TVmNWD)eAeI&nPDhgj{*WQbz@k<9K`>H8xKEIjk6I0ACbM8DIlE9V zT2F#(v;y<`oqATv@#88~a?WkkiwKL_Ck)rnmTj7~_4N;gue{KD@AP_y@OrLcYdS9l z{4bCFV_UmHcD{R9dHHKUO6Rr~%Dy)?H2mogfd@f*lRj+wum(WP>ZV^`g*>+0@Em;i zi4cMV;{smyH+{iVdVj9dX{32CcRI0AAKmq`&XA)6?06)9YUkus$H-YIGGyp?1Kr>% z?lK0~)jf&@1XEtir^UW{03LFSjL`@!VJv#JRa;yhuTA`qfc{}b_H9A6ejr;2Q8dcu zvOOHKI2*gVvf;Eu9{bU5|1z`Z#EF5 z%TWSKqFz~dMGVY;tG=7eas#x;Yj96L@o*k%@?S;Gbm~AFjw#)AVQ)%2-2s2=()`?8 zHt^we{5G%Jx2C7-&N~)nrm44GFoD3zhX3z~WMH%mthK8j^tD}dKt>u^)?iR6$RU@5 zgUw6z6u`+*ff)c`+nFGg6S@gGK1!wVfHT-S78YE^SI<{%G-SOPpJ42f%Z%{7Z#3%WDugvtfhAa2Z*|zFnU}$2#x~$Ne=K)h{ zFI=0wx~KAbQP-)yCH=4eE-MB0r`JuMQ7rR1>h05S)2ydA@$8uL^qgPp^|^In`lYf# zZ&NKnuG{;jajqWoGGFuXZwJnOI2h+q#wxS!qf*oMNeGQl Date: Mon, 4 May 2015 16:11:25 +0200 Subject: [PATCH 0345/1390] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3b833e8687..c73aaf9a7a 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,10 @@ Features ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/candlestickchart.png) + - **BubbleChart** (area covered by bubbles indicates the value) + +![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/bubblechart.png) + - **RadarChart** (spider web chart) ![alt tag](https://raw.github.com/PhilJay/MPAndroidChart/master/screenshots/radarchart.png) From df2a11d8ad1deeb1b1d769c0e39de97ac0143cef Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Mon, 4 May 2015 16:22:11 +0200 Subject: [PATCH 0346/1390] Updated screenshots. --- .../res/layout/activity_bubblechart.xml | 1 + .../layout/activity_horizontalbarchart.xml | 1 + screenshots/bubblechart.png | Bin 218355 -> 114951 bytes screenshots/horizontal_barchart.jpg | Bin 39571 -> 0 bytes screenshots/horizontal_barchart.png | Bin 0 -> 16989 bytes 5 files changed, 2 insertions(+) delete mode 100644 screenshots/horizontal_barchart.jpg create mode 100644 screenshots/horizontal_barchart.png diff --git a/MPChartExample/res/layout/activity_bubblechart.xml b/MPChartExample/res/layout/activity_bubblechart.xml index 9d17307a4a..1cc55dfb42 100644 --- a/MPChartExample/res/layout/activity_bubblechart.xml +++ b/MPChartExample/res/layout/activity_bubblechart.xml @@ -7,6 +7,7 @@ android:id="@+id/chart1" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@android:color/white" android:layout_above="@+id/seekBar1" /> MD@lc%Lvy~~sAPb-SX*!p~dLRM{p)8xi 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 z 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 delta 217368 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

    }WjPQCw8{S#}g|vb{$sVC^=OLaB z6JD|Y6IeeLnZe~@-GfrNj8n_hc9uQi5rlRM zZsE#S>M;SaE%MsSD%AZOZ*f(fMfx72!BvH}n$#uERd8E!R|GZ(&?0s(ud3&fPPHZ( zfz{heL&+VxQmPLetUrJL+-T+rJbexj=RBSld7S^%rIGN)g27XSHaZlHAr%AFmN!NG46T;@xCvzJjqwutCv1_)cotzC^%WITa zI%yn6G?}}_@hxckKJ6z>)scbOfIu_A6TWWL~tsQ_u|8zZY`gqkre|Lqz z+?U#9P0;JEcWJEn@*fQPp04SiQ0ebCFi#WW0?=Z&HwYg$2v3Hz14*=HZdlsSBs)m^ z-u*76yL#Z{|7(BFCG5-=2k4f=z{`g=naz1G?AseS__U^q=BylqdjQ{tnORSf?8AGh zo1LWV9X8o$Nkl6t(n+juE9$uHlT;vlJ`lfQJy4Pkxc4Zlto(lk%Ku6hQPgLmf{k?< za|JH=!-keW-|}pW0%xMSJgKLIPn)u6NN?K%DCaB8dzO|=^$oOsUXDt7^3&-*76BAcDu74zH=tNj}?OS-`l{&d+M@&=_2;=gh50^WWrIX zlcFb5_TD;Rm&>w?+O2g`zw*vHPJV6*p8R_{eQ^LPzBa5|c~F((Vc>9Kzck#c_NTly zwP$7eHvvf8@Rd>EH^E{PR6Hi?JU82oX#K%(hSA2aT@qfL#o`-bLQ+5gj&_pXR?~iV zPXe>5``-!1fMc(mo+ht-D-&|p7Pv?&+{LYDvnTR*YikVdbDmsd?sx0$pQ^aQYtNni zU=4wgU#9Aj`1E-9yQ(TE ziA{T}2)Hde<$dhyK(fIbwI|*6q)bXm!agfQ+@++7W@CTa>-{RR#5%-Dcl&%U(>`Yx(;f?MIe^WH2+l&RV~r z4fvOo(+ht3>9*|SHjzS5RHyj7OsW^ba=n+VY+x1<6Jrqid2M4Fu3f2hz0WdS&7;F~ zJ{B0*xWovW`{OUwe`VjY{$M|rO+8$@TBjQGdqoZuxb|r;rw6Va_7_oYn(EJvM~v5x zj`Hf!=@64+)tENs`G?sVo2}_$QMXVo1fgGU^lig6s*#b==^%65hHBuB>PaUmAxo0X z`Gn$ikLKNSy4@|E<2*2$JY=ghe^h(xX#bP8; zFdFkqd?O$$OUT&!4IXCGSvcvqakHO;x!($N5b4Tq?ODb@sm*GlurW3<2}ayG)|smN z<^~4FK~ig$$61V0qcmv6}&CYy1NzmN;lqWyLc!tL=n0z z=5GF6)OBTH?rPx!FZ9!%#qOAEHrHbY5fk$K8+56tCdeNP$k{_gdF4NuO4ITmI_xa| zeiRY~^KC~BG1Pr;%_s+dt}!x!H}D#9L=LqoZMrR?j(ktZ{qiNN$>Qn)YN(X{L$b|7 zt#pJ7Veh5a(W@g2=!SiR^h^h!&OwYOzjcK_O!v1)Yw6g6U~BBMht4X-+QkLGQ1AT! z7N%H`>F0-vr{F_Hcg3g1Ux za1W#G(}0lWZ969k8WVWEg`fTX`ymcCO!=ep^Vh2%c*exJhZRZ;x@Ts{-p<39GgoOE z14kCie=HAqAqTlEFDxtsC6jMWRVYOtvV6>+4v5gWAR$ELo%KCSX#gA)V3 zDfzk0r%3U6dk3ISztgtG>+(Yo!8=~nPp-}H!v`rs5qIq5Uy2PlhaM;k2@cSEK`nC8 z4C)Lpwn-06Okt=l>z9$r2`Pr@zC%D5!g%@bU4||aNBZmgHk&$_y0$n zB_$m9V31>7JB{_V`tSh<$^G{HeZc7#%U<7r0bh`sLcC&)Ed0>HA@*JIz$Bm%3j!pM z8&Us zk2))u_b!5qwPeLASy=iMZkBZK@Q6Fx^9mf zpo4NVve5N=5qO#VZZH0Jp$53PxWH-a{B1MPjG`HF5z{tS^0VT&zeZ7sNTKsg%6+U$ ze0|o_K{P8%Yu_$r^G^!bf9V_uzkv1iH?U^&#icKFlyesSm!vj$aZ>-VK$#^B^B2s? z0x#;_Z!8Ww60wyb&ke)G%1kdXZsl84ZcpSXngy=8Hq*E0wgdHdW~H+Vc{*yGsIJ1x zb*X+W>Ac#NJ~(M_8{Ls>YHAi*d=Y9#!GWXCy?*|}xBX{fbJ2WLXNph%@b`bSAJM>V z(G!qvK(_DlF~6VDelS2O#$v1jo&p1|d;!tGrz?P-Q0fF}?eVf9A7qd#;OS~pj398& zArK=4&_D+%)d;vSI-Swi-dw-W07B`ngXx2aQ0N~|B2R}q?uW1c%a%4Gf$PZ4W}f!{ z<_RRB0k?-ax6RW5det_I^?y)I`5={iejU~K6qr(2C}{FX^FEW#BH-rxRc@{1`7fiq zge&n17$~oWGDb7V`4+!A44kzVC;~<`iz|8rG2K|LZ)j5~_)b5`M&H-9WHfX?EJTk} z7F8|Rf3>gi8%BO1=_kX8_I4hm%C9Qc0@sa|=HDMs+Fy}WZ& zOy8^yvp-1P?d-b&{sV^QJ7}|I(2#45IVN2DQo?d&XwD-uVG*?_d;IVM7pOOV*$Oj9 zbPvcrdfa#O-lO~n-i?#Z9(Ni{5F6KZmUqJUorL#DhZhpZjoSqG=h{y~f%gM|)TWS$ zrKM`2Uf1~j$oR(N9YR}AO?td%cR1DKaHix0*OXl5Uqal*tdV6Oo9vDHebLi-P9l%w z`qiiPNVl7BZt^7t3LyW(mqQ3LG>hoZE|{OWO^h#$*VYHdwT{DINSEh~i*xVRn~iD7 z9;>zT_B^()W@lOd3D#X5as|=N(ciN+yb6(3VZ@B^fIvc4C@&Wel-WQZ^!fb37b+C>-2gqB4J{E{wa7d9p)Y1n{KFEKX{%%84;$>Ybrd6Djq_kLh1 zsaFyPCI=hY&|`J16tR6V$Pq;#tRWE0E#7t>9&&OIcb{$#oPuEuTpd`9Uhcv1_UUWRpUnkJt5Q8C&Rw)b>lVGF$?zm@VW#!u<>neM8pvx^gkEf^) z-~t+Sx@80Gb3QG2b3GUl{vNfF@CAelrZ<_dCt1X7{xqxYw{}2D6V6Q^pKLnlO9`7K=nbwkGlIga9R0Ct)}66|pvIaXDP< z*3j+;mDa3sAtG2}Ktwh1!ewgAmlv$rn{>t7LQw*jIA#JR+p<7&Iol32xl6}aesT5X z`V8`oeE_Y>nGM=K3&@mtZpJvGU|K;^?@^wrwI^9pQa%!IS(hrASx8N_Bm*IUg=9n4 z>__J5Ah-%F4p~5|_p-cUl)c{x6fw^A+UIz4a?PMcIWk@B$EroJ4(bWKMTT|x?sqUDaj(A{hP`_*Jnb@nySkNYu0CWepnfn9})jmmMK4&)jF5c z)6U%UO%gOItbxi^PFO@;Y8wRqaK8C6k(hr(Jkp2!?jlQtW89Z%U_omI7ARv`>03a` zP!Htf&brq6*5A>X)uGVWY4dR&r|BLNmFnm5x;6`r)wNgIzu*oFN+4Wmc*%M|1rOcCwecQR&=iS;AyosrVVm)@&0-8E(Q>k8k24 zrx1bkgL+3YAy93o_HV0sQ=U`2{gz5yrG2jSJ!P)delfTYpJlZvc zr9Qu*o3pqi<)ELV<+qb#gGq3Q`VtZR)tX`q6)Vk>8fM7$m~g0DKDK&5EA^jb?D53H z?Aqk}ELlBkLYqQBIoC|Ux%7QR9gPTyC`$L=)3%RYA&L&xc4C#spTNr>> z^D2M+6}H?a)}cxy-gGQYcp0o=?Qo|BZ<&pv&*Cy8s%^UFgCWxq2CaZbhJ$hE`-X9T z=Nv18=0z%U!RqvO!N20m{G`6G3>&hs2AESWT84&mn%@yqQk}Q<$VjeAUaTl*9396{A{%0Nk`VS5M+E!D0N>*9|1I%e}P{FdNZM_ z{7%i9dAO`@Up=zp{p`l}H(vhFnZ-FAa#g)byZm7c4ryB`ktkTbS|0PdY))OK?5W1| z2P-&IP7QZcZnTMkTq;jFBlk)4eS`Fy1zR*F;H&OPQ*rkvZAoBeVr4D)90Bj-iC_`LP$=Vf#%-pps6=3&LI0Kh9ThWnLv@58awLx+*-n@6| z?b0|+)A;$fu8ERh$$|aKlS{E!f2&d+G&ly&0x9fz(rQxMj^=3>qa_M*d~Ihg$M}wd zt%tp49qF!tGvZ(|)EXD8@$d!5&X(UeS6fo8;m_2xk(jU$O35xEas|7>F_HdeYEdd& zF@N-mFFr9%e0@XYkoUFgM-1th6@8lW={4g*%xmSQaMUE z9%4a`nNyZ~v1d1v1I1sPk_h?gpXTCZhU9?Ln4l~r(#4FNcu*RZ_*@_5#~@27>pg(R zL}{NTr%)R(=#Sg|zN@7^W{TO@ddr+JDCHH_hp!2%39Bn8clO`F0n(LSO1=E|Xgy5J z!AfBRD9V;T{Lwq?MLKji_ep~`B_ReNyIPg^N}+$>i4OXyvW{b329V_bz&ET0akcgb z!_@6LMpV6y+;J3R`^+DtE+->QNORzTm<4^B_7URgH7fphn@Ax(S+DUh{*eG9!eqC9# zhWZJ@_AE;6%5?isfv4Xx}xz4tFJY8R+vUwe# z{Ru*bkU`mOjJJp{sEqkF{09_9J+>|M=yHN(OG~<3a~3J5uCOWLkxx{!pW4%D3s=2W z>+=;|shXIPMRd`)o^6_2sysM7CoX$KJVX1@=y{JG^*b;V;l?eqRV}Rdu;!`F(Kn}0 zJyM}8wTe&P`}V8y^&coIGEj$eaK`{3PoyxlQae@su1IcoCag9)Xfm%4Zyj)*AB(lLgw9moKZSg5ch z_GYbu)&4Cfr_-Bc`c_nfT1Im>mVM~L{!dGXIy2AW)jjTuYRnc7Uf+Lf-e%0}aXzc% zSDvDO_f{K!wrGjQd74LeeipGZJK=fRX=xe?^&$S6w9ojRXYid>ABtl&$~PNq+YmZ3 zOigde5E3<|2K22kgOZRJnc;8lyLc)=Ei~~xU5RE-|TJZIqFRNwLs=P50Wyq^A9{3o1$jnJgQfyv<1PeA0Y3Y zv5Q55|K0tqVc+5zChAE7&`79*%-34(m_x6$D`OhI;9^+Ph|W4 zQl1!u%U5+g7OEF#mXXE6U7URRf%c(bE)Y>a5P zv-}+m*eP`EHwLf$MAIt>b_UHMR>-l&ch!mftXCz27;XlqTPG1^MOkjEGGBT|Q*ADwldfn&3BzUr1u zJMZJTt|riaC%=GsDJNvMEh#X^*pN9!m6NpzFZ|^O_9?BB@bTmST!lod`dPJT#HCu# zlU0}Vy-p^M;>Vg-tkP4gs>K1?Fg9=8!;}tYhl$Sc%gWJD3eZxVPtw(mYm%xiM^VtZ zKFG6yFrGS_)_U0zL*d-w5IJrzA?86)$J>Ud3-|_w*aZ>cyd^k^G zw^rEAV(J%5>^)^oEU18vUK=fOM5MSKE-IJEchjyaCxXBhTKr&+Nqj&NF0ii7$`$&V z4*!l)HSe#A2c#Lf1H#4sey!PcF2zCga4#zm0?D^ndkvxWAP_N8IqS_RmcHW*sgnpp z0HI>2QH2s>Jn6byI+XQSES6*#C&2|}B9nJ|FLtGVeM(rs+{5h4VVxDoBCAahsN?9C z#Zu#ygPq%1=7D*^O04mK|jEhe2hIhukqsg8^6kF>6_?0S_5<=UzOoLyJh~KpxaH9Nt1j<|=8M3+|Ug{i*=oYnI8t7O9%CIRPG*Lt1 znM|EUaUPVSXOBnzLGe~dM_i@xFuKFnA-pK@ee&p%Xj&TRxyEQ*iyPC=79y|m+>aPK zDGT=H>!ldt7hLmTKgWeT+njw3>k!0k+2fjdK6@mG`MyHF0ycP+_?vH3 z7UkdMfTTDMZT0Nio`vDjKv6Pa*(T`9h61dst{@|EC^B(Q%K3}jlX)8&>q9PT$Iq0 zfRAUx#ll)l#-%_0T|&DYUND-|PhCm2H)MfLVLocI!2=L2xN#)jcs(^R_qONUa(Ok! z8orx5{-LGGF?9)bb&!@xLs0WyyQZw*D+y%52>$Wn9A5E{tVv%GhSS$rF1*I%KB?bkaFAP|gmbIOncE)!E>?0 z1`0h_VGPkGLHUL}Nyvd|N}ikJ92EIQ*L%Wr1o-S0JPJalj;#Sywq6Ene!$-aG*3QQ z^Dv?iJMGueZYWxW%1hq}P?8lYLOx5aUqIE#ROTsh?U=)Jqk#UetY}1GH0r&IZGA5^ z@|dZpsZXE6!pHQp5wo?=3Nww2u0^sfG-g#eHk(NLflVu}7%8l6`ny^`S&C?X z2oCbAo%6f#_-LK&2g~NT1e?%2s?csN3AEm@*7A(x`}h!7Z-%8afiW1vkVk2esDICs z4w((Dnp@{wbA(`)jW}GTlnm?eHJZ~KF}JrUIqW@vOzZRTmbhGZZ`tc}mTM(S0jzrT zOgvom%=sX`lB}O?@2+I;h+j#l%hp>3` z-U>+o*etZUZ$e{xrUoop?V=brVeyfFiipur+Kv4t*;9`>;;=UA1s9`bQd%HLi?l^t zRJKLT-IQ)F=CIpqSP6M6et#Y8Lt6={9cl%HZRm`gn?=eKZYuM>E! zMRweZKj)2ZP@DfZ_phXcXqi{i{jhl0w8D0uAeesAJyuw8j9kLq_|u)D*%vrV%EffW zwb<>PrtwOh|L`Oy(*H?TO~Ux50|ic4{872c83Tfsri-jbwYp@gMPH6D_Cdv?{30m( zj?wDq&NF)g=FF5MkAAhWXjH2f#1q9*qwL5B<<5lxHqRdafxcFB?y;PZDN&uhaXV#{ zj%)Ram+6H>m|agDT<2dOl6oPMAxEguXX_W+Ywy8u(#cuKf+g37GDsl*9Uz)WZHQT+ zoV@{k3@v*eY)}Zl!z;&~*LnDZeT~Z{mxt7!J~{cK>BT0Z@Yhq}sf4*v=^WawZDBF1 zB*#;_!4bB!)Vsj?IXkvTi)8zuKbkqTyEQKfw(!<2-Z>Q-6nI;)0*s8xNY~c=#Zh7D3?a^9M25&ecEWlWf0uU|V-@%IzQT?Q zadF6souZ>?ct#h?f*}tYcw!Dbd5>F^pgR-gaiYQTrkS6)d4!8RPt!ayY_WnsoTu)e zATyZGVlWg7>q0Nz7`wey*rf#n)I9Nt-tST#Nl8z4j3}hFS!E$W+Y&{|QH<60{gUY( zYeypasQRSV)Q1%HO$l8u{TU+-4$_dhc&RZfsRR>ur4JGMfr(W@o0h!+K6yx`vQQHJ z^>fI{gID}Z-+(8ua_?%rips(G5P!dHS=yCj8RBb0yLQ2fHmhP>FUJi(LC2AdSl~`{ z%QJY_+sV-BLfr}&;K|3Sp+$cqT>QmkT&|!NR1m}xA}ovyMF^FJLapc}k-$CMsnyXF zF|aZGR@gZ06Rg#ba+bFPZ;S9)b$ z9bs!U=?a~MvcKZvI&0F~GAg7j-7Na;N&I6?34TB-2N31nUqX?9)MdZ_TFWObC6V8o zlt(>=lM%gs{$maAY5qJ&>`aIVi@c&I>$`%NtFSF{m7m%t9gYxf!%iFs`*RKwUY?n|FD{p*BwlJGExQ<0vsp^it46 z{Z-I!`A)CpFd|NCQzf1(uSDrHzky)6>{pULHjwgg6>H$PbHMbx25NdlK>T*gFoFMvZ! zD1P@D|7maNw$&f7=VCz%%LV<5d?T__U96QI>e|J#MqDnUS(UW+RK9pg9Qw@2C-d{0 zV0GG%lZd#;B(so7-U=OeZjF-6bs5v?iTnB-?fP8Fk=I%8M++BHQhD0@yB6&%{@E+& z*l6?4`Knc&IFiEIjVPD_({=q*0p8hq_UGe;aa$YziLDUZF|ByP@rK?*1eLW=B5#tK z>n$=92657;%GvO>4ledVqocV=*wbPW|LK}4-)S#udZb5#bt(O{SL#=KAYS`ob#VU8=|Xn0?~CzRtiF)qqZDS8NP zdLtUYTA>KJwMgufSEio2*tBR5?tkU5!CS6~fvnVn-G$w+kWS*$re5%ja?vGvh5ye2 zNp8+LyEJ3ZnUVna8Cf=(5)yFLjQLwv^{fteW15s*+8a~jiVmIk8L^n_V2Xf3li)}j zP5lbx`CCcl$ddzgFlZ}1I8`zlTM$O;sAG~%ouG3VywIy@S$Z(+$B}4eZjOyThj?;z zx9Y2#u=jAE4b}3BbdkM#&!D1#1uy#*T%9>$z!W6-(do^g(O8JlXLdmLqpIVR%apXk zf=pLc^G=$KJRN;+m2Ky!BVo)3-bgzr_$YZ0v@p3(<_vQ4q~|7Y#SfoHD$`VQ2C8yC zXu+<0qlIzvtCBLC=qJ)4s`W@)nkf%PC89sHh2hOejKw0G7M2*#xZ~}DQ@^mU`A~oM zUBz%hkac2JQ;u@^0`>Ioe3&ROC#OoMMPwe{=BAx^Uk-UKDiyz~Mai$ALd6{TJ}0seGg2%(;_>RG^~`*s z3f|USsNPeVt*G5tAQO6<5bEp1#6)UJOQoO*K=p-uCfZ>AhPkCYY~|TP100o`4$`!+ z*VbwhG=1$APUK?t6Ti9cgq^lf_o%SBy(i5{2iC%TrKi^U&T5y$wnu)uP;|0cEDlVY zeXY@_E;<1m^!Pr7eDn`D3_?7G29fNi9(8q9WC;>{XWBDUijD|YCN&HqF$R|V52T*u z1g398I}F3mmXwo^oAJT?F;ZAMICoAHc?+4U6>hsy95gMTGixoO;rGuw_cAD%Q9HA5 zLIR2ox-nf@mKZhV@za_(FT>;`Tn$6t{K99bBLU1qX=MC(3NDi`B}yQSa~pWGC=7jx zNf_xSBrA-&YpO^w5Y+-YvOip>tYe+dp!oiLJHL)p^OEei{pF6(5M$K(2VP7c!$>>A zw0)2G+e5=@ObHkD^3hixZr|JrA_tB4=-q`SY5y9uOFR|kUbZoSmIPX8L)ESQ=oV=n zy8+I_$_{kIEe@EwR5c?5`2-}^6UzUhA`7gFOqhpERsV4_#l>Ooq)%{B8{dDElQYN& z!a_p6j@hU**vxFhbE*#MK1F3;gGxEeZQX1>MI7n7?w<9^n)!v~C*d!@4sAY??!Z@i z!Ps@?TK41dTwTbr1+MwWqw zbuKC+iOcZ2rGVz@HNS&qUA)gDDL?Us1HVb}ln0FUM`$*xij(RltFIfSDmjY-1f3A3b4f~tFW%ydZ?*=9EKIkTyg$NXMj$Q9>nIo!_dnI>wi$CgGopLP?Pp4&Ns5626vej-PNkLrt+A}+z(TVEC z_Xepyhwj8sxA8~}nR-HiuM(|=&*E7=8o73w8KZ-3JDU|f>@;bi=O|c3!g@IZ2p_|2 zLH@twIXxgJ7kkbYz1w5*0E_t7p!3~@D|{bp7vo->p>oVKN$jd`dPr?7ZbXU7fY>L^_}kci&RP>95=U~y;V zHD>G^uY^JNs@*A*j<=AYmnGqaV{h$}FIY`>>@hPAhaO^XA~TXg}Pra@?}UnN!?EWwg6JI`A9)Ttu- zDxGI$v^_3aRIoL%S$SpCxM9(OzF%quJ=Q7T{$T-2(Y`nbx63KHq0ZC4VaN7B;s93- zRWX}7%2c;rFI~ql`~AYqIiDacbPWx1vqw7;y^y}0oXM-8?wlVIhk6>hwxRb(<$|e< z)GqhzUFr5QEK5I%Kv0un0~rT0gBcdU_LkqN|1|;GzX0%>S&Gd3md3HPi@YubxASdiQLy{{M66z+ zk&sbo>3(*IRl!B1QM9)&=|a_!wrS*h_Q6=$&C8lDk+j#~C`FkN*uYQ6O-E*J2= z(&bwY!3x2;r!0dfI56Y=yFWMUudDIG$l8+9qkU%<1ncoT!!dQJj39oq9Fp7*)7(&a znK0YDC(r!B2$hce*J|o-X5xdtwY3aF30v#$#Ued#*cI%y1WaqTvq|<}GwqpTTa3s* zhgIA1zOj14`Sokc{+FqP5(BxjbJi1Jkwde+5>3V=*s&?&FgoiU;W_S#5zt=fJs5Np zY^;q$=2Mi6Wy({vsqj%=jjUNW5^7CXj(c`uC>q3|mi3RK%)lTFfw@79Ff^^MNdAY0 zGIzv+(?G9uTCr?}$O(@pS*Z?E7)(d*?{-$EL>3plu?PtdLsajAAwc;7<_2_%1FS2l zC7yqL*=x+jw`ZU8KLi;d?H4pDQL)cy{D}WkU*>BQmcRWn=Gp*D4%RC!1eQeg*RLr! zwPo;7P#2{>xNzTEh%A@4S8LYV*U0qx6>CWrup#6%r{0kAyIx5z!ol(KWGf9mksdMv!OJd_$vCqMEjlHT=jK6`j5u-&5J9D2O zrku|wo2#(`;66ufXYOi$SQ=uhy{l6nKL0)E^z~1lX88!)fu6%!A!j2G*LHBd*$x&~uiW+P~9h}bsYwG2dw=ZBUM00aQ1^Zoo zX9C}Ov*dNW<*$E*%SU&*O>+oG3hisY23%M3=m?-aCj!sA0K(;akB z2BS4Kc4%K!hyD|Q=OJ^5*Q12XTNv`>K2A}J?N`3rqP@z$uW#{p^Aws_91Yla`Srj7k_ksJnYn^w8k+BovOn&b87i>2-@O z)|W@Uj#UDSwJrrpjO_8cmN39lXScX4;i4xqAX#SqO@ZO0HC{W~i)h<=$z_Ma#A}*e z+MTAaB{m4GEL1%I$A!K%Cnl*EGOpFt=80Mg0RIdIxe@->P8J2hxl$Do#@R)MIRdEU ziiw6=@kKAa4^l}^)D;DHYxqkz1vyh$Y@4CIvekOT7yA~WzAltWh(IjRKL#`8ZF~BE z+(V71tBO9q{AAuI%Qzrp~ zq;_2@Z?f1-dQ4b(z4HD)lFmA+itp>gm+tQF2I-UrX%Mb}l$3NzBQc89p3uLw zU7D~u=OU|F|Mz*=@X-ZF?b9uU8lHg5WuJV);zC>bz{;Yl!^?RLxp(yDUrp_3^JQ-*@X9AULIb zvCMD}SRvD7HHcIiDE=ch6D+OSfgfQPh4I|JK)B!19@n!UdsZm%PzZvj$w~-S+Gwvw zxxh2;(@^dc3YhXU(Ipf=3&2{l1SxwbFcH@DJ+rySNw*(l&HWyK0%V=%WSs#ZhU@PV z3o@(_iR%v%A&yT2jV{W1} zl4Qi3@6Gamd#cO?rTN%Y?$Jf@X{-TG$kIJRcjX%s%w~kNwPPR0yE8Jnt^~zV*AYy< zj$>*-DmDGBTCii$G8$c^up8Xd(0j!Qh(gct-o?*E*EdzwjPhpDcHkGZ4M;CUr(C^d zL5$ZF@r6dhT4rY{bR%z*TWM?Z8FdHRHU1WHA-Or1p{DG#4Ce9ex;}aqwQU8))Jbnz zcE$-jD$DSt5YWaFcfqm_b-@*z&j6mx4gMNYVGtde(=;ed16ob4QQK>@;P3GnAtrSN z-PZVaEbr+z1@p2yM5>*{-HX_tMrg2QVeF6QlJbD@m`eWF2iiXpxBT#IWd8k9gv$EE zY`3|M%y7Z9Scx8G>2^Qtit2%4vGkLI19Xe7mn7!Q89C&sV4zOY>8K{bUP|cAGT4W% zddpm`rQ!EPiTuk}-*7%+nPkV%VfO`7`Q|F|r*WBAkugmf|D=cq#>*2b*!j};W*M(h zonUu{#U4yLO#2-^N)xR*o;Vs9xbvK-l*c}SLVxU#LC&PRs&?FwY7bz?alp-uxb%2{ zcn)AfFedm0?D45He{`=|S&I1wsg^D^x1_vLhW zgF=}ykNbI{R<+nHhkh~eh;_X510O1ced8K7ya`bjF&1qm!=!u}{P`!IyHR>n4|3`I z_*The+&(!m`1e2yz0+R}kzmLMc@4)*j&Q`lW$8MHW3Vn6_kOFAT$TCdUX2{;ALvq- zbBawY`gb{sP>oe~7uWWrBq+A*O>7eEKisL!zhT0M0E{*I_k0QiyQ*Jm$F5Hi_!?R? zTo2xDWPLUBo42P{5EpQ(EPMPs=Ju!-fccgZ_WHz!_>CeBSZ8LmGZeu` zg>Qs&j}1X!c#zlLd=L0u4e9G*8aeyUng8Vx2j5Ww`SGkHPIuLsA->S0`jGkr30NQ; zY*Yuf`D~2*5LT|u&&rjcIYi3Yc8(lkwS|m1aoVAIX~J?a&BN8y$>MLJ!%xTw7Z|3` ziE#phm-w_V zY-3VO6~mHFw1W#J5naJA_A+V$Anr{yy=n}%!sgE2YqDOREL)V+x4O*5IvhddP6U-sE_6DEnWgATssV9Y*%v3-!D zVs41|GnjY|GuOS#r+T1yy5M}Ry}6Yu3;@5t(AED^!#B2_p||a)zIQXF;vxT1Rg!5T z7u7Gbojp`9>r@*uR1ern#kiuJ{DEK=*I=%nN&FlI(gpnc<}>HvO9WY~emST<1EZAL zcVnwhs{e~uf)TB}WC+G`eAI9ph-J>?h#{=k_gMKI?F|$ep67?F^Cdru9xXC2HCBX} zmJQqaaB5ibxR9U+NlxSlbY;3SPIIZvR3w47j%Ni~nZzq1>f>(L?U=MuJ`NX1`148t zsZN;tNM&NLB7w=QI^EjZYSfv;jQma&a&AyH%OFxU)~ebfYa3bmYA0$1+6~EwxBChT zGJ~1hqR?lbG7>3R{PXj$=;w#G(<8A-49ee185gD0;xMpYF68F7%Vt`6I!U1Y+i}rd z8r6r)v>lbuKvx5BKmc~XqIb$&&IkeR9=k*+Oc{P6Cf)+AEOBvIiwkE!k=Umr2-u_f zvp-_h-T*m0DP&&xN*q#%)V14_ve9$xerpJwL9E}-2cIXJomV_hv#gcr5oPd9Y742P zCgu)`C7O{|_VbvC+89MYrQ!%*wDs<`$+Fg(A4mFac*N&$u_eAv#3 zHq`xxvbJZ#8YPs1ZTo}yhD|7$EKzhe^Pz)wvrHob;Dj*-w)~8$x--&c87T}7o=Hb5 z(U{Ns4L#25gFuhSLF|T`0H2Na8r6Y zzr#j@&HFsq1~)TBI)*>?7wBJTFHcGHT<{0T85j6tPMj+@*%2)WXb{$_?1J-#X0$vn z*_b6f$^X0v*F>16Nu46Sm5crPSDD1wue)}w+9B_}$NC><$Ab)XDZS&sWsCpCT{4m) zy3b7A?MyOswPR?rrku^atxQ{-$VO7M7;29#$P{7DVriU=+jclo=6ekve3<{VCzk)> z*cfWNc@sJCW!&j_ksr)}o~~B6|GD+O>%bbRr4H`8zua}YKG1p!0?x3&Oxz3n{9VrJ zJ>~y0U*NS5pn%Cy{HXqDNnJz3fw~FtC@L^^*q8WTJVLtyfd-z^Ymdg~u9s>6xWjsd z;q17hRVtn;LHhn-eJ-9l5x0`OQQEG}6S3eA`XpD0S@_^+IiK(%@BVa>@Jvz^Vuo88 zV^V@*E;L={^BH3?p;pot8-uvT&;QYGRU63GXv-V}&2!XA+W-0L&tZmyDJe0B_7?@(`Y>*ZeztCM-6lJE%{x+tk**X>}D$kQ>J z&fIo=Q78)Df}htOB*A%i_OnicZ%ebuWI`C5ww~tie-67xzglo{%B<+h_CM;ge zLy?K3-3_b~MTljkU5c!j>5ML$V?3Ri&Fe*jfHrSJ8L7P!A?hx=CcESv%r_(9fQLE5 zurk43_6f?9e)Zehu$jB#(WPVEW5I|Ot|J)O{Ffe*JHbC)tnZLnFdVA)ij>lAx0KS- zI}al0#^hCw0UlMsPbnuz*cu+wc}M!~ zeYXF5Ju}PPqoZ$f<0cJn?|V94dv|J9Tk*-XcxfR06^DS`au>M~)~8F3#896j`a zMb;FSWJ<$+Gq?WKHJr8Ttr8?avkB9b5}t(g0x>Y1yKf2BRIWTWTt9v&xRgHjY#>la z_K==s%Op;uB)R+dER-c#SC4U*){Y=el_^C-x%ccoBwGJn#ey;riW;d`eb092PetFA z)BOG50n?fD(k5D>&xy804QX_dp!m#ygmOdjjHm6LI$IB0EX8G5*6GOc>eTALU5R-)H)Ror~cgQWqM zEvGsDkj(VEOJD|JCPy5F1-2#vnh?)yj(;3ZD2I#R0w)H%fh(?{5HlUh*Qu4Jaa87V z*_+gr#W_ z-hx<3J-_{1$I3(E5Ni6*`C>gfSFK!HdblAE8F3%K069wnKa8A9KX~W;ijXFAHX*3G zoWlkyh9OeLsvY(e7U=9)oSvu*!mZ|S?oAb@%GwnvX39 zy+5}Yb#^nxUder8OIc*U5Z)9STnLr^g5+OBY*-V%1AA6cK3cdY>jI-g+1u~QFGdz zecGMf{9akPMg*J_o$nR?w=u+&+Xu#dZ`W5}mVl^{RL(+BC$?Z``aib;3MhUE0nBwl zw@A*eiI*4Yum7kf#583=AxzDWA25*lPOv$%0(vso3BkL~BUo&Y0Cq|ZdN8`ni{;k} zmt!`ksq}?&yzphYf+k%<4#Ir$1wMlwIaD*tY|q-7Cy~N`1{YBo8$VsqkLLvltUs7w zGSh393hkoZ(`DNK!Fc@pLp}u9f3#}5uwd2{YWOtQ<}!;pc|!lK+URMIH;9^`k2JqZ zMgPRSk9|be&)Ah#ssCrVgKL{0ZH9cBy4Jx|Jc$<1Te5iRGW=_0CZ69;Bq$8|vPsjs zXi_9obv2`_Q3agt|%svAwTWunRsL3ppdetmQZr5>0`rMv zbWlnCsf)i*mSXvYU{*b*NbtwY{H_URI&W;?u}3&C7RGMCU@iDNZK~HrZGL$oG*owD zq68nZeh~1oUU}@30;U;|ttWG>RLxTep$PoAa5Pi8v|kC+{rhZgP`5J-iX>UTy%{=C zz?&yJXd%5y$HmG2(j5GNRyygq?mCaq)r1H7ksNNE-#X`IM=u?<+KH5EIx`ikU}&!* z!Q$Yu{IZnodkrnFYtNchGnbOsQfqCP?SP|`L>+g%;NHhgZ+PM<7z)$Vizg*=$DKu8jiy{Xvh5}^X{iIbsjf4 zdozt-nh-2pfCkQhl6TB7%tg+eNy5c8VwMv=ULP+nil-ixpa{Ihh=xiWUwOQviZ6I| z!Afzx`cKVE=|pI8?zQ&JS6eR7;`sNQFXLwr*19Gd&vV)!w<<`2G$zq%M&`bTdl&ZHi{C&o+^DO3M){61L-;d{&6#La>Bp>Y|BZ!BX}F=9CT} z2#10t=Y0=(h&zLFHW%?Vk1z2u*JpuF!=0F%4`W zB;ZgAmiZ_ffphWf&o^ugBu&<`Aqmt6%3OP~P&;Vf0m}uh@j5?|@?ni+O=Lej#fk%A zzk9*k-VENHiCT7@6om1wznt?pE#1PZt>-S4AcR5KxF^M5XL7|6P6upsY9afNj}Y0Oq{LQ;i7DEgGsq^J|+7atYzdoG>wG}rBgA#cTKYL3_e z+c|ab2QA6);GYa=@jnw`STr&h7J{6&nr+&)W`%#%a`TDwR3Z+fX}I>9##j0>@v;)* zjo_jq9!FP>a3?Cd+4auA?Dh%Qm;x{$!AM;5?(GaH)3Se8q&t5@kOk^V&m1ee^bOwC zOh$|JHc)31rg7pJv?I=w+m<>~*KpK8VJgjf7kS|h*T_K}Zm_Y}0V=)YF1;{$5i3nA z`Ew=E`-ODSsk<;@GM zP(e6Rgb`pF@I@%1=Nc~ra9u+Lxjx*L>mbS9laQ#1lxLCJe8yy>bV}5RfJIbT$}}3QNTvu3oS|lyG$dQ z<@k?5O7)0aVRsZBWcsitC#1 z+$-32lfDzsfKZO)pRjVEFQriazYWkENaOZ#!R~%Vurvu1Y0h{&k-Feu>}w zC~9LwhQ&B{`a}eJXgElJ5eJ#;p7~191Yr=U-+j6EYX5u|Q zik^P|L-VCESzVl3MQ3C~)NMGWKGZ|&HS>uRzB639Sl@AG(oSHVJJ?)19vZ5^n>2-6 zz79uR9|L%){D{$B{WNCFt+Na}R^9XUg#S)ZTgLeJhTeDp-xf_nx8ckqX}G#Bk7@eH zw7#$%qggVV;$VYMaQcRF`wwnsx8lKhRx*5KGkr)NWA%(xbl?h+!0E-=!MN! z*it@K&e`hNYT_*W5`zW;xF4+nDzr7uIF0tb-x{bLD#3&+e&c~%BekBxyb~+7Ngik& zMVYCXJ@fuPOP3b{Ct5itKZ#hKWK5M6pTP{i}Tw=1Wx2SMe|Ilw%ch zG`;}UXl*^Fx-1KGX&_}LfK@r`yU1i+KzKFx9&0L2uv9V+kSY+-py$@7n6>@7#6 zP(oQQ0$okN*6SiwWoltt{1)iEfZdY$MKdh0h5*-0SJ;*q%?(;+qN!?^;AEd`>cYd| zzaL%jEPv!IaN8F#8-ZgZ!jQ1w{rmlAV+nvhR*^5^I!ceCfJ)Qla_3qU5k-F*PvWRh zJglxCB{N%$%EPJurlubK@jx`vu@%kr)&4Al19^3|AP4BO48y66zzr-ll0Qs#!Ipv; zzS(hygt)(6+K1hAynEZJrHD+Ow_^2A&Eu3c^WT4Pt+f~p?s5a99baN|vusBcP=Lzs zpY7cUk}W7M1`Y3WDrQjKIvS<0^FVXmU_4#(E#rVfrNhvFGo)`OE{)%@c!TC2P&W(S zlXrXa5|QtLhiT9Aexh#TUQmXpQ9buhEeX0-{JBFx{m|^J7AO&tl5z74rbneQUK04{ zi-UAMJ^6S#3BC9HFb=x!02cFv=2~6U`XtwF1GO| zURmpGR^;f}r3-)cBJU>XmUh8%36>O7ufk2I53-~-C4X%w$jHqG@<)a22c#v26iraZVZY(jB3eCO&GRN*}!7ip@YNMVvguUJb-8V(??8VVDJV-0UBl-zA z#;`C+O$dgpFwu^Ha=GJ27}pO=&E^zN@Ud}Yy(tYEVfZBQaUIC%^+u~ zRWH6`#GR7kKk)${;OW!iCf!+aFhaJzS3o1w`zy?fvSXmOEwhU1-VfSz_mw<%jsccm*jih;d?cz#zm2E0>_O0Q4t2(=(JT7W|Ts7vt_B83YXW!d7A9v&rh-v`h>r~thYN;-ps%s z$#@quCY#y<6t&YQ3^<+)t_oQ{3D!q<~3o0z?{EVO$2{ce(+e4FTTI>%Q)ZTK_u^&w+i6T#W6S*#;Z#?L(Fp7Clh}`O4tKxY7Qf(GtSN%?&nf)&h_~ zDI};AauWr8ga6ty=DJN@*R0~N_Y+J&DzvAT9Um0|Y>d*t|JzTGj*o9_0Yiy8Mn=Du zmkoG!|IOG`R8-cw0^s!DsDZjwNS)T=m_;l}HU5vDs4{1?KSxOea0P#?6yE9nlF0bc zdUmF6Dq4bryCt{0amzJsvf312S{`1$Z{75rj1|HUg%JOBgua*I|Dpv)i*~dXgzAJZ z)2LTg*~n%7(U@Y9%sB%cP=GNT|NH~;!?0fjK&u*tm(>VHguQz3iR4B9ZHR1E>nsZa z-7rWikIZee7zQux69rDz;KQM=#ptgHMBs`s`OPIhd&yiToN* zKf60%-pnLf5F>C9-2^-f-5sAw?RQZcyg26eAIupAty&e-cn|{p&DNt7^QE(2ZOk<- zDkP>JvkO1L3p-Qa94$m`toNE6=pmU627v_?B+=m4U(`BMYWgB75O?S`(v?@Y561MT zl6-)XEkxLVpr+~mGpA8D$Nfp>&M+#705#8f5W;DX)@B^^KBc>q$@n-EJ{dKi=e%d) z5K)w*Bw(gW;}3A{gS+;Dz;iCO#?Kw4?5pwPE$db;ZJX^>l56>anNk>AoXIG1ge1IT zaFjE2?(>cS3(B!Gfu=BNB3~_AMOs^9Y=p-uqI(l$(#lO0U!bNv8b#z2m91ktjG>zp z(rwtbu+1%2@4@c`LzZHb*`RGXc#^LJ^7Rg|h-+`AV?P1h;HS$xkB~H6oYWeyxci)j z=mZ;N-M4EkFOYD*qnkxKT0n~+7s-ALCka~|#g_JUOZ;pIHFy(K?dD2<1t+AhI2wCd zC**A>?Bg=6-Yy|E911@B?@`wz#P=j$45WK%?f58=;Eio8P&;^b$~-Bv~g} z%Eug-T?7YfkY%Cnba=QQ7Z@4IU^{5rfyts2^KSd*I0&c^#)0>97%`qM$A&Vw&BkNU zt$b_b{bSea9;blGTu%HQ$D35PAwq0hQH5MI*cceLuDA`gM!Rwm9~TC(4RFKZbhg$V z0K?eYO&NY4UuFRR1Oa6V#$cFg302bjHkjluSGOXZkBY)lesOeB-x`aCt+Zaw{<~_0 zhCLUb38YOzp+c24ft%(c8=}N@*L2~lqyt48GSTFSmBjBz?k9+hw?|Uj$G3s+HK|3b z0XpG@>N=$?IP|mXYUAe~9@Ipkn0}y%c9YvEyUmZ zq#5b->xB22(d!}54>}Uha&FuHr^R!8J?>mTTBy4N?Qx&LhlYRn+12#>e;$0#yY;a1 z`Op8ESXdygKDMt$ar&&I{lEMaoTG%EKHe?wiib(u1xa+tOFRG?q7Qq8_EOk*)^4AE zdYr&U6*?V|XY~{0S<#&##3h2)4NEghMs;&jX8bd$wUV?FG7TNB0SxS#40E_m6C37;eQg&~eqU2@Iqj1)7l3kjaOfJr;| zog5LH<9`>ldFQ~`cC^WJAIZ$bC%MZ-+@oe|f8w@c{JmU5$NMV6)<=GP&q}+ok-jX~g!d0;5Knrq``b zs~le=rC09sicS*Wz0CA`h44%78>)pACyEAr1o}QNylyXmpkN`;&dci4C)vX*{WEO= z$wmU_C3RPw@GhZl>*gEXkP??&Mxe^N=G-$~V^qtrlgd`fUr zOmITzqcY7jV@y@O`3FT}{M9Ezf40QNl&TfH9DJ>59*R?k4ljG!Ev4awWb2IbqLIKc zqO;R^7nxE4`{f-AI$GMUh|tXbeJy^Y&;q2#`0{^}^v5c_PV3g7SP-ENMlPj)^r9fmW5Oyn=y58r=+)uV@ zeBE-;;Z3BDVhH{bG>X5s6RX}WS5qIkNJiAljzQ_}H^P=a)X7j}_RT&=DwF6oHUOR% zOXnvLZ#E^xDPA3|Gjpsa&D=;@qbnRFttCM3K{C2t*}dP^$RBw*+|=A91_etYkpype8R(a8DjXq+DhUrLF&3Rz_H)=M?pS`@Imi3a_OdKz%oxu? z7z!5Lil~%=2qSo%GS?%4@zPi(}O;Y;$F$%{<5DM z$b1u@0xoyV6(k_J*?oPVZwow6HNZq3s~+_Le@CLme-3jEhbaZo`42NFeDAXna;ump zA=HOzd(V`bkoTm<5qzdON)>Fya>5Ayyro$)99+DtNmD?KHrn{mWlaei^IyPQ=Nmus zr^)>cXILK?&~HErs-|2&ssG4x)lk-N`&DZ=oP`U^LQwlrsilnhD-+6IzF%YH%%SxF zYfL4IKC{zJnXLK_y^d{cc1ozS*S^i0Znw(0Xa}0#ivDu8ULcfhKmq@9;!=8SGZFcnp+8m# zg;SR4%IP+GSkQg0kS)Kh{y(bB3FtMdw#g{z768Fdwp;{UOhT=XiR*#%6O3AlziK7b zLYHV(2_oQ}&PUrc{V#V2@MBNp*9ZN&u0sKNL|0CaT0_crXYeTqI0}45LNNzKMwoRr zx&n`j?1#aBsBl||q>`et(?YDgd{u6=u`fnMiVyx%_%yw}owDbp(&;!8O2!qRmj!MM ze*ot*D9982TZy1-XfN8#^{r)c!2nLd{=cE;c;?3hJK4lnX1tn@lKJ)0EuVys64u7^DIg(!KlFYhKaBF<@h?hlFAv~~|L@?O z^NP-gin~dwXAN?pFAxxEmH6*JpDjA@L>@(1v(uIK|E=~It7jNzqFA!Qt*0Gi;0pr* zMz7aKzy2w8xdzUHz_tEvKljD@-z(VK+REVMOkMV98f^#SU0?!mS7R~p@5^t;hulzI z{0c=@5~glT2MUMQVn>1EDHz0N95LQ$+54Afda?cJl_%V`eyy{87KI7297bH+sq>y| zb6qFoX=|uL@da&T5iDB#XOq;CH17?X(e}gq-hX!Al&gvm=-pC`Pjq|VpKzrU;#^*G}W zfB2Z5LnoZqL2HnNf2*#Bf*_W%1Rap!*I_nz{G&go;r&1l5>j#YQi!yb$I%!w58D|MrJ^HY^f#OpRpIY#K)Uoqj<<>`Yr|=NI;LTnL^mt(4zYH-G;z)VG$k)TKX-~ zvFx{6^>1y`5uei*gIW-Z!$7r8ZIXRXEIt_5$m4_sno3^H5i#S_p)2GBs^wNmq&4Xs znE=mN<5+>ulz%S0vc3fe(RGf_Gy$KX4_>8a&z7JB;R+fJk{6=RWT3}2n1pM?Ny$${ zWv`!*#8S>1yG|r&w?FvU?koFN$@ZPQ#=&EPb?1<%)j&P5%RDi`g(pW>p_YCz3>hS^ z0Kw53<76A*UpF5f4mtcf%Vf%?;p}b`_;2$c?|uGR;^s5Rg@dy7$D8Bcs}dNkx8#9F;Uq?jsAaj1 zhlV*}{16*4w$K`tU>KN8ccnPJK&EY2{_-_#biP>>&M%+{fZ4z(q`}eM*k4iqg0)0J zi`ES7zobRw@>caJ$%I)gEQ+0QSDQl2-3Okda>X-W29*^6NiV9R%%~~!!v2x_F&62| z=0tA)L&dI!NIjA<`4oV)CP=O`jc0Nj*SDTu^waw~CQ9e)1A%9SR;AA|KlwwBW6x-> zhv~)2=Dg>z5A?Jg?d0i1j(V6s*wieA7Ks({xDhVJZtm+|csRQkwl)h4v;c(igi7D^ z7*$F0Ww0QjZ7OPtRkKB<*Q%s@FNyE?7iBTEIZR#B=;2DD9Rk2Pzdt==jwkkq)34}K zbsY?jJzdTjO%QQ!nWIs~LJDY&T^|bCX7@t7Q`w-4v841j=Q}FUWtf z(=_AEqZ)m7^884+{-!G5^OXBo?P}BS3XT28?TOU$wqOmo^^#e^R^S@v)eSm$_+8?= zVl0^ojhZj7Rg-)7I&>h%|J(=B@c8YyjUE`npyIm*py)jAVpnPlx}_ntfA13xj1dX! z=kG<}sWYkL%0Xf0q2*}RBt4e9jD9@R8R${7xcXs-h9kesHd8_)Wg4`-%mnQgSu}W0 zno;%Xp4U;teD?gfw|SCXXgV%B`B4(Y%+2j~c)YXomtN&`LXc z+6RolqR^y#CWY#!RI~799GJ8sB$wop&aWH1W0mifgca&=27jxu_ObAK$c*_ggy1nC z(6V?X(u0G*Yob*M0f!2(^me^k8>vyS65HaBFwqXkuKT}Fa&BETYt~6a)F~$ApNNvw zhcGz4em06^>B6vHU>L?!k3~<^RTxHJEAa=?IviV;q*0j+uVxU)s$Ax3&KE4X?p6N_ zu~fRMexRAw)~QsOzD8`SI}9^U1$UZpK19WQ_rpnW*NlXVE{cKm;W zKF}U56$w`&#*+?=!|I$U+WSb@aI9d>aYwUxb-DE}YHGE^XWsGzVece>3C_#J>vSgW z_YN+oje=hwTm}UV9j=H~hiv(EZy3tVf|TCH;mft;%p?V_YG6}p~k45kp_j((&5!+7D!+g$h8?O5}>x%j|^$Z~xX7R_welU!-S zdZvI$xQ@5vr3YOG^GHDG+57NtPI`J*Tm7i zJNAczim=keADRscRb6p!>{*Edq-_R0eQ!_R)qMB3%X@ROO>LId;DLBeWY{~9YA9WU zOWGZMxwUY4X*C*%PQi>F$)F?~O8&u3K_|oNV5I0-WHT;?FvGH1x(TMF<2ajn#Si)A z;vpq(D9;t#Ew=$7=1m_7r5clohows>XcP_}8O?@2P$xpkDU7EL5E*P#)BWRdlj6Lv zG5Vyl@m*g;PQ z=l9;$T4XcJQ>x7vYW|* zQV9CzfGrOTSvjYo#Tr*9ubLsFYDR#997Kg7U%R%Mg&;557=EfKAtnPu)5iRL(zAdH z!oAk20BlWhlAOP2(nqQGh@ED(w7XDH$QWjqDAz=Q7q^J;O_hk&^{$;d2{Ah0UAD+nin>3#tU?O|J+so1oSIr>^k<|#Y6C2(Y1Iz& zO?1urZaaOp_e0nzLv41%45v!%6@Ap8hW{}1aAvIK20u&LNmCIX-;VAgAD5A#>s(O& zxtSAJW}%N2)eZ3IU2`)FTSGRYJ z4U*q=E$Cg|BT70+csF1F-Pa_v^WX&iZ=iK9umJ<4p?beQ)9N|?g$SW7{bf-S7O&va z*c(Itty0++9>y#!RJ}*ju@9Qt*^74b!9_w+y&`PCMHn-42&vFAHH}qor%&L@xvr61#Rgr|x(+}qGQi5H z%T1h=PeA}0LP3F#y5G~v9?84i+EOg%Ik;E{ZQvAtVXVQbIn!JebG=J1@*DfOnJo_f&uWC2bqhdrWw zHW+pjnoDhGW6qeDF8nMX-M6http^v{GJ>->c)FN*^D^fel&NU<2MR|n*yBED%?4uB zi_YYDV}P+Vi1r(LKIFd-qB|4Xoxex3`5N`##CanJ`*#90sFN36k&TPCjNGA`yD|O2 zMyMVU-;xS@oCYQHe2ySWkGGI4Ix8Wozd8XwwGlSa*F;swcG*V_YdF5po`u-P;S{iZ z2p3#<%3JTsVE%lOvuRRq2_~JQttV~1zpL)->K`Hh=tc% zUfWwR&UKBn?p^BH;w`@gAN( zhCX!5R7DDeSI46F@y)Z-@8`Jg4km>x`p96u%vneezpYUts8Hgd+`q zw~gcw*5D{`BsY11$XdtDq+e#l@gc$m`IpS$6F+>6b_RDEop4dcD`U)+qICjZqRELm zB`_<;SVj2tR_hzJv>Jh9Xaj|0cOdv~X9-13^?C#z6{rbFe0iqpW_{;bZ6teqSlyfP z-3)!CiCvx4`m^;H#UZXl_;!8XZL%og*V*aBX)Da~&;*n*g=T9~fo-KF)ml8B0kT@d z8a|XKW+K!`PPSb3?)D#{14EZ-o{!Ji9Kg@R$H|FH$t)>c(CXAbVAKu)jlKd}8tBhY zF4gY*Tq17|s$2u2*UN_AB=DFE#Phfi@p=XE)PHV+8Dl1ILl0pqq8wMV1fF?VQglX+b zB$y)3XqzT>?o>hwtzo7a*QGSgq@up9zrSjB$*5%Z2Va8w>b=%cQ#vo8gL7-G%tz@1 zTkXFzg#Czp3WCA27Th0Hqz6k#x@EEbKn%z9gaXTSRj?DU2dih^1l#zYjnnkGPZxRO zeM^HGh6X>YDeg%6C!K;-pqX;532t>{%cU5;PN;H0(Q__^rWmV%J9>OS{)0@jt~@Pm zJ)!nwn-2w^2UUOfsVCtx6|?FZ|&b31E-IaaGV6{^SnXj zNT-svCI}66sohN*Wtodi>|pSd%;-);Z+BNJ z1w&jcUgpYL0Qi7%qXMm%ficfxrpT_Z@1Xyre=odEFFjy3C`(9!cIX!(d0Y<4b>Em= zv||;1dCdQfeI67IRE{J{JsZv)54*AIAZz~PK8NpOW3t$olcv^AiUecv3+d zS%q=%@`?0tQTfl*Bz`GHHvv`#dY)_tMg`1|xJS3^3WUl+mIRE#xA!OT#Ft#g}= zXS{RhCjswbUojnZ{kG;1T&Nj7308{WZ=Yw7z-Xzf$|5s6=xhwjlB(3!@ZO=9okn0I zEO@Xj4 zXGSB^#qkD!NYxuCloAB0{BE^G8HO`U<`0MBTyB&>;fBZjBl%i*Wp&kL7Y)3Q#aQg2 z#kHM-Ft^Ucltqfc=_$*_3<%-Fu1Su?K1}J8LDoAI4K($mhdL?qzVI?Dw?>W_OE+A; zfn!R}h~=5`CRjCr1Sx;BMUlXdua7vbKlvi8k^@Mdb7FBxO(N2;2`}AcO?Vs4Of)*z zh5Qb22MI3uUU8rGo#d2^G6oMePg}^2n5Hjvdf^1mLn3#axs;dqzsS(Oqc_vhGcR(6 zgVBw86J^^^aDG-EsG34REmH#Dps}Aw5uZG|x7*D9IuNeWjX1Y30J#&*8Mm;mV z9-nWrv7}qX!5bKNxk9k!mW;Cd#nBtUdh)^pwOC^*nbsziq@_~R-T9|pR5u-`PJAHR zu|2{GBk-%k(Hj;?{Ej}D$oP8UgYh(8bLgAsJ38}4e9|mf!l25ZYn+b$s>xEYK_8uY z=oPlW^IrT|>=V%=kxf-DrrpaJYsXRPJP);&@1Ev(Ohaj-qbb$%dMpGd;{-FYm*a^kBC`yrE6XT#CcST*ZNoHHKnE2@Y& z3zkrI;29I@f#k+j|L*#m?}75^yrjhP;Wkp~10<6F$I&^4W!AL;G;^|T+qP|EvTZ-v zw#~`5G1>NH*JMq7&-?xD>Q9}s&%U{q{meA`u>fbFPEb2V(bi-U^Q~$>s{-=h^jCPg z_1BpCVZC~(EU^uM19GSPnsB**zF`K^wW8X3F?UrMbn037GuX*B4Xr?pxsESOQ{_MZSu8lJlMFHBJ z{+oHt{Ma+~alKS~6{)PsR&=o0YAmDMJ#ay;4HdIWtpNi7{GCR$6~F6$V46UU$xe{K z^bXl7HS!X>?9?rYPNT?t_mwuR)M(wa@@idZf`=;cV`NmHUoFc;Q*Es`-bMyzCqRZvoIlF{Bvo54DzyWS6gP!<9Ou^yAmQs^|X(amG?&cg9?LH8Ked{+L~S2>j!1$fI4al z&3d`ch`oxn6%W&NEXw(G6H1#niM}{C-I>HoO%>O_z4b5ijxmDuv0fcx0oXOWWW|FAdmV*zK*NWO!+RV+EpiSE07Ei zdb)*g7P!P)pX?1SarGd5wjC@vmiz3j(%uP-2aK=tB>%jUzzD6kZ8vhNc?{!*U=HO` zKQjbjGR><_kGF`iRmGoMvM$O&hY|&10pK%z_7#DzzV_FooVND~dFdUAJ`$QI;n+x? z)PK3%ei`YiQtt5klw+}%6HkZHqmftWT}P>BJ)@)+efU1XZx(^w~mQHxeLsw=-%VqkJHBiSGs=GxHG zc#LE)@l!ghN?2u|s zqM21ErtpoBrna*$-QmkRELK4rNIsXv;ITPBZM#iJzHQe8L$TZy4u<0dR(7*1W{bSo zWivSc02L%;XX}VePN%s<}GL3-Xh)Wp9p0M84>@Rc`rB9`jUd z9eL+;xxw&C4&{$UxrVP3uHo!F#qL!5rM9i)mI5{)V0wL*b22tH`mhA&LKmT6dYt}W zEZHG9g^2T!xo_EmXH{`89H{?&o;Wp=xp-lAD$D41(9CSu$X{yE99VD z0qbZB+srTo0~FL59bCVVo!!@&J?Eor%W)ywv5V?LA<(MgVo|d)`dd_)6%^T1kxg1N z3oCoM4wOti$BnJd?d zu@f-JdGfIi40*Y+hoVP;6i$z-ZFg~2W^CrKKZFuRQCWSU^lGZ79}2 zc3miWZ7gv%L&s%nL$zq=qukg*OVX@Z9KIPy{`9aL`IE0;ikXf zi2&tSj(?8pzJS?_uxf2P`h8aN4jKu}F_T=d#`dVYdMv;j*PW+I9@T#!V4{k=w?YL= zqSb~0(i-Te;6($&*+QzRU1)_h0&&4wWmsE%rMbdmBF zi9xubV}7PsAxsJ=r6QB4Y{59Vd5J(G_BnFOlc4j3G)K}SHt_%}Y$N}zU=BTrvF9~~ z=S;UmP5-e3WsO#O*-?v!YQS4?SI0=8M9t~e>ABiL_97R+Q4Ii9;-lC5CZzqs3P6wFhR_{V0~M=Ahn zX*G)+95+?VUlE{PrL&l2IxtYwMR+V-c}e30Wnw`%KS{51k0hF#al}=f@64Z5e(bYV zpkb?n*##d3x(CY{m2dOv>SYk$7o@;rCI%&#sWF|Tl-lA>d0m+@>l^-A zCw6@h>QimN8koe76~W0t8e)T1%LdRIBxDH2fcJMUYa?@;TK9p^WsEO~$enE)Y_U@|or=8m}YC%%9X9R(v6f34+)X3`D>iPZbkiRl9; z5GnEw3jCXyHmRo-g0ZD+tuguziJMr>(* z6nwM-ty7!u32p&7Vygr#j0{6R4T1Wj`E}cSSyk#&`2|dot`71wyFJ^@jbDU|__!Q@ zRmuy}3fwC!Ie!sbU6h=c5nuCwV(jyltZll2Q*KNI2|ujF05OY0efC1)JLgY@fxtJn z0c^o8C=DLxTmoeJlf9YG5I~uk39hTWyR+seG?|NXB&)WQo<7z^N_7`fv$j&s8n{`| zDh~pMQ-xWxN{r7{N($2^rO5>)-xhA3;$cS_r3iIi+Ji7BBN+3J(4PKZo(8_E4jJa( zOl(4ea%Kj3S)Uu!tpdJ*-@xtFiS034)MB4X)3nT~1mr-Ic%M%L$gf;LiHD|5Uk0}- zi+rA0BdZ|dc~FF{#pBHT4ir?yLX0X=BB`;s)WL$JGjuK%02&~aRRN2_WNfoucCaiB zqG!^ub4U|S(VFjyY)hQkTeKJ@hh$=2SOQ>t0|sl*iXI7_~n!wZHrwzTyc`(m+3G-t}2AGL)? z!Q0M5vd0X7-CAH+@?Y%d7VJ?XBwO$!7%k>CM+wFA&2l^leXemmT z;C`4WQE#X(Q|@R(hMRL1N4KaEvbw*#UzjPXLWQcxyAZZn0&yI;VTaHI353|ueN?l+ zYBBJOPCCG$o9{mY-b?|%%)eG!>R*NLY9aXlu-7)6T zlOG_-LH@c-ZZntrUq@n)mcp!Cc!Cq8b^7>uK3G~dN+&rheO+Tib8u58EqZL6ow2kH zbl6X`o4%{ay!51PtSA;r-tLs&31X2tA$H`S8DuT66GXUy^zlm4a{1L%)nodD6lUL0 zH?WdJZCCEdZ1{L!H=1m56_K<=&alsc1rYN08Xj6o2t+N%G5+s&iS>ePDHN}U9 zWuiwz^XkWz=)m`zc>x_-Q)Yh7$k zn~b^kgkhIRo*I8O{9n5eSV6tYvW8HEzhugn1kTG#^0y@GBScMu@ToxLY01I>axvjt zQ@HPfUPNVsqWBz#Hy`SYJl;(Xa@E3T)+0ATWYa^8yXaVf-6G#|T3`?cktzNyGS z!3}+&_V|8*7HtvVt~bU%3pU}y3pH(|0<=B#AM|OCWFE{}!M~)Xvjk|xQ@Inn5+_YA zqO4TkC#uC2%R#BrtoS31uJaH9C2pe6ZcGo)O>32~bXfDe{xoLRKMkSx_y|@;Eq4O# zz^piTf?UXm7c0dq&o|O}dXJOhRw*qdz{O}v0u@R^NCyzw;*5Hu|3g-CO8w0@HP&;Q zgP*$siJPl4&jnQk_Wi$fF;;i8+Jx2eCl~~ffbG>?Dk8DBwtxG_q&-0Xv`xhxoVgM? zKRB?#diY}U9>k}TnHQ{QYjg-iDCTp+zX}>{$xvl#TSuoyMDZn1AwGyn>d3BG(OTuK%uHe zQKPu)$W3Ok^U9Eq*a6Dn?NBFdp7tfdmtwaRN>Mt@6$rE7<6CB&wo3bhSBErkjZ_TT zl~Zot+>ez-dMj;%e4pWHk#-QrrVKs^Ho8xB}NosjlcJb)!K8)ywdJI3{ zsexnV>RIBHqpH7dcxUb35Ir9ckl%Jk-}OP*)#aEtLCuFgF!qG9G=^PNs{YvVK}$i} z4qAL9-%fL<$RiXc7LH|ho@2p(wN)Z^;%8@K5=J#X`O~eEnIHJm78qq=7;Rj!#zAcE z=aAK6R1gYi0;;3gN$0%!m(zfAW5q_bxYtBe_ zKJ|8$r6;h!*tS^fUvXeBj1f3M&Oyjxbo~ z&Tn}g(JbLjN)g#{W;qQAr#ZtQS2Ln$PXgEwQv)be08prq+YR@}$9MprnVW9QJceZA zlOhZ0Y6PP5I);_z_a$>aXM6OJS-ptjIi~rM6VRA9?XbW*ghL!Ny-8_-=W&2vI|Wb8 zP*>!3YkzGYjrf$dQcJuwW6G!h19u^BIj_d!Up>tnHis}a3WPCk=P0oN(aj`oq%-h@ zMyxpji1oSLDqU?1%j9v^HFgm}jA{MEUBqIE!Grr%pqbK?*STU&((uMeI3dH~;FJ}! zz^v^iqTKK;j`YJL?f%4vz}O(b{D$1ntP>8`WTZg2r#53nonDdtiRa<~!)zt6k2bdv zoQiKeY>6id*+!aNK2CtJ(X(=oJX|{apd=#!*o_m)L`k>6gJF#xQcFHhA}V4b%UgUhQqX8P?FCNuaq%MptNf0=;aLEw zo55xO-_Cg`tH7CA=lCe!gu}bbyv2`o)>JOT0-up7oo@!>{j2@r)yyll}g7{cOTe-)zgUS;#+q3 zY6e$7KCc?29tjv{5WW?I{}O$|j2b|V&47iyvm!^7mFyT}NqaFpAvm{k{v=Sio4U;o z?;(21Kny&CouzuhZezC+oDAp=XQ&SDdQ@xd8>R zJ1qrydwTL2Nn^cKvY&8yS~nsbC?3U%0`ijBm2$=Y%oC;(cCleGpRYn~*#HR4k;SJ& zHqOjG+RMUS`%FXIC=@Js)IPZ^{*nuPy#qHd@hWD)A?{Q`8|YJ?=Zf9^aUB1h&WXRo z6XPlv&9TR$!#Bhe4c<3bh&KJDmPT#iPffTQ?sN2keiet*`uebJ`1=kC>`Y1Ze}k{T z%-jxacN2|03B9orW0PjL=>r6zo@R5lT}yeA$8eT6n=HUF#6kQ(H(aC~1Rqxr|NNM4 z11Si>xI$k30pX!Kp|VGq;kw-Sj0-fL-EB;SqQ$b#UY!VovpzemS}3q`%UDy`Y0Fp( zi%nRj^6a=Q^SH=fC7s_CL(d<0yWvo$37h6CVTZt}{yAdi(Mp_|PXV9;g>;Squrok7 zq}SRX!{Pzs!}zqgd4Q=Mns)}mo6QEl_jW341zom@t+FCba+R2RPSy`)03BYIJm2UM zHw#Fkc5BLnoOK)Ota*ui$T84;q8A{=PnmO0SDm8iWV04#Ogix|pY8UIQ!Kq@c(4g$ z1814+C-@ zvL9krV+Pr=PaSOzg4#wUB9e&QE@J|MO->)kEsT%K|7nnnM31T})gm(CO4h|H3!O$`j2?WmsqSU^Zd2Vx`;G#|J5( zF_F6jobgo_U)-m+R>H8`zJ?iq`{xHmi@EK|Yt5MVtdK}5&w-kZB}C`_d8*znsxt9G?tYaJwtPczWW#1(bzq1^!uIG#{f8f z_oucd1kPhsX9G-szQb*KmWl_(^_uOV22wRhaxyO8T-rZv`QI{4$&c}(2Z6HJ~4<5yQGULWX; zF-7E=^F(Bt1Y}Dw5w>gi(Qq0B>Psn0gr?`KG~p;(A5twA$H?P4{JV9&0I>jvigG510Xp;b6bzWPke{x~{2kD$lZo?s zvg5*mcJN`n%@gm?Wnl6D2B2BIUsUw}O=B(S>IZ2sQX+|}24~12s}_5_Gqj|y8OBM!1G5PZAn?GLMTGv?iyc zB2$_jkBuoyA}Hc%(0D4SXsL7iG3B0!b!IsfDfJA031<+IK#F!oRtru8o)DAi9oGdA zmNYEb1W?Q2bA;Iov1$nRDZS|{dV93!zSEGPf9Tm1 zNm839sh+r9ro45_Sy^JWGM(FFt&`-4uoFPIL)WN=q6f?gCYTpfQ_9&H=5z#bck8)3 zjnn0A+~j%(ckXe3 z2odlUigZO_nHEnWw@wOMpTHz%@%|tYhFRY2`C)4V7ASr=>HfL`<<$uRwB8Ij4{Ep7 zap@5jQ`sJ`423w~iHcMa-F&}IFvm)LV<;_H@f;8O6aF!az#TSC_wuh>qreaam@?v>jAXc zeLja;wbV1n`>s#*@X@5q{#10XWCb^P%h>M{>lGA&OFsG9&*sJ!t{_^mQ{8@bU z^)=bF)2i{n!LjD`ob;+jX#~G>r~w*k8?q)!NB1?K0gCmAg4iJdQ%I3sSj~o(R%RKO z2huW}gPGhLs*4Sy&ao0>uVlE;gELOJ0f$tki1{O3ph0k=XkK(0lOb@7n(F5Eohw zEuo6+=z= z`T00mAvyR_5hp{)RxRi;GPRsR9L@D{luBk}R~X`Xh0=T!!3JzW_G5_hZaY7BwFY;_ z$)8$>!Zu5cRdpP{+aIr2OGUoS)Y4BT2X#=}j}uZR0iy-jwNL@47fSn=wh=;Amd zckm}HMbqbbLFSl4~?|cYt%+E6S*QrZtMIyzHcAq4^bQ-I+1IG2b zrEZOD&;A9?2eyL(F5i>w+nFCwU(2dX`^Z^zjEkl;pwcLTEbu8Wgv0rs{Rr>{0K~ZV z6B2%+9#zr5cZLlR^w#Z()}67btY+4L7YS_-(4lQKq~ZL!LhmQ2?KIj*HhFv@2-{!4 z>(lRb&y8ZQ3O22S1MZSthCuI$?)C6#Obc`H?aF zK?Z~zxk11R^H!|d=|}R=KdSSvf(*6dl)cI&YTA471{2WH!wAw>-Df{0j-gG$0n~GN zFD;<^_Mhf@Ug*Q8T~ev0Mm=%z;yz{4cvSOPu%g9c!h_A1f`no?N#glizFK}beh7)_ znAF?|rEH~uD_r8hGIW06dgT+KmBWP3yDdw94l=SNwkr2tl>mLEiw4=NDlm>~NFJ&G zk2pVrV26EBMl|e#t+xl<2sUua*lCRuxM&wj5p}sDou9a<%S(}HI!YQ`#sR^A70Uuc zg3L|;5<1kk(SR=n0diH7lx}LJOj%O?;10ANi$m*j8=hGKt1Qg1MGAmh?)$UUI_IKsLU#Z#FI zrOfb_0;n-Nzzw!RYw((NHJggO_mWYiD$e^u%jPM55(r`)OM%dGRA0YcYARAHV2=n0 zzybdH)z-5}TTkBwGT_?L`IL^vb%3JwFUNeix;FHVTR_4cpGy1>E=}pl2DU_G;2f9J z)=L0g=-(mgjmv-sV~46kcZWbeP0A%Mh8&_!5ecHMJ9ytZ{_ z;DS%qCMtcDoth?%$a41j>lD^-(>O7R=?}$TP#~8nS3f3~4pAD^VylwhgNbtYgShli z%x72F&9yy1daVyBu<*Rl{f1V&1eO+kbMqC_4vs*xiA>TB~=OudM}q0%Ml%vkcRL&W!vyF7j|?Qv|b#> zE2V5Z(A|YU3BFpFk_DQLhx3GLHT6w}z^6y|p&*`zi$6CxO8)?39{hIAcdJ~dF9~%p z`PNIq$5Dt-&QRiaD2??YXG^`~`NOKsXHiSQJo6FW8n82gL;0R-jB7Iafa}C7&ut zFg*+>XtH4RjUKfx)<7_?H1~cn6lIR_27&|yuL@K&c{$9pTY*II`duZy)EwZ)_XX$> zB(gYpCaUIsU<`t~ZoQ~7D4|fK#oqw0Rs0TsT@WnQTCOeDlM=5L(2K_?%3a$gsN8O4 zo1qD&T?PR#2Y)*KDK+oL4&GppO<3fQs4cHq~%eDw(vt{6#8!HU2er4CKj z52@#Om1RCy?=aBY1=FYrNsk!ag!hi2vw35PYKlCA8LZ2u{$)Roy3{J&8AFb3Rssod z?1idUhj5NR8G?KE8!iE=*M=|F6h*je$vJdiK|_&M($goUr8~#KM1~kKM8IH*AMls+ z8n#DHy6_cWMK~Q*bJCS26r!&A7UJyJG{6?!(U`O;O6{TBvg{MxMP+-{w7Om8P$esH zvf4yay%)#{oW^I0Nqf;^R`c~P80G-&(HEEI{5sJc^woVnMbv1*k>=s@D6^saJlfS^ z$6DwT6UQJ|dD!^2Ex-pZ%*&uW^0U~IQ=d+; z3SlPMEIVjLNfy#FsnkCPlXOdA#1bK3hcE&~F(%Ej=u>t-PWM`WUkd=PTyF(#`qUb<~dsp9A+W~#I+Zvepz8GZ~>8B0<`hC+k5`^OWJ4As$F0m$seCpk* zyxN>Tt_KvXcq%n}pL&>-MPF5ks~ghA!HLyGPpuaGqu#wj*Xn!cAN-`%oB_xF`OC^d zI3j%eRpZ%?hU_cm@j1E5*9%YNYip31<{!Om*20=*!t;aUp8{^B7C=MrMT8Z5x_!wI zG6CdSUx=p659MeWWv0F`z&Y;9KfX%A251aPD11Mpy$^xW#2kO7Em3Hcuk)#qod8L3 zHU#;jA}N8JT*780sQwaHmjLt1U}}^fGYS0|;$w33PO@1L=N7s&A^a6u)NYg!G#ncQ z zpg4iBq(n0>yVTz_e$3>TGG@?SX}1^3#wOFTX>olAd-y*8kOZqtW`MVH4TNv3Md}(X z6?x(}!vK3Y*Yo{7f$=6a(ZBDf9MS4ptgp5d-7lfse$*AcX<@PU%lOGlV!2pX{#n3co?cjn&R;c zi+A~A%XruSqAIc{sP}=2hsI$l%5E51YIBN4Ha@ma7g4$~66?t18O5EDg$>1Lp#0(2 z)#i2~q%stq!0l@e>+6P(3t9FLjfeC05wup_5!|ht0m%EEi7fLT__gQ!QGWfZQ`o+k z2b{7GmO&0fp&kbt`^bZ4abOdOOzN_Yz1weltiI9Y7x`~g`f8#NPZw|D;Hm*-kQvX! z(-EzdHV|4FR{eLFXhZ;Xf=VKWBp#9ug|AQV9H~^cpaYRU6>i!W)s<7Wv?MBT(LR<0oawZZ$Ny>^|y z3-Eb2-=>oE_+x%_%~D*KC8?C3Y$%wXLxZ~XgK~@X;yLU4x!MY2sh>Nc0XToj{BR_; z>|tNjW{G!wc$!oflA3%1{sDSdPoM3KDMz_xSh1cQVpL0_DLrTYpu{ic{+klB0FZaA zwJXt~ndFj2$S@1p-!r9P_^6S3)G-?00vJDQm)0W{=zhfQU&H^1KO)jKoneP%nqBgK zGkE{agk0~D*b3KlP##!-UBqxGS(WmdRMXnAL*a9Y{`Ua)*HX#*nL&8f;`JW8l}q)+~MqaUVEEZJ5@~Gor2c(*O=MmS)&x2vExF zUe6kbXQ0`OE_X5LChR?$GI{3a;g%lEsFlva+hUx6{%d(r2E+}1HqSQpi@2_VuiZ}K%n zSJUgA`<`E0DZRkwn`KlRqT!rW$G6=B8P$Nlo=9bdL9L}q%#UZxSNI#8Qg+8j)xDRa zuytrhFrwESs&!Mu$Dv#)%SBE~20D@Zk2(KJ8ESsT1(DR5ATAaKzDafdFLm)TZqWpL zu^clGh{ROSQECwG;avjV4gj&ip>(0I`iB%q*rDBMlore}dyzm$a$IO0YErv0evivG zQUjNLp~sqGa9P>Q%pkRExmDr{+`nea^Pa~#oE=^0U1SRR@JAU@QUtt4xon-J59^!x_l zHk>d>URBqsOxx!#vq$qRuz`1Iza6NVebL4PrMaM-4q+Zs;l|0rh`hHNky^<;Cgcl= z5l&od7sMnk0;0(#32162zB7=gkN&OZY~@Bk9mf8|eF>p8CQO5}y{yC43Ob)ckhIK0 z+k(Bdf)57URa0G8Z>pK=1N)nk;G`9C^&|@qOx_`YEc-hY3u`{Wh}Y`y#$1LMzm3m} zEk$0?4aBo6DjMUDZp;nv#uOl;54y;aoE-80xZ_kLVZa+o1kA$Mqt(?QT%raMcEOJZ zM6&5rc-#`2jdC0&4uOFFk&XEZvkkpwTug>klx$Pv`nJU777*jvgDV3kmNJS>8Uy>e8<&!Lbb%O&vY>AY6LIGRo-b!vg(xR zSY(yxS}YM|0Ki10Np^8AqE-?Q{qnMV9XDma-5Z{yyKT7JCSg<6bB3>(n$}g~x?Dv6 zNS!a9ecEOd&XeY|Gc#Qk_EnIEKllEm&OF*q^zS}JovB~^+SPMIB$DbvToq^F3ZQFp zGMbE%15p?Sg1q zvA*NQU{Uo}YAYo8?LIl2V$S(e3Ib)Yk9wk2Gy5>*)@IBw2K?sggB#cA`&Ug{d242P z?#K$(j@!s03fUv0>gx-0Uc&qidUEN3U?zzat_)`Gm<7cn#cFk>Rv-H;g5k`Ft${a= zmEv?X0-RJqH{wSCHv@t?PD_F#H*aR-1$>x1YE5j^AR6Z%6%CA@R!Tyr1Q%N+J%8G& zV=r`gBB?>&ifZ=!sp)mHPw)Gtlw<0P+ObOob2E=i8PZ14;mQ?N$M*A_68-HAHcvkB ztpJuaoRqtz)A7aiCauhE`CGDBbI!|l%SHT_2>=pd-m;LyZQwIJ5rxYef1cZAv~7Wp z2YhNtI;@Wz3@y&OI6l3{h|&TVBa_h~8o)ayF^x+xkXa^PKt+x-W^$&x-VvheH~r5d z_RU6=bdfX1(#meMoyd-zVZMft%}-X_y#Rtgojegx#+9a4S5_E$tyNEkzu{+t6RA~1 z028p$5F$xvywU^?A!IU_z-{=hkemqHu~sj)Eb9D*Ck+QdlD)02-z#2^m$s*Yb&<VAH>w517SPsqKQM2%$`GyE0F1aZN(mDtVYxQd_%nUR6J0mGWC@?AQqrnXp+%u zEbY#Lr5a~#KF&)y?YvJ5%&H(PZnI_kM<-W<&pUJ#LBtUx5RcZL^Mpo|qnU+0_e9uLMIedwddwxAjr zUC+x zl3TGW;r^k1yEC)ef6sELzKVn#SkvLAXkZplCeg46HicXAoiu~ifY@B^|8RAc?dGSiyLaAJDH`@jXP1L`@j-}tfxa9?1uz>Hq$@%E8{>Nras4c-& z6s_|fbHwTn6NT^G$e4OSwvCCI8@5||fd=x-O1Uw2OXga8J7ou14Sbmu;1@N(tW%k<>#9EZ!y`}r-xZ0mM3Env&Z?-neX;GnY?{5%7o%&nj_Sx3l9Mzz07`j)VIyKQK~v{1 zMz6^-+!T>WH~Mly-hs!Gm*7?XfA2{1jiOKfzqUA8o#!0pvl~`8>Wk4AAChBgLHNj^ z3yU)^o)wlo94YjzaTK}-dp)PIO-}00OqR&>T%w+4h*fPj#+hU3%@J&QLq`}MHD?(< zBqhQf*8Kj>xCuMP0D6DU(%xzAs!_dTr1fqA&ko7eV{D#bl<=b0V4jK;Zvm3594YD= zgmd1A$hrj@W;i@5Re@-~phUtNg&(}^HqLx%M}!&DAn095ny5Pd@R@c7=>6`EdDgWl zCX0&p4DW0k&s7#BZ|uA(WsW@MxLYUzgUV%p99BL!d*ezWz)sb5d1i&C?BcT*^X;nF zsq#YJGP5YUZxu4FTwTjkoCz-)atcn?7luIjlBoQkpwPe@VsFb>n?^ejm!e%n{5lDI z8S$q7CUbcPCT^!Dvc9JC(NIX_dtJw@BwOs1#;upy)j_(k^Pb>hXcsM2O-zlgNCJG! zWev~3WGNdF@OZd988%DRP%I3-mM#uS^7Upr0<1bYTbyOP+P3Aqr{9{t{mh1tM1;Sz z%Md$#Vh@)|bk6rdcNx@6ks zvx1};g)>`&o##4%FrH>Uz&$CZ|C{50S=375VGtZ(1)A5K5ydAEYA+T}s`sPTd$UV8 zzSn|lYL^D)4OBd-F-enmp#T@KiS;S?=tElc*2~=YD)U{dXia0L*&%Nmbe77&3EAzT zv3iUHms5Q;t^_+?4-X;_N39Sen9`eIJvI5GxvC|08f@VgQQ_xZ`OAvJ?Qd#PTcGRW zXN4_*2V}if)$a31O&?rlx2Rvy z%Ghe4ml^PA=#x>WveO9b=#bs&skFo!FbgsO#`dmKjm;3qOvot?bvpP6O*oKc)9`qp z*Md36`gRwkHSdGMtx(YXdD_do!-8Q+klK3aJ=5n-(*y=%PrjGwcHx zwliZNwF|1`Ed#O-G|;x^yJYbF-lb;u3;Jzt+AhgU;L9U9Y&BHy-&e$(@Pv64?|tAX zgrEF2>+vNt>C_SJxHfgTVBvObesrF9{ceL<<9(%KEd4b@Kc9qSfI({hp*w_uQe270 zQ76rW17BiRL)v`dw(!R`Fv%v#9zGVJij-8XGZyC(W89m}Fw`8Ia=`78RrBmMsGGz` z1C8hb48N9j1+LokEOx#lIzTV*J`@FDeC~8-64O?Yf7nm)7Dt0LOFlyF{b}SyOJNhB&RFebzL10x6 z%Eg4}NsaHMZa~$TAd5i(T-N%cMljSea%I^QbQ9@QF0t-*)p!SrY@}xuzOR|87 z65B3E&?qgAs64p^eU!6=qlfQWD^56riIW%Dq-g`XjXLI`ZAucEdDbh=!K+Yl57O5> z1G7|2qROquwLh((A_~y;+^P2r+@9=3S4C!OjZ9xf)^McXPcm@qa)JS*H$uqzu6ETt zq$8BjqWLU!!SQx0J$Bs79X*e{E8dy!X$PJo!k-m%2>Uk$Rca}C{t<9HcQ`Su%SeQ! z3Eu&!is^}P!3Cif8rkBWDNhgz;^G=UuIINrd8gYQAC(nr=#c#`ULdn3*pPkMHplgC zWBFM4tzuAMH8b75db0zFYqFdE2=TN2L`^f36m|pxI0?l{Pbfn;b|!AfRr_o4g`| z9^bDUxf<5nnl4)F0U+o0YcVliiT4nNf-HM^- zfPGrr9?u*Rh*-7shGP2y;7ZjIfXDFeG(#ug*Z>FyItUm5)|S-v`t!zix~&L!#N4Oo zJxV599sA^OhdA8u*}k_)e(`atY&AnVKE$Hf5wf;VXQ$-z0DMpD=6QWE3BqCMKxL9m zT-KxT*~PIBO97;iys^q6iJ)>0obBBx<$)U2Mj8eO0m?2vBTWCM8m>1w$iAJXVkL)= zDy?$@^O)m|-7$yd^?NoVk{jspXt{=#u?t(NC`~@?{E!9)TGyp7y|)w^i`bEZpC{A(AAsP6Oc^eu$MFM>exxycM2gWu zY(6k9Y4;XY?Yfwi8p~`qPug~0CXS#)RDv)!Ljl>IO%Za5Tur$1b*~&tl>p&}o^+fb zh2It!zt_p8yCPO4TI5l87+tMZXMOMb-#5#$ z&zRgt9Ag1SR%kER!!8Csr*-@G**IWCL&@40Sb$oNuOZsSM&u#ZMU-@Te9`7cg)o$r z>l|Q$h@)9yPLgusUza$;;=Ve?tcD_7lX0t-4SlYikj>1ctcI!YviecRXN;gXhE6TF z>j3QA!TLZ-gB(F1CE84hN2Z>Vzr6fAw-6@^iJVeFVUy1^~eu`D@3 z>);mUbL-x7=W-8uJl|`Pd)qNfw0XWL5!;xs(uFL~s+mKIkd3j@3-8$~>^r}~f?4D= zRLx$3Dd0$SeK8C}q7sm^N#^TA(9~hU0$xQWF+0`NeIzF4yGyv7G2@dVL>5kKDj9hcSSuAfzA+fL_$N@{e7Q6A zG`rO#S6DPsR$M7la2`LxvcllHjC2KIbUEjjIwSOEytI)L+_7W&)hSjU@@2Va37DD- zNUat6U^x+d13h%WpsVvc=J|Z1IG{E;*zJ`k?1`DJnyTzeIOetcngCL!wuQGZOt>y9 zsZG9em{4k4;u;LBm+|A;j$X2Ayp8l^*8ZLhR6fz4Ls@plb4(_{6<2N)3Mn3&o1VeJ+Bo@e7IAe+#imB3pY^Jtg;*2PJ) zUOXd#sq6{@r6}tt>6F5kw8))KH#N1v&0HG-!K90bM}7hS48ss7mB;f0d`O;gEPNz! zu$3?H`VF0#z{oh6qX3-4Hsckz)f9>~xlnQl&X2}RHQOvDBp)?O z-K|EjBW2X#9Gpe&0Ox6coL>T!ZCV{kRrgnyMm{+F5vqnDV5$v=`MqB86s zVD$yH*cGpEirSuhA4r_^TZ6b+Z)}WNp(hL^qwWWsg;Kb@FmNo=x;$4x)=7@i)$cH)eXZR(tq)S?t zCP(zqMddn85+eZMYD%3Np!&Cr^kofO$vCdq2z>QOE#dQ3Dd<%_IBEj@h{SF}-OslKongM!r2vmt46w{uA5 zouZoor>4q4okJ$F;78A z2Rp5J)-s3ju6Yh)PqTr}Yu`REDn5u`Q8A%f8Gyt(H8W#t18({W^fVopzaWE5+Ip9) ztbL5@OXo#D!x(=aUZR)r)?1fM1&Om@_Dy@5N)`z^ya1z^hSPHSh%3y|B*!Decs|F6 zTPoD&nCRl5B#)>Bm0iMBD^fQmgTqCv{-}74rUQ%9mlBxod$2%f*pJ2bs=d~j$uXSZ zV*rQl@3{pb00KnEl7glopX}+QM6u$UA7PpH=kDd0MvV%Yjk|RLztZ<)ai_!c8DUI| zawX_=rO^-{6hHKuRbXewhA zi!7V-9wG29{v7348hz2P@qmU9?-h*u2jI){eFj%Qu{g`^3w5%$`0vBCMZflSAn}fc zrPlUXK1Ja9uHNoocGyf*+Gk0Zhjyw0_X~K-a>S~ESG6iT>C$2x(}63l8jF>~3nX27 zz$xHMRF0ns?40%XWM!JS{5EkD60Tb37LGG6Hm@l`LudkKYvh}-GT;O5nH|0WEK%W? zD~ut{-;r^WNjOW=ydJVNroPeAHMq^TGT@U5$myf$1z#{8&Eb#ypVe~HfDa5^$Gj1T zWw;kgr3AvhnpA2bQTKl&!$%f#d3d;xT1E;SiE$UwYNQZn{viM|lZCXY29$%=TBrO3^e!S%cJ?Y);`F&8#x z+um$pZqBZql9zX9@MvBO#}WU6$#fkHp?m5@*T%~gvl{=7%!mqm{})XFr@)7Zu+tme z9Ezv^FFvm3Kj#sdU;F>WYZ1SWCAQ^a)NeMUw14~GwT&g_c&}srb&0WZX0R>kikD1d z1Z5LH$Q{nq{@GGI+aDwC{vu(mCUc56*JXF-HUNiBML*Sru-D>{I@^eSZ<+@Vs-I*^ zVEIJ2R8KVtZL%0gNfQP1Z>taxb#4$|YV*w3F3TRblulMahca>=M|0#V236^p`o?i? zHpwn@*ka)YTp9CLFg88@ST^jfkC zEtMxwM?X;Ha;~71{H=_?)Z@tXUz_^-3Uc#*01QF%zQ@jDH)@%2Fr5N+OMfLF*CQEG zbOambPqBhHLI{aY28wT}rcC|W=D*>`Z5ODGHT6gDB3fzTpS*;uS4R}I5&@pFZdq}0 zmru-P3$a0AnVnhHCBr1;os#Q|1{GD*S+BojUNP1*aTi{kulz$7;W~0TNi$o0(*5%kAd+r$%A=yXKI4(nM*9bco-cSS0t1& z?FF3aCgMYn&^WMz-q|ar;2R|LFcb%#dFnyx`?j<6{Wn>D zLYq)w?2h~zqsnjN`h zdl27qO_iwc8~ygkEZ*k*dzks)gRH%Kn%;$L2~#FnNA~EXky4t!NX4Du`I2lr;hJiiaUQGUGWF=aZ2Z_0L~Cuc4~On@>(9oUd?`2rMj>ztg3PB(otkw-x9}&OqbmfSoLZG78kAT?P?{{SdkSM zS?Fx(%%~9S?uvxXrnAE7=%Ox!(D_!}^?K17X|*usN%|M&iPt(g(B((xA#EGg?iqI+OO}dFi!q|x8HioyNAa@FTb;|3;JI^)kqJrtE6UL#8qF02rD zjZV~hQh&i>7%M1;OY+G>N~k(ry%fe4%SMGT`kY$B#!r3#e}0K8Uwxkb#cRww`2c85 z)b0`Y`pAk$u&_esJw2*RooyVPoD@n>B8MGs;S zR)2|JNZBD$amr^aC?Dz&g&u2>OP|`*IczQO8*j8}ZA8UlVy=g{_C2CA z9>KQ9(B1^XZ@s@3c*%DNuP&k5y^^afGNM!C40+3DW=qPVY%-A3t{4ZW41>HVNv2Ch z%gSdd(};go!8>)+gvdC|WO^rwm}dXPd4IgSci?QEG5QBT?6b}faW+p=fBbG*-+7%f zwfe$!7z8uN!kui4Eo_IJE+I^JAy&klp3#Y#sE=MQR>-PnG)YqXZty!{r-zUdd#X_o zcg=rLQL@iPGTms;Od=~T@mlAO?GvFW@9w7Q?W9^LrOTVBfTRn#P~6|ADtE{N=cOP&{7~&j8q|$kKDuLeLHEt@-p7O z1K4VXYH$p7)V5-iaHKH^w7Vb~d zD4Bduz5LEF2i9n;T9x+6^K{N#M)!QeRu`nCck!xWxXw=FG#iAgZ8M%eICFK% zu~3&3K4sr%j6Pi^z)G1gGH-pq-jc2Gdjo=RLNM|sl-F4d3ZQ!1ORGbMRR(IrYk zc@Cu>jB1S)KO^VBQtSkZ^q8J5iY8`RGJ<$)$bSu&&j!valR20GXVS%YM(zU7W z+>F+m%BBs>e)tirdX->lmEMJGs31TqP5<&D?(7uamVa5C=_dB%1eL9G#!_%;&Cv9d zeJ#)^rSZ1RCTmAA`Oto9yS9N=1k0=R&R#Wh&Pl=|GW6SWLif4=K!ha&O#*1RVm;C%@bMwJ-g-AIRN*gUL zgjPtujiXi&Q4iKGQM>N}CLcaPbn-R&U;7W#{)hhsPhF$gd7ij+2JO_0sBPpR&_sXw zHP!+jx7J{TH%ZW~BlkT{b@L4V@x#bVZ&I;Vko{TI(h{ORfwnA!ib2KYr`9d#K;Epo z=YQ}a1v(6g*V?FVA6a#WMRuv~1|=gZP}=MeW11vo+3&c9a0W;e#gU6V^k3w?>q2uO z>)1z$NVvEz+hus2Q_1JJ@2^X%tD-AnK3|DfT0|>tta`Q7AY-7jhO|dZWGAF&@$*|fnp8-Loi8KHMnMt{O%!QzmN1B?23bM zT`U{IPMatQ5i+q;k0aAaaVjVcPNRWkOM)Q8u6k%82$oifyS^Ut2Qd;jRw%a%ROYa51xYhT1ukU%I2l9=4Ki%t7dtfi|N}Kje?;s~?Ie#9) zIP1hbvqKlg2F9CqHR8r`gPJgx41{xa z(0MM5D9+QAyq?a`S+o7Y0!=b?Z-wWgT3zB+7g=$~E2-bWeYrjNGMV{|G=I{z(UHoL zvohSYOtCWhTI;c^a+gtOCzD0#5va5JOes(*?Z#4OU08UjSRot-Z~qQN#YKne&cu)e z>{CjSCz2I_H%(@ED-HOJMvKY;DzQ$YG)%p;N*FqIbQm%D@Btck?Zm2hpcM<>f0Lyj zyoInWmR^1vZ_^AjkKa$Y(tpPCJZ3(4ADy$8SUY+qVXMdyQ%mb19k+4UPO97Hi2V@h zI@paW3(vjE(hF~*qIjf~4+U3-@tx4r_e@&}>vB+}C@wf`-=U)vKz4%;VmGl9&D*%n zD0h(}BkWt;Iiq!;q8M-UEOQ@w9H&v^(wDwX_snI}m=Tzis zU8{gn#65pFt|gLxX+Na4cN^~9G^>Z+O;|PpS@l2)1C*uXy&yGLUd$P^)=0-jRNY}w zeaG@hr4bbuS+Agb0m90Jh19ywF{}oKkQOCwc%mSGnb$?g#>er%9uzy)>2ZaTAfza1 z7^I&kO1Z&lk;`JNDSvx+ibK4^UQqh_h97xDltmS8SCPOF%C9mgU53)(`WbS zOdrNeZANBP6o0Yu<_YYYv7Fbj5ty!S-$ccop?l;A{-vwvl?!bBE1$vJILqn({r`<6 zEzp|U=0_1)p_eb>=>=?iBieG%VT)+7#q3}HD>Uyvz`}Efxc1GLuqzd++c#l1>hvzp z69++|XJGju&ZTdMNBFazx>A)c?Y3kY=XnEHVd~#75}rZLW3Z7&Dx-;vj@p3ZzB#{=L|f zwXq^bxAU=XLT0;Ii>Gmq{TXuMINEEDu5KJ7CmT4iLd7w0yPIeoh(dR19B`G^smXNP zaz5#!Zhv?2*h+WavuFCqJx7!raKoT5&@#!5=m-_#Y@Ei~J~u3~h1RC)qBYLRZzH-Z z^dJA5h{%WckyfiiWn2zytF-e_dVMks6J64C7Gt}8BYQWI>(+@7QN3xvWsLjZ*|ymW@M#%rj+5hR$-L zX?cc68q~AVkM7wkbo&9l z^M6-p9X-SBGmoRoUO~UHf?D`v@VZ)Cd zBv@Kw`K7m!la0*x%IAlA3>8}BfMhYwGF6l_Bs1s89j4Js$2JAsIzU;5Wtt?`(y`d| z<4@tvO>z0F&$IHzF*7EUFi4cvge{|=Fn|5{J@n39M)@I)13Rg0-$?)R68$SnNLw1s z5^dOGkss37x1Fg+?qTh%6R5=Qwz_R2(s2lqX2Nhqm7w<`=ZJ-EBV5<8V(#Ge)KQGp zs9{ex3EJ0EtX`cNTS>>x(TGgBXk{iI>!PaM2+T_ZE_zHXDVKf}dDu>5db|a3D7ybzU(ARPAek@rtI?-wxhf-tR+$6R+9naGlzsIKjSF)Iu_Viq67@oWdf?Hsf=MGHx~o)I&-3Q@M!#~ z51N9gLE4FD+_f4v1UPy*C4UbR6bph=RR{?BI8_Vz%;Qw1tHfXX*Vs$vY5En@1YO|)$gs~p8O{EwPR@89ijY#%@ixFsRkaK3C>?7T5H2_OeB54 z>6CT|S)rFwri~b*+L-NJ>M|>}GD}>MFN1V;d@tj@rqF(jyJI8X&duf}l+JYbg%F?= z_SJXr-ug2BgMS&J6n{j1mL`4+!TfsnQdq`O0Hq6;DV+q0l(kt_$%+!eJCQ4@Qp)D( zq*>>!o3n+gPARVs65=fIB}SJ=XZOemsW14L6r8Cj0p-R4E<#GeCS+V{UXc#2BIJA{bCS4}XhHy#mEt7t=9H@5Z=- zIVnypi8Wa>2~2oMaUhDLC%H~uzECWsrY2N-X*=jJV&QwQ zvGU5hgsUw?tZ5%P%Y38C)}Q@2jeXnboxQ}yPd>@i6Zf+G%DXK6;4n_JPV>S2YQyq{rh*#MP6|^g#RLjy)XPbhMNv&+aS*B(z4wifw=ON33s+ft<2bV7B{_u16da|K{u+d16*Lm=L^Di> zG4@OoXVVP+sY~d@aV>l9>)a|3r3rOb0ChB8T)Gu?9=<5@7%5wuC9uf=q)T_ui*7c$ z>{F%+9)F#2{Yh(Pl@-Feq)V+!^w>n9z!+Uw-4AfK&f@LghU)ZwxG0I`peqxID8xGd zGS1oWgWo~~J&3v{9>slgoho(QCq50*Lbx>=zwm3w=}ic)j-=hSzIr*;zV z|2XlceTX1Lgk7|XdA|hygb?VSZXTMC-wS-tu?4b@bmW{ieZ(aA=e+&l<~ z!^n(!IS$gXMlL!6bQlfon#JH8&Fze|Y=G9!Zy7nY5sy8H>ix*xHI%=CWn1+B;&Vt#QhWBVQ~T&&2B(T%xk~RZewXOv zE7;o);O^Lk`@p00zoMWb2)_6G^ePV3&wuh15Y| zFl?kBmCf_ZZdjT8Mf&U(iD0+ztkFpS4@>k_DaFjp46Rm+Pk;K;c%H}K|NDQRkAC!{ zbh}*|jRyUGpMUg^{t@5&<~QkdI@q?&Bab}7um0+;Nq>I( zw||@e_#gixi;Ig$DcQPpEC1jh`~yDz@sCrfROt8n?;8_E^#iQgDJlnc&^>e_EoPo$ zh2+ydO;N`o?X_KWJIEGZxzUc230|Sc&*hdBh{H5pHMbW{-9PTM~yP=gr3{v3j-h#Vz4&m6SARNxErz^2P80h9)omN8Y=5024kK2ddzIFaGlZ*cq-&8D7S!WUH*_3hRXyZH?Uwh?jpl1Q zim@i^IGbihAT4F0k)zCM$XqMYp&DjO8DK37x57AYK#{R09bPG6p>aT1#K_URST?aR zE@QDZL9AoL7EM09)Cx_E&=Eq%B?AeA*B4pWC!Oy+=en;#=YK@V%bE)%&L}0#2~ly8 zj)zjcAC9oUkf_Eavb}!2Ewh)Nw)jPCcS{=_d)`S8yWy!7YvzWrYy=$qzX z(uk6_i}0$3b$=r?qPK#KdWh~avb%(u+(taRk7(xy&6Vw~G2&0&Nrs6a?)j*`Z*-0r zOKw77tXjy5iG4x+q;#iecModpZ1xnMBNDCcxWvM z7p_v>Jk8Xj_k$30PM@cB@;uhmMx1JW=;~rtYQhqdF@N546T4nPr5Yc?w(;keQT+fc zk<+R*35kxrA5|&;C$A=&y{LX(Oe(PJHB1E-mMvAVTr~7CBk?`z02)7C< zq<89V^ndvy$m%32jOc&o%LK1~7uD-RV;0?S(SQES#0wX(XJ$bw`t26cu@f}fK2#?O zoXzySy8sKRebCWRD{~0730<03mgUlAlNnkoGg;ud2DG}xhkZK|gl4nJ+S(ew{oB9I zOE0~|^71mD{NyKj_St8tR;w&6E%AH5_j~;2Z-4$K2M-?P{`>Ez)9LW-Z-1M`#YO(` z5C5=q5!tp)6h(aF8{goc{j-0D<2XF?%ro@+eNLS^#XtOq|Bx?#`ODmY|NR6(@cz-> z5}K>CWsb(v570Su#1x+;!dO{$N0GW!CgeIE04;_&F%}Rlmx(R29nN+wbK*&QWRs=( z0e^Tl)dzOtZJ$F$##WFY!pM|%Du|$icjT)$7vD7Jnp4TKF!boKj}_XI$YveamWYZ& zaCsgAGj>3lolsK!j>d2b5u`vXEXAHPqg#1UrZ{4vhjRxhrTSQbQdko;>3Atg<2jI z$bc!?N7U)z&NP|(=;O$mhmeA>-DT~KyXu$y&=6)FgErW#B?`5=|KX`(pBUs)qO zcMX4j$>cEUYaB)BSkXAJgW8^LI1_bL6w|+OmG-f7D5VPQ5f~Rxvw9R_y}d03s(;-> z_k$GW{D=Gy0>T)r6!j0>N4(N9_OR7TNq?0B#T$w?ae1~|@l+F~_T9zttdg1h@*^$# zh|T@8H&0W!cb9SJiS-@NV}%r>#B59ltKg%eOGJ>h7%!l!iyjy0-na@QtXh?gA3BIt ztFZW;Lv+twK{z(<%p}s5L_Ocwq<>nHXthJI+QzO|0Zp*5YJ^)I8>`|Ht#yoLc(sC% zg5Ko?bQt2zO(9%|Xsv^=B$bWEaVP5aQ9+1w-9oY_3Nf+>gp~nsMa>715mZjEH4O+$ zyf1*HyM2z{(R1ilXXqrO$1#8gdriX1Ye!8?%`iQZvof*d_BKorc6{c)^M59-&NF{CE5VOMhP2@ zL<<{BwQ-`W*s6_CeFiekmVcDQ;VPi1cP0}pBQcT^5EWuML2OMCS@jgi86tHIsBAZV z%x5p+q@oa+#^sCS?8voJSQB+D&p}7w`wNzsxf`@s2NhvocmwC+YuJ|$BRlhGw~lt} zqcNueiey<>6%XBAqx;9d4b{5o(g!}Wxq<34KZjbrM)2+r2#&sly?^UI>^%>|%2ncP zXHiS@R6qF(R6g+I^q>DD+Q0kj=w1uq)eNP-Hi_`6rl^&vYiE1JP6eSNtc7D(^T)6j zPa#(?6Ky+4Jhj7U@dWKVn=ea=>IJA?ipijhIvZmoj*IJMjHqUrCP-QbK7aP2HPUm~ z_^GFuICwu+a{>fZPk&ux=}*3b=wC+k7ny$iY3fh>7`5$l5cFw2{xB179>#y=Yp}e8 zc9YygSj1FOq5{o1rXIhS+TL9T^oj$se=Nzx|N0Hu$IqGbZA=v<#unmYy%KP24kOBb zCIvbO(S8Wy!jDRv$7&v`-5qPtA;#2(#k@2%9*&C^Hg0qUJAXQc6JDhfp2LdQKnRp@ zQMlk#5Gp1-br}8bOUS7?uoH22uSR_BtQk#9^n?5;#+jVKYD}Sn9^uiK(P4mW&VXej z8Z)R~oBsE|GOEp##;#X!9ShOFKoDKUj#r6g9pBkbWKAP=h|vBB0M}wH^CulcM>4?9pcF+pX7Ib=Xdy(U-=bgXJ<1bK&Qu^7_SZZW3x(0V<=*+EB1p|z&EXDjs&+=mY1 zF~$CS?@@c5q)Ak@ zaa0&XYe>l+Nb|kJ4(^dZ1FuQ6sUH6 zcHaQ#Ai$fOX7YJJsacUw{07xZN|(K{HKepLvvtd-fy?UE!~^ zSzKI0&yViKkWnEdm2I6hheektBoDON# zxAPVV@I#|5pwxP(>5c7?+u1Rf0&o8|+#?%_mRhEubF2(dqDy#j1x!$vb+2@e9ibDK z9DhnRhO&S_5p>I2r|Vp!NcRGq%`?;<+;12X+?l3dW`76_`z=T8AD-uWFdimKt%cVE zWwXga-eDjYM-m}oZ^IOgdv_c5)QfN8&CM|V!3O~7p1Dl0v`VnJ#>BmQ*!D9YrE}r} zvg%RUz6p0~g5Jps1dFS5JI)8k3LR zP1NepIdLIj{fS%*TSpV9BpzltIpv9N@eD~iRF)iyu->U=3V^eHBUZCUbZvRec~$~@ zX=DF8Onij^tYIwD+WbuE7~2C8M?{y;62&oY)n=j@Aw-N7te}*_stS~J(4vCU0)HwF zmS>y{+NUlfgb|AsRnP2mT|AFPnQMy%VOv;Jb?j!HXsvta>*p{;)~dL>w$eRv#;glj zu1_+8ZF9~SP~ujWJ3E9(h2FHri3VYrq5_SjyI9dRgbvXN+;|Bmyn-DsBjZ-G&y7Zg z9dtoMrCm)qS|_Y5Q6sWuh@3eBdw;_afQhY1V%ZqXC?Iq^mhn??4;CXfL6(hH1XPQ2 z|D$t8`2n?i_u_8bhzvAW5u3HOcL!lZxT?*wM)43Cy*=Wh<1K}c=iCQ zI*karpzjQ;QAjhwrb3g~i2`>jYYH*Wc)L6d=^FwOvJQF@6@jc)nSOjfvmbd3y>x-j zp&#H(Pf?FMgyCDzxlDEMet#N&?Z+Vw319pII*zE_`xv!Pe1Pt`Kfu569Kx%cVqG{y zvO!D@(Y%+5y+4lKP(&BrKvy;pTTMbVv9=ReEpgp?TeE&TP!#PSoejF=tjt5OI*Jl^ zoH6g96w+~UHcS#Nte_)?<1`t;^GtK3=$)4VgoKMmVMhyCs!J_6iht*yMyLR7)re(% z*kB%Lz-b{6)h43WOx{S1YRO8&+=Jw3l)jI!Y@^vDEJS@WGuDOH2)BZ8y~0Y0lh1F( zD>OSlAeMD{m1TT;E0H~C&OglAH^hL)XzJtvyUb6uLRLIvy_y{%yA_w5{4eIMDf54q ze@skFaOlt>e((2wkAH&)5Avx`eTqt@g75pog!}B-vn(tu@b~`S-@|bnI-L&ndYw;v z;uAdiisF4I%a&&ii{Omu0VL6ja6u^-@Vo1^i_-B^t}s@G2eIoWGi=5BO5 z3OOMJST0&CoO3VXz5Nwbbt*g6GH?YL7HN4^AT#eMq@c2I2Vun{yu3sl1V*1l47xvq zLavyU6~Gapi+|Toq~-gwV2KvFsYjg^gv*piaSX!vhdUdl@b+#u2|%ojJ_uPtjmVwW z!>=L*8V}jNigV_B=t`4#dM6_2th*m>+Nnwya4lL|O+Nd$04#EaesOPU)aQ^;{JJ)Zf2-NL9)qD36&aV-iyJA42F*DBj>yeQH zN}nq_-G2cYwX;moAV+c(T4zkWM`vdWfJg^Zk?o8PFMJe(E%EN!LG^)s#LKN40!u_r z?`K?WEW55ctzn|eGc=LXoYFc+mKNEuHAI=!>FCTUUh9;ekL{rRfNS4)32UOt)FXFO z-?atdNbHFkYi}K=bNn39T8EW4j^Io+4A^+@9)E;o;Y>I27gkt(`y|2A8j}wmVDnFY zm}`IWBH>ya6-F$*^fq?0!Q96lr*Yq2pHjZgjGKMK~AmfeZJ2%uB2V}*=-Y`jUVSZ?5U)Hq9N)$`eRUgNYGcLA$he0fM#=~)2q9VnY^t3ZTrJVkC6aYwdm6<+vrB@ouqrl6R8p*GmDqsi znI+lyCop!D&gN;{%`+p7mXbW`c3xK8x-a2#=HT6$P^`pUFhAt z9cTL-s?~XKG2{k-{vnVmZO{s9`5fMx{}pTb4BGOD>$4eI(6mjg9@yAh7S7x>!GEm2s%q}kW`@s454mS!B-1V10Ita@)!n1OKe=zIbO*qPJez}R$&{^&|jvqVFR-td5r#BKcMw{|2yjZTga+w zT+}L6upHcnKZ5QCbieqo>HP7(MN}KuTlO;bzx-Fkwg=((+bF+>ke&f8RU0c>!nLQc z3FtldHI{$#pAc{RApOdIVrL3jpTL=@p|wodS}GHBvUQTqu@uIGM9Y9g;?i*d7ul~$(vYJYEo>|Yh2I}HpR3n%y@+CDtxEO2-MIU~VftlB_ssT6#t2SOAqK*5x;_>a(c& ztVvE(bQ|wwQkVqMNboX`d<&hW*cAkdvwphxTIS?c?D z;LJ=KS*wc6#67!Nd*>9(ue@t0ky_)gt>I2IGx`vq6aRP{XMeIuu((S5NbkZm zR^K?zhNmBZuBuaGwniRP+AWwnTL-!c1)Xtej! zo2g#gMYPgFcl+Sj1s2Hq_UfeUaaC?6Isp@j6Ok@!5hgf{~Br;M| zH*cVK=^7XQkFOCduA)_pGf}5^_6isNk3Xlrew4usDzhr;zeZKMG}Jc4J$A$<}N@=fv1d~lNXr#p~V13`H~3cyJwR|q1U%^R?1r;_m)Za5#f5e z5c~3BoFjjVi27)EB9%wz0@#VrDOWsm9qr}>VGt%P5P_)FQSBAh{@wpPq+(cG_R>4_ zbviHo8Lnq+Rr}9>iT?M#m;f<3=R~Cto`<)4Kf<#4wqy57I)_*%S1m2TM@*|CkdiJ;MauCmSE6deuogmMg^N_fcWBt# zA&v-N`eQ7$hP`J$2n!uYM(Ymfeg7-?uYQAg{yf&!eGo@bsey_S)d|Bo>UUFhj6iD( zvExB>Wdel4+qwxk)uW-_Al5dKKTD5$2!HH3bG8aWQQ)@NxEN0>F9V56K&h1eMuvf; z#*hDMr4X)zy>&K`cNoJdEo1BEDno?Cj@PLANAUa;=DSPRz^!^*jZ=h$3UdqzATn03 zUStcQp}W`cSk^gv%JdD8#MD42s{T88;d#21d+B<2r_OOPR=X+-o~L7RjJm?5LdYymqFa8D3KmR=c=pX$fCMPGEpP$c&xAuBHmX?;NR4UBP z&0*U%zV8!75!2Jt?B2bbFf@gXOwATcDe--u)zwu1HgDdHl#(cl&|2fVE(Z=A0LYB- z+-xCnqu+JxLzx9sd-woxw@3H&6MshN&2dsAA)+8$Stbq(MWMB{JYLRRv#@0IC0Vw! zupZYXkJ+UbztZR+Wa8-us2x0DXzY4?2li&x&&`7+Rpjz{?2Ctx?PQLXoU(WBd=f&J za_>gA!y4h*I6F3BO*ILxEfKD+Az}rVMQ-k3c;iI!=fdcf$kNfubxSDaLVxOER;SPk zEXTs$vH@pq66rXj?oWm~J)QwIC?>NkBLQ{==fW#!uSt0CrxE?u?Yox)7EeDI?v0Xs ztOS0_(+Nc>elBd2WL*7=7tPP50rYejBWyV=R-}};bCcM$D*mN;+_@Fr=--HtOZdBpvI+QEIq{XXsQ9!6L?HIJJ;pVHRBI_c1w@q!3jtzyM3WZcHm9ix!0 z6`BaGVnp&>!-}#{qC#vnQF4OFno88&Ns3FA>k1c7M*%25z}YrO?SJ5Y+>J9v6z@G= z*Rtzd$~ce`>DfboPL=@a=@xI%a9iY3UtJKMESm38SYc_PKJN5ry>pt@v2*5gC0aED zD@ueU>hxKA`xNb?$#deEsMp7JU4(5Bclva@mos!2VM*eCK>NsPIw#Jfl^VKb4aI_o zB5p>%EDxY6SKi zzP*#c-I^@9*zB!*@|ggWI*hQIb*yF`N(5hT_qmhlz`8c>?td-BZ=FK>0Ycbg0jTUH z5CsO4C>?Jb#CkItBeYMoe;hA5ixsaXx*{aA4-7@k3wkFdbkCwbS~;6nr)C(fXqj64 z8WsN-fwPr%^g*`nn6!yOpIbG)A)sdZR zxW~VRb^fIUSbvf!JK3VoOPMo^76NzYCRDFSw6q3Jj`cgF`spm!+H@?kV8`I})J8bc z-7pUe9Vp40YtpZI>Wztd(=fH@-l)>j|P=Pa&KNM12NgvbOX2aMvB}DWwe&r=WyKo#0v}-J+kXV+)v7L;ri6~f1j-Pu? zAAc4_`c)D<`aaE%Jx1fn2e2xh0Zg3hGk9+MLqP0!ILF?=zWNqaYG~<<=hzH=$;TtH znN1=DcrH$(O5B@8t+a^dSByZACC%KVRhH!FOrk2K#1aA}r0FWA1SLhfTpBSq6Y88s zN2Xx0C+pZ7rm-jLh^i@0gfR7MWhE?(@wSV4U6?_a?iCG-EPd}ax<}5M0A`tcV%G%14`>}ag7dM*+4z^9qJObx z8_vuW^#eO-zkP~$VFg=S229Ji6X=qVDGDHF(NK5v-GyyqTNa*WBdfR1f$Da$yky12 zeeyv(C0Tp%FgWf=gC!NZH4X|3jlzu35S^CaaVrv>nfPW+!&by{jIibOsnWFj3V^r_iX#lp0c;Bw8sJO%v z5njDcq`O0{B*xgdk5l6>_JTyI`$st>p8IoB6zN`ITpui9;*}6t+xl2RXhy`OC9xbE z+i`Gg$HdWrMX*R0d>FTho^Q@X%R(fvznI+U>uNIO8wumC)41=hN7z5^M1OP4u0egziQoj;#F*_X(}3?%YIk z?{=yaO=7>legSqnud5V@seehFgLk7(Um*+!z_J+U4>1O`E{`*VSBXRwp|jH ztO~a79hXn0fqOyseuIi>Ok$bGaRYxZ=U$RezjgU&p!hDq3i? z?TzpAr}gE^avfV@?cYWJ!;U#5uWfk-#vb+Q>K&S}OU%)>5eWIXEaL%Wq-f30a4A!n7|7!QT31EMAwk21FD5^8py^JAh0)VCOq;o;cMT* zd-%gtKl;}Y8v0-VJOn+|+9I{j{34Z4{5(Qf;MMS7{W{^Xmyt>#Dqgmr7hrAPft;8@ z_s$U>eHCl_0o+Ib63v;dbpPOgLtQwET@P{lYgEFs^xeJq-hUp1u#ogwU%f<^`ncs8 z(V|em>w-?Dwk&Mhrh-jWsf?{7RRsQqDQNXg18Iy%c{Ya1B;N|Dbzh_EAIDOyL1J0B zqglIife=NBh9Tpozy=YSxFe;+lF|?*#QL(*X-C;%N2JtdS%OyBgxKmbPWL%8rsM5L zST>gGjp6(h-+x)hib|tSeWFPm_@soSGBscv$N0X#E{pD#L|?VmEG;eZPygvZ<;f?X za{x?EP67;BC28a)2m)HIRwPdQcB`D zW^HW^rBsHQGVbBJF7xyAy!z^^+^L6EuM)ZeQB@;OUVp@L9K?{ep5I_2vBPrlnqv23 zut}tl^!jGOC=GEOm0SN&CWb}b2=b%?R#1}3h{m_6-rD@st(x@z%%m2w-J56)4!k)+O!K!$;Gm~6C z@;YY^y@haX>|UQ)ty#T#jVmv{N$274v4y>^vw8tNpT*NI=Vojp z#P~zA>|TE_O3x*B`h;$bJaZ1=I!N0>3rS1`iN@25R9K>-myz)bT6Kw42d%?o&&g3> z6o0Z%Kn%s32YW^6q|i&o3q%DiYuHv3EvM+|DSC2_NYoHIGUE%%h~H@e`ruyN_BF)o zOU6OqeRO;fu8r>WiB=bo%k7lVuow%LjNcjK$DZUD`bh<_d{=s8SeqX=zBTs(FZxpLJw7Tm#ytW}75 zOT?;&b$$`*Rlp(^6>PdR^i^u=G9q3ej@M9x18)@&7R5tfloF>0_c92BVKYjv*ZmfG zPEH4*<^he8XOY%1gf&Y?ZlNb;QCNoUqLcxuAKlBvg^S45Yl(>A`?!~E3nE1rwto>z zi%6x>mdxGx;#x0fbmW^;l33QL>I+Q8ClK*PqG*Lsh@|Kcw{Tnv!XPx)Hh*98A_~JG zL6M1~6@nH*UqM)xk@iW}tbKIYjHNr~Y%GbFWeqp6&OX!0C`Y`Z!Ikr8kgL~FJ^v2g zPzxN7YVRu37hlAkf7^^`xD8-6OMliW$$xUoIU9@}o4979RzNH*BP`2|1&WatomL8^ z6rtr8qj)mfqAUT^O)RO9iwnj8p+r!)3@|C=;sO)HqAPIW6#esOS>FC3dhR54Z~2zi zSmsktREbZVgsay~+!5o?Va<3asqrOpdW=}3anQoWV~wUdgNQE^M++z-5C9ZG>%MdC`Q{f%G4ed1Fr|HbEtTdU|^A9eL2@$t7of-|!b zd-EPbw}Ib2iHLQ=R!uE{Wrfu|M2&)x9nl!Fa1sGPdrP!aX;;MUqdR1 z&`TgLfprmKA7fSQrYANS9VqRak;H$JD|I8{x0%t{!n2Z}wtFm{Im6k*4e0d8YzK)B zBjU~yV&NM2fdRfs*S;Q>@mg4TtTLreLU0OS_fgnM9O;+DfI;(CuaEkd{C#>Ygi(aF zEG%DU2@hjlxm?RoulxQ2g-{C!dkJlyXW2SHNF7UcGGmmwLx@{#Kgn|d-v{Lmw;ifchHyqLNZeG`OklzuYUEbJo@OP{L6p&FS&T}B0>n-?KWC# zKKHrLarNp|o_+RN?z`_kTCEmKOG|9rxDhEOp69W&w8V)MCx#zTYmMVLL%~fsi1?73>rcH$dNfFwAffsJvg%QP_&)T# z+lXw5_M`X3jX~ZQpU@0>{K2VF6293qC5sroM9E9T_T^A}Y z)LgWi2*$;+>F(;plC;1M$_}rjU6jn4O3nMr)HNB(TYJc`gS~JZx4MIP^ZiMZ@E#Lj z%X~jv$5_$|Q94{B1VewSYiXEH(IYb~6JbPhRUD#~BJTOL-Z^E~<~@6;@7&DP!Mj*} z^MvV03c=dp6D+;>7XE4r|H3@gi6+~g{UFsX8|hxWn!K4rhat{Ho$1H!LrTfgOK;J; zvV`5JQr*6Z$@})wI(M01d2J}vOFriUBL}6Q_=HOS;eK5EW?B$A}hninwc07S<{>Wh^d7&a@RIY z`Q#i8apEPs_!_acu$aaXGx+vK0%r>mHHZbyR1NRmUBq{9MJ3jLmi_)-Sb+q`!P&Ki zsCyRG^9yHb-ll&!@1&%M6ml`7MXwvTbx{mjFcQlxDLo$^fAHPTP0;A(ibLq3shcc8R5j zB)|*KP>C;6SC^=;ngDvStvL#@WOvv9RhY}Xm;1td92sN%C1t`li`z3ctby{>*yF%Goe21YwQ!8eg%@zzXOXszs!Sx!8<81%8X>m>vFH+JPijPzSm8|8krfZ- zmx)%|CVvyjzL7HLB9xr8%8VZhOJGkn5K|5Gbkl#to`EJxYV<9A?=!?I2r{Po#gIju+`uH9g%u+*?ARg@@EJ zZg`G*c$@}TkRn102TdXODfO&Rl=2d^zv0ir8e;D1*byr!k-YRn5fr=&?h>5nC@5p zE%nDgfox17Y!`tvjC7%J)DpJ8faWUFIzZpug|;S;x|guhMX6(u$jsH}YZRSvJeJ7-_SnzGQ|9NMjCkkULu zC$q_OV>vo?xQ%7A3}|YDQ$&hHgbCtq57q6Vx`7ckjU#lV&~ZFWz}l@f(9nNqHc^9a zvH)q@V4HOyJr_~0U{xy!*ER2zbTqPKi)E)s3jI!rD~*byjDSS$uuoSu8xUxAR2T3M z>_XS3%xKPg01~C=60NjYII%!DznTSa#xb8nHUTX@H`fo7V0kVm2v*iue(p6R&U*SP zd;Z=}bN5eul2ccDRICaJLB)Tu*|cp7V%t{2UKhQxiU77ha1X7d3nFZXs2ft>yN&HX z{c&1H&M^P=SMaYbqfyL#_@3#vGASOP~9Fl*05kHvb9DGGNFqsfUIgTyM6-W;6f0UH5;KPBqg77( zV!fRv3fEf-i4<)#P^&f2TCFoKRMfgE$?QQ)0E!9SWurVwr&giw?L&zwf*7q;G1n6m zOaKb`Wo(Q-EBm%G^U)`T^oP3WfQ@bMdFnXD)7ySuF^ztjEZBNWVCd^ViJyn)u>@_Xkt$pv3;R* zxp`~u+Gd;~bK|PnS$Gh!&sG-D?j`*F9|WfYad69V%C1ycSyrrG>!OuHCi`Oj(e&}T z*8nLQfN;ZzD;$J2;BUQu5+__BVj>wKOua_MLx>ozoCJR%sm^Z3o}Wf5jWsce?HHTx zTBAYZ!#|CdHqr4{i09868{Si|6RphCc;usqx1J+-{aQl4vkY(&M>uysjt+dH^T#0Q zqT>)97}q1WQlUOEfp9#-3{QRMNwtQuPt&e6=zIH7a(XxlSr!w^8Wp8ZIzwl_Y^;h} zT_*SJWy60x_Y?K|>oy&QZLxT{L-*)eQ#(pgKpT`WW3Fy^nMVISPOySvatMp+8_X)o z;j~e-UdPynzTd~OY;4=1jL)Y_q$SpU!FB&`0;&5n#Wnm&lU8LGWz86aVy!5lBM`T` zYHVu8_UbfJpTCO z{F8t3PxzHz`4uK6CV2DBH+kZTC-~wQzsOy8-Nl0sK8Wx8eCbPH;^@(%{D=SWAE;KV zNGbXL_rK4jOP6@!i6?mQ!3SwJoBY&I{S@E(-uL+GSHH^7{_M}9wdVQfpXWw+MI3)1WLGNQD1IoiLD6{6xYaqm9tip#ZcyognG5srUA zwU!B%R#B0U>|Y|j6rtlM@Mfy?)fM8UtGJ#=rLof#^q1a5tX;s;0wNpPk07X^qL}{0 zD@ZHCZMwukgz|lp;7rtswIT|`VK-19)=fy((-KM#b;eOl7{~Zwh*m+ObpIpz7&th^ zKJ|MW)XtqmUwILYCXilMbT}C_(1m}pcvJ)ou94P>YmShG=Ltrg#dI>Nffx&@Ap##a zI)poQ8L?wCa&MiW)gDpH_~DEc0w~XnmqtO1u%a9{VjM7{bF72WS&(0QI@e(@FTIN+ zZ{_1NC7m`Qh~fwlNx~=`3a4gb*q|F+D9%KQxOov+DIZTAKQ@&99i2+<9`J*@CNweCwO)gzJ<$u*Bjd7GEOdigOal{upTVhJj_ ze=5n_CY{L_bJ3fL_Ml&FQ6+OI^I1ft8VV2);VuBQCi@o|Eu~T&c-R+ z2lnCje1spGHFf(DWV8*|@+sVR{{+2wYS@_4ahT0EsGEnfq#hM3-LYM}NCy5FJsbN>@^Vuse|{;&8y_*1Oe z?YIv;1D1{Iwoze-u$&YH$TTs18i=q%HFyE(UZP!nl*pP$zPEoG5A2WWL=+phWNdVm zR)ld#kBE3Zz$9s~iY+tfb61E~+DOmIirpg6Lg9tysCEw_qick+n!KCJ+HQ-Y$Lgre z)I;X89s^(qvTHi?P#Pr_O2_#ym0Cx-#F_-Mno8OIls9S~{GQSdLPuDgV^o74?b_o+ zR%6I$$;)2|&mn)7&=35KyX(4yhxGu-vL}zT)=58aVq$`ciHS^yW8h)~&}=rDoSek> zeRl5L$uIumFY+tD@+)+^U4HK8evZS35A!>}^E-Uv6QAH0e&H7kOF{@f|M}1J2Y>Jf z{MxVm8V3&^L`umo|MD;M^FROd{Q9r|I@hjUBM1UM_ql)1v1!vLKKt3vvTN6_p|$Xh zUXU_d$lD2_>%bh+)d%+CZkeO?z1IoOUo*ByqFB6U4k^8^!+G&{a#ZIbT~Q2NtVHIJ z7dj8rn3T)gK1<`t2k~}qAzE3xiM;T}e5`Nb^oOvAedTQkS`3BnM0Pq?2$`{G8`j~O z9jr@nR55?F@70ugWr_56)I;%ABTPwhfn}o4mk4b+3BB2K(2*F9*bMS7(${AA8H*@~ z5F=)4W_~EWFZGy#-csu^oo&)hSQ`;YQLQGO^=K?u zFm#X7>HRqR|Gc239;~rgQQa~_hgcWaqmH0 z{V>h_Te03)#6R~PoQ)4r+q)6nTEaW^Cs@l@v3K5!jw7Ng@8YgJ2;FCyx@$A)_zSdG zmav*zsczo{0{n$V(}@$~h6Kt%(BTL|>Yfk3|8Rs|n~@ybx-I$&>sh9~*M}AsvcHOR z{w05`vo9j2eS*Ea2`^ql2ca2<((6ermKVX<>_gvz;5S8)2MsgzF}wIJ!uO&s+ylu+9_-;G+}CNwbt>25d@; zxUI)t$PBE*%z=ce2rkUO>o6SD4iX=$+0~0{ms$mNx-t}Gzx{* zsC<_%GZvy#-TM+pA(0&%jJ1nZt1z{>4Tpc9@V=iUo;#4lJ#|z0!0meISmA8lfVY2Z zGr{Erh+{L(k-V4EYNQjSRq3A4LSm^tRsT3O{~d%@C{bbEM1UgIUgbcEblj5b8L5<= zd%6GU%&;CAg%XWG2s6T4>%WE8F`dc-XuA$N%$=}VcZ~vA62-`>i?@3-?)F*3HrDEn z+)HhHSgV(CPJ9!&c*2~^xyz7Q^ICt8@a}w8oWb37j)bLC#2<}_&CjfQ6{~LYlOXVk zf{<#xp4i=w&Yh8Mu%^K4%ZrlfG3VQe+MIk|J#-=)x+YmJs1W<=+i0gwwD&`3r*dnt zYG7k;Np#3)pXaLn!u8FqNj+}OYJsJ@G&(Qhg;zl6#I#x2dVwcXVHF-`06=`qoMG!7G%Dk8D-PB z;dv(28Y}f@h^;A8Q{zkf zJ*))yAH=fqah;5;1UZ7GutCST(G@1TFVm`hfLKlp+6LzNN+B$Z+9QAa5~r`|w$!h7 z_CD#tpVyZ*kiyC<;Y7KuSsSf=lh3geg7>ZZ&CG9wLv;jDx2cYn?(xB=eV=o z+Ch>qq-YL2>r(<>I*bvn!^G1MQn_arR-=jz!<+n?`VL%QjkaAxe--EQ8;Cea6zWMK zo~h3CFk#n4#zHb9JS2Ay{!Zr-qcVoZP>6lh)g81?~)^DwTf>-g}5;nHf~=fLgso|E*V;*uRNwKmTc>#YMx?p4mWr z=@kC=zJzowRCj-s-q-&VwZHZ&O#IUSO8x3t-4_%)mmcWZ~SA_$~9L0 zpPwaOx{UwQpHY4G7ufhe{7-CHxB|5%cB4jgsc-u|7~GtHzsoew*E`RIV_{9!iI&%f?lNWRY3X@BUz#C`Wqu`V7$I1bM2B)S(6t*oJx9wpt35&F#kFg1f- z0HHG-`E2=-pl`y@ZQf5?)`{~A5o8jeeUf( zcgn7@A5eX8FX6&6omY+^W+qebB~mdo)hSLGeOkCk)uq}$G6YL>PKY@J3l^?Xo~ts( zuP;S|(pncCNbOrtxgPIL(+-I5qw9FEDv@VvfB+8$k$gSk3&U<{U$LK{$6kf$qV`6c<0hYYeQ z#uP&Z6`0XJ780proaicz?yIyKA0&Sg6Ii-$_{<5@sdCp&O!c?9WpcR@zoIfLRKxwSxz!-nA2F%LY@ZMX_<`xPgLVy=(Yh874ZJ zH?%Gv#(U%U8A`MXkv;Hqj&*;Lr<+j}qfaLaLg%P(**0n_pAqFpQu@0}BZj!JumEUg zXXl9Hs65t|Xo?I4#FC;x=D$z+dr3jIji}4{NTNgorI1i-q*g?eI|v{A8Pv=k@Y}a` zFQo*f2(K=)`sY6&T5cI}TZ(pUVj$p(9G%m7D_WxNAH{!;u0hzraxL81 z4LCaw;NJT|wC&)(`F+A;htNw`%xg*`uZffr-`PyhyO+S4Md$!4 zv7Q`I--VEgo#`m4lj(mmMhLW4NFj#;!p)CAM&s!Rh*vvzgaPrM_N8T`yavv>L%45! z0nuMFds5n_Ba_V8>M%mJdqm4E!mEqMUCK%HdkPfHY@0);SV{%zW_k=qYjhYx6d~#r zD!aELTnBri0hTaDabj;PRET!##8bNo?*A#`*`3JNV$O-=)>(gaH^ksc&XDlpJgeV% zjp)iUvf`GEo#cEjQq=PFSu`Bu7&0+L3P3LH?_|^bjPlxmbs~(izI0JqrUb+F@XxJQ z3)gk2Rw~3gAuekYr-2Be!y)iN4kFE;JcEvz9_mDlzNGnnGRMZ!8KG0MA+FrwQ2>$Y zmQVe}(^U3tPpE&F>elb&dew^Mpxqkw#n-S;eHVN2xN-gP>If-OJ)i!ub3~m!(w5o# zopOiLV|Y5cJaizXpxf;NP^;C9aAgL#%CnhLg(bQ79K?(`1|;s54S2gZqhm7;BK!`x zHG={ckEuO#uV;5e~$as7tN=(tEo{j zky~R5s`mW?uD{eq4(|?TF)OQnqNVBPKE)InOM>~ z%X}rLiI-ZPku`-IUS_)W=SbB~T%%<1ye$E$5oUjs8o!I&v=e*NZm8DL?N!v}(?rXc z5nde~^pLd)tSx(xQ=3d~*jgqye+9|9RvA6C=)+fDP3(G!%Ty60&W`Va&>^vGu-y1Kp}QR!wQ#4eeM$AiBg=I|PH z6eWL+>4#`Mbw6>dd;NRqxdhjiSo_u?`p3>=O*RrhFQ(afo=R{Mu#A{~dd&?Q@PbnI z#=11E96V7}9?RCEzVBn%meDX#YQ$p6Z;nDOLN;)Vbe_jZ{5t1-R~%c_2(9V6dui7m zBeo`yQ46GnvvroKAAiySChIsO-sl-8gjj#EZ|A|NwZ`*2KK}8K69fV6c6;b}69fUa zZFBJ8K@J`~IAotJFE0<7DZcM>-+lKXgbDrwPvj_ySY2IZ_wL>7+qW-?mh+LAsIe{9b{Q%PXRDia|cE zbAd81GLt%jhhtNz-e5|6Hm$xsOe}wf6uZQaK9?xyR8UM~L1|z&<&KUP0{hxKM7@up z9UJL$Yxhzqgp}ADnqV97L=^BSJ=ByKeuh-5SxbjlRErtY~DpMe+B>iQEGo1w}4wg zR_pk${sl-2*_;6tqgUtgFP|bj`!4?64peuI`05!%9Ai&3k@00j7-GfC*wGTPoFuYm z=)3!gg^SdEq=-fbeP)^}D>gG^erb)UR}r3@85wx5V9E8)^&8%o(m`7u&Z*~d-~D6c z>Lqk-3N7TQGZCwy?XawP#%X_QqKfMD376N1+uh_nrO|SdGJDpD@==@t(?BPVR4P_T z*Tvb;L{8MPY97|iB+`49apr*?f0=_8#i)?0+w31C{ZW0X9=A-V&Ns=NrccrYU(he*fo;RyRM`PE{*9(R_!EOOvWo^>Qj zrU~*RI7ZVn!f}jl=m+jetrM`m5MyzKaO^gnK`Pp5BQLdk7uhnS5Ye0p1Vr z_H3c?_`R%r?FS>kU5v7(p{|G^v23=f_THi1dkvvOl&q!b0OWrX{L~pFM8*k2WD1Hb zsFI&{Dg(Q8L9-;A8wio6E#@?Nbe1h)&Ib>vder=P(MUSggA{$)be7B!E3hQh2li3D ze=h{lx^d#Y+)LG%!a4gY?&W_@chT#z~$bsm7lI+c$O$1ZgdEXku4BgeHO zi*EqNSYmXxnUQ}(RnQ00=&|{t&?VQkL=!|Lzzb=BGP4OqGN~brF+h6(_w6s?AN+aL z^e#kyg&UOz*RjH?Rj_ImBBe$Q_TU8;6w|F&PM@i z$i~5RYjL1sSFICYJxhH4sL^MW7F248s?iLRl{&iLC3t`LWk|Gaw6xG(4e3@8mW^sH z6JI-LgivdfCUjIA=+y;+t7k{oRoaMpGsWl-nKO~h{TS&HYT@EU3rw}2W3B!ne0LX8 zwTAmK^S$&aj}<}=nGbr%Op-%Zo6^RpKzjBKi;XKk#M?ScWydCh)0a(iikOM+5AcFh zN#5=Z9rSIg^~|oZf)Q(y|M2YdHFp zYM2dawj$9Ll4xS8!7*a1Nw@kSk*{%@785`AAkwuHd5rg7zruTP$r*c-l^QZeWX{4T ziXv84Rx%%C0H_T9ytcMBT*&Fa(^}JNwZ?)IKk9!EAtlNWP=0_lS!d$M9zeBwSQ9m( zg;nBqpWyNW@k+}$vdCl((UL|JB28N#Q0fGw_E#uv6sDtiAYy_&*}&d2gS0K2?Hj2+ zxDUHILEP;Ucl)>Woo;jt>K0xY92fi+*0m$1YnMVF$0Z>7^)R&1)LAjrv}{QUalSB! zpVog7&}l)X3>7gu29-rGbcxBq==X#k9dHBTLYV@{hN!j70%L>Ep-8b{(usc#`x3eD zDN=`%Mqp`;Tt0`GJ8(;M(DWNg*D(t1B2~VnJ3OQV*WduOQNqDdtGK}hobVb|{}gU? z2_-$0^oT7}ln7TNyavP((S>7)Q*sTei6wvGpy;w4#LQ+0ed4q4qP4);ny3v~8Ft0No}NTbHIN8mKQPIE zimf#Kvr;Ix0&#?W`3;1M2oC=D#FN_*{Z@_(p*>3wZ9<7EAc(9fLVFe^Y@`lBM;IX|nRXu>odub~PGkmC2bQRs{P^k^KJy@n zS24H_l|5S#o|~+Z+a0eI+M56s2_(2u1q4r z4$j%{Bm6eefsYbz*lW(n$miz#pWXvF9GbJGdhc$6tBZ7BKY?&Dq`)j zSwCdiHhC-M0ggH-mh>POQxpNd0RT{71W|BGBm*?%x=eBeVu%DJOy_@7MXoWK#-zyE z3m0~wFxpc}Df3o^B2%K>8qU?XQD?tLP?3FGoN;1A^ z#w>*GASPx;w{WnQy&8YQtEHlYX(=l`iijeYd#CXC%+3z2NxbM16Wte3(k8SwAyqG7 zQi`GLr7qE}5xG681`AjzWW_bHU)^XfVXmIHe>?8wRs5r;Xj;dq^^c&0G&b~lWOF_0 zIVSh7q*`Xw|yhkhxX&lO`)O)-Sdf-S8mHfy3zG>tQC#)l zq|xP^(u_!jkGvSG$SUing-`QX?nnqx4iDmCo-9V)i@|@vnVy{;<edy=6BjQYV%z3KJtg5VeQg?q>kLqqs-9i({5)zgz3G}dx#bdER z3o!V>dQUw3052~+yo`|mSq3D7{Qzs0y46A;b@klU)m>flm_y|}-@MbABKGh7vExMS zy(4Z;mDR#)IoIm09PYj6oQT+a|9;=!cfeL!btgxg`C@?#dZf#Xj+WX8vUA40aU``In5}_h+#E9f-}#W?pV;pS#iZz20@zX+i(NL*$pQ zF*)yKIZ-?7O|HUB)NQU^j-y3_SBEb%CS%Rw2>lzOOYCTD`R(XhgmDNtzKVSpt8z zrrRamu|((K9;B0^!%1|GmoJtL&|*S*?s;Ug3XlCD#g4m?(!}z*HPD@^BaOjsjxh5* z7Qf|P6qi<+p1bV4*|M}^E~yAs4OwxSxy@%t?FzYB2&mnDGubfYl`soUT4H&F$#Z0E zP_<}k138RF>pf^%BiTUkNQlS2n!SIEasXn@9AZbz4WDP4?POwhmD6rpChobZznvCj zySFj_{zu4mE;|`$R3G2WTDjr96a%)P`@(NvR!^hZTm%ejP}|guk1)}&svrb!V59*s z64z3dL^h&m8S!dI|MNsfpS~YmAZfw##nZ?aPJM&kFd|tnl~lvuWBk2e1nhrcJK2dZ zqJ!N`9{6}Gth^;)((fVtUhUQ7?I-@(5u727-dR8r7vsA5c{=$irpXSVXe5_}7?e~X zUbQOxz&!uYJ~$KnL~WVyHDe%~Lc`j_Py%z-Xma4+S7{<(f@P9yqm!RuY5g;-EPTwJ zU0T$<8?DbNm5@mxD#1s0fm?qTGuOw=^=|<%adNrNfjtZ!AHpl2VSe)&2b7d1w!!D9 zYKGb1H>}Py2KZkNC3vN?F9EFY4xc=L?p{9dKVF$?qVK+W|X-FI$!J(?8Ml3aX~?8V;%JH_^w zDou3|eLaf-*0_2sUu%+M$x9diglzAQk~LL6i-lrsQTj_6Oqx{8Iv<3?7T96oQ97Ho zn=eCa`1XjwcISUFt7qsv^RF1a=SR`OcChA#W^8wYQD?^!`i~!BeEK5e6X%?7RLe}K zjnx`RQG(@Wt3u6}ywuW8XY6crjIkpI<5%d7k2~W&lTt_*q+6Bvp=G{Ak^rfSTvflh zOHh*r@2XRrrn7buNEvmHu-ScpB3bs{lLk_Udav}08LfZ(S!&bTs3_Bzb0YyBp3Vo_|8;i_lGHQj6%WX+<#~2vM7lhW=^kc$@*MeCR;bMogyR^QOM+U7b`<5@hu(*-O8L zKKlLG?RS48TC}dGJDQZ^tw*~#!E`%p`~Ht`^*2AmXUFRf#0c(hRhY?|?=OiC|Bsd0)cjHDr`YX|}A*TV0=NNF*EaPJ3^is_7s)VPWG- zT$}qA@?^R67b*{5>-_VUzU%#@ySF({1$hT*I+K5Z%}K5tLpCl|GD%-bR7r3mqLg^| zLAlctaR&I zXSRPvB;Jq1RG7xb;TPDm_2xq-mHaTS=iJ|$u##<;rTg#6^E<1V)Lva8F@O*bC<`-B zR$OIq;|r|Le=D}E;e3Wxd`&fCHqD@lqOhd%eUgPiU^;#?zY1#@EDY)IU%?*FnuWH6 zK1wzMAsU6OM4)bLs9HYL;h;u65GHznwT*wL7*%>Kd>Zw_p$5o#~6)APQo)YRy3wY{luZ0Gb-|({*3R)vy*>h zn2n2=mAA^KE#z5L5yG;i6)Q2^snOn8O_CxiC1EXD{n?6Q)Od$<6!X_M0JOAVsNQvn z4_e<{TOx<^sG0ChZL4Ti4b9x*?~TVK8iBwfz;p_uHJD5hlLUriH+wJDi$$BByUgVB zDyG}PPkXBL$QXK)x0v5}8l%JVvuA(NCN3>+G>-Tq(9*W_(Y0x$KS8Vx|1fefKK|Mb zvu3(wU*{z#9Yiht(F=6)(`@!0V%)jAE)e6SkMeudr8$y8k79lEKZ?Co(=O)PTV&7u zTf|Nw=`=~aUQysD*F?hwZ;CdfL(JmeB%C%HuZt^~NKg?s3r>;X)BDq3t-$oAAIj`!*&2-`nd{L#xEGlp zR8)Cs^nvxTqTafkxwWjEBt80R^0bRx+<#N+>CO$qO7cdp!_s$sfUAGM_a&yME|Cm6 zs3sVl&>z1_T3jmGO=(C8h@IiRW-ELsYeUx{*3DZlHJ}m3X0|_5Qte|+5TphaO%;i% zUNag;a;gXPyXHJ8R_TvlW3%@tg>iAiIxR@%x-5PCy<~g0yV@{%Z+EJ$)1-qLT_St= z6Ubx@vTkthN~1vX>Jxvh0aG80mzY^2x+VESg1XA{KnRcUnlGfWm}JIO2*tEYy|yG0 z+J=vehG)I?nK=XiN+A6aT%y~hH%QNXjmggYkedKZuv#+A`y_L{z$iV0`NHQi{CDS- z(V3p1JADhIBUh8n_9NMf71cW4ienk8=d>XjkB<`<={1Jku9KNW;S}+Cz2y`$jQ`~M~ntU^aipn-5XeQp_iNMWlyj#7G zJMlWUbjJTigF?4-UA==t(gf4ZFue}R{D5?Mfpq&K>CR<}#R0N?fo$h8$@WE(<$26} z-4I^3DOkH*H|qU&dTLLGLU75}B;y$7PGxJo(cltBQ(k4LlFcKB=_>>cwFP z?5L>tQVpZDXMffRI4fm!BJR3Y)M=5r`Gk@to@0NmoFF^%JTloRBQEu}uj|dO5jz|+ zc;s&8-gQ5AIBZ755iV06PZjDh4Joc^gV zV~Wq`;MRr{!$yJZNoNE_bV6@(oW=F0nBROBA*ZOoQH3}r-fLzxj>#q7+r{U{ zD8@4bcA~uUHnyF{K)-BRCi_3jT8kY{kTjutcpts{4`UWwnoqqSMi`i`{+o?W>q`L4pYB%8S_NFYbFDvq6=R23 z(?!=eF})58-}WS(Lwg}jTGz#$sOvOIk;x|M`ByO;mul1CD8Vt@=d5=$i)UhOg8_e+ zsy}gVMM@m(#x6>GAtyl%AJ>-}49|Ze?=B7Z->?Rj@DPg!aS~t$SQ12s^v18!nO<~f zXPK@yt9cqwfA#FtXn~pUW99}WqxPm-A+$S3df{c#0jEiy_I2qRHW=#R1rj5tTJtbeT1Y5qk7VT($%R)T z>AtOdY36#EekY&+Dhbx~=uJ+^`vyT;%9E1#djVy8JenPAe4?xB73?mI}jdxtY5G$E6Vh|HiKv!ZEe zX%MxfM?Xz^>KSae&o}aymNkuYzk;#rp+^i7rIxi#Hfn^+ zABKb_hBhvgX|R6_JXtWYJiyDx^L;hEgoxRnYoJQ1=2il1C+0{B#*UdEKTmr37%XjP z@uQDB5HU43mB{Az0yn)zR3V!u*|

    s-tA_0lZ35!#%x57<_QHdCD_Pq!)&I3AaRwTd!n#z7F%d)*8dw>5Nr8oe3?X?H!P zddht1zD;yWNYvB`wJlrAi1P~OGd5?Rz70QxnBJ`Ezio_~CWjOK`7)oil_C&3TYTCq ze$fG7TJo&b5*gKk@mePMdM7sAa(H?sXm}=cH||w7!zqj5cB#7@er7HrG7Na^t}x(>3EWVf00g{T8{aZ`4e(4adHbes!e|nZb^2#U4nZPYRri zI@ye!h9I7(Rirae58(n5j)Fup*&6>aC>T0d`2frTbPapB{SGpf8#fIR*KTS*X}!W& z?$MuRfQVo*fr5a2&jU}PAc(!b-pX#4s7Wsna4&fcE%U@KH84R!b5_P)!IY;9-0=r4 zog@mY=eIJW#3<{mE`n)Y5BwL_fvsB}J9BeJ9CQD=u?QWCApsI>hMDN~rI|;E9s(D^ zWQBS;kYsH^y0s&A-V+y-x%u)rt9L{k{97>Br(WY+_QXK1VJx7BoAPBGsKeg%_Fo`5 z1SIUlWH>46uV4K%{}qkA3Hk3B`u{$x^8bZK{s%|D!m+kLV88eF1FIu|URO`HfsdkL z&uZP);1ImVwsG3j0~HdIX|54Xg;kQjw0`N^fh9nuQf|zltNn5qW>*@leBC0r!PW~kmIf3_GdE87) zML`4qmk>EI`4P#D@E1ihsgHcpegbTqc5*OS5*T84BBD8|dEC7#<12JzcN{vuCl%FR z%LsZi7%?j<@>CL}8bX1lbX**jcQ>eO55&#Pucv`;?_Y~+`93Y6+E2{zrSg6gDb~#C3?F|j_@Q{9yvg*uI6)ZuIMBe&N#UgQfxH(m?z7cbL9n2wA z(+aVaA`=j*LRSgSfHBJ^dF0pNg(=f)M7{c!((+|CNYAX427p}A3PzOv^74W1)3?$U zRcg3)Z2%TRF!W+=9LFLBlD+(%4*IcjhBs@2S59J$b&&=Zj8y(+IywVQW@em`K_*N0dMv>Mrajw}*8Wq_5hD5>`lLiT-qK=3BAf`FM+b$|6rc@h5VuC< zKa_gv<=G7dUW(dpHs8mEyS;lzYE-0x3L4W_41DeJ+sW*Ph>!&AgFpV2LiX$_fx z$e$A->ntfEx5~my>j3vf;G2Hnm=aJdQ-2dlbZ+)Nz)`l-Gt|}ntbH1AMt(nPRyZ1< zr3NuQ$`ZYfS(|C#;N3y%7F8uGo>bToGb~D%5quScL|_$Jna{d7n3Z43n;;(P(p)kS z-go_441R)T7*YM?^;c{H^B%DlMoiO1!kDe(v3PDoy!S(w2PHct48nc)P=SksBr zW|R6DL%c*ei*x8XUQ3?>msoZ!vCP$4%Hht+$TLvUUtzBx24rP0zA!`+nKVw1=1p%r#$jCvE1d{Hkv)P3SGS@V%k9SCl`2+-_L+A>67 z6b9$XK*IQ6UOBqmDVX2o5ynIapQ}`>iy4~Iv#{DqE!%3rHV4N+Nt6m85+5T(>%= zqy~UDlchu$eop0vII2Oy^28m{#y@u86e#5GwZ*|WJAgvM_Pr^9qgl&|1g99G>um66 zb&CkI7F0qSWw08!J(eiTu?`u-y-3IfntLq*Rb7g-J`sE!{CA`h$O@dsGtb|GSop4>-@&%Nt(OOtLqm2reXR*-J4FOO9J>g7i(&Or*xU79= z>76KQMpN6h@^5!-I$^EQn#y2-<@Hv-`KmCx3X5E-nojt7KdB_E*jaSGyi71Jm6x8f zb=B0h-f08i!bKo6xE9f#<8mSUpeRxG{y6N{A-mT~P2k5+9|Rxaob~|XyLLDhs>(`D z$oe#N%_Z;!a_C$v!Z9LxTxmPumOp3P!ahjsQ=%ugo$az~v@BbTR4@WOrtE*w*x->9 zOhdIxNJnPS*gjE|gUNZLe6{=_aa+Gy)8&CKJ2ig`Hqk`QUo_7`Yg!79eoBW=af{Mo zT-%dD1vph@m`urnlLRs&6E}%A7iY74d(G~9&#hZM!Kl`J^u(TZcf}M4Zpmt3W4=Dk z345H%i;I`V)o~Ld1~+P1bJHwnXs~{JE*%+I`5Zsd|ykM!{nby@*_zu@Bzyd4X#+ z$`y*Y!t*bk?xFSSV1&wy0$FpC(Wm$MaIqO#S_f3X9o#tWJ8TBaZOXK!W`k3}JK9|U zhU)3IgA?g;f}f)~ay02#Jnz*A^~?9zu`=}rOD$tv^Rrbxd0-%IuylcRp2yIpdg;~) z928g2C#*m=6ay#>ob*5UzSQ`73*9Til;VRX&<%CMtr}9w9jG-C*nrlnuPq?ZxXNRK zDw&UmwUKXE2HD^K?2v2GkYXp5ZZjL`;i zh6V9|dEbq@xpcJ#5C9eOKv_v=V$Ps~;woXmJyj~xKbE{{#SKvs0g&X}RElV5G$xLn zQKn_2Py1hAka1fO_(K?1uRl5hZ_d?y9}h8%Kem2N)(5I_IXLBt+^^bYqujo9svy;6 zDV1ZhbZUIGVfJ3OA0K@1eK#Cc*C@c;P|sbJ_}V3E&Wn{iznn%bEcJf}I|6n~iE}?YOdR(lG`l!K_ z)b*`V_I2PWn;X3&QLWet+yT_!w7}iLC@`0eoi5Db5Z`k~Q;tB+HxzR&MU1t`=l&`> z5?b(3GeMvG+M)L71!Z*F=I1zE$jB+$vN~1m2>+FTAdSiJE%>#ST2<(6O(U6h{DqN* znz3=^>*_OuK44Zg*e<0*)YAJ2!sz@UEb;NJtltJaD|gE=+U3USdM)#0ueX!KJmI2S zRJjB?M$LU+vsGo=t5dS&X)nKb@CYXVA>iY>9cNuM)duf*IcmhP_?fv6DSh73gcbbM z*Bk$E)iw#uxbJ2B8}4qg`|v@E_baKk>xLF?T*>xZZ>E&|$2Ty-1^ne*9ZeL^bhTox zyt!MmO>6H|>c})Y8Dl-y#c^i2s%>iH8~hN_K!ySW3@*!prP0^Tq%oX8ja$rI2>xjB z8fz2Km$~+G@#tHhwtvX(bc$i->vTY9SW5m&zoFWrTbm9TVwi&QM23CmfTZ$gsO&0J zZ}hioiB+CEofAV!?wU1iyR|k40U=mcF)+3wFQMW4P~# zm_D9;clbgKm6G#%s*8s#&H5MYi1?si4_Jyg<~r;V0yChZ7$Mv6)y~Z!zI40uToW@0 zMr2j$rnSS2##}T+@LZ%%Xdn6dOS*GO6&(fhAj@|~O>_y|aVvRk)eO$p`fi+`( zG5!A(E@;B|s2=?jE|`$JGru8%3S)u-l^`ef8zyT6LW&bt>?MRzQMGc*+9kpyWw@9j zgZNt1M6GUw`L=`URk_J5ueNC8Vi;`kUs>y%)oxyUe{9&bb!~0+s!@OCdEdz5g9;l? z#AV$0o$#FS#Qk^z-bOFxx_{-X*ETAWmPeJn7xKxsx*NJT&#ha(yl_WYbaSN6a!=%1 zY{tNSkr3o3e>eQJy~Ht^=<7tf)QwimuNU&<%CyN&I;k=Om1 zTu+dP<4#sp5W2`IPTC^$sJ_o8&B^6Tb$S1-MUfKSX=U$3ppxW>W^?0kndMfzxK7t# zq7j%zcYz3st*qyUIYP-&ZwUI8gn9c@D?$Z&f(5EXoW6ZYdSwgZ+jZsQZR0+OK5ZjE zVjK~xxv^mG&k}#-${hG)?r|cTZZsX}$nac{ZXaa$w7xDs0x`BhrsEstz5KKcn(rH6eQF)*YOjN}9FUXc0sO7&TBEIjYc~;aqlF+^_jb}{#vhqEvZ-mb zBg`-aFvR32;8VwVlK0oTyo!jzF4UwRz_ezZps~NvQ0np%vKwgPbm~~uqu4?fNoNksu~8@clcx6YEO4t>%K?y-QzUfsVYI)9dD^s{^_%;N@v;gNg3$&$ zc~~wbqHu26s8oae?@s-ht_F6!buJuVV;rG=DKIDOlBPB@*W2f$j3<1S?scG#qIcbB(+L zgEOV#dihEr0#;BpK9~KWWYboT+G75IoHR8Kk!xk^2ki5~74Xu@(*Pb5JH!AW31z2b zxe8*(@|GTOd88sjT_DD$xZYe%743e&hi+#Ylas!=%l--V#%%oh_r`wAn+`BgaFGqL zcc9oFo2aTe>XfU=0@KJfW*xE^{($5EgYZt*o)V&8U*DMUBY#9Vm)!-&e|f$*zq~Qu ztwrX$yldPpfv7G8C(m8$`aL))CFTp*&5wj;Z??0yR*`za258JnosjUk^$k!wYL@r3 zST40%XL9IxC@S&?oZ8r9BJ3t{Z+&&>oN+(C)ekV@uL5zhS+tdT5U4#!#$o$xkdb+4 zcuTk8v%JC_!H=R;MAu0BuI@tdp3#(~)we3lmnJLwdj-W|@*cficeXxX>7Y3(;CzzB zF5-#-1j)0`ak4s)%&vzuEPFgxce!}yqAyQkb!azKc(RFj_EsY!-j?t6Ub_bjVk!)H z)``0AZU6p$lH*}FPr8Sqfq!GJ+)33e%=&6hxSq6H+0SNN*`FT9Qyp^!wzWPg1D|H(hhAhnNydvlKWmaJM6!1{FNhmZCd+^$gB z>BIiS@e?HC!;W!EO-veN7MqKM^{Z~0p=BQrRL)AWvQ2~6`mwuJ`Gh!Y`2HT|M?{4u`mdlj%hcUZ9`h5o#5 zwQ3|k3NWX|k%%$a<3RVDq4JxY2JaiW;WfSY)}K<#wK#*-ESWtxa~9`-`Emj(e`W%UqTZbjNn98>Xs$&6uU)2JE!huf@~^i7D#b)p`SQx zS|GShmk%s$3VCl&a1rT2c%2cMcFlnUg6d974zLl%PAkc%6m@ z>{3?O8jBt?`3X*vc9_BQFfCoq+GvA2Ak}Cj*^+>*HEXq8ceGlC5t52j4LEup5s$#u zqVl1mop~_=_XDaZ3#IoCO}cd2_hRNAsc#a7eJh39;g9@4+uv(l{^vK~;MT4nM)|64 z5Jr;6$x6)5!a;739i7!w7Fh2(2OUBRiN5YkwLz>FNOMP(VV8fN>i2-kwjG-^v@T%y zr=@+wAgPsZZ$;cUr^>6PVC%P6QEU3N46dro8*HX{)eS!TFm>YI2}e%t@*7{<5^1tQ;_4#L@!R3Y6zzBuT_^4Z4FIT zH;kqs!73POgj`n)4Z|24+kx%Kmb?d8jH29eK2X!5S+eDIcJAuWclYj@L3dh~5%)cr zRgWo-Ky6N{E{>vc`?epdtynpXc;HmWLn-cd_7I#aS@B<2^}F-=dcc4$g|affc8174 zqIBp{&rv~8`LsPmr=%o-u$a+-xE*XeMOHh9stW$(9v&9}xgmErV5q#ttwas9^K0ol za;FQ1rz?detSgkP+=hTV`VC)aFW7yTWaza4|8;4|0*}ExTQP2Lo|9?InBdDB0q)?7 z`gsoiVAT9h@MOuOyp~m&JC-d>;mzAvb#5Zrh^Hi|-Fa$(DTK})}TuH%}Dx)IzDHdHhD{yup1zwHNY98t9mQQjR<);;O{SM9*R5cB|lme}2xSKiD! zTbmL0w=d>aXKL%cUrUiYMRJh~#AFuc0`2nj!VoleUCV}L)dTeF;TI)%|GfDgRe(sG zL$~2WyWu1LzxRkA59W9ik4JGWJg06m9uXSQYU%tYQ{xQ2HD{5VWaJ-s$ zi(*SK^rTF8Kzq}I7ckJ#t_k#4Qu0FWJ4`8B8aOZgvvYF0A!@odD6pW7QH zcnrh$!#~|O^a`0fDscyUZFDOzn-(49gT@)0=llf&AOpHgg9h9L)^0{A0l7H)&esep zl!PnN?C*Y~41Vc=j-`NR12YNA;X4Ol9)7v2MP-m1+!e5g zE$Vg*t0gcTV46~%){4I(Xo?k2I8Kuv%g=*=fzqQPgoqj@?AxE2(tffaVHTj+*UhI9 z7YH9{AGL~PvMyru_`Sqizv9MeTCnfq&?{3LDFpi@mWE35l*WH*6Zx^hSUD@FCSmdO z8>rUf)^Za!K_OHa*0?K7>)_EMc>PHO3*^P+ck9FNqe7-cI5tU$+u*a7F$>P6Iin?) zkTLH!)+V+%gYD!Y+n!b4YM9jK7C|GU%VCj*9(*%&teVA6LsOTptRzW2PfbFL9L&V{ z_qyGRDeMn0f5Eaq$IYX~IiY$4gFUibmc%vi2+Vr$4K#WNzj{O4imGAcj^Oi3kn+Wa zb@(OM{CJMuiA{P$kV)xno^#dgZWzA_hZ-x>q%GWuy|%_xyuCJWE`W3&1vzoO1a_0q zSA}OHOB)bYMbJ-;jN5?5HL2r`g#-^dR>y0^7to^XfouNb4gKbdFE>l%SM8(6(VR+b zHZb2v{zJ)RCPqulgon82`zslVv8Z3rU-(70@dnu<0a!UJprN> z$gIr8+6f9`yTGhWq{G>%ARJMKXe`Z^YIRW+_hJx}S;VH^GTPs1+YJ0z?5`{LGVsU`Xh44vbbF zd#p;k!bpyG1P>6$)jEDL2U<|NY6^MQ56$ED z9(0*h0|*LJCmOzQ($$CVa->gAACw0i!r6ps1 zLFkIrEo^p-*pWdY->-8)SaZ}5=T=kw2tq>vXg35uH=cEO^3mj_nI{UsB@?7s>&=3V zgs>a#N=OezXZv4yFS8}I0}LwjXqhN9YPC02@M69tU5LQc3waDZSOWcTY&M62O<)>C z`@Cdd!2|z%-$M306<&&MOiJ|ww4V7H3gTr=*GGK9wSeMD3+YKIRZKfm37goLH*2!P=!gGg1u^%TWb>i~e3NXJy zsXtG75ZJ%??d5j=R)-%f)DfPK3lqo)Fh@0y3eE=x4}~wuCMJafP-4B+`hn+K0E?v` z(>NsvFlX{L9`em6w9t58eMwAg1+4HLic8IIO|@%dn^W5fz5)vGT;1-Dl3pZNgv7`& zJh?BPVU2qh*0@w z2(OVg%$&{qM$?OOu)Y^~&DyzQ`Ez~ssq(8G#!;ny4^o7r$nMHZXSCTIw|rxl39t@~ zz2UCj_YPGjr(*BM(-m73y^`$g(qjHizO3NvO6X|(bVL8rw z-rz#uqCb@fCg6wNrRFxXAKOqLk}nPkka0m`dHbid~bsO0^n$UvLy;F>VL+>9bD^sXS- zHrkx1{I%?nRx><+xK6YV|JFLD_CO@mmBXS2{qepYc4FXEX5AjNC1Yp5{oX{bx^`@= z^o351G+o0=445F;Sur}5<$k|`m~(IPy{>)9V&US25FcTC;y6SPD}7NIRJJtmUk+Mn zhL^N{KgPCq`p~tzXw&OKtZZq7`n2tiuilBSAkiW~fA1Qc-PqLX@A6Xl8aDle(=hz0=$J>u`)NIuqSKfWz>Dwbn^2Fa-Euj>>ud2-?7+pY zCaVhSEKNmwehN97XItV-Qx3h7z4K}G!~BH#&ya&Mso3}U=i8IP`L9Fne*%jC`*bm_ z|7PAZwlQ*cZut+AxRUYXpJ7fO28v9Munld2j65hpL=+B{5iJS=g(xT(lVp+zn=w6{ z0fo5vUQGE)c~Pf6U>=h{+x;Z{}SYCUlI1MoIa z6f_jt5_IbG#@~6v|G9CzejwogM*Sn^)CGeTIC8bH9a*bb*wt54$gzxac>y0nv(W|8 zAWFHYh6E$d9oS%4{oDC!R?#Qt={QiY{&bo>cAH}S%og@36gj3qvYrbuk`y!~CO}ex z7W=&XG!ksQh)>^WS`{X{XS5<|)y4LOh^{ego;TKNJc&V;tS);|IyD zdx?c8y?i%NN2LSW(*c^dM;mMCyVWRgILHUJQ;~3-U`Ga8ES=b4EGVMWf>Rn{GYUtV zeZ$)PY-WjRDFiEUp9RrA=(~y$=0vgn*}}w|G4=MTMKnuZe_A~~s3VXT ze;pZ+p-IrmZXs{KymVr%BEP_$Ldm&1JIhHlhg32LnBAb)q(W_fdRN~pQCvxy$v0=n^73mCQV zChTTHggJA!p3gm9C34uqA~u%IW=3>sjSGo1Jd+qs?`JX$Eg~r>Ak}netuI=0*?pu4 zL@)Z?w-fw3MwqVh^lcj@_9-9!iT>3hAda*(kRS~b6)DBA-45E7v=glLH(V(PQRI-;DW#3pDM= z_AzYxh-c4wq_nPjDaN16=#u{!r?zVie;X452%_t7Eh3)V+&Ls-nzah#+{vFgRzE6R zJTxeED@L*mBifiVB}KjYEX4Xls=$uSQ|?hWn$LI(Jc5v_2V!Mi@|VB@TMwhbR8E2M zh(SJ|ER|ZR9xZy4MDCuT?8@bAphgRyknrH}@E?iKg+=3g=<4|tk>KOE&IJo~3J})j z&3g*MLsRB7_Lr=wOa^fgE+6O9HqqSvs2MF%VrH(I=EGI5W{ud#2jm1s_l5*|nj4w) zm?B-t3~YL7S`^LuJPk@&Kmp|^fJ$422RVrn4ffYg8IBymtJLzdu0((%d}{$LAs1( zg>Y*6{M#U6M~ekwG>-q(E`(thKa&>sO1r&Z*GSW@ZxCq6$#((o{VNLk1qX&_Xu(4E z;*l%_qNND>wEX%swp3CRCq5MCs7eGH;Y{!O*^shY?6Yx@#H$~xzy{~NS=_(o7Oh6f ztd8L?{yAK5MKuNQq$E7J7=};^8qB2yp@Z=z2rcBbVrF(Su?9rBO<`Y96h-N%#V>>K z>!rf5-;TB+4uS&3Nqt1$i)Sb^j|F>%?P0{SI20jkV8ojscUF3q+Dyf_FWNuTio7+B zG`Wf%%5ldb`}~vE|7`a5!z$1U2bNSO5H2=%s&tz=C`!2%1h#OUh;bccYIacr7vo+MKWHSXIicMo*@{~CTncU4o|O9&;rZp>Z|Qa zKTpFl&;sm@gcS7l=a-*YAjVa62E=< ziij4~^cD^4n7E_WKcfa2?&?5+6qddpz&@H8NUo+S*+zaOB6*q0X0WCP=6}#a3=Vd} z6I3tRB@PNiDW(6u&Sw4`vkoikRA0N5qcxVw9t z9nSWc3jO{A$zSUS^&Q!k`I^PnTy1~*L!7Ot)D;I-_d^PM$Mw4z^v~~Xse)yGr|b@P z$JD;SqSIV)$_ks+umN4bM+FS!N7z)2u$alMEoW-G99!ABiL;8pPIA`;9zytb&*2dd_pWTe(FJuGaPEG^Hw|;Eg6ZG1t0` z61^f2<>(9pl^J=^n9*)max;{dF0)_9KS~&5wup)1T?;%;MukbTOsFmsN?BQr$;6t} zQ;O`uTHMXvYO%fykW*JIV4fbSrg1T$5|&6rs@x1IE{~Oq+e5yTBD01bVpD`0FX~-Q zsmP=}L1UQdY7KoM8n~&wnt%^vYQjz4TWCmHXSDM|GteGb#;Z>82T5LRQJ)2^G1sQC7JprRT zsAjq!In>RVk=IRvc0NxQWvxr6(kOC~WPhHNhkZ09MXGv?sx(*nsZnF%St)f2d69N{ zEgfyO0(f)>KIq3HZE0Mz%2;FuHE1xk-Emi49yJOK997^^yh6->(H(@=25>A%(Je5o zA9T7nng%CHhn}x@Hb=@i7%FeI8h8gCYtm|XluA<37Kvk(NJ=(^m2s1H$4nIO#K)o;h>7BQvSs5gkTE$QBT9>0zbN~<4N9W&z1 zWcF%RoKh33X)2ZqTw0O>ni<=Qg(z#cl55JMNg6K{kd}SZxmBe%PSE3#`R(>{f$%gb zwo)D;(m8|I9W-?gY&63#ohtA5klQR+0>tuF!g%`K= zs-wkK_rX}c*jO}9>5G!=L{7fP8c`vfkv7~>B2VDo^vRgxjxvHn&lj{vf`-Eu*B;<+ zp1{ixD?USTpqU|qXlBSZ$?#j60Uh0`b(tsXMmp9Sprle56=Y$B2{y%0Zbege8WdeW zh@wOVOB&$I^RiE(b}ZNP4y61U%k*JK)wuzQXjLOjiWS;0o%_w15W^3nRrHtgvKt+*RX(QlM9 zm59VQRpCtP+LIxVU%|TU`s?4e6l`6g+s?8*5bFzyRm1OpFE||*)Vc=eS*?qFmxo-8 z<<^p>2@j~-|19&a4tnPj8V|T;YMly#zstt+83PZvmDHM#?rH*7yIorSG;O^ICb&c%pW|T~WN@(VYfp7pU9|ydm5Hibt6- zT~NHjFCV#WFna(h)l*891@3ec@1`AiVr}`#Ji=}DBSv{I1O7?YBLeD!OtUWvx2@ya z77Fh`-zx&Qxt^kVWZc04A$fUKxxgKtu6TQ4k9MmhTS-4dIaL4w+2v&VV7HLGw<;cf z^0lwQ3+~KVwmq&;n7ro$JmD4&Yuqxot#o&AhEdI}7xcqZP0RY_ebm~;3_r(*R{{A6 zfWA0e4;rzCHn*-}p)0={x)B zKmNa7trzT(*zD2ia}N&DDF}Jx$`G&nMXbWYE*eivZ+pf`g+g7|?-Noh;oAPCMEAEqWJt!AT=woO=)-W*pQwz|XH1b~253S<&@_|KG%Rv`?8!JtlGhLD zX^2egiK{c;rM9&OL&R^x<$VP$q?CIQdiA=|REFOB{O_$c*If$f9c?b3EcmYEepj}b zUSHjV<=fS7vr^K3#C?g5{!AhHSF@j@B&fyT-P49heOkxUl`g29aevw4|8$Ofg7*1> zD*wwPeyJn*GAQkMK5pBr!lv4tPt%@&m$ni+k-M=Jw<;BD8|0iV7ZygGaZ=k>=QqDV$?Q>w)t z9@0z)o-%4DKj2U#)fD0Zz_BYHAdNi7z@Y27?#Zs!1Z5_BE{)3>Mlx~4I<-E7(n!Wd zl1{Md_k=wt+lNYKTD@-HI-Yg^+#@!eOYccc#t0|cQ*p7HZZ?;VhuShIc0a|xC3OcOn~R+vyS`SV%VpQGp>?C@fi-HY2*Zf zZX6S@-MwT!=_JaM$5=o$zSWkPrDrBgLjvWfq$e*cQW_0xsp2&NzJ1fZ{rA;^6G~pL z>9VC|ws$*-+BAlDzX1jDyCw0v!iWI#)sKLyb;eerG0SAb>Y`2T3>^04-XQ0#3@7o; z=Dg-uFB)uA$1zbcnbdkyMq?>$K}&yp@!q%uQI>%y7qL%p+R}q1b1Tog^Tw0El+sc= zpUnXmk|$VONbi59X&yF{8_%~E+ou)n=!qy+t7+Y{swyr7Vis=~9-Kc;cw3$H`td?==-wE2fOovg>!&Q;~q)38vn zbQ2<>U83DLX%U8aQOpyWm1q_7#F%?=!YWQOkiptzoXa1nFTDz)ZrsV{4pt)fl~2d*ymNqz;G8+x>L)>ybocV8$nzoHK(aS)=%YA=p+R62+hZ zrBJH$k6P&-li4IJ6Ebk-PcS&x+LY~KTW8do5l(^-R-{=2DW z#4f_L{Z!~nGR+>Z4W*(2C9;HkifI!03X^Wy)T>is$|O`rz@t*!>cpg?=SKSM6d$y( zU2T^dpC}BfRHn~nL{mkIXwih+ScY;wDz9m!EzHq3HK z`;LqqR(Oj8o^W1t8J>74_yL1=^0Z3p(-~qq3zHHv#?g?BcO0WL16P6Wn;3C^>W&xz z$1V5a6fLW0#@I;>t7x||`y^g(UzFO$)Je7vKu!6v?>|J9zOo(5YXl&mE~5V`s+9k4 zK&1aUZ|uK|D*tI2XlXldwIcmk1_Jj91vXi|ImZP>9LghZNb;%c##6kq%y{s!fk;?M ze+dP(r7phx+<+56A(fJLWL^oB+iB3eU!REVOZ;wU@)eP8*RvTJ>94ype2dO?ZC37+FV4*_%GpAS6yn%|G1b4U$lo7kc@ zY0Es-CYWT(dGjKNfQ%8D7)_z@IY7nk2RD}PZ4TsUGCA@)lUDtQXBW>0M*(FeA!OPd z2@!w3W4KT~gi6047`glglEYEfL!b1KAjOT zBoY5yWcPYWtD+D(h@SHz#)q|abbnJ@kE~KNsnVf~Q~)Q@af(Q}?u(3tT1qQV6W{7VEUg}$R$9Ezzi+vv??pA%JaHrM@W^VLgYvCk$t7_utwXV$T-MGX<)HWL@SRVz1B{u6>k>c4;Wqz9)J;mQ& z@^d{%!>Syu?|&qsV2LPo%Suh+MStQ&uR+iK`A$O*yLx#zskAuMvLBd?*;NKPIutV+V1LLJNpL)Qw)|V7uy4wS;P*{*MaDx# z6_B_uWd&)95DO}foZuypDsUanX%H)|q}Wi*@dFYa1J;H>mZGAGB=S(@_(m8bEjyTj zW2~to^rTg@u)6WYd{!b9o}P z5Zy&J-Gc*od!pcJ;8j!`uQ1K(m1d8Y=sOIs-yr`KjzL;|0vO-;%un#Np5%Ta9JVk+ zZC~c~mkBhTqd}-!cf=grQ?65ZWJ7ts6HXkTVS;So)@08LTzi~rjwDHSx|#?eY0dUX zz@-bEC734b)}~U2u68}YX+wuhC+B4`LOSVh@2UAaV6MJK_V(nHOk}MvmHqdOFbH^o zgZB|E9yVbv<;jvo!kj0fY~Y1O{S-zCsot9f+3M+00*Q5C?lx9klaxb7!qOj4B=^^aT^L<3m`<&Nwh=UfFx1A)Dl~4jEKJ$M9*i{)|Es!b05%N-V+h!K4+U z#>v{G?9?@@sA*CeDbz2ZKH7>70^(KI@K)GHY+_9a_Hh`Q>A+z4H;@5HSdADAClioD zmdzd3b&c14tj>3`I1C#s%84H?X&W-qFqbAPsAjHxdBE2c=ix8RY^5p@#hs$c*97iL zb&(+OUY3U;s9*-K)gki!G@`|1*0h1TOlScTS=Xr|OAcJ{K3Rm4^G^%zMQ-b&3Jc4w zF~$0Vp}1Q@K@Jl|k+jZfmkFUh#PNQK!O-b?0>nv8qhWFnfSy7|kt zTPrsJ`^r@N75UYu9Z zy$UaYgf95py*|fd{8Di@s zU03mPL)H1Gh#L9$CY|fn0+?Wb(|7Px7e`;G>WEo-tNLw|WJ^?hBCBLe4Xk62)rff; zOV2fjIv*CCyR@%S^uJb-|DT>;b!mI-HB4T0pBNF?&nQbxJDic)rGz94 zD#vP$Qv3#!B}FO9G}48+QoJN#M-!*8T+B(Q&EoiGDSXN7Vo7LE#dc9(dgx!2+Mt4a zx`8zBzoKZGtkA(aC4x9k00ky%_MWN`8L!8Hciy?zUTNQtqj3LUw=8~D1;PZ{PUo4L zQ*~_7nVqfx8-P2mcUfd)y)*wh1-e7=0b1e1U%PCGZ;dbi}^p$G@tpUX;dzP2C;Dvg&@`sX|{4K z7otnKY*DPr2EqVJ%$A@%t^2MXjHjwJ^7?OJd60Z;S*8Cy_<9OExmBF-a9q&Pi&PxZDkzap0kc$q^cXFrXR_R5)nH9xFiGZ4z>(puJkhZr7w2vB#9=4>AeX4?p9+tQ z4e;+^owWATc!pq;0Ldo-rgSda9lYf`9<~V*)FLB{0YliLX+Kq&Wk*oXK)N)hafLtO z7;~5pVN?>w2^U!C4{0an#vZ`*Rv5@0hj3e5y^%bOe+UCboT_b$%;wLeM>v}fo6wMH zmST@6cTFXj?v1&~9CiN8-NVf!4{}cZ`{>?#En=-&_*+2SiUVvKdS{6_-W-QHkyLNq zV>IcNGw+C0wvOVOxym?{6tm&uEnkj%>;%5M=%7aM3Y3$PD342jutkDmSqw`a8^V*?YW2`WPlaV zBT46?)a*T42f;Oe*-<31`vuRywkb?Nt@v*SyhhWeISWP<0MS-5JOd33aYwmJk&Dlc zbzV9@fA|8id0uXvdUQ3oj@R=ZlJd(5lz;KA(`1iqihEkCw!C$MJpMyutdM8Xl(sGm z{+>M{tGa!AP5O8vNEN$8dnAk>@`pD8<$J33K$mN-JEA zC4PpCFKDCBo;`kIzf@{m4eGVjCvYnp5gf?sgEi(r@KtAADX)+&AxTJ^!qOD4dd;(1 zLHf_I*ETSH=x#Td1(01M;lrZS3Wevx3Ww)Ik?-FTZMUbaHoMr@ux<6m97tGkdIRKV z3Pf2ED(J`yq8)iT)RpSnbaG@wd;CVaTrO@Dh?>jPPLXEdOSC30fLu7(mU?r@o7)2c z=y0S3v^c$?7rh@V#S(Hwq`7BfP^H}m^ZiBhbmc2*DcYOMo2w)fZFb}Y@QwSlpeJw6 zs6pjuDByK{7PFN)LG3|<*b@TCZb^5KPX5({=5p@_Dnb5SWpKK&8u7rIyH%sapM&fG^lYw5bh7dVkR zWFn42>-T#qsWSL)FQfL2PXpL<)z~YC?r0+^nX;88i{n+(S@I1w@UD>5y|Q{8?p} z`s9ooN9wEF{9@Pt&pR=KR5Y&SCmC}J`(N)wTQ9Z$7XSR8uiE{e@5KKQb5_*;SN@a3 zo3dO)aT~<@Ua48K(@r1^Om-EF;!Qv~MK**8EXk?6*g~?djDn}uD+9B0>XvT&K(X=G?SEWu;HY6H1Og`QR`&*SFv@NUU|hdgp%FC8Yf@xT2(St-c+l z4O(tMG=(i19ed*O$05mLo`BtHvM4y*1+(Odj@CSt&sG$(B1Fs-zxhvJF=UNa?bByz zVOUzg+RTKfN8hXSNGu}fF61rL1BXR7WR}FVi2)^wlJdzB2`$aQth33nK*@3p7o1#h z2{jxB48CY3#_uHSqgE23z~xRUE=gwT@|Yc_rR;pek4nJQA*xT=Uy$9`(G~Pdsn9jhV#3Cml>(| z!1Ki{rj5ER5Z!3N2rpt+6!%f0-g;ZFogeCGC$`m2DvD~T(=H`fIuH3lC$@qG1?Osg z0G*Jfag|FEjvj64et8Wer0)+c(Mp}>kUX)Av=hh6WwhMnc|G|1sf>i=npPBN5hIK7 z`yE`=u+9)3Mi(Wm3*M+haSHZT0`r=a>^Wudlrx+z+WqV$kC z4tKcpmLtB=7RZ}y*NBA|qFetPKEjxX2iJqc>I`sZwyTi#D*1PYP|$l*J&DhJVsENO zdcuw!;~LA`4O}(n5jgFI|B@H512NK8WQE`iKO(Q2saM2}E3BS-`;XejvQ?CuVa`Dv zdj%h6*U!pOjO*=`oFZxSbL=xpY05Gv}9ftWBA(|16EYc5Pz* z`wIwYH#DtgAHS%eCnL)YPa|Rki#Sda6~n zwAo(yT3Fvq~o*bk!3(Rm7#+aOY;ehOp$a; zXR~eOOvi3TWm_`jN;{ob85^}BwkF&#TlL7;Y5%f1TE4W4OtaB7HO1xE&fI#cVTu0~ zJkgd@QOzT0nV89%H-woR&xn^=^jPY&Z#L$N@opuuU2YE97uAnVVri0}crpy$cN>>F zN3vd9m|Q&FEjWzk2_mW zLMJ7QiwA`{?u!E$dGe`^Cys63;C5OPHO#i&X3dyS5?NbUE+^0B0A#>-1#7hTWJ_GK zEnIB0t8~YJhIt0vJ&oykgo%ifmCnqPwxz7dEZa=nNILDZvI?ES)aA*zOsFwqqyxT# zedGZel~Bg)QSs2KpT)Y!lS`(Y)?8k(vb@4?W}}txEV?Lb;s`@Kj1{a>xU2j@o@E7d zyFatc#^H*d9?ne;jY1#~zU;AjWh>ngR8z()l8(nJp>2CCy9Sb25u{aXQ^#OX=6_|F zMDDzJbJ@oao7WjcCc{FZS~Q01%UaB+w@eRn%zAbttTTiR;Px1TMl`TSkzgB$A*NmL ztLkA~v8Xb-DDPf)nugBO+A-tqglp8;BdexRu|P8*ba(12o07$0Xm+4tN~#qLAWsm| zVlH~@g{_hNvr*Neejh~Rv0$00w-IltQC6qfPHr7TvdEm1x=p!Zv;s_7us7(`)s=+X z+afGoBqTbBt_&$w&J&CoBEZubeirr`&WUFUVUc^Hh!L;6WZmO%L8iTUyM*UnS@P=~ zfC01Z49>8cj2nAl%VdeRs`H|5DVf@K7wBGGpQ=Rilr8~$RQv=NHO;17TiGN;T_~M~ zRv5y3K8ggZhnYLI31XwsM=NTxE;7_rhLFV8Dv{bpUudZHBpM##7`((S3qw_k^@699 zTWU3{4o}}_3V7&Y4Z$KXxJ#;2i`5xWJ?oM#S=dRoSaH~7Up*~$M;#h_NIFu7pC<04 zSaKM2t{*jenLRptxf%Tq6WtYzq7I}0)KOI|Ie+O`**z;s;Z&mw5)x}tb0QXx*ukzl zykm25%BbRQIP6TxyQRSvs2gM=A=j$SO|=>nnmXlny#%OQTdjq4vM<1&Ti`Z|H?izk zIdQh#VuvQ1+FLezODjuTEdW81HmV)6WXQ+clFU8|_EtTdWRSL&X6Kg{URwlqpW;hRJL11>iYOoY;lN$$4?!G^d`c)^an`%7s0aE`|1Q+vKUN_(smY|B8d2GennShn z7achyV)Hl1sKK2mas*^Y3I2p}LD%*f_S&3q_n4X7b!2*&9x%pu``Va9Ok?B>p&??7 zaYakrsS4!|tfCBf$mQZ<$cz)ZxC16QM_N%1<|x3EW&0MBr5#?>x>a+|eElb*9r1rL zzW8eckfAc1^}emU1C&ivl>5&B)0(vRDX4d2j&Awvn*5v{HJ_W}4MqW%+u{pE;S}!h zjycx17+hSq%r94tMCSV$6W9lL>jD~w2F|?ZQopw%ST!#2Y>2fM#M%zZ2e_)sW*<1J zq#9vUEOBh_|1Li%A;Z^M=6Pqk7Y$4Aw)5^LJNQ$oW7W^bUp zk;Ca6M<&@_{gR?Pq=PYp3J;nOV@reIW@c=#jRo1l4b^^Od8v(24uf*L2R3jIR`A(Q zf)^21IB?x-Q7(Ucv%7lDN7Z;`T{zJ1n}GqJ!_SX(shrCs$_k&LO!(F4Vc-WGek!^%sl>8`jgA-bNSUeso*Cf9;0P!;!z2cAA|5 zB^YMe(T6JRlm+})hRC02mOKmH05V@X^FmVZN!znvH%1Py)zyGZRy)F`*Dj;iz;?%$ z;K-WIkDQ`3*^&P^*0SIg`UM zJ@gC$r&xK9p_u_LCG;+s;VF@E7(Kq|4L|MP0=F%!-7wz$6hHOeqUmq}s8sEVc?AhQ z59A0s=)Iwq3;|Z`*CFLPy1Ql8$C6xn99I5+e3>IawT_qxxBtZWssA2X)QbqrW1~a1 zm*od=q4D2(8$mh2-11n@z=50QwV09*eHev3m2e=ZKX5-nfxoL-oS>dQud4ZlYSxt2+q$``ZLAwH#CC{eo%!B>KgpeB$+{eEsxE6nLWq}y3 zOCzu=;;dNz-EI8o#W0NXHS7IZq#pXw)`xQ2_LbF)&in>Fq9;Ss^Wlttj8YZ&?BP4V zm9m>Nw}$WaqA}Ga=;&`<=^Vvm%-L zWBW`pUI!-kBg7>TX=+dLj1sVPwXgqdQ=@q1tycOGi`CKo>nMBrzoi?b{(l=~|MQ8g zZYzJlf$#;;XMCm&MEWcDTrp+k$t`e>2jS(NqgItFnX@X6B;Kk#+4%8{z2%7Y97+q; z&?zB{{6mI$$wZguB8{}4ND!KSuoz!1?~HVElb%AHD)bNuF&be&YL+PfQ@D0k-+d?q zOo=q0i3AHKxS$~xUW|dfq0Qwls8LY(83P+#kxGuv3eUtvu&==XPfdBBLS-HVweFc* zrnb!V23?0~#G@fAHiV*Z0B`Tx3MP}G7-X^SYc6v)GBdkNV&9It+da+IcXk3?(UQaE%@ukM4azkJ+IE}icagFJOJ0ppbAl{74 z%dG~!jsi^vdp34t|0a=G1zG_cLQpb{q70J;F%z<2%9mPg@{pNTp|umsD1u-Fw!dws z&n_EUWht=YSVetNxO(j|5C7mlY^t(W*)PWXR~aIN(XZZ&C_(#{12TB%#%0BjK|epa zWy0e@JDS9>0_UNv1yxC-(te-!?}z=G1BRuiJ!6l>m%m6b*O@L~Z>Wb=XktNiN=3HZ z-1=3QAr|}q9ltvwFe8YV;l0fNWjsGvR#&{o9nqCAmx5h=0=CNJYDpv_t~=w5eMkI< z%@_PO_+jAh#{qMLeqL@)?eAWB) zDHu|YZ;=;);Yf%|qi{*)2&C3!sv4xk z=JVYbPf~HBf7y-YyZ8NZ4ZCLg!!}a{=0@b9s+W4~lR+$`pA8Lai0vo)S^lUuZ;cU# zv_o%D{*MHd5uCI)3xc_;lmu@>)88=n1^n219TwfAtcQ|>xIR|HqOBFI>x{@Fp4oNa zF-dVE(R1o9K))Wcm37u@OB`-Rr@0VDOGI}~S8K78}nqh?rgt7pFX z{OE4nC^)bHB)G?UVLpgx@%R?LsS&IRend%{d=x)78o_bCqL(UMU(#G%=k_-b>DNY= z#O*G=8QaeW;p%^58_qhnADp;FU2M(c?x-&<%;3pUgBC^?gbuXHSoTZfy46`d1W=DS z8?Qd(tqI1_atwqc7}bo7PQtG^ z7z>ITKaHl+NQoy1;jE>%1kO&iD2k{laV0TeKRG3Wksyp+N@$CyuedrJzi@QBQeFGj zY*WI#cAa;VZOGknZa45(yKc6fXL+CVZeH`=KNjutJ>mMXRxAr741L|L7#6YTo?zWY z!4G~tDd_Vco?Sx3l6cQly2%%_;})8^kr|m)9(1wgN1L!w;L`Ok zu};?FNe_Y>YIC~}=tCc!Zen2t*W*_r@NBWq;Is!U2 z4h)?_L6f<*)zo$)F|?)`CMvC}>2cjk6AKkpE?!=!O-4YorWsHI^Bj0LQRTfC> z)U8AgB}nj!D8?GKhM2|{apX6(!+&>Ox_DPh8|5zLoX3%J8J)FvcL~Y2(&s6b_w>W$ zX~%?gw{1~U`A?4o3(af|Ar1l95s9HL0A%ebQeIb=8Z)!>bs3#jpS)-5SA(b`GbEI@ z5v0!}Ok~;Ej=`Z`p{eNV+gPyeiUURxvrLF#&U)y)D$a4@Fy}NPsFkH{4AN1e2(jzc z3nAG#$q1U+xu%U%?JoW{`ZP>AC7!-qxY(9)=8eN1%&l4$itQ#zma(?$v&m8BSIx;UY12_CHo)SJU>{^;w+zzFbEYf!m&0 zEN^?L2=1KAFtg*YoBjK!?BMFC-Gz44n|;B<2N~?p;|gV8;10|_z5>Fn>&4SFgz8=m zv#O1Pb2SM04ya(+lOBrd_6$)=?VN@(d()G!N`=j|SXcPw;V>9T4G9EfJv5VA@=8@&YA{ocjw-D{vGT0`$F0D7GA-?(W`+2eFL z%k9wa+;OnRT%W~~3I6e;;kVu{i_~RUg&s^6ej0m~XLDVQnX>Vqj`VzmcZ!@?__$WTWox>``Q$QzV>SmC#l zW!G(GOpcDCN_o|qoMm{ia=D2>e4*kr9}6Y~jw&p02M`Ut`9Dk*f0cvySQC-O2g_Jv z4;?%G3ST$xDA*z%t2Y4dOZDiMxOVB9#9l4AQnO{G!X0ioeg`)U>EkU6={Rp&X{Pk$pe#(jEIDS2rfQ)iS0-l0A)EfF!zTJTt<3+O^&(yaZ7B`D zYc!@ilkHK1fjOy9%O;05--3SW`|I=f(WNH)klSd}9Roq?ZQGAc0QJNDJMX;Slsm? zb8zzVdv+`=42jsRGxzcafT%9#T#;9w6P%%M(H-aSw9kHBSixd10S;?j*2TfW!mtn{ z`f$3z;(H5JOmbIogJP;h$wN(jQ|ddR zGHf}f){IKiHgB|l=#*sO(xu|e!g&&p{?##M7VIPyVa@RbmGfLwJ7s3GtVg;PD%wx; z&>)?RUg-)*%luXCzxSiJJ})jAM<QOD~$-&+S*mCnrTVRNWZ32ZlD9Li)JnQCXnJC zuxzcG^W~PfSWbb}1H1IKO8S^J94AzB?B-5ATNeSNVq^BubLaw^F=bKYD&3tws=utx ztZ%F5>i<}&WYdhO)cR`YJ8IdY70)F=XP?@&9%T$)$ZFY6>`Kj~XgB|=6s@YU!k(kk zw-Z?!yyrcsU_%n(*%-o;nHd)~3Xb*a%MRKvuo+e2hFEG{cIezXCKcYi?!cd+4!zM> zFD3gAs+gGCQ&w0Y>0yNtkm&6=zZl2;I5}^=-z+ErkJ@0HImPqshL&c}K8cIzigJdg zCsq?TFS+A{a)!Dm$U_`)&d?DP)yy80=j`aIO-^1aXK0m^2BVxms<}Gnn|#*F+U>Jc z?Qa?rl<4+jqZGzYQjI7moj@*{F*2*mepQd(EmXM{4y>ynW-7wmreYWMd3dHSuvQ)1 zq8HXXz9KIuv~{4jB8HY@&5P};aX}Yadt5dSv3(-udVJQFJj~%2`QpaXu5j5->q-}# zVN-*7Wdk8R@w(dThx4xpAgQW2-O7j4{RInaCQTz|Bd^Ex>I*kmc6U~GPPD<=LkVlK zTL!jY4%v${)IId&V$Ltb4ZSzO;5Nw--E-ZfaYitUtyOPA+p-2>s#k4X}pzFnw=5x3#e$ zyoUmD{B|39?d>zm{5{A0-TNNC1lA~hy4f)9@r5XCLW9X~>pyU2_8N>cm=*6cgZ)tN z!+kk@zQ#{~8B&LnV@#yu3AI%F;&A@fbXR(DftyncrS+WJn>!TDP&}6N9~t-w8Fb>1 zml%oF6j9(d`78$LIxWoE1Q6UEctzyJnYePz6Um_hG!<{#C=FYn6Dj| zvpsogJ#B$V>Lp0@T;cbI&Ps!W8Y4`DRP z8dA@%F5$nAKTB%gJs+2K|IpV!;|iEB;lXtNfDPq2IN;2uJ<~&jk?mI(OT~OIl=H^w zqY>&5-R{pVFx}``eTl>MabYMF2&~&HJe>;WL%og;PVU7L7q!I{6#gRog1Z$_&KU6t z_Z*C7oM!IHUEv7Ab_l@mWN*0BQ`>y6&-OUoBmZW&9({lPAh_N`9}d6e$j?9cpq%wV z#%F`z_?x3s(5df+_}Bc4^hQ+Yjx+h$sP;W&qAR@0AF;1sT3YCXW|m=#PwXBq7_;K3 z2OQP!QlxD_C_s-LlLi!XhAB8S2?P!2^G2y}_cqo(MY{=y27>?v@t1jhM7syHa|F~s z>`R|tfkd0Vs(*)JV^qgi)iqOx?8nA=EQ+5QSKnviPB^tfao@Lby$|Cq7neR$?sZhg z4kNq_aAYBUv(Za(yxezr7R{mTL5G{beOnB}?^P5M4!XMfri}%RRYQA%kiKwWwVC$k z6de^$2DdeNGNgp?IkQzu~p0OhSFc#cr@Jc;R+=$EW#4a&Uv6rZ;X@7S1%ie6o=H@KeDxtg}8A>B6QQ%BWpjA>UfCk>32D~pY0ARNv zMl+br<;=H87v6wj9ROR^3KV*tGzJQL&|2Ab9=HvC%+VjNL+xZ`>amyW3n91gBRi2+ zr5geZoYX8V|8*mM)wTKxEt|^o&aA&7fX?0!2MR`9Hjc#CN1E@Z-r4+3y%K6Eet^RKhn+ITRR6H>{pVZ~yOXDLXA^xg;DAP(0p$eYEaq{`Y1Z z-v2L;*8fllk2Gw5AZiF-*ZKp#$;j%OAfVW3W*O;Z)(rNrNi@2OC}6Y;Y|5HQ5}OTc z$9*?(#Ux7fak(}6Y`~5d_tzfub3Gb8Ib!*zDTx%>;mWmU(T*G^`5Jr&k{C1P3Ou=C zK_!gHGC7Z4K6&Osh*_gV2aX)5C=$e&c?&L*N0QH;X(om5FH!d@wp?mWuw|GG`YMyQ z&7q|}a;S5Qw=ivCZ&gK`VrD%Fd#te)^FM0Yh|0n(kE&76ub$pR)atw;=b=^=+X4@w zp*0^a>A&{mrTn)|_iwzqO1?;Np?@wA(+O(Q=|>^sB~lb9C6C&yqbUZ}pwg25EFK-7 z=*9OZN6R!wG^`tvIA6HSI@Y&|JB7eyngk68@dbE^%wTvL7&p2rAQvf$9ouiL@6Y65 zqh?Qn&9-bl0pBqQm+Qhb=j?YJT<$^f++zh~1+Yqgd*e@2OB@k}TT3y*E+!`}X2{CL z5~(@+D*O;k-KCVC41ThT<{TfNPxl87E}Y%39*kID`%wQpg(sF{waBNL&Rsp6y+4oF z9?IH9o+5jW8nVE|lV_SckwD*=QI;GXTzq&4!gu|Dg5 zSWl`D5;_=@W@tq$i^dc0m9a~cfyQT2+e4~K1tSgMWf~-3g#U>= zcJU43fZt{zHz0j2Frsh&D*^6%!{qZ40@{!08Vt6a?mS@95tQK6=ZoRLfkF)i zfwFSG&!gSANi#mQ?0>Ys@fXG$K)5=Ib>9;F(zrxi5Qj9wMgR{vTE-)>zI{uqB#OZC z9g2dEWx!L4u+LZ-gl(illZ2j5yeQMqwbU?iwj3I+d&%a-x>_;Z$~s-^5G=R7#x9U; z{-&;!Rh8ap2|M6+y0mI%v6kXflo&=slA(}fe8D8fkRf2;0@=ADN8Uk7;M>u8D)A~H zpHT0rcO8T0;TYQTmC2-q+!|cne!1nQUTWf{_nE(XP3(tjQQQQ zR|Jq7{1vjzrYJgamO}ct%Nb8~A9gK=0Z;bjLfvfMo1-eE)h+QaR&p~#(hdRT*&Jr( z(&s0#Yg=wO1Cw_EIey2JZp2@(?>b<7TDg8RTY{_ z?|PtPh1aU$P46!NM$`bx`_{@qllRC#D`<||GlSu|%5-bGxalR$hF0YUn2PiEpPvHf z@^VM4-WB{itrX=%xx4Bu&DFRRo-#g^i#- zsxH?L?INz-S`E`DFc`Dc9f>Nz&T<7h=?vTFuV#MR`eGZ#9KO?HSM2+izyT!?vnw#30DE)g)olKqnPv69{ChR|o+P^%8*PSC% zGW$eH0}OD;aFB8G0)Ivlh~W5f2?--42tZJ>3`r)2j0k3A0yI=q!UcGBYHLw#!J2z( zY9*YzBD&gCRq5@U6}OgUtIOIh*P83j4K>lm)81FJL;(nVSHDl>^w*i5)BhUEdT)%Q>VUE$>UD zN%pXmHLNeHbePyGj}&HB;;0dfDG-ns2*?Qm23)~~eHCc1jO`isUJT6(&>+Ae7BAxs zmgoaW7Z4Jf>JgxXPm?DfuViOfs)2lET?{3xA+-w5;Zx3P3o1|z@%6znF|ia2Dkn%{ zus6ooI2c6dV@*yv@p@8M8)(6z6;q(X^@Fj`s59pNbJOwhHV80ib?fl3$_TJ!_0r;O zoW%{JxwD5{0%v^-66SN&X-Q-k?*qw@6^nj1ko}%$81Gs21(>}nGpLHf84iwPovMHU z;}XIyGUTK!si?9elI0Ep!)!PaGRX_`K|y3vDvcqKoyPVqF-RnUp;D@$98y!6#Mzu;HO_B8MEH?TE{dl>a1vU%Q|k?Qh%fBd~gRdK{LobtLAtHYZfK}`s6Ya>HA#@QE) z8AqIiaI)Kh!oG0mi1ZQ~(7X~92FBtHc&vypEaGo1UmeP=&!_?*&t+x^>xecsbJOV9vkF94K^UFm@82n{InM{VQkD7XFeZ*`$dNT%A|p=` zVU_Y~5m(irv-x_&EQkv+`}#5cF{wE0nMEBPx|ijueJk&jCM}{;NMq+mxt;h(>zVQF zXF$J&Y}a`6Tmzr_O zeIsG~Ub4W0OC3BXahGC5a?!V^{VXiIfn5Zeotqm2dczmXg#n2Dn#T^=p*9C@bfq0d zW&5_i?ak4@q<@N=GXyS4PwiQ^0_?LuIXY@xf-94B*tjP7u2vk-Z`f2NS6txItpdJl zL;oP%(ARq*K*_#XwX3t>7rtdA`Lyc~z1{(s6Vs{N@(S8d^>NG{!;5wtAM|tls*KEA z_y)J#Wn`P^M7!`j%BjiCo#e%`C0v3yK4#z_bTe~0^c|>tZB=3U=8nS`+A?400`$t=ET3DRd=U^lTu zA>CfjyFd7WD@VboMr=N)NB!Jw5IU+qUNY|qRFXkvhX95gevg%t7mm3-%EfMYU=u?I zg}m97D6}?cG!2R+yP~^gvVwAhc2H)KoP@B;M4@+=Svv0$q+YXo`}he4&m>>u9WXBw z?MYa|HltI<0*7zYm4Vi-jAFn9uR_8Xw^sNUrvHd>ls-1N!%wwyXg*~$>W@&A+{jW^ zw<51;IErZ1+U=hquPdfzPQZDyl!-Sc2dI`|%Gt%Y!kRzB-Z5x%LV9*5RIy{uF}4le zTVhchwH1jBuh|)E7IdnXDza%0u_5?sU_`cs0&-I|W?|g_GR;;zSvsRrGYOabR{;k} z8ZKBSQ!Q1pbjW&{>M=VaT0o*NvwdR~50m7|*w^S%SuC5g)zYPh2aqD2E&{eR9IMQYN{)3 zE3F7<-he=wt#H6;`WaRH-=az5ePcF2nVcya2b|B5a5pO)f5+FNz2uh_MnLR>MqyD8 z7hEq|T$lfW;h-#0&?rtFmf}a$Em1Hd29-C@G<8Z6-%yx6)LQmOb6aOF{Q1wSB1Hxf zQPmvTvP9A~)=MhXv!|DX-%q_syj(OgmeFEr3#{MMsd-^jSXG0YuC?S$+Et4#L4`|3 zm9T7Oz2*hM_$f=1=J<8BPNB6ibG&~Ze( zeij{?DZmq+L9*Y$_oke12R$8SQ0{znFvM>VB875kx8g7zrw|p?EODIi&DD@j?jMEF zpk)k9$%v4X;$xs0a?H(*q38tRDj8FD`#FSpPK*Kbg`pJ(CLGTS7E~HF@PW|^#(Imx zQG6OD%!@EV$gl?w5Yf?d+uKcsM^vkGhBF~HNCP97LZ*uuFGkAtEjhzWT28wD% zwM}Q7wDNB9Qpd)cwH>JCSUTEpMAu{3OB0V)I_kL6U%}i@xc&jxbEJ+v3`0Oh5jC=F z^8dI;CUlw1SyMn5YoQ4nv1L4#G383Se=b92S;;t&k)7zWy6sOee6VrcvKa4DqHB05 z+OS+kr|SK)@1m7c0W=pmp6`ft5@D>JA**ja(F&JfOPVy&Qx6ID2OMwHjIb=E&2e$( z@Rcv77p+an1%Z2#CPdu8RU7K?Ei`L=hpO5a#BCpY@TM!%HJs5sGnabrcDP}z=2IT$ zwS)Ha2>{Wz9zWzuXM9I%z_$~Fj_*^_`(km=aJ6!OT?=nHA}&cIR;;-IQZdxsiN6h+ zwjI3co}qS_uX;eRdI)|#vPk9`Y$&fVh~}&qrutNjX52?LJ<zqZWY2>W`_Z6gNPh2O5!XH9Z;5BrIDtMK#6FdFeEJsdmq<39h+ zI26w)hNO7GkS9=_lh$NG@C#QMYBUjkcg*xZJ^6nbhg{+DNxe~`zG z;E_Xzisvg1Y>gumN=dP-a5h_|VauaN@jlL`5Sni!U4D-%_MU41E%S?V^l_MRg`S() z8UU_1dpyW_0HCZ9`4kf%cA(-wbfR5VK_A0$C}{wQUb<~z2)hKXX{{!83X;|9zHDc?@q<^LmA7{ zJ+CQI1LiwvY)f-G89x&j_YIi5Xhg;9_vc-@nWBhJx>C!=Y>G7i9I9kC4n2J1t!Gq> z)Ua3JWz-cdUJS z*`HttI9NoLlE9B}|CGdnnV%AC}uwZK=2 zAnUlQDfMwXhgs0lZ8dC#yZKfOuQ!NOr)si3 z?Q-c`XY;e8k#~^Q3xD+=r{mNL{m2V_KXPTL54OfuQFT;>x%iF90| zuvcbd@u_9?6H!c3?1JZl^-=0h;bTc0r8busatUB2N!dK;1Ia{!vt^}@z~T`mi!NP> zPDl2_u@zM^uL@0FX@(Q{bYho9Y>Swu3Z_dPV*BR2gVJ1EQL?5|jz!wf}vVK0) zJ8G#X-F!iT%~g3xzn+bl}hQnlPOw_!pVYENvs+rwMEN&Aq-UB} z3jDd%G4h7d-+XJ@!!xd^tX8ekh3C``mn2g}+cuSXxJjgoCYHJB)MJ#^>cgL?E}G8N zPXW4vf2kt}B|uatBgv=HbkvJVb+61!6EutKMQ~2DjdM&HkrD@Vlg6BJW(>)JT+(Q$ z%*94IAr@r96<3C4AUR)xMsl3~;;`YSuX8k^Hdl_= zvS+qi<^l`AkPKeBM%;gcpqy9VlXA6Wc^BF1=E^y}sM_cp5+1-2%Y6-|1b|Ny>58h5U+r!ysx5eH% z$)mJtWNjM2?UIiY`#<}kr?RrsCmO>pAc$G#oyrGeE!X?4X&u(M@-C#$Qelr#TE*GB+^}Kc*SOlRnn}ujd)N@IV6f_uMo$dkRAke_MWEMY5^ z3^z2Uw8{l$zs7zS?*Zb-!cmdgn}T1xpbcb@1F~U#~ZG z0!So+yjNtaU5I=dMBzUC_0R+0h_5&ADh%}5UCJ3VXvFSxx1uaby_eG-*%JmAqeK`{ z8pCDa;7)iUjuRdXvBI2gWsG4ZdI!0WdjaHSF}HOcFbgNEL#iZXTgcc5?YR1KL4h$X zIzy8bFe33}cKR}c!HYHhqddnq)_D5;rvk;?06B-qf!6>{+$nbPqgA*o`qB-^38GZr z!{3;{Xpy~#@Yy@r@>GJ+lr^Nf@S9igwqK@fM^r*&Sq2|sZy>U^^^r~~TNE$i=ka3T)6!eBM z5sJ{NXk+i9kz>|#!`Kco_{E+S{A~g}rQ(g@0QsE)#$$>}Aw5O`9x67R8}oIcJ)3fU ztC(AQFWme<9>mRA;Vuvtc;mkiVOLyGzg51bvg%ab=z`$nC+q`i$&iADD8P={) zOJbfY9{n+*g9eGIcHlg7yw{$PS!ItQAAE1oXi>C;C%&hlwLx}*L+8+n$^M$m`Sgr1K}5XdWs2YJ1#Z;%M|<0#Ovk%(bGi9A0)9 zh0l(H-wiPm2*sh#+WyQD@yv}cuh~@Kd{JlMJnNS15~5B)T#512TO}*KCn~_lZRO7gdb%GGqXkjgCaAjrLYlpo9fjvxuRt)#t4ACl~p=jVJn^L;&O>t0u9s zCV%b8y$|5N0b1?Kq7)Gz%4Mu2L)0%FpsmkE#K(=rnw<~ferk{AUPc*Y&hWKfB<{^Q z#`F(EA-LUWrHIc7q8FFT46mQUacajaG4`M zu?bRj$eU0f167QZ(qyI+>JWWY4rG-{$Z zz!%^!yOt-a*1LEQcDsgD?NikykFMYLHKAKgq)4*w5$i__t|Sto5SL-sRL^~-$?7sR zRP{*5qZOTss_9*$6M$_v<*?oh%Vl`Pb|)LqJ)5-j%M+=bOBBZm30%WXDahtcd638< zAa|xu#JEzCuo9h>k5-8}Vw^}54B#JE*Bk?WVM0nJs7NT)$c#$`gT1?`a)^waHplp* zAmY)M_r@I!qs1-EOI#Zq-Z9R_6&MlkI~yKkL2~8<1fn3JlnxRe^n@3f23AVo+X@gA z!tEef@Pch#Rn5r%eoUyyMdj4nle0F789vm;`0c7Y31bxdOWr59AZsp&vis-CMA#{l ztAUZ#C}MmBf?p+&1IJvVW(m-eTEWx|{v|0msj46OY-2IE^R>EPXnfOcXy=FttR2r{ zBo?S05;0N*y;oef;(^otxU~Ddu4_BB=VBky<^lfbZG~MSQ%LF`?{<<19aCthejXtq zwO{60WmjVfgavGkUE8oUHkNFfa9~k47gN5m}sb0>Hl=)kkNp0C-OJ?jvo0SQZw1EE$>J2`YhYU9he{@(X&?;zi`sBYrK|dum68Xq{d_;T3 z5`q*md%Y=*D$6~rhz2rIriE%}iI%~;)fGl6)J_51%$qr64_ep1{NI;Pikl||sooI%TQ9+OHD4Vr6wO^J>HNuq|(jLV#yk+-V zfmivAP1?QPY?u1bjcm`??}KNZnwmj5##`N4o9J`v#-*uo9@6F2mGS`}DI4VbZw^x4 zl7cDZ{a?)a%+|A#87;KoPiI8qt69;PQ=*fp6+`dsOW#}!x)ioqm;)bGW6aM=GW^d< zu^1oKq1+5O>KwgWtGTYTo4EFu4EwzImyBCK#z$3ist9@7@?G6N0AaFG-4El={D4}$MYz0MGwOsWSb0PtkWp*EJ zNk+0kBiw__sW=3$qH=RDSdDi>P`RXf^!^QI#wpg=^?bqPcDc>yKO| zW;>2byaL^J1-o;%LZzLuApUf4jW@XFkTi)O!G9ds}*QOBV}Q zBYIm)Yf}dcOB;G)3qvOtOFMIVr~jdu(*JkyG)GZZdPo2zTh_?hcw?!&=Z`gN=Ygog zJrN50zfiVU*+v%aN5akGA3AscttV0=n8PAz_fd#G=PO5s0+3>&Tj8GWWmqe*-GFKcHLxv1tMft#?xk0qe7&`jL z53LhI6?r1*Qed<6LN6a~@4 zvx1TSUp{w#?{-8{JYwVB;kjEZO&;t713q4;c_Hm9-jhr7_s^~VBw2k5N8U3cw7vM` z9E`iG`hU4&@9LJtkN%aY=wBiKpMPZG|Lr3FH}?1cZP@xBFhvbdZ)AL>KqyIJqkU$O5#eSI08Jl`t;K>#yohpV=7#3Npfn3;%Yy z-&u}zU5T&=_HkXfXZq@dFHZyAfVz=f1VM)&fgSxy*Kb==r$VujPK#7d%Z*z0c6I;& zjUeH9fJ$Lii?~R-ce7^NFlier1}MV1twpnDNlHIA3AuL;NkLBW{w0MS!Z*@vyjfd@ z%KpS#B-vXp-+}EHml~I(7cI> zQ4lQRdiGN zaS`vXNBWefHNX?`-tM0fyME1F%FTSSEYLG7#86aA_ooM_kdL}g!KgvaB5K`D>G;_w z0*nPJS-TPR4p(YMs+Q}Xhq_m>oaPpdBQoEh z3&L7yjP5)e^HjKeO(mZmCA&t+dSu+lCCTt@8?kG#-Pek$XzJ?19?| zKW=Glo^>HrG&c!fEO%3Fqf?j}SCqT7jXHP8R3&Y_aV3}CfLz2M2YSb{Tr{eZ5h+V_ zJO+op{$_XgR>`YTJRwCFv`EQL5ssty@5 zVRDoOW1Qlwt6H>})}3fDj0Whu{ki1&yW4HeV}a}vI&Sx!xDvoac1 z3I%2mgmsVhx;%mvsjCzZoILZGat%+J%ySo(!b7AxWg z{;W6I8U$a~O^~VQP!GKSE$(O-kSbvf@+G(z9sw+AVloRU(gflO%fonMbdMrLA@z;S zb4)6paGayHy^aoDbOrOJV>mQ{KM62c=6ebpreESyLBdD4boq1u=}UZbttDF)XeEo= zV@IOjZ-eW&m{u8M%H4q8+`x$J4=#v2Ta)zC{^%LTzhhD!*x=Ukn^DNdSHX>Z7RTlb zs)jMqMN>Xjwf8joq_H@>Az}=cGZ^_)UIOpHYa~;qu7F zd}CL{U;@L}8@jxx{0il>&QksDL$a^1PGh&Li(*?xna@SgLNRubYL;#Sx{ zEWRBBt}e|0x}J>a^-kaORKojg>2IR_!`W_8esJ~SU+LKBC3a%q(5 z6uzigN~g!}xv#3vVdJ^R7C&na_(#2e+D~A<_^WJ(ku7jQ+K3P4(m+Cpw48V1;9v*J2-xyn$dW`HnwE+W3`iD_-BZ zxObr4Bb&Fv8CY(-=hvbNZC;Gd_WsCrjn-#v);0DlGth4z4DOq zZObU1QIGgS4Oq$6pY`P{ryiXa;H8zRVWm%h`rr6Kbdl4{wQrnWAMmzV9j*J#UkxSu z+ge+Tx2~Vi8dk%OTZna8O#>1)7VuDPsgMH}{ONVHCsxO=yFT^M`BgN@@YD(zIZuExrc7ylXqHqtlg6I-@bnux4-E@y-7E3MLRN!(|U6E zZ7)YM@lec^o5gyX#Ijdq+)cdbrvy9ByNRd{do0xFI$4_I^0k07#fiKa0=z3ph-Z!- zX=H>^tvGz?N)71vH_;Rqq6ty#TRNgY0T(eJ4sgg8i z)iBu@>RBQ`G6aVF#}DyWBNV@@h9;dU=aFQ34$IUerj@$#oXHnYVxDs zxha>`%hS|4O3Cp|EmubJUDZEq;BN7`Tz=#@+?qa$m3{8R*y-`E^{@uT!M@x~7=UYw zVs5RTb>qXBo~s_ZEqiz&y!`pHb3X!%c3{CFCz06>HibrRLSB7v^TWMulJv%9x8TyfDYh^`=Z>yJkPzf% z-?Pq65x2giRCTc`uoWd@Z{d;z6fL7o53qMylD;(Gv$Vo^Qk3iT%NkY^*;})Ca@K!F z!UG0}eLA6p__jB=zg$9olY?vQE@`H%c#KS%FvlvxamzOv?Zuxs(YMcoieJZ5hgI(J zi`>l`h=bb?mpgkz6$9&YF<87tXMWqh&^b+k`KjKi<6`@nSG&2%PWc7VvtEz;ouYGC ze)Dn=3@PLBE8K1CV2)C)0;-z3-GuZL6%-{@REh(}>|PI29FzKBe-GX*dluOt+@B8r z+WwAHM==rEKZ*oG6%|9Ve}L+9mlBKK*v40??_{mEUIGmGH;pqZhuc%?z39kQJ3hl8XV1jk)5Ms)(=TG(sXCw?>Ze^HD%OA|Y#6$#C5N*?b zkw8#4Y>tr_!W4C)No3)1ia8aQiWH*@c{q2jR6e$IAS^o~2?3`c9jcg|kvwT>;<@pp z-$(lUo5f(UchlBnJ1W0DE1z7Ej~^Yj_;s*^qZPn9*)RXab&xT#8XAHI08mE%pU(^( z|BFRN=>PYb;XmiF9F6V&_+T_}_Y zD97|Je|_AGX%rK$i;;n{$ZkJ<-FZwE=8h6(FeFv*X4`Yp;2mf1H5pHdC79< zm`pRz&kgz?g)F7ZWm*m_c@|M5kdgD0I*QFYU%xUp-UF0JN_s4Y@ta3!WxR!zE9D(| zeK50ti2jn)>pf&|O4F^=JNtgNADo!#lpGHZ>)$mw+6bmC+e08kWi@QCgG?iJ`-^!0i15`}D z+%}k#SbyP!NoBVQ*9WS^Q9_p%;rWeFN)v{rNWQIcvNy0NXL}ebySLx7_<8Fw)p$+_ zk*5OS!uTj^g&GyfP+0x_Ku$Am)Lm4yP!;%2iA>BGSLW^%#%gJ#X`s2LtQq!j^(^AF zr?!&;{`I%n;4Yx%DX1c#Qh*kj11FPHrDSC2fcE1tereo^4UMT*5j4S=R}mu3ij1SrZv#}(LNk*7pL!h?L{EukiBmlwOwi5t%uL~hU zO<^tQcLCp9veRkohY` zEp9=JoYQ#E5<;A#XF>SD;y{_Zv6+n7d_uEYsf55~qnJx_8n|xsdK4|f^10z@S_L04 zCjjRD4;`g(bu8GhO*9V#U;9_#X6UoFS8&Td`I`Wo8V(t^tG`+yJ%oE)msmQ2^oJX3 zw!z4wA(x7P5}|_aWnCow&xY1d(*ECRL{JaModb4`hVBrunQn#x9)8jTf_@Wbg%)~0t{1`G>_Wu!yuE}#q-Ec z5KRw12ICv&7|1tFVEP93jcDnkr<2hGXirRxvVm$PZCpR_UJAetqPB_E-D9(#L3GU|{R@Ns-?(lM? z12{+G&L%EJ0TEvWa*1mC!)w24?hBpn2Q|Akc>~jDAuQ9brzP9%k=d*MCfL|!w=1BN z7K4G2)op_`uI*dTU-nVfT`hT+Dv)OuwrG9qFn==q>Ifi(>kXK;%OhaQ>@J;C0~nBJ zlzi!ci)yT#b=qqz-U0<_0mKEaD-kr&dcV*VKnHk)(TWsrnTCdG9fY8l0Jg@f)QeNv zxK+KKJDfAKK!DA`(#^m1-tsYhu3Xq|xjVOQ9d^-Q|2ROkg~O|ftD$}r_Qn$guTD5j zrbK%Sje`7S0_;*q-#-;)L$1sa^R*d-XTJ+Hn;k%xI9nM?xC4fx>5h`fF$(!3@IS{& zBG!$E?{TOPUpfNRtlS;&>#O)ZLm%gURO!F$tR~|d{A@6_h<}Nx*;~MK$bC&N?E^hS zvKr79VJxHN+dFnay)?5{lB$rD^uJ1GuT^T*J0pP72P8J2=!GLpqm4QNN8um`6-#$} z8Lq&Dpn8MS9{Vk?(kI*ZO$18UMrhmU=m%Wmj;M*}67&O+DPY{wRX=2QFQx>~7MjQk zdxgUPaysRj-j$wb%$8?>|Dlfu7%9M8-{om}6zlt4r!LN)5QXJ9LlqbF?(0BZ;(%NG zq{5+jQgou`kK1Fq_~%N0$I>-lTCfPO@-uMR?A^Mt2?M0awWR^P&<`4&pX7$+b3M#? z(kAC?*>$Wk7xtfd1s>&pZa)7jR7m81yZHzk+L_pxD!W)3TMPeZEc@Rlu{9d7|AiLP zf0vw1tUWYv2nLz~2e}i+!9JaA2y*O|fpIe$vkaHij;H1HjiB{RJXo_SYMvId?5Zh2 zNEO&rSTQqZ(blHQOf5BuRyqTxwN|$f>sysG^SqoC2VAPSwDmyA^g<3|-OO?Mt?-^DCHzm6kWl=}w=VM2== zO>8ik&XnNcLb#OT?%`eycT!d}98xOhX2-TBK9{h|3ACTXP|{d;TRE2F!Igdy^)jxg zMm8!X&cJZ9C{J)x<8mb5F1~Yk-(+-oX-Q~j#*pNW@Q88rO2H&6)k@)iMrf#Lsutu8K004!sTAPCsR(|{ay$QmHVrJ>SqeN-ryk85|4dQJ$I+2(akSQpp zoyW#pLz3iTnvv5w_a!fx^N#(K3&|>z)wVkAYe@13F2wZI-It4>=iUZta+aCmi99p< z3eAK`sN(GyPY%JfM!q?=aLV~n6m(dZ}<(3MM#7;P=t#6bh1&|zVANC1S- z?phP^N|s%7gGPZFSJ_bmQ2CHjjHyQLp1YEEcCzuFj)I<}vcGD*P!XVvFGHGlt)d0L z^G{g{9u~8I#V9M5>_N~rzN9UKxk?YzKC@jB!WnK@l<1-`=xkb|vktGVJ>=h7mtuGG zKPKZSy)l;%(aau{1GdZUdig366t4CWFvY>z8!Q_Qf`ag!uDghaj1)TFAC57liZHGg zE=I_n5uu$Q#Ph>9*f|!RyTz5H{?ltlhqxfCM`SE^!)kOV4P6U=hi5e08dP_b8bqgd ziyL5XUA}daFc7k}j%!eBjNZ4g*bmVzl#pGtLEd<=dcqf?u94=H#!V^tc`_{YCLW!Jl&{>@|`FU<3<)MGVL_G4GKfV3@ZR*1c$fd z?c~G`Dtbkn6eOG~Lzz?VDZP^>@5Lb~r*L>m zm_Z$|?b`0~LP}1T*I9O=UKuasDp`BE8mRGPZU1G;mTfPzOIF{`zae{?jII&eHuN@^ z-^{)Fmq(7OWFZR|zUPmIi7-3MG;t-!k%IwS4CGmTVgB%JDjoY4Ftl}t{LY8~AO*!8 z7_;3NJ?4C6fa;#l2c(Z~w}oMH0s7qDU~7VUBsYA$p9G<% zZI?g%`NCvtm>L<9xA0bad3CkjX}%A26+(cw@P>k4C`op%+SJe@&C6SPgOOTy0drnW z0r-J}Uw^X>Aw6~8oPWa(sLh+ZHb9O@xW2NeH9SwIEQtk?ACS9QUl{~j5QaE4vq5uS zh)|@;X&!6BPl!;V=I0TaW?`I_&Y{H7GboMn?PN~&C0=RqW<*|YW9=n|mdQ#y{Cnii+Do3qM$Z0l2FMfOxAey6+uyYm zZ;~G4t{z>oz8^gdhJm?|+HLvv$BAUDgK%Acswe-xD7)hsrfTZDX*7!I^iU^jn1i6+ zeR=}-u?&kJInA|oy3TNzgFMXr%<3U%OZT_}zCyqV>`L|GS62c3-08ip#a z(MGj@a=#hf`dF23HDfCqo3{g_CAtse9!`unhD1oUJVpN|a6s^}oKWkb3d*WPRWVhc zJ&W2=_Whh}W`)_r@#k8UQ)FF%=orEk>M+Lc>XNz5fOQa_v)F)RFul(2PjUQ^sLVuA(q){Axr2r@ z-XTsJYgYNH_X{TW63y)k#iA4@Yu>c9c^v_gRp{nUAtzm)^jCtcTQ1iWwc~?PP|X!f zA4x zR+e%NtYrwvbgPwmH3W@L?3iYqGISy4fF;+%MRIjKn#|KYNq*vuVRRTS2M@RfHqf>% z5aT}I5ygl=x)Hj6cQm4ivsK+n`&wy`${$r~92<8s10<+O^*mwYHWqBvdvjI+v}^J% zT257%Iw77~Wejo6(3xjrr{|?;%;LB*NwYKaE1sBv zH!%;t2J5!NwH2ba9eQ1fV&4dH-|Q#l4Uh>{LW{p6Il-_$fVm^<5oGKC1Jh$~1+LBs z%ZM$@H0pD33_hp9ll?)@-vwz|8iQlDG5WIc? z1=Iua4->x;IX2?$3V_8m<`*{Klj7_{y3cjdD?{CZfZwA^3FaR1@rX%2vV7jDN{R9; zil6-=rmpLGBj^{YOaa9|D6Z?qIjRd<&|f9Nq~!=(Qsi}g^#xVZH35AkaaLY_-jWWkHyKqMaC~6NSOn74H;69mb{YxT% zDH(XpxWLaS11gqSuif09{Fh@;!1D;6K=YU1?hQ^O`*C;T+>?tdiW> z3m*2SMEM^#_6M+WI>+TpSmZV=W>I>}_Cb!G?M+c^g0tuUVC|i{GzqwE%}U$0ZC2Vg z-n7k1o0Yb0+qP}nw(YL(+?>7l=;(gsx`-U&`Z=Nu{M zP>}+-3`u3e&V423~G{ zk1|?61S>8DdKdZJ{GD)ywd<;m|JsH=>d zAISz*8J5BI+BJT{bS1T?>bW7t@{O$P37NEKKBip<4oU3_NvoRKxA8wCq&XK9`k<-YE0~;Wm>id`TuXWTfW|kRzcvZtH@$Bk znUc(=aZ0AKwAY>@#BmG#iveJwLsM{^ybTd$fKS)E5c8f>qm$qB|EFK%2QAcZ%DCHVDwzoVYA6Y-@LknXA4P;s&-gEL*&V z(jH9blQe}sq}Im#tMUy>hTa}B;)&wOlf70`5dKvSy1W_?xOd^CP^R(b)3ulgB+sXc zV3XmyIcSz#F?pbCa!>$}(8&~io~EtO2m>^E8EEK;1*K@X!)Am@vshO5uHZcLiQ<+K z3mrPJqc|6B@K!~Z$6lYoe2B!T4P2ItH2fpC*-qTPeb&xmsx3i3`KVPEVWw)lrq*=i zE+RjlUp5Q*P21So9KyVDcl^t!o?X(TZprA`a4Zxz6P;Egj4NeG>r6zT8M9Gb=F-w8 z1|0yjwN}^k%Qe#rw1N!KCml;<>R9;I(BQ}WSS&SE)Xm705yT1HF3##QVzl7onXBcQ z>Sq{Xb`B?5I)A)y&|cv`E?nJVJfhV<`82{o1TO$AN&qs+RiabS0hi|0i>e;p7Dg{w+*-4^gP*VxzyOOMBlz)ebxeDJh!{>J2 zppM$CZ`JAxIA=-^Me*_Wm$jZ6O2w>*C;&={>$x#)aJ7tK`znvNNNeo=+ z0ec_W?RF_iXx|Mj?^wFDbltgc?F&l#u^?Y5uIZ zUZi(NkB&L?&$LMGS?$o!2e z*MIbyko&CqcLP`kS(NhG85qo|aaoMl^;A3}1-Q-XsjpXic;XgvgWQS>mp3waS%B%= zz~nqhUfoPI#QlB2GGgiCHO$17D3qyJF%bPXZERm6q0d1uiA&Uxl?dre0Lb*Alp2#G zxRWfZ9knXx{zmEK2j!#ffLQ-J<jwVKEg^wH*tux_@bf^iFxWY2kaT-@ zudvwQcICmb!jeG{8s^8jG3*}|T^Df>941Dhn7KI9Ahl@A?R>WnRyCN)f3L@HCmDqG zRxy0i!BVG9u1hdWg7oS2V~CGuC^SlD1=zn52`EGOhc>`f`Lj1Yl$ktMTyrD0nJA@V zLFfFGvIBNVMZX~qCxGe4inI*{j#1ET`d?H>85}Cw-nR~^I?-Pe)n-0Hg4tNxx7H{=(Mw9UH0?UFAw+KI`#V+>5 z>YN&r$s1F|3ZjTzV}bD{83up*h1qHro(3Xr8I8u%o}KA(Zd+ZcbrnWc=t(3i#68JB z@xI@lotC1!ZFRidOFDiimrgaY1Z&3DhK(u&4O^n|ASMd|K4WjqPD)06dwxvztqip0 zGd`RKT?=1Y=sL8t-t{ZWAcZ82l-N-j(=QA`g5YH$vr1{P%bW+A0{X?16TiHa=fh2_ zSm!zQ@dc9dr@pH#s$OwDh_=+**1C7j0&TEhWyLC}LcYdNI10fT>Lz-_SFL#Iv%W{h z-qanCt|ut0A#TR{$`qu zCJs?xBHKJrsj&Z&!7$BaDd`G?eh_K-+z&)vKphF!wLhO0H>Gs@!!6CkQPuun)HW8jMbW|7G?`Ryu^yXg`y`~ zV3J0!Vkg}k%MC0=_-HjN5Sa(z*X+B7U*iFa+8lq5TkA~MRB(^|={unxaB)Iz(qRo> zzd%8JUYk*ysS?|PjfC9pt>hZ`+PD7_}TILVjTslT+71mv!we~d8_w-XbAoVKhDSDONa-S;5u{_SId zQN%{RmKbnE5G(79zNm3KL91nm-nmq?5pcfs8{%pRRU^5#& zc&Ob7z25WeF~ ziCwId^QEm7klFMsa?q^`z^sk1-3Z#~y>@{&3eLD)r#>rre@r^^w?xu=?K+mqYv;3;tU@;s2DsIsT93ZxI70ga0mh zXQ}>CLs3KYp$8S}r?#c@SD_L5gB)A6NQ@S)Pe?{4DrHz&WSerBUTN*JFcpmPQS~L9 zq+C#vy+E+rbBEBF<>|T>z)R#$LE)+AlAUIDJUzLk_VfAl`!CfewiwO;ps)IrY=Ca1 z1eX4|oZcZBt zySa$sXc@^SS+K$ldZo>v4OSS-1`Th6@|-LrAzDaQ%~qnmq~0)bocv2iueBro#8l_C zVw!V+dDA`E@^WjmQ49=d6vxnZ%ViVI&=T5=J=+YD>?%JrACDKieQv_;gbr8JJmPPj zo-hR0fLn|~t-C-zW^XR5i(lo)JifKMFs2TY*WU>PZNt_@T<&CN1ev@&Xg*Rq>Z~zF zZBC-w?8{2l-}!skVp#2#{VE->Bz4P-G0WoE`KRIgMuP*PY>reG8O;Sme)hpGC5^Hr zSkfg6ca4pn!UKg)%IhlrNM8PBj5gVqyTnCdMSIGd#Ij>YO`G>(Fc?XV4)&S@eVnLEaV_V>)2Fz&6&=qB{UnYZt@a zj7NFJ`&45ViUYi)R2$xM8V6ywx)rqjWfI!CECU#|OMY)XfnPUwLLP zQ#@v^U(sMf(}{sAK!7Kdu86wVu|EYj5?rVFupph9YzU~@qKneUV=ar;ah=Nara=|u zeDOsCCpKF|w^J;CPmmu1V+>*V1Mhf+KNlt7`1dJhO8$0HLs4g>RwmQg!EI0~NP#g! zsN98OgdQB3+H-kS-RGqDlO%p>!`QLN&h!6mQf&hh9x%GZJwZ8SRFs=bux5(PA$ndE z+?G+TKcTohT$A&2Xgs~;Z4;g<49k$Txw=p1x++cNk>YGp-*&~5i@z$Qk7S2 zT1wAb!2veOKC0Alg(fzUK=_EpSUWW8mY!^CG=ZY9xYv}8zqs8{4UxK>g>(*cc^813 zi?KmtE3guZLh_9)uZtk<$eVk>tT*500jvJaNVF0%i}NZo{m$>}#|=k|D@;50Jx`>hgfKPD7MpBD@O?Ef zv7KIWL^WqF9GtxnzOLe694HZEh-lQ<9u3v5bBrhqZEvlgd2S4BvMG>s9leu#U=^fv ztq=DC#HLkZ$H?{(tni0*hWMnTW`T0YSz_N86qKhoQmND(xLYU~Lbgx(2V%zx7@jCb zHvV08j1M4n&T3U)4`9Z$-R0)bX8mgO+b`y4P!=%xyPg#0qXfo0D;v%bdv0}D$ol)V z3_6n_C=6P$7MR*$1iV1LkJ`uYlho<6?l^{CG5*nI$r0gWTo*@Y1cXB!vzXibmppp# z&;P=X3Pe_#xPkuq759(V^uOKciT`8q`ThUx>-L{zr%F{zeuEL!XQt-1KpBlBbyak$ z%Aa|bI(R*rR|dra<@ep_pXP;m+0Pfe4as!S`FV@D^TCl5pJ`WZih^xCIL!O`R8Z}p zx6HxMXcMBCPz9+L`>>}VM|+*I@Nv8q81wbZnJ8uJrRnD(7SJPdvy zqC{)TtXh{4K!Y!)HRM#AT96kpsx(o;lZnbQaJ9={K8(7bU_|iNm{?^}c~U$|U$GNv z;}-APgEAP9FLQ!Y^pHasu?0XW*sUov@-t{BD`S;x{}xi8Hr!aIcjw`S|Lv|^G6 zmL1DjDDoUGV$LtWeg`DA3TDH(C< zK?=kB==Y{g9@gSAEV#9*16O-`6#2$m$>;9@aHT=%1TvI!+Ki%=&ur1xss2BK%hugr z{Z`{P_39Y_W3CLZH=cDevU%?3s1NGFk%+6#D^mQN%*VO83$@p!; zf^u{#NGP0yF1;1};5>}JXe2up-)ba)+1nzEZ3u&O^|3Tqu^~JXa+QO7*cO1dDf+^f z;p>DD$opDRZQw(;D312@fw0kLmjIUuaq_=H>~raTNZ|hnzeoR4O#k~;`=5gZ&;RkO zreI<6e|JCEfbmNFPYvXlOt-riR4gM_NXU(Z5HJ*^0c`mFzaA%H;8Ee&u}RW2jz@}d(QBl_-?Z)}G7l|mzu?+mo8E42zkWTc%bs@2r=Q1? zGdmcIZg--^iYhWXYahB>wPtG_#An<^mEq%C9CW1AQ@raPD!uC0}c zP*)X?q~G@HEXu!fn(6+6&Ix9L&7?2oDzEQab0b!6k@;e?C#OE!m!NLrOP-!S(@59E z-NBTmBug*PSe!eM0pw}!9?U@lSKZMVEwegT_JM*l`7;UcoKL2OxrxsYiYy|rHk{CF zbGe4?9+K!!Y4Ymeag7ZcXVNiV2|q>dHkKDeXqskN<^$PSZg%lxo;D#~XSQKxVlN}h z52HW3v>;9IHG?uJEysrkqD%~&wZ1n)WUWoRi6L^yl@Q=h!D6cohD*7wf+LpgRRG0E z)$pSN{4Mm5qFBwvC!r0|KKvC`mc-#d>p$21UQdGZ&u+m*1)bgzw^Q-tsu9diAsOgJ z8vNY-*HH{0Q7{a;dw1uSiJTX2OL0WnCYjTaQ*HG9a^F{xc@(N%^1&ixXorUeBmP06 zX{Apf-0alcywyXbwoX+~t7sK6qp?M(B!vu&(s=GofA&V)t(kb&Cgnjkw)SVnuNqxJZxbDgUN8Hn-OY-A10i~;WZT;EDw>CmQ z%*@tY)cw0MXjEuaWdbBLHSYA1{z~)7#wI;%I5*kpCQi}Tli=A_o}N*mRt9U=6NX0( zlDdUXwn61WhtGP4_&t0dG+m(Dy!7F-F(}7lsCank#uXnrCH02~Sd>05E~B`j0H5s+ zuNL{<=>%&dV&wJ(93MmGjXKbFAL>atEs~SHoTSq%k99jJ?Pl7!HWJEAx{NCRUj+B>#q)L4n6fI{is~)uT%fqewcvk?|@v`$z=h z`+etop5EtXszKh&ksLkC5~A}g^f@<}lb9xx;p1sk)wMM)1tI$gLkn?wR}4r;N>u?{ zUNlm{Q-$*`U3JRg7_^Xx)1QZe$=HuKlur9p2h=E_?y#o*qxQOv!3WXWXY4DYm)7D| zJp|qx@4cJsvkWZ`;!jgPl;$ZZ2bU3%U@sU=KkT?2$ksI(iJ(UM&k(!T}dXWQAu!M&ho$-BsB}JWL;?y(Nf<$B=cuBs` zW@=&ck;aE+0zA3vFqgmrxiw3#NvD-LN+Lj4JSJvEt(PKprGJyxCrLI=C+e8^)--l^ zLGe)^4^@(~zEsT53P!XBv(J*wo9xA;O)4A}xvo z6Jx~Z7Nr+pN3$9Az+7}ESVYrU%e~x6?!VfKGbvau9ji>d%2e3!rq)C+-aoK}{4Qr9 z>>8#Qd&TY7uUm96K{yjL{?7hyV@%)h2cg0x*>ZOD;KeM*{0#`Qp6#NR!4zKOlo(= zeB=;h-(>WU9Je1LGP{mtJA*yXyU0M-&UY^%q*VM^%Cj#sxZYs-_c22eM05=h^M1`{ z()I3Aw6wH1DyICtC}FQfogwS&$?22?RiiD7ucA0#=<|npe~gkU^}32%u)*;ls+mbf z2Yo8cxzNaxLQQNdG!g}?lq2}HX}bI?G;JD48?*nteTaKrca$|A>oXs!OJN9oZU=O3kEBL7vL^GTJR4TV5rTX` z7c>`o_V+q#f>-2adI0vi+T%pIJG6j>X`aXOt@n?1FXQfwVLvrlLKraJ!@c zlXi4$?&&BFDYs} zO~};-QUH;`U&TE%7*nGiXa)SAx;YY%0P+W{h19uh$C|#iRN%H3yLyx8T!1jUWJ=n?D_gblaPTX&EjnY!Rr`xjmjeNeFOV!8JAYz^ie=Bgd1b^S{ zoKjidqO-laj5p_w+$^YTY?y;j;cjn5?`Jt&xh?t1f32;mD=jLtE7KE|cRp=8svj-? zO>lcyZUGB!I#H~1Cg9r)(bLoIz#;e(wTX`Hlc@4jrTV2>g>6vw{PBl_Q+=PINkF<+ zbHG<3xoe>*!3~cGjapgL8;R0WbI@>5N3OahEHXlpJaTg$`9!`PpWx5rRqF!)2*ZV5Ocy%4~vN(QA~zf|F7()+_dce4|H z?mybd5P`ZJ^Bl7o4P7*C0AceyeynttVgr@TsNQ@Sa9Zt&V6$_H(!+47$mGPxj40f* z2)QGGs~ff_Vu+}gpwun4-kluS6_(l)P3izra3NONCmR``F-Fo7>t!QKP+*GE9W>P% zP~ckUif}#Lwd(hAOL+aSiSx?z1Ggu~?5D%}f_m*CPu^xx+hAWS ze!f$|pPMvqEf(`$`!%%2w7ZGP-=mZIV3npoG&_#EOpNoYUV2y> zPHdhlMvBhUXZ?gHt=AbXouAr`pbDjk=eexr4lqP2-+Ni21tW7`w;#RoMsQU`IsADK z>IgL^Cc)+_1lD!}lUQ~WaO%i`OE<~2Qo2VXsVLB-ea`sGx=Ziu=acTV$|U-ChH1X9 zMOB9gNN+TwtiJbmH#x=A`OF%KvqTwvDym7h97Jaxo}K|617hopOQ$mL*<~R|7&7dfo+-dRNoHSf*^s9@Kq3#G}HqFcST68au4%RRj|O|^t5kN@VTEtsmikDS~H-mrW*K;JNgv6?XPkwa&t zMu~>viXgv9h-eAa22yLIy?{o8&=x#_(P{@Cvd)~N)43uF=mLKMU8gRbpODK$adH^F ziQ+0q!0~1iBsk%Nb_1sG@sw86>LrA$=t9G4|KQZ!#J`V4|I(G>o&CB0Yk`rU>C10) z=p*;{6NusfCX!^c7&+@CE(ARSW+JqIX?*2Z2LY#k_l zm2tEScfr#iBD3B!`2`}1gsu+0Lo5L4`JZ(MWM#G^8p{lh3yH80FPE%Ub3U4|Btgd( zQjl(!C0&D-wZAp8O*pI9Ni;apfIG~`_brz^ELwxI-t^FTm6rO;+B&r(ZQ+7G@a1Mw=zAkN!!y@*Qs!TEJeXeD#uqX2{gN zb5!AzNUR5+TiO9bf-LUC-Q|%(mNvqZFBSQy>2qbJB1}QfW$X;LgK&0(vl1mn%?r$; zqxscIXk4C21hGk*qD}oy8QY}(PAlQ7*?$gB&myTl-AKQF)sg&Ho#^s^NV44j-*uw@ z$g)G&I?4we_gQ**Yavu1eSTf#-k9h%SizjdHZCc^E;hv+meTf#|01D$V?gyQ!zJv*p30@7;Nlj;xu&PwsV5S<;5bA}f?k7u3V7X%iJf zw6q*_56g{ta4NK;56bpy+2-!3X7F42F7;*>w4WIC?9!5~k`EF9at&zz=#GzdzF$hD zt=d&JhpA=`)6!{XcU0Y6c{T7LG=66wvm{_Zw&1MCWHB@KN_2X)1kta*e)Qn&$=FG) z6vqK0Ck|X7do#MAk2v3d4!uVRII0FIr0$N)%78Xh>oAL$4J5~#Op^xbtGbx(0R7@q zv4`(RIa*q<*+NHT=72~mM)sEb;-|f7_%Ac=N`VK11noKp@>N=Summh`IT2OhaWA1A zXee7q6ikFJDzq7=zCNIFXbobOc<7Hm=8|y;ov4wMiBmIszpQ2rr0(bN6m(Glz!|rG z0RZ=5G5@F{dZljAWg+9`K*FMmQx39HtKMrRBeLyeXMl9vEqtokYvcw3h-0pIx5S+r z&^RxIdy&9yz>hbMlggi^2w?cKIj3g)W$q~SwK$?dC0UpzeFG+xnBbXF@DROf{x6^V zw}r8#8v_2E&w(MefFaF9)KKDgoS%!&g{QSa`fX>O%rz z;*+oh9#6#bPX+B0jC;w#xxSZ#D>wy(!pKuwFOTPmr?sMyBaCeN!DF-UDgK2J_%X*J zLBVmmn+Dq~(yuZ`>pWnRmDI$43iJcdAG~NWB|#ZHJ^S0QM;b_xu{ygtegPW;qagw& zc2V-LI^<xz|z4_%X}6P_c~WJb1)znuJvd5K5;p9&<~@s z9tk>e%E~{sAbe<5e@UdkLwDvD8z_3X>OEwL^@mRWau!BU`NmXAraQtGD2F!D@1(d( zx<7%c@c`x4BRjNtpZv+9@hRMNn-q|jf`;3;tP6d@!Ay_F^*Mdb(8|w>p6`CVSkb{F z#B&t^`~0ZmVpu*U+PJlGZ6Wa;pcM%Z-#K2z(LZ};tknuY3ZtRy37i>M`PwFdBZ&Vs z@P(#W%inHgivxe=m27r~EDM4%3c^L4kS?3Fn<_=PWqgT{cOOk8%KzYi{ty=px(_jy zKZMutBbr`mT9MxXWOq_?+Tu1eL@a2ajzt-zwa^1kOikRpm221r& zOX)>Lo>`3}Ie-F&>DCRt_GvQ-RXsFQ1fFa5dN3+{Y8bJSs!^j`K$t5ZGQ%oNH_A`+ zu1?#WrtB9l9B`V+7o>tJ<~GCGMv#J}PQcq}@TI=5Z~c9z*^P-bp=yD6MbjgjWgd9X z_SO|tZUqWBndnvmbEL6#*GVvKLN2bBQzyQ9Al_vhwU(1BNxv%N^Bq>3iy^tP&0k%- zcHUmufIm2pz_Qu?WMIGKJIVN!P^#XHfq#W}_Dzu@M$n>{-8nTDG(-v;;$~c)QO^^G zp>n7fRv&^T#WXl%3IU6RV#FnC7G8w-9D&t6zSIo`P6YOj1CLnIM=LHYIqy=Y ziTr>LvNTFS%z*XMCX1z}dw=R*C)GOPwYbj?>{K(TM9G0A?Y2RhC1pv-GUn!1%r6D5 zSB$X_6%)k62#!a69}hYu=h8)uJuD};luwyJ1)Ul;BxWhq6EmHfKkeWZnjZuF0OyuI zNMB@PEED?F>uD)H250D(8N4+g2c@B}g3>e~fwYPKo|I9x*bonY#A9tjuqa^fF%{(I zht1BqWz{HLHCvvtG8k~3!ID4Kf3(N(s{A*aGE(!#YiD2=PR?EB0>u#XQ(rab2NSu? z+}HDEJr^3-UF*<{zEZ_X!m>!v3>`w8R)mkk z8`p3AtU2wf#${wwq>J9mLl;`1)F$1bjZfO6y95C0U?_2t6RE)w`=Kc>Vo!JmOyMA` z+CjqR8i{_cHi9F!k+I;l%==o!@D_5dXeZ5JNwRGZE0?dFmZE_4(!1ZEP%`w z{*p24{YTp5w2Qes!&AU;Wp`AX06{Ey^Ov}AMmk}{ki(G%FJU|ZnSr~i$bj?mGVGuO zLZM0(7;)QnTYmUCw$F;hE8ppyJ=QCj7uZ=Wf19HJSrEhPT~jV=-2noq4>xN^A%~E9 zolVx17oAMIVf{X56TaRCYRR&0FbIOPZ#O-8vwl-N-+w&_66^^!Wmf5>f8C==p zz1p=#oW3W7Zz)FbE2Eca*kbV0TdIrut8mB>El_GIrh`EBe$18R@v@l_IxaLeJC&xW zG7fvrMTpBu+pzeq-lVrq-knDS7zjV_-t`!A7c%lBscy0UIScuUd90Kw zq5FUzyI5j|8Lbk>t_W<6pSg-6mYw}zqM+8$w|U0)>%O1|1e-o+ue4}u8Y5Z}m=QM! zc#`Lvm#&Qlt$=}3=z84DOGYZFn3YBb?*LncuH>)?EESKDn$-rO+?Qz~oK0(rFdA)+TU! z14`0X6hG39^dURedf>zaHCfSc9>PoTnh88fQoxG?kIA!C0B($d^m3x?bY`==t*fr; zi<-QU!4s82npd#%wUuOe3?J|IW{Z1!Fw>m40Y%Kq^L7jQ8pK;IKm@Mm2%u#FFv~<; zdnPL>`1jo>VXjZRZB-WnVIY(*&+RoAN^6!Uz6y7XEkL_@Q+P^W=sY4q4GEBVts)** zBK6(g>#lT9HJGa4*3Sr*9XiE+ zp>^A8A%3NgH^csGgMeMn;jXYO^01R}v8~^PtR?hDtSn_#r#zQxl~NyHLiL4z%mFjr zB2#5yrM4)*p5RQRp!0P$#Qn}(5LqmoGG z@_U14d;)nKv!kP`<+iKbP5hx zj`QZGiSmwWt*Z{J7EQ*Fo|lZV08pXR@7JS`Y1bRxlWfOp&L7X|+kWwom|v+B5we*6 zMY4C#_sbIHe>{!cJ&mkB5XM55Al zGqRcY&;glQiOTL^rYq;k$;KRHv6?~@Ij*^%_5U`7CvmX9;yqHJv^)ZutjR_W!xjvq6@I=bT`LU z2n<>njnU~~!WDlAUC|>gM!fP_A*5lb&#Q~8)8||440cHJMP(&od<%M8+11TPDvfHh z@&+b+6d6#k1aV!(PFie>C=EyhV&_sljSe}xZHq!qs|xSb$Ojo2q(}nyte`RuJ^eez z<)99wbZN$_!%0Kw6|+5H{C~kbRHNcBEdO|xc1KTYWZ7iBs%&(65h%Q6WATi|R5cyV6Ww+kg^rneMjVW}E7?1BGmbdTxjOo8@_DrA zc~P>aBG~56cM00hyQ{0Hy+N)HChX(B#gVoT4{jvIoijn#a=Lg_TK zrV^8ad%w<(Hi>qpG&Lebs`S|i%u=?p5Mky{flfPGCDO~Xh2CH!p6*VhgDW9gG1r!L zN{nf8tV@vFQklP7}Bz+k4KB4{_myI}Jq>gk&^ zeXQlGBV0MmdnC)||Ln0hWznGBD0q60_m`jvfBzbAs0x(|n9*#-b5(FOMZJ@K>zJ~M zzEQ_gZV_sL?~)xSa@A~=);U(~2zYq6R2p$^31TQ+ppzg-F|7#`KY((6yKb;!=$7Co zU&<3lOYe}LPj$@+`bdiLzWVaw!|hFx`D8nIXT7!D6T~g#2^yYmncZd@giuwf}=CO zZ?LGvBE;+x$na3N9%|b#!o-w`D6BOWPss)Uu01qI4wUnJQrJ75gkv+aenDio3YAi~ zQ55GYnipkstt=B=E(EdAsB0BtltL0pmi&|x>Hma|3{}%^O7b<%^mYli+M!`DVlEin zDw`Qwos1tb5!d(`WgmW;RWdUZFWxM}l8g{FTJvD~Ju^qHYvF2MM*f}VLy$2d!!rY` zFjpC2tjYNHSQG@U-A9A2tHOD4Q=2emS6@uG*(ker*`xVd*N*oI!jS>s{8omksdz%k z!d>~GwTg5NZldCv*^(vzm3}*L(k${EQ&iEUAI?DER`L=Jc#XFJFBa_=Z0 zX;+r7@NXt+Qs#7{T;P7lq`>D!#_1Py^AhgmrRA7Kd_l3V1wWIY) z05WzC`8P z2bCEK{qFu3fNfK4^3$-W%tLA5-XD{Z&cK6dF+KG^RtAYiLf=bI_Djg}g>PRl$!aeF zoZI_i^l&6&bLd91mANdK{7%q)Gc)!i7sF7?h^J|Fn_O>C5g=QXRnnKtLsg`>!ck75 zZ#qYfmh6qc>z{Tt^v6g^kc@7DSg(xp>uWo0Ox!}QH_orlT!kqPZF$;DPQ=c!9z$ib zDH>Vf!ZTAX$dU+fZuY6EFQ5aRr(AOzhcZ)f0pZr=ZsP4T(fMI$V-`!STEMtrN;4Rf zX;WaVV8ex>xCFSVGb7wcf;Ewmlw4q*f37Pzm#Cka%cnHafBIFQYoe$%^~rUI_BzCo zIWix0l+QR@2moT+lC>+zp*ih~wwn0jBN0L7Rc>w4Y{$sbNUe9h(Y8mq^N6~6=TNJo zC>gUn-d#MSnPaq;hfb5yOS_TXJl;c~mCHdRzB7-<6Gg2fhDrVKwiU2a#Uvb=AYi{A zdMl`udt|4L1<~aBe74|z{{THqm`-({+P_YG?g&MD947Gw`->x;4iz$sqRV*#FLW%q z8JwX|9+ZnW&T@KXi|6&C@=*wUsRI6%r3OAIO0ga90Vg^(Pp*MG+B4;rxqqU_>iB~t z7M4QO7OvX>_Lam1S6~4A2(dd#VdZOGt(TIEn57OCGZcO8Wf*Fz9vpMKK8VE~5H@N- zDLE^EwCeCm{4=ODze-(eKIjf=?!>K#Vu5ACZFE=1jbtjV_JC{w)tBYrTndV1^)uxQ z;-v4tuKexe{@uAbzy(CE4Ex5i_caepo2wBzFMS&%I1t0%^%%ZIBgY(CUShQbD3ZR> zzvWg9z&Xaz`(@VW`z6=SAT+gIzfBQK^@9K$G)SJD6l?pWGhe!oJ*dc2xWH$*&a}N=!gFUd>S8nFlH#l z>~a^LjJevO%CqdDkG7oU3{0M)IUsaL_!^pu7iB%Wr}0Uizws*htUt474?NVG_sMzX z7;)C)(A)vLJKhm5)%`;xy^xK2r;${|`63sQM`KAJkyQV-r`u_U+F%T)Pjv#0konZ# zhoWVb>m^C?`PG0RI!fM~%As#qN2xj`n)@27ER^yyI%akA4{RKI&@th0$M6xA0e*C7 zrS@+1m2?LC6PDYLa(fw~^2)L=XNGXkhWnM_U(oNnqginr9t`_LxS^p{R+~FAnuT|3 z397Db5ex(Q|y{1F5b53gmPh&3oeKIAnGD_$tJqn>UF5)a9H{q`gnwm3kY zMl$^~QHGsXlS7_ja6Sf=hcDF8zjsUP;9jshZav`)M$XWVt-<>xI1$;W^$+9)m>IW2 zLlJegA+hKTV;u@sS83^iQy{b=%l63+-Jr54*iO?>=mHMF^P>RAJ;3QIEUxS@QYza35^N>~?<=I?pqWvOGHZ;%OAjuv2a z_9<-ra7)mjzoDa`N?j=70uL;Ln#F0AqRAN)QH1jMMjH9R1AYhCuV8~;RsRO23G*w? z6!_b^5@Irn)#<-zsLbIMxictJkBW-+bVohGd%&D*Gu>%`>3#0|DW-9Cr6=3^bjy(Y zSHo5%sFQ^`1A4{RZrsOgh}nFhk`Mi_s99g(QV~Y@$P-i7@IUZr4-+H&(md{y7o{)m zBvHhpJ|C=^!oV<`1jkBRrGZ_AhsR80rh1W?N8Di(C~s7fu4rAkbs1{}n;}|*z>}IO z+Q$ptsF!htKV>S~BX~oAY0Y8C=GnUBo>5IC4xn;MCdGJ6H!ZfBBdbO-Enn&$Ew{~S z3*d*#_aiaIXMA)=;lBo@sz{+>`eML&r7;2Ml;b(o7rM%oZHfIRMG+(Oh%l1%ZR-|S zL(QjBQ7m=vMj%?K=!oP!(;N!OFe$HAxmWkw5*we;Avtexd-o!z@q5Ta_U2QaU{zXc zpT>lk5l@{?&=@DZzc{fB@ccsV@h8Hd%#1tJ%*jfuTo2u?TvL9x@7z%y+PVDAt5!zl zg)AHKihugg4^0l%G@oBqfZZV>8Ajj33>L@of_$=hev;?3uvi91qLesAo!xikh#hb~ zd5yrJVMBoU@Pt2MR7c?aaS6`>72Yd;-PHY>EuE9E7_!$7kx)`8Hw3LM-dtJRzay~-{rl#31Hqw^ zwp1g|=F?wz{Rm<+vlCAL%aof{zd$;;q=7P zLGl;O55H+2MY_r*#cGJundU=sb(v7u^hCT3e<3g{I~OMxb{xt59A?h101Muq|>E{_{dN6)+BpMvC{!N z;v~QdiD&6jV#in|@zy?RGhhjakvuu_yfZCTC)k24^D{!VMw0oBnDNOt$d>d%qKo|{ ziCcR9QaggbjBA~?zWKnZXv<5XS10~2*50W}6e!5nEZeqi+ji9{+qP}nwr$(C%~Q6m zIo*9H<|1aIALbA2*bh4*b7!t^t@+vt7gdZ}MAb=Ou0(-yD}@xOa)IwSzV7dHPoA0v z?1hv(5ylxq?T6Tss1g_)Lqd<2IkVZxnH#CxIt|J_l(jFWoqC!#SKE60YT0(<24hGK z;rXQE;#aaepd54woJ2A#$wGc%psXRiK{g{RT@Z4d@L{Wc;}TpOKtpzUU||TmJUhkv zP*n3Fo?S2_H3xF?Ne568ZZT7tUFOszOxief(mJR=hZcDY<~OOK&-&4NzN4&a;mGY? z(;RacGm^7)BuC0e8wYYbT~dBQtVdVT*@^f9jgbkr6WOMLoX!^z-WJRY)PwuPCfp=` zpumy(;?u#@k_$ixFERT2^?+2LXv79k`1Cr8mRZoc$4KkkMAVl@Z&!|zpr0_G@mmwc zCS)K}#DXE1Yz`{+mrSPV!tm8hFmgu@PTKYfhJo;sg)rba$hp*`{ojU1Wuk+@JU78! z-oA0Uz&P>(xx`3M>r)&#sJH3af1!?DXfM#nMge2}D|`3|=}(m4>9wYy*NN^VvYm*M z*_-i-osiVo&&^Q^C^Q76!3;sN;;n_(RPC2I^vZ*bc&@8&w*gemaWkc6QjQ)m%R!i~ zv5*7Kss-u#G_FaSDNt`8*DQBf=>t*i9}$W8GaV@3EqPunomH7U*{>r#%){0q&6^^Q zMCah*3-;5i(#?<&a9$`uyA<1Pe>gW4p?9B|m$aM( zFi12Wxg9Bv5N9jzgBDg%qOR)MDj*I<*epQW5zRW*(R-8OXAE~5zEI|$$DMhA@D;Z5Vehj+{y=gLr+%>lg-3_l2 zoIJ&x0t0{73sdVxD}8D#o+5+JZ955RywR_>tYP>)RX5$0xgu0gGYFPbp#bmLF>96V zoKs!HRkFa`P#C=n(H(@A0XYHA_;{DDdUtf4GqMS3orB?5;u737Px~`4K;7UKc-WD= zt@66Z4(xFI%~p=jJqB&*e!oFC>yb7W+Wu-X*M4yPVb`=pT5+f$CDga`nOuwelM1xy zKt`8J)B6ZwS%t|M@7pW3$tahGMG2_hUL?7AZ}K; zI>d#Idm(KI$NDF_Bzm)NC3Af@a(xxF-nD`-R?*`!fZB2X_zT=|d&$a=J(O%=Yv41E zsI2Cdi05;Q`RZP-==OxW;pk#}>aRbikT6dBDv?LW-NeQ{Y8ISQ4xExiSdb@=z_n!Z z4yMSG(q%8}vk3?46I%jjFKH(64WtbuEfhuff(}VJGE~1!sBLP!N2U>CMINRvH^{Q( z2q@Me6dH4ul@C#~xL>)J(@G{~b3^y@pc?+H`WtW%Jha?19Nol#o4rL;&2X{wh^IL_ zM8w(+m)`@g2PC8vze`p|SdWN=)LZzk|_K0Fse z4>#wK#nPL?M6AN;8G)*(w!~)Z13mzqGiZ<>1)T>d95`hkXKSzBEI0+&<=6cg7sm9Q zdH1r`VYmMv84^nTU~MH^=;+YP)U{^`S#RItJ&5dn1QsjA7q#;bzHph}MYZ9n!aQuw ztvUwJX@Kem`+>vRRn`-SxfdB98koE?6tGm^XaqQD(_Z0JS67o#~m``8oRdLFc; z;^T>*E{#_!QQirKn%@wZVk z^955Me(1{>w^x7#PMNkrTZhHQ&b!AO?##(PyKBjNfIYa<1CTwNf(6f5sQV&K&W-+s zV1iJt`O%^8QS=Pst91=)+dmmWmjo%>Db%G2bd^|Dn6mx{fMn>nT{(JaC^37u^ZbFi zh+7WVQRW)Oc0dk2uq-As<-hEY4}q(mY=~z25pcDY7ai z_EFvX>=fn3*_WL(v%teV+JF-O& zY4QtKO$k`Tm2N6zs>nMZtG?UPabUys3{xwdEmrBdH)wLAmv1mPu^0Hx_vA6cqn+)AheEVgCCTuQC?4|0|nDBCKF% zVe9-~p+q@~vhsrh2tHa=5UPU8Uq4`?GS&BmV#3R0BxE8nST`ls`VGycC`D?&3E+l* z2k`gfm}XIIcR8-I*qgfScI7@FKc8XuA-EyUflS73(`8XxJzbiLa*v#(J4%-tgA_bu znd5bZ!I&7TCX>+AZo^W#T~4X#WdzX2o3GKgoNYSowd|zHQ4s2yshW2|nn$UD8{F3w zcfJbxEnJ3M%}5+;c~Da)JROWvq)h6_^0j=0$pqmU;s-^b7>!{u(h4y(bG!HBi}bg@@L;Of?p#mW0(k@+B62S+gZDH@&c!bLGK(dU3CrAR7jp1L zOU7ov%&|;PK$1b0QFw)cLlMVv2+;5Wf=hJuEcDCSy$R{G3qz)}Zm6~k-C ze=t(!=!2Q53t(2Y7xz$K4HCgwi~K~Y4{;$dzEp@t=ZuEiiBx7e!yhH$+75j6Yc*1$jd{kn1Pz0Z2gdCk6-?Y-@XpaaSzp3)vclrFci zq}9Zcv0H1Zt>W~sEp`%aDy#Mp;>e2`T~7T?P!}e_i%6S^8zoxV>>9pq*hiG%Y8z=9 zny~lG>0h%3fuuUkbMRnEjULASR|0}JbV6t%+pJ?1Wm59>oLpFR_fRxYPP#oB(xvct z_;IYl+eEM@SI34>RP!j9hq7<7&|*ZBm_fjy=KR)}>tMzTXAX>;NmWf}*{8Z&vu#vH zC8mlJF40naDfn>S`I?yg!~5bYhiIj z_+gY$A1j;=c+4~cV4;5igxdQD5eDXK*J3p?w--?w7*U4W+f8@B-UAPII2JRsO15I^ z8Ig)WendztJVA?~=DMxF9CbK0M=@5E&{f-5S`gTMmY1N}S?i*P(?ZrN%6}fUE{0^M zhVILIyK-`mLd}I3o^fJ4G{+G_cRj&Be(EnV1>fI2k~Qu4HngITADx+>EyBak9g$)F!r#S_m72Z9Ih%~pE?mY515{3+8d3xpJ$ zZ>p@73nw?!_0q%=olODRcQJNx=(duN1~u;8-KW0Hi6(GMjY>h0M*ZnRZL}jbnl+Ql zoVz*BNH`z2e=2#DjbcMKM3&Es*en^+>LW!rAtC}SAY~0KeUCe15lyK(K?2MTJy;M~&t_)C>lp=aKUbrCLHk+GU6gF+K?^#jPI&mbo~%ggfD7LD6~HbD{jvsOouvrS)Gm#BvjLl!E- z-9M5H;ACvE4HCL7 zVzcd!2{sY-RH%Qs1?#3eRF5HR-x#IsbWmVlWi<$`UWo_mLyaIkT!5&_+$%u{eVusM zm$u>}*WO$Sv^dRw$Fc1wu>>;#PZe7m8=R1Ji0t~tw~Wa>JI=QWi`jAr3u@J{d9o~4 zxyPy68!XC;Y2sYpL@KgDHgV~6pPoRfWXaezIkept?sp0@xwofTSVyv3)pl)_I<+30 zE6lMg_Yizxjp|d7gOUoD2JR$-RH@J5YL-Tz1P{p@_GCiIxaiOtrFGhYgRb zqD@Zr8xz|rSu$ByMyD_*ZhgH}L^->;6zOy;=|ZOB!ApAtK7jrm+sZT8SU>xIwe5R*4KuIFfh0B&DH z<(2cs1FbHvpuMufK`yh=0Yh(pVhDDdv+wSyxYEO(OSj$uMenHlSqkvIT2np`GvAVa z(;bqY*{|hZFXqL2WR%}RUQRfx*LP-=k=Y=s*Jo$6YIYy(d5GP{8+vb5T7K$eoQbKc zZT^oley`DCmwV2YQeEsy1HjmmpWKzt+~{kH3^<3eCbA7tjH}@i{^lE^uMFB;eT5w2 zGFg%&)-*z_E0$B$h3E1Inpf7AeMJi1s0uuV1~^Z2pRd9C9(z_no!07r zkknjS_amNqDQvl;$NId6=eEYqQW8O1mDq*NsAX|3^+&TFY!NdA^)icTKGhqO1f!J? zX~|21BVubU6BkKwh{Lb(;Y)GbH1gglQOeP`JZ%=k0kAm zV54!l;Lhu(LDWGWQ{kL>{sIh8gT~ASR<`1-xmer&=~s4P^D&5$qtZH~R3-8{)VuQ| z5wmsriie>p;%g2%dAjkq@rj+JP06^G)+spjJa05KsR7qH*#%v8=QLWZNxQyss)Uzu z3e&aXGb_Z6ervlGM+(v~a=Oh#a5K}>uh!I^EM>d4*(3pO-d^hB1|6EYnz3g%wdCB< zgVN4GQ)F#YrIqGZ8JBa*xQbZALOQ4VuX}q-i$#=@gUIG$9u#>tbevhA`B|uy^?QBg zg7n6+x2NtTb)VS@Jpit*m9+XZ=9#X~OmwwSi=v%$Q0cF)+)5YaA|gI(%HAGl8|O6{c%6y3=x2kRc)xZ;h}bl;V6D>kK_I4rB;mDD(i zZPF!^6DxU*gL9%;k=jm<$3Jp~PcJ9-ODQoiCrfg4TY;I6qLyZ%8407u*=(ypkfM{S zTD9UCpMulRSzK3OTDHsC3*3kHX&9^HGp*Z1ZJmkPj01OrO~rAPjWelnl#8FneS%o& zP2!|0Obe_QjZ5|XL+BkVr$DLE3_Dt_Q`f0i2+2>zCA4nYg*9GbSwwCdj&0jXKQJbv zbX$gEtnDW`(lJ@C5k!|st=>`zD`lKb9v?{=-kYhPDzH0J;-{D8hfo`_WyylBn~j&r z4;0&_R&HAlm>Y-xDkSIdhm@K$EvRKPf#+~)Ph;GZk)?H*1XCKa-GQYOt`>3J=0iHq zjc>Q21Y-FRhbNhg)`Gflv#wd{^Ss&7FPqxJwrWho{$i@^z2^)i;x~?qB_N-mQ4kn| zA7qs+6gg67)!KXxsXTP)H?5u$4X1PK+)5<_I#nl=FE-5GxB`oo!C zG1F)>xbCi`N?s6%{2fOjr4v#}g%2q_0cv5XK!37%Fd=U>E~O$ie2M z^m5c2_wYFGawgIOg_8@{ zup51zQin+%u|8#cK1s*}N~ww`m%ZS)6G$4QuGsb9A`0DJguow0Z0Huh2>rDPy~@ar z9A%ub!`L#z5#{1w>=KQQ%6e|P){R3A@%Ww5uP<9@9@nurQh@A_E0V}c@B1` z!Hyfq78mN%BZW^IU}=>Io=oB!tl5->gu9(H8+en)sHyCf3umC0L5oV zU2rL3kJ_}na+uJ-F$NYCj!0k^(E@#_Jgc?6pfCrDkW;lYnZwuHU?9s&@#D(v2mP>V z7|;jK>+vZLg^V=(?GUN!yK0xND+S$gUpPIe?X@-YaJxm9E|k=bps?`6F=L z0ob^9A}p?m`4ura)!_#Uu!k$IXCoY{hT@6A{{{h0jro0=4{jKytb}suB zN~(8Ui?8X;mGoPs(VXerRuK`o7bJR+Kass(T>MhpWmrC{DmMo8>GA!O5H z%mrA7(P-LZFSOxC;7I>=fAv|sUJIc?>w$Ip)V}_g_eS0*ePkfNf!HHaS;h>usnGUS z(PK7Dpj$_d-qD~(t{P#uiNn{9xHra(_Gvt!UB^xB;;{|iR7elZ+w^^dzz<$L6n?{U z9@t&Sz*iIZhX%+jluv2`WkI2|?B?r^fnr*6^G^wG_jPaVx$gB}n0=&%Js6~YBe&}h z28mw~eP&ZaDczxdWB3>}O~+Pm#A{&gF9&b%UlD|^W!e$H!+9HE{ucty_FlnkZ|zGn12# z4f3_(vSIrL&Q4z1!qwR0IML#`!>9FxX%x6MaGdHqonz;N`ij7F;=Cbi3PzBh*uVWk zL^507uW5%`3J{ftulOU+nCLcm~0*?>!789RAW zN~DRjKIg6L6WW{w*(4+=`Kfd1_I}D>jl&EY~T+48pcxs+M5hh-t0K_jVpn|OAbm%y~oc; zD(pJ276AV6&HX3+=7q&x|A-F7m}|Ass5!$Uf^f^buZ@z_NV0uIES6gmU-$Gti+drs zCVKB=ZsN5qtQx%sR&F`3y$0Bb+rjnExdCNOGsbOdgxgfit4yh*grUD_H?O92a&jmS zWe3L;xWfmKd#1O5-+{)%z+>|z`V&29dPI>7H$4NbPXvNbgt||L?gv%IzLm%WqxD#o zJHlQueP76scW=MP-l*HtC!cTR?E$TK9^ zzBEhU)-x`e zl@#61Su5?+>!VIz4nd8L%!=$5Q1?56286u(G9uCl8!?K2eg?)c0(w z2Re%H4n}8~v41ldEN7LmXDo!9jxjW~VhhlX%BPRzcB=trXjt`QeeWhP%2zQcMp-o{ zZ`_Ki$Z)lDodpkIJ))eNx)W^hY3|H7pOTqHMo~^bvwZ_MtMW|^3_6^K+h)k$dtVG? z1JNy5yz`i%a4kE_nJHrqwv*bNJjZ1SZ;LXOuAt|Q9{0E_f8(V4}+0&T7b`E;dn-H+R{mqJDjCo z@ZlqJ^`BtNv9~O4X-c8AH5+7_=HDUop2d{xN}CvthCji?*EXj^fg7lTKWXPHm+b0C zesDevjKYC;=Vs{S*t_)X7q|Y12KSyt;p(S;*Bt{iS_b5Y@Mt{2u{v{Qnc)QUF`*G+ zid8!yIw?cim6UFXytb-%R##%wDvR$j65@|IXd4ao(FpvSO=k$Ml40;th=__g=+@rb z!QZmhQPamy7{x&WfquXci_spIS#G3_Pr^5cf7hEXcH?UG(W-?pdVsj)MVusy zs-cM$sHDy37fZq-mqI0*at520nNE?$WLZ%sajH+Po)?iOKZdeS0c{T{S+;3}aJ%!U zqcO;6gYi0|avq1`p{BNYRdJV9J#Ju9O7l~Loe@epI&^4cev zaj8BNx6%dMY336nH;MTOHyNSm`?>Wb*+p}V5&T|dlZpKn6QvI2nwm;(BGsA|l?Brg zxEqPJ6!U0$5+r$!HAcMep~GKK2)TT^FE@EaZuGfIL)#7X(8~4iAMoblrT98z^PCTg zib7$$vhjBcr=ki6Dj?ewB}5hp*kZwMrf(^Pv@*bJe|K#M!F&R9p|Ofk+ez0a#YpVo zTA6@l%r16HSMHG~8!!3fT*W&HIQFKhwhYaCt%en zSz}t=pd(dn`mH+$v{!Cp?ssEwyd-XWg&UI4+kHN_gYxZ|x^Z5P(U&UiPp8S>sBJTx z<%@K_!~DKZI4XUEBYpN@cI~U!5k&N^W12|ZtJwj%Aa$23xVC)_$saeUTn>lIaM(Mk z)_DT9^nr?vf&Jx#1v$*fCCj%x_Vi@rU=0FjVW%PYB~a=+J~E8<*c+hQVaqP>?SZr_ zwYOcAu{W6xzHV98cbIsf;?dp__{QBqv)$+hu0z@ zJaSL2dgWY^AfAwz2M=9K_(ZSVK|s!6dPw^BiMX5iK|W`swJT2_KCLROJX|_WPMaw`H(kZ;MO4##;Iwg9 zDIMc*Ch^l0x7*HM3N0l!QL3|R_=!%t;`H7ynBrcA*#g}*cuqEzY4)1Cya+wDCNP-_ zMJMtZsWSup;=faFIWH_NNmqT|R`sWU3Y~m^Dz82Nh=%s>Xj9ik! z;R~+8dZU6U+=KgRZ4=+uSXLQo3_TtukDn$@j?jG7_sgSE(1OSp$;2e?rZM<4dReVs zoH^Nmtx4lRc8V#b7yk{uOR0DW(7a9NmraD@6G>JqF0?2t$7CggV?wO#hbgUp;xV_; z=A^$%J%0<-y4&6--VfEJOoMK(4qe*jyjZI|O*n@_gyq9}kN{>S^&*RyJKlG`K#yLQ z7dI;xx9j8U;QF)(czG=cYPHLH8F*gv;PvtM>B@SG&f+8DE9>Xu;_0u5-CM2w_xTKL zmDPU9%o{d?U*g&m_5;_S*$`vmBAPc0$@oEUkJ5|;-KNoLGU6!Ga>fV~FOYg-KP$j} zK3?L)1SbqWZz-hpc*px(XkXB5jF@cDH;imRvBa2rfGFNQn@+)mm0>>4)E7mj)F4Bm z#K2wuZ%J8Q<$h_w-WheufJ66xA#xjlg|v#mL*73kX)`ba*+Ha_BY|Hzvz6Hw8ha4Q z1$cRfm~0)IP)mh{uo{3y_;Tb26D_&cW($03;LanU69bgeLn>~1)U2d(p zs!t?XpA7@ct@PfRnCO&-^_fp&h%a139kG6~nT6vqrLhq;rX3&7ER`-<@+RG!Brtp& z$o93mu@~;|xoCq62FpS{ET~_3`N2n&9!FG$Gnpnjo4o?>^d=pP@s}6WpDCv^G!1gX z*(>|wY?gM+V24TPC>;8?K5`?|nV1_K{OD!WlI>6;w@{)8+d32&oai z?YG*oWN7l$D`^8OX%S^i41~P;p$Wjf1Fj0_4f>dQj@J|msso}>v6%Q7t1CEd>k2GQ zg+PB6CWtg(K`2IWs)LhOYa^r}b22&eAkGH`Pi$HXz1!6Ddt0FYP={k#6|ra@kQ~t` zdvUWQ2-e)na(9olldA+VguA7>u3ymdLU(}QDKL5^$l|6g^2px_TpMFH?hjGcJEuhV zqur6e(d_H3^N_y1^-|6C!A?d+L>dg}t<1Qbu`4_eU zyH23*QDSuOvvACcj{>U;Azcm-zXk+L+9zqJPI9D?w4(ye2H@!sV%8|yfYsjsRBHiT z+5q&viWRF_S-5z3&Z7s~PSJDf zSA?!!&v!nvq=g2nAT)ZwX#&Qv*EX$aNVC{4!&!ggId)S0W!$@Ry+&xlmqQgNW>1-~ZY;hb zS~&PB81fimtGJYtYSFo`ei74Vbe6p9ODozNw6{@Xsk40IY$l0Qw#9$qCPN0l9&iuh zq>GJGe=qzxfw`z7Oa2Vetf*NcM#n5k%BY0&*{Us`Ok&$8 z;ug;1<}O(Eq%VPIjf~~5ILdi~qmb;&SNP0xW(3$$E}^0K*HJ_jDq_O(=h$k>qBJeh zf(wBxh!)fi&&tDcZ>3*Sb3SVhwqR?~g`?mv3%b-lX+DIaG|(iX3$m@sQF{nKtCP#h z#!Xu*z;UsK5e9#>%B*mm-1*$ZPnk~R*5L9r8kM|Dt{WjUizf7U0=lV zWsSLCL@Or3JS0H;kjc{9&GJnea|O=#(=CPl(ZT60oBm(2&jv4qF3mVqu3*O~H$r6} zEMIJ(r3r;_7TI*8@@Om%we6a~{PI2H`KBKGPI*rgG_rphYvZv|GySq;)mC@&MbWm5 zgTnP5S48T{4ysB{1^s=Cib4G&IEwftS2s7QP99fG=Q-I~)Y~qwvsBN;Jjj(a=LU+^ z#R7rYEgXn((gnXGYbf*6BdMA9*R+#_E|plIE)_+~U1o@QXSJLX!r%^B(2NKpwSeT5 zPLY~21>N#()z!6!oC1MQfMU3;J()70Nm+2jF7IUSJz}H$`VCu!*o%Kn}^Q7JlThm~A%TBkbFI8~>EAP$mCXK=shW;$tPAo3}icY*HPv>-6kQY#=%G|a(M^NM~V`v zFG%DBtwn>i{p71HJ7TnueD!WF`r8V5ramu(=RNNJJ;!HSu)-Tl9zqKvL=vMcHWyEK zjA^*XZDpR!!ro$o^IU`f?%H}=oSATktsPmoUPX0p@tip}R1Oar39i~Dc1vx>P=S~b zOqNn-QbA#73*m1)x03EQ!x%dqedBeTak!-O2o=oqLQ87z^y+i_pQN>JsNZ@AGyp)y zKR5UPcWsCCe_Pw3A?R-5^nWK={GZtMe#Hpbw%{s^Sdm(!UP08{(ss=%o;@SLT6C{! z|HWyIq=#$(f`FRFz%xZ~POBupUaH2SNncikWY{v}VyatWL3Sc41K`P_Tzwaqn(Uq< znNd6zTkSfAggf5LM0jwBb(n*9V#ucB0|c#d&;?3lm-N%HDdzl3w^&>(66L_I0c?g? z#%rxWf?gmaSbg-9$XKL9RP~&SUWSSS*Q`nC^ZZztofpmu0}2HzVXnib9}4VLL}&0GKPw{LO&~2y{be# z90dklTDwr6f=SV1FUvk7xKy(t!oSTtFjq;Nk5`R_F(b%q7=QY3Go(!>WT zm_7u`CX;Z7c0E@$1~&zwaCVE0M90DYf(;$(>LnxSi6y(6Yy_e9Z1`9Txio85#?tHS zP$~4MW(Q(n_1`+AFa?Km6hcye=_ppHkUCF!Iu(zwT2;ZZT{@CdCnu8znSiF zm)=@%6-jL?vUWyAU7IQfwzJ8oSj6ig@Qun1*Tf%WSD|LfzryXIkSBOn%toe*wIn$g zPvRuCBc^|6mTJefmMZeQ@$g~y!4miT;Z)m3qkn>jW7Y>rY^?OQcY3w=gM$FBuUZX0 z(}!o;L%=#-Hjx4_!TU|07B+K*w#8DL(GFd$VfWzzGKcoR-Y=B?BEOL|CD<8?=wwuN z#ejD;by$%&sKtjy{Fs8OA>SmnZ`GEHI2|YU@_po|wn=UWd1W+ct2RTQ3sYqvB}5BI z&k$Pv?Io@9tOnzL%S%{~H6Wv;uYa_t$Y7!wBC#)UxYWy-yU$KNA=-`u2X+_G|5;e4 zx<|kx3+mh)+5v)&oxLUE2^0r@!y)9+{3UVSXH4xTJ$0))gZbyJvbxZj4MxY~x!+Ao zd$G}rs}V8Q5QX?xxD+pQUZIzxLL0^_Z}Y7CRxjDz&>6XYzL|#k#-?EeNM6z#Q=U1e zh$e^HDdnv=NbT>PW_!mXOTLc}b;ply zNyB;fl~&1>a+L|2ddFRu6XnkdmJ12x?@kTRnysUY->6`B@I>vmOkJMjiKiqn<$>cj z-MVRSZ4V}uhtj%iRH?rSZ*`A1R2F=(c9LK8uU`}apQ9*n$Fj7#2Bk@eyw>Gp#UBWL zT&9#>6*bHW^GP<0v?+?Xfpb2>WY=0=(yw#s)AqwP% zm31!$(~cwsH55unUOwov8%S88c0%UMi-ok;E-EV;G%C5C*78HmcpQjJ;foVrT2r@T z$_>bMrfb?E2!5_KqcVmnK`Y6+fu5~au;caoT|k1ZNM#L#96Ms?&SPslQd;$ar@_2j zc||~$y%4~3JYg5^z)952cCLOy<>?&7xFahs~V zx$ZY@{n71oLg&MGE#jEtkA5#p_BEI}3-NTb+MpP)C8ePKUL4n`U0#uYWY10FyI&jKN!}jP=jms- z(noMbyeorzU&AOgb70i%H*rrO*AoJvZ}Rd(<@$-_>yGuk8pywEVpkK?ll#le(vk1< zgzB9VkQJa-KBYfj^#;N>w1l_Y1E_b}gQscF*&7gs`O_s?_K(2~eZ#x)NLB2UjmV&& zITR%Y@qU*$#l$3r__5Z<97zK zmh;UKmDjP*T%@MP&qh9WQplAyB0ZGO>AH2pxaHclB^KD?j|%ME1tSSIMMPuq)2=)A z{5(AfgS+Q1&3R*@d)|)Zpgpp%(jIzf)vy5ORe7kxH^kPZU)OvY*A|`PCW$I&!hb-- zv@?NgJSyllr@hC3R_@V3AGOEwj=ON%R@l6KTAIb)856#$_J%#>(;Kj{vefM(C5h&@ zeT4k3v-QHq2qcj6?SX61j+b&I#0x!!vn}$oD|2dR5YZmv-I0K>ZOgrNfRXFQcF0vF zR=0615`!|v^KwS-DwroaOWpcj-j)#koi$Z9an~Kg`PW7n^zOASyttp=srx|bw2k^J z|M0x;p}RxkespYd@Em(~F$;=tHKPMIS34)8hel2N0-L8vC-+D^63Q+fDvPI(DQ=3H zxP7|iyDMq9J!*J86lz=g#m+3DC(h)}w|QSMbw4b8Zs_0d;^fq|+MtZ*fdTe}5zCpe zQeU^%#!QdaDj>-R3baC^5nM?{HAm_k?{mTn-0R(k=2bh+#k!Z;-6{#;%Qturlos_D z{68FmPOvT>`2RTswf-A#|37_ex7`0q1WNt?*0=u0pnFDr$7zWJ!Ea8l;jW*f#>o73 z*VBN)qJs%|O%A&qxYVg=)3IffJQ8)=Yfq4XE zPfnpgJ+KwJ`TNL=qcri32aRckZ!h;c$G6C<=`Wc9VKC%`6GNw7Dk2YZq7SNe!Vzf# z@(iqVfqj!8_%9rozdYqR9_Fr>Sf6%&q8Y|3NQd2JpAR)a>c=(qz{;UIl$0O*{h1{* zJrh+=Dg$*X2|v@ao9a%PmshF>JQ>E2&;rhKHqb)ZUSe^+hXSIqpPsQuB1)`Xj z9HyB?fHd(CPsR#R5wkZq-Q&xVWT@LI zuPWgv3N&E4k5(&oA^{Q1+J71_x|zFmTKq6#m$j7HypB_ZR;KZrv8zyKX`Ho!V$bbwLN=IE$1x6d2J5tUC>`&RibW?+-&laZ90t?{pEBE zdS1I&su06=m{TpP7~&I%BzaFv8!^2rujU}N4hcr8sHKF(%#;pKfx@MwQKc8N(x=NyY0O)1q4OIv6mvi{P{iI&;2>4RIBUsZ zMn$(4M7AScs<}~yZcS2>TXD`Qo*HU>CBmyypcimq1uq7EAC%qkqT#0W z0jc}NNURH0BGMUj>lyfZ2{&-LPypTFy!N5MmNCyB_{|FNk>dMY+op18nEj)_RXJ?E z)xH>6fPO+1h*w^9uS-eEx5Teee1eN~e=B1Lkg4^VpyoU!w-H8OBUH@}CmJyR=;gvh`{QdoJl)y2cW*U-c z1w2Ges8l#VGFpeXef_F%VU z2UfbPLzVDMqPJ_n?>{QSP~v%7CMW>FINE04Wh6F&?^^R0L^| z)PTT7hyrpxdDW50>A(Etg0pNbsB1cPKJ>3)HBnb<+b3rRLn)FwFD>0P)>b;Lc2-(y zRw}zX+g+-5G_m%6^OCShB=TzKnt0?-zE1o8Vf9{px4&@cd+!gR0PNu{T!|o3-wC}J zx%%C1`Bk0t?K>B@u%VUTJ*F&pFt5t+!$Ae=&tmUY!pIU^rZ)^#!enWiovj)_?fzYL zE0N+sKk5C||K3!%SRkNFZ6_thC45HL^)VOV+DGe*8?7cqd~-<#_~mzjJ_m*!f_-wT z%|C+xV!$cD`+fuP(i+W!e&o2FL;K!)C>)nCx5&#Yh2z^K!2r2@czk!<9eO zsyzddqF{x-)T(N&6HyxJMMi7|?I)_hpy|}{yGA4Afg}uN%~zQeQW%ji90x?!D3i#3 z{WJl|HxkWr(d-&O`gxd0@M|N1cBN2`Z1; zCk0qBB-1wb>_UKnP)pRHyEVmy)N`_)g4D|o$pW-n$ZfA9)waMsl3Tbe#n8whAVPsu zmt!;=^UKT24X^A9(4!iZM>FWmx~3+vLUT(k9>myBSa$6fZrJLq3rd*uCUK1LFP* zsI(%f0)(ao+Vw|`1wHJ_`UuiA0!;6h4Dh{pggo;h_Q+fAivk^ZQS`vL3}<=nS|Gn$ z#>Zb{jJZWqX9`35#wFP~(I?ogYBT{!&Mlvqyogh&V-GrbD^~El2fTA6ymcbuHz9}x z3^?NRWI|{uE~I?O^5^PF_ZwTGJfJ)lJQYSA0+bXTQsRG=z8T zX~%v&TjxH&lc8X@r@t}U46U}08}?_Pc+<(EXJ-)QMJ@YtUaa?=w>0R%k_x-0eexTn;U0wMYysSM=lQX{dFqwf&^;h2} za?8<4xC02mjHqm!t<~;G_W2|kk@dR4>yH|GbHWve_*@TFW!|;gXLiqIDniNB88*RQ95-11i<*DkP>9GU#C-%xX?x zUZX$WQn)_qPp!v($MX}b`Yi4`iNUr(PA7HuLr54X7Uf?}vVCyQT*1kQp#NvdsAs@d zXV4(5hh{Px|J|4VZse+Bws7Dmf3~PULr@ z^ceO3;_MxRZ0ojd!L)7Lwr$(CojYykPTSaN+qP}ncJ6dme&<%ackYdPRVQjh%!u`4 z{#j#owBAM^t&1H~x#)F9sl$F~j5{;yWRf@|32zKsO5&=>q9z~7T#~!}jeSfyTDhsQ zQdPFKK>kRoI#C&w6FUy&hp6dlGK2#3v=OmCF1#>Zq17KDT`P!N#D3TH@?#a6+S!%G z?a5X^%p?L19`F5@GBN{O)D|}hYHJ|vuMQC%<+S-u9HGZ{2OmH|s8{!ZEF(@>WKXR_ zA2)o#7LHFtjbu-EY}g`_2S%%zm`W5r>u`0R8Tyh)^Kq(dcRs2%sMPpk(X5Yd>i^p6 zOaQsg1^RpOVr9`HG_`jPf#@~kYT@-44*sHFa$cv$D0Vj34x;6j;Vl3}4+y&2HgZ$l zHc0yfb&N<99c;~UD-0%{s+hFff~=jeHgN073rNT_$u1mb)GPTZ-9_F6lL-66>{psD zV_S}O_*wl56A&^+!sJz5GO>L|o3!r-YbU$2hHnt0$2EYYVSQ6RF5?=3dM9?^=!B_^ zz`-}*-s&3ix7xFx53rAHLH@Ud<^H>00$KN9S2JHfUZ!lhz?8{nNoRwP3!na4l65O2T)b>&ihqN|(4%1X zxz&kY2K}J#B~Ao9^Rg(g55r?!+e)?_=A%R6gb>Bsu56U)^i+~b|}U<35tQQ%~AO4 zt(%^3McL+x-P4K%xT1Q^t`OVfQJ_Jkn>y)r5`52=MB14iCNCu?4#p>(G}n_FPG~n3 zI3k|}YB2eCG#M#Y9$I4rYVcptfoGsyUoBnOy^dm+ur=whp zRKnOu!+$W@EBrSjv}c9PH?u5{=)j|Mg4m`lc~YaEHuK6}VJ%9iad{G9MobIODNx7o z%D2O1n`_=%W$O*EnJK*SC^0jcxx#8qo%bNSTTtjYfFA;)u5X){hRDTi=~Ybb=E|GK z!RT|#8fl~1OcdX7&Qo2{Nk9s~yS&W^K?P9PzQ=7Wbs{kn+#@7?FX zL1ivqxnX-%pDh133jBQ`xL@dJb9GHT@O=Jr|EH$=>F<(VIp-sLUa}pyTUoaadiV+S zEng3j?kF2CnQo4&RPw{fVRZ0sv49%F;9m2x7Yf-g9H-Z!wAdNul5T$`9OAOr#7T0A zy+n-=Ws+-j$%KUi0P7J#R2WXr1QawX5W7|-*w@&E+UM%)2i%CDQGxVHLb-qRcAHv*MRd^d~ z8l3);8~y$ALzCzY#RJDh_t^a$9Cfs>ePH}5NwpxpYV(f2ZD9?G3utye?gxCaqtA!< zVy;GPRYKDi_q!SC;B#pQ_dHGrPn-8FR`p%r@iT@3H~hg$?*hp@1QWkA+;E2*@1XBL z^7guP7Mp+Qi1aHSj`nVav*lqjsw0u35F7bFWNl2`=>>E;T3JCP<^>=0-C zOd>lXT-~xS`UYs;VTNyX6;qL=hb!AczMo6`;2JThX*2Z9GBvd_9}q2jsy2P{qgyL! z#QdbGexdMtC##YAyS^Vt@OwSCjynCs?%5zO_+TIG7=!kAINOISk2j+O6EEbx#@_G) zi?_%hVGei7Vk4RT(K};w>V>uHaz_-pCJ{8E(Y(JI8k#Ar93DYMVL7?PU?m+QFbkI? z-_Fq5NR}Oyh^0vq^+wKYvAacgLPj)6J<~eOIa6tv z${ZzPP(G=4yP|&K>Lb|`3zL+<8MAdt3XNjAb_Aw$Mr$d)qSc>_D)rU4b6?~X<8tLn zODUO-CtvbFRhdAXz+d9`tHV_;N8rP-nCw+F@G%9~;Fc~)IW>K5gx&s?&f=VoJ+j)X zOGpuBCom%pqdSQNN(yh&pnyWbV~+GZ>o2gI*9(*_ppyNUQ;xoP1EFaM&N&e(!(2!U4JJ1oeoWh zgZVWCG^T5d10bCj>4{;4X?Ckgq83#V{4iR)qEeJCtJj|VhIx)BLnJOv=iYX4;_XVZ z*$N{}4sN>ml?a2!_>?-nD8E{aCaIh|v^Bo`sHlBohtK#puNt~7MAS?qS~>8G?nD11=6Pp&%Pp`UJ86L=L!eSgHP7_w-t>VjgLpBmk9<7V2H}1l{ zj(M=Pf;%-|q!Onb^*J6=dXr~$PDP!7d9)oru@jclla_6+vI#fomw4#RG#6WhQ?e3f z-o399kyPPL{BaGgqwS-7|8ha97_ zX;cgx7YXz5#OUbi=(ST_+SG?Le z+0aPdZ+V8^*!zlON2OZ=sv*L_2a*(rZbclmKb5i=3{d0eiVA8Qe=Ic0{>1%R-0(4F zgF;1-+eXy`4Y9^SsTdL5i_a#DGz}3k$f2l9_rgavdDnN5o4ldnCmw%BzoOsfC!q=z zd2;;*oZe($Ye-`@7rkm9S5CXVBao}b%Q2ah|09&8be%+A7{QeSUOLCLkxe!Cr`!m1 zPJdbzDg8)z*r-UO$Vnz#tWK*^GybpFKXgO4-pA(rk0f0({=XB@P1?%;sM7zhMf>yX z|5c*?zvzblVhjG^n76R3oj2I-JN!VWv)Php=adp%i<`15kh#n3aW;^tua20qVPu4m zup)L53r(LgzI{8~;{fpMv&URKm!fD9H7=pwfl{F@851SRx+Fgw~{^nBp-4SPM)!L#+~F>M7-* zVHbnS^ql7UP31pZ9n$a|GfAJmp;9{mT!wNYKWOL+Q-_p!QAaIPH12? zuxPDl_!hCV(5%`b;x&ZRTiy#DN^3oo9;4nB@RVFI(;3=X+nbw5UdFLAOhZqT{6?Z8 zr9^8afTsG5A}xkSGo~SzQmGNH5qg+ahhYHHW)@sh8$hiC|M4-c73X%LdE5CS1-RXBQ6 zE6V8dB2ujpb(+FLyJv{I5B&8hApIvjQCfj#hUp$23P&MrZDV}=B3L|FZ-S^q(Xg?= z<7H+UEkHiy0b7fK2wDrEwCCMKGd%!E?RIf&MoHEJarFkDDPw^Yuz{V} zD}#Qj-S7fTMm`>fYNZzyI4&?P)-)MsUxvdxgkG9qRlOEpJAX2%2vKU@$pbbt;RxuG zR5KA(qbb37+Frw|WGHG72S)E%!l>6F`;!tT8mv(4K&aW_JFX#rasjry4d|>_hZXRE zTaX4|*a-AM8al|$;4dz}=UIaj8}K{|N@{&FyM;?AK7jy`$RMCYC%is582QKcmP-o| zzrhWl0MKbK_6R(zWhf%SDqIUL)Ysx__L~OtRS0;(G|a}fL+$4fx<1TB&mG$u=wirh zKPWJGQ%MidCHn1@&?klkDBQF4y(hobEnh)~5x^`NJR(zC$;y5rCSoP`);+|ARRRquy-GsY>?|Dpc=m;b25P1*f*HBdv)8l7$J5J4 zee#jpm;L=GNDpV1$NR#WIsY(Xpd@J+-xm~&!&{8ZUKbagsZLTi`N!lfLH)Y1EDBmnVskg)75}@wq||Jo;M|2nsH6!wJK_{ne_o6J?>nWxLlI(Z6-*-8D>S9e5VZrs zja|64Ah3v7*xb_`Ys886Bg|n*ikhxJO#7c`bu)x|GlPP4?WCm^-Z`Urfm~t$|0p>C z{}O|sh87*}ZeM@xATpm8Fe|9bZoG zO9Wc$8$mhi1Dy@afY(wP0qu5{pgmL|UJUkj^Dq)Lr|6S%<~pL*OmP z%buYHFmzsI<18u3#bG8ql?tH<1}C+dL4;!)#W`VGLsP`FdQF12&LaZc@4)85o4Ic` zMsiZen}Os&n^}c_vqRNK@TOdzwXFhYDTU=_3gE8ZAStnoduB%bbuH6 zGp=7OynEj+C@Nk~hI1rIZh9116b=Q>4GW>JE1!3d$zES%_wR;rTh zb}~gU`gXrpd+0Ph1D=S4^p43qHM>iAI(j?X<8)EvY@&SQcqcs7G!Vcv%;UHe?3!|((1ET46E0C zlmCa}qBD0smC&j5(A9g3h~MCDMVLKv_}B0AfhskZvMTKqnuYS^);bK9xVOiygJjL;1hqt1=mejuC9+1fDXM zakSR;Km>hyyCdrverv(x~o7>yc9t>O5a{qa%TV0w$1Yimcka1Fe=b2S&WQT!fu zszdw>*t(^zzqaKgC6-7=8U*CBEjcc{ystcQOs{qz#=!=SuU@fi*(^6e!{!LSmrluO5B_7i@b&QZ>%U05Wmp z-qU0}jHt?fOcAqmmA}>v<=V6hNgQBwX73;J@zoLZ+^f7!_oFhEsb)Rzubp~=wUUaU zfi)sZ-24{kJhz$)%DEFTSb!+j3ZRLBu`lpKoCNe$spFyHH&R4+wZcNpO096s-}#z(iOeCYEkCA**l&ho_E_)B2)4IY zL*z0jBCd9@l}Zi9P*Q{pgh2y(5F#06I{lQp0z7fzjxgRldFBI_1cD}^+R#GxfsfVc zv8r!Ygwe7z6Ch`ccp$kOO=84{$&H!wv2|>7-!*j2_F2Bq zt_^q(X`xV()(Tm`si9=hMq#{s2y)?48Q-7^-61vV)MwuQx;#EsequY@e8YCx--T6b z@20=waopt6VA)=Q#+&2q2->@I+iK@`ruw%s_QtE5RafRrwMq|Y7I`)3sxC>5@L+3m z$&AtIGC)|d&bo$ZJ;KY58@(ED)KaV0l81ch9ix=B)I$L!!q}&M&vS1;?pwh()7nH> z9Sn63nEA0$=qmSn$%?=z!p*zcKku-o&R`eqUN_oK!^TL$yaBs-#}OtMRclpx)(T>V z-%tXoy{7%@6NehF*wcCXj@4eA{hTjv^=)mb3(vzUCSI2w!+o4x80?L? zV#jD{{aYlt$Ep?XT-?=;Ml|rldmP(0TGkMTg?_`(Hh^UTy;0U=CHt(p z*_d$v9NSkk%RsxIWyP%imrdN9L6fW*S+Jd-*Bk3xzy`5TXhD2@y`i(zF64P$v7kp_ zG*ZDP^RDco=iB*};wbu-3%Yu$j&-XhFq>x}H=A`-XKN|~l(7U^g!rqP!cK3)L8UA4 z6u}Lr1_4hVe}fZHTeH=yLb0lRZ#`hp znzIq!zJUnta>2{e?eym7_2eYk7(S&6Q;PDHzx||sYB*4((sOQKGfw4EMNdNgZqT8r zGp880VAP6jj0Ag83i8MkT)9F^bvcrgKpr*T@>Z*1wE9-BVc5RvyGkF1$e0m^2d*uu zX`CGqJN`}v|MuX0`krLw&vagEyx2RXK=|zTBrCM4Tf>HwA}Te$EmF(Vn$t7KMc4R1 z%e|*GeX+{ECMZQ#=8{jFN|j}L3glCtYnZAB3uoUFiSJ`aUgI&BfwMg-(-$1GoV27; z&C4!%!F&Alk?KK?m2E+F-sfMe>-QbQuA_9IYRy3GI6^xYXboRrV)x(Ab^D25b{Vyo6ixvqA*2?g;+q4xPRB(B|L(exrEt^cE*1RLGl{8GA}GR>f6zJB(rm^nMfk7L1c zcsb*%`{p|IvVM=z7VqzSxAU~y^y~C%_JdE2-$y@%|ItfO1QF;`yt{ts$S+T2-8??$ zmiSXv<2;EPJMQ8oWGPNF8ce86M&pXKvRjI@Zt0s9VaDvslxkhEK}Chl)q74*W~><} zE!@oa3ly2ESZzu1mMmA^6s8XfMF-7==%;>xsa8GE?xtc>t`!AUQPU0}c^@7t5QQiu zSU?#?hN`*7sACoVRKu1tT}EMzNbyIF4!caFY(md0y~OntR=x4E)1yfZomjit)5dt1 zjXS)%wm2?~f><{NJY1?j&^^9q+P>wb}&I_qx?U2A*!@)xuhgaxYyxvVUL zGJrd)f}l>$SC!(j7v#AoZ2B(5X#0d7S+oK@py;_X zvRxJX6`3avt1Sxpz%l194Q~Kh9t?~=V-i&TN)p7=XW@{x`*sT%iWUZpbcR@98fU#n78&_ss2fLfY_foNVfd}_iMs>wzb-twFQb=rvUJEn1ok(QuFXD+dqcCeL#AXW%QEc9(bOOa8 zD7u+Ihx`h_M&rzg7@Cx{`Op+tU_|1*G)HOS5|#Zy-8%r+U1%!4nM<<@!N3~E>C5fl z%-;Y74rb7xzoUusxVs*?F{4k}gq1QPxuAYcr2N6MOEj1zvjh>d@gMsRbrf#9`*T^j3C58&%GP)BwW2mqy>)&Xza{G_RIXxJzA7t! z-+tI`GVgGDT^uoNgGA)mzu+X)91kPunrK%CycW{WCkgQW?YB;MG)o1B0x}|OOR5B? zitVZ2Onx;~MfFTc(G%x}WjAm&Y06`$andE?bhY?;C%SyP-0U!w0r0#lrzov&1gVCS zM7J0r+J!rNYwBq1NnGciU_mkejzZJwAOY#iy^wq}z5Hi!d)a#AZ|mrMf@jYhntk;0 z1ksphN@~AQ4&|zr!iy4<%FEz`V{YirIqN4oSScgr4#EcLK_*r=DTXpJPr5M+wwDNF zg?njl^rB&A499!RgB?jKUhjar$l-xv{exZMRevP-U77)Zjx%YS*TrUvm&gFJdjhS@ z?62+NU-?EvR@h9B?Ue3V!c;k9o(Tg>x4hoDyY*3kn6v$s5Y ze=vFbqzLq^$mm0yajTGXau#o$qwZZq9Y# zkmh^%A~h+gbMmT&X(q-@)aBWjVTG>! z-Q{XI+{gE;RowEh2?~;N_wpHM)P<~hOvPdT@@jE?ndp)w9Z=0;?c75h_e0~0Csz=? z?CoXUnEA3Q3E`l|Y?m9#@Y0DE-(4gQwxvzi97F9gP3~$0rnhD(nJT%aDCB#K9Fgkq zdjU0Ii!<~%Q#R?Yu>^u<54@N>K%lwA7)Y8wF;Imm>Rw<95uIiuN*ydTb^oznd?y*V z7OQP%KBd<41yTq1!Gl|YGZw~T{{@qm!<2I>sb8hlInE!PF4#1Q|Csz5a(UeG0j2(9 zuXTP3;>P9*uy2K(75SQ_5T5g^o0=CsrkB@*GBr<=x6tFu$gA6m&QT?qL-$@8_As$L z?_wU)LprMYDAHrFcXMqxsv3Pe$=;n+LfC+-0Tp$~E~mphZ|6b88EhB{OjD zNWOQ}W;({+TH+T}=CYOCdKf#}^CYsW+Xuee6Bgl~V=TR?(5N%&f6*$`g-h=et5no} z6K@|%nyzDv?@b{C4>O?V{8pi$T4y!e7PP`a`~*T2y_szQh*!+&6G%)D?8})hFS3N0 zZZ*bu{~dCSWhMrY&wuI&xCiS=N>ENp&`C$o`Rae$?thC~qXbIeZE7{EUEJ=kfLiSh zgs_B!(EUe!Tpl3Un)Ni^zm*Ujp=4I*SvOEm$WtkKM)d+mkXx%S{LMk`0RT^M$cL7UWncnZK*AtT%n{6k(e_s| zhRO6ZqHoLnr#JTBt$@tBT!8jOrFTir-sT5X9;r3r7c4{9xM#SzH=jm7ez7}%s-2(~ z32xbS%=vB7EBj8QZ@G1^!Y=uB@JkaYLRx`Nbu>@LCSTOJhU|LDmpgmNEh5i1Lfa<< zo5-_FfXXnv>jeL&d4BX-KA>$-8v8oO-WW48(nn(McLVQ~kOpgNL2aPvPl`{B+mEGhFE;lhbQWLvXMIUlpWkJP3ydgceWkR z?sfQl*4IGb?jbZ=b%}dQT0N5$yrPxtm9A-Ze(xyW!*pzHtVZ!O?cOle*(2-t?SJtf z=zV~O-Kj&y(#pWa(&qtiI`8cfdjDEGkg~j!osKAD&wOsOD9+w-YEDnF%jczUI(B3H zF~tIjce0mZcZgUSsbX|fW;XP5k@|5eg|*c>r>Io*09=(Xuk@jXZ_t0>nO~3LC;yM+ z_Z!l`!?TY{%zs9!{IB(+Ci0(<+W#A#{Yxc8W6OSn4Z-iPzT=Z#>7d~{FRV24BQ>Q~ zp>ea2^csck72CbDbR8S>)iT+Bm;(AVuCeHLJ}myigc@*fQ){u1Li%x*qX=?8 zhZL4yH?Dqa{UGh~qQgPazz)sU0OwQhi4|$+Vxyfqspv(V>=6yB5UU=yZAzDKG8VsX z4;}37fxK=ZH$o6~gtHi{2$P{e=rWAzo}hK|2YP8Z89KbztHUeEylIVailSB6xS|>@ z(oKFN&)H1vp}sw4VaGkx@C?_LB~Zf?1Y}SHQ)ZNx;aYs>*3Hv6zQMOLOZoTP_SqgDk~u48@W$o!m%4Q61*v@--Lm5pkGokCT7uf4B0z%01o>#ZmAtwv?z zz1B^`HedE(QpJMhhwkElGJ#?vE_3R+Fno+_6!~nu36g^|DnnKYp5K^*D%*g9R&1s= zptkrww+P31IP=8$&{Hdoa>~0S*~X!;7mZh(=e4Z97cjXuRLbiDd>^Oe&3~YvHi;#U zL5J%Vyw@65=5zLio!IL{ARa2NW#!^N(JgNo4XT5uL-WzxkkOudDqx#iv-6tj{3g zkI=8s<0gt;s${DxFeCFFlElF+;Pw-2&QuaI$p+?+8d}*zwZgVb<2En8c;89u6G%YjyzXD`_)v?c*v)VF=hCDcz9n-u|%_Zil@MQ zuhEEu>+#6Dh)4QvsgnlZgI#<1o&MOp#se=M^-KiVV8T7zw!WK5!xFefPgQ4L8bR0N zl(~Myz%H5pZdWNDOkd>X9@ci~Am!a8jE$av=7vY)A% zeH!c$Y3H1yXQpsD%O_2&_h(`!5{4&vzWoJmPKqwo<2vX{|GGhmJ-QLv9RRF{?2iiiH+J)jDXC5rx;luJeqlO&kDHDCq5NFu*!-OINDY5~AB^KeD@<;2 z3fHFZtaK&L0h_|FK1!q(UZV2lEaS^Fk^F!uYwQioH&fS_ zfARIZ0o@}6p{YUGrB1%`R2sbZXO8MLCQUBI8yJ+CI3Jx!50JlosE|<`704fB`r-5N z!@QsEoJfd7|0wGL)-Ve_w8<2D3R-Xo?#4hqsh_DdDh65h_o@m_IgY3coMu@3DVxjq zjh2CfIVRFMb%Gp!6_%)hP^pL&a>p@Q_*`M2J9P+Y==Qi14G$SA^;cyWJlJIf_p@6B z6SvtRsP@kM#gy)#Y!qgbs4_(d`28_`YnaUL;(e3wF?+)1TEl#m?0S!{N3vBT+(ha} zA9P|qd3d&$t!KTLkNOP%Y#+D(pl9woQAE9+tlBtec3b*^2C1gVx3T=4yglx>2h0bk zn)?YR0}*ckm5~5^(bP7eIjj4PC%VRy>-5~+rt>2o>Tfh{XqRT(W?i~-My&zXm{m|8 z^ovtq(0L{m0$LU0NnSN3d#K!sZlj0Zc8>ts8)h!)%_cmWyEw<#JEZ9m{dQ9Io>``e zb*ac*RLu_le;LNWR10?J&!~uFpno?EM6jEG#)SN@^&j@o|KEo34|=eb7ql8+K}JQqrJuWR?onTC{wROmGIS1V>@FLcvIhgTs#LL^4E zVIRo|xRyjt1v5-ki7*_EU;7O7cN5{9oc#e@}K_-|KD~a#!TqrGrLjTUmf*@}vY}Zbk-`~gJl{x5O(0~FO(|tQzpi=Apy5>j zH$zdajHPIlbX}hQ=_Dhjjt&@WW@1clMGEA)0s5Y*idW=IP<4AXe)>*8A9^i5vLQ17 z)1IJW(V(=@0l?pkKi2_-P>s0cVyG^HTJ6hJ69l}NBr%2}??GuLa}H}RGF+rf$4aUq zwZRULU{Ck8ceGdGjaQNjFba^Chm#yrQq5r{Th<(;lP15}18k~bG*9U-=^CRtC2D@$ zY@H=E2jL6$$LT6UVs=-{3XJaBEEpFqo$WpJ2_TP9zNJG-Y+%n(>B68jwXk7z?_gsq z9(KNBGys3%2*E#vUA#Ghl&|U8H|e>XeaG-k{p6g?XN1FCe{i3$atkUOTgnlabjIkz zONU=V$9;H!71kkdNc#cg5kEI)z#(8QvN>gczSYQoivs^MJ^X*_4*pkfjEtd^xv83= zjf?63u;FZ#9cN@!lrOtPGxm$-LTFkPC^RGKgoI)h(OOhmOW-*cz?Q+#z$Y_j$>yyO zhX%vN?>@g?b$oBsxTJtNaD0!a9mhdu_Ph|wG{;F9r|YhhtedQxkI_iKoKHXl#Ogr8 zP-(S>obq+Os-K%_SGsfMYjWe|jw=n=ODZD`*{)P0Tjdl^CB#g!Ez`X6arSY9^#k~~ zNdsfG3fqV&B?N;Gcl-q1ki!T}_U24$vY`dqZNLf(&SR#(1-13pHm9qOYV0=+3^c)t zww=w=F4w&Fx#^pzXga2|b0RhuO(*KGo86KL5hBqs1JBGvDKNZEaq%z=%7!3LkPm)jP1euOY&SRa-iijOuD{zsKg8 z@*~0mc9tCAh@nn0;rK~kQyIYw%vt=h6&!#;nm3Ly*-4=>yKJXg?!{MNN|Mta26v#CXkJOBjqD zMW+OkD?Ez~+76K(SJPXri^y(~YHwXFSCb*-I`8;bC9%AS&YV*#sTxk$ILDuDU@nIj z$-XJ|DW9uXtr1tM{^Y&xMMI+?!p-ZXjqU_PqLe8(8fOquT>XG%;X7)L))|I(PphsY z?4dr=VRjYuZL8m6A!b&yjkuoYiT8x#Tr_bd=d4qFWyW=Y zdnyP)h&@ZrZYM47_uxH8thj8hhfdBj<-eb`!M@;*R&UW`#D0SXv^kxCO>TsrIa<4A zx4dzerccFK|Bj-iCkKoA?gZ)6%(wvX2|H6yypa1&$hWf8r8hqkNlty=NHdQf|1x_IJ4s&y5dcGw!Qh~SOcAt`d6Ie;bEdDA@nr= zZD9gkGTo?G{*ELBWPdS^QzU+nhBS@1P4;s7ZEQm7_Op@Gbx)z)&?Y|y%rf&4Yj}1i zO%)-XP<7(u`>N-kKw?zz9J=!}bqWjo-_zj#4E)^xS>XSF3MBu8|7;a&`3(k?&m4V6 z)NYcHVo42gLL(sCBwHi@VK%~KE2o8x;mC)$gCxe?o||<^X>CH;j3N!+taq-z9BO0x zNmGdXL=VS0q)&qr?h&T_A?V~XR5>$UT8@gMDMJnQaZtW>pbsctYTMvZ9>asRahS>= zr!HJ*zjn3uQOtQpC~4A4>$sT#LXcGYQCK#hKoU{7Y8oKNq1@qMq<%~B_VRk&HkMRq zB{!AF7|i-Xk9fuq-1_7$3t|cSA%HbrdIhQE{>_Bmu?ZCHfL@U3fbwBJrI;k*z@Tvh z-}ZkFGn}=DhkNotxDJyBsbbB?bg0Y*^<5^Zcfyh(YNh-QPxdR`Lo0x4*E+rqXWBF# z725WML@Ienv1Y|dw()P_@FeWu($B}M`E!UtjKX|Ai2{rM#%q$7xn~NQtEnV| zx%F6Cp96s>OrxRN7h?7tcI?}lpVLmxFpw3#)9%qo^G8vt+W;z0NhZDoo3!k;fN|3s zAC7-ZDVlS;CyNg&^QiWUw^o_g)HCB$at-Vrr|UfD1gbl0`>T_qgXjA>zO!eo-!>e& zK6wRn^4cLU7L8V#@`4ET8hWH&`oJ1|G_~`8g z{;;7%@z~YwO6DXUyVjIrzhC7RgbcYA!CYG*y)Jp+?*~s5e;+vzmK|@Flb;_&I2C*y z1Cxz2Upm~}w!>Y%qik2UkX#d;ROP9ZOAc=O#DMakJFxw$9`lo1%&oNvoG8Q1FaDKX zjhJZ@D}OTU@1Fwf|BMa)!!uL~OLGgGpXdLc!k4UUEx%xZ;=8@YCAMa8kZ-d)sJ($o z6~PXcQL30K^U1&zk0IQ`s-4%t!3B)}LI2_JGb=(cH&{dVMRDMesE53t!!49Ex8v{`Abx=`&RrM0!ms>Ql6KhD}^n;BicTqkQS?`5cFjmF#T z4>0f&^QE{#lkMxPyUsYy7NoE<$x1cM2Ry+TwUm3_tjAzO&!$Dc>gloa4po&7yWl&D zkmSVKHj3arUx|VE!boNWq6pSQf-Wu~MAQ%Ah=PvzYpxIikT6tZ+XkbC>nUMwdsaF{ zkn`0{vn9fF<8Vih!C+;QH?-)(qkU2d+eD?bRX5JmNlJ~lkbi_%41>tahjyqu^wWM~ z5eU{Oc;644S*+C$Ch#t=KpR^&)bz~z`jGZsomedFx@h~}6Lw=NaH|+9BZ1^ZzU5G? z0SF~Dz3=uQ#!@xP6@yARpFF?#FK%wd8H5SVT`_AYELUMO{o77*98K2N0L#gjQZPV83VtKcOlnmI5URaFeUy}CNupK@G z9aPptb^`gNXc^hAYwl+EccNZX^p3bX#kTKfvHM}M`g}rszE4@qmsvojv!;LkQuriO zOh1q(BZo)aKroVe1VfU#1P`K@SVe3v41$s%3S?O+ha15`PAcO_bUdZ?f%XcbONMb; zq{Pk4Nqc(UP;d*Bl#(cuOHeu&x|bunw4#)cD>R?qQrr2)>R;YP;_-_=1b?7(iTLV} zM$6@(s&o_0T}ieUQNuNzlDRKNg|b(=8`Zk|Slso`?ynl$J>(6kJ1kLuiL7-N$sCgh ze$lb#=A9r&+J)>65)N}R_N@{I22}T4TxLp7a$(cW4zfX@S}NP0PTR~MtvQ*L=$>!W zFt>_@+Y#;oc;|uk{~F<;zRCU#bnZ54e~^w$;{-j@imA^zta}}G08ST!$S3yv&`Z}c z79Ly$l!zAYSmGhu(CjzgIVyic(F&x*N8C&N$BUwq zTEqVDD+H*f8Mpp>v&5SrcgsI7ROu_nX;r% z6jWv~-f|GP+!Ov_A$xi7(uC4H{_ApHP7-!LRYS}T5_?*!{JxHC>^_Bfa$_{i7V-vA zsm~<$ylYi+aCgAZ(CDDC2!~+-b%Q*4c4=TqYCT+sF&&_Ht){Z3hOdtETkC-C=C%2( zRpNf6zR;x6OR|Q^ay9c$&1M-_dkk{ESqw{TaZ_;pFaQ=IxiHk4yOnBU?vkxx!+*#W zSwKge40OP{hZ#5B$cFE1YL%SKAz1cB?E+0=jM6z1;GkzzA6du&1#wcK6U7-3{8Vbc zWLnZ#@DcmVTM(DrXqTXgDm`61QU$i+&pQjb-hIcvFSJN_79x}n&{)TTrpCxLnq_;_ z300CHYnWlwG**pI%~N@K8WCYl848Xh39DeDFaid*@U^2oeu*(Jh-O^`oi80T_~|=j0#cqB@~(H%Nsn-FWcoYK=KZf zLW~vYT(=^lG<%+{jIYo9ueGS3mT7Zm zvOZxW<2ZqK=`@M;LHF{PydP0K>{6qoy#9r68}+R_&?{V|B%BFwzsi&QZco4urd5)`d=JI zwu-I{&QJYE_s(34yWU1C-2qxyRJ5h*o6_vxq(GxkyD?o45w3|nWSCAToT|&jEnQhR zjA0ygR>Xh4R1wyO8mrNL`ppEAlSoNCuiOa zy$P#y>aMB6aib`0$`S<$CvQm!ZD^I1w}FKX5i4t&N}}-r466A7%u-2W*&g`fz1fq+ z_sigHMvp9pn;1pnSY6_sB5OK@z3OvugV=QK8wStbC`phT1AhT{Ev!ypze2^4*<>dp z@v%7WW|LnR zC|9s1k?pgxOGyjGawSAb4zZ!C>K>#&bKIGd>afWzd=JUl+rE?1EAUZl%6dOGrM^A?wsVdl* zg@F;(*r%Q44++7i(K${AJt zTBb6G4PO#}*Ctr#vhx3=dG5`r{9uT?ckmv%;~uG*Sj~{};MCiFN%;!CIB<_S;EloV zf1-}Wv3KmG<&peN^?)P4F|E4DVZolP7;~aqyMdF6IyOXf!+yjFZWUwv`#=-CJo11! z#$HOJ2}qhVuaG0hDUZ&%vzlj5XzNhp*u5%v=#G&vxsRio3U}NB(mHkELb*s2)45J9 z*%=T03_WIs*E&m21#3mYEU6l4+z$K*xqZU1EJ`>~XN7#TMmJSLcmE}TO}ACG?m-H& z_Dk1F5cE2KM-t?$C8fPFQE!JXi_i{I&pSk60+q;;J(sWznUPR7+{( zgL;ckzQqkPFOL7z_QpDzO-J~hiK}LBHE70Na~AtiSF>yB4Q}fpLdLaBz_eT>P>MxJ z6G^4@UG$h@2!ZdeRo&rg5VEf_VfC-Ef7&8qqF@#YnQ+Yd{2D{{7CD~m5S5Ea0z#sL zRDKPbv5Eh)jpSW@;eyaSw#nK}*;IU?nDU4>^_HIe4w98ncj)s0?Nc=dyfuVpP36~O zz2d~cpkV|Pzm#ouew1aNX>6%mrUF2O1sYVE`*w3+1UCu`G^h+kX%p&VZ%DH+ z<-uveEzCWY8UmY{(7jg zjC>-yABG-*GO-Q%LxC10GjTbdAUH;e7Wv^7mSl2a5;j#=KYCK-!0n zqy&)=jaF~dxo}oH#kPkT=RStqyckF_ZINY}Rh%Kd zU@`(6v4GVeB!@sN(X>G#^#XWge=kK+&vu;Uon6NweDZ@(z^ixJh%BMjGE8da@=c+% zs@G0fHSNHa~2_PZ&;AMeE@q**=o=m69oJ`|V?8H~O8t!v6AldD6 z!oARKdQPvp?XG?&%*S+a7 zgtlXVS^Wj6H#F#EtR0%I7}^N8JSE1V(M_JSXWyB7nDfc;&d?XH<8G-}7#_)F9OY0#6OY>v4?rj~k}!MWs=X>sY{{RQ zf>*r3v@QgLi_3cAcQ|J=Vm#+S8THT& zyRZ>*+6CDu!VQH8y`s4t)W}rs-E+Y7A@d-xg)o1KH?TvTk*`+H4_}SvxetK3Z;(OE zx-;E^W{fGk-w7{Nzs`P^`)~{!(VC4An*WT4qS`p4g4%-wLUHGm1wl^;6a}&dx1eg> zW-0xg;t<#pH0)N#=Tz}@P9<(Ik*j1#L64PseehNMc)>FAg$pEiXGiEpuln4=u)CGN zdQZA|e@~c0OfhPMZmJQ*_<0hpuV@dqw_jWs9>w&3wRRP7Q6S$R=@x0EL_(w$lu$}K zrBmspq`L$uDM3Lbq+97urIogjQc6I&O9X-ctatuo0q<7tKledb&wbx{Id9(7RtBOj zzr7t#C`&YEFLf6kzyDJ)KIZdzDne8aOrL65-k87a5RLvAZ!-5t&zo}99nY7BUX5xX zf7~2#zb5^g;A*|6-qHx)J|Z;5x^2SCz6k1Lq+m<+&wz5c(9Q*4eN4qp-^$(?tP}lM zB)tnm9p3( zt1DD9xL-an^f=Ks<;#{d`ju{NCnlz6R8&ah%3N-?G`Ykr#;W}(xBNo*fLiXyV%95H z4QL;cu!l9DeWm0tc4?nZ!R4iIOp(CflT* zpbpO9esO1HLG?7Fu#mozHl1-EImLA8Jgc$Ed!?8`;-!me3z?MRwr=m{*2N+)v0gIR z+;eaBeD_9DCNZWk&(BQTl?s1<>z3A*`bVnfwwQ$$7Jtr>hh^BE4L7Pw`|Q+$EhN%E z&U8K<# z8-8_J+{5%y9(*L_TOZal9tC0~8Gba*W{q%otZmMICar!_(z??D)pFMSJY!|0=e*GT zWlByDtIi_jE}61-XUbEXP7bH7BF2eM9xG+*KJ%c~H1*yXRZ+?8lo#{9RJGF}DukGq zPb3{bmc{nf&gLWPdjm6RFYnVa`;(>R7rZ|&q%ZgB2^kumx`^lWR*^)?r%ET(aG&#n z(d1i!TRqq7@{NZT(5cU%4&T|wA@YAHap@ywcQ2V?>0Iw1U)cB)BchM%l;tD)&-sT% zd@E6@*9@tBT?ff=ZZKEa;_uQnb;+)-G{n$m=W{Lxb&A*}Qc}xW$j98g$LdwV+$!_F z4Vi~ZoGh|4zHJ@jS(B7{(%8o=B^9o0ceR#<)%I6qpF zvlXTm#-Pyey?8n)41wx}p{GYk+q1$4-YrG(M)5A!jFPyPBkzS=apZ5(BX46TNk6-9 ziS#<~8FxFMG(#fiGG*-YfRe!5j)7fXc6N#a=9{Od{x+bM2MB6)+UEhNfKE}dL<`awlnmcF+xrJ;JxYIyRosO zlUvC{kTTH;Z`Kax)v1uGSUkx@YCEyz_C8d1ov*!mbK&eb<)0(bQzPq8C59r`3llV* z(Fta$BnCD`Vm$CZS6MyD-#f!Z)q6U7>x#ddH`#mbAgP$UPh;BNwpl>r=Ef{8CA)Xi zB=KUNQ+&z4LVfk^YbWg?+9#xw4b{9EEta?3Cz~I8Sa~IW^y`+va-V$pICy}a`ep39 zPO9u>T%5G0BB(^Q!3Ma*&Jz#V8b$YdAFf-O9Fc$*=xNN zl-;|nZ?Uq$ulOwg$=e$0PumarNGM;1HC3917qox5nt9ppnQE>6{9r{m|C0QSbJxsB zW#1fzD|uq|PHT=MPSdm*Px5^N#H?wKp%)`3P&MKU1v;0DXDaC)^Hd;4zlk}IW-#o?XMpU**}|Q=RkSh zioA)~J4)ZU&sM(nwYV~IG=$HO+8k@qHVE9~(yqnv;)%?3^81UkcL zz^Wnhe!)s0^VP^5k{(8nNu)0UP9h)Z8&@x&k-eMaB&WOou8rt2wUFNiG*;Hv= zAfYP5GkAM~{iMnBwEHT;TPo+}^|bRCrfE&8rHduxO0uUhXne@pqI!EbYea_;5u6kOY7y%2O+x<7ql-YB7y4Slc^A2bjw;l9jMl8^WxogmJEbwMn_J2v}N*(^)^)5nD>2?yocrlRgwMRsRvNR%kdLv|Nv$fxNq|AMgj z^_iZh{yjZU2U7O1Q=QsmUJKZhdDxR-;D)i!7ks`#1h89>*O&+NYQx7;^DpdPC{(lH zv?d*yi-{)rAR!kyC0^AU_u>{Vy>dAOZSY5 z;w?N++cQ|Lj?)>-*&XP!cBHeIh&7l*v*xnu?rZHKA6R0v5-vVk97?C0h1}dtW@BfX zzOOsZ9Um)iS_ipqzSl<<#P+_hR{oAhf8>;2Am00gZJs{*+I3sZI_64VF1s~;6z;l| zjNxzJ7w2+>X*M~)dpbSj2Q%_yO?8-SVK{$3BZp4#7qo`J6rUm2IFjAMjfr4(TTupo*QX)(mniy z_KGV1&NtaxksGCp)BHVQ*!MHi=dg4bD|tVRjL_~Foi$VI^t-_!l^RKmqKF~(C^q#f zGrF8|vCuh*Tp=`k9lW;S8%8KenfDNwgB8`VV?-Cts*%kT&kNht8kh--qS}$2Kij5} z`B|3c+ewv|Vu9bbzA)d+7L~L^SsQni_sj|kJU>Xb@VUdRJ?))P-^Bj>!l_EVi!a-W zP9$JGzGay~$uTy~hJ%>W8Y7c}fXu>xDrKZEAb4g@^hRDQb3{?Vsuc%m#kw~QopAJc zr{eWa6Hau=%)po~%uKyi&f6jZ7I9-TUEO(?qQ50FiJuN<2yvReRAu{kJU_Y3b!ngK zj-Zt5Q$G@Y<%|7}Bk%p2b(t$j_io$KYs%BRQ5#!{__k(0P~us+AdJz5A(sZhw14lR zrglnE^mJ(C1C&^)q9?nW4}A99xKgE^1ERV-_b~6i@uy*L5zqHsOkucVUG`jly+Eyj zg-CB@7MXWs#X_=Es8dNy(5=pDp`eVOO2c9dvN+@FflPh60SO;j4lTewv((RPO@qGS z4n=t?`D0g|HP=)=45qwICSJCFY*JJs6?r|5#p0z++s%X`o!yM;pjPLLOQ8zVEEGuA ztc#aQ#gR>;s?;B3*L3CjXQRLO=4>JsW5di)M*2id!6z(`Ygp;Ok4i}#Q;3+fGE#p% zNbwQTa#=WuDx1QKlxtCDs|XpxD!K7u9xqeGP21>;6=hiqP^_HaYxMGaXye?UugLqF zylaDp{5;S zMa+c@NownpjmO5dnKgsl&_wZOcOgaPbpkX5KHD_wM<*3{Ur&;Q1TQRb8yKU#>!9UX>r;#aT zMUHV#diuh}IcYV^iLBS75AR7Wt31yQb__p%CKHp%P=U4B>+3mvW|WS#M%gcAJ(DJP zVs9tDX;hJ}JMSybKf`?D6;r!oN|mxSmhB1T6Ccj83tmYUVn?nQS-dl2icMWt8POOC zvF|5u*lJ*2eW!dc8UqhWCkM42Z&29UbLQGfb{715-;gs|yB*$0UU^1Qmb564CP}yn z-YR9wNe*Xbb+Z%FQMo#5#;-iinzVLH9rZKgi)OTHg#3$064h4-2wc@G{4ec!8NaFJ z@$%YMsjM9(+c_~yoxHc0EWqozzd5#UZ0EV!qOAWh{uR%(Q`oINwN|HjPp2&bU!vx2 zq;Ij_J6$VQSf@CH1H8FqW9{j;!X!i}XqVN&yy%ge|8sj=iI}J;94S{i>CBa7_s^)a zzOhMxkh|v$yGa!{dP$Sfd^Z)v!^l-+cG%BHeZ|3by^@hN$53b#Hvcxt`yCBS4e#Q1 z0G%;!C514&RIqsBN(anGH~Xq>k3pW^(Yw5; zP`k;eW*D63R&@HyNX3T!kRs9EKKT%5E{e&uRYBXkGxxKX)0kYMwTW8yb%?8#YQ;?F znr3Sr`5Q|;xk&O(AnQSu>b8O2rbrm@@a(Sy+og8gH*2vuxj3veGC8nXg ztM=sPf)4|b@#X}g7B=!fjDB>=97x5nxY_bCh~F3>@OvJQuHXH?UZCo9$}WJ5#-bn zNO&jao|DF;GJ{`N^5t?a@pAtF;e)dLwjhDn@{@gvdb<;{C4I~&{d4UKLGjNRBs?E- zHtiH>v0@~h;bP3%F8xUFiEI0E->X2Q?^f5jK(}_|Z032lZ??A4TH~Bp?n~P*%u1#c z!d|^2QB5DFY7S$|N!$8>-v7b)(xX1(+s@orzA0ZG&%YECe|{rJE7$5?Gg}@OeoUVn zDxC&So10|kJ_k0MTH^5jBlqgn9{RP)s)7J>?_EokkwkRbJIe&L_m4TNiN84`Q&Tv!lxcQ;>X2%`b^ADeYN>F z9lRdp_$D^Iihcb(|5wc`pie z@iw3NJg#kLJR`5dYB$@Lin~P`V>=e^_n;CKzXkIy$ zi&~cSx-nW}aCRBwaETa;-5%Qco`tQK8ivz@bBr_K{=Hw-iWk*9?AsvVVA;3C@-GL+nHIP)NkbVDbytcb9evt7WgvU9BHR#`KSR&S){<{-W2Y zbKCD^ET#0w^LG>BXueBUeE@KuDRppIq#nzp=TH#yc z1nkQveXoCe&4wCweKu?R`|;hgsOm2w!M=M$uq5zP?}wKI1mH7!QHZg=qlLpE^&48~ z+uJ8R9Fiwc#B15_W*sVKBgXukrhpRCA0>UF?!j562!@zcl9_go z)ZTH{am@*e62+$$N@|YAn<^FaiS%>1;4WZ1$-U1zHGh9(q!vk|`7!QE{ig~!=}zg| zRujrZRp(|QW?7h!4qJ%hxgML0=Sf;5^f~%9yd747vRzL#@|h_pb*}B_JL+Xvgox-) zI*T>*e4=H!;p0jy{)Tx0MW5xPPxV-6$0Mv_g8@tR$D`Wesx$fc&x%4_!U9anQaO@S zUW>BljlP^G4YIMoRZ4{&9dTwxM5x+HjRAsf%74q3q z7~S|5O2;eBFqOGinSHDsw;Sy?y+)#|7g8r=GvA$NpQwC%$_0wH7_Q0whw2 zzyfE)Q=+c?AyO8FF9{{+KQM9JM@hb<-AvhQYCz;{dtX)ebMDTwtWPI)&{8Nl-{km8 zO58yZc^*xFb)Kud-J6Okw3&o1ZRxSb-g|Q$j5XVP5m}fgE7JCeFY~Nj*ul82wQ_wQ zSUehf{YOlVD6r?K2CTCG^Z+*YQ&jF&5R zvc{smaL6n+tZWu*TT%;qcPY)_itdv;Lbzi56Fb3=B)$f_BhK9G&v`#3PP!potFF~b zC8FfSZl}a&l_O2Ibj_#EMJRllHOM5QJ=xQ?L2t}&!%njSKk;c(E`dXqODY1dlJ=fF zO=jZ>$4tgi=X7**ZWbOpc9hRZx5J-6dSgiSOUy{8_)Li^$WyG^9$I3(*5ueiHPz;5 z$KCSRll(N#k(D^NZ=~Puz7_WTR`~VaN3TQG@Y7$CX7%nzcCb%vYF09cL}3jle9K`P zebJagiHwc8^ujJ7V#=4V@WGX$NsG}|zJ-zK~imfK%@ zT_-&ewFl2V+7Sy!E_sGt>w;M3?WqgNWTy;m<{g(mD@&L|x?M~zxGMA(5Na$`3_8xs zA>G%TaUsYh`DkxfG>xnjUpcV4>1ee2#ay-Crc9+}V7c{aNSupisF3bta$?Ycs{hBd zu8p@X88dJ9iay3=JvCYT`t8%|$44_D60+xc#K$KHeslV&93e@7q?KHnzDb_lHpFkaZ-86e#Dc2b?jAe49*C}m;TkwNYDrQJKF2D8*vkiSay(=|@o z^sd*bGUU4qB(Fkp1z1#6#^&SNwXVNvi&B2OUq*2LYs-_*-PkSqHl)iGk2+!zMMy3R ziru@X=IX;h*sFFHJw;V6&V!8N-D6BTHOS)!ub$-c*Jdr;cv17-;cu3}jFCZyE>0|}x|7qjcQI>}TPbVbpl$KLI}oR>Kxt((Z0 zmVNFu23qL;Xe6_&^9z+lWV)|aJt68P-8OS3Wzp~1ubMgf%|(|#9mid~XqH7_T;l%$ zJ05vaU%RQ-dI;N+Z!xX@IoY-=MIwGVdkLY_Gd==4qz>DwXGAYoc<8H3kfCN7;G(9E z(9FL|-2vAx$=<2RTB}?n7;DD}^?THKuL5JO>A~e}0{oV+7K*-%k;n5%9?`p|3_(*t zeOC*fjNIDeJnJzPG`4$M=29;~QtUfYw;9B?hqC7PI?oviBG=|TJ4c2jS!D9K4m-aj zJwQ>T2}b~fyGTIz>R8`dk9=Ld@$~gm1K(;+S$T)9QOKy z$lZ1PjVC^0+(+6!C-{9ZY{3g$A_9ZqAWZ0zMS&d*dH&G$zE1?g<*qkD$HA{eYFSc4 zLIaBg@96N**ktcixJM*ew?pZL4A)gnNagW zGj@ija;fL-LxXZ^Y0mZIjbh|v3eB*nNNStlkOo*{kq6(ss>@4ApdvGq^u;#EzCC(vauz9z$FiQ%WqT_x%H(0&gi~jRj&Vs(p(DkMzSop5OtGrP zpW8+1`b4mm8t|MMsS-ca)O53();4(0;@Xn8tyZcS4==rHPpnsR#c*0~zo@C3ZGk!x5> zO(kz)eOL{@dFh(*#M${CFH6YSV2J)Q2F*u>1fgl32*36b&g%)B@>GJV-tSEOni9+x zs4bo2{Kma9Vmuj`Z&Q^+aET`^WK-%z1_msRg&9APHdUq+hhj5evwmnjE797gdWL;m zM@GCa_4AtC)NIPRZ<&FS1NY<2hE#7i?k#0|UL|^6KO2`4?MduWz0daemY?lJTlPhA z_eix1_e12OOjk&X`iq?yF18bNRJ$e^$u}6EtzF<+d-Jdb`=d!F*GJbWqLNpecl055 zBJ4Tp8)cN7gZl9MCP~9s?0WFk&!^o%VJYb&n>0kp5xORhMsF0Ej<4lQw#8S%&!=s8 zF`FCzQk*Vy1aQ2kk$4YidJaa@d8)7v1;BY%#t%(@A2uHhL65EbFRc;QBKtKW6$+Zw z=#zBQxt!p>Bq#n@rCB(RVfZ#~WInc8xKi2XinDwkAJ-KNbXg0>@%~Ba3M+{OM;-DI zcc+xMu?g2@GH!f)!M|Ssj;+_V8p^TIh78CyU?=itB3p!e`!ujY?#p7_=zn=TWZvLT zC5j)?wya6Y3uGci#&%G%fXj>858_x?LH@*u-EGSOj7#@k@vRsT-roreTQui%H3@W8&xIU zOFI+J_fL{^tzr(4%b~7+yUR^2g1@4oB<$5+oesfV^fJWRxFCvLLAK8%7Aak?B$%DH z{r%#K?5je2Qb0>7Fj|^+yb5#004OOTu!$<`Dmz%)K^9`Z-$^01&%<_!FgWVwEM}EA z`XYv%w+~KR>PsCi_a(Qi#FRJg>x7}H*U#Eu&oI&No@_?CZ_Hv%7kZ-KypQb!TJp7v z!?sbuhS!9ncl3*1+6}D_*|<14*Y^6w)Cl=f4b3sU-k-l7o?kHM^raU;cjP{Gz}AI# zuSD-!sx5d{+VEaOr)lmolh~J~%qsJVVp|S+WdJjZD9|u*KY1(%J-wO^l`VOXf;c_P%gz)aZ{uXS! zR6aw>u?kDP*eW$re5wl(gq`N>wPI6b;wZHn!@1+DCQbO>A0)Dx-)&=$T=NEBUTg)5CV$_XbG=5sNeC}q?i<259)anW?*ku#(lfz+5{AMjDwD5V33&d=f_AFYOOZx# z`Gg1Im<1!FnX$96L`_MO?h-XZSkaWBP>iwTdArMEalsKu@9i73jQlOI)vIDEa-&14 z-6jSDL;}@T#V}bHrWtNN?Zg{g3;DWB0` z|7^$7a`$ss{Z0LQ`)pD2{IRm(kp3)EhF}A!4V0EdlHkD3;q4ZoZQ;<`@sJpETxy3iBTi@i8 zafD;9&Khp;7zR|*v2{&-pHZAq3d;-yd}hP=&f(%N)U#}?E!kWwEfUlfp*Qb&=6k*9 z>KDNhjabNRdVJn|i07R-bDRzy18pS{5 z%mq(XTD0XXS|p@8G@??YF;?DHQoL7B*r_S*J=~&Vs)sUq&0wB$!+I0x=9{wq*JYQ44f0u;Y2nVbdLyIxVUB2Bg}HwPcRDfF`qR< z!_O==Dp9HkR#|H_ibG%_IG=nazR~o9|H-BqQ@1zXuhZhz+7@s;sC0Bsws5DFoR`i2 zWOPx0a_Am|p~p6Q(+bI!A(sF@LNI-!=JfLiclni!GCjB&wB*iP$_Y+|h2e7<+Y=iq ziD^YdUTaqrMVUnOX^%f&;)mHrPuZ&RitBA};luEem8*o}jCA|rhB%BZ*C?HHs;7*k zLX1BbFhn<`jBs8oYfW>1aoMy)I;W4AdwOHLK{uL2*`YJ21zh(=^+u+M77|KwwLCrX z0@>BOg{ao9TV-F$rbcqo$u)cYc(0qPVel5yG$uplo}uT+k!5({Wqj`{XP>8 zXpqoWmK3Ha*_bg=5e0GFN;yhG17CmoH0JokK>uBg9#09H=xa7+qM_wJZXC4lIQbA7 zo@|JzGHSeK;T&ONh#f)*qBApph8;=B;_QO~j-*YfwX<$nJcPvbZ z@UFRM`*txfmgejj?#$f=-xoB6EteEUFVm=HusxVywC#Fg=UMi)wJ+%ri;Tw$8M5w@ z?EB*7p$3In9BfW+uoq>C7w+o%y_zAck;$#PAtC)zztGa6uw9yNWOSggJoJiI6GLsI zz#^gUid97P{3+wWa+y|{^{?VjeJ`Q`M- zpm5oAh*VRue!p1DvzU@n2j2NG>xtxuD>bV-2;>jWxSiVlc9Jz}&&I=zpDe+XKj}u| z?yU)5+L14>17E&;EU~NmCd1REv#T2U`Y9~AheTw$Udg0Ei62H(RX1@Lde6C}3f(o- z7Ah0#Van&4OSHKbTtaN?-eS?Iy;gCBYRXLf))0Sc89$%<4Xu>M@kH^;*HJ7f=nk(f zJMFrwcD8s2)2?(!Q*G_*skz81CDIeAZ`>=*-rN?|y3}+ck>U9g{%~=n(|E3nL-cwC zq05u0(l?>#g74js$R#fE73S<|nLU=M4?f>6X~70Pm8%=zQ_g_EJ?$_j_g5 zkGf@6a9Tl3k!Dq6it}x)hc6;`Uml*$&gIee0QuTVd{1 z^=S>A_Z9EI8QBx0ji|Ei*HPHv_ODHk<;{`b6!+T4+nIjaztgBfR75mgdQN$VbY6RJ z)4gq&K5Ozho!hKG%E?n9t}09}Pwy>tzHm-ld6Y+68zD)wKJskg`3w%?Ck>YoCgK_& zeJPbkXpTvx6}On5-#rmhSS2f(@K@nD&e+_P2AuhB#5p)Hv)_CSb8#5~h^l6Wx)%D5 zR)(e!J630i0h^7L$sG2w{nY1(F#|ol(T#N*4Dh=FfvmiGQ_Tp-Ti!yzT$@M)fH3W?ukjPqWw#qO+?OA7zV*^SIovI z(rU?_*=(aX>QqWETheFFrAS-512pKYW|#+~iVJsgdw?JmtibNMUbp{}Y{tdUkqe!~&5l zo+0?2jz^FRx1`Vr#F*8RSMhN;+2pS$a7l=sam8i#a`$x1&5;qx{pyxXwyF7zuYFr1 z*R@%3BGkhTH1@U)S1)Pqu9gW3677~grW`wI=iic1#ZB$%pBGoLBj)ft@a7c>e}*@M zsHQRAA`!DU^ddPJI4Jc_xHX^=P9+x_A%8`i$6%1Ge{&bBe8GXDQ%&FI3G*GEUAgt5 zXXH(*R}5?+Z zuiw>KSLIA@_@c?-L2w`9R(ZaEt82Mu^KL1!m$*ul2{@xe6X;!db>zel-t*2NW#VJKL5N?*KMiqb7S-;FBYB$P{I7u3E#`ewgroh-v)GB8M9*yTn zEce2nDW`ak^dT)__@Gc?^;YsIkWG|)SdmzbZCRBto{^sO{J2rt>NYo7yBl@cYhsFS zaj*K@>}N5rMOT5ij*5|WU9Ihn>+UyRX)?Qu#yFv~7mm2p`E|=%I zx|sKc^4i-)McxegX6v*xcoW6ax?``exAwWq72T`-t6%R=w|s>_s>i;#IpTU&R8MWc zEqJn!yS3MTzoNpI@1-xIN8x@4;pde(^-NC>#K5JQ*{R}J=Tk7g&s-W78_}mgJ+1pB zG)|mABt#%YKu1SM$PLmKFZM!Q1lv9l$iNRF0$729X>wvJ!mLvA;_Pz5@>1er$|`Jf z;(P6|RIoBniWQ%6^oHiJl3*qZu3=_5u?D%$2~Q z(!=#5*goI_iUwv@V28xdenY>ZUZzqd3=p-z|0g+shk(HG_cw&CjO?t8L z8Q@=o(`*OY@H8TV0d&H{W@4vrWC1z&O-&G>#R_tw_rSkr1>XcRIM5nq5fPx0f=cY* zx1eF&y~Nl)2jJm=ZxJ5&4p`{{l^XCR6GweJBi0}Cc5wMl0X{*GEg*g`+d(mZ^$oB` z_&`Hm{OcQFx@_ub@LfZ{`XX#+Sz*6u309PCOwBC*kpkrbU<3r+Ur_k2EHf*UeE&z89cqk{iQ@_%yp*?CwT=q&M{G)?yt1AN-~@-Hyo@$8Q{DJ#S~ zCm$G15x8;}dUN8>#=iw0MM-NrGdF812Yric`gY%0_^WnsP((NGXp5h^#W}kQQXv&0 z1O({SYCoGQGSWYnqyO&vF-Sjz^dnwE<4%EA9{EF{^ESX1bVvNpR)`57kgS;%AkQp!C>;?>}iV*<;ddT)?Tfm2pzLLJtFLfcM zr7dpdg;}!*dSAwHSVV2Kzm0Gl3l`b$vPM7{90ooC-4^k)k+Q)DpkN01$;CB&dkEcy zqjm*Vcdaeq6;hBv6EhvQD+7){ggOeOtfVd8%rYwJ4)SxikqPfCH;i~IxtpKx!$hoNlv{c_>&e9-;<2W3-zo4>E>IT&J~rZ6rNzG@0Q z{}D)AV40%P{e8frR^VcwE`A$=WG4m$_Zs8`&?_~5wgtmKz&K8BsI^ zBNO-_MD(pdMx*RtW_artHb8n^QGDnw!wR%wJPkw!J80dy^@ljeu@g0x9zzGrKnlRX z4l(JL@WFtA<$odhpF+X?>?@s;Kyc2WOnLpMV!)@1Hh+lp_jbi&?z%o~d`4#IaSxdh z5In37Ywe5upMf7Wz~(@0abm9omDgtw5MD+e*4k>)AL1ORHRIIwm}g)RLO*|akYj9s z4+cc=Ul?Dbyq5S|_SiHxkddDQLp1c>yPr+;-EY!AuKUwk3oISLwnKqAz>=o~H^2Vl z?dFEibkCmsub}gbL1)J$&)E=Usbx125TI+UKbyp--ynZf!>8_Qi?0-Y5uKt(K%j^N zD_uV+gHLD}$nf_aOo#r;AP*)-O@TXn$haUxo;j>mX?FN%|2oU71lEanF4{;9WES?c zhvlBn|C{uGbpKZ~7LXksXoeF1M&8=e#@Y((b2^#?-_TC5Q~`!E0OAJhxbgHis0zE7 z*+Zk#QKi0?(-!~u_52%kfWZNT4?Aw?%fR3B|6%+P&OzNeq){nofIxc^jJMYghz0?H z{5t#)notZn=r5uW8;F$=#LCe1C`-`cc51VRLJ#0w0eCPgtO(_?u~RdHI3ML=9$4E4k5FMAFy8KgIS_0P$!hgS zD95pK2PGIoALw5h=wJFLAK+8F9sD4&W|n3S(BYl#uTTGO14jC?0}z0@4TcX`=F%Mh z0QaZ_<(*W;hjZg-+W`nN@!^Ha4m#|f}|<~+SEu!U$~3$Rn-IB)ndK(_x^U^_ne z!~=6+D-J;z13=gy_`qhAj{biNbR0u;eGGfqz#_7N;Dli;qAm!29F6Z0==-n#91MEI zLZ2l9D{lb)3L6ai@BJp+Q6pGZ1<5}DRdaH{3nHkP!UluB@ZSYEPF}cm1j$xFUaSB^ z5Jp}~(eTrkg_wXiP50Mt&|SPonSqAuIvI@>P>ez_0CP(b7%fwl>QU3r` z69r;5Y#k#!;dcR#vg82l+RUf?&UG*vP_rI3fUYOMjqpQ3zsfhx!pQ7)@xK5V={x8j zDYrd}&?JObzoFMP!s_5TT=f2)3H_KCf1l=w0w86`-#4uvoRtjODv1;2-3aOhdGHqS z{%bG{=#;_3z&`>05ZJ*SBxnvIHw+j|0$PF1yVEP+!TVnGfpT=%M>t zg@OE_yI6m=Pu0Ii{K{BfO68d9D12Nv%LirBDO3_qC3{bQ-Z z2s+06aM)wV05UfP@$THY)o18F=Ue zw>@6=_&(a=g_?yZ5I}qY1Weds$PK#RA%0xPKXTWmgFFF22Xq{E-cQL05ADB);a@r~ zbO7GXkhQ7+{qF=Auw%-3koEn$b`N13$A-|NvH%WXwB=Y& z;HuFSN1dvXVg|;a+(2(7cUS{)K1?S z?2!9A7|L5ah}c2E^F&5sKVXjv4thu~;$row34mz?@a15zrJumf(7$8c~0H+x!4tB$mR1W+c9Kre_tb-*oc`PgeQ2@mapkVhy4CTTP^?i9->WA=-S_EmG zmbeIm*-a=CbTcZf&xYjxG174?J$l2=M-PBxj+i}9A^bqU%Eo@JIfdHm;`}^TzD>Y1 zbO1iA*$))`KVl!p_ClCtW)*6V-D->4c-a>!2_5R`UwR-ah1W3_OmebYu*X~Z(^L($bNwK zC-4Ki5~5lDpU{qDEd(c551Pogfgf0Bm#%;x?C-M0ulZ60e6d~NI@b(%iU&}z&i=CU z&!K)W^{b470U-Wt>s9}PWMO9S0I@nI-FP+Oo%I3`;sd>hT{q;ZhL`4bE9jUa`!~eV zKt%}xm4YI7t3SZ-1%V27CmN*Y4{?5o2qyB@b1Jq0cBBB5;{eM9{j#VE^NlNI-SP;SCy&19f@Pfi@ z!Bw$#G&KD+qs%~y4$bLusUR^`CPY9GgJJXrSV{lK`1I2P4{rN~#XOG9N>}~o(LlCz zK(??NwS5CG)@bxO)H{Rt>S zvw>t4R=Ta-@Pht5!hW~lf8q1XO>OZn)Tz?iprjQHild@13LXFa-yx4<@)p7iCTI=| z&7rTsAQpnN1Mr#9b*u0ENq`eYj&_iLHd$hosVH%P6%Xu37zPh{{XgRUVDDEknhpl8 zYU5wvz+BDF%;m_0a8}?lI*<%P7tY}V+YX!*)j$Zdw&Oe+n4y!ghyEVRCxC1qzzSej z?o6{gX2>EZzOnA%?964-XIRJqPy3oIZL6lGy2;qgj;jC34J@f0ZU_duNX2Ftv#hTWtCFVNqU!+&9G z`|iwpK8rgR?KsxzvWCnS!MZ}t*~4B$Xb&&g_Z`N+w!A06 z^7?BS9iba@SU|-V*1paB{tV_gW&-KO!ZLv5rooU68}ClvhZhCLSAW>y(a>P&rY64V zSi(69hVUL>8n9-;7WLoYj$@AT3xBQ>5TQCK6U)FvSC7Ykgm%oK&m%ecG|-)M zeXbn%9Bkdfsp>yq9mf{4{?1@OJ_5odh>x(@jb=T(P=9Sm{WVMOhT7sWS{O_5V4nH~ zO#5MH{;}PEh;tk}%}h7y&VoE26O1dci(~Oa@WT9>5j8a#@#TUZ3Fyov4WPg-j-46# zZG_`kkTo!GY69bkG8p1v^FYWbyZ|sU@Tb)s4IEX#+Af|h*~bCab`lJe*I+y<{g`PO(q8xA5Q>;OZA2`?aYS?JenMFO_oK5jUL3L^ez;8)x*f?UJ>Bb4J< z*%XcOtOezWBHF_Vlny?;AU{qB{+gY6z|Kobr)qy7FdHx`!zNI7>HZk$IF=OU*J8=V+5%cLqW~rX z>t|mj;e~`QbipKvbRr7YV3FZyB!QkhxIrwUArHpoi(m^7?6`#}^T&usp*n!E=-l<{ zuL4oB3K%|Yy}d^7&!LVJlwpu7ArV6AOK?`?(G1H|zA_lHPp!Z_+=m`%PUH$A_AWdqtL0c}u_KF}QV;iCO7 zhxnlzMR80Mc;x{779gBU2N1y0RKXu$9LI)1+U8ww1RdctNIYO86lW1!5VHDqCXnOa zPdd0v0cFO3ll5UPU?d0_6YRk0QTE43$FW4jby8p#01W{kSdRz?n^ylZBK;K^B+X1r zEx^w)<3|YC10J`{I5H3DOMq|-yNh(O<~Qjd*ZtAOqzLGNtb6E(4U4x9F7n?WA5no= z+E{>XI!7G?s*BquyzI~mqDVnZf;B9e=0CtVj*WwF1Rt8?w890UVyACqZw$^49=Ayb z`quEl_wQimIBf5K8{s$>4!$r4o4J+_!36-1TO54O3^tCG4F3tpaf}>%Fba0-QqCw` z82|80+CevmK0$TxDIwVGDsTKhU>(QS!6$oQ^|SvOE~rD#^c<<=KwahF+cvQJL7e&% zkmDFR_=X8=*+F0$E{x;f%sHqU=z}N+pW}d??^VzK8O(9a9DE7_c9BkP9xjw0&p#Yd z2lP3KgHIU1<_kiLzeW9U*P*W<9K7-$q*Mpm0T( z_d3AA??ImdICxJ!?Dtfl-}}x#^ihC=--AwI4qgHeo7Tv!{)-F_Ui^MUzEIi+FJ6bu zRG+N<2JOSrg?iG#+lN86aiBd|NBeP)`$1lzH&`CLiWF=fInXA*q8)clv4RW=s1hL{ Qd<6d$s({V^dr++Z1IGh^PXGV_ diff --git a/MPChartExample/project.properties b/MPChartExample/project.properties index 4ab125693c..a8d309b24e 100644 --- a/MPChartExample/project.properties +++ b/MPChartExample/project.properties @@ -12,3 +12,4 @@ # Project target. target=android-19 +android.library.reference.1=../MPChartLib diff --git a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java index a7c1adb33d..f8027b645e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/components/AxisBase.java @@ -14,6 +14,8 @@ public abstract class AxisBase extends ComponentBase { private int mGridColor = Color.GRAY; + private float mGridLineWidth = 1f; + private int mAxisLineColor = Color.GRAY; private float mAxisLineWidth = 1f; @@ -108,6 +110,26 @@ public float getAxisLineWidth() { return mAxisLineWidth; } + /** + * Sets the width of the grid lines that are drawn away from each axis + * label. + * + * @param width + */ + public void setGridLineWidth(float width) { + mGridLineWidth = Utils.convertDpToPixel(width); + } + + /** + * Returns the width of the grid lines that are drawn away from each axis + * label. + * + * @return + */ + public float getGridLineWidth() { + return mGridLineWidth; + } + /** * Sets the color of the border surrounding the chart. * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java index 527922d8cf..a559a298f0 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRenderer.java @@ -164,6 +164,7 @@ public void renderGridLines(Canvas c) { }; mGridPaint.setColor(mXAxis.getGridColor()); + mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); for (int i = 0; i < mXAxis.getValues().size(); i += mXAxis.mAxisLabelModulus) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java index 990d42d4ce..8960ab3eb2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererBarChart.java @@ -86,6 +86,9 @@ public void renderGridLines(Canvas c) { float[] position = new float[] { 0f, 0f }; + + mGridPaint.setColor(mXAxis.getGridColor()); + mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); BarData bd = mChart.getData(); // take into consideration that multiple DataSets increase mDeltaX diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java index 285332dbf9..119f2fcebc 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/XAxisRendererHorizontalBarChart.java @@ -117,6 +117,9 @@ public void renderGridLines(Canvas c) { float[] position = new float[] { 0f, 0f }; + + mGridPaint.setColor(mXAxis.getGridColor()); + mGridPaint.setStrokeWidth(mXAxis.getGridLineWidth()); BarData bd = mChart.getData(); // take into consideration that multiple DataSets increase mDeltaX diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java index d173207f11..a0038787f1 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRenderer.java @@ -245,6 +245,7 @@ public void renderGridLines(Canvas c) { float[] position = new float[2]; mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); // draw the horizontal grid for (int i = 0; i < mYAxis.mEntryCount; i++) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java index 7fbf904f28..a960cb7553 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/YAxisRendererHorizontalBarChart.java @@ -161,6 +161,7 @@ public void renderGridLines(Canvas c) { float[] position = new float[2]; mGridPaint.setColor(mYAxis.getGridColor()); + mGridPaint.setStrokeWidth(mYAxis.getGridLineWidth()); // draw the horizontal grid for (int i = 0; i < mYAxis.mEntryCount; i++) { From 43046425fc2ed73d0d3f177759706116e02a9053 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 19:14:39 +0100 Subject: [PATCH 0145/1390] Fixed bug in BarChart, improved example. --- .../CubicLineChartActivity.java | 2 + .../HorizontalBarChartActivity.java | 19 ++++---- .../mpchartexample/LineChartActivity1.java | 1 + .../mpchartexample/LineChartActivity2.java | 1 + .../mpchartexample/RadarChartActivitry.java | 1 + .../notimportant/MainActivity.java | 41 ++++++++-------- .../mikephil/charting/charts/BarChart.java | 8 ++-- .../charting/charts/BarLineChartBase.java | 7 --- .../charting/charts/HorizontalBarChart.java | 47 +++++++++++++++++++ 9 files changed, 90 insertions(+), 37 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 7d50fe3a60..3d1e10f963 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -283,6 +283,8 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); data.setValueTypeface(tf); + data.setValueTextSize(9f); + data.setDrawValues(false); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 43232e875b..701ed94d86 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -41,7 +41,7 @@ public class HorizontalBarChartActivity extends DemoBase implements OnSeekBarCha protected HorizontalBarChart mChart; private SeekBar mSeekBarX, mSeekBarY; private TextView tvX, tvY; - + private Typeface tf; @Override @@ -59,10 +59,10 @@ protected void onCreate(Bundle savedInstanceState) { mChart = (HorizontalBarChart) findViewById(R.id.chart1); mChart.setOnChartValueSelectedListener(this); -// mChart.setHighlightEnabled(false); - + // mChart.setHighlightEnabled(false); + mChart.setDrawBarShadow(false); - + mChart.setDrawValueAboveBar(true); mChart.setDescription(""); @@ -76,7 +76,7 @@ protected void onCreate(Bundle savedInstanceState) { // draw shadows for each bar that show the maximum value // mChart.setDrawBarShadow(true); - + // mChart.setDrawXLabels(false); mChart.setDrawGridBackground(false); @@ -90,17 +90,19 @@ protected void onCreate(Bundle savedInstanceState) { xl.setTypeface(tf); xl.setDrawAxisLine(true); xl.setDrawGridLines(true); -// xl.setEnabled(false); + xl.setGridLineWidth(0.3f); + // xl.setEnabled(false); YAxis yl = mChart.getAxisLeft(); yl.setTypeface(tf); yl.setDrawAxisLine(true); yl.setDrawGridLines(true); + yl.setGridLineWidth(0.3f); YAxis yr = mChart.getAxisRight(); yr.setTypeface(tf); yr.setDrawAxisLine(true); - yr.setDrawGridLines(true); + yr.setDrawGridLines(false); setData(12, 50); mChart.animateY(2500); @@ -275,7 +277,8 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { return; RectF bounds = mChart.getBarBounds((BarEntry) e); - PointF position = mChart.getPosition(e, AxisDependency.LEFT); + PointF position = mChart.getPosition(e, mChart.getData().getDataSetByIndex(dataSetIndex) + .getAxisDependency()); Log.i("bounds", bounds.toString()); Log.i("position", position.toString()); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java index 3765902144..023218ed75 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity1.java @@ -323,6 +323,7 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); + data.setValueTextSize(10f); LimitLine ll1 = new LimitLine(130f, "Upper Limit"); ll1.setLineWidth(4f); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java index 9b58f437bc..f381c6073f 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/LineChartActivity2.java @@ -322,6 +322,7 @@ private void setData(int count, float range) { // create a data object with the datasets LineData data = new LineData(xVals, dataSets); data.setValueTextColor(Color.WHITE); + data.setValueTextSize(9f); // set data mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java index 8bc64815a2..b8e91db183 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/RadarChartActivitry.java @@ -192,6 +192,7 @@ public void setData() { RadarData data = new RadarData(xVals, sets); data.setValueTypeface(tf); data.setValueTextSize(8f); + data.setDrawValues(false); mChart.setData(data); diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java index 99c23cc462..4e4aeeb674 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/notimportant/MainActivity.java @@ -60,11 +60,14 @@ protected void onCreate(Bundle savedInstanceState) { ArrayList objects = new ArrayList(); - objects.add(new ContentItem("Line Chart 1", "A simple demonstration of the linechart.")); - objects.add(new ContentItem("Line Chart 2", "Another simple demonstration of the linechart.")); - objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); - objects.add(new ContentItem("Horizontal Bar Chart", "A simple demonstration of the horizontal bar chart.")); - objects.add(new ContentItem("Combined Chart", "Demonstrates how to create a combined chart.")); + objects.add(new ContentItem("Line Chart", "A simple demonstration of the linechart.")); + objects.add(new ContentItem("Line Chart (Dual YAxis)", + "Demonstration of the linechart with dual y-axis.")); + objects.add(new ContentItem("Bar Chart", "A simple demonstration of the bar chart.")); + objects.add(new ContentItem("Horizontal Bar Chart", + "A simple demonstration of the horizontal bar chart.")); + objects.add(new ContentItem("Combined Chart", + "Demonstrates how to create a combined chart (bar and line in this case).")); objects.add(new ContentItem("Pie Chart", "A simple demonstration of the pie chart.")); objects.add(new ContentItem("Scatter Chart", "A simple demonstration of the scatter chart.")); objects.add(new ContentItem("Stacked Bar Chart", @@ -79,7 +82,7 @@ protected void onCreate(Bundle savedInstanceState) { "Demonstration of drawing values into the chart per touch-gesture. With callbacks.")); objects.add(new ContentItem( "Charts in Fragments, awesome design.", - "Demonstration of charts inside Fragments. In this example the focus was on the design and look and feel of the chart.")); + "Demonstration of charts inside ViewPager Fragments. In this example the focus was on the design and look and feel of the chart.")); objects.add(new ContentItem( "BarChart inside ListView", "Demonstrates the usage of a BarChart inside a ListView item.")); @@ -103,7 +106,7 @@ protected void onCreate(Bundle savedInstanceState) { "Shows a LineChart with different background and line color.")); objects.add(new ContentItem( "Realtime Chart", - "This chart is fed with new data in realtime.")); + "This chart is fed with new data in realtime. It also restrains the view on the x-axis.")); objects.add(new ContentItem( "Dynamical data adding", "This Activity demonstrates dynamical adding of Entries and DataSets (real time graph).")); @@ -130,15 +133,15 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, LineChartActivity2.class); startActivity(i); break; - case 2: - i = new Intent(this, BarChartActivity.class); - startActivity(i); - break; - case 3: - i = new Intent(this, HorizontalBarChartActivity.class); - startActivity(i); - break; - case 4: + case 2: + i = new Intent(this, BarChartActivity.class); + startActivity(i); + break; + case 3: + i = new Intent(this, HorizontalBarChartActivity.class); + startActivity(i); + break; + case 4: i = new Intent(this, CombinedChartActivity.class); startActivity(i); break; @@ -167,8 +170,8 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { startActivity(i); break; case 11: -// i = new Intent(this, DrawChartActivity.class); -// startActivity(i); + // i = new Intent(this, DrawChartActivity.class); + // startActivity(i); AlertDialog.Builder b = new AlertDialog.Builder(this); b.setTitle("Feature not available"); @@ -208,7 +211,7 @@ public void onItemClick(AdapterView av, View v, int pos, long arg3) { i = new Intent(this, LineChartActivityColored.class); startActivity(i); break; - case 20 : + case 20: i = new Intent(this, RealtimeLineChartActivity.class); startActivity(i); break; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 6c5a25416e..d4ed7387c7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -223,12 +223,14 @@ public RectF getBarBounds(BarEntry e) { float y = e.getVal(); float x = e.getXIndex(); + float barWidth = 0.5f; + float spaceHalf = barspace / 2f; - float left = x - 0.5f + spaceHalf; - float right = x + 0.5f - spaceHalf; + float left = x - barWidth + spaceHalf; + float right = x + barWidth - spaceHalf; float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; - + RectF bounds = new RectF(left, top, right, bottom); getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 6bfcf3bf49..101dc61934 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -689,13 +689,6 @@ public PointF getPosition(Entry e, AxisDependency axis) { e.getXIndex(), e.getVal() }; - if (this instanceof BarChart) { - - BarDataSet set = (BarDataSet) mData.getDataSetForEntry(e); - if (set != null) - vals[0] += set.getBarSpace() / 2f; - } - getTransformer(axis).pointValuesToPixel(vals); return new PointF(vals[0], vals[1]); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java index 8ce78c4205..ce4c1904ce 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/HorizontalBarChart.java @@ -3,11 +3,17 @@ import android.content.Context; import android.graphics.Matrix; +import android.graphics.PointF; +import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import com.github.mikephil.charting.components.Legend.LegendPosition; import com.github.mikephil.charting.components.XAxis.XAxisPosition; +import com.github.mikephil.charting.components.YAxis.AxisDependency; +import com.github.mikephil.charting.data.BarDataSet; +import com.github.mikephil.charting.data.BarEntry; +import com.github.mikephil.charting.data.Entry; import com.github.mikephil.charting.renderer.HorizontalBarChartRenderer; import com.github.mikephil.charting.renderer.XAxisRendererHorizontalBarChart; import com.github.mikephil.charting.renderer.YAxisRendererHorizontalBarChart; @@ -132,6 +138,47 @@ protected void calcModulus() { .ceil((mData.getXValCount() * mXAxis.mLabelHeight) / (mViewPortHandler.contentHeight() * values[Matrix.MSCALE_Y])); } + + @Override + public RectF getBarBounds(BarEntry e) { + + BarDataSet set = mData.getDataSetForEntry(e); + + if (set == null) + return null; + + float barspace = set.getBarSpace(); + float y = e.getVal(); + float x = e.getXIndex(); + + float spaceHalf = barspace / 2f; + + float top = x - 0.5f + spaceHalf; + float bottom = x + 0.5f - spaceHalf; + float left = y >= 0 ? y : 0; + float right = y <= 0 ? y : 0; + + RectF bounds = new RectF(left, top, right, bottom); + + getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); + + return bounds; + } + + @Override + public PointF getPosition(Entry e, AxisDependency axis) { + + if (e == null) + return null; + + float[] vals = new float[] { + e.getVal(), e.getXIndex() + }; + + getTransformer(axis).pointValuesToPixel(vals); + + return new PointF(vals[0], vals[1]); + } /** * Returns the Highlight object (contains x-index and DataSet index) of the From c8d6d7fd7356212537f058bd94729c33e89fbd1b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 20:00:27 +0100 Subject: [PATCH 0146/1390] Added API level badge. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 998fdedd75..628eefd72d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) + [![Android Arsenal](http://img.shields.io/badge/Android%20Arsenal-MPAndroidChart-blue.svg?style=flat)](http://android-arsenal.com/details/1/741) [![Release](https://img.shields.io/github/release/PhilJay/MPAndroidChart.svg?label=maven central)](https://jitpack.io/#PhilJay/MPAndroidChart) [![API](https://img.shields.io/badge/API-8%2B-green.svg?style=flat)](https://android-arsenal.com/api?level=8) MPAndroidChart ======= From 6927a6db99ebc53ed2f05a2e8996bbc340664b77 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 22:10:31 +0100 Subject: [PATCH 0147/1390] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 628eefd72d..67d16379bc 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,8 @@ Getting Started For getting started, rely on the **"MPChartExample"** folder and check out the examples in that project. The example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). +For a **detailed documentation**, please refer the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). + Furthermore, here is some code to begin with. **Setup:** From 85382309eb26813a874ba1e4105815395fe13fb6 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 22:13:38 +0100 Subject: [PATCH 0148/1390] Update README.md --- README.md | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) diff --git a/README.md b/README.md index 67d16379bc..99b37b9d62 100644 --- a/README.md +++ b/README.md @@ -159,55 +159,6 @@ For getting started, rely on the **"MPChartExample"** folder and check out the e For a **detailed documentation**, please refer the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). -Furthermore, here is some code to begin with. - -**Setup:** - -For using a LineChart, BarChart, ScatterChart, CandleStickChart or PieChart , define it in .xml: -```xml - -``` -```java - LineChart chart = (LineChart) findViewById(R.id.chart); -``` - -or create it in code (and then **add it to a layout**): -```java - LineChart chart = new LineChart(Context); -``` - -**Styling:** - - - setDescription(String desc): Set a description text that appears in the bottom right corner of the chart. - - setDescriptionTypeface(Typeface t): Sets the Typeface used for drawing the description text. - - setDrawYValues(boolean enabled): If set to true, the actual drawn values will be drawn next to the points, bars, or pie slices of the chart. - - setValuePaintColor(int color): Sets the color used for drawing the values if setDrawYValues(...) is enabled. - - setValueTypeface(Typeface t): Sets the Typeface used for drawing the values if setDrawYValues(...) is enabled. - - setValueFormatter(DecimalFormat format): Sets a new `DecimalFormat` object that will be used to format all values inside the chart. If nothing is set, formatting (digits) is done automatically. - - setPaint(Paint p, int which): Replaces the specified default Paint object with a new one. This method can be used to replace any predefined Paint object with an own Paint object and develop a completely personalized design. - -**Getters and convenience:** -- public ChartData getDataCurrent(): Returns the ChartData object the chart currently displays. It contains all information concerning the displayed values such as minimum and maximum values, value counts, value sums, ... -- public float getYChartMin(): Returns the current minimum y-value that can be displayed by the chart - bottom line. -- public float getYChartMax(): Returns the current maximum y-value that can be displayed by the chart - top line. -- public float getAverage(): Returns the average value across all values the chart holds. -- public float getAverage(int type): Returns the average value for a specific DataSet type in the chart. This type is the type provided in the DataSet constructor. -- public PointF getCenter(): Returns the center point of the chart in pixels. -- public Paint getPaint(int which): Returns the requested Paint object from the chart. - - -**Gestures & Selecting:** - - - setTouchEnabled(boolean enabled): If set to ture, touch gestures (such as scaling and dragging) will be possible on the chart. NOTE: If touch-gestures are disabled, highlighting on touch is disabled as well. Default: true. - - setDragEnabled(boolean enabled): Enables/disables dragging for the chart. - - setScaleEnabled(boolean enabled): Enables/disables scaling for the chart. - - setOnChartValueSelectedListener(OnChartValueSelectedListener l): Sets a selection-listener to the chart that will generate callbacks when values are selected or unselected. The callback contains the selected values and their indices. - - setHighlightEnabled(boolean enabled): If set to true, highlighting/selecting values is possible on the chart. Default: true. - - public void highlightValues(Highlight[] highs): Highlights the specified entries in the chart. - **Other:** - saveToGallery(String title): Saves the current chart state as an image to the gallery. - saveToPath(String title, String pathOnSD): Saves the current chart state as an image to the specified path. From 370604bb4be2b8b35acb2e3cc1d3b41b00e90eb9 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 22:17:41 +0100 Subject: [PATCH 0149/1390] Update README.md --- README.md | 80 +++---------------------------------------------------- 1 file changed, 3 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 99b37b9d62..8d3ae1910e 100644 --- a/README.md +++ b/README.md @@ -52,14 +52,14 @@ Features **Core features:** - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - - Dragging (with touch-gesture) + - Dragging / Panning (with touch-gesture) - Finger drawing (draw values into the chart with touch-gesture) - Highlighting values (with customizeable popup-views) + - Multiple / Separate Axes - Save chart to SD-Card (as image, or as .txt file) - - Read .txt file chart-data - Predefined color templates - Legends (generated automatically, customizeable) - - Labels (both x- and y-axis, customizeable) + - Customizeable Axes (both x- and y-axis) - Animations (build up animations, on both x- and y-axis) - Limit lines (providing additional information, maximums, ...) - Fully customizeable (paints, typefaces, legends, colors, background, gestures, dashed lines, ...) @@ -166,80 +166,6 @@ For a **detailed documentation**, please refer the [**Wiki**](https://github.com - centerViewPort(int xIndex, float val): This method makes it possible to aim the center of the view (what you can see from the chart) to a specific position inside the chart, described by the index on the x-axis and the value on the y-axis. This also works very well in combination with the `setScaleMinima(...)` method. - fitScreen(): Resets all zooming and dragging and makes the chart fit exactly it's bounds. -**Adding data:** - -If you want to add values (data) to the chart, it has to be done via the - -```java - setData(ChartData data); -``` -method. The baseclass ChartData class encapsulates all data and information that is needed for the chart during rendering. For each type of chart, a different subclass of `ChartData` (e.g. `LineData`) exists that should be used for setting data for the chart. In the constructor, you can hand over an ArrayList as the values to display, and an additional ArrayList of String that will describe the labels on the x-axis. Example with the class `LineData` (extends `ChartData`), which is used for adding data to a `LineChart`: - -```java - public LineData(ArrayList xVals, ArrayList sets) { ... } -``` - -So, what is a DataSet and why do you need it? That is actually pretty simple. One DataSet object represents a group of entries (datatype Entry) inside the chart that belong together. It is designed to **logically separate different groups of values in the chart**. For each type of chart, a differnt object that extends `DataSet` (e.g. `LineDataSet`) exists that allows specific styling. - -As an example, you might want to display the quarterly revenue of two different companies over one year in a `LineChart`. In that case, it would be recommended to create two different LineDataSet objects, each containing four values (one for each quarter). As an ArrayList to describe the labels on the x-axis, you would simply provide the four Strings "1.Q", "2.Q", "3.Q", "4.Q". - -Of course, it is also possible to provide just one LineDataSet object containing all 8 values for the two companys. - -So how to setup a LineDataSet object? -```java - public LineDataSet(ArrayList yVals, String label) { ... } -``` - -When looking at the constructor, it is visible that the LineDataSet needs an ArrayList of type Entry and a `String` used to describe the `LineDataSet` and as a label used for the `Legend`. Furthermore this label can be used to find the `LineDataSet` amongst other `LineDataSet` objects in the `LineData` object. - -The ArrayList of type Entry encapsulates all values of the chart. A Entry object is an additional wrapper around a value and holds the value itself, and it's position on the x-axis (the index inside the ArrayList of String of the LineData object the value is mapped to): -```java - public Entry(float val, int xIndex) { ... } -``` - -Putting it all together (example of two companies with quarterly revenue over one year): - -At first, create the lists of type Entry that will hold your values: - -```java - ArrayList valsComp1 = new ArrayList(); - ArrayList valsComp2 = new ArrayList(); -``` -Then, fill the lists with Entry objects. Make sure the entry objects contain the correct indices to the x-axis. (of course, a loop can be used here, in that case, the counter variable of the loop could be the index on the x-axis). - -```java - Entry c1e1 = new Entry(100.000f, 0); // 0 == quarter 1 - valsComp1.add(c1e1); - Entry c1e2 = new Entry(50.000f, 1); // 1 == quarter 2 ... - valsComp1.add(c1e2); - // and so on ... - - Entry c2e1 = new Entry(120.000f, 0); // 0 == quarter 1 - valsComp2.add(c2e1); - Entry c2e2 = new Entry(110.000f, 1); // 1 == quarter 2 ... - valsComp2.add(c2e2); - //... -``` - -Now that we have our lists of Entry objects, the LineDataSet objects can be created: -```java - LineDataSet setComp1 = new LineDataSet(valsComp1, "Company 1"); - LineDataSet setComp2 = new LineDataSet(valsComp2, "Company 2"); -``` -Last but not least, we create a list of DataSets and a list of x legend entries and build our ChartData object: - -```java - ArrayList dataSets = new ArrayList(); - dataSets.add(setComp1); - dataSets.add(setComp2); - - ArrayList xVals = new ArrayList(); - xVals.add("1.Q"); xVals.add("2.Q"); xVals.add("3.Q"); xVals.add("4.Q"); - - LineData data = new LineData(xVals, dataSets); - mLineChart.setData(data); -``` - **Setting colors:** Since release [v1.4.0](https://github.com/PhilJay/MPAndroidChart/releases/tag/v1.4.0), the `ColorTemplate` object that was responsible for setting colors in previous releases is no longer needed. Nevertheless, it still holds all predefined color arrays (e.g. `ColorTemplate.VORDIPLOM_COLORS` and provides convenience methods for transforming colors from the resources (resource integers) into "real" colors. From 1901fd82c5ea40fca51fa4072755703258dbd995 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Fri, 27 Feb 2015 22:24:20 +0100 Subject: [PATCH 0150/1390] Update README.md --- README.md | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/README.md b/README.md index 8d3ae1910e..e0e0c79b1c 100644 --- a/README.md +++ b/README.md @@ -166,48 +166,6 @@ For a **detailed documentation**, please refer the [**Wiki**](https://github.com - centerViewPort(int xIndex, float val): This method makes it possible to aim the center of the view (what you can see from the chart) to a specific position inside the chart, described by the index on the x-axis and the value on the y-axis. This also works very well in combination with the `setScaleMinima(...)` method. - fitScreen(): Resets all zooming and dragging and makes the chart fit exactly it's bounds. -**Setting colors:** - -Since release [v1.4.0](https://github.com/PhilJay/MPAndroidChart/releases/tag/v1.4.0), the `ColorTemplate` object that was responsible for setting colors in previous releases is no longer needed. Nevertheless, it still holds all predefined color arrays (e.g. `ColorTemplate.VORDIPLOM_COLORS` and provides convenience methods for transforming colors from the resources (resource integers) into "real" colors. - -Instead of the `ColorTemplate`, colors can now be specified directly via `DataSet` object, which allows separate styling for each `DataSet`. - -In this short example, we have our two different `LineDataSet` objects representing the quarterly revenues of two companies (previously mentioned in the **Adding data** tutorial), for which we now want to set different colors. - -What we want: - - - the values of "Company 1" should be represented by four different variations of the color "red" - - the values of "Company 2" should be represented by four different variations of the color "green" - -This is what the code looks like: - -```java - LineDataSet setComp1 = new LineDataSet(valsComp1, "Company 1"); - - // sets colors for the dataset, resolution of the resource name to a "real" color is done internally - setComp1.setColors(new int[] { R.color.red1, R.color.red2, R.color.red3, R.color.red4 }, Context); - - LineDataSet setComp2 = new LineDataSet(valsComp2, "Company 2"); - setComp2.setColors(new int[] { R.color.green1, R.color.green2, R.color.green3, R.color.green4 }, Context); -``` - -Besides that, there are many other ways for setting colors for a `DataSet`. Here is the full documentation: - - - `setColors(int [] colors, Context c)`: Sets the colors that should be used fore this DataSet. Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. You can use "new int[] { R.color.red, R.color.green, ... }" to provide colors for this method. Internally, the colors are resolved using getResources().getColor(...). - - `setColors(int [] colors)`: Sets the colors that should be used fore this DataSet. Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. Make sure that the colors are already prepared (by calling getResources().getColor(...)) before adding them to the DataSet. - - `setColors(ArrayList colors)`: Sets the colors that should be used fore this DataSet. Colors are reused as soon as the number of Entries the DataSet represents is higher than the size of the colors array. Make sure that the colors are already prepared (by calling getResources().getColor(...)) before adding them to the DataSet. - - `setColor(int color)`: Sets the one and ONLY color that should be used for this DataSet. Internally, this recreates the colors array and adds the specified color. - -`ColorTemplate` example: - -```java -LineDataSet set = new LineDataSet(...); -set.setColors(ColorTemplate.VORDIPLOM_COLORS); -``` - -If no colors are set for a `DataSet`, default colors are used. - - **Displaying / styling legends:** By default, all chart types support legends and will automatically generate and draw a legend after setting data for the chart. If a legend should be drawn or not can be enabled/disabled using the From ca027fdfda11cda3d9fd9cf26addf914aed80341 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:07:51 +0100 Subject: [PATCH 0151/1390] Update README.md --- README.md | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/README.md b/README.md index e0e0c79b1c..070aa42ada 100644 --- a/README.md +++ b/README.md @@ -192,56 +192,6 @@ For customizing the `Legend`, use you can retreive the `Legend` object from the // and many more... ``` - -**Displaying / styling labels:** - -Labels (classes `XLabel` and `YLabel`) are used to describe the values of the chart on the x- and y-axis. While the x-axis labels display what is handed over to the `ChartData` object as an `ArrayList` ("xVals"), the y-axis labels depend on the actual values that are set for the chart. - -Labels can be enabled/disabled, using the methods: - - - `setDrawXLabels(boolean enabled)` - - `setDrawYLabels(boolean enabled)` - -the chart provides. -In order to apply a different styling to the labels, the methods `getYLabels()` and `getXLabels()` can be used to acquire the labels object and modify it. - -Example: - -```java -XLabels xl = mChart.getXLabels(); -xl.setPosition(XLabelPosition.BOTTOM); // set the position -xl.setTypeface(...); // set a different font -xl.setTextSize(12f); // set the textsize -xl.setSpaceBetweenLabels(3); // set how many characters of space should be between the labels -//... and more - -YLabels yl = mChart.getYLabels(); -yl.setPosition(YLabelPosition.BOTH_SIDED); // set the position -yl.setTypeface(...); // set a different font -yl.setTextSize(12f); // set the textsize -yl.setLabelCount(6); // set how many label entries should be displayed -//... and more - -``` - -**Limit Lines:** - -Limit lines (class `LimitLine`) are (as the name might indicate) plain and simple lines that can be set for all `Line-, Bar- and ScatterData` objects. They can be used to **provide additional information** for the user. - -As an example, your chart might display various blood pressure measurement results the user logged with an application. In order to inform the user that a systolic blood pressure of over 140 mmHg is considered to be a health risk, you could add a `LimitLine` at 140 to provide that information. - -```java - -LineData ld = new LineData(...); - -LimitLine ll = new LimitLine(140f); -ll.setLineColor(Color.RED); -ll.setLineWidth(4f); -// .. and more styling options - -ld.addLimitLine(ll); -``` - **Dynamically adding data (real time):** For **adding new data** to the chart dynamically, there are various methods that allow to either add `Entry` objects to an existing `DataSet` or `DataSet` objects to an existing `ChartData` object. @@ -284,8 +234,6 @@ mChart.animateXY(3000, 3000); // animate horizontal and vertical 3000 millisecon If `animate(...)` (of any kind) is called, no further calling of `invalidate()` is necessary to refresh the chart. -In order to support animations below Honeycomb, this library makes use of the awesome [**nineoldandroids library**](https://github.com/JakeWharton/NineOldAndroids) developed by Jake Wharton. - More documentation and example code coming soon. This chart library is intended to fill the gap between popular charting libraries like "GraphView" or "achartengine". From 7d37dcb9757b84b801084858dd7c0189dbb7ecbf Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:17:25 +0100 Subject: [PATCH 0152/1390] Update README.md --- README.md | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/README.md b/README.md index 070aa42ada..7f7f6b117a 100644 --- a/README.md +++ b/README.md @@ -192,48 +192,6 @@ For customizing the `Legend`, use you can retreive the `Legend` object from the // and many more... ``` -**Dynamically adding data (real time):** - -For **adding new data** to the chart dynamically, there are various methods that allow to either add `Entry` objects to an existing `DataSet` or `DataSet` objects to an existing `ChartData` object. - -Class `DataSet` (and all subclasses): - - `addEntry(Entry e)`: Adds the given `Entry` object to the `DataSet`. - -Class `ChartData` (and all subclasses): - - `addEntry(Entry e, int dataSetIndex)`: Adds the given `Entry` to the `DataSet` at the specified dataset index. - - `addDataSet(DataSet d)`: Adds the given `DataSet` object to the `ChartData` object. - -In addition to that, there are also methods for **removing data dynamically**. - -Class `DataSet` (and all subclasses): - - `public boolean removeEntry(Entry e)`: Removes the given `Entry` object from the `DataSet`. Returns true if successful. - - `public boolean removeEntry(int xIndex)`: Removes the `Entry` at the given x-index from the `DataSet`. Returns true if successful. - -Class `ChartData` (and all subclasses): - - `public boolean removeEntry(Entry e, int dataSetIndex)`: Removes the given `Entry` object from the `DataSet` with the given dataset index. Returns true if successful. - - `public boolean removeEntry(int xIndex, int dataSetIndex)`: Removes the `Entry` at the given x-index from the `DataSet` with the given dataset index. Returns true if successful. - - `public boolean removeDataSet(DataSet d)`: Removes the given `DataSet` object from the `ChartData` object. Returns true if successful. - - `public boolean removeDataSet(int index)`: Removes the `DataSet` at the given index from the `ChartData` object. Returns true if successful. - - -**Animations:** - -All chart types support animations that can be used to create / build up the chart in an awesome looking way. Three different kinds of animation methods exist that animate either both, or x- and y-axis separately: - - - `animateX(int durationMillis)`: Animates the charts values on the horizontal axis, meaning that the chart will build up within the specified time from left to right. - - `animateY(int durationMillis)`: Animates the charts values on the vertical axis, meaning that the chart will build up within the specified time from bottom to top. - - `animateXY(int xDuration, int yDuration)`: Animates both horizontal and vertical axis, resulting in a left/right bottom/top build-up. - -```java -mChart.animateX(3000); // animate horizontal 3000 milliseconds -// or: -mChart.animateY(3000); // animate vertical 3000 milliseconds -// or: -mChart.animateXY(3000, 3000); // animate horizontal and vertical 3000 milliseconds -``` - -If `animate(...)` (of any kind) is called, no further calling of `invalidate()` is necessary to refresh the chart. - More documentation and example code coming soon. This chart library is intended to fill the gap between popular charting libraries like "GraphView" or "achartengine". From 27b7ec16d1cc530921131a2df1fcb9780ea77655 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:20:40 +0100 Subject: [PATCH 0153/1390] Update README.md --- README.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/README.md b/README.md index 7f7f6b117a..109a604b4b 100644 --- a/README.md +++ b/README.md @@ -159,13 +159,6 @@ For getting started, rely on the **"MPChartExample"** folder and check out the e For a **detailed documentation**, please refer the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). -**Other:** - - saveToGallery(String title): Saves the current chart state as an image to the gallery. - - saveToPath(String title, String pathOnSD): Saves the current chart state as an image to the specified path. - - setScaleMinima(float x, float y): Sets the minimum scale factors for x- and y-axis. If set for example to 3f, the user will not be able to fully zoom out. - - centerViewPort(int xIndex, float val): This method makes it possible to aim the center of the view (what you can see from the chart) to a specific position inside the chart, described by the index on the x-axis and the value on the y-axis. This also works very well in combination with the `setScaleMinima(...)` method. - - fitScreen(): Resets all zooming and dragging and makes the chart fit exactly it's bounds. - **Displaying / styling legends:** By default, all chart types support legends and will automatically generate and draw a legend after setting data for the chart. If a legend should be drawn or not can be enabled/disabled using the From 61b493deebb58907cf8df7127c4c7db1093ef64a Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:26:34 +0100 Subject: [PATCH 0154/1390] Update README.md --- README.md | 38 +++++--------------------------------- 1 file changed, 5 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 109a604b4b..ba70af84d7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ MPAndroidChart ======= -A simple charting library for Android, supporting line-, bar-, scatter-, candlestick- and piecharts, as well as scaling, dragging, selecting and animations. **Supporting Android 2.2 (API level 8)** and upwards. +A simple charting library for Android, supporting line-, bar-, scatter-, candlestick-, pie- and radarcharts (spider web), as well as scaling, dragging, selecting and animations. **Supporting Android 2.2 (API level 8)** and upwards. Remember: *It's all about the looks.* @@ -53,6 +53,7 @@ Features **Core features:** - Scaling on both axes (with touch-gesture, axes separately or pinch-zoom) - Dragging / Panning (with touch-gesture) + - Combined-Charts (line-, bar-, scatter-, candle-data) - Finger drawing (draw values into the chart with touch-gesture) - Highlighting values (with customizeable popup-views) - Multiple / Separate Axes @@ -157,38 +158,9 @@ Getting Started For getting started, rely on the **"MPChartExample"** folder and check out the examples in that project. The example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). -For a **detailed documentation**, please refer the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). - -**Displaying / styling legends:** - -By default, all chart types support legends and will automatically generate and draw a legend after setting data for the chart. If a legend should be drawn or not can be enabled/disabled using the - - - `setDrawLegend(boolean enabled)` - -method. - -The number of entries the automatically generated legend contains depends on the number of different colors (across all `DataSet` objects) as well as on the `DataSet` labels. The labels of the `Legend` depend on the labels set for the used `DataSet` objects in the chart. If no labels for the `DataSet` objects have been specified, the chart will automatically generate them. If multiple colors are used for one `DataSet`, those colors are grouped and only described by one label. - -For customizing the `Legend`, use you can retreive the `Legend` object from the chart **after setting data** using the `getLegend()` method. - -```java - // setting data... - chart.setData(....); - - Legend l = chart.getLegend(); - l.setFormSize(10f); // set the size of the legend forms/shapes - l.setForm(LegendForm.CIRCLE); // set what type of form/shape should be used - l.setPosition(LegendPosition.BELOW_CHART_LEFT); - l.setTypeface(...); - l.setXEntrySpace(5f); // set the space between the legend entries on the x-axis - l.setYEntrySpace(5f); // set the space between the legend entries on the y-axis - // and many more... -``` - -More documentation and example code coming soon. - -This chart library is intended to fill the gap between popular charting libraries like "GraphView" or "achartengine". - +Documentation +======= +For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). License ======= From a2e92e6ef076c57be7dbfe2f7fd923dd4c4cf91b Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:41:06 +0100 Subject: [PATCH 0155/1390] Update README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ba70af84d7..6fb5fcc71c 100644 --- a/README.md +++ b/README.md @@ -153,15 +153,12 @@ dependencies { - Import the library folder (`MPChartLib`) into your Eclipse workspace - Add it as a reference to your project: [referencing library projects in Eclipse](http://developer.android.com/tools/projects/projects-eclipse.html#ReferencingLibraryProject) -Getting Started -======= - -For getting started, rely on the **"MPChartExample"** folder and check out the examples in that project. The example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). - Documentation ======= For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). +Furthermore, you can also rely on the **"MPChartExample"** folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). + License ======= Copyright 2014 Philipp Jahoda From 8ccc75ffe075c390ee8dcb9073d65665eaff42a7 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 11:41:47 +0100 Subject: [PATCH 0156/1390] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6fb5fcc71c..75072874eb 100644 --- a/README.md +++ b/README.md @@ -157,7 +157,7 @@ Documentation ======= For a **detailed documentation**, please have a look at the [**Wiki**](https://github.com/PhilJay/MPAndroidChart/wiki). -Furthermore, you can also rely on the **"MPChartExample"** folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). +Furthermore, you can also rely on the [**MPChartExample**](https://github.com/PhilJay/MPAndroidChart/tree/master/MPChartExample) folder and check out the example code in that project. The corresponding application to the example project is also [**available in the Google PlayStore**](https://play.google.com/store/apps/details?id=com.xxmassdeveloper.mpchartexample). License ======= From 542913082c0ff137c9eeba23f2f0af6ad4cc71b0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 15:23:07 +0100 Subject: [PATCH 0157/1390] Fixed BarChart highlight crash (issue #390). --- .../mpchartexample/StackedBarActivity.java | 2 + .../mikephil/charting/charts/BarChart.java | 37 ++++++++++++++----- .../mikephil/charting/charts/Chart.java | 4 ++ 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index a372a26e1a..a43c408b51 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -77,6 +77,8 @@ protected void onCreate(Bundle savedInstanceState) { // yLabels.setPosition(YLabelPosition.BOTH_SIDED); yLabels.setLabelCount(5); yLabels.setValueFormatter(new MyValueFormatter()); + + mChart.getAxisRight().setValueFormatter(new MyValueFormatter()); XAxis xLabels = mChart.getXAxis(); xLabels.setPosition(XAxisPosition.TOP); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index d4ed7387c7..06c75d9155 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -136,13 +136,28 @@ protected Highlight getHighlight(double xPosition, double yPosition) { // only one dataset exists if (!mData.isGrouped()) { - int dataSet = 0; + int dataSetIndex = 0; int xIndex = (int) Math.round(xPosition); - if (!mData.getDataSetByIndex(dataSet).isStacked()) - return new Highlight(xIndex, dataSet); + // check bounds + if (xIndex < 0) { + xIndex = 0; + dataSetIndex = 0; + } else if (xIndex >= valCount) { + xIndex = valCount - 1; + dataSetIndex = setCount - 1; + } + + // check bounds + if (dataSetIndex < 0) + dataSetIndex = 0; + else if (dataSetIndex >= setCount) + dataSetIndex = setCount - 1; + + if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) + return new Highlight(xIndex, dataSetIndex); else - return getStackedHighlight(xIndex, dataSet, yPosition); + return getStackedHighlight(xIndex, dataSetIndex, yPosition); // if this bardata is grouped into more datasets } else { @@ -165,7 +180,7 @@ protected Highlight getHighlight(double xPosition, double yPosition) { if (mLogEnabled) Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - // check bounds + // check bounds if (xIndex < 0) { xIndex = 0; dataSetIndex = 0; @@ -199,9 +214,13 @@ else if (dataSetIndex >= setCount) protected Highlight getStackedHighlight(int xIndex, int dataSet, double yValue) { BarEntry entry = mData.getDataSetByIndex(dataSet).getEntryForXIndex(xIndex); - int stackIndex = entry.getClosestIndexAbove((float) yValue); - Highlight h = new Highlight(xIndex, dataSet, stackIndex); - return h; + + if (entry != null) { + int stackIndex = entry.getClosestIndexAbove((float) yValue); + Highlight h = new Highlight(xIndex, dataSet, stackIndex); + return h; + } else + return null; } /** @@ -230,7 +249,7 @@ public RectF getBarBounds(BarEntry e) { float right = x + barWidth - spaceHalf; float top = y >= 0 ? y : 0; float bottom = y <= 0 ? y : 0; - + RectF bounds = new RectF(left, top, right, bottom); getTransformer(set.getAxisDependency()).rectValueToPixel(bounds); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index 665e6e3f91..b5fbc8ac68 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -485,6 +485,10 @@ public void highlightTouch(Highlight high) { if (high == null) mIndicesToHightlight = null; else { + +// if(mLogEnabled) + + Log.i(LOG_TAG, "Highlighted: " + high.toString()); // set the indices to highlight mIndicesToHightlight = new Highlight[] { From 90c2662d33b65ccf555fb8600e8031f39b1e1fa0 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 16:01:18 +0100 Subject: [PATCH 0158/1390] Fixed issue in stacked-barchart concerning disappearing values. --- .../mikephil/charting/charts/BarChart.java | 36 +++------ .../mikephil/charting/charts/Chart.java | 59 ++++++++------- .../charting/renderer/BarChartRenderer.java | 31 +++++--- .../renderer/HorizontalBarChartRenderer.java | 74 +++++++++++-------- 4 files changed, 104 insertions(+), 96 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index 06c75d9155..f00ea9c26f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -132,33 +132,21 @@ protected Highlight getHighlight(double xPosition, double yPosition) { int setCount = mData.getDataSetCount(); int valCount = mData.getXValCount(); + int dataSetIndex = 0; + int xIndex = 0; // only one dataset exists if (!mData.isGrouped()) { - int dataSetIndex = 0; - int xIndex = (int) Math.round(xPosition); + xIndex = (int) Math.round(xPosition); - // check bounds + // check bounds if (xIndex < 0) { xIndex = 0; - dataSetIndex = 0; } else if (xIndex >= valCount) { xIndex = valCount - 1; - dataSetIndex = setCount - 1; } - // check bounds - if (dataSetIndex < 0) - dataSetIndex = 0; - else if (dataSetIndex >= setCount) - dataSetIndex = setCount - 1; - - if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) - return new Highlight(xIndex, dataSetIndex); - else - return getStackedHighlight(xIndex, dataSetIndex, yPosition); - // if this bardata is grouped into more datasets } else { @@ -174,13 +162,13 @@ else if (dataSetIndex >= setCount) + groupSpaceSum + ", baseNoSpace: " + baseNoSpace); - int dataSetIndex = (int) baseNoSpace % setCount; - int xIndex = (int) baseNoSpace / setCount; + dataSetIndex = (int) baseNoSpace % setCount; + xIndex = (int) baseNoSpace / setCount; if (mLogEnabled) Log.i(LOG_TAG, "xIndex: " + xIndex + ", dataSet: " + dataSetIndex); - // check bounds + // check bounds if (xIndex < 0) { xIndex = 0; dataSetIndex = 0; @@ -194,12 +182,12 @@ else if (dataSetIndex >= setCount) dataSetIndex = 0; else if (dataSetIndex >= setCount) dataSetIndex = setCount - 1; - - if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) - return new Highlight(xIndex, dataSetIndex); - else - return getStackedHighlight(xIndex, dataSetIndex, yPosition); } + + if (!mData.getDataSetByIndex(dataSetIndex).isStacked()) + return new Highlight(xIndex, dataSetIndex); + else + return getStackedHighlight(xIndex, dataSetIndex, yPosition); } /** diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index b5fbc8ac68..eff8b1371f 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -485,9 +485,8 @@ public void highlightTouch(Highlight high) { if (high == null) mIndicesToHightlight = null; else { - -// if(mLogEnabled) - + + if (mLogEnabled) Log.i(LOG_TAG, "Highlighted: " + high.toString()); // set the indices to highlight @@ -1092,32 +1091,32 @@ public void setDrawMarkerViews(boolean enabled) { mDrawMarkerViews = enabled; } -// /** -// * sets the draw color for the value paint object -// * -// * @param color -// */ -// public void setValueTextColor(int color) { -// mRenderer.getPaintValues().setColor(color); -// } -// -// /** -// * Sets the font size of the values that are drawn inside the chart. -// * -// * @param size -// */ -// public void setValueTextSize(float size) { -// mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); -// } -// -// /** -// * sets a typeface for the value-paint -// * -// * @param t -// */ -// public void setValueTypeface(Typeface t) { -// mRenderer.getPaintValues().setTypeface(t); -// } + // /** + // * sets the draw color for the value paint object + // * + // * @param color + // */ + // public void setValueTextColor(int color) { + // mRenderer.getPaintValues().setColor(color); + // } + // + // /** + // * Sets the font size of the values that are drawn inside the chart. + // * + // * @param size + // */ + // public void setValueTextSize(float size) { + // mRenderer.getPaintValues().setTextSize(Utils.convertDpToPixel(size)); + // } + // + // /** + // * sets a typeface for the value-paint + // * + // * @param t + // */ + // public void setValueTypeface(Typeface t) { + // mRenderer.getPaintValues().setTypeface(t); + // } /** * returns the x-value at the given index @@ -1176,7 +1175,7 @@ public T getData() { public float getPercentOfTotal(float val) { return val / mData.getYValueSum() * 100f; } - + /** * sets the typeface for the description paint * diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 9451d89696..08b8584200 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -241,13 +241,6 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) - break; - - if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) - || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) - continue; - BarEntry e = entries.get(j / 2); float[] vals = e.getVals(); @@ -256,6 +249,13 @@ public void drawValues(Canvas c) { // non-stacked // in between if (vals == null) { + + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) + break; + + if (!mViewPortHandler.isInBoundsY(valuePoints[j + 1]) + || !mViewPortHandler.isInBoundsLeft(valuePoints[j])) + continue; drawValue(c, e.getVal(), valuePoints[j], valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset), formatter); @@ -276,10 +276,19 @@ public void drawValues(Canvas c) { trans.pointValuesToPixel(transformed); for (int k = 0; k < transformed.length; k += 2) { - - drawValue(c, vals[k / 2], valuePoints[j], - transformed[k + 1] - + (vals[k / 2] >= 0 ? posOffset : negOffset), formatter); + + float x = valuePoints[j]; + float y = transformed[k + 1] + + (vals[k / 2] >= 0 ? posOffset : negOffset); + + if (!mViewPortHandler.isInBoundsRight(x)) + break; + + if (!mViewPortHandler.isInBoundsY(y) + || !mViewPortHandler.isInBoundsLeft(x)) + continue; + + drawValue(c, vals[k / 2], x, y, formatter); } } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 993ff11076..74be3fa939 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -21,16 +21,13 @@ */ public class HorizontalBarChartRenderer extends BarChartRenderer { - private float xOffset = 0f; - private float yOffset = 0f; + private float mYOffset = 0f; public HorizontalBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { super(chart, animator, viewPortHandler); mValuePaint.setTextAlign(Align.LEFT); - yOffset = Utils.calcTextHeight(mValuePaint, "Q"); - xOffset = Utils.convertDpToPixel(4f); } protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { @@ -58,7 +55,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { if (noStacks) { prepareBar(x, y, dataSet.getBarSpace(), trans); - + // avoid drawing outofbounds values if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) break; @@ -121,7 +118,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { c.drawRect(mBarRect, mRenderPaint); } } - + // avoid drawing outofbounds values if (!mViewPortHandler.isInBoundsTop(mBarRect.bottom)) break; @@ -142,11 +139,13 @@ public void drawValues(Canvas c) { // calculate the correct offset depending on the draw position of // the value - posOffset = (drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.calcTextHeight( - mValuePaint, - "8") * 1.5f); - negOffset = (drawValueAboveBar ? Utils.calcTextHeight(mValuePaint, "8") * 1.5f : -Utils - .convertDpToPixel(5)); + negOffset = drawValueAboveBar ? -Utils.convertDpToPixel(5) : Utils.convertDpToPixel(5); + posOffset = drawValueAboveBar ? Utils.convertDpToPixel(5) : -Utils.convertDpToPixel(5); + + if (drawValueAboveBar) + mValuePaint.setTextAlign(Align.LEFT); + else + mValuePaint.setTextAlign(Align.RIGHT); for (int i = 0; i < mChart.getBarData().getDataSetCount(); i++) { @@ -158,6 +157,8 @@ public void drawValues(Canvas c) { // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); + mYOffset = Utils.calcTextHeight(mValuePaint, "10") / 2f; + ValueFormatter formatter = dataSet.getValueFormatter(); Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); @@ -176,14 +177,14 @@ public void drawValues(Canvas c) { if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) break; - - if(!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + + if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) continue; float val = entries.get(j / 2).getVal(); - drawValue(c, val, valuePoints[j], - valuePoints[j + 1] + (val >= 0 ? posOffset : negOffset), formatter); + drawValue(c, val, valuePoints[j] + (val >= 0 ? posOffset : negOffset), + valuePoints[j + 1], formatter); } // if each value of a potential stack should be drawn @@ -191,15 +192,6 @@ public void drawValues(Canvas c) { for (int j = 0; j < (valuePoints.length - 1) * mAnimator.getPhaseX(); j += 2) { - if (!mViewPortHandler.isInBoundsX(valuePoints[j])) - continue; - - if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) - break; - - if(!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) - continue; - BarEntry e = entries.get(j / 2); float[] vals = e.getVals(); @@ -209,8 +201,18 @@ public void drawValues(Canvas c) { // in between if (vals == null) { - drawValue(c, e.getVal(), valuePoints[j], - valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset), + if (!mViewPortHandler.isInBoundsX(valuePoints[j])) + continue; + + if (!mViewPortHandler.isInBoundsTop(valuePoints[j + 1])) + break; + + if (!mViewPortHandler.isInBoundsBottom(valuePoints[j + 1])) + continue; + + drawValue(c, e.getVal(), valuePoints[j] + + (e.getVal() >= 0 ? posOffset : negOffset), + valuePoints[j + 1], formatter); } else { @@ -230,10 +232,20 @@ public void drawValues(Canvas c) { for (int k = 0; k < transformed.length; k += 2) { - drawValue(c, vals[k / 2], - transformed[k], valuePoints[j+1] - + (vals[k / 2] >= 0 ? posOffset : negOffset), - formatter); + float x = transformed[k] + + (vals[k / 2] >= 0 ? posOffset : negOffset); + float y = valuePoints[j + 1]; + + if (!mViewPortHandler.isInBoundsX(x)) + continue; + + if (!mViewPortHandler.isInBoundsTop(y)) + break; + + if (!mViewPortHandler.isInBoundsBottom(y)) + continue; + + drawValue(c, vals[k / 2], x, y, formatter); } } } @@ -273,7 +285,7 @@ public float[] getTransformedValues(Transformer trans, ArrayList entri @Override protected void drawValue(Canvas c, float val, float xPos, float yPos, ValueFormatter formatter) { - super.drawValue(c, val, xPos + xOffset, yPos + yOffset, formatter); + super.drawValue(c, val, xPos, yPos + mYOffset, formatter); } @Override From 9dfa682f858b6b77133012525edea05ec726ee5e Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 16:23:06 +0100 Subject: [PATCH 0159/1390] Fixed issue #391. --- .../mpchartexample/BarChartActivity.java | 1 + .../HorizontalBarChartActivity.java | 1 - .../mpchartexample/StackedBarActivity.java | 2 + .../mikephil/charting/data/BarEntry.java | 2 +- .../charting/renderer/BarChartRenderer.java | 55 +++++++++++++++---- .../renderer/HorizontalBarChartRenderer.java | 15 +++++ 6 files changed, 62 insertions(+), 14 deletions(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java index aad8f99fee..352db3a3e7 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/BarChartActivity.java @@ -167,6 +167,7 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.actionToggleStartzero: { mChart.getAxisLeft().setStartAtZero(!mChart.getAxisLeft().isStartAtZeroEnabled()); mChart.getAxisRight().setStartAtZero(!mChart.getAxisRight().isStartAtZeroEnabled()); + mChart.notifyDataSetChanged(); mChart.invalidate(); break; } diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java index 701ed94d86..db15dfc0db 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/HorizontalBarChartActivity.java @@ -21,7 +21,6 @@ import com.github.mikephil.charting.components.XAxis; import com.github.mikephil.charting.components.XAxis.XAxisPosition; import com.github.mikephil.charting.components.YAxis; -import com.github.mikephil.charting.components.YAxis.AxisDependency; import com.github.mikephil.charting.data.BarData; import com.github.mikephil.charting.data.BarDataSet; import com.github.mikephil.charting.data.BarEntry; diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java index a43c408b51..2019c32c22 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/StackedBarActivity.java @@ -71,6 +71,8 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setPinchZoom(false); mChart.setDrawBarShadow(false); + + mChart.setDrawValueAboveBar(false); // change the position of the y-labels YAxis yLabels = mChart.getAxisLeft(); diff --git a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java index 52de15090a..b472e41ee5 100644 --- a/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java +++ b/MPChartLib/src/com/github/mikephil/charting/data/BarEntry.java @@ -118,7 +118,7 @@ public float getBelowSum(int stackIndex) { float remainder = 0f; int index = mVals.length - 1; - while(index > stackIndex) { + while(index > stackIndex && index >= 0) { remainder += mVals[index]; index--; } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java index 08b8584200..8db89a2389 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/BarChartRenderer.java @@ -161,7 +161,7 @@ protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) { * @param barspace the space between bars */ protected void prepareBar(float x, float y, float barspace, Transformer trans) { - + float barWidth = 0.5f; float spaceHalf = barspace / 2f; @@ -181,6 +181,30 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { } } + /** + * Prepares a bar for being highlighted. + * + * @param x the x-position + * @param y the y-position + * @param barspace the space between bars + * @param from + * @param trans + */ + protected void prepareBarHighlight(float x, float y, float barspace, float from, Transformer trans) { + + float barWidth = 0.5f; + + float spaceHalf = barspace / 2f; + float left = x - barWidth + spaceHalf; + float right = x + barWidth - spaceHalf; + float top = y >= from ? y : from; + float bottom = y <= from ? y : from; + + mBarRect.set(left, top, right, bottom); + + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + } + @Override public void drawValues(Canvas c) { // if values are drawn @@ -206,12 +230,12 @@ public void drawValues(Canvas c) { if (!dataSet.isDrawValuesEnabled()) continue; - + // apply the text-styling defined by the DataSet applyValueTextStyle(dataSet); ValueFormatter formatter = dataSet.getValueFormatter(); - + Transformer trans = mChart.getTransformer(dataSet.getAxisDependency()); ArrayList entries = dataSet.getYVals(); @@ -249,7 +273,7 @@ public void drawValues(Canvas c) { // non-stacked // in between if (vals == null) { - + if (!mViewPortHandler.isInBoundsRight(valuePoints[j])) break; @@ -258,7 +282,8 @@ public void drawValues(Canvas c) { continue; drawValue(c, e.getVal(), valuePoints[j], - valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset), formatter); + valuePoints[j + 1] + (e.getVal() >= 0 ? posOffset : negOffset), + formatter); } else { @@ -276,11 +301,11 @@ public void drawValues(Canvas c) { trans.pointValuesToPixel(transformed); for (int k = 0; k < transformed.length; k += 2) { - + float x = valuePoints[j]; float y = transformed[k + 1] + (vals[k / 2] >= 0 ? posOffset : negOffset); - + if (!mViewPortHandler.isInBoundsRight(x)) break; @@ -348,13 +373,18 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { continue; float groupspace = mChart.getBarData().getGroupSpace(); + boolean isStack = h.getStackIndex() < 0 ? false : true; // calculate the correct x-position float x = index * setCount + dataSetIndex + groupspace / 2f + groupspace * index; - float y = h.getStackIndex() < 0 ? e.getVal() : e.getVals()[h.getStackIndex()] + e.getBelowSum(h.getStackIndex()); + float y = isStack ? e.getVals()[h.getStackIndex()] + + e.getBelowSum(h.getStackIndex()) : e.getVal(); + + // this is where the bar starts + float from = isStack ? e.getBelowSum(h.getStackIndex()) : 0f; - prepareBar(x, y, set.getBarSpace(), trans); + prepareBarHighlight(x, y, set.getBarSpace(), from, trans); c.drawRect(mBarRect, mHighlightPaint); @@ -376,13 +406,14 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } } - - public float[] getTransformedValues(Transformer trans, ArrayList entries, int dataSetIndex) { + + public float[] getTransformedValues(Transformer trans, ArrayList entries, + int dataSetIndex) { return trans.generateTransformedValuesBarChart(entries, dataSetIndex, mChart.getBarData(), mAnimator.getPhaseY()); } - + protected boolean passesCheck() { return mChart.getBarData().getYValCount() < mChart.getMaxVisibleCount() * mViewPortHandler.getScaleX(); diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java index 74be3fa939..7dffac0787 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/HorizontalBarChartRenderer.java @@ -275,6 +275,21 @@ protected void prepareBar(float x, float y, float barspace, Transformer trans) { mBarRect.bottom); } } + + @Override + protected void prepareBarHighlight(float x, float y, float barspace, float from, Transformer trans) { + + float spaceHalf = barspace / 2f; + + float top = x - 0.5f + spaceHalf; + float bottom = x + 0.5f - spaceHalf; + float left = y >= from ? y : from; + float right = y <= from ? y : from; + + mBarRect.set(left, top, right, bottom); + + trans.rectValueToPixel(mBarRect, mAnimator.getPhaseY()); + } @Override public float[] getTransformedValues(Transformer trans, ArrayList entries, From 049d5fc23bd6738df617ebc6d73bff81ff1d3871 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Sat, 28 Feb 2015 16:32:08 +0100 Subject: [PATCH 0160/1390] Update gradle and manifest. --- MPChartExample/AndroidManifest.xml | 4 ++-- MPChartExample/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/MPChartExample/AndroidManifest.xml b/MPChartExample/AndroidManifest.xml index 19ce5c8176..70d72b91d5 100644 --- a/MPChartExample/AndroidManifest.xml +++ b/MPChartExample/AndroidManifest.xml @@ -1,8 +1,8 @@ + android:versionCode="34" + android:versionName="2.0.2" > Date: Sat, 28 Feb 2015 16:37:25 +0100 Subject: [PATCH 0161/1390] Added jar file. --- .../libs/mpandroidchartlibrary-2-0-2.jar | Bin 0 -> 549340 bytes MPChartExample/project.properties | 1 - 2 files changed, 1 deletion(-) create mode 100644 MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar diff --git a/MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar b/MPChartExample/libs/mpandroidchartlibrary-2-0-2.jar new file mode 100644 index 0000000000000000000000000000000000000000..cc8d47f6a770063eb4b83b06caa7f0ccfbe52a4c GIT binary patch literal 549340 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%0D^e}}G45n{WfuMw^t|kMvR`zF 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 z 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 z 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

  • N?k&{V1m6V20jrLYt==Y^WHI(tu=b!N* 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 pk+sy1FzL0WfO*WuEmW2l2n?m~H^3AhM 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 z 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

    eF^VYsJqvonIW61yB8g`nXPMTkr@m8 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/k+oDIK<)eOWrEK!`xvc!2TPn^$& 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%0A5T_+!58yl7DX9LKq`n);v_FlE#72LpYI+^ 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

    eF^VYsJqvonIW61yB8g`nXPMTkr@m8 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/k+oDIK<)eOWrEK!`xvc!2TPn^$& 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%0A5T_+!58yl7DX9LKq`n);v_FlE#72LpYI+^ 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

    eF^VYsJqvonIW61yB8g`nXPMTkr@m8 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�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Μe)!u#rJ!y3 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

    vRFCVQ}~$l2DUK*lWFZ% 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 #bSIPSQ--UY& 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 Date: Thu, 30 Oct 2014 12:49:04 +0100 Subject: [PATCH 0005/1390] Minor fixes. --- .../libs/mpandroidchartlibrary-1-7-3.jar | Bin 1275770 -> 1275754 bytes .../CubicLineChartActivity.java | 2 +- .../mikephil/charting/charts/LineChart.java | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar index e6c40e70e0c4ae351a4c52d41216a430acf10190..a876f607f09e8b3b9ff2bff04be0444532563c00 100644 GIT binary patch delta 126095 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Μ0jj=I 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 N`TCgZOf#AO-9Ejv=y%aRva4V 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 diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 32102fab94..982f360daa 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -240,7 +240,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); + setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress() - 100); // redraw mChart.invalidate(); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index d5b14c2e95..bc51eb3c1a 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -198,7 +198,8 @@ else if (j == points.size() - 1) { // if filled is enabled, close the path if (dataSet.isDrawFilledEnabled()) { - float fillMin = dataSet.getYMin() >= 0 ? mYChartMin : 0; + float fillMin = mFillFormatter + .getFillLinePosition(dataSet, mOriginalData, mYChartMax, mYChartMin); spline.lineTo((entries.size() - 1) * mPhaseX, fillMin); spline.lineTo(0, fillMin); From 22d855cee2d70d7b62f8559c826457b56b177287 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Thu, 30 Oct 2014 12:49:59 +0100 Subject: [PATCH 0006/1390] Minor changes. --- .../xxmassdeveloper/mpchartexample/CubicLineChartActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java index 982f360daa..32102fab94 100644 --- a/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java +++ b/MPChartExample/src/com/xxmassdeveloper/mpchartexample/CubicLineChartActivity.java @@ -240,7 +240,7 @@ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { tvX.setText("" + (mSeekBarX.getProgress() + 1)); tvY.setText("" + (mSeekBarY.getProgress())); - setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress() - 100); + setData(mSeekBarX.getProgress() + 1, mSeekBarY.getProgress()); // redraw mChart.invalidate(); From b4d80e8aa48959289f4d904ed00026e6e4164c71 Mon Sep 17 00:00:00 2001 From: Philipp Jahoda Date: Tue, 18 Nov 2014 15:43:34 +0100 Subject: [PATCH 0007/1390] Major changes to the architecture, introducing Transformer class. --- .../libs/mpandroidchartlibrary-1-7-3.jar | Bin 1275754 -> 0 bytes MPChartExample/project.properties | 1 + .../CubicLineChartActivity.java | 6 +- .../DynamicalAddingActivity.java | 8 +- .../InvertedLineChartActivity.java | 4 +- .../mpchartexample/LineChartActivity.java | 16 +- .../MultiLineChartActivity.java | 4 +- .../mpchartexample/RadarChartActivitry.java | 2 +- .../mikephil/charting/charts/BarChart.java | 88 ++- .../charting/charts/BarLineChartBase.java | 453 ++----------- .../charting/charts/CandleStickChart.java | 14 +- .../mikephil/charting/charts/Chart.java | 312 +++------ .../mikephil/charting/charts/LineChart.java | 40 +- .../mikephil/charting/charts/PieChart.java | 30 +- .../charting/charts/PieRadarChartBase.java | 4 +- .../mikephil/charting/charts/RadarChart.java | 32 +- .../charting/charts/ScatterChart.java | 24 +- .../charting/interfaces/ChartInterface.java | 38 ++ .../listener/BarLineChartTouchListener.java | 4 +- .../charting/renderer/LineRenderer.java | 267 ++++++++ .../charting/renderer/RenderBase.java | 74 +++ .../charting/renderer/Transformer.java | 603 ++++++++++++++++++ 22 files changed, 1259 insertions(+), 765 deletions(-) delete mode 100644 MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar create mode 100644 MPChartLib/src/com/github/mikephil/charting/interfaces/ChartInterface.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/LineRenderer.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/RenderBase.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/Transformer.java diff --git a/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar b/MPChartExample/libs/mpandroidchartlibrary-1-7-3.jar deleted file mode 100644 index a876f607f09e8b3b9ff2bff04be0444532563c00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1275754 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 z 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